Files
intl_news/docs/llm-cache-optimization.md
simon c1ab751d95 feat: 日报改为每日一次 + 新增 LLM 使用/成本/缓存文档
- domestic_full.sh / pipeline.sh 新增 --no-report 参数:跳过日报生成,
  保持 M1 抓取 + M2→M6 管道不变,用于 12:00/18:00 只抓不生成日报
- crontab: 07:00 全量含日报,12:00/18:00 --no-report(日报每日一次,降低 LLM 费用)
- docs/llm-models.md: 各 LLM 调用点分别用的 provider/model 事实清单
- docs/llm-cost-analysis.md: 真实 token 消耗与费用构成、降本建议
- docs/llm-cache-optimization.md: DeepSeek 上下文缓存机制与命中率提升设计
- docs/README.md 增加上述三个文档索引
2026-09-04 10:38:33 +08:00

5.8 KiB
Raw Permalink Blame History

DeepSeek 上下文缓存优化设计方案

目标:提高 DeepSeek API 的 prompt 缓存命中率,从而降低 M4 翻译与 M7 日报的输入成本。 依据:DeepSeek「上下文硬盘缓存」机制(官方文档)。 状态:设计稿,尚未改动生产代码;文中「改动点」需确认后实施。

一、机制要点(DeepSeek 上下文硬盘缓存)

  1. 默认开启、零代码开启:所有请求自动参与缓存,无需在请求里额外传参。
  2. 「缓存前缀单元」完整匹配才命中:每次请求的输入结束位 / 输出结束位、以及系统检测到的公共前缀,都会落盘为缓存前缀单元。后续请求必须完整匹配某个缓存前缀单元,才会计入「缓存命中」。
    • A+B 之后再来 A+B+C → 命中 A+B(沿用例一看)。
    • A+B 之后再来 A+C → 不命中,但系统会把公共前缀 A 落盘,下一轮 A+D 可命中 A。
  3. 价格差异极大(deepseek-v4-flash):
    输入 空闲 高峰
    缓存命中 0.05 元/百万 0.10 元/百万
    缓存未命中 1.5 元/百万 3.0 元/百万
    • 命中比未命中便宜 30 倍。提升命中率是单位成本上最强的手段。
  4. 可观测:响应 usage 里的 prompt_cache_hit_tokens / prompt_cache_miss_tokens 直接给出命中情况,可据此验证优化前后。

二、当前实现的问题

场景一:M4 翻译(llm/extractor.py)

当前 user message 结构(prompts/translation_and_extraction.md):

请处理以下英文财经新闻:

**标题**: {title}          ← 每篇不同
**来源**: {source_name}     ← 每篇不同
**发布时间**: {publish_time} ← 每篇不同
**正文**:
{content}                  ← 每篇不同
  • system prompt 完全固定 → 可作为一个稳定前缀,但只有几百 token,占单篇输入比例很小。
  • user prompt 里「标题/来源/发布时间」都在正文之前且每篇不同 → 导致每篇文章的 user 前缀都错位,正文 {content} 无法形成稳定公共前缀,命中率大幅下降。
  • 实测单篇平均输入 ≈1667 token,估算其中 75%+ 是正文 {content};若能让正文前缀稳定,可显著命中。

场景二:M7 日报 AI 摘要(scheduler/reporter.py)

  • system prompt 固定("你是国际财经日报撰写助手…"),user prompt 是当日事件列表,每批内容不同 → 只有极短的 system 前缀可命中,命中率低但总量小(每天仅几千 token),非成本重点。

三、优化方案

方案 A(推荐,改动小、收益大):稳定 M4 user prompt 前缀

把「每篇变化但重复出现的结构性开头」从正文前挪到结构里,让正文 {content} 作为相对固定的前缀占位,或至少让「固定指令段」全部前置。

调整 prompts/translation_and_extraction.md 的 user 段,把固定指令前置,变化字段后置:

请处理以下英文财经新闻,输出 JSON(标题译文、正文全文译文、事件列表):

[MODEL_INSTRUCTION_BLOCK]   ← 完全固定的指令/示例(移到最前)

【待处理新闻】
正文:
{content}                    ← 长固定位置内容

【元信息】
标题: {title}
来源: {source_name}
发布时间: {publish_time}

说明:把很长的 {content} 提前、固定,让后续连续请求以同一篇或相似内容为前缀;配合条件:同一批 82 篇连续翻译时,尽量让公共 system + 固定指令 + 常见正文前缀命中缓存。

方案 B(最直接):「正文最早、短字段最后」重排

即便不改语义,仅调整 user 段字段顺序也能提升命中:把 {content}(变量庞大但相对可复用的重复新闻源)尽量前置且稳定,{title}/{source_name}/{publish_time}(每篇必变)后置。这样 system + 固定指令 + 正文前缀可形成缓存前缀单元,后续请求命中。

方案 C:并发下最大化公共前缀(很少改动)

  • M4 并发 concurrency=3 同时发 3 个不同文章 → 冷启动多,前缀难以公共。可在首篇(或任务开头)先发 1 篇建立缓存前缀,再并发,后续命中率高。收益存在但不稳定,不强制。

方案 D(工程化验证):在 events 文件记录缓存命中

利用 usage.prompt_cache_hit_tokens / prompt_cache_miss_tokens,把这两项写入 data/events/{date}/{hash}.json(现有字段 prompt_tokens 旁),用于量化验证方案 A/B 落地后的命中率提升。属观测增强,不影响功能。

方案 E(日报场景,次要)

M7 摘要量小,可不动;若要优化,保持 system prompt 稳定即可(当前已稳定)。可复用「截断重试时复用同一前缀」。

四、建议实施顺序

  1. 先落地可观测性(方案 D):给 events 记录缓存命中 token(小改动,零风险),跑 1 次对比基线。
  2. 再实施方案 A / B(重排 M4 user prompt),对比命中率与单篇输入成本。
  3. 酌情试点方案 C(并发预热)。

五、验收标准

  • 单篇输入 token 中 prompt_cache_hit_tokens 占比显著上升(目标:日常连续翻译批 >50%)。
  • 单篇平均输入成本下降(命中 0.05 vs 未命中 1.5 元/百万)。
  • 翻译质量、输出格式不受影响(缓存只作用于输入前缀,不影响输出随机性)。

六、参考