주피터 노트북에 적었던 것을 1개 파일로 모아본다.
import os, time
from langchain_community.document_loaders import Docx2txtLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from dotenv import load_dotenv
from langchain_community.embeddings import OllamaEmbeddings
from langchain_pinecone import PineconeVectorStore
from pinecone import Pinecone
from langchain_community.chat_models import ChatOllama
from langchain import hub
from langchain.chains import RetrievalQA
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from pprint import pprint
# 환경변수 로드.
load_dotenv()
# 텍스트 스플리터
text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
# 문서 가져와서 쪼개기.
loader = Docx2txtLoader("./system.docx")
# 가져온 문서를 쪼갠다.
document_list = loader.load_and_split(text_splitter=text_splitter)
# 임베딩 설정
# 경량화된 한국어 지원되는 ollama 모델...
embeddings = OllamaEmbeddings(
model="llama3.2:3b"
)
# pinecone API KEY
pinecone_api_key = os.environ.get("PINECONE_API_KEY")
pc = Pinecone(api_key=pinecone_api_key)
# embedding 과 dimension 맞춰야 함...
pinecone_database = PineconeVectorStore.from_documents(
documents=document_list,
embedding=embeddings,
pinecone_api_key=pinecone_api_key,
index_name="index-system"
)
# llm 설정
llm = ChatOllama(
model="llama3.2:3b"
)
# prompt model 설정
prompt_model = hub.pull("rlm/rag-prompt")
# 질문(query) 설정
query = "제9조(홈페이지 등 공개용 웹 서버 관리) 내용은?"
# retriever (데이터 가져오는) 설정
retriever = pinecone_database.as_retriever(search_kwargs={"k":4})
# qa (질문과 답변) 체이닝
qa_chain = RetrievalQA.from_chain_type(
llm,
retriever=retriever,
chain_type_kwargs={"prompt": prompt_model}
)
# 사용자 사전 설정.
dictionary = ["목차를 나타내는 표현 -> (홈페이지 등 공개용 웹 서버 관리) 추가"]
# prompt 설정
prompt = ChatPromptTemplate.from_template(f"""
사용자의 질문을 보고, 우리의 사전을 참고해서 질문을 변경해 주세요.
만약 변경할 필요가 없다고 판단된다면, 사용자의 질문을 변경하지 않아도 됩니다.
사전 : {dictionary}
질문 : {{question}}
""")
# 설정된 prompt 를 llm 에 입력하고 문자열 파싱을 한다.
dictionary_chain = prompt | llm | StrOutputParser()
# 적절하게 변경된 질문을 qa_chain 에 입력한다.
dictionary_qa_chain = {"query": dictionary_chain} | qa_chain
# invoke 로 실행.
ai_message = dictionary_qa_chain.invoke({"question" : query})
pprint(ai_message)
동작은 뭐... 되긴 한다. 시간이 좀더 걸리는 느낌...