[8기 랭체인] RAG 파이프라인 구축 해보기

이번 포스팅에선 LangChain을 활용해 RAG 시스템을 구현해 보겠습니다.

이번주 월요일(12/4) NVIDIA에서 주최한 Korea LLM Developer Day에서 RAG에 대한 소개를 듣고 LangChain을 이용해 RAG 구조를 구축하고 싶다라는 생각을 했고, 이에 대한 설명과 적절한 예시를 소개하는 유튜브 영상을 발견해서 학습하고 발전시켜 보았습니다.

📽️ Chatbots with RAG: LangChain Full Walkthrough

Retrieval Augmented Generation(RAG) 이란?

LLM의 기능을 확장하여 외부 정보로부터 데이터를 검색(retrieval)하고 이를 통해 텍스트를 생성(generation)하는 방식. 즉, 자연어처리 영역에서는 데이터를 Vector 형식으로 저장해 VectorDB에 올리고 이를 이용하는 과정을 RAG이라 할 수 있겠죠.

RAG의 장점

  • 최신 정보 혹은 나만이 가지고 있는 자료에 대한 검색을 가능하게 함.

  • 없는 정보를 만드는 할루시네이션을 줄일 수 있음.

  • Bing에서 검색을 하고 추론을 하는 현재의 ChatGPT 방식 보다, 특정한 영역에 대해 뛰어나고 빠른 결과물을 생성 할 수 있음.

  • Prompt에 모든 정보를 넣기보단 질문과 관련된 정보를 DB에서 찾아서 넣음으로써 토큰 수를 절약 할 수 있음.

그림 처럼 새로운 뇌의 영역을 만드는 작업이라고 생각하면 좋을 듯하네요.

Give it a try!

without RAG

먼저 gpt 3-5-turbo를 이용해서 llama2와 langchain에 관한 질문을 했습니다.

예상대로 두가지 모두 잘 모른다는 답변을 받았습니다.

그럼 한번 짧은 설명은 context로 추가 한 뒤 답변을 받으면,

위 결과는 제가 준 context 내용과 거의 동일 합니다.

이렇듯 모르는 정보에 대한 답변을 얻는데는 한계가 존재합니다.

만약 이런 정보를 매번 사용하려는데 그때마다 context를 찾아서 올리기엔 토큰도 잡아먹고 관리하기도 힘듭니다. 그럼 이걸 해결하기위해 RAG을 한번 써보겠습니다.

with RAG

  1. 데이터 불러오기

from datasets import load_dataset

dataset = load_dataset(
    "jamescalam/llama-2-arxiv-papers-chunked",
    split="train"
)

RAG에 올릴 데이터로는 llama2에 대한 arixv 정보가 담긴 huggingface에 올라온 데이터를 사용했습니다.

  1. VectorDB: 데이터 저장소 마련

VectorDB로는 Pinecone을 사용했습니다. API key를 형성하고 python으로 불러옵니다.

  1. Embedding: 데이터의 vector 형태로의 변환

from langchain.embeddings.openai import OpenAIEmbeddings

embed_model = OpenAIEmbeddings(model="text-embedding-ada-002", openai_api_key=OPENAI_API_KEY)

texts = [
    'this is the first chunk of text',
    'then another second chunk of text is here'
]

res = embed_model.embed_documents(texts)
print(len(res), len(res[0]))

OpenAI 임베딩 모델을 사용해서 vector로 변환 해주었습니다. 이 모델 또한 과금이 되네요;; 하지만 변환을 한번 해주고 저장해 두면 다시 변환할 일은 없으니까 한번만 요금을 내면 됩니다.

VectorDB에 저장된 데이터중 하나인데 원본 문장(text)과 문장을 가져온 원본 데이터의 url, title을 저장하고 VALUES는 embedding 결과를 보여줍니다.

  1. Retrieval: 검색과 사용

from langchain.vectorstores import Pinecone

text_field = "text"  # the metadata field that contains our text

# initialize the vector store object
vectorstore = Pinecone(
    index, embed_model.embed_query, text_field # from my index
)
query = "What is so special about Llama 2?"
vectorstore.similarity_search(query, k=3)

질문과 관련한 k(여기선 3)개의 문장을 뽑아서 context에 추가했습니다.

DB내에서 유사도 검사를 하기 위해선 질문 또한 embedding 과정을 거쳐야 합니다.

def augment_prompt(query: str):
    # get top 3 results from knowledge base
    results = vectorstore.similarity_search(query, k=3)
    # get the text from the results
    source_knowledge = "\\n".join([x.page_content for x in results])
    # feed into an augmented prompt
    augmented_prompt = f"""Using the contexts below, answer the query.

    Contexts:
    {source_knowledge}

    Query: {query}"""
    return augmented_prompt

유사한 문장들을 prompt의 context로 추가해서 답변의 질을 높입니다.


다시한번 질문을 해보겠습니다.

Q: llama2 개발에 사용된 fine-tuning 방법은 무엇입니까?

  • without RAG (gpt 4)

    • A: LLaMA 모델에 대한 구체적인 fine-tuning 방법은 메타(Meta)가 제공한 기술 문서나 연구 논문에서 더 자세한 정보를 찾아볼 수 있습니다.

  • with RAG (gpt 3.5)

    • A: supervised fine-tuning (SFT), instruction tuning, iterative reward modeling, and reinforcement learning from human feedback (RLHF) 등이 사용됩니다.

이렇듯 gpt에 추가적인 정보를 알려주어 Specialty를 부과 할 수 있음을 알 수 있었습니다.

한계점 및 더 알아보고 싶은 것

  • VectorDB에 넣는 데이터에 대한 정제 방법

    • 유사도의 우선순위로 관련 문장을 뽑다보니 중복된 정보가 나와서 token을 잡아먹는 경우가 생김.

    • 이를 해결 하기 위해 DB 축적 단계에서 중복제거를 할 필요성을 느낌.

앞으로…

RAG 기술을 써서 내 정보를 넣고 면접, 자기소개서 작성에 도움을 주는 컨설턴트를 만들어보고 싶네요.

5
1개의 답글

👉 이 게시글도 읽어보세요