관리 메뉴

너와 나의 스토리

[LLM] Chat Completion API / RAG with Llama-index / 임베딩이란 본문

Data Analysis/LLM

[LLM] Chat Completion API / RAG with Llama-index / 임베딩이란

노는게제일좋아! 2024. 5. 22. 11:20
반응형

Chat Completion API

  • openAI의 gpt-3/4 모델 기반의 api
  • 이 API는 사용자와 AI 간의 대화 흐름을 관리하는데 사용된다.
  • 대화 형식
    • system: 대화의 맥락이나 모델의 행동을 설정하는데 사용됨
    • user: 실제 사용자가 입력한 텍스트
    • assistant: 모델이 생성한 응답 -> 이전 대화 내용을 전달하기 위해 사용됨
[
  {"role": "system", "content": "You are a helpful assistant."},
  {"role": "user", "content": "Who won the world series in 2020?"},
  {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."}
]

 

 

RAG(Retrieval Augmented Generation)

  • 정보 검색과 언어 생성을 결합하는 기법
  • 모델이 질문이나 요청에 대해 관련 정보를 외부 데이터베이스나 문서에서 검색
  • 검색된 정보를 바탕으로 응답을 생성하는데, 이 과정에서 언어 모델의 생성 능력을 활용
  • RAG는 두 가지 주요 단계를 결합하여 작동한다.
    • 정보 검색 단계(Retrieval)
      • 입력된 질문에 대해 관련 문서를 검색.
      • 검색 알고리즘 사용.
    • 언어 생성 단계(Generation)
      • 검색된 문서들을 입력으로 받아 응답을 생성.
      • 언어 생성 모델(GPT, BERT 등)을 사용하여 자연스러운 텍스트를 생성.
  • 검색 증강 언어 모델(Retrieval-Augmented Language Models, RALM)
    • 훈련과 추론 과정에 검색을 통합한는 검색 증강 언어 모델
    • 전통적인 언어 모델은 프롬프트를 기반으로 자기회기적으로 텍스트를 생성하는 반면, RALM은 문맥 검색 알고리즘을 사용해 외부 말뭉치에서 관련있는 문맥을 먼저 검색한다.
    • 문맥 검사는 일반적으로 문서를 벡터 임베딩으로 인덱싱한 후, 근사 최근접 이웃 검색을 통해 빠른 유사성 조회를 가능하게 한다.

 

임베딩(Imbedding)

  • 기계가 처리하고 이해할 수 있는 방식으로 내용을 수치적으로 표현한 것
  • 이 과정의 본질은 이미지나 텍스트와 같은 객체에서 그와 관련없는 세부 사항을 최대한 제거하면서 의미적 내용을 캡슐화하는 벡터로 변환하는 것이다.
  • 단어, 문장 또는 이미지와 같은 컨텐츠 조각을 다차원 벡터 공간으로 매핑하고, 두 임베딩 간의 거리는 의미적 유사성을 나타낸다.

 

벡터 인덱싱(Vector Indexing)

  • 인덱싱: 데이터를 검색 또는 저장을 최적하기 위한 방법
  • 벡터 인베딩의 경우, 인덱싱은 비슷한 벡터가 서로 인접하게 저장돼 빠른 근접 또는 유사성 검색이 가능하도록 한다.
  • 유사성 검색 인덱싱에서 사용되는 알고리즘들
    • 제품 양자화(Product Quantization, PQ)
    • 지역 민감 해싱(Locality Senitive Hashing)
    • HNSW(Hierarchical Navigable Small World)

 

벡터 데이터베이스 (Vector Database)

  • 벡터를 빠르게 저장하고 검색하기 우해 특별히 설계된 DB.
  • 문서를 인코딩하고 저장하는 LLM에 의해 생성된 임베딩을 저장하는 데 유용.
  • 임베딩을 벡터 디비에 저장함으로써, 의미적으로 유사한 텍스트를 검색하는 최근접 이웃 탐색을 효율적으로 수행할 수 있다.

 

VectorIndexRetriever와 RetrieverQueryEngine

  • 문서 검색과 쿼리 처리를 위한 구성 요소
  • 특히, 대규모 문서 집합에서 유사한 문서를 효율적으로 검색하고 이를 기반으로 쿼리에 응답하는 데 사용됨
  • 이를 통해 모델이 더 효율적으로 질문에 대한 답변을 제공할 수 있다.

 

VectorIndexRetreiver

  • 문서 벡터 인덱스에서 입력 쿼리에 유사한 문서를 검색하는 데 사용
  • 텍스트 임베딩을 활용하여 유사도 기반 검색을 수행
  • 대규모 문서 집합에서 특정 정보와 관련된 문서를 빠르고 효율적으로 찾기 위해 사용
  • 작동 방식
    • 문서 벡터화: 문서 집합의 각 문서를 임베딩 모델(예: OpenAI의 텍스트 임베딩 모델)을 사용하여 벡터로 변환합니다.
    • 쿼리 벡터화: 입력 쿼리도 동일한 방식으로 벡터로 변환합니다.
    • 유사도 계산: 쿼리 벡터와 문서 벡터들 간의 코사인 유사도 등을 계산하여 가장 유사한 문서를 찾습니다.
    • 결과 반환: 유사도 점수가 높은 문서들을 반환합니다.

 

RetreiverQueryEngine

  • VectorIndexRetriever를 사용하여 유사한 문서를 검색한 후, 해당 문서를 기반으로 쿼리에 대한 응답을 생성
  • 검색된 문서와 입력 쿼리를 종합하여 응답을 생성하는 합성기(response synthesizer)를 포함
  • 단순히 유사한 문서를 검색하는 것뿐만 아니라, 검색된 문서들로부터 의미 있는 응답을 생성하기 위해 사용
  • 작동 방식:
    • 문서 검색: VectorIndexRetriever를 사용하여 입력 쿼리에 유사한 문서를 검색합니다.
    • 응답 생성: 검색된 문서를 기반으로 입력 쿼리에 대한 응답을 생성합니다. 이를 위해 다양한 후처리(postprocessing) 단계를 거쳐 응답을 합성합니다.
    • 후처리: SimilarityPostprocessor 등을 사용하여 유사도 기준을 만족하는 문서만을 선택하고, 최종 응답을 정리합니다.

 

실습

1. open_api_key 등록

os.environ["OPENAI_API_KEY"] = getpass.getpass()
  • 이렇게하고, 실행시키면 api key를 입력하도록 박스가 나타남.

 

2. OpenAI client 생성

from openai import OpenAI

client = OpenAI()

 

 

3. Vector DB(Chroma) 생성

  • EphemeralClient(): 메모리 내에서 작동하는 chroma db 클라이언트를 생성
  • create_collection("quickstart"): "quickstart"라는 이름의 컬렉션을 생성
    • 벡터 임베딩을 저장하고 관리할 컬렉션을 생성
import chromadb

# create client and a new collection
chroma_client = chromadb.EphemeralClient() #on memory
chroma_collection = chroma_client.create_collection("quickstart") # 1번만 실행합니다!

 

  • Chroma는 벡터 스토어(vector store)로, 대규모 텍스트 데이터셋에서 벡터 임베딩을 저장하고 검색하는 데 사용된다.
  • 벡터 임베딩은 텍스트 데이터를 수치 벡터로 변환한 것이며, 이를 통해 문서 간의 유사도를 계산할 수 있다.
  • Chroma는 이러한 벡터 임베딩을 효율적으로 저장하고 검색할 수 있는 기능을 제공한다.

 

4. Embedding Model 정의

# 임베딩 레이어를 정의합니다.
embed_model = OpenAIEmbedding(
    model="text-embedding-3-small",
)

# load documents
documents = SimpleDirectoryReader("./부루마블.pdf").load_data()

 

 

5. Vector DB에 데이터 저장

# set up ChromaVectorStore and load in data
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
    documents, storage_context=storage_context, embed_model=embed_model
)
  • Embedding을 이용해서 vector DB에 text-embedding pair를 저장

 

6. 문서 검색

from llama_index.core import get_response_synthesizer
from llama_index.core.retrievers import VectorIndexRetriever
from llama_index.core.query_engine import RetrieverQueryEngine
from llama_index.core.postprocessor import SimilarityPostprocessor

# 리트리버 설정
retriever = VectorIndexRetriever(
    index=index, # 저장된 문서들을 불러옵니다.
    similarity_top_k=10, # 유사한 문장을 최대 몇 개까지 선택할지 설정합니다.
)

# 문서를 쿼리와 합쳐주는 합성기를 구현합니다.
response_synthesizer = get_response_synthesizer()

# 쿼리엔진을 동작해 동작시킵니다.
query_engine = RetrieverQueryEngine(
    retriever=retriever,
    response_synthesizer=response_synthesizer,
    node_postprocessors=[SimilarityPostprocessor(similarity_cutoff=0.3)],
)

# query
response = query_engine.query("부루마블이란?")
print(response)

 

7. RAG

from transformers import GPT2LMHeadModel, GPT2Tokenizer
 
# Load GPT-2 model and tokenizer
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
model = GPT2LMHeadModel.from_pretrained("gpt2")
 
def generate_answer(query, documents):
    # Combine the query with retrieved documents
    context = " ".join([doc['text'] for doc in documents])
    input_text = query + " " + context
     
    # Generate response
    inputs = tokenizer.encode(input_text, return_tensors="pt")
    outputs = model.generate(inputs, max_length=150, num_return_sequences=1)
    response = tokenizer.decode(outputs[0], skip_special_tokens=True)
     
    return response
 
# Perform a query
query = "부루마블이란?"
retrieved_docs = query_engine.query(query)
response = generate_answer(query, retrieved_docs)
print(response)
  • 쿼리한 결과를 기반으로 모델에게 질문
  • 쿼리한 결과는 관련 문서를 포함하고 있고, 모델은 보다 정확하고 문맥에 맞는 답변을 생성하게 된다.

 

8. Disk에 Chroma db 저장하기

# save to disk
db = chromadb.PersistentClient(path="./chroma_db")
chroma_collection = db.get_or_create_collection("quickstart")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)

index = VectorStoreIndex.from_documents(
    documents, storage_context=storage_context, embed_model=embed_model
)

 

9. Disk에서 Chroma db 가져와서 쿼리하기

# load from disk
db2 = chromadb.PersistentClient(path="./chroma_db")
chroma_collection = db2.get_or_create_collection("quickstart")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
index = VectorStoreIndex.from_vector_store(
    vector_store,
    embed_model=embed_model,
)

# Query Data from the persisted index
query_engine = index.as_query_engine()
response = query_engine.query("What is the prompt engineering?")
display(Markdown(f"{response}"))

 

 

기타 참고 사항

  • colab에서 pip install이 오래 걸리는 경우가 있다. 
    • 다음의 옵션을 추가해서 설치하면 빠름
!pip install -i https://mirrors.sustech.edu.cn/pypi/simple —trusted-host mirrors.sustech.edu.cn {package}

 

 

참고

- [LangChain으로 구현하는 LLM]

 

#COLAB설치오래걸리는문제해결 #RAG예제 #ChatAPI #ChatCompletionAPI #OpenAI #Llma_index

반응형
Comments