上下文是什么
LLM 无状态:每次请求携带的 messages 列表就是「可见记忆」。Agent 多轮工具调用会在单轮请求内堆积 system、历史、tool 输出,很快触及 Token 上限 与成本上限。上下文管理的目标是:在有限 Token 内保留对当前任务最有用的信息。
分层设计
| 层级 | 内容 | 生命周期 | |---|---|---| | System | 人设、工具 schema、约束 | 会话级,少改 | | 短期对话 | 最近 user/assistant/tool | 滑动窗口 | | 工作记忆 | 当前任务计划、变量 | 任务结束可清 | | 长期记忆 | 用户偏好、知识库 | 向量检索按需注入 |
不要把所有文档塞进 system;按需检索再插入 user 或 tool 结果,减少噪声。
截断与摘要策略
滑动窗口:保留最近 K 轮,简单但丢早期约束。适合客服短会话。
摘要压缩:窗口将满时,用模型把旧对话压成「事实摘要」一条 system 或 user 消息,再拼接近期原文。注意摘要可能丢细节,关键数字应结构化存储。
结构化状态:用 JSON 维护 plan、completed_steps、entities,每轮只传状态 + 最近一两轮自然语言,比全文历史省 Token。
messages = [
{"role": "system", "content": "你是数据分析助手,可用 run_sql 工具。"},
{"role": "user", "content": "分析上周 DAU"},
]
工具往返后 append assistant.tool_calls 与 tool 结果
messages.append({"role": "assistant", "tool_calls": [...]})
messages.append({"role": "tool", "tool_call_id": "call_1", "content": '{"rows": 1200}'})
Token 预算实践
面试与落地检查
- 是否区分「展示给用户」与「喂给模型」?
- 重试同一轮时是否重复累计 tool 输出?
- 是否有会话 ID 关联外部记忆?