对话压缩

长对话不会天然变成好上下文。

用户连续聊了几十轮以后,里面会混合目标、试错、纠正、闲聊、工具结果、过期假设和已经废弃的方案。如果系统只是把历史消息尽量往 prompt 里塞,模型可能既慢又贵,还会把旧信息当成当前事实。

对话压缩的目标不是“尽量缩短”,而是保留当前任务需要的最小充分信息。压缩策略要回答三个问题:

  • 哪些最近消息必须原样保留?
  • 哪些历史信息可以摘要成自然语言?
  • 哪些信息应该抽成结构化字段,交给程序管理?

场景

以一个 B2B SaaS 客服工单助手为例。

用户先说“我的发票开错了”,随后补充公司抬头、税号、订单号,又说“不是上个月那笔,是 4 月 18 日支付的那笔”。客服助手需要生成处理草稿,并可能调用订单、发票和客户资料工具。

这里的输入来自多轮聊天、订单系统、发票系统和客服知识库。输出会被客服查看、编辑,并可能触发重新开票流程。使用频率高,并发也可能很高。没有 AI 时,客服会人工翻聊天记录、复制订单号、查系统、整理回复。

最常见样本是用户按顺序补充信息。最容易失败的样本是用户中途纠正自己、给出多个订单号、把上一次咨询和这一次咨询混在一起,或者工具查询失败后又继续追问。

同样的压缩问题也会出现在代码助手、学习助手和销售跟进助手里:

  • 代码助手要保留最新报错、用户最终选择的方案和修改范围,丢弃已经否定的实现思路。
  • 学习助手要保留学生当前卡点和已掌握内容,不能把一次答错永久写成能力判断。
  • 销售助手要保留客户本轮明确需求,不能把寒暄和模型推测写成采购意向。

问题类型

对话压缩不是单一摘要任务,通常包含多类问题。

问题类型适合模型处理应由程序处理需要人工确认
判断相关性判断哪些历史轮次与当前问题有关token 预算、时间窗口、角色过滤高风险信息是否可丢弃
摘要压缩目标、约束、已确认事实和待办摘要版本、来源轮次、更新时间对外承诺、金额、身份信息
结构化抽取抽取订单号、时间、偏好、决策、任务状态schema 校验、冲突检测、存储长期保存或触发操作的字段
冲突识别发现用户前后说法不一致工具事实优先级、状态覆盖规则无法自动判定的冲突
生成根据压缩后的上下文回复上下文拼装、预算控制退款、开票、权限变更等动作

模型擅长把一段历史转成可读摘要,也能辅助抽取字段。但程序必须控制保留策略、schema、权限和版本。否则压缩结果本身会变成新的不可靠上下文。

收益和成本判断

对话压缩的收益主要有四类:

  • 降低 token 成本和响应延迟。
  • 减少无关历史对模型的干扰。
  • 支持长对话继续进行。
  • 为审计和恢复提供更清晰的上下文状态。

成本也很实际:

  • 摘要可能遗漏关键约束。
  • 摘要可能把模型推测写成事实。
  • 结构化抽取需要设计 schema、校验和迁移。
  • 压缩链路本身会增加模型调用和错误点。
  • 调试时需要同时查看原始消息、摘要和抽取结果。

压缩策略的核心判断是:当前错误成本是否值得引入额外链路。

场景条件简单策略足够需要工程方案
对话长度3 到 8 轮,目标清晰频繁超过窗口或跨天继续
输出风险草稿、润色、用户可编辑触发流程、影响权益、进入系统
信息结构主要是自然语言目标有订单号、金额、状态、决策
冲突频率很少纠正和改口经常出现更正、多个对象、工具失败
复盘要求不需要审计需要解释为什么这样处理

方案阶梯

第一层:只保留最近消息

只保留最近消息是最简单的压缩策略。它适合短会话和低风险任务。

例如写作助手里,用户让模型“把上一版再短一点”,最近几轮通常已经包含足够信息。保留完整历史不仅成本高,还可能把早期草稿风格带回来。

推荐做法:

  • 固定保留最近 N 轮用户和助手消息。
  • 永远保留系统提示词和当前页面的关键上下文。
  • 工具结果只保留最近且仍有效的结果。
  • 超出窗口时直接截断,不生成额外摘要。

收益是便宜、稳定、容易调试。成本是丢失长期目标和早期约束。

只保留最近消息通常足够的场景:

  • 单次写作、润色、翻译。
  • 简单问答和短客服咨询。
  • 用户每轮都会重新说明关键对象。
  • 错了可以重新生成,不进入下游流程。

第二层:滑动窗口和优先级截断

当对话稍长,但还不值得做摘要时,可以用优先级截断。

优先级通常是:

  1. 系统规则和安全边界。
  2. 当前用户消息。
  3. 最近工具结果和明确业务对象。
  4. 最近几轮对话。
  5. 用户明确确认的约束。
  6. 更早的闲聊、试错和废弃方案。

这个策略仍然不要求模型做额外压缩,主要由程序按规则控制。它适合中等长度会话,尤其是用户会在当前页面持续操作的产品。

第三层:滚动摘要

当会话明显变长,而且早期信息仍然有价值时,需要摘要。

好的对话摘要不应该是一段泛泛的“用户讨论了发票问题”。它应该保留:

  • 当前目标。
  • 已确认事实。
  • 用户明确约束。
  • 已否定的信息。
  • 已执行工具和结果。
  • 未解决问题。
  • 下一步待办。

示例摘要结构:

目标:用户希望重新开具 2026-04-18 付款订单的增值税专用发票。
已确认事实:订单号为 A123;公司抬头为 XX 科技有限公司;用户否定了“上个月订单”。
工具结果:订单 A123 已支付,发票状态为已开具,允许申请红冲重开。
待确认:税号和收件邮箱尚未确认。
禁止使用:早期提到的订单 B456 已被用户排除。

摘要适合人读,也适合模型继续对话。但摘要仍然是自然语言,不能直接当作业务数据写入系统。

摘要的风险在于失真。特别要避免:

  • 把“用户可能想要退款”写成“用户要求退款”。
  • 丢掉用户否定过的信息。
  • 省略工具失败或数据更新时间。
  • 把多个对象合并成一个对象。

第四层:结构化抽取

当对话里的信息要被程序消费,就应该做结构化抽取。

例如客服开票流程,系统需要稳定字段:

{
  "intent": "invoice_reissue",
  "orderId": "A123",
  "invoiceType": "vat_special",
  "companyName": "XX 科技有限公司",
  "taxId": null,
  "excludedOrderIds": ["B456"],
  "missingFields": ["taxId", "email"],
  "requiresHumanReview": false
}

结构化抽取适合:

  • 工单分类。
  • 表单填充。
  • 工具参数生成。
  • 多步骤流程状态。
  • 冲突和缺失字段提示。
  • 后续检索和审计。

它的收益是稳定、可校验、可回放。成本是 schema 设计、字段迁移、解析失败处理和人工修正 UI。

结构化抽取不应该只依赖 JSON parse。系统还要校验:

  • 字段是否来自用户、工具还是模型推断。
  • 枚举是否合法。
  • 业务对象是否属于当前用户。
  • 金额、时间、订单状态是否和工具结果一致。
  • 低置信度字段是否需要追问。

第五层:摘要 + 抽取 + 检索

复杂产品往往需要混合策略。

长对话本身可以用滚动摘要保留整体脉络;业务字段用结构化抽取进入任务状态;历史会话、知识库和项目记录通过检索按需进入当前上下文。

这类方案适合高频客服、代码修改、销售跟进、学习辅导和工作流自动化。它的工程收益很高,但也要求可观测性跟上。

什么时候简单策略足够

简单策略足够的判断标准不是“会话还没超过模型窗口”,而是“丢掉早期信息不会造成明显业务错误”。

以下情况可以只用最近消息或滑动窗口:

  • 用户每次都会明确当前目标。
  • 历史只是表达风格或草稿变化。
  • 没有跨轮业务字段要入库。
  • 没有工具执行状态要恢复。
  • 输出不会直接触发外部动作。
  • 用户能轻松发现并纠正遗漏。

例如内部文案助手、会议纪要润色、短问答助手,通常不需要滚动摘要和结构化抽取。

什么时候需要工程方案

以下情况应该升级到摘要、结构化抽取或混合策略:

  • 对话经常超过上下文窗口。
  • 用户会中途纠正关键事实。
  • 同一会话里有多个业务对象。
  • 需要跨天继续处理同一任务。
  • 需要调用工具或写入业务系统。
  • 需要复盘每个结论来自哪轮消息。
  • 错误会造成对外承诺、权益变更或操作事故。

尤其是“输出要进入系统”这一条,一旦出现,就不应该再把自然语言摘要当作唯一状态。

方案选型表

场景条件推荐方案不推荐方案判断理由额外成本
短对话、低风险、可重新生成最近消息滚动摘要和记忆早期信息价值低,简单可控几乎没有
对话中等长度,当前轮最重要滑动窗口 + 优先级截断全量历史控制成本并保留最近指代截断规则维护
长对话但输出给人看滚动摘要只保留最近消息需要保留目标和约束摘要调用、失真评估
对话中有业务字段结构化抽取 + 校验自然语言摘要入库下游需要稳定字段schema 和修正 UI
多对象、多工具、多天继续摘要 + 结构化状态靠模型阅读全部历史需要恢复和审计状态机、trace、测试
大量历史会话可参考检索式历史上下文固定塞历史摘要相关性随问题变化索引、权限、检索评估

反模式

第一种反模式:超过窗口才想压缩。

压缩不是应急截断,而是上下文设计。等到 prompt 放不下时再删消息,通常会删掉关键事实。

第二种反模式:摘要只写结论,不保留否定信息。

用户说“不是 B456,是 A123”,摘要如果只写“订单 A123”,后续模型可能再次被早期 B456 干扰。被否定的信息在很多业务场景里同样重要。

第三种反模式:把摘要当事实源。

摘要是模型生成的二手信息。涉及金额、身份、订单、权限、状态时,必须回查工具或结构化状态。

第四种反模式:结构化抽取没有来源。

字段值应该知道来自哪轮消息、哪个工具结果或哪次人工编辑。没有来源,后续冲突无法处理。

第五种反模式:每轮都重写完整摘要。

频繁重写会增加成本,也会让摘要漂移。更稳妥的方式是滚动更新,并保留摘要版本和触发原因。

第六种反模式:用压缩掩盖产品流程问题。

如果用户必须在长对话里反复补字段,可能需要表单、步骤条或工具查询,而不是更复杂的摘要。

工程清单

  • 场景边界:压缩服务于当前会话、跨会话继续,还是下游业务流程。
  • 保留策略:哪些消息永远保留,哪些按时间保留,哪些按相关性保留。
  • 摘要结构:是否区分目标、事实、约束、否定信息、工具结果、待办和不确定点。
  • 抽取 schema:字段、枚举、nullable、置信度、来源和更新时间是否定义清楚。
  • 冲突处理:新消息、旧摘要、结构化状态和工具结果冲突时如何处理。
  • 校验重试:摘要或抽取失败时是否重试、降级或请求用户确认。
  • 权限过滤:压缩前后是否都避免混入越权信息。
  • 可观测性:是否记录原始消息范围、摘要版本、抽取字段和本轮上下文包。
  • 评估样本:是否覆盖纠正、多个对象、工具失败、长对话和缺字段样本。
  • 成本延迟:是否有 token 预算、摘要触发阈值、缓存和超时策略。
  • 人工修正:客服或运营是否能改摘要、字段和任务状态。
  • 回放能力:线上错误是否能重放当时的上下文包。

小结

对话压缩的关键不是把历史变短,而是把历史变成当前任务可用的上下文。

短会话可以只保留最近消息;中等长度会话可以用滑动窗口;长对话需要滚动摘要;涉及业务字段和下游系统时,需要结构化抽取;跨天、多对象、多工具的任务,则要把摘要、结构化状态和检索结合起来。

判断升级的标准很朴素:如果丢掉早期信息只是影响表达,简单策略足够;如果丢掉或误压缩信息会影响事实、权益、操作和审计,就需要工程方案。