多轮会话与状态管理

真实产品里用户会连续说很多句,智能体必须记住前面说过什么、现在进行到哪一步。多轮会话的核心是状态管理:如何组织历史消息、如何裁剪、如何表达"当前处于什么阶段"。本章为实战章节的状态设计打基础。

消息历史组装

对话状态的最基本载体是消息列表。每轮把用户输入追加进历史,连同系统提示一起发给模型:

messages = [{"role": "system", "content": "你是订票助手"}]
messages.append({"role": "user", "content": "帮我订明天去上海的高铁"})
resp = client.chat.completions.create(model="deepseek-chat", messages=messages)
messages.append(resp.choices[0].message)   # 助手回答也入历史
# 输出:下一轮继续携带完整 messages 即可"记得"上文

上下文窗口裁剪策略

历史无限增长会超出窗口、抬高成本,常见裁剪手段:

策略做法适用
截断最旧只保留最近 N 轮简单闲聊
摘要压缩旧消息压缩成摘要置顶长会话
关键信息抽取只存用户意图、槽位值任务型对话
分页/外置历史存库,按需取回超长会话
# 只保留最近 10 轮
messages = messages[:1] + messages[-20:]   # 系统提示 + 最近 20 条

状态机:该不该用

简单问答不需要状态机,消息历史就是全部状态。但任务型流程(订票:收集出发地 → 目的地 → 日期 → 确认支付)建议引入显式状态机,让代码清晰可控:

# 状态流转示例:IDLE -> ASK_CITY -> ASK_DATE -> CONFIRM -> DONE
# 非法状态(如在 CONFIRM 直接问出发地)应被拦截或引导回退

会话 ID 与服务端状态

多轮状态必须存服务端而不是前端内存:客户端每次请求带 session_id,服务端据此取出该会话的历史与状态,支持多端续聊、断线恢复:

{"session_id": "sess_8f2a1c", "state": "ASK_DATE",
 "history": ["...最近 10 轮..."], "slot": {"from": "北京", "to": "上海"}}

长任务与恢复 Checkpoint

耗时的多步任务(批量处理、长文档生成)若中途失败,全部重来代价高昂。可引入 checkpoint:每完成一步就把进度与中间结果落库,恢复时从断点继续:

{"task_id": "t_99", "done": ["step1", "step2"], "todo": ["step3"],
 "partial": {"report": "已汇总 80% 数据"}}

恢复时读取 checkpoint,把"已完成摘要 + 剩余步骤"重新组装进上下文即可继续执行。

小结

多轮会话 = 状态管理:消息历史组装保证连续性,裁剪策略控成本,状态机管任务流程,session_id 支撑服务端状态,checkpoint 支撑长任务断点续跑。这些正是后面实战章节要落地的核心设计。

笔记加载中…