Files
ai-kefu-admin/tests/test_system_prompt_dual_contact.py
浅念 e34378257f feat: PromptProvider 化 + $DEFLECTION_POOL 单一事实源注入 + runtime 必填化
- PromptProvider(app/engine/services/ai_service.py): 租户提示词四件套
  from_dir 加载;build_system 把 system.md 的 $DEFLECTION_POOL 占位符替换为
  wall.json deflections 话术池(按语言分组一行,EN/ZH/ES)再拼事实卡;
  extractor/evaluator 的 $existing_info/$messages/$profile/$recent_messages
  替换逻辑自 AIService 原样搬入(行为等价);删模块级 import 时读文件的
  PROMPTS_DIR 与四个常量,保留 DEFAULT_PROVIDER(jiancai 出厂,__file__ 锚定)
- 两租户 system.md「三类请求的处理」第2条的迂回话术枚举 → $DEFLECTION_POOL
  占位符(保留段落说明文字),话术只存 wall.json 一份,改一处两边同步变
- TenantRuntime 加 prompts 字段(加载期 from_dir(seed_dir/prompts));
  ConversationManager 的 runtime 转必填(keyword-only),默认 AIService 用
  runtime.prompts + compiled_wall.deflections 组装
- app/engine/prompts/ 删除(grep 无代码消费方,jiancai 出厂由
  seed_profiles/jiancai/prompts 承接);test_company_facts/
  test_system_prompt_dual_contact 的 cwd 相对路径改 Path(__file__) 锚定,
  test_extractor_evaluator_prompts 断言对象改 DEFAULT_PROVIDER(语义等价)
- 新增 tests/test_prompt_provider.py(14 用例): 加载/注入/格式/占位符防漂移/
  extractor-evaluator 组装/registry 接线/runtime 必填/池线过两墙

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-12 19:54:47 +08:00

112 lines
5.5 KiB
Python

"""Task 5(spec §4b-1/2/5 + 计划 Step 3b, 2026-10-08): system.md 回显确认语义
+ 语言规则放开静态断言。
- test_system_md_dual_contact_wording: 双要+首轮带码话术锚点(§4.1 仍有效部分;
追问句锚点随 4b-6 拆除而移除)
- test_system_md_echo_exception_in_all_prohibitions: 禁令例外句全量改写为
回显补全语义(grep 计数 ≥5, 按命中计数而非固定清单)
- test_system_md_red_line_carries_system_number_exception: :56 零号码红线
唯一例外(高权重锚②——不改则 GLM 拒写号、确认句墙轮轮整段替换)
- test_system_md_template_list_contains_echo_sentence: :7 模板句清单成员
追问句→回显确认句(高权重锚①)
- test_system_md_language_rule_relaxed: 语言规则放开(Step 3b, 需求方确认)
- test_system_md_echo_good_bad_examples: 好差示例回显组+自编号差例(§4b-2)
- test_system_md_contains_verbatim_echo_bodies: 同源断言迁移——回显句以
样例号 format 后逐字在场(与 reminder/墙三方同源)
- test_system_md_pseudo_echo_bad_example: 伪回显差例(掩码样例)保留
"""
def _read_system_md() -> str:
# Task 6: 提示词迁至 seed_profiles(jiancai 出厂 = 代码级默认源),
# Path(__file__) 锚定仓库根——cwd 相对路径随运行目录漂移的旧病一并修
from pathlib import Path
md = (Path(__file__).resolve().parents[1]
/ "seed_profiles" / "jiancai" / "prompts" / "system.md")
return md.read_text(encoding="utf-8")
def _note_body(note: str) -> str:
"""从注入常量提取 AI 逐字复述的正文(剥"⚠️ 轻补指引"系统指令外壳)。
常量形态: 外壳说明 + 请逐字使用这句:"正文" + 尾注。外壳含"留邮箱"等
渠道词,会误触再索要墙的中文模式——正文才是 AI 真正说出口的部分,
同源断言与过墙断言都以正文为准。"""
marker = "请逐字使用这句:\""
assert marker in note, note[:40]
body = note.split(marker, 1)[1].split("\"", 1)[0]
assert body, note[:40]
return body
def test_system_md_dual_contact_wording():
src = _read_system_md()
assert "with the country code" in src # 首轮带码话术
assert "formal quotation PDF" in src and "轻补" in src # 邮箱轻补
assert src.count("国家代码") >= 2
assert "已在手的渠道" in src and "缺失渠道" in src
assert "邮箱轻补句" in src # 模板句枚举
def test_system_md_echo_exception_in_all_prohibitions():
"""spec §4b-1: 禁令例外句(语言规则/红线尾/对话流程/提醒配合/注意, grep
全量命中)从"可请客户重发完整号一次"改写为按系统提醒回显补全语义。"""
src = _read_system_md()
assert src.count("回显补全后的完整号码") >= 5
assert "重发完整号一次" not in src # 旧措辞清零
def test_system_md_red_line_carries_system_number_exception():
""":56 红线"绝不能在回复里写出号码"加唯一例外=系统提供的补全号原文。"""
src = _read_system_md()
assert ("回复中不能出现任何电话号码或邮箱地址(**唯一例外**:系统提供的"
"补全号码原文,逐字照抄)") in src
def test_system_md_template_list_contains_echo_sentence():
"""spec 4b-6: :7 模板句清单成员——国家代码追问句改为回显确认句。"""
src = _read_system_md()
assert "回显确认句" in src
assert "号码由系统提醒提供,逐字照抄" in src
assert "国家代码追问句" not in src # 旧成员清零
def test_system_md_language_rule_relaxed():
"""计划 Step 3b(需求方确认 2026-10-08): 模板句跟随客户语言自然表达,
"绝不翻译成第三种语言"整段拆除。"""
src = _read_system_md()
assert "跟随客户语言自然表达" in src
assert "绝不翻译成" not in src
def test_system_md_echo_good_bad_examples():
"""spec §4b-2: 好差示例裸号组改回显确认形态 + 新增自编号/改数字差例。"""
src = _read_system_md()
assert "直接\"Got it, thanks!\"收下" in src # 差: 裸号直接收下
assert "自己拼号码" in src and "改动数字都是违规" in src # 差: 自编/改数字
assert "一个数字都不改" in src # 好: 逐字照抄
def test_system_md_contains_verbatim_echo_bodies():
"""同源断言迁移(Task 5/4b-6): 回显确认句以统一样例号 format 后逐字在
system.md(引导策略节+好差示例——两处逐字指令漂移会让 GLM 混合输出两种
措辞); 邮箱轻补句正文沿用旧断言。"""
from app.engine.services.conversation import (
_CC_ECHO_EN, _CC_ECHO_ZH, _EMAIL_NOTE_EN, _EMAIL_NOTE_ZH)
src = _read_system_md()
sample = "+966 50 123 4567"
assert _CC_ECHO_EN.format(intl=sample) in src
assert _CC_ECHO_ZH.format(intl=sample) in src
for note in (_EMAIL_NOTE_EN, _EMAIL_NOTE_ZH):
body = _note_body(note)
assert body in src, body[:40]
def test_system_md_pseudo_echo_bad_example():
"""生产验收 r2 实测伪回显: AI 把 +966 5x xxx xxxx 掩码样例当客户号码回显
("Got your number +966 5x xxx xxxx")——好差示例补组钉死禁止。"""
src = _read_system_md()
assert "Got your number +966 5x xxx xxxx" in src # 差例逐字在场
assert "那不是客户的号码" in src # 差例定性
assert "掩码样例当号码回显" in src # 好例禁令