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

10 KiB
Raw Permalink Blame History

一期客服确定性路由:关键词表留痕与迁移对照

日期: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 均已接管其余能力。


二、一期词表原样留痕(删除前的完整内容)

_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。