Files
group_fqcd_jr/docs/customer-service-routing-legacy-keywords.md
张胜宇 e239eb778b docs: 品牌全量口径统一为「南方基金」+ 作废文档清理
1) 客服 Agent 四份交付文档 + 构建脚手架:品牌由包装占位 XX科技 / 旧名 南方财富
   统一为南方基金(热线 400-889-8899 / 官网 nffund.com),系统名改为「智能服务系统」;
   同步追加 §0.4 修订记录行,工程记录行保留原占位字面以支撑硬编码扫描验收。
2) 开发文档:清理 28 份已作废/残留文档(14 份移出归档 + 14 份仓库副本),
   新增《文档规整方案与开发前待决事项-2026-09-17》。
3) 客服agent 四份交付文档首次纳入本分支。
2026-09-17 15:15:22 +08:00

160 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 一期客服确定性路由:关键词表留痕与迁移对照
> **日期**:2026-09-16
> **触发**:客服模块重构前代码清理(依据《客服与投顾模块重构前代码清理建议-2026-09-15.md》§二 A2/A3/B1/B2)
> **性质**:**留痕文档**。一期路由已删除,但其词表是这些拦截能力的**唯一存放处**,
> 故原样抄录于此,并给出逐条迁移去向。**不要只依赖 git 历史追溯**——本轮出现过
> "死代码里的能力被当成已实现"的误判,词表必须留在可检索的文档里。
>
> ## ⚠️ 2026-09-16 后续更新(形态A 模块级清除,必读)
>
> 上文 §一 写的「保留未删」**已被后续的客服模块整体删除推翻**:
>
> - `app/service/agent/customer_service_routing.py`(含 `chitchat_streak()` 与 `_CHITCHAT_*`)
> —— **整个文件已删除**,`chitchat_streak()` 不复存在。
> - 先期把 8 条提示词注入词迁移进去的 `app/core/customer_service_rules.py`
> —— **也随模块一并删除**。
>
> **后果(重建时必须补齐)**:本文件 §二 的词表现在是这些拦截能力**在本仓库中的唯一副本**。
> 以下能力当前**在生效路径上不存在**:
> 1. 提示词注入拦截(8 条词)—— 红队 RT-009/010 仍会失败;
> 2. 凭据披露拦截(`_SECURITY_DISCLOSURE_PHRASES`);
> 3. 安全关键词路由(`_SECURITY_KEYWORDS`)与零容忍词(`ZERO_TOLERANCE_WORDS`)。
>
> `app/service/agent_run_application_service.py` 的 `build_outbox_metadata()` 也不再覆写
> `chitchat_streak` / `clarification_round` / `session_context`(`AgentRequest` 上的字段仍在,
> 但已无写入方)。**重建客服 Agent 时按 §三 的对照表逐条恢复,并保留本文件作为验收基线。**
---
## 一、删除的是什么
| 项 | 位置(删除前) | 判定 |
|---|---|---|
| `CustomerServiceIntentRouter.classify()` | `app/service/agent/customer_service_routing.py` L40-65 | **全仓无调用方**。全仓 `.classify(` 仅命中 `app/service/agent/base.py:205` 的 `IntentClassifier.classify`(另一个类,无关) |
| `CustomerServiceRoute` | 同文件 L7-12 | 只在 `classify()` 内部被构造 10 次,无外部消费方 |
| 9 组关键词常量 | 同文件 L16-37 | 仅被 `classify()` 使用(`_CHITCHAT_*` 除外,见下) |
**关键事实(决定了本次删除的风险等级)**:`classify()` 无生产调用方,因此
**删除本身不产生任何行为变更**。它的真实代价不是"回归",而是"这些词表原本只存在于
一个不生效的位置"——例如提示词注入拦截的 8 条词**从未在任何生效路径上运行过**
(红队 RT-009/010 因此必然失败)。所以本次处置是**先迁移、后删除**,而不是只删除。
**保留未删**:`_CHITCHAT_MESSAGES`、`_CHITCHAT_PHRASES`(`chitchat_streak()` 依赖,
而 `chitchat_streak()` 被 `app/service/agent_run_application_service.py:57` 用于
组装 outbox 元数据的 `chitchat_streak` 字段)。二期路由 `app/core/customer_service_rules.route_message()`
(`customer_service.py:215` 调用)与 `IntentClassifier` 均已接管其余能力。
---
## 二、一期词表原样留痕(删除前的完整内容)
```python
_SECURITY_KEYWORDS = ("验证码", "密码泄露", "被盗", "诈骗", "非本人交易")
# 明确的凭据披露和提示词注入必须在知识检索前拦截,避免把攻击内容当作普通 FAQ。
_SECURITY_DISCLOSURE_PHRASES = ("密码是", "密码为", "我的密码", "验证码是", "验证码为")
_PROMPT_INJECTION_KEYWORDS = (
"忽略之前", "忽略所有规则", "系统提示词", "开发者消息", "泄露提示词", "越过限制",
"不要遵守规则", "显示内部指令",
)
_COMPLIANCE_KEYWORDS = ("推荐", "收益最高", "稳赚", "保本", "帮我买", "替我交易")
_ACCOUNT_KEYWORDS = ("持仓", "收益", "订单", "定投", "银行卡", "风险测评", "投诉进度")
_HUMAN_TRANSFER_KEYWORDS = ("转人工", "人工客服", "投诉", "赔偿", "法律", "纠纷")
_POLICY_KEYWORDS = (
"申购", "赎回", "到账", "费率", "手续费", "确认份额", "交易日", "分红", "规则", "政策"
)
_PRODUCT_KEYWORDS = (
"产品", "基金代码", "基金经理", "份额类别", "a类", "c类", "净值", "风险等级"
)
_REFERENCE_PHRASES = ("这个", "那个", "它的", "刚才", "上面", "前面", "这只", "那只")
# ↓ 以下两组已保留在原文件(chitchat_streak 在用),此处仅作对照
_CHITCHAT_MESSAGES = frozenset({
"你好", "您好", "嗨", "哈喽", "在吗", "谢谢", "谢谢你", "再见", "拜拜",
"你是谁", "你叫什么", "你今天开心吗",
})
_CHITCHAT_PHRASES = ("今天天气", "讲个笑话", "你几岁", "你开心吗", "你忙吗")
```
### 原 `classify()` 的判定顺序(供追溯语义用)
```
security(_SECURITY_KEYWORDS ∪ _SECURITY_DISCLOSURE_PHRASES) → intent=security_notice
→ _PROMPT_INJECTION_KEYWORDS → intent=compliance_refusal
→ _COMPLIANCE_KEYWORDS → intent=compliance_refusal
→ _ACCOUNT_KEYWORDS → intent=account_entry
→ _HUMAN_TRANSFER_KEYWORDS → intent=human_transfer
→ 闲聊 → intent=chitchat
→ _POLICY_KEYWORDS → knowledge_intents=(policy_explain,)
→ _PRODUCT_KEYWORDS → knowledge_intents=(product_inquiry,)
→ 兜底 → knowledge_intents=(faq,)
```
---
## 三、迁移对照表(逐条)
### 3.1 已迁入二期(本次完成)
| 一期条目 | 原属词表 | 二期落点 | 说明 |
|---|---|---|---|
| `非本人交易` | `_SECURITY_KEYWORDS` | `P0_KEYWORDS` | 二期 P0 原先只有「不是我本人操作」,该说法会漏到知识检索 |
| `替我交易` | `_COMPLIANCE_KEYWORDS` | `P2_KEYWORDS` | 不被 `P2_PATTERNS` 覆盖(句式白名单无「交易」二字),须用字面词补 |
| `纠纷` | `_HUMAN_TRANSFER_KEYWORDS` | `P2_KEYWORDS` | 投诉赔偿类的常见同义说法 |
| 8 条注入词(全部) | `_PROMPT_INJECTION_KEYWORDS` | **新增** `PROMPT_INJECTION_KEYWORDS` + `PROMPT_INJECTION_PRIORITY` + `PROMPT_INJECTION_REPLY` | 落地于 `route_message()`,位置在 **P0 之后、合规拦截之前**(混合输入先拿反诈话术) |
### 3.2 已被二期覆盖,无需迁移
| 一期条目 | 二期覆盖方式 |
|---|---|
| `验证码`、`密码泄露`、`被盗`、`诈骗`、`转账给`、`安全账户` 等 | 已在 `P0_KEYWORDS` |
| `密码是` / `密码为` / `我的密码` / `验证码是` / `验证码为` | 全部含「密码」或「验证码」子串,被 `P0_KEYWORDS` 覆盖 |
| `稳赚`、`保本` | 已在 `ZERO_TOLERANCE_WORDS`(输入侧) |
| `帮我买` | 已在 `P2_KEYWORDS` |
| `转人工`、`人工客服`、`投诉`、`赔偿`、`法律` | 已在 `P2_KEYWORDS` |
| `投诉进度` | 已在 `P1_KEYWORDS` |
| `风险测评` | `P1_KEYWORDS` 有「风险测评结果」(限定式) |
### 3.3 有意不迁(含理由)
| 一期条目 | 处置 | 理由 |
|---|---|---|
| `推荐` | **不迁**,交 Todolist **C-09**(访客侧推介边界) | C-09 的 DoD 明确把「推介请求句式」的**输入侧**识别限定在**访客**,且要求**客户侧行为不变**。现在若把它加进全局输入拦截,会改变客户侧行为,与 C-09 ③ 的回归要求正面冲突 |
| `收益最高` | **不迁**,交 Todolist **C-03 / C-05** | ① 它属「收益承诺 / 比较类」而非安全类;② 加入 `ZERO_TOLERANCE_WORDS` 会破坏 `tests/unit/core/test_customer_service_rules.py:87-92` 的 DB 镜像断言(那 11 条与库内 `agent_negative_word` 被断死相等);③ MVP 已定**输出侧**只拦收益比较与稀缺性,C-05(数据层)是设计指定的落点 |
| `持仓` / `收益` / `订单` / `定投` / `银行卡` 等**裸词**账户问法 | **不迁**,交 Todolist **C-03 ③** | 二期 P1 刻意用「我的持仓」这类**限定式**,避免把公开问题(「什么是持仓」)误判成本人账户查询。补裸词需配套设计,属 C-03 范围 |
| `_POLICY_KEYWORDS`、`_PRODUCT_KEYWORDS` | **不迁** | 其作用是产出 `knowledge_intents=(policy_explain/product_inquiry)`。二期意图由底座 `IntentClassifier` 产出,`INTENT_POLICY`/`INTENT_PRODUCT` 已在 `customer_service.py:44-45` 独立定义,不再需要关键词路由 |
| `_REFERENCE_PHRASES` | **不迁** | 原用于标记 `requires_context`;二期无此机制(会话上下文由 `customer_service_session_memory_service` 承担) |
---
## 四、本次改动清单
| 文件 | 动作 |
|---|---|
| `app/service/agent/customer_service_routing.py` | 删除 `classify()`、`CustomerServiceRoute`、9 组词表;保留 `chitchat_streak()` 与 `_CHITCHAT_*`(87 行 → 约 45 行) |
| `app/service/agent/customer_service_agent.py` | **整文件删除**(5 行向后兼容桩,生产零引用) |
| `app/core/customer_service_rules.py` | 新增 `PROMPT_INJECTION_KEYWORDS` / `PROMPT_INJECTION_PRIORITY` / `PROMPT_INJECTION_REPLY` + 注入拦截分支;`P0_KEYWORDS` 补 `非本人交易`;`P2_KEYWORDS` 补 `替我交易`、`纠纷` |
| `tests/unit/service/test_agent_governance.py` | import 从 `customer_service_agent` 改为 `implementations.customer_service` |
| `tests/unit/core/test_customer_service_rules.py` | 新话术纳入 `REPLY_CONSTANTS`(过"自绊检查"+ 带官方联系方式两条守卫);新增注入拦截 / 混合优先级 / 迁移词回归共 4 组用例 |
| 本文件 | 新增(留痕) |
---
## 五、验证方式与本次限制
设计上应执行 `docs/14` §13 的统一验收命令集。**本次的实际限制**:
- 本机 Managed Python 3.13.14 **未安装项目依赖**(pytest / fastapi / sqlalchemy / pydantic / redis / pymilvus 等全部 `ModuleNotFoundError`),仓库内**无 venv** → `pytest`、`ruff`、`mypy` **无法运行**。
- 因此本次实际执行的验证为:① 全量 `py_compile` 语法校验;② 全仓静态引用扫描(确认无悬空 import)。
- **遗留动作**:补齐依赖后必须补跑 `pytest tests/unit/core/test_customer_service_rules.py`、
`pytest tests/unit/service/test_agent_governance.py` 与全量 `ruff check`。