728x90
지금까지 우리는 사용자 질문을 기반으로
적절한 Iceberg 테이블을 선택하고, 해당 문서에서 정보를 검색해
GPT가 정답을 생성하는 단발성 RAG 시스템을 구축해왔습니다.
하지만 실제 업무에서 사용자가 묻는 방식은 이렇습니다:
- “상품 목록 알려줘”
- (이후) “그 중에서 가격이 가장 높은 건 뭐야?”
- (이후) “그 상품의 고객 리뷰는 있어?”
이처럼 대화 흐름이 이어지는 구조에서는
이전 질문과 응답이 다음 질문에 영향을 주어야 합니다.
이번 글에서는 이러한 흐름을 구현하기 위해
ConversationBufferMemory를 기반으로 대화 상태를 유지하는 구조를 설계합니다.
🎯 목표
- LangChain의 Memory 기능을 이해하고 적용
- 질문-응답의 히스토리를 유지한 대화형 RAG 구현
- 다양한 테이블에서 이어지는 질의를 자연스럽게 처리
🧠 Step 1. 대화형 QA 체인 생성 함수
# src/conversational_chain.py
from langchain.chains import ConversationalRetrievalChain
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.memory import ConversationBufferMemory
def create_conversational_chain(db_path: str, collection_name: str, k: int = 2):
"""
대화형 QA 체인을 구성합니다.
문맥을 유지하기 위해 Memory 객체를 함께 사용합니다.
"""
# ✅ 문서 임베딩 모델 설정
embedding = OpenAIEmbeddings()
# ✅ ChromaDB 컬렉션 로딩
vectordb = Chroma(
persist_directory=db_path,
collection_name=collection_name,
embedding_function=embedding
)
# ✅ GPT 모델 구성 (대화 기반 응답 생성)
llm = ChatOpenAI(
model_name="gpt-3.5-turbo",
temperature=0.2
)
# ✅ 메모리 구성: 이전 질문과 답변을 자동으로 기억
memory = ConversationBufferMemory(
memory_key="chat_history", # 체인에서 사용하는 메모리 키 이름
return_messages=True # 이전 대화 기록을 message 형태로 반환
)
# ✅ 대화형 QA 체인 생성
chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vectordb.as_retriever(search_kwargs={"k": k}),
memory=memory,
return_source_documents=True # GPT가 참조한 문서를 함께 반환
)
return chain
⚙️ Step 2. FastAPI에서 메모리 적용
# src/rag_server_conversational.py
from fastapi import FastAPI, Depends
from pydantic import BaseModel
from src.auth import verify_api_key
from src.conversational_chain import create_conversational_chain
import uvicorn
app = FastAPI()
# ✅ 요청 구조: 질문 외에 세션 ID 추가 가능 (여기서는 단순 처리)
class QueryRequest(BaseModel):
question: str
# ✅ 체인 생성 (여기선 단일 컬렉션 사용 예시)
qa_chain = create_conversational_chain(
db_path="chroma_db",
collection_name="iceberg_products",
k=2
)
@app.post("/rag/conversation")
async def rag_conversation(request: QueryRequest, _: str = Depends(verify_api_key)):
"""
대화형 RAG API.
이전 질문과 답변을 기억한 상태로 새로운 질문을 처리합니다.
"""
# ✅ 사용자 질문 추출
question = request.question
# ✅ QA 체인 실행 (메모리 포함)
result = qa_chain(question)
# ✅ GPT 응답 및 참조 문서 반환
return {
"question": question,
"answer": result["result"],
"sources": [doc.page_content for doc in result["source_documents"]]
}
if __name__ == "__main__":
uvicorn.run("src.rag_server_conversational:app", host="0.0.0.0", port=8000, reload=True)
🧪 테스트 예시 (httpie 사용)
http POST http://localhost:8000/rag/conversation \
Authorization:"my-secret-key" \
question="products 테이블의 상품 목록 알려줘"
http POST http://localhost:8000/rag/conversation \
Authorization:"my-secret-key" \
question="그 중에서 가격이 높은 상품은?"
✅ GPT는 이전 질문에서 나온 내용과 연결하여 응답 생성
📎 요약 및 핵심 정리
- LangChain의 ConversationBufferMemory를 활용하여
질문-응답 흐름을 메모리에 유지하고, 연속적인 문맥 처리가 가능하게 만들었습니다. - FastAPI API를 통해 RAG 시스템을 대화형 인터페이스로 확장할 수 있습니다.
- 이 구조는 SlackBot, 웹챗, 어시스턴트 등 다양한 UI와도 연동 가능합니다.
728x90
'LLM & Generative AI > RAG in Practice' 카테고리의 다른 글
📚 LangChain 기반 RAG 구축 시리즈 총정리 (1) | 2025.04.05 |
---|---|
[LangChain RAG 구축 시리즈 Ep.30] 📦 전체 시스템 구조 정리 및 운영 환경 배포 전략 (1) | 2025.04.05 |
[LangChain RAG 구축 시리즈 Ep.27] 🔄 GPT를 활용한 질문 → 테이블 자동 매핑 고도화 전략 (1) | 2025.04.05 |
[LangChain RAG 구축 시리즈 Ep.26] 🧩 멀티 테이블 구조에 맞춘 자동 컬렉션 선택 및 태깅 전략 (1) | 2025.04.05 |
[LangChain RAG 구축 시리즈 Ep.25] 🛡️ 사용자 인증이 포함된 RAG API 구성 전략 (1) | 2025.04.05 |