키워드 사전 활용으로 Retrieval 효율개선 (LangChain)

2025. 5. 17. 01:48·Python/Langchain

들어가며


사용자 질문 표현이 검색 성능에 미치는 영향

여러가지 Chat GPT를 포함한 생성형 AI 모델들을 사용하게 되면, 종종 사용자 질문이 모델의 답변 정확도에 큰 영향을 주는 것을 체감하게 된다. 특히 RAG 이전 실습에서 소득세법 문서를 학습시켜, 간단한 AI 모델을 구성하여 질문해보면서 느꼈던 점은, 사용자 질문의 표현 방식이 검색 성능에 치명적인 영향을 미친다는 것이었다

{'query': '연봉 5천만원인 직장인의 종합소득세는?',

 'result': '근로소득에 대한 종합소득세는 기본세율이 적용됩니다. 따라서, 연봉 5천만원인 직장인의 종합소득세는 
 개별적인 경우에 따라 달라질 수 있으며 정확한 계산을 위해서는 기본세율표를 참조하여야 합니다. 
구체적인 세율 적용 및 공제 항목을 고려해 정확한 금액을 산정하는 것을 권장합니다.'}


예시로, 만약에 사용자 질문이 "연봉 5천만 원 거주자의 종합소득세는?"이라면 이는 모델이 이해할 수 있는 형태지만, 법령 원문에는 "거주자", "과세표준", "세율" 같은 용어가 명확히 기재되어 있지 않으면 검색이 어려워질 수 있다.
해당 문제를 해결하기 위해서 키워드 사전이라는 개념을 도입하여 배웠다

ChatOpenAI로 간단한 LLM 구현


해결법 : 키워드 사전 방식 사용

이 문제를 해결하기 위해 도입한 것이 바로 키워드 사전이라는 개념이였다

키워드 사전이란 ? 
키워드 사전은 사용자의 질문에 포함된 자연어 표현을 도메인에 맞는 용어로 매핑하는 일종의 중간 필터 역할을 한다
ex) 사람을 나타내는 표현을 “거주자”로 변환, 세금 계산을 “종합소득과세표준” 등으로 바꾸는 식


이처럼 단어의 의미와 맥락을 이해하여 유사한 의미를 가진 문서를 찾는 방식으로 해주고, 추가로 키워드 기반 검색을 보완적으로 사용하여, 정확한 단어가 포함된 문서의 내용을 찾는 법을 배웠다. 탐색할 문서가 너무 방대하고 넓은 AI에게 키워드가 들어간 문서를 놓칠 위험을 줄여주고, 동시에 임베딩 기반의 시맨틱 검색을 통해서 단어의 의미와 맥락을 이해하여 유사한 내용을 찾아내는 실습이였다


본론

이제부터는 개념적인 설명보다는, 실제 실습을 진행했던 코드를 공유와 함께 관련한 내용을 다뤄보려고한다
문서 데이터로는 소득세법 내용을 담고 있는 .docx 파일을 사용하였다

소득세법 공식문서

해당 내용은 아래 링크에 나와있는 문서라, 관련한 내용을 첨부할때 참고만 해주면 좋을거같다

https://law.go.kr/%EB%B2%95%EB%A0%B9/%EC%86%8C%EB%93%9D%EC%84%B8%EB%B2%95

 

소득세법

 

law.go.kr


Python 환경 기본 세팅

먼저 개발 환경을 설정합니다. pyenv를 이용해 Python 3.10.13을 설치하고, 해당 프로젝트 전용 가상환경을 구성했다

터미널에서 Python 기본 설정

이후 langchain, langchain-openai, python-dotenv 등을 설치해 LangChain 기반의 기본 환경을 갖췄다

%pip install langchain-openai python-dotenv

문서 업로드 및 텍스트 분할

LangChain을 활용한 Vector Database 변경 😲

LangChain에서 제공하는 Docx2txtLoader를 사용해 해당 문서를 불러오고, RecursiveCharacterTextSplitter 로 분할했는데, chunk 단위는 1500자, 오버랩은 200자 설정으로 텍스트의 맥락을 충분히 유지하도록 해주었다


임베딩 및 Pinecone 벡터DB 연동

다음으로는 다음으로는 OpenAI의 text-embedding-3-large 모델을 사용해 임베딩을 진행하고, 이를 Pinecone에 저장하는 방식을 진행했다

text-embedding-3-large  모델으로 생성 (프리티어)

from pinecone import Pinecone
from langchain_pinecone import PineconeVectorStore

index_name = 'tex-index'
pinecone_api_key = os.environ.get("PINECONE_API_KEY")
pc = Pinecone(api_key=pinecone_api_key)

database = PineconeVectorStore.from_existing_index(
    index_name=index_name,
    embedding=embedding
)

위 내용처럼, inecone Index에 연결하기 위해 from_existing_index 방식을 사용해주게 되면, 아래 사진처럼 나눠서 저장이 된다

실제 Pinecone에 나눠서 저장되는 문서 내용들


search_kwargs로 제어하는 검색 문서 수

RetrievalQA 체인을 구성할 때, 가장 먼저 설정하는 핵심 파라미터 중 하나는 retriever이다. 임베딩된 벡터 DB에서 사용자의 쿼리에 가장 관련된 문서를 가져오는 역할을 하며, 검색 결과 수를 조정하고 싶다면 search_kwargs에서 k 값을 변경하면 되는 방식이다

retriever = database.as_retriever(search_kwargs={'k': 4})

 

위 예시처럼, k=4로 설정하면 관련도 순으로 최대 4개의 문서를 반환하게 되며, 이 값은 결과의 다양성과 정확도 간 균형을 설정하는 데 매우 중요하다


답변 생성을 위한 Retrieval

LangChain의 hub를 이용한 RAG 체인

이후에는 LangChain에서 제공하는 hub 기능을 활용해 RetrievalQA 체인을 구성했는데, 이 RetrievalQA는 사용자의 질문을 받아 관련 문서를 검색하고, 이를 기반으로 LLM이 응답을 생성하는 구조이다

실제 현업에서 ChatBot 구현시 RetrievalQA대신, create_retrieval_chain으로 고도화 하는 과정도 거친다고 하는데, 해당 내용은 dictionary_chain 이라는 개념과 연계하여 사용이 가능하다고 한다

관련해서 추가적으로 궁금한 내용이 있다면 아래 링크를 참고해주면 좋을거같다 👍🏻

https://rudaks.tistory.com/entry/langchain-Langchain%EC%97%90%EC%84%9C-createretrievalchain-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0

 

[langchain] Langchain에서 create_retrieval_chain 사용하기

create_retrieval_chain은 Langchain에서 문서를 검색하고 그 결과를 처리하는 데 매우 유용한 체인이다. 여기에서는 이 함수의 핵심 요소와 사용 방법을 알아보자.1. create_retrieval_chain의 목적이 함수는 두

rudaks.tistory.com

 

다시 돌아와서, 아래 사진처럼 처럼 invoke() 메서드를 호출한다면 모델이 어떤 문서를 기반으로 답변을 생성했는지를 실제로 확인할 수 있었다. 더 구체적으로는 문서에서 어떤 내용들을 가져오는지 확인도 가능했다

실제 실습때 출력된 소득세 Document

출력된 Document 객체에는 해당 문서의 경로와 함께, page_content에 검색된 텍스트도 함께 포함되어 있어 디버깅이나 추적에도 유용하다고 한다


키워드 사전을 이용한 질문 전처리

이제 실습 내용중에서 개인적으로 가장 핵심이라 생각했던, 사전 기반 전처리 로직이다. 사용자 질문에 포함된 일상어를 우리가 정의한 키워드 사전에 따라 변환하는 로직이며, LangChain의 ChatPromptTemplate과 StrOutputParser를 통해 구성한다

 

실제 코드의 내용은 아래와 같았다

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

dictionary = ["사람을 나타내는 표현 -> 거주자"]

prompt = ChatPromptTemplate.from_template(f"""
    사용자의 질문을 보고, 우리의 사전을 참고해서 사용자의 질문을 변경해주세요.
    만약 변경할 필요가 없다고 판단된다면, 사용자의 질문을 변경하지 않아도 됩니다.
    그런 경우에는 질문만 리턴해주세요
    사전: {dictionary}
    
    질문: {{question}}
""")

dictionary_chain = prompt | llm | StrOutputParser()
tax_chain = {"query": dictionary_chain} | qa_chain

 

이렇게 구성한 체인에 질문을 넘기면 사전 적용 여부를 판단하고, 자동으로 키워드가 반영된 쿼리로 변경 후 응답까지 받아볼 수 있었다

{'query': '연봉 5천만원인 거주자의 종합소득세는?',
 'result': '연봉 5천만원인 거주자의 종합소득세는 624만원입니다. 
 5천만원 이하의 소득에는 1,400만원 초과 금액에 15%의 세율이 적용되며, 84만원을 더하여 계산합니다.'}

 

아래의 이전 답변과 비교했을때, 내용은 짧아졌지만, 질문 의도에 맞는 고도화된 원하는 답변을 받을 수 있다는게 신기했다 👀

{'query': '연봉 5천만원인 직장인의 종합소득세는?',
 'result': '근로소득에 대한 종합소득세는 기본세율이 적용됩니다. 따라서, 연봉 5천만원인 직장인의 종합소득세는 
 개별적인 경우에 따라 달라질 수 있으며 정확한 계산을 위해서는 기본세율표를 참조하여야 합니다. 
 구체적인 세율 적용 및 공제 항목을 고려해 정확한 금액을 산정하는 것을 권장합니다.'}

마치며

배달음식 관련 Retrieval을 위한키워드 사전의 중요성

지금은 단순히 RetrievalQA 체인만 사용해봤지만, 관련해서 공부하면서 앞서 설명했었던 create_retrieval_chain 같은, 고급 체인을 이용해서 실제 현업에서 쓸만한 구조로 확장하는 연습도 해봐야겠다는 생각이 들었다

 

추후에 내가 좀 더 지식이 쌓이게 된다면, 백엔드는 Spring으로 챗봇 서버를 구축한 다음에, LangChain은 Python으로 돌려서 스프링 프로젝트에도 적용해보고싶다 🔥

 

'Python > Langchain' 카테고리의 다른 글

FewShot, ChatHistory 활용해서 RAG 고도화 + Streamlit으로 배포 (LangChain)  (2) 2025.05.28
RAG 개념 + Vector와 Embedding (Python)  (1) 2025.05.13
'Python/Langchain' 카테고리의 다른 글
  • FewShot, ChatHistory 활용해서 RAG 고도화 + Streamlit으로 배포 (LangChain)
  • RAG 개념 + Vector와 Embedding (Python)
huncozyboy
huncozyboy
이지훈
  • huncozyboy
    열정을 기록하기
    huncozyboy
  • 전체
    오늘
    어제
    • 분류 전체보기 (63)
      • Spring (26)
        • JWT (3)
        • 무한 스크롤 (1)
        • 매칭 로직 (2)
        • OAuth (4)
        • 자동화 (1)
        • 캐싱 (1)
        • AOP (2)
        • Swagger (1)
        • S3 (1)
        • CORS (1)
        • Spring Retry (0)
        • Webhook (2)
        • Grapheme Cluster (1)
        • 연관관계 (1)
        • CS 개념 (5)
      • DevOps (13)
        • 스왑 메모리 (1)
        • Blue Green (2)
        • Docker (7)
        • Route 53 (1)
        • 리버스 프록시 (2)
      • AI (2)
        • Claude Code (1)
        • Copilot (1)
      • CS (4)
        • JAVA (4)
      • Github (1)
        • Conflict (1)
      • Python (4)
        • Langchain (3)
        • Crawling (1)
      • 일상 (3)
        • 회고록 (1)
      • 알고리즘 (10)
        • 투포인터 (0)
        • 슬라이딩 윈도우 (0)
        • 정렬 (0)
        • 이분 탐색 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    OAuth
    EC2
    DevOps
    java
    도커
    알고리즘
    스프링
    JWT
    백준
    Docker
    redis
    프로그래머스
    https
    aws
    LangChain
    Spring
    코딩테스트
    수도코드
    자바
    코테
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
huncozyboy
키워드 사전 활용으로 Retrieval 효율개선 (LangChain)
상단으로

티스토리툴바