跳到主要内容

大模型上下文如何科学管理:不要把聊天记录当数据库

· 阅读需 7 分钟
一介布衣
全栈开发者

很多人刚开始做大模型应用时,会把上下文理解成“聊天记录”。用户说过的话越多,全部拼接给模型,似乎模型就越了解用户。

但实际情况往往相反。历史消息越长,越容易混入过期信息、无关闲聊和互相冲突的指令。模型还可能因为上下文太长而超出限制,或者忽略真正重要的内容。

科学的上下文管理不是尽可能多地塞内容,而是:

每次只给模型完成当前任务所必需、可靠、最新的信息。

把上下文想成模型的工作台

可以把模型想象成一个临时办公的助手。它每次接到任务时,面前只有一张有限大小的工作台。

工作台上可以放任务说明、相关文件、当前状态和工具结果,但空间不是无限的。如果把过去几年所有聊天记录、全部业务文档和每一次工具返回结果都堆上去,助手不一定更聪明,反而可能找不到刚刚要处理的那张订单。

上下文窗口就是这张工作台的容量。一次请求中可能放入:

系统规则
+ 用户问题
+ 历史对话
+ 检索到的资料
+ 工具定义和工具结果
+ 本次模型输出

这些内容加起来不能超过模型的上下文窗口。而且,即使没有超过长度限制,内容太多也会降低模型找到重点的概率。

第一步:先给信息分类

不同信息应该由不同的系统负责保存,不要把所有东西都混在聊天记录里。

信息类型适合放在哪里例子
固定规则System Prompt 或配置输出格式、安全规则、工具白名单
当前任务状态数据库或状态表当前步骤、订单号、任务进度
业务知识知识库和检索系统产品说明、制度、帮助文档
用户偏好长期记忆常用语言、展示习惯
最近对话短期上下文当前几轮问题和回答
工具结果任务状态或结构化记录查询结果、错误码、审批状态

例如用户说:“继续处理刚才那个订单。”这句话本身是不完整的。系统不能只依赖聊天记录猜测“刚才那个”是什么,而应该从任务状态中取出已经确认的订单号和当前步骤。

第二步:给信息设置优先级

上下文空间不够时,不能随机截断内容,而应该按优先级处理。

一个常见的优先级顺序是:

  1. 当前用户的最新指令;
  2. 安全、权限和业务硬规则;
  3. 当前任务状态和已确认事实;
  4. 与当前问题相关的检索结果;
  5. 最近几轮对话;
  6. 更早的历史闲聊。

例如,用户刚刚明确说“只查询,不要退款”,这条限制应该比几分钟前“帮我处理这个订单”的模糊表达优先。再比如,数据库确认的订单状态应该比模型自己总结的旧状态优先。

上下文超限时,优先压缩或删除低优先级内容,同时保留任务目标、硬性限制和最新事实。

第三步:保留结构化状态,不要只保留聊天记录

聊天记录适合帮助模型理解语气和意图,但不适合作为业务系统唯一的状态来源。

不要只保存这样一句话:

用户:继续处理刚才那个订单。

更可靠的做法是保存结构化任务状态:

{
"task": "查询订单",
"order_id": "12345",
"user_id": "u001",
"step": "等待返回订单明细",
"confirmed_facts": [
"订单存在",
"用户有查看权限"
]
}

结构化状态让程序知道当前任务走到哪一步,也让模型在下一次请求中获得一份清晰、短小、可验证的上下文。

这里要明确模型和系统的分工:

  • 模型负责理解用户表达和提出下一步建议;
  • 状态系统负责保存任务进度和真实事实;
  • 数据库和权限系统负责确认数据存在以及用户能做什么;
  • 上下文构建器负责把当前需要的信息整理给模型。

不要让模型自己成为唯一的状态管理器。

第四步:压缩时保留结论,不要简单截断

对话变长以后,直接删除最早的消息很容易丢掉任务目标。更好的办法是把旧对话压缩成结构化摘要。

例如,订单任务可以压缩成:

已确认:
- 用户要查询订单 12345
- 用户有查看权限

已完成:
- 已确认订单存在

待完成:
- 返回商品明细

限制:
- 不允许执行退款操作

这种摘要比几十轮原始对话更容易被模型使用,因为它保留的是当前任务真正需要的结论、进度和限制。

但摘要也不能直接当作最终事实。订单是否存在、权限是否有效,仍然应该由数据库和权限系统确认。模型摘要是上下文材料,不是事实来源。

第五步:检索只放相关内容

知识库不是上下文的仓库。用户问“如何申请退款”,不应该把整个公司制度库都塞给模型,而应该先检索与退款条件、流程和当前用户角色相关的内容。

一个基本的检索流程是:

理解用户问题
-> 生成检索条件
-> 召回相关文档
-> 按相关性和权限过滤
-> 必要时重新排序
-> 只把相关片段放入上下文

检索结果还要带上来源、更新时间和权限信息。过期文档、无权限文档和与问题无关的文档,都不应该因为“可能有用”而直接传给模型。

还要注意,外部文档和网页中的文字可能包含恶意指令。检索到的内容应该被当作参考资料,而不是可以覆盖系统规则的命令。

一个实用的上下文模板

每次请求都可以按照类似的结构组装上下文:

【任务目标】
用户现在要完成什么事情

【硬性约束】
权限、安全、输出格式和不可执行的动作

【当前状态】
任务 ID、当前步骤、待完成事项

【已确认事实】
经过数据库或业务服务确认的信息

【相关知识】
与当前问题有关的检索片段和来源

【最近交互】
最近几轮仍然有价值的对话

【工具结果】
后续步骤真正需要的字段和错误信息

【输出要求】
希望模型返回的格式和表达方式

这个模板的价值不在于格式固定,而在于把不同来源的信息分开,让模型知道哪些是规则、哪些是状态、哪些只是参考资料。

还要对上下文做监控和测试

上下文管理不是写完 Prompt 就结束了。生产系统至少应该记录:

  • 输入 Token 数和输出 Token 数;
  • 哪些内容被压缩或截断;
  • 检索了哪些文档以及它们的版本;
  • 工具返回了哪些字段;
  • 模型是否引用了过期信息;
  • 上下文变长后,任务成功率和延迟如何变化;
  • 压缩前后,模型的关键判断是否一致。

还要专门测试三种情况:

  1. 很长的连续对话;
  2. 旧信息和新信息发生冲突;
  3. 检索内容中包含恶意指令或与系统规则相反的内容。

这些测试可以帮助我们判断问题到底来自模型能力、上下文拼装、检索质量,还是状态管理错误。

最后的判断

上下文管理的目标不是让模型记住一切,而是让它在当前任务中看到正确的信息。

可以把整个原则浓缩成三句话:

  1. 聊天记录不是数据库;
  2. 模型摘要不是事实来源;
  3. 真实状态、权限和业务数据必须由代码和存储系统管理。

大模型只是在一次请求中使用上下文进行判断。真正可靠的 Agent,需要在模型之外建立状态、检索、权限、压缩和监控机制。只有这样,上下文越长,系统才不会越混乱。