20 轮客服对话,第 8 次调用开始亏钱:LLM 对话记忆的三种策略实测

在这里插入图片描述

1. 先说结论:第 8 轮是分水岭

多轮对话有一个隐藏的成本结构:每多聊一轮,历史就变长一点,而历史在每次调用时都要全额重发。本文用一段 20 轮的香港物业客服投诉线程(粤语、真实感长度、系统提示 1,500 tokens 常驻)实测三种记忆策略:全量重发、滚动摘要、摘要加事实保护层。结果:从第 8 次调用起,全量重发的单次成本开始反超滚动摘要——整段对话跑完,全量策略多花 79,392 tokens,滚动摘要省 19%,摘要加事实层省 15%。但省 4 个百分点的代价可能是个事故:滚动摘要把案件编号 A-4821 摘没了。这笔账怎么算、事实怎么保,全文拆开。

2. 环境信息

  • Python 3.13(纯标准库 json/re,零第三方依赖)
  • 对话样本:20 轮物业客服投诉线程(走廊灯/后楼梯杂物/停车场道闸/会所冷气,四案穿插,粤语真实感文本)
  • token 估算:CJK 字符约 2.2 字/token、拉丁约 4 字符/token 的近似法——估算用于策略对比足够,计费请以官方 tokenizer 为准
  • 模型部分零调用:三种策略的 token 数全部是确定性算术

3. 三种策略:谁在什么场景下赢

策略 A——全量重发。 每次调用把系统提示加全部历史塞进去。质量最好(模型看到一切),成本平方增长:第 20 次调用要发 2,225 tokens,40 次调用累计 79,392。对话短于 8 轮时它反而是最省的——短对话根本不需要记忆管理,这是很多人踩的反向坑。

策略 B——滚动摘要。 保留最近 4 轮原文,更早的压缩成一段摘要。成本线性化(每次调用约 1,600-1,700 tokens 稳定),全程省 19%。但它有个致命暗伤,见第 5 节。

策略 C——摘要加事实保护层。 在 B 的基础上加一个结构化事实表(JSON:客户资料/案件编号/各案状态),与摘要并列发送。比 B 多花 4%,换来的是编号、电话、承诺事项这类标识符永远不被压缩

核心代码骨架:

# depends on: SYSTEM_TOKENS(常量), est_tokens(), SUMMARY_B, FACTS_C, TURNS
# full runnable version in the repo file conv_memory_manager.py
KEEP_LAST_K = 4          # recent turns kept verbatim

def ctx_tokens(i: int, with_facts: bool) -> int:
    head_n = max(0, i - KEEP_LAST_K)
    t = SYSTEM_TOKENS                        # resident, every call
    if head_n:
        t += est_tokens("SUMMARY: " + SUMMARY_B)
        if with_facts:
            t += est_tokens("FACTS: " + json.dumps(FACTS_C, ensure_ascii=False))
    for r, c in TURNS[head_n:i]:
        t += est_tokens(c)                   # recent turns, verbatim
    return t

这套「阈值前全量、阈值后摘要、事实永不在摘要里」的三段式可直接抄进任何多轮对话应用,建议收藏

4. 成本曲线:crossover 在第 8 轮

在这里插入图片描述

三条线的形态说明一切:红线(全量)持续爬坡——每多一轮就抬一截,永不回头;绿线(摘要加事实)第 8 轮后走平——它的成本由常驻的摘要、事实表和固定窗口决定,与对话总长无关。灰虚线标出的 crossover 第 8 轮,就是"该不该上记忆管理"的决策点:预计对话不超过 8 轮,全量重发既简单又省钱;可能超过 8 轮,立刻上滚动摘要。注意这个数字依赖系统提示长度(1,500 tokens)——系统提示越长,crossover 越早。

5. 比成本更贵的事故:摘要把编号摘没了

在这里插入图片描述

策略 B 全程省 19%,比 C 还多省 4 个百分点——但它有一个实测演示的事故模式:滚动摘要写的是"業主投訴多項設施問題……“,案件编号 A-4821 在压缩时丢了。对话进行到中段,客户问"我的案件编号是多少?”,模型的上下文里已经没有这串字符——它只能编一个或者承认失忆。物业客服场景里,编号是客户查询的唯一凭证,丢了它等于案件失联。

解法不是"把摘要写得更好"——摘要天然压缩事件、天然倾向于丢标识符,这是它的工作原理。解法是把标识符从摘要的职责里剥离:结构化事实表(策略 C 的 FACTS)与摘要并列发送,事件归摘要管,标识符归事实表管。两者失败模式不同,所以生产环境两个都要。事实表的维护规则也简单到不需要聪明:编号、电话、金额、日期、承诺事项——出现即入表,永不依赖摘要携带。这行纪律值得收藏在团队的开发规范里。

6. 与 0830② 的关系:省的是两笔不同的钱

0830② 讲过 Prompt Caching——缓存重复前缀省 66%。它和本文解决的是同一枚硬币的两面:caching 省的是"同一对话内重复发送历史"的钱(读 0.1 倍),记忆管理省的是"根本没有必要发送的历史"的钱。两者可以叠加:滚动摘要让每次调用变短,caching 再让常驻系统提示变便宜。先做记忆管理(结构决策),再开 caching(计费优化),顺序不要反。

7. 踩坑与避坑

症状正确姿势
短对话也上滚动摘要每轮重复发摘要反而多花 4%先算 crossover(本文第 8 轮),短对话全量重发
摘要里丢标识符客户问编号,模型失忆或编造事实保护层:编号/电话/承诺进结构化 JSON,不进摘要
token 估算当精确值成本核算与账单对不上近似法做策略对比,计费用官方 tokenizer
摘要只在轮数触发、不看信息量编号在压缩瞬间丢失标识符出现即入事实表,与轮数无关
常驻系统提示不计入对比低估全量策略的每轮底价SYSTEM_TOKENS 是每次调用都要付的,永远算进去

这张表建议收藏,上任何多轮对话应用前先对一遍。

8. 总结

20 轮粤语客服线程实测出的三个数字:crossover 第 8 轮、全程省 19%、事实层多花 4% 买一个"编号永不丢"。对话记忆管理的本质不是省钱技巧,是把"模型该记得什么"从隐式的上下文堆砌变成显式的信息架构——事件进摘要、标识符进事实表、近 4 轮保原文、其余全丢弃。这套分层在 20 轮的投诉线程里成立,在 200 轮的长期助理场景里更加成立。下一步顺理成章:把摘要步骤本身交给一个便宜的模型调用(mini 档),再和本文的算术对比一遍真实成本。这篇也收录进「开学季·九月创作之星博客挑战赛」——多轮对话的账,越早算越省。

参考链接

  1. Anthropic 官方文档:Messages API — https://docs.anthropic.com/en/docs/build-with-claude/messages
  2. Anthropic 官方文档:Context windows — https://docs.anthropic.com/en/docs/build-with-claude/context-windows
  3. Anthropic 官方文档:Prompt caching — https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching

原创声明:本文为原创技术实践,token 数为本地确定性算术(估算近似,非官方 tokenizer),模型部分零调用、零计费,全部逻辑可复现。

在这里插入图片描述

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Patrick在香港

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值