From 8268646b0c8cc135abaa687737aef2866cc3ceb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=BF=E4=BA=91=E7=A7=8B=E6=9C=88?= <15273589815@163.com> Date: Fri, 11 Sep 2026 19:52:08 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AD=94=E5=A4=8D=E6=96=87=E6=A1=A3=E8=A1=A5?= =?UTF-8?q?=E5=85=85=20=C2=A78=EF=BC=9A=E4=B8=A4=E4=B8=AA=E6=97=A2?= =?UTF-8?q?=E6=9C=89=E5=8F=91=E5=B8=83=E8=84=9A=E6=9C=AC=E4=BC=9A=E4=B8=A2?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E8=AF=8D=EF=BC=88=E5=86=99=E8=A1=A5=E5=8F=91?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E6=97=B6=E5=8F=91=E7=8E=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit publish_customer_service_config.py 与 publish_risk_agent_config.py 的 active_config_items() 都自己写 SQL、只查 platform_config_item,而 ConfigReleaseService.effective_snapshot() 要读全部三张受管表。用它们发版会把生效版本里的 提示词一起清掉 —— 且没有任何声音:_warn_dropped_items() 只告警不阻断激活,Agent 侧 _chitchat_prompt 有兜底会回落代码默认值,功能看着正常(与 release 174 那次事故同型)。 已在答复文档里建议改用 effective_snapshot(),并列出三个细节:同 key 覆盖(对方已修)、 JSON 列必须归一化(SELECT * 读出来可能是字符串,不解析会静默走进"没有该 key"分支)、 提示词搬家要重分配 version 且按 PromptPayload 字段挑(漏 input_schema/output_schema 即丢)。 另提醒时序:admin 端校验「配置 ⊆ 代码 allowed_tools」,画像工具那一版必须等代码合并后才能发, 否则 422 且报错只有"配置超出 Agent 工具上限"。 --- docs/NL_develop评审回复-架构师答复.md | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/docs/NL_develop评审回复-架构师答复.md b/docs/NL_develop评审回复-架构师答复.md index 427f008..3be72ac 100644 --- a/docs/NL_develop评审回复-架构师答复.md +++ b/docs/NL_develop评审回复-架构师答复.md @@ -210,3 +210,48 @@ alembic:current = heads = 20260911_risk_rule_index ← 单一 head,只有 > 最后回应你 §1.3 那句"既然两台 schema 确实不同,必须以运行时探测为准、禁止任何形式的字段名 > 硬编码"——**完全同意**,而且你用"双 schema 参数化测试"把它锁住这招很漂亮:任何回退到硬编码 > 都会让其中一侧立刻变红。比我原来担心的"靠人记住"可靠得多。 + +--- + +## 8. 补充发现(写补发脚本时挖出来的):两个发布脚本会**丢提示词** + +我按你提醒的"同 key 覆盖"去写补发脚本时,顺手核了一下**继承源**,发现一个真问题: + +`tools/publish_customer_service_config.py` 与 `tools/publish_risk_agent_config.py` 的 +`active_config_items()` 都是**自己写 SQL、只查 `platform_config_item`**: + +```sql +SELECT i.namespace, i.config_key, i.value_json, i.schema_version +FROM platform_config_item i JOIN config_release r ON r.id = i.release_id +WHERE r.status = 'active' +``` + +而 `ConfigReleaseService.effective_snapshot()` 的文档字符串写得很清楚 —— 你自己在 +`publish_chitchat_prompt.py` 里也引用过这条: + +> 快照读的是**全部三张**受管表(`platform_config_item` / `prompt_template_version` / +> `model_routing_rule`),**漏读一张就是一次静默失效** —— 这次的事故正是这么来的。 + +**⇒ 用这两个脚本发版,会把生效版本里的提示词一起清掉。**(本环境 201 里有 1 条 +`customer_service_chitchat` v2。) + +而且这个失败**没有任何声音**:`_warn_dropped_items()` 只告警、不阻断激活,Agent 侧 +`_chitchat_prompt` 又有逐字段兜底、会回落代码默认值 —— **功能看着正常**, +和 release 174 那次事故一模一样。 + +**建议**:把这两个脚本的 `active_config_items()` 换成 +`ConfigReleaseService(session).effective_snapshot()`。我已经在新的 +`tools/publish_profile_tool_whitelist.py` 里这么做了,顺带处理了三个细节,供你参考: + +1. **同 key 覆盖**(你已经修了,很好); +2. **JSON 列必须归一化** —— `SELECT *` 读出来的 `value_json` 可能是**字符串**, + 不 `json.loads` 的话 `isinstance(value, dict)` 为假,脚本会**静默**走到"生效版本里没有 + 该 key"那条分支。我第一版就踩了这个,靠加诊断打印才定位到(表现出来像"配置缺失"); +3. **提示词搬家要重分配 `version`**(唯一键含 version),并按 `PromptPayload` 的 9 个字段 + 挑字段 —— 表里的 `checksum`/`created_by`/`created_at` 是服务端生成的不能搬, + 而 `input_schema`/`output_schema` 是 API 收的、漏了就丢。 + +**时序提醒**:admin 端校验「配置 ⊆ 代码 `allowed_tools`」(`app/service/admin_service.py:219-220`), +所以**画像工具那一版必须在你的代码合并进来之后才能发**,否则必然 422,而报错只有 +"配置超出 Agent 工具上限"(看不出是时序问题)。我在脚本里加了前置自检:合并前跑会直接中止 +并说明原因,而不是抛出那个费解的校验错。