当上下文窗口填满时,系统会摘要早期消息。“订单 #ORD-2024-0312 的 $127.50 退款,48 小时截止”变成了”客户请求退款,希望尽快处理。“代理现在缺了金额、订单号和截止日期。它处理了 $50,忽略了订单号,并承诺”一周内解决。”
这不是模型错误。这是摘要在做摘要该做的事:把具体细节压缩成笼统描述。
摘要丢了什么
100 次需要摘要的客服对话中的事实保留率:
| 信息类型 | 保留率 |
|---|---|
| 情绪/意图(“客户很沮丧”) | 94% |
| 分类事实(“产品:电子产品”) | 87% |
| 具体数值(“$127.50”) | 31% |
| 精确日期和 ID(“订单 #ORD-2024-0312”) | 23% |
情绪能保留下来,因为概括不损失含义——“沮丧的客户”不管是否被摘要都是准确的。数字、日期和 ID 会被摧毁,因为摘要把它们替换成了类别:“$127.50”变成”退款金额”,“3月15日”变成”即将到来的截止日期”。
代理正确执行操作最需要的值——金额、日期、ID——恰恰是最容易丢失的。
修复方案:结构化 Case Facts
把关键值提取到一个结构化的 case_facts 对象中,与摘要后的叙述并存。叙述会被压缩;事实不会。
{
"case_facts": {
"refund_amount": 127.50,
"order_id": "ORD-2024-0312",
"resolution_deadline": "2026-03-31",
"customer_tier": "premium"
},
"summary": "高级客户因产品缺陷请求退款。对初始响应时间表示不满。"
}
摘要处理对话流。case_facts 处理精度。两者都能在摘要中存活,因为事实在叙述被压缩之前就已经提取出来了。
数据
500 个案例对比:
| 方法 | 摘要后的错误值比例 |
|---|---|
| 标准摘要 | 27% |
| 结构化 case facts + 摘要 | 3% |
减少 89%。同样的对话,同样的模型,同样的摘要触发时机。唯一的区别:在每次摘要前把金额、日期和 ID 提取到结构化对象中。
为什么更好的摘要 Prompt 不管用
“摘要时保留所有关键细节”本身就是一条模糊指令。模型仍然可能把”第 42 行的 NullPointerException”概括成”auth 模块中的空指针错误”。摘要的 prompt 指令面临和其他模糊指令一样的解读歧义。
结构化提取是确定性的:识别哪些数据类型必须存活(金额、日期、ID、版本号),在摘要发生之前提取到命名字段中。提取是显式的,不依赖于摘要质量。
第一步
在实现任何保持策略之前:识别哪些数据类型必须在摘要中存活。不是所有东西都需要提取——情绪和分类自然就能存活。数字、日期、ID 和配置值需要显式持久化。
识别完之后,在每个摘要周期前提取到持久存储中(scratchpad、case_facts 对象、deployment_state)。
双约束设计
长会话同时需要叙述上下文(用于自然的交互流)和精确参数(用于正确的操作)。把它们分开:
- 叙述 → 可摘要。自然压缩。提供对话流。
- 参数 → 持久化。版本号、配置值、时间戳、回滚点。永不概括。
摘要处理叙述。结构化存储处理参数。两个约束同时满足。
一句话总结: 在摘要前把具体值(金额、日期、ID)提取到结构化 case_facts 中——叙述压缩没问题,但存活率只有 23-31% 的精确值需要显式持久化,否则就是 27% 的错误率。