LangChain을 활용한 Wikipedia 문서 검색 및 다중 응답 생성 방법 - 소설 배경, 주제 추천기

GoGoComputer·2024년 11월 10일
0

studyEct

목록 보기
5/10
post-thumbnail

이 코드는 LangChain을 사용해 OpenAI의 언어 모델을 기반으로 Wikipedia 문서를 불러오고, 다양한 응답 스타일을 설정하여 질문에 대한 답변을 제공하는 예제입니다. 주요 단계별로 코드의 구성과 작동 방식을 자세히 설명하겠습니다.

1. OpenAI API 키 로드 및 초기 설정

from dotenv import load_dotenv
load_dotenv()

.env 파일에 저장된 OpenAI API 키를 불러오는 코드입니다. dotenv 라이브러리를 사용하여 환경 변수를 쉽게 관리할 수 있습니다.

embedding_function = OpenAIEmbeddings()

OpenAI의 임베딩 기능을 설정합니다. 이 기능은 텍스트를 벡터 형식으로 변환하여 데이터베이스에서 유사한 내용을 검색할 수 있도록 돕습니다.

2. 위키피디아 문서 불러오기

inoformationWiki = input(str("검색할 내용을 입력하세요: "))
loader = WikipediaLoader(query=str(inoformationWiki))
documents = loader.load()

사용자에게 검색어를 입력받아 Wikipedia에서 해당 문서를 불러옵니다. WikipediaLoader는 LangChain에서 제공하는 기능으로, 특정 키워드와 관련된 Wikipedia 문서를 불러오는 역할을 합니다.

3. 문서 분할

text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=500)
docs = text_splitter.split_documents(documents)

불러온 문서를 500자 단위로 나눕니다. CharacterTextSplitter는 긴 문서를 작은 청크(조각)으로 나누어 모델이 쉽게 처리할 수 있도록 도와줍니다. 각 조각의 길이는 500자로 설정되어 있습니다.

4. 벡터 스토어에 저장

db = Chroma.from_documents(docs, embedding_function, persist_directory='./MY_db')
db.persist()

벡터 스토어인 Chroma 데이터베이스에 나누어진 문서 조각을 저장합니다. persist_directory에 지정된 디렉터리에 데이터베이스가 저장되며, 향후 검색을 위해 데이터가 지속적으로 유지됩니다.

5. ChatOpenAI 모델 설정

llm = ChatOpenAI(temperature=0, model_name="gpt-4o", max_tokens=1000)

ChatOpenAI 모델을 생성하며, temperature를 0으로 설정하여 일관된 답변을 얻습니다. temperature가 낮을수록 모델의 응답이 덜 창의적이고 더 결정적이게 됩니다. model_name은 사용할 언어 모델을 지정하며, 최대 생성 토큰 수는 1000으로 설정합니다.

6. 멀티 쿼리 리트리버 설정

retriever = MultiQueryRetriever.from_llm(retriever=db.as_retriever(), llm=llm)

저장된 벡터 데이터를 검색할 수 있도록 MultiQueryRetriever를 설정합니다. 이 리트리버는 검색어를 입력하면 관련된 문서 조각을 찾아줍니다.

7. 질문을 입력하고 관련 문서 얻기

question = "이 내용은 무엇인가요? "
unique_docs = retriever.get_relevant_documents(query=question)
wikiOutput = unique_docs[0].page_content
print(wikiOutput)

question이라는 질문에 맞는 관련 문서 조각을 검색하여 결과를 확인합니다. unique_docs에 관련 문서가 저장되며, 첫 번째 문서의 내용을 wikiOutput에 저장하여 출력합니다.

8. ChatOpenAI 모델의 매개변수 설정 변경

chat = ChatOpenAI(temperature=1, presence_penalty=0.6, max_tokens=3000)

새로운 ChatOpenAI 모델 인스턴스를 생성하며 temperature를 1로 높여 답변에 좀 더 창의성을 부여하고, presence_penalty를 설정하여 특정 주제에서 벗어나지 않도록 합니다.

9. 다양한 응답 스타일을 위한 프롬프트 템플릿 정의

beginner_template = "당신은 {wikiOutput} 에 대해 설명합니다. {input}"
expert_template = "당신은 소설가 이며 당신에게 불가능은 없습니다. {wikiOutput} 을 바탕으로 세상에 없는 소설을 써주세요. {input}"
empty_template = "빈 질문에 응답합니다."

각기 다른 응답 스타일을 위한 템플릿을 정의합니다.

  • beginner_template: 단순 설명을 제공하는 초보자용 템플릿입니다.
  • expert_template: 소설가 스타일로 창의적인 소설을 생성하는 전문가용 템플릿입니다.
  • empty_template: 빈 질문에 대한 응답을 위한 템플릿입니다.

10. 프롬프트 템플릿 생성

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을 사용해 생성합니다.

11. 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)

각 템플릿과 모델을 결합한 LLMChain을 생성합니다. LLMChain은 주어진 템플릿에 따라 답변을 생성합니다.

12. 프롬프트 실행

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에 저장합니다.

13. 결과 출력

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)
profile
IT를 좋아합니다.

0개의 댓글