from dotenv import load_dotenv
from langchain_teddynote import logging
import os
# 환경 변수 로드 (API 키 등)
load_dotenv()
# 모델 및 캐시 경로 설정
os.environ["TRANSFORMERS_CACHE"] = "./cache/"
os.environ["HF_HOME"] = "./cache/"
# LangSmith 추적 설정 (프로젝트 이름 입력)
logging.langsmith("RAG-Project")
LangSmith 추적을 시작합니다.
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 문서 로드
loader = TextLoader(file_path="your_document.txt")
# 문서 분할
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
documents = text_splitter.split_documents(loader.load())
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
# 임베딩 모델 설정
embedding_model = OpenAIEmbeddings()
# 벡터 저장소 구축
vector_store = FAISS.from_documents(documents, embedding_model)
from langchain.retrievers import VectorStoreRetriever
# 검색기 설정
retriever = VectorStoreRetriever(vectorstore=vector_store)
from langchain_openai import ChatOpenAI
# 언어 모델 로드
from langchain_openai import ChatOpenAI
# ChatOpenAI 객체 생성
gpt = ChatOpenAI(
temperature=0.7, # 창의성과 일관성을 조절
model_name="gpt-4o", # 모델명
streaming = True
)
from langchain.prompts import PromptTemplate
# 프롬프트 템플릿 구성
prompt_template = PromptTemplate.from_template(
"Given the following context, answer the question: {context}\n\nQuestion: {question}\n\nAnswer:"
)
from langchain_core.output_parsers import StrOutputParser
# 결과 파서 설정
output_parser = StrOutputParser()
from langchain.chains import RetrievalQA
# RAG 체인 구성
rag_chain = RetrievalQA.from_chain_type(
llm=gpt,
chain_type="stuff",
retriever=retriever,
return_source_documents=True,
output_parser=output_parser # 체인에 결과 파서를 포함
)
|
연산자를 사용하여 연결):이 방식은 LangChain에서 체인을 구성할 때, 각 구성 요소를 단순하게 파이프(|
) 연산자를 사용해 연결하는 방식입니다. 이 경우, 각 구성 요소는 Runnable
객체로 간주되며, 순차적으로 실행됩니다. 예를 들어:
from langchain_core.output_parsers import StrOutputParser
# 프롬프트와 모델을 연결하는 체인 생성
chain = prompt | gpt | StrOutputParser()
여기서 prompt
, gpt
, 그리고 StrOutputParser
는 각각의 작업을 수행하고 다음 단계로 결과를 전달하는 구조입니다.
RetrievalQA
체인 구성 방식:RetrievalQA
는 RAG 구현을 위한 LangChain에서 제공하는 특정 체인입니다. 이 체인은 검색과 생성 단계를 함께 관리하며, 사용자가 복잡한 구조를 쉽게 사용할 수 있도록 from_chain_type
이라는 메서드를 제공합니다. 이 메서드는 검색기(retriever
), LLM(llm
), 결과 파서(output_parser
)와 같은 여러 요소를 하나의 체인으로 결합합니다.
예를 들어:
from langchain.chains import RetrievalQA
from langchain_core.output_parsers import StrOutputParser
# 결과 파서 설정
output_parser = StrOutputParser()
# RAG 체인 구성
rag_chain = RetrievalQA.from_chain_type(
llm=gpt,
chain_type="stuff",
retriever=retriever,
return_source_documents=True,
output_parser=output_parser # 체인에 결과 파서를 포함
)
이 방법은 단순한 파이프 연산자 대신, 복잡한 체인을 보다 쉽게 관리하고 구성할 수 있도록 도와줍니다. RetrievalQA
체인은 내부적으로 다양한 단계를 포함하고 있으며, 이 단계를 사용자가 쉽게 설정할 수 있도록 메서드를 제공합니다.
|
연산자를 사용하여 프롬프트, 모델, 파서를 직접 연결.RetrievalQA
체인 구성: 특정 체인 유형(RetrievalQA
)은 자체적인 체인 구성 메서드를 제공하며, 이를 통해 보다 복잡한 구조를 쉽게 관리 가능.두 방법은 사용 목적에 따라 선택될 수 있으며, RetrievalQA
는 특히 RAG 같은 복잡한 체인을 구성할 때 편리하게 사용할 수 있습니다.
from langchain_teddynote.messages import stream_response
# 질문에 대한 답변 생성 (스트리밍 출력 포함)
answer = gpt.stream("What is the capital of South Korea?")
stream_response(answer) # 스트리밍 출력
from dotenv import load_dotenv
from langchain_teddynote import logging
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
from langchain.retrievers import VectorStoreRetriever
from langchain.prompts import PromptTemplate
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_teddynote.messages import stream_response
# 1. 환경 설정
load_dotenv()
logging.langsmith("RAG-Project")
LangSmith 추적을 시작합니다.
# 2. 문서 로드 및 분할
loader = TextLoader(file_path="your_document.txt")
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
documents = text_splitter.split_documents(loader.load())
# 3. 임베딩 생성 및 벡터 저장소 구축
embedding_model = OpenAIEmbeddings()
vector_store = FAISS.from_documents(documents, embedding_model)
# 4. 검색기 설정
retriever = VectorStoreRetriever(vectorstore=vector_store)
# 5. 모델 로드
gpt = ChatOpenAI(temperature=0, model_name="gpt-4o", streaming=True)
# 6. 프롬프트 템플릿 및 결과 파서 설정
prompt_template = PromptTemplate.from_template(
"Given the following context, answer the question: {context}\n\nQuestion: {question}\n\nAnswer:"
)
output_parser = StrOutputParser()
# 7. 체인 구성
rag_chain = RetrievalQA.from_chain_type(
llm=gpt,
chain_type="stuff",
retriever=retriever,
return_source_documents=True,
output_parser=output_parser
)
# 8. 체인 실행 및 스트리밍 출력
answer = gpt.stream("What is the capital of South Korea?")
stream_response(answer)
전체 코드를 함수로 구조화하여 각 단계가 명확하게 분리되도록 만들어 보겠습니다. 각 함수는 특정 작업을 수행하도록 설계되어 있으며, 이를 통해 코드의 재사용성과 가독성을 높일 수 있습니다.
from dotenv import load_dotenv
from langchain_teddynote import logging
import os
def initialize_environment():
# 환경 변수 로드(API 키등)
load_dotenv()
# 모델 및 캐시 경로 설정
os.environ["TRANSFORMERS_CACHE"] = "./cache/"
os.environ["HF_HOME"] = "./cache/"
# LangSmith 추적 설정(프로젝트 이름 입력)
logging.langsmith("RAG-Project")
print("LangSmith 추적을 시작합니다.")
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
def load_and_split_document(file_path):
# 문서 로드
loader = TextLoader(file_path=file_path)
# 문서 분할
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
documents = text_splitter.split_documents(loader.load())
return documents
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
def create_vector_store(documents):
# 임베딩 모델 설정
embedding_model = OpenAIEmbeddings()
# 벡터 저장소 구축
vector_store = FAISS.from_documents(documents, embedding_model)
return vector_store
from langchain.retrievers import VectorStoreRetriever
def setup_retriever(vector_store):
# 검색기 설정
retriever = VectorStoreRetriever(vectorstore=vector_store)
return retriever
# 언어 모델 로드
from langchain_openai import ChatOpenAI
def load_language_model():
#ChatOpenAI 객체 생성
gpt = ChatOpenAI(temperature=0.7, model_name="gpt-4o", streaming=True)
return gpt
from langchain.prompts import PromptTemplate
def setup_prompt():
# 프롬프트 템플릿 구성
prompt_template = PromptTemplate.from_template(
"Given the following context, answer the question: {context}\n\nQuestion: {question}\n\nAnswer:"
)
output_parser = StrOutputParser()
return prompt_template, output_parser
from langchain_core.output_parsers import StrOutputParser
def setup_parser():
# 프롬프트 템플릿 구성
output_parser = StrOutputParser()
return prompt_template, output_parser
from langchain.chains import RetrievalQA
def create_rag_chain(gpt, retriever, output_parser):
rag_chain = RetrievalQA.from_chain_type(
llm=gpt,
chain_type="stuff",
retriever=retriever,
return_source_documents=True,
output_parser=output_parser
)
return rag_chain
from langchain_teddynote.messages import stream_response
def generate_answer(rag_chain, question):
answer = rag_chain({"question": question})
stream_response(answer["result"]) # 스트리밍 출력
return answer
모든 함수를 통합하여 전체 워크플로를 구현하는 최종 코드는 다음과 같습니다.
#1. 환경설정
from dotenv import load_dotenv
from langchain_teddynote import logging
import os
def initialize_environment():
# 환경 변수 로드(API 키등)
load_dotenv()
# 모델 및 캐시 경로 설정
os.environ["TRANSFORMERS_CACHE"] = "./cache/"
os.environ["HF_HOME"] = "./cache/"
# LangSmith 추적 설정(프로젝트 이름 입력)
logging.langsmith("RAG-Project")
print("LangSmith 추적을 시작합니다.")
#2. 문서 로드 및 분할
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
def load_and_split_document(file_path):
# 문서 로드
loader = TextLoader(file_path=file_path)
# 문서 분할
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
documents = text_splitter.split_documents(loader.load())
return documents
#3. 임베딩 생성 및 벡터 저장소 구축
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
def create_vector_store(documents):
# 임베딩 모델 설정
embedding_model = OpenAIEmbeddings()
# 벡터 저장소 구축
vector_store = FAISS.from_documents(documents, embedding_model)
return vector_store
#4. 검색기 설정
from langchain.retrievers import VectorStoreRetriever
def setup_retriever(vector_store):
# 검색기 설정
retriever = VectorStoreRetriever(vectorstore=vector_store)
return retriever
#5. 모델 로드
# 언어 모델 로드
from langchain_openai import ChatOpenAI
def load_language_model():
#ChatOpenAI 객체 생성
gpt = ChatOpenAI(temperature=0.7, model_name="gpt-4o", streaming=True)
return gpt
#6. 프롬프트 템플릿 및 결과 파서 설정
from langchain.prompts import PromptTemplate
def setup_prompt():
# 프롬프트 템플릿 구성
prompt_template = PromptTemplate.from_template(
"Given the following context, answer the question: {context}\n\nQuestion: {question}\n\nAnswer:"
)
output_parser = StrOutputParser()
return prompt_template, output_parser
# 7. 체인 구성
from langchain_core.output_parsers import StrOutputParser
def setup_parser():
# 프롬프트 템플릿 구성
output_parser = StrOutputParser()
return prompt_template, output_parser
from langchain.chains import RetrievalQA
def create_rag_chain(gpt, retriever, output_parser):
rag_chain = RetrievalQA.from_chain_type(
llm=gpt,
chain_type="stuff",
retriever=retriever,
return_source_documents=True,
output_parser=output_parser
)
return rag_chain
#8.체인 실행 및 스트리밍 출력
from langchain_teddynote.messages import stream_response
def generate_answer(rag_chain, question):
answer = rag_chain({"question": question})
stream_response(answer["result"]) # 스트리밍 출력
return answer
def main():
# 1. 환경 설정
initialize_environment()
# 2. 문서 로드 및 분할
documents = load_and_split_document(file_path="your_document.txt")
# 3. 임베딩 생성 및 벡터 저장소 구축
vector_store = create_vector_store(documents)
# 4. 검색기 설정
retriever = setup_retriever(vector_store)
# 5. 모델 로드
gpt = load_language_model()
# 6. 프롬프트 템플릿 및 결과 파서 설정
prompt_template, output_parser = setup_prompt_and_parser()
# 7. 체인 구성
rag_chain = create_rag_chain(gpt, retriever, output_parser)
# 8. 체인 실행 및 스트리밍 출력
question = "What is the capital of South Korea?"
generate_answer(rag_chain, question)
if __name__ == "__main__":
main()