test: PromptProvider 审查修复(组装缝断言/占位符约定文档与glob守护/边界注记)
- I-1: test_company_facts 捕获完整 prompt 的用例补话术池注入断言
("- EN:"/"- ZH:" 分组行在场)——守 AIService 组装缝,防 Task 9
重接提示词线时静默丢池
- I-2: seed_profiles/README.md 落档 $DEFLECTION_POOL 占位符约定
(缺失 = 话术池静默不注入);test_prompt_provider 占位符防漂移改
glob 遍历 seed_profiles/*/prompts/system.md,第三租户自动纳管
(空 glob 显性兜底,防假守护)
- Minor-1 注记: _format_deflection_pool docstring 记已知边界——条目
含引号/换行暂不转义,Phase 2 编辑器批次处理
- Minor-5: test_provider_loads_from_tenant_dir 删恒真 or 侧,改单一
明确断言;registry 加载期显性失败清单补 prompts 读取失败
(FileNotFoundError 说明);conftest build_jiancai_runtime 注明
data_dir 仅占位、从不 ensure_ready
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,8 @@ def _format_deflection_pool(deflections) -> str:
|
|||||||
紧凑不膨胀(设计 R1: 话术单一事实源,提示词侧只引用不复制)。
|
紧凑不膨胀(设计 R1: 话术单一事实源,提示词侧只引用不复制)。
|
||||||
只渲染主池(deflections);deflections_contact 是已留资态的墙替换池,
|
只渲染主池(deflections);deflections_contact 是已留资态的墙替换池,
|
||||||
本就不属于 system.md 教学内容,不注入。
|
本就不属于 system.md 教学内容,不注入。
|
||||||
|
已知边界(审查 Minor-1 注记): 条目自身含双引号/换行时暂不转义——
|
||||||
|
现网池线均为单行纯文本,Phase 2 后台编辑器批次统一处理(输入校验+转义)。
|
||||||
"""
|
"""
|
||||||
pools = dict(deflections or {})
|
pools = dict(deflections or {})
|
||||||
langs = [l for l in _DEFLECTION_LANG_ORDER if pools.get(l)]
|
langs = [l for l in _DEFLECTION_LANG_ORDER if pools.get(l)]
|
||||||
|
|||||||
@@ -135,7 +135,9 @@ class TenantRegistry:
|
|||||||
|
|
||||||
加载期显性失败(不流入运行期):目录无任何 tenant.json(seed_dir
|
加载期显性失败(不流入运行期):目录无任何 tenant.json(seed_dir
|
||||||
路径拼错→静默空注册表→全量 404,必须炸)、无效 JSON、slug 与目录
|
路径拼错→静默空注册表→全量 404,必须炸)、无效 JSON、slug 与目录
|
||||||
名不一致、零站点、wall 编译错误、域名重复绑定。
|
名不一致、零站点、wall 编译错误、域名重复绑定、prompts 读取失败
|
||||||
|
(Task 6: prompts/ 目录缺失或四件套不齐 → PromptProvider.from_dir
|
||||||
|
的 FileNotFoundError,加载即炸,不流入运行期)。
|
||||||
"""
|
"""
|
||||||
reg = cls()
|
reg = cls()
|
||||||
reg._seed_dir = pathlib.Path(seed_dir)
|
reg._seed_dir = pathlib.Path(seed_dir)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ seed_profiles/<slug>/
|
|||||||
- **空域名 + `data-site`**:`es` 站 `"domains": []`,与 main 共用挂件域名,嵌入代码以 `data-site="es"` 参数选择站点。
|
- **空域名 + `data-site`**:`es` 站 `"domains": []`,与 main 共用挂件域名,嵌入代码以 `data-site="es"` 参数选择站点。
|
||||||
- **`site.brand` 是覆盖层**:缺省项继承 `config.brand`(深合并),只覆盖门面(标题/欢迎语等);AI 脑子与线索管道留在租户级。
|
- **`site.brand` 是覆盖层**:缺省项继承 `config.brand`(深合并),只覆盖门面(标题/欢迎语等);AI 脑子与线索管道留在租户级。
|
||||||
- **wall 不写在 tenant.json 里**:加载器会把同目录 `wall.json` **隐式并入** `config["wall"]`(原始词表,供后台编辑/回滚),编译产物挂 runtime 的 `compiled_wall` 供引擎消费——词表数据源只有 wall.json 一份。
|
- **wall 不写在 tenant.json 里**:加载器会把同目录 `wall.json` **隐式并入** `config["wall"]`(原始词表,供后台编辑/回滚),编译产物挂 runtime 的 `compiled_wall` 供引擎消费——词表数据源只有 wall.json 一份。
|
||||||
- **`config` 内不含 prompts**:提示词由目录内 `prompts/*.md` 提供(Task 6)。
|
- **`config` 内不含 prompts**:提示词由目录内 `prompts/*.md` 提供(Task 6);**system.md 必须包含 `$DEFLECTION_POOL` 占位符**——组装时注入 wall.json 的 deflections 话术池(缺失 = 话术池静默不注入;test_prompt_provider 以 glob 遍历守护全部租户)。
|
||||||
- 加载期显性失败(不流入运行期):无效 JSON、slug 与目录名不一致、零站点、wall 编译错误、域名跨站点/跨租户重复绑定。
|
- 加载期显性失败(不流入运行期):无效 JSON、slug 与目录名不一致、零站点、wall 编译错误、域名跨站点/跨租户重复绑定。
|
||||||
|
|
||||||
## 纪律
|
## 纪律
|
||||||
|
|||||||
+2
-1
@@ -82,7 +82,8 @@ def build_jiancai_runtime():
|
|||||||
engine/session_factory 保持 None: 直连测试自管 async_db(NullPool 跨
|
engine/session_factory 保持 None: 直连测试自管 async_db(NullPool 跨
|
||||||
循环纪律),manager.session_factory 为 None 时 lead_push_service 回退
|
循环纪律),manager.session_factory 为 None 时 lead_push_service 回退
|
||||||
模块级兜底,与旧 runtime=None 行为一致。无 engine 即无句柄,无需清理;
|
模块级兜底,与旧 runtime=None 行为一致。无 engine 即无句柄,无需清理;
|
||||||
data_dir 仅拼 db_path 字符串(无 IO),模块级缓存单例跨测试复用。
|
data_dir 仅占位(只拼 db_path 字符串,无任何 IO——从不 ensure_ready,
|
||||||
|
不会创建 tenants/ 目录或库文件),模块级缓存单例跨测试复用。
|
||||||
"""
|
"""
|
||||||
global _JIANCAI_RUNTIME
|
global _JIANCAI_RUNTIME
|
||||||
if _JIANCAI_RUNTIME is None:
|
if _JIANCAI_RUNTIME is None:
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ def test_facts_concatenated_between_system_and_context():
|
|||||||
asyncio.run(svc.chat([{"role": "user", "content": "hi"}], context="⚠️ 提醒"))
|
asyncio.run(svc.chat([{"role": "user", "content": "hi"}], context="⚠️ 提醒"))
|
||||||
p = svc.provider.prompts[0]
|
p = svc.provider.prompts[0]
|
||||||
assert "HESUPIPE" in p and "HDPE" in p # 建材事实在场
|
assert "HESUPIPE" in p and "HDPE" in p # 建材事实在场
|
||||||
|
# 审查 I-1: AIService 组装缝守护——默认服务的 $DEFLECTION_POOL 话术池
|
||||||
|
# 必须真实注入(锚分组行格式而非具体话术,话术内容随墙演进而变);
|
||||||
|
# 防 Task 9 重接提示词线时静默丢池
|
||||||
|
assert "- EN:" in p and "- ZH:" in p
|
||||||
# Task 6: system 组装含 $DEFLECTION_POOL 话术池注入,SYSTEM_PROMPT 原文
|
# Task 6: system 组装含 $DEFLECTION_POOL 话术池注入,SYSTEM_PROMPT 原文
|
||||||
# 不再是组装结果的连续子串——改以首行/事实卡标题锚定顺序(语义等价)
|
# 不再是组装结果的连续子串——改以首行/事实卡标题锚定顺序(语义等价)
|
||||||
assert (p.index(SYSTEM_PROMPT.splitlines()[0])
|
assert (p.index(SYSTEM_PROMPT.splitlines()[0])
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ def _wall(slug: str) -> dict:
|
|||||||
|
|
||||||
def test_provider_loads_from_tenant_dir():
|
def test_provider_loads_from_tenant_dir():
|
||||||
p = PromptProvider.from_dir(JC_PROMPTS)
|
p = PromptProvider.from_dir(JC_PROMPTS)
|
||||||
assert "HESUPIPE" in p.company_facts or "管道" in p.system
|
assert "HESUPIPE" in p.company_facts # jiancai 事实卡身份标记(审查 Minor-5: 删恒真 or 侧)
|
||||||
|
|
||||||
|
|
||||||
def test_provider_reads_all_four_prompts():
|
def test_provider_reads_all_four_prompts():
|
||||||
@@ -57,9 +57,13 @@ def test_system_prompt_injects_deflection_pool():
|
|||||||
|
|
||||||
|
|
||||||
def test_system_md_carries_placeholder():
|
def test_system_md_carries_placeholder():
|
||||||
# 防漂移锚: 两租户 system.md 必须保留占位符,丢了它话术池就静默失联
|
# 防漂移锚(审查 I-2): glob 遍历全部租户 system.md——第三租户落地即自动
|
||||||
for prompts_dir in (JC_PROMPTS, AUTO_PROMPTS):
|
# 纳管(约定同步落档 seed_profiles/README.md: 缺占位符 = 话术池静默不注入);
|
||||||
assert "$DEFLECTION_POOL" in PromptProvider.from_dir(prompts_dir).system
|
# 空 glob 恒绿 = 假守护,先断言至少一份
|
||||||
|
system_mds = sorted((REPO / "seed_profiles").glob("*/prompts/system.md"))
|
||||||
|
assert system_mds
|
||||||
|
for md in system_mds:
|
||||||
|
assert "$DEFLECTION_POOL" in md.read_text(encoding="utf-8"), md
|
||||||
|
|
||||||
|
|
||||||
def test_build_system_appends_facts_after_system():
|
def test_build_system_appends_facts_after_system():
|
||||||
|
|||||||
Reference in New Issue
Block a user