AWS 기술 블로그

Amazon SageMaker JumpStart와 Vector Store를 이용하여 Llama 2로 Chatbot 만들기

Llama 2의 대규모 언어 모델(Large Language Models)을 이용하여 질문/답변(Question/Answering)을 수행하는 chatbot을 vector store를 이용하여 구현합니다. 대량의 데이터로 사전학습(pretrained)한 대규모 언어 모델(LLM)은 학습되지 않은 질문에 대해서도 가장 가까운 답변을 맥락(context)에 맞게 찾아 답변할 수 있습니다. 이는 기존의 Rule 방식보다 훨씬 정답에 가까운 답변을 제공하지만, 때로는 매우 그럴듯한 잘못된 답변(hallucination)을 할 수 있습니다. 이런 경우에 파인 튜닝(fine tuning)을 통해 정확도를 높일 수 있으나, 계속적으로 추가되는 데이터를 매번 파인 튜닝으로 처리할 수 없습니다. 따라서, RAG(Retrieval-Augmented Generation)와 같이 기본 모델의 파라미터(weight)을 바꾸지 않고, 지식 데이터베이스(knowledge Database)에서 얻어진 외부 지식을 이용하여 정확도를 개선하는 방법을 활용할 수 있습니다. RAG는 prompt engineering 기술 중의 하나로서 vector store를 지식 데이터베이스로 이용하고 있습니다.

Vector store는 이미지, 문서(text document), 오디오와 같은 구조화 되지 않은 컨텐츠(unstructured content)를 저장하고 검색할 수 있습니다. 특히 대규모 언어 모델(LLM)의 경우에 embedding을 이용하여 텍스트들의 연관성(sementic meaning)을 벡터(vector)로 표현할 수 있으므로, 연관성 검색(sementic search)을 통해 질문에 가장 가까운 답변을 찾을 수 있습니다. 여기서는 대표적인 In-memory vector store인 Faiss와 persistent store이면서 대용량 병렬처리가 가능한 Amazon OpenSearch를 이용하여 문서의 내용을 분석하고 연관성 검색(sementic search) 기능을 활용합니다. 이를 통해, 파인 튜닝없이 대규모 언어 모델(LLM)의 질문/답변(Question/Answering) 기능(Task)을 향상 시킬 수 있습니다.

아키텍처 개요

전체적인 아키텍처는 아래와 같습니다. 사용자가 Amazon S3에 업로드한 문서는 embedding을 통해 vector store에 저장됩니다. 이후 사용자가 질문을 하면 vector store를 통해 질문에 가장 가까운 문장들을 받아오고 이를 기반으로 prompt를 생성하여 대규모 언어 모델(LLM)에 질문을 요청하게 됩니다. 만약 vector store에서 질문에 가까운 문장이 없다면 대규모 언어 모델(LLM)의 Endpoint로 질문을 전달합니다. 대용량 파일을 S3에 업로드 할 수 있도록 presigned url을 이용하였고, 질문과 답변을 수행한 call log는 Amazon DynamoDB에 저장되어 이후 데이터 수집 및 분석에 사용됩니다. 여기서 대용량 언어 모델로 Llama 2를 이용합니다. Llama2는 Open LLM Leaerboard에서 2023년 8월 현재 상위권에 있을만큼 강력하며, 범용적인 목적을 위해 사용될 수 있습니다. 또한 LangChain을 활용하여 Application을 개발하였고, chatbot을 제공하는 인프라는 AWS CDK를 통해 배포합니다.

문서파일을 업로드하여 vector store에 저장하는 과정은 아래와 같습니다.

  1. 사용자가 파일 업로드를 요청합니다. 이때 사용하는 Upload API는 lambda (upload)에 전달되어 S3 presigned url을 생성하게 됩니다.
  2. 사용자가 presigned url로 문서를 업로드하면 S3에 object로 저장됩니다.
  3. Chat API에서 request type을 “document”로 지정하면 lambda (chat)는 S3에서 object를 로드하여 텍스트를 추출합니다.
  4. Embeding을 통해 단어들을 vector화 합니다.
  5. Vector store에 문서를 저장합니다. 이때 RAG의 type이 “faiss”이면 in-memory store인 Faiss로 저장하고, “opensearch”이면 Amazon OpenSearch로 저장합니다.
  6. 채팅창에 업로드한 문서의 요약(Summerization)을 보여주기 위해 summerization을 수행하고 그 결과를 사용자에게 전달합니다.

아래는 문서 업로드시의 sequence diagram입니다.

채팅 창에서 텍스트 입력(Prompt)를 통해 RAG를 활용하는 과정은 아래와 같습니다.

  1. 사용자가 채팅창에서 질문(Question)을 입력합니다.
  2. 이것은 Chat API를 이용하여 lambda (chat)에 전달됩니다.
  3. lambda(chat)은 질문을 Embedding합니다.
  4. vector store에 관련된 문장이 있는지 확인합니다.
  5. Vector store가 관련된 문장을 전달하면 prompt template를 이용하여 LLM에 질문을 전달합니다. 이후 답변을 받으면 사용자에게 결과를 전달합니다.

아래는 vectore store를 이용한 메시지 동작을 설명하는 sequence diagram입니다.

주요 구성

LangChain이용하기

LangChain은 LLM을 편리하게 사용할 수 있도록 도와주는 Framework입니다. lambda (chat)와 같이 LangChain을 이용해서 Llama 2를 편리하게 이용할 있습니다. Llama 2는 SageMaker Endpoint를 이용하므로 LangChain 연결시에 ContentHandler에서 input/output에 대한 transform을 아래와 같이 정의합니다.

endpoint_name = os.environ.get('endpoint')

class ContentHandler(LLMContentHandler):
    content_type = "application/json"
    accepts = "application/json"

    def transform_input(self, prompt: str, model_kwargs: dict) -> bytes:
        input_str = json.dumps({
            "inputs" : 
            [
                [
                    {
                        "role" : "system",
                        "content" : "You are a kind robot."
                    },
                    {
                        "role" : "user", 
                        "content" : prompt
                    }
                ]
            ],
            "parameters" : {**model_kwargs}})
        return input_str.encode('utf-8')
      
    def transform_output(self, output: bytes) -> str:
        response_json = json.loads(output.read().decode("utf-8"))
        return response_json[0]["generation"]["content"]

content_handler = ContentHandler()
aws_region = boto3.Session().region_name
client = boto3.client("sagemaker-runtime")
parameters = {
    "max_new_tokens": 1024, 
    "top_p": 0.9, 
    "temperature": 0.1
} 

llm = SagemakerEndpoint(
    endpoint_name = endpoint_name, 
    region_name = aws_region, 
    model_kwargs = parameters,
    endpoint_kwargs={"CustomAttributes": "accept_eula=true"},
    content_handler = content_handler
)

Embedding

RAG 동작에 필요한 embedding을 위하여, “GPT-J 6B Embedding FP16”을 사용합니다. GPT-J embedding은 semantic search와 question and answering 같은 text generation에 유용하게 이용할 수 있습니다.

Llama 2와 마찬가지로 embedding은 SageMaker Endpoint를 이용해 구현합니다. 따라서, SageMaker Endpoint Embeddings을 참조하여 아래와 같이 ContentHandler2를 정의하여 LangChain과 연결합니다. 여기서 embedding용 SageMaker Endpoint인 endpoint_embedding는 SageMaker JumpStart로 “GPT-J 6B Embedding FP16″를 설치할 때에 생성된 SageMaker Endpoint입니다.

from langchain.embeddings.sagemaker_endpoint import EmbeddingsContentHandler
from typing import Dict, List
class ContentHandler2(EmbeddingsContentHandler):
    content_type = "application/json"
    accepts = "application/json"

    def transform_input(self, inputs: List[str], model_kwargs: Dict) -> bytes:
        input_str = json.dumps({ "text_inputs": inputs, ** model_kwargs})
        return input_str.encode("utf-8")

    def transform_output(self, output: bytes) -> List[List[float]]:
        response_json = json.loads(output.read().decode("utf-8"))
        return response_json["embedding"]

content_handler2 = ContentHandler2()
embeddings = SagemakerEndpointEmbeddings(
    endpoint_name = endpoint_embedding,
    region_name = aws_region,
    content_handler = content_handler2,
)

문서 읽어오기

Client에서는 Upload API를 이용하여 업로드할 파일명과 Content-Type을 서버로 전달합니다.

{
    "filename":"gen-ai-wiki.pdf",
    "contentType":"application/pdf"
}

Lambda-upload에서는 용량이 큰 문서 파일도 S3에 업로드할 수 있도록 presigned url을 생성합니다. 아래와 같이 s3Params를 지정하고 getSignedUrlPromise을 이용하여 url 정보를 Client로 전달합니다.

const URL_EXPIRATION_SECONDS = 300;
const s3Params = {
    Bucket: bucketName,
    Key: s3_prefix+'/'+filename,
    Expires: URL_EXPIRATION_SECONDS,
    ContentType: contentType,
};

const uploadURL = await s3.getSignedUrlPromise('putObject', s3Params);

Client에서 아래와 같은 응답을 얻으면 “UploadURL”을 추출하여 문서 파일을 업로드합니다.

{
   "statusCode":200,
   "body":"{\"Bucket\":\"storage-for-qa-chatbot-with-rag\",\"Key\":\"docs/gen-ai-wiki.pdf\",\"Expires\":300,\"ContentType\":\"application/pdf\",\"UploadURL\":\"https://storage-for-qa-chatbot-with-rag.s3.ap-northeast-2.amazonaws.com/docs/gen-ai-wiki.pdf?Content-Type=application%2Fpdf&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIAZ3KIXN5TBIBMQXTK%2F20230730%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20230730T055129Z&X-Amz-Expires=300&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEAYaDmFwLW5vcnRoZWFzdC0yIkcwRQIhAP8or6Pr1lDHQpTIO7cTWPsB7kpkdkOdsrd2NbllPpsuAiBlV...(중략)..78d1b62f1285e8def&X-Amz-SignedHeaders=host\"}"
}

파일 업로드가 끝나면, Client는 Chat API로 문서를 vector store에 등록하도록 아래와 같이 요청합니다.

{
   "user-id":"f642fd39-8ef7-4a77-9911-1c50608c2831",
   "request-id":"d9ab57ad-6950-412e-a492-1381eb1f2642",
   "type":"document",
   "body":"gen-ai-wiki.pdf"
}

Lambda-chat에서는 type이 “document” 이라면, S3에서 아래와 같이 파일을 로드하여 text를 분리합니다.

s3r = boto3.resource("s3")
doc = s3r.Object(s3_bucket, s3_prefix + '/' + s3_file_name)

if file_type == 'pdf':
    contents = doc.get()['Body'].read()
    reader = PyPDF2.PdfReader(BytesIO(contents))

    raw_text = []
    for page in reader.pages:
        raw_text.append(page.extract_text())
    contents = '\n'.join(raw_text)    
        
elif file_type == 'txt':
    contents = doc.get()['Body'].read()
elif file_type == 'csv':
    body = doc.get()['Body'].read()
    reader = csv.reader(body)
    contents = CSVLoader(reader)

이후 chunk size로 분리한 후에 Document를 이용하여 문서로 만듭니다.

from langchain.docstore.document import Document

text_splitter = RecursiveCharacterTextSplitter(chunk_size = 1000, chunk_overlap = 100)
texts = text_splitter.split_text(new_contents)
print('texts[0]: ', texts[0])

docs = [
    Document(
        page_content = t
    ) for t in texts[: 3]
]
return docs

Vector Store

Faiss와 OpenSearch 방식의 선택은 cdk-chatbot-llama2-stack.ts에서 rag_type을 “faiss” 또는 “opensearch”로 변경할 수 있습니다. 기본값은 “opensearch”입니다.

Faiss는 Facebook에서 오픈소스로 제공하는 In-memory vector store로서 embedding과 document들을 저장할 수 있으며, LangChain을 지원합니다. Faiss에서는 FAISS()를 이용하여 아래와 같이 vector store를 정의합니다.

from langchain.vectorstores import FAISS

vectorstore = FAISS.from_documents( # create vectorstore from a document
    docs, 
    bedrock_embeddings  
)

이후, vectorstore를 이용하여 관계된 문서를 조회합니다. 이때 Faiss는 embedding된 query를 이용하여 similarity_search_by_vector()로 조회합니다.

relevant_documents = vectorstore.similarity_search_by_vector(query_embedding)

Amazon OpenSearch persistent store로는 vector store를 구성할 수 있습니다. 비슷한 역할을 하는 persistent store로는 Amazon RDS Postgres with pgVector, ChromaDB, Pinecone과 Weaviate가 있습니다.

Lambda-chat에서 OpenSearch를 사용을 위해서는 Lambda의 Role에 아래의 퍼미션을 추가합니다.

{	
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "es:*",
            "Resource": "arn:aws:es:[region]:[account-id]:domain/[domain-name]/*"
        }
    ]
}

이것은 cdk-chatbot-llama2-stack.ts에서 아래와 같이 구현할 수 있습니다.

const resourceArn = `arn:aws:es:${region}:${accountId}:domain/${domainName}/*`
const OpenSearchPolicy = new iam.PolicyStatement({
    resources: [resourceArn],
    actions: ['es:*'],
});

roleLambda.attachInlinePolicy( 
    new iam.Policy(this, `opensearch-policy-for-${projectName}`, {
        statements: [OpenSearchPolicy],
    }),
); 

OpenSearch에 대한 access policy는 아래와 같습니다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:[region]:[account-id]:domain/[domain-name]/*"
    }
  ]
}

cdk-chatbot-llama2-stack.ts에서 아래와 같이 정의하여 OpenSearch 생성시 활용합니다.

const resourceArn = `arn:aws:es:${region}:${accountId}:domain/${domainName}/*`
const OpenSearchAccessPolicy = new iam.PolicyStatement({
    resources: [resourceArn],
    actions: ['es:*'],
    effect: iam.Effect.ALLOW,
    principals: [new iam.AnyPrincipal()],
});

OpenSearchVectorSearch()로 아래와 같이 vector store를 정의합니다.

from langchain.vectorstores import OpenSearchVectorSearch

vectorstore = OpenSearchVectorSearch.from_documents(
    docs,
    bedrock_embeddings,
    opensearch_url = endpoint_url,
    http_auth = ("admin", "password"),
)

아래와 같이 OpenSearch는 vector store로 부터 similarity_search()를 이용하여 관련된 문서를 조회할 수 있습니다. OpenSearch는 vector store를 정의할 때 embedding 방식을 bedrock_embeddings로 지정하였으므로 similarity_search()호출할 때에 query를 embeding하지 않습니다.

relevant_documents = vectorstore.similarity_search(query)

Question/Answering

아래와 같이 vector store에 직접 Query 하는 방식과, Template를 이용하는 2가지 방법으로 Question/Answering 구현하는 것을 설명합니다. Vector Store에서 query를 이용하는 방법은 embedding한 query를 가지고 vectorstore에서 검색한 후에 vectorstore의 query()를 이용하여 답변을 얻습니다.

wrapper_store = VectorStoreIndexWrapper(vectorstore = vectorstore)
query_embedding = vectorstore.embedding_function(query)

relevant_documents = vectorstore.similarity_search_by_vector(query_embedding)
answer = wrapper_store.query(question = query, llm = llm)

Template를 이용하는 방법은 RetrievalQA을 이용하며 일반적으로 vectorstore에서 query를 이용하는 방법보다 나은 결과를 얻습니다.

from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate

prompt_template = """Human: Use the following pieces of context to provide a concise answer to the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.

{ context }

Question: { question }
Assistant: """
PROMPT = PromptTemplate(
    template = prompt_template, input_variables = ["context", "question"]
)

qa = RetrievalQA.from_chain_type(
    llm = llm,
    chain_type = "stuff",
    retriever = vectorstore.as_retriever(
        search_type = "similarity", search_kwargs = { "k": 3 }
    ),
    return_source_documents = True,
    chain_type_kwargs = { "prompt": PROMPT }
)
result = qa({ "query": query })

return result['result']

AWS CDK로 인프라 구현하기

cdk-chatbot-llama2-stack.ts에서는 OpenSearch에 대해 아래와 같이 정의합니다.

const domain = new opensearch.Domain(this, 'Domain', {
    version: opensearch.EngineVersion.OPENSEARCH_2_3,

    domainName: domainName,
    removalPolicy: cdk.RemovalPolicy.DESTROY,
    enforceHttps: true,
    fineGrainedAccessControl: {
        masterUserName: opensearch_account,
        masterUserPassword: cdk.SecretValue.unsafePlainText(opensearch_passwd)
    },
    capacity: {
        masterNodes: 3,
        masterNodeInstanceType: 'm6g.large.search',
        dataNodes: 3,
        dataNodeInstanceType: 'r6g.large.search',
    },
    accessPolicies: [OpenSearchAccessPolicy],
    ebs: {
        volumeSize: 100,
        olumeType: ec2.EbsDeviceVolumeType.GP3,
    },
    nodeToNodeEncryption: true,
    encryptionAtRest: {
        enabled: true,
    },
    zoneAwareness: {
        enabled: true,
        availabilityZoneCount: 3,
    }
});

Chat을 위한 Lambda를 컨테이너 방식으로 생성합니다. Bedrock의 region name, endpoint url, model Id등을 파라미터로 제공합니다.

// Lambda for chat using langchain (container)
const lambdaChatApi = new lambda.DockerImageFunction(this, `lambda-chat-for-${projectName}`, {
    description: 'lambda for chat api',
    functionName: `lambda-chat-api-for-${projectName}`,
    code: lambda.DockerImageCode.fromImageAsset(path.join(__dirname, '../../lambda-chat')),
    timeout: cdk.Duration.seconds(60),
    role: roleLambda,
    environment: {
        bedrock_region: bedrock_region,
        endpoint_url: endpoint_url,
        model_id: model_id,
        s3_bucket: s3Bucket.bucketName,
        s3_prefix: s3_prefix,
        callLogTableName: callLogTableName,
        configTableName: configTableName
    }
});
lambdaChatApi.grantInvoke(new iam.ServicePrincipal('apigateway.amazonaws.com'));
s3Bucket.grantRead(lambdaChatApi); // permission for s3
callLogDataTable.grantReadWriteData(lambdaChatApi); // permission for dynamo
configDataTable.grantReadWriteData(lambdaChatApi); // permission for dynamo

SageMaker 사용에 필요한 권한을 추가합니다.

const SageMakerPolicy = new iam.PolicyStatement({  // policy statement for sagemaker
    actions: ['sagemaker:*'],
    resources: ['*'],
});
lambdaChatApi.role?.attachInlinePolicy( // add sagemaker policy
    new iam.Policy(this, `sagemaker-policy-for-${projectName}`, {
        statements: [SageMakerPolicy],
    }),
);

직접 실습 해보기

사전 준비 사항

이 솔루션을 사용하기 위해서는 사전에 아래와 같은 준비가 되어야 합니다.

SageMaker Endpoint 설치

여기서는 Llama 2를 설치하기 위하여 SageMaker JumbStart에서 N. Virginia(us-east-1) 리전을 이용합니다. SageMaker Console에서 SageMaker Studio를 실행한 후에, SageMaker JumpStart에서 “Llama-2-7b-chat”를 고른 후에 Deploy를 선택합니다. 설치가 되면 “jumpstart-dft-meta-textgeneration-llama-2-7b-f”와 같은 Endpoint가 생성됩니다.

SageMaker Console에서 SageMaker Studio를 실행한 후에, SageMaker JumpStart에서 “GPT-J 6B Embedding FP16″를 고른 후에 Deploy를 선택합니다. 설치가 되면 “jumpstart-dft-hf-textembedding-gpt-j-6b-fp16″와 같은 Endpoint가 생성됩니다.

CDK를 이용한 인프라 설치

여기서는 Cloud9에서 AWS CDK를 이용하여 인프라를 설치하고 편의상 Seoul Region을 사용합니다.

1.Cloud9 Console에 접속하여 [Create environment]-[Name]에서 “chatbot”로 이름을 입력하고, EC2 instance는 “m5.large”를 선택합니다. 나머지는 기본값을 유지하고, 하단으로 스크롤하여 [Create]를 선택합니다.

2.Environment에서 “chatbot”를 [Open]한 후에 아래와 같이 터미널을 실행합니다.

3.EBS 크기 변경

아래와 같이 스크립트를 다운로드 합니다.

curl https://raw.githubusercontent.com/aws-samples/generative-ai-demo-using-amazon-sagemaker-jumpstart-kr/main/blogs/Llama2-chatbot-with-vector-store/resize.sh -o resize.sh

이후 아래 명령어로 용량을 80G로 변경합니다.

chmod a+rx resize.sh && ./resize.sh 80

4.소스를 다운로드하여 압축을 풉니다.

curl https://raw.githubusercontent.com/aws-samples/generative-ai-demo-using-amazon-sagemaker-jumpstart-kr/main/blogs/Llama2-chatbot-with-vector-store/Llama2-chatbot-with-vector-store.zip -o Llama2-chatbot-with-vector-store.zip && unzip Llama2-chatbot-with-vector-store.zip

5.cdk 폴더로 이동하여 필요한 라이브러리를 설치합니다.

cd Llama2-chatbot-with-vector-store/cdk-chatbot-llama2/ && npm install

6.Enpoint들의 주소를 수정합니다.

LLM과 Embedding에 대한 Endpoint 생성시 얻은 주소로 endpoint_llm과 endpoint_embedding을 “cdk-chatbot-llama2/lib/cdk-chatbot-llama2-stack.ts”에 업데이트 합니다. 만약, 기본값을 그대로 사용하였다면 수정없이 다음 단계로 진행합니다.

7.CDK 사용을 위해 Bootstraping을 수행합니다.

아래 명령어로 Account ID를 확인합니다.

aws sts get-caller-identity --query Account --output text

아래와 같이 bootstrap을 수행합니다. 여기서 “account-id”는 상기 명령어로 확인한 12자리의 Account ID입니다. Bootstrapping은 1회만 수행하면 되므로, 기존에 cdk를 사용하고 있었다면 bootstrap은 건너뛰어도 됩니다.

cdk bootstrap aws://[account-id]/us-east-1

8.인프라를 설치합니다.

아래 명령어로 인프라 설치를 시작합니다. 전체 설치에 약 25분정도 시간이 소요됩니다.

cdk deploy

9.설치가 완료되면 브라우저에서 아래와 같이 WebUrl를 확인하여, 브라우저로 접속합니다.

실행결과

채팅창에 “How many customers using ML on AWS?”라는 질문을 입력합니다. Llama 2모델이 학습할 때에 이러한 정보를 가지고 있지 않으므로 아래와 같이 답변을 줄 수 없습니다.

gen-ai-aws.pdf을 다운로드 한 후에 채팅창 아래의 파일 아이콘을 선택하여 업로드합니다. 업로드가 끝나면 아래와 같이 “gen-ai-aws.pdf”을 요약하여 보여줍니다.

“gen-ai-aws.pdf”는 AWS의 ML을 사용하는 고객숫자에 대해 아래와 같은 데이터를 가지고 있습니다.

At AWS, we have played a key role in democratizing ML and making it accessible to anyone who wants to use it, including more than 100,000 customers of all sizes and industries. AWS has the broadest and deepest portfolio of AI and ML services at all three layers of the stack.

이제 동일한 질문을 하면, 아래와 같이 정확한 답변을 얻을 수 있습니다.

대용량 언어 모델(LLM)의 특성상 실습의  답변은 블로그의 화면과 조금 다를 수 있습니다.

리소스 정리하기

더이상 인프라를 사용하지 않는 경우에 아래처럼 모든 리소스를 삭제할 수 있습니다. Cloud9 console에 접속하여 아래와 같이 삭제를 합니다.

cdk destroy

본 실습에서는 Llama 2와 GPT-J Embedding을 위해 “ml.g5.2xlarge”를 사용하고 있으므로, 더이상 사용하지 않을 경우에 반드시 삭제하여야 합니다. 특히 cdk destroy 명령어로 Chatbot만 삭제할 경우에 SageMaker Endpoint가 유지되어 지속적으로 비용이 발생될 수 있습니다. 이를 위해 Endpoint Console에 접속해서 Endpoint를 삭제합니다. 마찬가지로 Models과 Endpoint configuration에서 설치한 Llama 2와 GPT-J Embedding의 Model과 Configuration을 삭제합니다.

결론

SageMaker JumpStart를 이용하여 대규모 언어 모델(LLM)인 LLama 2를 쉽게 배포하였고, vector store를 이용하여 질문과 답변(Question/Answering)을 수행하는 chatbot의 기능을 향상시켰습니다. Amazon SageMaker JumpStart는 다양한 종류의 언어 모델을 가지고 있으므로 목적에 맞게 선택하여 사용할 수 있습니다. 여기서는 Llama 2을 이용하여 RAG 동작을 구현하였고, 대용량 언어 모델의 환각(hallucination) 문제를 해결할 수 있었습니다. 또한 Chatbot 어플리케이션 개발을 위해 LangChain을 활용하였고, IaC(Infrastructure as Code)로 AWS CDK를 이용하였습니다. 대용량 언어 모델은 향후 다양한 어플리케이션에서 효과적으로 활용될 것으로 기대됩니다. SageMaker JumpStart을 이용하여 대용량 언어 모델을 개발하면 기존 AWS 인프라와 손쉽게 연동하고 다양한 어플리케이션을 효과적으로 개발할 수 있습니다.

실습 코드 및 도움이 되는 참조 블로그

아래의 링크에서 실습 소스 파일 및 기계 학습(ML)과 관련된 자료를 확인하실 수 있습니다.

Suggested tags:  [Amazon Bedrock, Generative AI, Chatbot]

Kyoung-Su Park

Kyoung-Su Park

박경수 솔루션즈 아키텍트는 다양한 워크로드에 대한 개발 경험을 바탕으로 고객이 최적의 솔루션을 선택하여 비즈니스 성과를 달성할 수 있도록 고객과 함께 효율적인 아키텍처를 구성하는 역할을 수행하고 있습니다. 현재 AWS의 Machine Learning, IoT, Analytics TFC에서 활동하고 있습니다.

Kim Jongseon

Kim Jongseon

김종선 시니어 솔루션즈 아키텍트 매니저는 소프트웨어 개발자, DevOps 엔지니어 및 인프라 아키텍트의 경험을 통해 글로벌스케일의 전자 및 하이테크 기업의 클라우드 기반Digital Trasformation을 완성할 수 있도록 기술적인 도움을 드리고 있습니다.