AWS Ambassador

5. 환각을 최소화하는 최신 정보 반영 LLM RAG 애플리케이션

Window to the world 2025. 3. 5. 15:15
반응형

 

 

RAG (Retrieval-Augmented Generation) 는 대규모 언어 모델(LLM)과 검색 기술을 결합하여 보다 정확하고 신뢰할 수 있는 응답을 생성하는 방식입니다. 사용자의 쿼리가 입력되면, 관련된 지식을 검색한 후 이를 컨텍스트로 활용하여 LLM이 정보 기반 응답을 생성합니다. 이 방식의 주요 장점으로는 최신 정보에 접근 가능, 환각 현상 감소, 도메인 특화 지식 활용, 그리고 응답의 투명성과 추적 가능성 향상이 있습니다. RAG의 핵심 구성 요소로는 지식 저장소(문서, 데이터베이스, 웹 정보 등), 검색 엔진(벡터 데이터베이스, 의미 기반 검색), 그리고 생성 모델(LLM) 이 포함됩니다. 이를 통해 보다 신뢰할 수 있고 정확한 정보를 제공할 수 있습니다.

 

RAG(Retrieval-Augmented Generation) 과정은 5단계로 구성되는데, 

첫 번째 단계인 인덱싱(Indexing Phase)에서는 내부 문서, 웹페이지, 데이터베이스, API 등에서 정보를 수집한 후, 이를 의미 있는 단위(청크)로 분할합니다. 그런 다음, 각 청크를 임베딩 모델을 활용하여 벡터로 변환하고, 생성된 벡터와 원본 텍스트를 벡터 데이터베이스에 저장합니다.

두 번째 단계인 검색(Retrieval Phase)에서는 사용자의 질의를 임베딩 모델을 이용해 벡터로 변환한 후, 벡터 유사도를 계산하여 관련성이 높은 문서 청크를 검색합니다. 검색된 문서들은 적절한 기준에 따라 랭킹이 매겨지고, 필터링을 거쳐 최적의 결과가 선택됩니다.

세 번째 단계인 프롬프트 구성(Prompt Construction)에서는 검색된 문서들을 LLM(대규모 언어 모델)의 입력 형식에 맞게 가공합니다. 이를 위해 사전 정의된 프롬프트 템플릿을 활용하여 사용자 질의와 검색된 정보를 통합하고, 토큰 제한을 고려하여 최적의 컨텍스트 창을 구성합니다.

네 번째 단계인 생성(Generation Phase)에서는 구성된 프롬프트가 LLM에 입력되어 최종 응답이 생성됩니다. 이 과정에서 Temperature, Top-P 등의 매개변수를 조정하여 모델의 응답을 최적화하고, 필요에 따라 생성된 텍스트를 추가적으로 가공합니다.

마지막 단계인 후처리(Post-processing)에서는 생성된 응답의 정확성을 검증하고, 사용된 정보의 출처를 명시합니다. 또한, 사용자 피드백을 수집하여 시스템 개선에 반영하며, 전체 프로세스의 성능을 지속적으로 모니터링하고 평가합니다.

이러한 5단계의 순차적 과정을 통해 RAG 시스템은 정확하고 신뢰할 수 있는 응답을 생성할 수 있으며, 최신 정보에 접근하고 환각 현상을 줄이는 등 다양한 이점을 제공합니다.

 

 

Bedrock과 SageMaker JumpStart에서 제공하는 LLM (Large Language Model) Model을 활용해 학습 되지 않은 조직의 내/외부 데이터를 불러와 응답을 생성하는 RAG (Retrieval Augmented Generation)를 구현하여 특정 분야의 질의에 대한 응답을 생성할 수 있습니다. 

 

LLM Model은 대량의 비구조화 데이터에 대해 훈련되며 일반 텍스트 생성에 뛰어납니다. 그러나 사전 훈련된 LLM을 사용하는 데는 몇 가지 제한 사항이 있습니다. 예를 들어, LLM은 일반적으로 언어에 대한 이해와 일부 상식에 해당되는 분야의 말뭉치에 대해 훈련되므로 전문 도메인의 특정 작업에는 덜 효과적입니다. 이러한 문제를 해결하기 위해 RAG를 사용하면 LLM 외부에서 데이터를 검색하고 검색된 관련 데이터를 문맥에 추가하여 프롬프트를 증가시킵니다. RAG는 조직의 내/외부 문서 저장소, 데이터베이스, API 등 다양한 데이터 소스에서 올 수 있습니다.

 

RAG는 특히 질문 응답, 대화 생성 등의 작업에서 유용하게 사용됩니다. RAG는 기본적으로 두 가지 주요 컴포넌트로 구성되어 있습니다.
1) 정보 검색 컴포넌트: 이 컴포넌트는 사용자의 질문이나 프롬프트에 대한 관련 정보를 찾는 역할을 합니다. 이 정보는 문서 저장소, 데이터베이스, API 등 다양한 데이터 소스에서 가져올 수 있습니다.
2) 텍스트 생성 컴포넌트: 이 컴포넌트는 검색된 정보를 기반으로 응답을 생성하는 역할을 합니다. 이 컴포넌트는 대부분 LLM을 사용하여 텍스트를 생성합니다.

RAG의 주요 장점은 외부 데이터를 참조하여 도메인 특정 텍스트 출력을 생성할 수 있다는 것입니다. 이는 일반적인 LLM이 주로 일반 도메인 말뭉치에 대해 훈련되므로 도메인 특정 작업에는 덜 효과적이라는 제한 사항을 극복하는 데 도움이 됩니다. RAG는 사용자의 질문에 대한 정확하고 관련성 있는 응답을 생성하는 데 도움이 될 수 있습니다. 이는 RAG가 검색된 정보를 문맥에 추가하여 프롬프트를 증가시키기 때문에 가능합니다. 이렇게 하면 모델은 특정 데이터를 참조하여 더 정확하고 관련성 있는 응답을 생성할 수 있습니다.

 

아래는 Bedrock에서 제공하는 Titan Embedding Model과 Cluade v2 LLM 모델을 사용해 RAG용 Chat Application을 구현한 과정입니다.

 

1. 라이브러리 임포트
 

 import boto3
 import botocore
   ...
 from langchain.vectorstores import FAISS
 from langchain.indexes import VectorstoreIndexCreator
 from langchain.indexes.vectorstore import VectorStoreIndexWrapper

필요한 라이브러리와 모듈을 임포트합니다. `boto3`는 AWS 서비스를 위해,  `langchain` 관련 모듈들은 언어 처리와 벡터 저장소를 위해 사용됩니다.

2. 환경 변수 설정 

os.environ["AWS_DEFAULT_REGION"] = " AWS_DEFAULT_REGION "
os.environ["BEDROCK_ENDPOINT_URL"] = " BEDROCK_ENDPOINT_URL "


AWS 리전과 Bedrock 엔드포인트 URL에 대한 환경 변수를 설정합니다.

3. Bedrock 클라이언트 함수 

def get_bedrock_client():
  return boto3.client(...)


`boto3`를 사용하여 지정된 자격 증명과 엔드포인트를 가진 Bedrock 클라이언트를 초기화하고 반환합니다.

4.  임베딩 대상 문서 텍스트 파일 읽기

with open(file_name, 'r') as file:
  text_data = file.read()

파일의 내용을 `text_data`로 읽어들입니다.

5. 문서 객체 생성

documents = [Document(sentence) for sentence in sentences if sentence.strip()]

  

 `text_data`의 문장들로부터 `Document` 객체 리스트를 생성합니다.

6. 문서 임베딩

all_embeddings = [np.array(bedrock_embeddings.embed_query(doc.page_content)) for doc in documents]

 

Bedrock 임베딩 모델을 사용하여 각 문서에 대한 임베딩을 통해 벡터값을 생성합니다.

7. FAISS 벡터 스토어 생성

vectorstore_faiss = FAISS.from_documents(documents, bedrock_embeddings)

 

문서 임베딩 값으로 FAISS 벡터 스토어를 생성합니다.


8. 벡터 스토어 저장 및 로드

 vectorstore_faiss.save_local("Unified_Faiss")
 vectordb = FAISS.load_local("Unified_Faiss", bedrock_embeddings)

   

FAISS 벡터 스토어를 로컬 파일에 저장한 다음 다시 로드합니다.

9. 쿼리 임베딩 및 문서 검색

query_embedding = vectorstore_faiss.embedding_function.embed_query(query)
relevant_documents = vectorstore_faiss.similarity_search_by_vector(query_embedding)
query = """Valid-Ticket을 구매할 수 있는 기간은?"""
docs = vectordb.similarity_search(query)
print(docs[0].page_content)

  

문서 내용에 대한 질문 쿼리를 임베딩하고, FAISS 벡터 스토어에서 유사한 문서를 찾기 위해 유사성 검색을 수행합니다

주어진 쿼리에 대해 `vectordb`를 사용하여 유사성 검색을 수행하고 가장 관련성 높은 문서의 내용을 출력합니다.

아래는 VectorDB와 연계해 관련 문서를 검색하는 데모 애플리케이션을 구축하는 과정을 보여줍니다. 

1. 라이브러리 임포트

import gradio as gr

 
`gradio`는 웹 기반 인터페이스를 만들기 위해 사용됩니다.

2. Bedrock 클라이언트 설정: 

def get_bedrock_client():
  return boto3.client(...)


AWS의 Bedrock 서비스를 사용하기 위한 클라이언트를 설정합니다. 여기서는 AWS 액세스 키와 비밀 키를 사용하여 인증합니다.

3. Bedrock 모델 설정 

def get_bedrock_model(model_id, model_params=None):
  bedrock_client = get_bedrock_client()
  return BedrockChat(model_id=model_id, client=bedrock_client, model_kwargs=model_params)

 

특정 Bedrock 모델을 초기화하고 반환하는 함수입니다. 이 모델은 나중에 텍스트 데이터의 임베딩을 생성하는 데 사용됩니다.

4. FAISS 벡터 데이터베이스 로드 

vectordb = FAISS.load_local("/home/ec2-user/...", bedrock_embeddings, allow_dangerous_deserialization=True)


로컬에서 저장된 FAISS 벡터 데이터베이스를 로드합니다. `allow_dangerous_deserialization=True`는 직렬화된 데이터를 안전하게 로드할 수 있도록 합니다.

5.Predict 함수 정의

def predict(message, prompt):
  docs = vectordb.similarity_search(message, top_k=4)
  doc_contents = "\n".join([doc.page_content for doc in docs])


사용자의 메시지를 받아 가장 관련성 높은 문서를 찾고, 이를 바탕으로 프롬프트를 생성하는 함수입니다. `vectordb.similarity_search`를 사용하여 입력된 메시지와 관련된 상위 4개 문서를 검색합니다.

6. Gradio 데모 인터페이스

demo = gr.ChatInterface(fn=predict)

 

Gradio를 사용하여 웹 기반의 챗봇 인터페이스를 생성합니다. 이 인터페이스는 `predict` 함수를 사용하여 사용자의 질문에 대한 답변을 생성합니다.

 

 

 

 

반응형