perf(llm): 短新闻 enrich 跳过时不再标 'n/a',避免 enrichment_loop 反复扫
问题:
enrichment_loop 的 in-loop 过滤 (line 616) 把 'n/a' 当成
"未 enrich" 信号:
if any(s in ("pending", "failed", "n/a") for s in statuses):
todo_ids.append(a.id)
短新闻入表时 format_status='n/a'、image_ai_status='n/a'
(commit 1 决定),而 enrich_article 在 is_short 跳过这两任务时
保留 'n/a'。后果:enrichment_loop 永远认为"这两任务未完成",
每 ~3.5 分钟反复把同一篇短新闻捞进队列 enrich 一次。
实测(commit 10 修复前 1 小时数据):
- 9 篇短新闻 × 18 次 enrich = 131 次完全 ok
- 131 - 9 = 122 次纯浪费(占 95%)
- 每篇 enrich 内部 Angel + 美团两个 LLM 调用是并行的
- 浪费配额:Agnes 免费 plan 风险、Angel 月配额、美团限速窗口
修法:
enrich 跳过某任务时,把对应 status 标 'ok' (语义 = 该任务
"已完成" = 不需要做),而不是 'n/a' (语义 = 任务存在但跳过)。
改动 2 处:format 跳过 + image 跳过。
短新闻 enrich 后,所有 *_status 都是 'ok',enrichment_loop
看到后不再扫,只跑一次。
注释同步更新:解释 'n/a' vs 'ok' 的语义区别,提醒后续修改者
不要把 'n/a' 写回 status 字段。
存量修复(不写入 commit,运维动作):
修复前入库存量的短新闻 format/image_ai_status 仍是 'n/a',
deploy 后第一次循环会把它们 enrich 一遍改成 'ok'。如果你想
立刻修,跑:
UPDATE articles
SET format_status='ok', image_ai_status='ok'
WHERE is_short_news=true
AND (format_status='n/a' OR image_ai_status='n/a');
不改:
- enrichment_loop 的 SQL/loop 过滤条件(不动 'n/a' 状态值,
仍有合法场景使用:meituan_client 未配置时 commentary_meituan
会标 'n/a'。但生产环境 meituan key 已配置,该 case 不存在)
- ingest 路由的 *_status='n/a' 初始化(那是在入库阶段,
enrichment_loop 不会立即扫到,有 2 秒起步延迟 +
is_short_news/body_zh_text 过滤)
- comment_status 等其他 status 字段(短新闻也会跑,设 'ok')
性能影响(预估):
- 修复前:每篇短新闻每小时 18 次 enrich × 1 路串行 ~18 秒/次
= 占 enrichment_loop 单 worker 18 * 18s = 5.4 分钟/小时
- 修复后:每篇短新闻只 enrich 1 次,约 5 秒
- 节省:短新闻 LLM 调用约减少 95%
- 副作用:长新闻 enrich 不再被短新闻"挤占"semaphore 资源,
长新闻 enrich 速度会加快(从当前 ~18s 串行,可能回到 ~5s)