이 튜토리얼에서는 Stateless 챗봇 서버에 LangGraph를 활용한 상태 기반 메모리 지원을 추가하여 업그레이드합니다. 이를 통해 모델이 이전 메시지를 기억하며 보다 사람다운 다중 턴 대화가 가능합니다.
이 업그레이드의 주요 특징
- LangChain 통합을 통한 Gemini 2.5 Pro 기반 구동
- 세션 메모리 유지를 위한 LangGraph의 MemorySaver 사용
- Flask로 구현되었으며 CORS 지원 포함
thread_id
를 사용하여 사용자별 대화 히스토리 유지
Stateless 버전과의 차이점
Stateless 버전과의 주요 차이점은 다음과 같습니다:
- 상태 관리:
messages
를 통해 대화 히스토리를 추적하기 위해TypedDict
기반의State
클래스를 도입 - LangGraph 통합:
StateGraph
를 사용한 상태 기반 워크플로우 정의 및MemorySaver
를 통한 메모리 유지 - 세션 메모리: LangGraph의
configurable
입력을 통해 고유한thread_id
(예:user_124
)로 챗 세션 연결
상태 기반 챗봇 전체 코드
import os
from dotenv import load_dotenv
from flask import Flask, request, jsonify
from flask_cors import CORS
# Typing 및 LangChain / LangGraph 관련 import
from typing import Sequence
from typing_extensions import Annotated, TypedDict
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, BaseMessage
from langgraph.graph.message import add_messages
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph, START, END
# .env 환경 변수 로드
load_dotenv(".env")
api_key = os.getenv("GOOGLE_API_KEY")
# Flask 서버 초기화
app = Flask(__name__)
CORS(app)
# Gemini 2.5 Pro LLM 설정
llm_pro = ChatGoogleGenerativeAI(
model='gemini-2.5-pro-exp-03-25',
temperature=0.5
)
# 시스템 역할 + 메모리 플레이스홀더를 포함한 프롬프트
prompt = ChatPromptTemplate.from_messages([
('system', '당신은 딥러닝 전문가입니다.'),
MessagesPlaceholder(variable_name="messages"),
])
# 메모리 지원 상태 스키마 정의
class State(TypedDict):
messages: Annotated[Sequence[BaseMessage], add_messages]
# 체인: prompt → model
runnable = prompt | llm_pro
# 그래프 노드 함수: 새로운 메시지 생성
def generator(state: State):
response = runnable.invoke(state)
return {"messages": [response]} # 상태 내 메시지 업데이트
# LangGraph 워크플로우 생성
workflow = StateGraph(state_schema=State)
workflow.add_edge(START, "model")
workflow.add_node("model", generator)
# 대화 저장을 위한 MemorySaver 사용
memory = MemorySaver()
chat_app = workflow.compile(checkpointer=memory)
# 고유한 thread_id를 통한 사용자 세션 정의
config = {"configurable": {"thread_id": "user_124"}}
# API 엔드포인트
@app.route("/chat", methods=["POST"])
def chat():
data = request.get_json()
user_query = data.get('user_query')
if not user_query:
return jsonify({'response': "질문을 입력해주세요."})
# LangGraph에 메시지 및 사용자 구성 전달
output = chat_app.invoke(
input={"messages": [HumanMessage(user_query)]},
config=config
)
# 모델 응답 추출
response = output["messages"][-1].content
return jsonify({'response': response})
if __name__ == '__main__':
app.run(debug=True, port=8000)
무엇이 상태 기반(Stateful)인가요?
Stateless 챗봇에서는 사용자 질문마다 독립적으로 처리되어 메모리를 유지하지 않습니다. 이 버전은 다음과 같은 방식으로 그 문제를 해결합니다:
State
스키마 내에서messages
히스토리를 유지MemorySaver
를 사용하여 대화 상태를 저장 및 복원configurable.thread_id
를 통해 스레드 기반 메모리 유지
결론
이 업그레이드된 챗봇 서버는 이제 Gemini 2.5 Pro와 LangGraph를 활용하여 상태 기반 대화를 지원합니다. 이는 실제 서비스 환경에서 똑똑하고 문맥을 기억하는 어시스턴트를 만들기에 최적입니다.
직접 구현해보고 싶으신가요? thread_id
를 사용자 세션이나 쿠키를 기반으로 동적으로 바꿔보세요!
'AI' 카테고리의 다른 글
LangChain, FAISS, Gemini 임베딩을 활용한 벡터 DB 저장 및 검색 방법 (1) | 2025.05.08 |
---|---|
벡터 데이터베이스(Vector DB)란? FAISS 예제와 함께 깊이 있게 살펴보기 (0) | 2025.05.08 |
대화상태 유지 챗봇 구현: Gemini와 LangGraph 활용 (2) | 2025.05.08 |
Google Gemini 2.5 Pro와 LangChain으로 간단한 LLM 챗봇 서버 만들기 (1) | 2025.05.08 |
쉽게 배우는 Google Gemini API 프로그램 (0) | 2025.05.08 |