← 返回目录
ap7.2实操⏱ 约 13 分钟

会话与历史裁剪:省 token 的那个方案,贵了 54%

五种策略实测——全量历史又便宜又不丢信息,因为缓存

🔎 最后验证 2026-08📚 来源:本节五策略对比为 ECS 实测(2026-08,deepseek-chat,15 轮对话,含前缀缓存命中统计,脚本与原始输出见本节代码)🧰 Python、DeepSeek API
为什么学这个

多轮对话有个人人都知道的问题:每多说一轮,你都要把之前所有内容重新发一遍、重新付一遍钱

于是几乎所有教程都会告诉你:裁剪历史——滑动窗口、摘要压缩。听起来天经地义。

我实测了 5 种策略跑同一场 15 轮对话。结果是:

  A 全量历史             成本 0.0025 元 (  +0%)  输入 5486 tok  缓存命中 82%  ✅ 记得
  B 滑动窗口(最近 6 条)    成本 0.0038 元 ( +54%)  输入 2595 tok  缓存命中  0%  ❌ 忘了

滑动窗口把 token 砍掉一半,成本反而贵了 54%,而且忘了用户说过自己对花生过敏。

这一节讲清楚为什么,以及真的装不下时该怎么裁

💡 打个比方

你去同一家餐馆吃饭,老板认识你,你一坐下他就知道你不吃辣。这是"缓存"——他不用每次重新了解你。

现在你为了"节省老板的记忆",每次只告诉他最近三次点的菜。结果他每次都得重新琢磨你是谁——你没帮他省事,你把他的记忆清空了。

为什么全量历史反而更便宜

关键在 ap1.4 讲过的前缀缓存:模型服务按"你这次的输入,前面有多长的一段和上次完全相同"来命中缓存,命中部分只收十分之一的价

  • 全量历史:每一轮的输入 = 上一轮的输入 + 新的两条消息。前缀完全没变 → 缓存命中 82%;
  • 滑动窗口:每一轮都从头部丢掉最老的一条前缀一变,后面全部作废 → 缓存命中 0%
  A 全量历史        输入 5486 tok(命中 4480 / 未命中 1006)   成本 0.0025 元
  B 滑动窗口        输入 2595 tok(命中    0 / 未命中 2595)   成本 0.0038 元

B 的 token 只有 A 的 47%,但它们全是全价。

这是一条很容易被忽略的通用规律:任何"从提示词开头动刀"的优化,都会让缓存失效。动态插入的时间戳、每次重排的示例、轮换的系统提示——都是同一个坑。要改就改尾部。

五种策略的完整对比

  A 全量历史                 成本 0.0025 元 (  +0%)  输入 5486 tok  缓存命中  82%  ✅ 记得
  B 滑动窗口(最近 6 条)         成本 0.0038 元 ( +54%)  输入 2595 tok  缓存命中   0%  ❌ 忘了
  C 摘要压缩(只压一次)           成本 0.0042 元 ( +70%)  输入 3206 tok  缓存命中   4%  ❌ 忘了
  D 滚动摘要(每次掉出就更新)        成本 0.0067 元 (+169%)  输入 4561 tok  缓存命中   3%  ❌ 忘了
  E 滑窗 + 用户档案            成本 0.0070 元 (+182%)  输入 6146 tok  缓存命中  12%  ✅ 记得

记忆测试很直白:第 2 轮用户说"我对花生严重过敏",第 15 轮问"同事送了我一罐花生酱,可以每天抹面包吃吗"。

  • A:"绝对不行!你对花生严重过敏,必须立即拒绝或转送他人。"
  • B:"可以,但注意量。花生酱热量高,每天 1 勺即可……" ← 在过敏场景下,这是一次严重事故
  • D(滚动摘要):"可以,但选无糖无盐的天然花生酱……" ← 摘要里把这条丢了
  • E(用户档案):"绝对不行!您对花生严重过敏……早餐可选杏仁酱,但需确认无交叉污染。"

D 最值得注意:它是"正确实现"的摘要压缩——每次有内容掉出窗口就增量更新摘要,提示词里明确写了"必须保留用户的个人情况、忌口"。它还是丢了。

摘要是有损压缩,而你无法预测它会丢什么。在忌口、过敏、身份、金额这类信息上,这个风险不能接受。

结论:三条决策线

① 上下文装得下,就别裁。 15 轮对话累计 5486 token,离任何现代模型的上下文上限都还很远。在这个阶段裁剪,是在解决一个你还没有的问题,同时制造一个你本来没有的问题(缓存失效 + 丢信息)。

② 真的装不下时,裁尾不裁头。 优先丢掉的应该是最老的那几轮的助手回复(通常信息密度最低),保留用户说过的话。别动系统提示和开头——那是缓存的前缀。

③ 关键事实必须单独存,不能靠摘要。 这是 E 唯一在裁剪场景下答对的原因:它把"小林、花生严重过敏"抽成结构化的用户档案,每轮固定注入,不参与压缩、不会被摘要吃掉

# 用户档案:和对话历史分开存,放数据库
profile = {
    "name": "小林",
    "allergies": ["花生"],          # ← 这类字段永远注入,永远不压缩
    "preferences": ["不喜欢牛奶"],
    "goals": ["调整饮食"],
}

成本上它确实更贵(+182%),但这笔钱买的是"不会把过敏的人送进医院"。该花。

一套实用的会话结构

1系统提示(固定不变 —— 缓存的前缀,永远别动)
2用户档案(结构化事实
忌口/身份/长期偏好,每轮注入,不压缩)
3本轮检索到的资料(AP4 的 RAG,放在这里)
4对话历史(装得下就全量;装不下从最老的助手回复开始丢)
5本轮用户输入
上下文装什么

再加两条工程细节:

  • 会话要有上限:一场对话超过 N 轮或 M token,提示用户"要不要开个新话题"——比悄悄丢信息诚实;
  • 会话要能过期:用户三天前的对话还挂在内存里,是成本也是隐私风险(ap6.5)。设 TTL,到期归档或删除。

🔧 动手做:量一下你自己的对话成本(15 分钟)

  1. 跑本节代码,重点看 B 的 token 少一半却贵 54%,和 D 的"正确摘要"照样丢了过敏
  2. 打开 ap1.6 的流水,统计你的真实对话长度分布:P50 多少轮?P95 多少 token?——先看数据,再决定要不要裁。
  3. 检查缓存命中率:如果你的多轮对话缓存命中率很低,去找"每轮都在变的前缀"(时间戳?随机示例?)。
  4. 列出你产品里"绝不能丢"的事实:忌口、身份、金额、已确认的选择……把它们从对话历史里抽出来,存成结构化档案。
  5. 设会话上限和 TTL,并写好达到上限时给用户的提示文案。

做到这里你应该有:真实的对话长度分布 + 缓存命中率 + 一张用户档案表 + 会话上限与 TTL。

为什么:多轮对话是 AI 产品最常见的形态,也是成本最容易失控的地方——因为它的成本随轮数平方级增长(每轮都要重发之前所有内容)。而本节最反直觉的发现是:最朴素的做法(什么都不裁)配合缓存,在很长一段时间内是最优解先测,再优化——不然你的"优化"很可能像 B 那样,又贵又坏。

❓ 测验
滑动窗口把每轮输入 token 砍掉了一半,为什么总成本反而涨了 54%?
⚠️ 避坑摘要压缩是有损的,而且你无法预测它会丢什么

实测里 D(每次有内容掉出窗口就增量更新摘要)是教科书式的正确实现,提示词里也明确写了"必须保留用户的个人情况、忌口、偏好"。它还是把"花生严重过敏"丢了。

为什么会丢:摘要模型面对的是"把 N 条对话压成 80 字",它会按"这段对话在讲什么"来取舍,而用户三轮前顺口提的一句忌口,在"这段对话在讲什么"里权重很低

所以规矩是:能结构化的事实,永远不要交给摘要。摘要用来压"上下文氛围"(聊过哪些话题、讨论到什么程度),关键事实走独立字段、独立存储、每轮固定注入。判断标准很简单:这条信息丢了会不会出事?会,就别让它进摘要。

🤖 让 AI 帮你设计会话管理方案
我的 AI 产品是【描述】,对话轮数分布是【P50/P95】,单轮输入约【X】token,用的模型上下文上限【X】。请帮我设计会话管理:1) 现在到底需不需要裁剪历史(结合前缀缓存算一笔账);2) 哪些信息必须抽成结构化用户档案、字段怎么设计;3) 真要裁剪时的顺序(先丢什么、保留什么、怎么不破坏缓存前缀);4) 会话上限和 TTL 的建议值,以及达到上限时给用户的提示文案;5) 需要监控的指标(缓存命中率、平均轮数、单会话成本)。
✅ 小结

会话三句话:全量历史 + 前缀缓存往往是最优解(实测最便宜且不丢信息);任何动提示词开头的操作都会让缓存失效(滑窗砍半 token 却贵 54%);关键事实要抽成结构化档案,别交给摘要(正确实现的滚动摘要照样丢了过敏)

下一节回到用户能直接感受到的地方:流式 UI——ap1.2 测过 TTFT 快 8.2 倍,这一节讲怎么把这个"快"真正做进界面。

下一节 → 流式 UI 与前端体验:让等待不像等待
🔎 来源与核验· 3 条,点开核对
本节每个关键论断都对应一个可追溯的来源 —— 这是本课程"靠谱、不过时"的底线。
「15 轮对话 5 策略实测:全量历史 0.0025 元(输入 5486 tok、缓存命中 82%)、滑动窗口 0.0038 元(+54%,2595 tok、命中 0%)、只压一次摘要 0.0042 元(+70%)、滚动摘要 0.0067 元(+169%)、滑窗+用户档案 0.0070 元(+182%)」
📚 ECS 实测 history.py(2026-08,deepseek-chat,temperature=0,价格量级同 ap1.4)✓ 已核验 2026-08
「记忆测试(第 2 轮告知花生严重过敏,第 15 轮问花生酱):全量历史与用户档案两组明确拒绝;滑动窗口、只压一次摘要、滚动摘要三组均回答「可以」」
📚 ECS 实测 history.py(2026-08)✓ 已核验 2026-08
「判分提示词最初写成输出 YES/NO 时,5 条回答(含明确拒绝的)全部被判为 NO;改用中文标签「反对/支持」后判定正常——标签本身带来的裁判偏差」
📚 ECS 实测(2026-08),呼应 ap5.3 裁判偏差✓ 已核验 2026-08
智图软件的赞赏码
都看到这了,打个赏呗!
接下来 · ap7.3
流式 UI:让等待不像等待
继续读下一节 →