카테고리 없음

[LangChain RAG 구축 시리즈 Ep.29] 🧠 멀티 문서 기반 답변 생성 시 참조 문서 요약 전략

ygtoken 2025. 4. 5. 22:46
728x90

RAG 시스템이 문서를 검색해 답변을 생성할 때,
단일 문서만 참조하는 것이 아니라 여러 문서를 동시에 참조하는 경우가 많습니다.

하지만 GPT가 3~5개 문서를 한꺼번에 받게 되면,

  • 핵심 내용이 흐려지거나
  • 전체 내용을 단순 나열하거나
  • 응답 길이가 길어지고 요점을 놓치게 됩니다.

그래서 이번 글에서는:

  • ✅ LangChain의 stuff, map_reduce, refine 체인 전략을 이해하고
  • ✅ 멀티 문서에 대한 요약을 보다 효과적으로 수행할 수 있도록
  • ✅ 실제 체인 구조를 비교하고 선택하는 기준을 제시합니다.

🎯 목표

  • 여러 문서를 입력받아 GPT가 요약한 응답을 생성하는 구조 설계
  • stuff, map_reduce, refine 체인 방식 비교
  • 실무에서 적용 가능한 요약 전략 예제 구현

🧠 Step 1. 체인 비교를 위한 기본 구조 준비

# src/chain_compare.py

from langchain.chat_models import ChatOpenAI
from langchain.chains.combine_documents import (
    StuffDocumentsChain,
    MapReduceDocumentsChain,
    RefineDocumentsChain
)
from langchain.prompts import PromptTemplate
from langchain.docstore.document import Document

# ✅ 기본 LLM 설정
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)

# ✅ 공통 프롬프트 정의 (질문은 요약 지시)
prompt = PromptTemplate.from_template(
    "다음 문서들을 참고하여 요약된 응답을 생성하세요:\n\n{context}"
)

# ✅ 샘플 문서 리스트 (예시)
docs = [
    Document(page_content="products 테이블에는 상품의 ID, 이름, 카테고리 정보가 포함됩니다."),
    Document(page_content="orders 테이블은 주문 ID, 고객 ID, 상품 ID, 주문일을 포함합니다."),
    Document(page_content="customers 테이블은 고객의 ID, 이름, 지역 정보를 가지고 있습니다.")
]

🧪 Step 2. Stuff 방식 체인

# ✅ Stuff 방식: 모든 문서를 하나로 합쳐서 한 번에 처리

stuff_chain = StuffDocumentsChain(
    llm_chain=prompt | llm,       # 프롬프트 → LLM으로 연결
    document_variable_name="context"
)

result = stuff_chain.run(docs)

print("🧾 Stuff 방식 응답:")
print(result)

📝 장점: 빠르고 간단함
⚠️ 단점: 문서 수가 많거나 길면 출력이 초과될 수 있음


🧪 Step 3. MapReduce 방식 체인

# ✅ MapReduce 방식: 각 문서를 개별 처리 → 부분 응답 → 통합 요약

map_reduce_chain = MapReduceDocumentsChain.from_llm(
    llm=llm,
    prompt=prompt,
    document_variable_name="context"
)

result = map_reduce_chain.run(docs)

print("🗂️ MapReduce 방식 응답:")
print(result)

📝 장점: 문서가 많아도 안정적 처리 가능
⚠️ 단점: 처리 속도가 상대적으로 느림


🧪 Step 4. Refine 방식 체인

# ✅ Refine 방식: 첫 문서에서 초안 생성 → 다음 문서마다 점진적 개선

refine_prompt = PromptTemplate.from_template(
    "초기 요약: {existing_answer}\n새로운 문서: {context}\n개선된 응답을 작성하세요."
)

refine_chain = RefineDocumentsChain.from_llm(
    llm=llm,
    initial_prompt=prompt,
    refine_prompt=refine_prompt,
    document_variable_name="context"
)

result = refine_chain.run(docs)

print("🔁 Refine 방식 응답:")
print(result)

📝 장점: 문서마다 반영을 반복하며 깊이 있는 응답 가능
⚠️ 단점: 초안이 너무 단순하면 개선 효과가 떨어짐


📎 요약 및 핵심 정리

방식 특징 적합한 상황
Stuff 모든 문서를 한번에 입력 문서 수 적고 짧을 때
MapReduce 분할 요약 후 통합 문서 수가 많고 균일할 때
Refine 초안 생성 후 문서마다 개선 순차적 정제 또는 깊이 있는 요약
  • 멀티 문서를 다룰 때는 GPT에게 **"모든 걸 보여준다"기보다는 "잘게 나누고 요약하게 한다"**는 관점이 중요합니다.
  • 특히 문서가 많고 길다면 MapReduce나 Refine이 더 안정적입니다.
728x90