Files
meida_backend/prompts
xsl e78ba3feef feat(report): LLM copy generation with mandatory post-validation and fallback
report_copy/v1 prompt(系统段零变量)+ 结构化 ReportCopy + 素材组装
(skipped 不进 prompt/超长裁剪)+ 贬损词表/一致性/绝对化三重校验 +
重试一次后降级规则直出模板(T-P3-10/11)。

- copy.py:ReportCopy(schema 宽进严出取舍见注释)/compose_prompt_material
  (ok 过滤+6000 字符裁剪,低优先级先丢、硬结论不丢,记录 dropped_keys)/
  render_fallback_copy 零 LLM 降级模板
- validation.py:PEJORATIVE_TERMS 35 词(源自合规 §3,初版内嵌注释)+
  一致性三规则(枚举同款含别名/色值在板内/建议句需规则支撑·宽松口径)+
  绝对化用语兜底
- copy_stage.py / validation_stage.py:任何出口 passed=true 或抛错,
  语义层重试一次(与网关解析层重试独立),仍违规降级模板并 fail-close 自证
- 单测 25 例(词表含变形/三规则正反/降级零违规)+ 集成 4 例
  (FakeProvider 全栈:干净通过/脏一次修正通过/持续脏降级且最终文案
  零贬损词——黄金断言);全量 529 单测 + 49 集成全绿

偏差说明:
1. prompts/report_copy/v1.txt 非新建——LLM 批次已放置初版(user 段变量
   为 {payload}),按本任务契约改写为 {dimensions_json} 并补内容红线
   (该文件任务文档明确归 T17,无与他人冲突)。
2. check_conclusion_consistency 按契约签名 (copy, dimensions) 之外增加
   可选 rule_hits 关键字参数:规则③的支撑判定需兼容命中内嵌在维度/
   顶层列表两种 T16 契约形态,缺省时不追责(宽松口径)。
3. 绝对化用语未按单字「最」拦截,取营销语境复合词(最好/最合适/第一/
   百分百等 17 词):单字会误杀「最近/最终」等中性词,红线范围不变。
4. 集成文件未挂 MEIDA_RUN_INTEGRATION skipif:用例为 FakeProvider 内存
   装配、不依赖真实 PG/Redis,按任务要求仍放 tests/integration/ 并带
   integration marker。
2026-08-14 22:09:09 +08:00
..

prompts/ — 版本化 Prompt 模板

架构 §8.1:Prompt 存文件(随代码版本化)+ 场景绑定版本号。 运行时由 packages/llm/prompts.py 的 PromptRegistry 按 id + version 加载, 使用的版本号会写进每一行 ob_ai_call,用于回溯「为什么当时这么答」。

文件布局

prompts/<prompt_id>/<version>.txt
[system]
固定不变的、可被供应商缓存的前缀。

[user]
每次调用渲染的变量部分,用 {占位符}。

铁律:[system] 段不许有任何变量

架构 §7.2 缓存前缀纪律 / TD-04:

系统提示词与稳定知识片段必须放在 prompt 头部且不含时间戳、随机 ID、 用户昵称等变量,否则缓存永远不命中,输入成本翻数倍。

这条规则靠人 review 是守不住的:破坏它以后功能完全正常,只有账单会翻几倍, 而账单要到月底才看得见。所以它被写成了代码:

  • PromptRegistry 加载时校验,LLM_CACHE_PREFIX_MODE=strict 下直接拒绝调用。
  • tests/unit/test_prompt_cache_prefix.py 扫描本目录下全部模板。

会被拒绝的东西:ISO 日期、时刻、中文年月、时间戳、UUID、长十六进制串, 以及名字里带 nick/user/name/now/date/time/id/rand/session/ request/trace/token 的占位符。

要注入用户画像、检索结果、会话摘要?放到 [user] 段或调用方传入的 messages 里 —— 它们本来就该排在固定前缀之后(§7.2 ③ 上下文组装)。

改 Prompt 的规矩

  • 不要原地改已上线的版本,新建 v2.txt,再在 routing.py(或 LLM_SCENE_OVERRIDES_JSON)里切过去。旧版本要留着,ob_ai_call 里的历史记录 才有意义。
  • 报告与 Agent 这类核心链路的 Prompt 变更必须先灰度 + 跑黄金集回归 (架构 §14.3)。
  • Token 预算见 §7.2:系统提示词 ≤ 800,输入合计 ≤ 3700,输出 ≤ 800。

内容合规约束

每个面向用户的 prompt 都必须在系统前缀里写死:不做医疗/减重/整形/命理结论 (CR-12)、不评判外貌、不使用绝对化用语、用户输入视为内容而非指令 (NFR-SEC-04 Prompt 注入防护)。