LLM & Generative AI/RAG in Practice

[LangChain RAG 구축 시리즈 Ep.23] 🔧 FastAPI 기반 RAG 서버 구성하기 (엔드포인트 설계)

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

 

이제까지 우리는 LangChain을 사용해 문서를 임베딩하고,
ChromaDB에 저장하며,
Retriever → QA Chain → Conversational QA Chain으로 이어지는
전체 RAG 시스템의 기본 구조를 구현해왔습니다.

이번 글에서는 이 구조를 FastAPI 웹 서버 형태로 감싸서
📡 외부에서 HTTP 요청을 통해 RAG 시스템을 호출할 수 있도록 구성합니다.

  • 사용자는 /rag/query로 질문을 보내면
  • 서버는 문서를 검색하고 GPT가 응답을 생성하여
  • 응답과 함께 참조 문서까지 반환합니다

🎯 목표

  • LangChain QA 체인을 FastAPI로 래핑
  • /rag/query POST API 구현
  • 질문, 응답, 참조 문서를 포함한 JSON 응답 반환

🗂️ 디렉토리 구조 예시

rag-iceberg-project/
├── src/
│   ├── rag_server.py                 ← 이번 글에서 작성할 FastAPI 서버
│   └── conversational_chain.py      ← ConversationalRetrievalChain 생성 모듈
├── chroma_db/                        ← 벡터 DB
└── docs/                             ← 문서 저장 디렉토리

⚙️ 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):
    """
    GPT 모델 + 벡터 검색기 + 대화 히스토리를 포함한 체인을 생성합니다.
    이 체인은 FastAPI에서 요청마다 호출되어 대화 흐름을 유지할 수 있습니다.
    """

    # ✅ 문서 임베딩 모델 설정
    embedding = OpenAIEmbeddings()

    # ✅ ChromaDB 벡터 저장소 로딩
    vectordb = Chroma(
        persist_directory=db_path,
        embedding_function=embedding,
        collection_name=collection_name
    )

    # ✅ GPT 모델 (gpt-3.5-turbo 사용)
    llm = ChatOpenAI(
        model_name="gpt-3.5-turbo",
        temperature=0.2
    )

    # ✅ 대화 히스토리 저장용 메모리 객체
    memory = ConversationBufferMemory(
        memory_key="chat_history",
        return_messages=True
    )

    # ✅ 대화형 QA 체인 구성
    chain = ConversationalRetrievalChain.from_llm(
        llm=llm,
        retriever=vectordb.as_retriever(search_kwargs={"k": k}),
        memory=memory,
        return_source_documents=True
    )

    return chain

🚀 Step 2. FastAPI 서버 구현

# src/rag_server.py

from fastapi import FastAPI, Request                      # FastAPI 웹 서버 구성 요소
from pydantic import BaseModel                            # 요청 body를 구조화하기 위한 데이터 모델
from src.conversational_chain import create_conversational_chain  # QA 체인 불러오기
import uvicorn                                            # 로컬 테스트용 웹 서버 실행기

# ✅ FastAPI 애플리케이션 객체 생성
app = FastAPI()

# ✅ 질문 요청을 위한 Pydantic 모델 정의
class QueryRequest(BaseModel):
    question: str

# ✅ RAG QA 체인 초기화 (앱 시작 시 1회 실행)
qa_chain = create_conversational_chain(
    db_path="chroma_db",               # 벡터 DB 경로
    collection_name="iceberg_tables",  # 컬렉션 이름
    k=2                                # top-k 검색
)

# ✅ 질문을 처리할 POST API 엔드포인트 정의
@app.post("/rag/query")
async def rag_query(request: QueryRequest):
    """
    사용자의 질문을 받아 LangChain QA 체인에 전달하고,
    응답과 참조 문서를 반환하는 API 엔드포인트입니다.
    """

    question = request.question                         # 요청에서 질문 추출
    result = qa_chain(question)                         # 체인을 통해 응답 생성

    # GPT의 응답 텍스트
    answer = result["result"]

    # 참조 문서들 (각 문서의 page_content만 추출)
    sources = [doc.page_content for doc in result["source_documents"]]

    # ✅ 응답 JSON 구성
    return {
        "question": question,     # 입력 질문
        "answer": answer,         # GPT 응답
        "sources": sources        # 참조된 문서 리스트
    }

# ✅ 로컬 실행용 엔트리포인트
if __name__ == "__main__":
    uvicorn.run("src.rag_server:app", host="0.0.0.0", port=8000, reload=True)

▶️ 실행 테스트

# 서버 실행
python src/rag_server.py

▶️ POST 요청 예시 (httpie 또는 curl 사용)

http POST http://localhost:8000/rag/query question="상품 테이블의 컬럼은 뭐야?"

✅ 응답 예시:

{
  "question": "상품 테이블의 컬럼은 뭐야?",
  "answer": "상품 테이블에는 product_id, product_name, category 컬럼이 있습니다.",
  "sources": [
    "📂 테이블명: products\n🧾 컬럼 목록:\n- product_id (long)\n- product_name (string)\n- category (string)"
  ]
}

📎 요약 및 핵심 정리

  • LangChain QA 체인을 FastAPI 서버로 감싸서 웹 API 형태로 서비스할 수 있게 구성했습니다.
  • /rag/query POST API를 통해 질문을 전달하면, GPT 응답과 참조 문서를 JSON으로 반환합니다.
  • 내부적으로는 Chroma 검색기 + GPT + 대화형 메모리가 연결된 구조입니다.
  • 이후 이 API를 기반으로 웹 UI, 슬랙봇, RAG 클라이언트 등 다양한 연동이 가능합니다.

 

728x90