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 增加上述三个文档索引
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
# DeepSeek 上下文缓存优化设计方案
|
||||
|
||||
> 目标:提高 DeepSeek API 的 prompt 缓存命中率,从而降低 M4 翻译与 M7 日报的输入成本。
|
||||
> 依据:DeepSeek「上下文硬盘缓存」机制([官方文档](https://api-docs.deepseek.com/zh-cn/guides/kv_cache))。
|
||||
> 状态:**设计稿**,尚未改动生产代码;文中「改动点」需确认后实施。
|
||||
|
||||
## 一、机制要点(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 元/百万)。
|
||||
- 翻译质量、输出格式不受影响(缓存只作用于输入前缀,不影响输出随机性)。
|
||||
|
||||
## 六、参考
|
||||
|
||||
- [DeepSeek 上下文硬盘缓存](https://api-docs.deepseek.com/zh-cn/guides/kv_cache)
|
||||
- [DeepSeek 模型与价格](https://api-docs.deepseek.com/zh-cn/quick_start/pricing/)
|
||||
- 相关代码:`prompts/translation_and_extraction.md`、`llm/extractor.py`、`scheduler/reporter.py`
|
||||
- 配套成本分析:[llm-cost-analysis.md](llm-cost-analysis.md)
|
||||
Reference in New Issue
Block a user