一、客服 Agent 智能增强(正面回应"不智能、动不动就转人工")
- 决策链由 2 个出口扩到 5 个:E1 澄清 / E2 计算型 / E3 知识直返 / E4 证据约束生成 / E5 分级回退
- 转人工从"默认动作"降为最后一档 E5c,只保留 4 类白名单:
P0 反诈 / P1 账户与个人数据 / P2 写操作与争议 / 用户明确要求人工
- 46 条金标实测(修复前 → 修复后):
转人工率 43.5% → 10.9%;出口准确率 45.7% → 100%;事实正确率 69.6% → 100%
禁忌违反 1 → 0;档位越权 / 无出处数字 / 误拒 四项零容忍全 0
- 安全不变量 INV-1~INV-5;零容忍规则未删,改的是挂载点
(输出侧字面黑名单 → 检索层档位隔离 + 判定层合规词表 + 输出守护)
二、知识库:档位单点化与物理隔离
- 新增 app/core/knowledge_tier.py 作为档位规则唯一落点(G-03),
knowledge_contracts.py 原定义块改为显式再导出(X as X,非副本)
- 档位过滤由 bool 默认值(fail-open)改为 tiers 必填集合(缺参即 TypeError)
- Milvus 侧四集合按 visibility 分区键物理隔离;双 schema 收敛为一套
- 新增 app/core/actor.py:访客三元组与匿名判定的唯一构造/判定点(G-01/G-01b)
- 新增 app/core/fund_fee_rules.py:费率计算纯函数
三、前端入参边界对齐(本轮 W11 新修,4 处"校验宽于存储")
- message 加 max_length=8000(与浮窗 widget.js 的 maxlength 一致)
- session_id 加 1—64;idempotency_key 上限 128 → 64(对齐列宽 String(64))
- feedback_type 加 max_length=32(对齐列宽 String(32))
- 8 条路径参数补 min_length=1 + max_length=64 + 字符集正则
({session_id} / {run_id} / {handover_id})
- 改前超限值会落到 MySQL 才失败(500);改后一律 422 AGENT_INPUT_INVALID + 字段级定位
- 新增 tests/unit/api/test_frontend_boundaries.py(33 例),含"端点表 ↔ OpenAPI 全量对照"
四、投顾模块整体清除(D4.4 / D4.5)
- 删除投顾相关 controller / schema / model / repository / service 及门户页面
- tools/portal_api_check.py 同步作废 AD003/AD005/AD011/A047 四条用例与 advisor_t 登录
(端点与账号均已不存在,此前稳定报 3 条假红)
五、验证(提交前实测)
- pytest -q:1856 passed / 2 skipped / 0 failed
- ruff check app tools tests:19(= 基线);mypy app:2(= 基线)
- 前端接口契约体检 portal_api_check.py:38 项,通过 34,失败 0,跳过 4
- 全链路冒烟 e2e_smoke_test.py --read-only:31/31
- HTTP 全链路探针 http_probe.py:11/11 succeeded
- 跨文档一致性 _consistency.py:GATE PASS
- 真机边界复验 12 条:12/12 符合预期
六、纪律与文档
- 可改文件白名单 A-09(docs/46)与底座会签申请单 A-10(docs/47,组 1—组 4 全部受理)
- 零 DDL:未新增/修改任何表结构,89 张业务表与基线一致
- 证据留痕:docs/evidence/**(含 46 条金标 score、快照、清除与重建记录)
- 未提交(刻意排除,见提交说明):仓库内 客服agent/ 与 开发文档/ 是 2026-09-16 前的
过期副本(Todolist 440 行 vs 权威 D2.1 1167 行),权威正本在仓库外;
_chunks_report.txt 是 tools/build_knowledge_chunks.py 生成的本地产物
207 lines
8.6 KiB
JSON
207 lines
8.6 KiB
JSON
{
|
||
"artifact": "t2g-c09-visitor-advice-guard",
|
||
"generated_at": "2026-09-18T12:49:24.354760+00:00",
|
||
"date_local": "2026-09-18",
|
||
"purpose": "执行 C-09「访客侧推介边界」(关键路径 C-01 → C-03 → C-09 → C-06 的第三步)",
|
||
"scope": [
|
||
"app/core/customer_service_rules.py(业务层)",
|
||
"app/service/agent/implementations/customer_service.py(业务层)"
|
||
],
|
||
"hit_signature_boundary": {
|
||
"input_side": "route_message() 的 PROMOTION_REQUEST_PATTERNS 与身份**无关**:访客与客户都被拦下并拿到 ADVICE_BOUNDARY_REPLY(C-01~C-03 已落地)",
|
||
"why_not_visitor_only": "输入侧按身份分化会让**已登录客户**拿到推介内容(知识块里真实存在配置建议),而 MVP 第 1 步要求客服无投资建议类内容。做成身份无关是**更严的超集**,不削弱任何红线。",
|
||
"output_side": "按 DoD ② 严格分化:护栏**只作用于访客**(`visitor` in context.roles),客户侧完全不套用",
|
||
"flagged_for_user": "若你本意是「输入侧也仅对访客生效」,改动量是 route_message 增加一个身份参数 —— 属另一处口径变更,本轮未做"
|
||
},
|
||
"implementation": {
|
||
"VISITOR_ADVICE_PATTERNS": [
|
||
"(推荐|建议)[^。;!?,,]{0,6}(购买|买入|申购|赎回|卖出|投资|配置|入手)",
|
||
"(为您|给你|我们)?推荐[^。;!?,,]{0,6}(基金|产品|组合|标的|理财)",
|
||
"(更|最)?适合(您|你)",
|
||
"(收益|回报|业绩|涨幅|净值)[^。;!?,,]{0,4}(最高|最好|最优|第一|排名)",
|
||
"(最值得|最划算)[^。;!?,,]{0,2}(买|购买|投资|入手)",
|
||
"(排名|排行)(第一|首位|前列)"
|
||
],
|
||
"visitor_advice_violation": "复用底座 compliance_context.is_prohibited_context 做语境豁免(询问/否定/引用),判定口径只此一处",
|
||
"agent_hook": "CustomerServiceAgent.handle() → _route_and_answer() + _guard_visitor_advice();原 handle 主体改名为 _route_and_answer,保证**所有出口**都过护栏",
|
||
"on_hit": "整条换成 ADVICE_BOUNDARY_REPLY,且 transfer_required=False / transfer_reason=None(不建单:访客没有工单承接方)",
|
||
"single_source": "名单与边界话术都只在业务层规则文件,底座不复制 —— 避免治理层注释里警告过的那类『常量各写一份必然漂移』"
|
||
},
|
||
"why_narrow": {
|
||
"不收的表述": [
|
||
"推荐",
|
||
"适合您"
|
||
],
|
||
"推荐二字本身": "政策原文「不得登载推荐性文字」含该词,连它一起拦会把合规问答整条打成边界话术",
|
||
"可以买入": "操作性问答「交易时间内可以买入,T+1 确认份额」会被误伤;名单只收『推荐/建议 + 交易动作』",
|
||
"持有": "产品字段标签「建议持有期限」不是建议"
|
||
},
|
||
"probe": {
|
||
"cases": 10,
|
||
"mismatch_count": 0,
|
||
"mismatch": [],
|
||
"rows": [
|
||
{
|
||
"text": "稳健型客户建议配置:货币基金 30% + 纯债基金 50%",
|
||
"expected_hit": true,
|
||
"actual": "建议配置",
|
||
"note": "配置指向",
|
||
"ok": true
|
||
},
|
||
{
|
||
"text": "该产品更适合您",
|
||
"expected_hit": true,
|
||
"actual": "更适合您",
|
||
"note": "适合性结论",
|
||
"ok": true
|
||
},
|
||
{
|
||
"text": "这只基金收益最高",
|
||
"expected_hit": true,
|
||
"actual": "收益最高",
|
||
"note": "排序性表述",
|
||
"ok": true
|
||
},
|
||
{
|
||
"text": "为您推荐的产品如下",
|
||
"expected_hit": true,
|
||
"actual": "为您推荐的产品",
|
||
"note": "指向具体标的的推荐",
|
||
"ok": true
|
||
},
|
||
{
|
||
"text": "建议您购买南方现金添利货币基金",
|
||
"expected_hit": true,
|
||
"actual": "建议您购买",
|
||
"note": "购买指向",
|
||
"ok": true
|
||
},
|
||
{
|
||
"text": "是否适合您需要结合风险测评,不能在这里下结论",
|
||
"expected_hit": false,
|
||
"actual": null,
|
||
"note": "询问/否定语境",
|
||
"ok": true
|
||
},
|
||
{
|
||
"text": "产品建议持有期限 6 个月",
|
||
"expected_hit": false,
|
||
"actual": null,
|
||
"note": "字段标签",
|
||
"ok": true
|
||
},
|
||
{
|
||
"text": "不得登载其他单位或个人的推荐性文字、图片等",
|
||
"expected_hit": false,
|
||
"actual": null,
|
||
"note": "政策原文里的『推荐』二字",
|
||
"ok": true
|
||
},
|
||
{
|
||
"text": "交易时间内可以买入,T+1 确认份额",
|
||
"expected_hit": false,
|
||
"actual": null,
|
||
"note": "操作性问答",
|
||
"ok": true
|
||
},
|
||
{
|
||
"text": "货币基金风险等级 R1,1 元起投,赎回 T+1 到账",
|
||
"expected_hit": false,
|
||
"actual": null,
|
||
"note": "纯公开资料",
|
||
"ok": true
|
||
}
|
||
]
|
||
},
|
||
"chunk_scan": {
|
||
"chunk_total": 628,
|
||
"per_pattern": [
|
||
{
|
||
"index": 1,
|
||
"pattern": "(推荐|建议)[^。;!?,,]{0,6}(购买|买入|申购|赎回|卖出|投资|配置|入手)",
|
||
"chunks_hit": 4,
|
||
"hits": [
|
||
{
|
||
"doc_id": "PROD-012",
|
||
"visibility": "public",
|
||
"source_file": "product/个人理财产品手册.md",
|
||
"hit": "建议配置",
|
||
"snippet": "属违规行为。 / / **保守型客户(C1)** / / - 建议配置:货币基金 60% + 纯债基金 40% / - 目标"
|
||
},
|
||
{
|
||
"doc_id": "PROD-012",
|
||
"visibility": "public",
|
||
"source_file": "product/个人理财产品手册.md",
|
||
"hit": "建议配置",
|
||
"snippet": "%—3.0% / / **稳健型客户(C2)** / / - 建议配置:货币基金 30% + 纯债基金 50% + 混合"
|
||
},
|
||
{
|
||
"doc_id": "PROD-012",
|
||
"visibility": "public",
|
||
"source_file": "product/个人理财产品手册.md",
|
||
"hit": "建议配置",
|
||
"snippet": "%—5.0% / / **平衡型客户(C3)** / / - 建议配置:纯债基金 30% + 混合基金 45% + 股票"
|
||
},
|
||
{
|
||
"doc_id": "PROD-012",
|
||
"visibility": "public",
|
||
"source_file": "product/个人理财产品手册.md",
|
||
"hit": "建议配置",
|
||
"snippet": ".5% / / **进取型客户(C4/C5)** / / - 建议配置:混合基金 35% + 股票基金 35% + QD"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"index": 2,
|
||
"pattern": "(为您|给你|我们)?推荐[^。;!?,,]{0,6}(基金|产品|组合|标的|理财)",
|
||
"chunks_hit": 0,
|
||
"hits": []
|
||
},
|
||
{
|
||
"index": 3,
|
||
"pattern": "(更|最)?适合(您|你)",
|
||
"chunks_hit": 0,
|
||
"hits": []
|
||
},
|
||
{
|
||
"index": 4,
|
||
"pattern": "(收益|回报|业绩|涨幅|净值)[^。;!?,,]{0,4}(最高|最好|最优|第一|排名)",
|
||
"chunks_hit": 0,
|
||
"hits": []
|
||
},
|
||
{
|
||
"index": 5,
|
||
"pattern": "(最值得|最划算)[^。;!?,,]{0,2}(买|购买|投资|入手)",
|
||
"chunks_hit": 0,
|
||
"hits": []
|
||
},
|
||
{
|
||
"index": 6,
|
||
"pattern": "(排名|排行)(第一|首位|前列)",
|
||
"chunks_hit": 0,
|
||
"hits": []
|
||
}
|
||
]
|
||
},
|
||
"knowledge_defect_found": {
|
||
"doc_id": "PROD-012",
|
||
"title": "产品手册 · 四、产品对比表与推荐策略 · 4.2 按客户类型的推荐策略",
|
||
"source_file": "product/个人理财产品手册.md",
|
||
"visibility": "public",
|
||
"content_hit": "建议配置:货币基金 60% + 纯债基金 40%(C1)… 等四档配置比例",
|
||
"verdict": "public 档携带**投资建议类内容**,与 MVP 第 1 步「游客线无投资建议类内容」冲突;运行时已被访客护栏挡住,故不是运行期漏洞,但属**语料缺陷**(该块对访客永远不可用)",
|
||
"recommendation": "登记为决策项:修语料(下线该节或降为非 public 档)需要补切片 + 重建集合 + 重跑检索自检,属知识侧动作,建议与 F-05 回写合并或单独立项"
|
||
},
|
||
"tests": {
|
||
"rules_level": "5 例真阳性 + 5 例克制用例(test_visitor_advice_violation_detects_advice / ..._ignores_non_advice)",
|
||
"agent_level": "4 例(访客被替换 / 客户原样 / 无措辞原样 / 边界话术不自绊)",
|
||
"targeted": "2 文件 69 passed"
|
||
},
|
||
"gate": {
|
||
"pytest": "2 failed / 1534 passed / 2 skipped(失败集与 T0 基线同一组)",
|
||
"ruff": "22(改动文件 All checks passed)",
|
||
"mypy": "3(无新增)",
|
||
"docs": "50 documents, no number collision",
|
||
"schema": "89 business tables passed"
|
||
}
|
||
} |