独立专题 · 成本优化加餐
相关阅读:
drafts/llm-07-cost.md(全链路成本治理)
Agent 上线第三周后,账单往往不是因为「答得更长」,而是 同一套 system、工具 Schema、规章前缀,每轮对话又被完整计费一遍 。Prompt 缓存和上下文压缩,是少数能在 不砍模型档位 的前提下,立刻压低输入 token 的两把刀。
缓存解决「重复前缀」,压缩解决「历史膨胀」------两件事别混成一种「省钱 Prompt」。
本篇只聚焦这两块:什么该缓存、摘要/滑动窗口怎么配、何时坚决不压、和 RAG/路由怎么划界,并给一张 假设量级 的前后对比表(示例,非厂商报价)。
你将学到
- Prompt 缓存的命中条件与内容选型
- 会话摘要 + 滑动窗口的组合策略
- 明确「不该压缩」的场景清单
- 与 RAG、模型路由的职责边界
- 成本前后对比表示例与落地顺序
- 生产踩坑与监控指标
一、先结论:输入才是账单大头
一次多轮 Agent 请求的典型输入构成:
text
总输入 ≈ 固定前缀(system + tools + 规章)
+ 检索/RAG 块
+ 历史对话 / tool 中间态
+ 当前用户消息
固定前缀 往往占 30%~60%,且每轮重复;历史 在长会话里线性膨胀。
缓存只动前者,压缩只动后者。只优化输出 token,通常砍不到主因。
| 手段 | 主要省什么 | 典型适用 |
|---|---|---|
| Prompt 缓存 | 重复前缀 | 多租户 SaaS、统一 Agent 模板 |
| 滑动窗口 | 近期对话 | 客服、结对编程 |
| 周期性摘要 | 远期历史 | 个人助手、长调研 |
| RAG 限 TopK | 外部知识块 | 文档问答(见 drafts/llm-03-rag.md) |
| 模型路由 | 全请求单价 | 简单 FAQ 走小模型(见 drafts/llm-07-cost.md) |
二、什么内容适合 Prompt 缓存
各云厂商的缓存实现细节不同,但 工程规律一致 :把 稳定、长、每轮都要带 的内容放在 Prompt 最前面 ,且 少改顺序与字面。
适合缓存
| 内容 | 原因 | 注意 |
|---|---|---|
| 固定 system 角色与边界 | 全站共享 | 改一行可能整段 cache miss |
| Tool / Function Schema | 体积大、变动少 | 新增 tool 放末尾,别重排 |
| 企业规章、合规条款(版本化) | 长且稳定 | 用 policy_v3 版本号,别 inline 改字 |
| 多租户共享模板 | 摊薄前缀成本 | 租户差异放 缓存块之后 |
| 静态 few-shot 示例 | 演示格式 | 示例过多反而拖慢首包 |
不适合缓存
- 每轮变化的 RAG 检索结果
- 用户 PII、实时库存、会话 state
- 频繁 A/B 的 Prompt 文案(hit 率接近 0)
- 把「当前时间 / 随机 seed」写进前缀
提高命中率的四条硬规则
text
1. 静态块在最前,动态块在最后
2. tool 定义顺序固定;新增 append,避免重排
3. system 改版走版本号,便于对比 cached token 曲线
4. 以账单/日志里的 cached input 为准,别凭感觉
验证方式 :发两次相同前缀的请求,看第二次 cached_tokens(或等价字段)是否显著上升。各 Provider 字段名不同,以控制台文档为准。
三、会话摘要与滑动窗口
长对话不能无限堆全文。常见组合:滑动窗口保留近 N 轮 + 周期性小模型摘要 + 关键事实结构化存储。
滑动窗口
python
# 示例:保留最近 6 轮 user/assistant,更早的丢弃或进摘要队列
MAX_TURNS = 6
def trim_messages(messages: list[dict]) -> list[dict]:
system = [m for m in messages if m["role"] == "system"]
dialog = [m for m in messages if m["role"] != "system"]
return system + dialog[-MAX_TURNS * 2 :]
窗口过小 → 模型「失忆」;过大 → 输入 token 仍爆。用 P95 对话轮数 定 N,别拍脑袋。
周期性摘要
| 触发 | 做法 | 风险 |
|---|---|---|
| 每 8~12 轮 | 用小模型压缩为 bullet 摘要 | 摘要比原文还长 = 负优化 |
| 话题切换 | 旧话题单独归档一条 summary | 跨话题引用丢失 |
| tool 链路过长 | 只保留结论 + 关键 ID | 丢失中间推理链 |
摘要 Prompt 要 约束格式与字数,并保留结构化槽位,例如:
text
输出 JSON:{ "goal": "", "decisions": [], "open_questions": [], "entity_ids": [] }
禁止复述寒暄与 tool 原始 JSON。
摘要本身也计费------摘要频率 × 摘要长度 要进成本模型(见下文示例表)。
四、何时不该压缩
压缩不是越狠越好。以下场景 宁可多付 token,也别压:
| 场景 | 为什么不压 | 替代 |
|---|---|---|
| 合规 / 金融 / 医疗审计 | 需完整原文可追溯 | 结构化归档 + 采样审计 |
| 代码 Agent 多文件 diff | 压掉行号与上下文 | 滑动窗口 + 文件级 memory |
| 用户刚确认的约束(「必须用 Redis」) | 摘要易被泛化 | 写入 pinned_facts 永不摘要 |
| RAG 引用作答 | 压掉 chunk 来源 | 保留 citation 块,压闲聊 |
| 低置信 tool 结果 | 需重试原始上下文 | 仅压缩已确认步骤 |
决策口诀 :若压缩后 无法回答「依据哪条消息/哪个 tool 输出」,就不该压。
五、和 RAG / 模型路由的边界
三者常同时出现在架构里,职责别混:
text
用户消息
→ [路由] 选模型档位(便宜 / 旗舰)
→ [RAG] 按需拉外部知识(动态,一般不缓存)
→ [缓存前缀] system + tools + 规章
→ [压缩] 历史 + 大 tool 结果
→ 模型生成
| 层 | 解决什么 | 不解决什么 |
|---|---|---|
| Prompt 缓存 | 重复前缀计费 | 检索质量、模型能力 |
| RAG | 知识超出窗口 | 重复前缀、对话记忆 |
| 上下文压缩 | 历史/tool 膨胀 | 首次检索召回率 |
| 模型路由 | 单价与能力匹配 | 前缀重复计费 |
反模式 :用 RAG 塞整本手册代替缓存------每轮检索块都变,cache miss,且检索费另算。
正模式 :手册 索引进 RAG ,Agent 行为规章进缓存前缀 ;历史 摘要 ,检索 TopK + Rerank 限长。
与 drafts/llm-07-cost.md 的分工:该篇讲预算、路由、熔断全链路;本篇只深挖缓存 + 压缩的可执行清单。
六、成本前后对比(示例,非真实报价)
假设:B2B 助手,日活 500,人均 8 轮/天,30 天;固定前缀 4k token/轮,历史均值 2k token/轮,输出 800 token/轮。
单价用 示意系数 (input_unit = 1,cached_input = 0.25,output_unit = 4),仅看 相对降幅,勿当作任何厂商价格。
| 项 | 优化前(示例) | 优化后(示例) | 说明 |
|---|---|---|---|
| 固定前缀 input | 500×8×30×4k = 480M | 480M × (1−0.7 hit) ≈ 144M | 假设 cache hit 70% |
| 历史 input | 500×8×30×2k = 240M | 240M × 0.55 ≈ 132M | 窗口+摘要约省 45% |
| 输出 | 500×8×30×800 = 96M | 96M(不变) | 本篇不压输出 |
| 摘要额外 cost | 0 | +500×30×400 ≈ 6M | 每用户每天一次小摘要 |
| 加权示意总分 | 480+240×1 + 96×4 = 1104 | 144+132×1 + 6×1 + 96×4 ≈ 666 | 约 −40%(示例) |
换参敏感项:
- cache hit 50% → 55% 而非 70% → 总降幅缩水
- 摘要写太长 → 「优化后」可能比优化前更贵
- 路由已把小模型分流 40% 流量 → 再叠缓存,降幅 非简单相加
落地顺序建议:① 监控 P95 输入构成 → ② 稳定前缀 + 测 cache hit → ③ 滑动窗口 → ④ 摘要 + pinned_facts → ⑤ 与 RAG TopK 联调。
七、实操清单(可直接贴进 PRD)
text
[ ] 日志拆分:prefix / rag / history / user 各占 token
[ ] system+tools 放最前;动态内容置后
[ ] tool 定义变更走 append;system 改版本号
[ ] 仪表盘:cached_token 占比、hit 率、改 Prompt 前后对比
[ ] MAX_TURNS 按 P95 定;pinned_facts 列表
[ ] 摘要:格式约束 + 最大字数 + 触发轮次
[ ] 压缩前检查:是否含合规/引用/tool 原始依据
[ ] 与 RAG:TopK 上限、Rerank 后再入 context
[ ] 与路由:难例仍走旗舰;缓存与档位独立
[ ] 告警:cached 占比骤降、摘要长度 P95 超阈
踩坑清单
- 把 RAG 块塞进缓存前缀 → 每轮变,hit 率归零
- 改 system 一行不告警 → cached 占比静默下跌,账单涨
- 摘要丢失 pinned 约束 → 用户反复纠正,总 token 反升
- 滑动窗口过小 → 「刚才不是说用 PostgreSQL 吗?」类投诉
- 只缓存不监控 → 多环境 Prompt 漂移,测试环境 hit、生产 miss
- 压缩与路由重复优化 → 小模型 + 狠摘要,难例质量崩盘
- 用示意降幅当 OKR → 必须用自家日志重算(见
drafts/llm-07-cost.md估算模板)
相关阅读
| 文档 | 关系 |
|---|---|
drafts/llm-07-cost.md |
路由、预算、熔断、月成本模板 |
drafts/llm-03-rag.md |
检索限长与 RAG 评测 |
drafts/llm-05-tool-engineering.md |
大 tool 结果摘要回灌 |
小结
Prompt 缓存 盯稳定前缀与 hit 率;上下文压缩 盯历史与 tool 中间态,且 pinned 事实、合规原文、引用依据 不能压。RAG 管外部知识,路由管模型档位,三者各管一段。先用日志拆输入构成,再按清单落地;降幅用自家数据验,示例表只做量级感。
标签建议 :大模型 Prompt工程 成本优化 Agent