
本文详解如何在前后端分离的 react + fastapi 架构中,利用 langchain 的 `conversationbufferwindowmemory` 实现上下文感知的多轮对话,支持自动保留最近 5 轮问答并注入 llm 提示词,无需前端维护完整历史。
要在 React 聊天机器人中实现真正的多轮对话(例如理解“它比上一个贵吗?”中的“它”和“上一个”),关键不在于前端存储所有消息——而在于后端智能地管理对话上下文,并将其结构化注入 LLM 调用。LangChain 提供了轻量、可控的内存机制,完美适配你的 FastAPI + GPT-3.5 流程。
✅ 后端:用 ConversationBufferWindowMemory 管理上下文
ConversationBufferWindowMemory 会自动缓存最近 k 轮(如 k=5)的 human(用户提问)与 ai(模型回复)交互对,并在每次调用 conversation.predict(input=...) 时,将这些历史拼接进提示词(prompt)的 history 部分。你无需手动序列化/反序列化消息数组——LangChain 已为你封装好。
以下是 FastAPI 中的典型集成示例:
# backend/main.py
from fastapi import FastAPI, HTTPException
from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferWindowMemory
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI
app = FastAPI()
# 初始化 LLM(请配置 OPENAI_API_KEY)
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.2)
# 定义带 history 占位符的 prompt(关键!)
PROMPT = PromptTemplate(
input_variables=["history", "input"],
template="""你是一个专业客服助手。请基于以下对话历史和最新问题,给出准确、简洁的回答。
对话历史:
{history}
最新问题:
{input}
回答:"""
)
# 全局共享 memory 实例(⚠️注意:生产环境应按 session_id 隔离!见下方说明)
memory = ConversationBufferWindowMemory(k=5, return_messages=True)
conversation_chain = ConversationChain(
llm=llm,
prompt=PROMPT,
memory=memory,
verbose=True # 开发期建议开启,查看实际注入的 history
)
@app.post("/chat")
async def chat_endpoint(query: str):
try:
# 此处可插入你的 query 重写逻辑(如用 GPT 格式化为内部 API 查询语句)
# …… your query rewriting logic ……
# 调用 LangChain 对话链(自动注入最近 5 轮 history)
response = conversation_chain.invoke({"input": query})
return {"reply": response["response"]}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))⚠️ 重要注意事项(避免踩坑)
不要全局复用 memory 实例:上述示例中 memory 是全局单例,仅适用于单用户开发测试。生产环境必须按用户会话隔离——推荐在 FastAPI 请求中通过 session_id(由前端传入,如 JWT 或 cookie)动态创建或检索 memory 实例,例如使用 ConversationTokenBufferMemory + Redis 缓存,或简单用字典 {session_id: memory} 管理(需加锁/考虑并发)。
前端只需传递 session_id 和当前 query:React 端完全无需保存历史消息用于上下文构建。你只需在每次请求中带上唯一 session_id(如 localStorage.getItem('sessionId') || uuidv4()),后端据此加载对应对话窗口。这极大简化了前端逻辑:
// frontend/App.tsx
const sendMessage = async (text: string) => {
const sessionId = localStorage.getItem('sessionId') || generateId();
localStorage.setItem('sessionId', sessionId);
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: text, session_id: sessionId })
});
const data = await res.json();
// 更新 UI...
};- return_messages=True 推荐启用:它使 memory.chat_memory.messages 返回 BaseMessage 对象列表(而非字符串),便于后续调试或扩展(如添加工具调用日志)。
✅ 总结:端到端协作逻辑
- 用户在 React 发送消息 → 带 session_id;
- FastAPI 接收后,根据 session_id 获取/初始化 ConversationBufferWindowMemory(k=5);
- LangChain 自动将该 session 最近 5 轮 HumanMessage/AIMessage 注入 prompt 的 {history};
- GPT-3.5 结合历史生成回答,并自动将本次 (query, reply) 存入 memory;
- 下次同一 session_id 请求时,窗口自动滑动,旧记录被剔除,新记录加入。
这样,你既获得了自然语言层面的上下文连贯性,又保持了前后端职责清晰——前端专注 UI 与状态管理,后端专注语义理解与状态持久化。








