- 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 增加上述三个文档索引
126 lines
7.7 KiB
Markdown
126 lines
7.7 KiB
Markdown
# LLM 使用点与成本分析
|
||
|
||
> 本文档基于 2026-08-30 的代码与真实运行数据编写,用于:
|
||
> 1. 盘点本项目所有使用大模型(LLM / embedding)的位置与调用方式;
|
||
> 2. 分析 DeepSeek 每日费用的构成与量级;
|
||
> 3. 给出降本改善建议(不改写生产代码,仅供决策参考)。
|
||
|
||
## 一、本项目所有用到「大模型」的地方
|
||
|
||
本项目有两类大模型能力,计费方式和对成本的影响完全不同:
|
||
|
||
- **对话 / 补全类(chat completion)**:贵,按「输入 token + 输出 token」计费。目前全部走 **DeepSeek(`deepseek-v4-flash`)**。
|
||
- **向量化(embedding)**:便宜,按 token 计费。目前走 **DashScope(`text-embedding-v3`)**,与 DeepSeek 是两套账户/两笔账单。
|
||
|
||
### 1.1 对话类 LLM 调用点(付费大头,DeepSeek)
|
||
|
||
| # | 场景 | 位置 | 触发频率 | 单次 token 规模 | 说明 |
|
||
|---|------|------|----------|----------------|------|
|
||
| 1 | **M4 全文英译中 + 投资事件抽取** | `llm/extractor.py::translate_and_extract`(`_call_llm_sync`) | 每个去重后的唯一文章 **1 次**(失败重试最多 3 次) | 单篇平均 输入≈1667 / 输出≈2342 | 这是**最大的成本来源**,每篇独立调用、整篇中文全文均输出 |
|
||
| 2 | **M7 日报 AI 摘要** | `scheduler/reporter.py::_call_llm_simple`(`_generate_ai_summary`) | 每天 3 次定时(07:00/12:00/18:00),每次 1~N 批 + 截断重试 | 每批 max_tokens 500–800(截断重试 1200) | 依赖当日高重要度事件条数;事件 ≤10 一条批,超过则分批 |
|
||
|
||
> ⚠️ 是否重复翻译(重要成本放大项):
|
||
> M4 设计了**增量机制**——同一 `url_hash` 的 `data/events/{date}/{hash}.json` 已存在就跳过,不重复调用 LLM。但每天 3 次定时全流程都会把**当天新增的去重文章**翻译一遍,若某天连续中断/失败多次,缺的篇会在下次补齐,当周补跑可能一次性翻译多天积压文章。
|
||
|
||
### 1.2 向量类(embedding,DashScope,低费用)
|
||
|
||
| # | 场景 | 位置 | 触发 | 说明 |
|
||
|---|------|------|------|------|
|
||
| 3 | **M5 向量生成(入库)** | `embedding/pipeline.py::embed_all_events` | 每天对已翻译文章批量 | `text-embedding-v3`,dim=1024,batch_size=10 |
|
||
| 4 | **M6 / MCP 检索查询向量化** | `vectorstore/pipeline.py::search_news`、`mcp_server/server.py` | 每次语义搜索 | 单个查询向量化,量极小 |
|
||
|
||
### 1.3 不使用大模型的环节
|
||
|
||
- M1 抓取、M2 正文提取(trafilatura)、M3 去重(SimHash/指纹库)、M6 Qdrant 入库、M9 MySQL 写入 —— 均**不调用大模型**。
|
||
|
||
---
|
||
|
||
## 二、真实 token 消耗与费用估算
|
||
|
||
以 `deepseek-v4-flash`(官方模型名 `DeepSeek-V4-Flash-0731`)当前价格计([官方定价](https://api-docs.deepseek.com/zh-cn/quick_start/pricing/)):
|
||
|
||
| 计价项 | 空闲时段 | 高峰时段(周一至五 9:00–12:00、14:00–18:00) |
|
||
|---|---|---|
|
||
| 输入(缓存未命中) | 1.5 元 / 百万 token | 3.0 元 / 百万 token |
|
||
| 输出 | 4.5 元 / 百万 token | 9.0 元 / 百万 token |
|
||
|
||
> 注:本项目常见的定时运行在 07:00(空闲)与 12:00/18:00(接近高峰边界),因此同一日费用波动约 ±100%。
|
||
|
||
### 2.1 M4 翻译实测 token(来自 `data/events/*/` 的 `prompt_tokens`/`completion_tokens`)
|
||
|
||
| 日期 | 去重后篇数 | 输入 token | 输出 token | 合计 |
|
||
|------|-----------|-----------|-----------|------|
|
||
| 2026-08-21(大日) | 82 | 135,616 | 208,146 | **343,762** |
|
||
| 2026-08-22(中) | 43 | 74,063 | 88,893 | 162,956 |
|
||
| 2026-08-30(小日) | 44 | 73,364 | 103,091 | 176,455 |
|
||
|
||
单篇平均:输入 ≈1650–1720,输出 ≈2050–2540 token。
|
||
|
||
### 2.2 单日费用估算(仅 M4)
|
||
|
||
**小日(约 44 篇,176k token)**
|
||
- 空闲:176,455 输入˝中位 ×1.5 + … 简化按 输入73k×1.5 + 输出103k×4.5 = 0.11 + 0.46 = **≈ 0.57 元**
|
||
- 高峰:输入73k×3 + 输出103k×9 = 0.22 + 0.93 = **≈ 1.15 元**
|
||
|
||
**大日(约 82 篇,344k token)**
|
||
- 空闲:135,616×1.5 + 208,146×4.5 = 0.20 + 0.94 = **≈ 1.14 元**
|
||
- 高峰:135,616×3 + 208,146×9 = 0.41 + 1.87 = **≈ 2.28 元**
|
||
|
||
### 2.3 日报摘要(M7)
|
||
|
||
每次约 1–3 批,每批输出几百 token、输入为事件列表,单日 3 次合计约几千 token,费用 ≈ **0.03–0.1 元/天**,可忽略。
|
||
|
||
### 2.4 结论:费用的绝对构成
|
||
|
||
- **M4 翻译是绝对主力(>95% 费用)**,日报摘要与 embedding 开销可忽略。
|
||
- 单日正常落在 **1–3 元** 区间(视当天文章量与命不命中高峰时段)。
|
||
- 若出现 **补跑/积压**:一次把一两天缺的篇全翻,或当日文章量冲到 80+ 篇,单日可能到 **3–6 元**。这通常是用户感受到「费用较高」的真实触发点。
|
||
|
||
---
|
||
|
||
## 三、成本高的根因分析
|
||
|
||
1. **输出 token 巨大**:M4 做的是「全文英译中」,每篇都把整篇中文翻译完整输出,单篇输出 2000+ token,是费用的绝对主体(输出单价是输入的 3 倍)。
|
||
2. **每篇独立调用**:82 篇文章 = 82 次往返,system prompt(约 3000 字符模板)每篇重复计入输入。
|
||
3. **每天 3 次全流程**:虽增量去重,但当天新文章都翻译,且 07/12/18 各跑一次,频繁触发。
|
||
4. **重试放大**:`max_attempts=3`,失败自动重试(实测约 +3%)。
|
||
5. **高峰时段触发**:12:00/18:00 的定时可能落入高峰计价,费用 ×2。
|
||
6. **付费墙源白跑**:CNBC/Reuters/FT/WSJ 等源抓不到正文,M2 标记 no_content 后**不会**进入 LLM(有防御过滤),因此不会为这些源付费——但它们也没产出,相当于 M1/M2 白耗。真正进 LLM 的只有 investinglive/zerohedge 等能抓到的源,这些源文章较长、翻译输出也就大。
|
||
|
||
---
|
||
|
||
## 四、降本改善建议(按性价比排序)
|
||
|
||
> 以下均为「建议」,未改动生产代码;实施前请评估收益与副作用。
|
||
|
||
### 建议 A(收益最大):限制 / 缩短 M4 输出
|
||
- 全文英译中的输出是主要开销。考虑:
|
||
- 将 `llm_scenes.translation.max_tokens` 从 8192 降到合理值(如 4096),或
|
||
- 改 prompt,只输出**中文摘要 + 关键事件**,不再整篇英译中(日报和检索实际只消费 `content_zh_preview` 前 300 字与 events,不必整篇全文翻译)。
|
||
- 收益:可显著削减输出 token(目前占费用 >60%)。
|
||
|
||
### 建议 B:尽量把翻译放在空闲时段
|
||
- M4 翻译集中到 07:00(空闲,半价)。避免 12:00/18:00 落入高峰计价。
|
||
- 仅日报生成放在 18:00(摘要量小,价差影响可忽略)。
|
||
|
||
### 建议 C:减少不必要的重复翻译(积压/补跑)
|
||
- 确保增量机制生效,避免因重复运行把同日文章翻译多遍。
|
||
- 若当日中断,下个定时点补齐即可;不要为了「补日报」频繁手动全流程重跑。
|
||
|
||
### 建议 D:缓存命中优化
|
||
- DeepSeek 对「缓存命中」输入大幅降价(0.05 元 vs 1.5 元/百万)。把 system prompt 固定化、相同前缀复用,可提高缓存命中率,降低输入成本(输入约占 40% 费用)。
|
||
|
||
### 建议 E:换更便宜的模型 / 分流
|
||
- 若质量可接受,翻译/摘要改用更低价的同类模型或「空闲时段」更明显的档位。
|
||
- embedding 已用 DashScope 低价档,无需动。
|
||
|
||
### 建议 F:成本监控
|
||
- 为 `_process_one` 的成功返回顺带累计 token 到日报 `stats`,或定期统计 `data/events/*/prompt_tokens` 总和,用于成本对账与异常预警。
|
||
|
||
---
|
||
|
||
## 五、参考
|
||
|
||
- [DeepSeek 官方模型与价格](https://api-docs.deepseek.com/zh-cn/quick_start/pricing/)
|
||
- 相关代码:`llm/extractor.py`、`llm/pipeline.py`、`scheduler/reporter.py`
|
||
- 配置:`configs/system.yaml` 的 `llm` / `llm_scenes` / `embedding` 段 |