1 분 소요

TIL: LLM과 RAG를 활용한 AI 챗봇 만들기

1. 사용환경 준비

  • OpenAI API 키를 환경 변수에서 가져오고, 필요한 라이브러리를 임포트한다.
  • ChatOpenAI 모델을 초기화하여 사용할 준비를 한다.
import os
from getpass import getpass
OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
from langchain_openai import ChatOpenAI

# 모델 초기화
model = ChatOpenAI(model="gpt-4o-mini")

2. 모델 로드

  • PDF 파일을 로드하기 위해 PyPDFLoader를 사용한다.
  • 지정한 경로의 PDF 파일을 읽어 문서로 변환한다.
from langchain.document_loaders import PyPDFLoader

# PDF 파일 로드. 파일의 경로 입력
loader = PyPDFLoader("[2024 한권으로 OK 주식과 세금].pdf")
docs = loader.load()

3. 문서 청킹

  • CharacterTextSplitter를 사용하여 문서를 작은 청크로 나눈다.
  • 청크의 크기와 중복되는 부분을 설정하여 문맥을 유지한다.
from langchain.text_splitter import CharacterTextSplitter

text_splitter = CharacterTextSplitter(
    separator="\n\n",
    chunk_size=100,
    chunk_overlap=10,
    length_function=len,
    is_separator_regex=False,
)

splits = text_splitter.split_documents(docs)

# 청킹된 내용을 상위 10개까지 출력
for i, split in enumerate(splits[:10]):
    print(f"Chunk {i+1}:\n{split.page_content}\n")

4. RecursiveCharacterTextSplitter 사용

  • RecursiveCharacterTextSplitter를 사용하여 더 자연스러운 텍스트 분할을 시도한다.
  • 여러 구분자를 순차적으로 사용하여 문맥을 보존한다.
from langchain.text_splitter import RecursiveCharacterTextSplitter

recursive_text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=10,
    length_function=len,
    is_separator_regex=False,
)

splits = recursive_text_splitter.split_documents(docs)

# 청킹된 내용을 상위 10개까지 출력
for i, split in enumerate(splits[:10]):
    print(f"Chunk {i+1}:\n{split.page_content}\n")

5. 벡터 임베딩 생성

  • OpenAI의 임베딩 모델을 초기화하여 문서의 벡터 표현을 생성한다.
from langchain_openai import OpenAIEmbeddings

# OpenAI 임베딩 모델 초기화
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")

6. 벡터 스토어 생성

  • FAISS를 사용하여 문서의 벡터 스토어를 생성한다.
import faiss
from langchain_community.vectorstores import FAISS

vectorstore = FAISS.from_documents(documents=splits, embedding=embeddings)

7. RAG 체인 설정

  • 질문을 기반으로 관련 문서를 검색하고, 답변을 생성하는 RAG 체인을 설정한다.
retriever = vectorstore.as_retriever(search_type="similarity", search_kwargs={"k": 1})

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

# 프롬프트 템플릿 정의
contextual_prompt = ChatPromptTemplate.from_messages([
    ("system", "Answer the question using only the following context."),
    ("user", "Context: {context}\\n\\nQuestion: {question}")
])

8. 디버깅을 위한 클래스 추가

  • 디버깅을 위한 DebugPassThrough 클래스를 정의하여 각 단계의 출력을 확인한다.
class DebugPassThrough(RunnablePassthrough):
    def invoke(self, *args, **kwargs):
        output = super().invoke(*args, **kwargs)
        print("Debug Output:", output)
        return output

9. 사용자 질문 처리

  • 사용자로부터 질문을 입력받고, RAG 체인을 통해 답변을 생성한다.
while True: 
    print("========================")
    query = input("질문을 입력하세요 (종료하려면 'q' 또는 'quit' 입력): ")
    
    if query.lower() in ['q', 'quit']:
        print("프로그램을 종료합니다.")
        break
        
    response = rag_chain_debug.invoke(query)
    print("Final Response:")
    print(response.content)

10. RAG vs 기존 챗봇 비교

  • RAG의 장점과 기존 챗봇의 한계를 비교하여 설명한다.
  • RAG는 실시간 정보 활용, 정확성 향상, 맞춤형 지식베이스 등의 장점을 가진다.

태그: ,

카테고리:

업데이트:

댓글남기기