이 코드는 LangChain을 사용해 OpenAI의 언어 모델을 기반으로 Wikipedia 문서를 불러오고, 다양한 응답 스타일을 설정하여 질문에 대한 답변을 제공하는 예제입니다. 주요 단계별로 코드의 구성과 작동 방식을 자세히 설명하겠습니다.
from dotenv import load_dotenv
load_dotenv()
.env
파일에 저장된 OpenAI API 키를 불러오는 코드입니다. dotenv
라이브러리를 사용하여 환경 변수를 쉽게 관리할 수 있습니다.
embedding_function = OpenAIEmbeddings()
OpenAI의 임베딩 기능을 설정합니다. 이 기능은 텍스트를 벡터 형식으로 변환하여 데이터베이스에서 유사한 내용을 검색할 수 있도록 돕습니다.
inoformationWiki = input(str("검색할 내용을 입력하세요: "))
loader = WikipediaLoader(query=str(inoformationWiki))
documents = loader.load()
사용자에게 검색어를 입력받아 Wikipedia에서 해당 문서를 불러옵니다. WikipediaLoader
는 LangChain에서 제공하는 기능으로, 특정 키워드와 관련된 Wikipedia 문서를 불러오는 역할을 합니다.
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=500)
docs = text_splitter.split_documents(documents)
불러온 문서를 500자 단위로 나눕니다. CharacterTextSplitter
는 긴 문서를 작은 청크(조각)으로 나누어 모델이 쉽게 처리할 수 있도록 도와줍니다. 각 조각의 길이는 500자로 설정되어 있습니다.
db = Chroma.from_documents(docs, embedding_function, persist_directory='./MY_db')
db.persist()
벡터 스토어인 Chroma 데이터베이스에 나누어진 문서 조각을 저장합니다. persist_directory
에 지정된 디렉터리에 데이터베이스가 저장되며, 향후 검색을 위해 데이터가 지속적으로 유지됩니다.
llm = ChatOpenAI(temperature=0, model_name="gpt-4o", max_tokens=1000)
ChatOpenAI
모델을 생성하며, temperature
를 0으로 설정하여 일관된 답변을 얻습니다. temperature
가 낮을수록 모델의 응답이 덜 창의적이고 더 결정적이게 됩니다. model_name
은 사용할 언어 모델을 지정하며, 최대 생성 토큰 수는 1000으로 설정합니다.
retriever = MultiQueryRetriever.from_llm(retriever=db.as_retriever(), llm=llm)
저장된 벡터 데이터를 검색할 수 있도록 MultiQueryRetriever
를 설정합니다. 이 리트리버는 검색어를 입력하면 관련된 문서 조각을 찾아줍니다.
question = "이 내용은 무엇인가요? "
unique_docs = retriever.get_relevant_documents(query=question)
wikiOutput = unique_docs[0].page_content
print(wikiOutput)
question
이라는 질문에 맞는 관련 문서 조각을 검색하여 결과를 확인합니다. unique_docs
에 관련 문서가 저장되며, 첫 번째 문서의 내용을 wikiOutput
에 저장하여 출력합니다.
chat = ChatOpenAI(temperature=1, presence_penalty=0.6, max_tokens=3000)
새로운 ChatOpenAI
모델 인스턴스를 생성하며 temperature
를 1로 높여 답변에 좀 더 창의성을 부여하고, presence_penalty
를 설정하여 특정 주제에서 벗어나지 않도록 합니다.
beginner_template = "당신은 {wikiOutput} 에 대해 설명합니다. {input}"
expert_template = "당신은 소설가 이며 당신에게 불가능은 없습니다. {wikiOutput} 을 바탕으로 세상에 없는 소설을 써주세요. {input}"
empty_template = "빈 질문에 응답합니다."
각기 다른 응답 스타일을 위한 템플릿을 정의합니다.
beginner_template
: 단순 설명을 제공하는 초보자용 템플릿입니다.expert_template
: 소설가 스타일로 창의적인 소설을 생성하는 전문가용 템플릿입니다.empty_template
: 빈 질문에 대한 응답을 위한 템플릿입니다.beginner_prompt = ChatPromptTemplate.from_messages([HumanMessagePromptTemplate.from_template(beginner_template)])
expert_prompt = ChatPromptTemplate.from_messages([HumanMessagePromptTemplate.from_template(expert_template)])
empty_prompt = ChatPromptTemplate.from_messages([HumanMessagePromptTemplate.from_template(empty_template)])
각 템플릿을 ChatPromptTemplate
을 사용해 생성합니다.
beginner_chain = LLMChain(llm=llm, prompt=beginner_prompt)
expert_chain = LLMChain(llm=llm, prompt=expert_prompt)
empty_chain = LLMChain(llm=llm, prompt=empty_prompt)
각 템플릿과 모델을 결합한 LLMChain
을 생성합니다. LLMChain
은 주어진 템플릿에 따라 답변을 생성합니다.
input_text = "추가 설명을 해주세요."
beginner_response = beginner_chain.run(wikiOutput=wikiOutput, input=input_text)
expert_response = expert_chain.run(wikiOutput=wikiOutput, input=input_text)
empty_response = empty_chain.run(input=input_text)
각 체인을 실행하여 input_text
에 따른 답변을 생성하고, 각각 beginner_response
, expert_response
, empty_response
에 저장합니다.
print("Beginner Response:", beginner_response)
print("Expert Response:", expert_response)
print("Empty Response:", empty_response)
초보자, 전문가, 빈 질문에 대한 응답을 출력합니다.
이렇게 작성된 코드는 LangChain을 활용해 Wikipedia 문서를 불러오고, 다양한 스타일로 답변을 생성하며, 생성된 응답을 출력하는 기능을 수행합니다.
from langchain.document_loaders import WikipediaLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chat_models import ChatOpenAI
from langchain.retrievers.multi_query import MultiQueryRetriever
import os
from dotenv import load_dotenv
import logging
from langchain.prompts.chat import (
ChatPromptTemplate,
HumanMessagePromptTemplate,
)
from langchain.chains import LLMChain
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate, PromptTemplate
from langchain.chains import LLMChain
from langchain.chains.router import MultiPromptChain
from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE
# OpenAI API 키 로드
load_dotenv()
embedding_function = OpenAIEmbeddings()
# 위키피디아 문서 로드
inoformationWiki = input(str("검색할 내용을 입력하세요: "))
loader = WikipediaLoader(query=str(inoformationWiki))
documents = loader.load()
# 문서 분할
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=500)
docs = text_splitter.split_documents(documents)
# 벡터 스토어에 저장
# db = Chroma.from_documents(docs, embedding_function, persist_directory='./{inoformationWiki}')
db = Chroma.from_documents(docs, embedding_function, persist_directory='./MY_db') # 수정 필요
db.persist()
# ChatOpenAI 모델 생성 (온도는 0으로 설정)
llm = ChatOpenAI(temperature=0, model_name="gpt-4o", max_tokens=1000)
# 멀티 쿼리 리트리버 설정
retriever = MultiQueryRetriever.from_llm(retriever=db.as_retriever(), llm=llm)
# 로깅 설정
logging.basicConfig()
logging.getLogger('langchain.retrievers.multi_query').setLevel(logging.INFO)
# 질문하고 관련 문서 얻기
question = "이 내용은 무엇인가요? "
unique_docs = retriever.get_relevant_documents(query=question)
# 결과 확인
wikiOutput = unique_docs[0].page_content
print(wikiOutput)
# ChatOpenAI 메게변수 설정 변경
chat = ChatOpenAI(
temperature=1,
presence_penalty=0.6,
max_tokens=3000,
)
# 템플릿 정의
beginner_template = "당신은 {wikiOutput} 에 대해 설명합니다. {input}"
expert_template = "당신은 소설가 이며 당신에게 불가능은 없습니다. {wikiOutput} 을 바탕으로 세상에 없는 소설을 써주세요. {input}"
empty_template = "빈 질문에 응답합니다."
# 프롬프트 템플릿 생성
beginner_prompt = ChatPromptTemplate.from_messages([
HumanMessagePromptTemplate.from_template(beginner_template)
])
expert_prompt = ChatPromptTemplate.from_messages([
HumanMessagePromptTemplate.from_template(expert_template)
])
empty_prompt = ChatPromptTemplate.from_messages([
HumanMessagePromptTemplate.from_template(empty_template)
])
# LLMChain 생성
beginner_chain = LLMChain(llm=llm, prompt=beginner_prompt)
expert_chain = LLMChain(llm=llm, prompt=expert_prompt)
empty_chain = LLMChain(llm=llm, prompt=empty_prompt)
# 프롬프트 실행
input_text = "추가 설명을 해주세요." # 예시로 사용할 사용자 입력
# 각각의 프롬프트를 실행하여 결과 확인
beginner_response = beginner_chain.run(wikiOutput=wikiOutput, input=input_text)
expert_response = expert_chain.run(wikiOutput=wikiOutput, input=input_text)
empty_response = empty_chain.run(input=input_text)
print("Beginner Response:", beginner_response)
print("Expert Response:", expert_response)
print("Empty Response:", empty_response)