데이터 전처리
데이터가 위와 같은 이미지 파일인 경우,
이를 읽어올 수 없기 때문에 데이터를 전달 할 수 없다.
이미지, 표 등과 같은 데이터는 vector DB에 효율적으로 저장할 수 없다.
따라서 알맞은 데이터를 전달하기 위해서는 데이터의 전처리가 중요하다!!
다음과 같이 이해할 수 있는 Markdown 포멧으로 데이터를 전처리 해줘야 한다.
| 종합소득 과세표준 | 세율 |
|-------------------|--------------------------------------------|
| 1,400만원 이하 | 과세표준의 6퍼센트 |
| 1,400만원 초과 5,000만원 이하 | 84만원 + (1,400만원을 초과하는 금액의 15퍼센트) |
| 5,000만원 초과 8,800만원 이하 | 624만원 + (5,000만원을 초과하는 금액의 24퍼센트) |
| 8,800만원 초과 1억5천만원 이하 | 3,706만원 + (8,800만원을 초과하는 금액의 35퍼센트)|
| 1억5천만원 초과 3억원 이하 | 3,706만원 + (1억5천만원을 초과하는 금액의 38퍼센트)|
| 3억원 초과 5억원 이하 | 9,406만원 + (3억원을 초과하는 금액의 38퍼센트) |
| 5억원 초과 10억원 이하 | 1억 7,406만원 + (5억원을 초과하는 금액의 42퍼센트)|
| 10억원 초과 | 3억 8,406만원 + (10억원을 초과하는 금액의 45퍼센트)|
키워드 사전을 활용하는 이유
- 예를 들어, 다음과 같은 질문이 전달되었다고 하자.
query = '연봉 5천만원인 거주자의 종합소득세는?'
- 다음의 코드로 query와 유사한 4개의 데이터를 Vector DB에서 뽑아보면, 원하는 데이터가 잘 추출되지 않는 것을 볼 수 있다.
retriever = database.as_retriever(search_kwargs={'k': 4})
retriever.invoke(query)
이럴 때에는 질문 query를 바로 전달하지 않고,
다음과 같이 keyword 사전을 활용하여 사용자 사용자 질문을 수정한 뒤 넘겨주는 것도 좋은 방법이다!
LangChain Expression Language (LCEL)
https://python.langchain.com/v0.2/docs/concepts/#langchain-expression-language
Conceptual guide | 🦜️🔗 LangChain
This section contains introductions to key parts of LangChain.
python.langchain.com
- 내용이 방대하지만, LCEL의 주요 요점은 두 개의 실행 파일을 시퀀스로 "체인"할 수 있다는 것임
- 이전 실행 가능 항목의 .invoke() 호출 출력은 다음 실행 가능 항목의 입력으로 전달된다.
- 이는 파이프 연산자(|) 또는 동일한 작업을 수행하는 보다 명시적인 .pipe() 메서드를 사용하여 수행할 수 있다.
The pipe operator: |
https://python.langchain.com/v0.2/docs/how_to/sequence/#the-pipe-operator-
How to chain runnables | 🦜️🔗 LangChain
This guide assumes familiarity with the following concepts:
python.langchain.com
pipe operator
- pipe operator를 사용하여 선언한 chain의 경우, chain 사용 시 파라미터를 전달 할 때 invoke()함수를 쓰면 된다!
ex)
dictionary_chain = prompt | llm | StrOutputParser()
question = dictionary_chain.invoke({"question": query, "dictionary" : dictionary})
prompt = ChatPromptTemplate.from_template(f"""
사용자의 질문을 보고, 우리의 사전을 참고해서 사용자의 질문을 변경해주세요.
만약 변경할 필요가 없다고 판단된다면, 사용자의 질문을 변경하지 않아도 됩니다.
그런 경우에는 질문만 리턴해주세요
사전: {dictionary}
질문: {{question}}
""")
llm = ChatOpenAI(model='gpt-4o') # 모델 불러오기
#keyword 사전을 이용해 query 수정하기
dictionary_chain = prompt | llm | StrOutputParser()
question = dictionary_chain.invoke({"question": query, "dictionary" : dictionary})
[전체 코드]
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import OpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore
from langchain_community.document_loaders import Docx2txtLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI
from pinecone import Pinecone
from langchain import hub
import getpass
import os
from dotenv import load_dotenv
# .env 파일에서 환경 변수를 로드
load_dotenv()
# 텍스트 스플리터 설정
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=400,
chunk_overlap=100,
)
loader = Docx2txtLoader('../trabean.docx')
document_list = loader.load_and_split(text_splitter=text_splitter)
# PINECONE API 키 설정
if not os.getenv("PINECONE_API_KEY"):
os.environ["PINECONE_API_KEY"] = getpass.getpass("Enter your Pinecone API key: ")
pinecone_api_key = os.environ.get("PINECONE_API_KEY")
# LangSmith API 키 설정
if not os.getenv("LANGSMITH_API_KEY"):
os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
langsmith_api_key = os.environ.get("LANGSMITH_API_KEY")
index_name = "chatbot-index"
pc = Pinecone(api_key=pinecone_api_key)
embedding = OpenAIEmbeddings(model='text-embedding-3-large')
database = PineconeVectorStore.from_existing_index(index_name=index_name, embedding=embedding)
# database = PineconeVectorStore.from_documents(document_list, index_name=index_name, embedding=embedding)
query = 'Trabean 통장의 환전 기능에 대해 알고 싶어'
dictionary = ["사람을 나타내는 표현 -> 거주자", "Trabean -> bean"]
prompt = ChatPromptTemplate.from_template(f"""
사용자의 질문을 보고, 우리의 사전을 참고해서 사용자의 질문을 변경해주세요.
만약 변경할 필요가 없다고 판단된다면, 사용자의 질문을 변경하지 않아도 됩니다.
그런 경우에는 질문만 리턴해주세요
사전: {dictionary}
질문: {{question}}
""")
llm = ChatOpenAI(model='gpt-4o') # 모델 불러오기
#keyword 사전을 이용해 query 수정하기
dictionary_chain = prompt | llm | StrOutputParser()
question = dictionary_chain.invoke({"question": query, "dictionary" : dictionary})
print(question)
# `k` 값을 조절해서 얼마나 많은 데이터를 불러올지 결정
retriever = database.as_retriever(search_kwargs={'k': 4})
relevant_docs = retriever.invoke(question)
# 검색된 문서 출력
for doc in relevant_docs:
print(doc.page_content)
prompt = hub.pull("rlm/rag-prompt") # 알맞은 프롬프트 생성 모델 불러오기
qa_chain = RetrievalQA.from_chain_type( # RetrievalQA 객체 생성
llm, # llm 모델
retriever=retriever,
chain_type_kwargs={"prompt": prompt}
)
answer = qa_chain.invoke({"query": question})
print(answer)
'프로젝트 개발 일지 > AI' 카테고리의 다른 글
[LLM with RAG] History (0) | 2024.09.26 |
---|---|
LangChain 이란? (0) | 2024.09.26 |
LLM이란? (3) | 2024.09.26 |