一、客服 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 生成的本地产物
243 lines
6.6 KiB
JSON
243 lines
6.6 KiB
JSON
{
|
||
"artifact": "t1b-tiers-and-derived-fields",
|
||
"date": "2026-09-18",
|
||
"decision_refs": [
|
||
"D-01",
|
||
"D-02",
|
||
"DEC-33",
|
||
"H-05"
|
||
],
|
||
"scope": "① 会签批准的 tiers 改造(登录客户可见 registered);② 补切片 family_id/param_class/intent 并重建重灌",
|
||
"code_changes": [
|
||
"app/core/knowledge_contracts.py: 新增 PUBLIC_TIER/REGISTERED_TIER/ALL_TIERS/TIERS_BY_SUBJECT/DEFAULT_TIERS + tiers_for_roles() + visibility_expression()",
|
||
"app/core/knowledge_schema.py: FIELD_CANDIDATES 新增 family_id / param_class",
|
||
"app/service/knowledge_search_service.py: search() 签名 include_internal: bool -> tiers: frozenset[str](必填无默认);_visibility_filter 删除;缺 visibility 字段的集合在受限档位下 fail-closed 跳过;KnowledgeHit 新增 3 字段",
|
||
"app/service/knowledge_tool.py: 用 tiers_for_roles(context.roles) 求值并下传;输出新增 3 字段",
|
||
"tools/build_knowledge_chunks.py: 派生 family_id(去掉两位行级后缀)/ param_class(最早出现的关键字类)/ intent(按集合映射)",
|
||
"tools/setup_milvus_knowledge_collections.py: VARCHAR_FIELDS 新增 family_id(64)/param_class(16)/intent(32)",
|
||
"tests + tools/seed_knowledge_r1r5_faq.py: 7 处调用点补 tiers"
|
||
],
|
||
"tiers_mapping": {
|
||
"visitor": [
|
||
"public"
|
||
],
|
||
"customer": [
|
||
"public",
|
||
"registered"
|
||
],
|
||
"admin(未在表内·收敛)": [
|
||
"public"
|
||
],
|
||
"advisor(未在表内·收敛)": [
|
||
"public"
|
||
],
|
||
"未知/空 roles(收敛)": [
|
||
"public"
|
||
]
|
||
},
|
||
"visibility_expression": {
|
||
"{public}": "visibility in [\"public\"]",
|
||
"{public, registered}": "None(不需要过滤)"
|
||
},
|
||
"dual_verification": {
|
||
"query": "高净值客户有什么权益",
|
||
"guest": {
|
||
"top1": "FAQ-0024",
|
||
"top1_visibility": "public",
|
||
"top_score": 0.5486,
|
||
"verdict": "低于 0.75 高置信门槛 -> 不答 / 引导登录 ✅"
|
||
},
|
||
"customer": {
|
||
"top1": "HNW-006",
|
||
"top1_visibility": "registered",
|
||
"top_score": 0.7604,
|
||
"verdict": "可召回 -> 能作答 ✅(改造前与访客完全相同,恒 0.5486)"
|
||
},
|
||
"public_query_baseline": {
|
||
"query": "基金赎回几天到账",
|
||
"guest_top1": "FAQ-0026",
|
||
"guest_top_score": 0.8446,
|
||
"customer_top1": "FAQ-0026",
|
||
"verdict": "公开问题召回与 A-03 基线一致 ✅"
|
||
}
|
||
},
|
||
"derived_fields": {
|
||
"param_class": {
|
||
"none": 453,
|
||
"scale": 38,
|
||
"threshold": 66,
|
||
"count": 4,
|
||
"rate": 67
|
||
},
|
||
"intent": {
|
||
"policy_explain": 288,
|
||
"product_inquiry": 191,
|
||
"faq": 149
|
||
},
|
||
"family_id_unique": 186,
|
||
"family_id_multi_block": 48,
|
||
"family_id_empty_or_mis_stripped": 0,
|
||
"sample": {
|
||
"POL-AST-009-01": {
|
||
"family_id": "POL-AST-009",
|
||
"param_class": "none",
|
||
"intent": "policy_explain"
|
||
},
|
||
"PROD-006-05": {
|
||
"family_id": "PROD-006",
|
||
"param_class": "threshold",
|
||
"intent": "product_inquiry"
|
||
},
|
||
"FAQ-0026": {
|
||
"family_id": "FAQ-0026",
|
||
"param_class": "threshold",
|
||
"intent": "faq"
|
||
},
|
||
"COMP-001": {
|
||
"family_id": "COMP-001",
|
||
"param_class": "threshold",
|
||
"intent": "faq"
|
||
}
|
||
}
|
||
},
|
||
"milvus_live": {
|
||
"fin_faq_collection": {
|
||
"row_count": 149,
|
||
"unique_doc_id": 149,
|
||
"fields": [
|
||
"doc_id",
|
||
"title",
|
||
"content",
|
||
"chapter",
|
||
"section",
|
||
"tags",
|
||
"doc_no",
|
||
"version",
|
||
"effective_date",
|
||
"expire_date",
|
||
"source_url",
|
||
"reviewer",
|
||
"source_file",
|
||
"family_id",
|
||
"param_class",
|
||
"intent",
|
||
"visibility",
|
||
"embedding"
|
||
],
|
||
"field_count": 18,
|
||
"num_partitions": 16,
|
||
"visibility": {
|
||
"public": 139,
|
||
"registered": 10
|
||
},
|
||
"param_class": {
|
||
"threshold": 17,
|
||
"none": 106,
|
||
"scale": 18,
|
||
"count": 2,
|
||
"rate": 6
|
||
},
|
||
"family_id_unique": 86
|
||
},
|
||
"fin_policy_collection": {
|
||
"row_count": 288,
|
||
"unique_doc_id": 288,
|
||
"fields": [
|
||
"doc_id",
|
||
"title",
|
||
"content",
|
||
"chapter",
|
||
"section",
|
||
"tags",
|
||
"doc_no",
|
||
"version",
|
||
"effective_date",
|
||
"expire_date",
|
||
"source_url",
|
||
"reviewer",
|
||
"source_file",
|
||
"family_id",
|
||
"param_class",
|
||
"intent",
|
||
"visibility",
|
||
"embedding"
|
||
],
|
||
"field_count": 18,
|
||
"num_partitions": 16,
|
||
"visibility": {
|
||
"public": 288
|
||
},
|
||
"param_class": {
|
||
"none": 232,
|
||
"scale": 9,
|
||
"threshold": 24,
|
||
"count": 2,
|
||
"rate": 21
|
||
},
|
||
"family_id_unique": 75
|
||
},
|
||
"fin_product_collection": {
|
||
"row_count": 191,
|
||
"unique_doc_id": 191,
|
||
"fields": [
|
||
"doc_id",
|
||
"title",
|
||
"content",
|
||
"chapter",
|
||
"section",
|
||
"tags",
|
||
"doc_no",
|
||
"version",
|
||
"effective_date",
|
||
"expire_date",
|
||
"source_url",
|
||
"reviewer",
|
||
"source_file",
|
||
"family_id",
|
||
"param_class",
|
||
"intent",
|
||
"visibility",
|
||
"embedding"
|
||
],
|
||
"field_count": 18,
|
||
"num_partitions": 16,
|
||
"visibility": {
|
||
"registered": 15,
|
||
"public": 176
|
||
},
|
||
"param_class": {
|
||
"threshold": 25,
|
||
"none": 115,
|
||
"scale": 11,
|
||
"rate": 40
|
||
},
|
||
"family_id_unique": 25
|
||
}
|
||
},
|
||
"reload_self_check": {
|
||
"result": "7/7 命中",
|
||
"truncated_fields": "无",
|
||
"samples": [
|
||
"FAQ-0026 0.870",
|
||
"POL-AST-012-01 0.792",
|
||
"FAQ-0019 0.612",
|
||
"PROD-006-05 0.695",
|
||
"FAQ-0036 0.847",
|
||
"FAQ-0022 0.848",
|
||
"HNW-005 0.749"
|
||
]
|
||
},
|
||
"gate_rerun": {
|
||
"pytest": "7 failed, 1441 passed, 2 skipped(与基线逐项相同)",
|
||
"ruff": "22 errors(与基线相同)",
|
||
"mypy": "3 errors(与基线相同)",
|
||
"check_authoritative_docs": "0",
|
||
"audit_schema": "0(89 张业务表)",
|
||
"verdict": "相对 T0 基线 0 回归"
|
||
},
|
||
"known_gaps": [
|
||
"admin / advisor / operator 不在 TIERS_BY_SUBJECT 表内,按收敛规则只得 {public} —— 是否放宽属权限决策,未擅自扩张",
|
||
"端到端(Agent 层)验证无法进行:customer_service 未在 AgentFactory 注册(客服业务层已于 2026-09-16 整体清除),且访客创建会话被拒(403 AGENT_PERMISSION_DENIED,属未会签的组 2 访客鉴权)",
|
||
"Milvus row_count 为压缩前乐观计数,观测值可能短暂虚高(前次已自愈)"
|
||
]
|
||
} |