- 删除生产死代码 app/service/knowledge_tool_service.py 与 app/infrastructure/milvus_knowledge_adapter.py:后者硬编码 Milvus 字段名, 违反 AGENTS.md §E,且仅被前者引用;生产检索链路实际走 knowledge_search_tool -> KnowledgeSearchService -> knowledge_schema 运行时探测。 - 删除上述两模块的单测,以及依赖 legacy 位置参数构造的 tests/unit/service/test_knowledge_retrieval.py。 - app/service/knowledge_retrieval_service.py 整文件回退底座版本, 移除 legacy 双构造与重复检索实现。 - docs/05-接口文档.md:客服画像候选改登记为 §8.5,恢复 §8.2 解析知识引用; 既有 §8.1-§8.4 编号全部保持,修复此前出现两个 8.3 的问题。 - app/model/profile.py:current_customer_id 改为普通可空列映射,与 alembic/baseline_generated.sql 及真实库一致;原 Computed 声明会让 ORM 把该列 从 INSERT 中排除,与「必须显式写入」的实际 schema 不符。 - 新增 docs/客服Agent接入底座扩展说明_v1.md,供集成分支评审逐项确认。 验证:pytest tests/unit tests/contract -> 1275 passed, 2 skipped, 0 failed; ruff check app tests tools alembic 通过;mypy app 通过(244 个源文件)。
11 KiB
11 KiB
客服 Agent 接入底座扩展说明(v1)
用途:提交
qyqy_develop(集成分支)评审时使用。 本文档逐项列出「客服 Agent + RAG」能力为接入底座而触碰的既有文件、改动性质、合规依据, 以及明确未改动的底座边界,便于架构师逐条确认。依据:
AGENTS.md、docs/00、docs/01、docs/05、docs/09、docs/14、docs/20。
一、总体口径
- 本次接入遵循
AGENTS.md规则 7:客服 Agent 继承公共BaseAgent、由AgentFactory创建, 不绕过公共鉴权、记忆、模型路由、工具、合规、审计与事件流程。 - 数据库侧未做任何基线改动:没有新增/重命名/删除表,没有改字段类型、可空性或业务含义, 没有新增迁移脚本。
- 底座中所有「既有 Agent 默认行为」均通过带默认值的声明位扩展,默认值等于改动前行为,
其他 Agent(
FundQueryDemoAgent、RiskAgent、PlatformProbeAgent)路径不受影响。
二、A 类:纯新增,不影响既有代码
| 文件 | 说明 |
|---|---|
app/core/conversation_privacy.py |
客服会话落库前的凭据最小化(密码/验证码/证件号/银行卡/手机号 → 占位符) |
app/api/controllers/visitor_tokens.py、app/api/schemas/visitor_tokens.py |
访客短时令牌签发接口 |
app/service/agent/customer_service_routing.py |
客服确定性意图路由(安全/账户/人工/合规/闲聊/公开知识) |
app/service/customer_service_session_memory_service.py |
客服 Redis 短期会话记忆(30 分钟滑动 TTL、24 小时绝对上限、16 条/约 4096 Token 截断) |
app/service/customer_service_handover_context.py、customer_service_handover_admin_service.py |
转人工上下文构造与管理员只读工单服务 |
app/service/customer_profile_candidate_service.py |
画像候选(Phase 2,异步、需用户确认 + 管理员审核) |
app/service/knowledge_authority.py、knowledge_config.py、knowledge_publication_service.py |
知识权威回查、运行期配置、受控发布工具所依赖的服务 |
app/infrastructure/milvus_profile_projection.py、neo4j_profile_projection.py |
画像投影适配器(异步派生写入) |
app/worker/memory_sync_outbox_worker.py、customer_profile_candidate_worker.py |
画像投影 Outbox 消费者、候选画像 Worker |
app/static/index.html |
客服联调测试页(/customer-service-test) |
tools/publish_customer_service_knowledge.py、verify_customer_service_phase1.py、knowledge_import_preflight.py |
受控发布、只读门禁、导入预检 |
以上均为新增文件,不改变任何既有模块行为。
三、B 类:带默认值、默认行为不变的扩展(对齐底座扩展点,建议直接确认)
| 文件 | 改动 | 默认值是否等于原行为 |
|---|---|---|
app/core/contracts.py |
AgentDefinition 新增 requires_model_intent_classification=True、recalls_customer_memory=True;AgentRequestMetadata 新增 chitchat_streak/clarification_round/session_context;CoreResult 新增 clarification_required |
是 |
app/service/agent/base.py |
recall_memory() 在声明关闭或访客时置空;classify_intent() 在声明关闭时返回 None |
是 |
app/service/agent/factory.py |
仅在 requires_model_intent_classification 为真时绑定意图分类器 |
是 |
app/core/config.py |
新增 visitor_token_ttl_seconds、milvus_local_uri、knowledge_embedding_endpoint_code、knowledge_embedding_timeout_ms 与 resolved_milvus_uri 属性 |
是(新增项均有默认值) |
app/core/knowledge_contracts.py |
新增 ALLOWED_KNOWLEDGE_COLLECTIONS 别名(与 ALLOWED_COLLECTIONS 恒等);KnowledgeHit.answer 可选字段;KnowledgeSearchResult.hits 补默认值 |
是(三个 fin_*_collection 白名单内容未变) |
app/model/knowledge.py |
新增 FinKnowledgeMeta = KnowledgeMeta 别名 |
是 |
app/model/memory.py |
__all__ 与 ProfileSnapshot 兼容转出 |
是 |
app/service/agent/bootstrap.py |
新增注册 query_knowledge 工具,handler 复用 knowledge_search_tool(与 search_knowledge 同一实现),required_permission="knowledge:query" |
是(不新增能力面,实际范围仍由 config_release 白名单收口) |
app/service/memory_service.py |
upsert_memory() 新增 status 参数(active/candidate),candidate 不覆盖现有有效记忆 |
是(默认 active) |
app/service/public_platform_service.py |
转人工工单 reason_detail 落库前做凭据脱敏 |
是(安全收紧) |
app/main.py |
注册 visitor_tokens_router、挂载 /customer-service-test 静态页 |
是(纯新增装配) |
pyproject.toml、requirements.txt |
新增 milvus-lite>=3.2,<4 |
是(可选本地开发依赖) |
.gitignore |
新增 .worktrees/、data/milvus/ |
是 |
四、C 类:需要架构师确认的底座语义扩展
C1. 访客身份(app/api/dependencies/auth.py + app/core/security.py)
security.py:JwtAuthenticator.authenticate()新增分支——当令牌含visitor: true声明时, 返回roles=("visitor",)、permissions=("agent:run", "knowledge:query")、data_scope="public"。auth.py:build_request_context()对visitor角色跳过IdentityService().resolve()(访客不在sys_user中,无法解析身份)。
合规说明:
visitor角色只可能出自用项目 RS256 私钥签名、且显式带visitor: true的令牌,普通用户令牌 无法携带该角色;- 访客权限固定为
agent:run+knowledge:query,data_scope="public", 不包含任何账户、持仓、订单、银行卡、投诉进度或画像权限; - 该分支只影响访客令牌,非访客令牌仍走完整
IdentityService身份解析。
请求确认: 是否接受在底座统一鉴权链路中增加这一受控访客身份;如需要,我们可补一份
docs/ 说明或在 docs/05 登记该令牌类型。
C2. 客服 Agent 的角色与安全路由(app/service/agent/implementations/customer_service.py)
allowed_roles由("customer",)扩为("visitor", "customer");handle()首部插入确定性安全路由route_message()(安全提示、合规拒答、账户入口、人工转接优先于检索);- 新增
recalls_customer_memory=False(客服不隐式召回长期/画像记忆); - 新增
chitchat_streak == 4的一次性业务引导; - 业务口径:
COMPANY由南方科技改为奶龙基金责任有限公司。
请求确认: 角色扩容与行为契约变更(安全路由前置、闲聊计数);品牌名属业务口径调整。
C3. 画像快照 ORM 声明清理与 current_customer_id 映射更正
三处相关改动(属于修既有缺陷,不是改设计):
app/model/risk_questionnaire.py:原有内联ProfileSnapshot声明与app/model/profile.py的同表声明重复,两个 declarative 类映射同一张表会让 SQLAlchemy 直接拒绝导入。 现改为从app.model.profile转出规范类,保留对既有调用方的兼容导出。app/model/profile.py:把current_customer_id映射为普通可空列。- 依据:该列在真实库中是普通可空列(
EXTRA=''、GENERATION_EXPRESSION='',已实测),alembic/baseline_generated.sql的建表语句也没有GENERATED子句,tools/seed_profile_demo.py明确写着「不是生成列,必须显式写入」。 因此不能声明Computed(...)——那会让 SQLAlchemy 把它从 INSERT 中排除,反而永远写不进去。 - 附带发现(建议底座侧修正):
docs/00-新数据库基线设计.md第 783 行把该列描述为 「生成列」,与docs/02/alembic基线 DDL 及真实库不一致。本次未改动docs/00, 仅在此登记,请底座侧决定以哪一侧为准。
请求确认: 上述三点是否按「修缺陷」接受。
C4. Milvus 双地址与部署约束(app/core/config.py + app/service/health_service.py)
- 新增
milvus_local_uri(默认空串)与resolved_milvus_uri = milvus_local_uri or milvus_uri; health_service.py的健康检查改用resolved_milvus_uri。
约束(请一并确认并写入环境规范):
- 团队/生产环境的
.env必须留空MILVUS_LOCAL_URI,否则健康检查与部分检索链路会指向 本地 Milvus Lite 文件,出现「健康检查正常、实际查的是另一个库」的隐性偏差; .env中默认值为空串,默认行为与改动前完全一致。
五、D 类:本次已从 ZSY 侧移除、不进入集成分支的内容
为避免把违反底座规则的内容带进集成分支,以下内容已在本分支删除:
| 内容 | 原因 |
|---|---|
app/service/knowledge_tool_service.py |
生产死代码(全仓唯一引用是它自己的单测)。生产路径是 bootstrap.get_knowledge_search_service() → KnowledgeSearchService |
app/infrastructure/milvus_knowledge_adapter.py |
违反 AGENTS.md §E:硬编码 knowledge_id/snippet/tags 等 Milvus 字段名,会打挂字段名不同的环境。且仅被上面那个死模块引用 |
tests/unit/service/test_knowledge_tool_service.py、tests/unit/infrastructure/test_milvus_knowledge_adapter.py |
上述两模块的单测 |
tests/unit/service/test_knowledge_retrieval.py |
依赖已移除的 legacy 位置参数构造 |
app/service/knowledge_retrieval_service.py 的 legacy 双构造与 _legacy_search |
已整文件回退为底座版本,消除「同一服务两套构造语义 + 两套检索实现」的技术债 |
检索仍统一走底座既有链路:ToolExecutor → knowledge_search_tool → KnowledgeSearchService
→ app/core/knowledge_schema.py 的 detect_schema() 运行时字段探测,无任何硬编码字段名。
六、E 类:明确未改动的底座边界
docs/00、docs/02的表结构与字段语义:未改动;alembic/迁移脚本:未改动;- Milvus 字段名:无硬编码,全部走运行时探测;
docs/05-接口文档.md的既有章节编号:§8.1–§8.4 全部保持原编号,客服二期新增的 「客服画像候选」登记为 §8.5(不占用既有号段),另有 §9.7 追加;原有交叉引用 「§8.3 知识库管理三端点」「§8.4 公共只读工具索引」仍然成立;- 其他业务 Agent、场外/推广/风控域:未改动行为契约。
七、F 类:需要业务方在环境侧确认的既有约束(非本次引入)
config_release是环境数据、不随代码合并:换环境需重新发布客服工具白名单。- Milvus 集合 schema 因环境而异,检索层已运行时探测,任何新增代码都不得硬编码字段名。
- 本地 Milvus Lite 仅用于本地开发;团队环境应使用受管 Milvus 并留空
MILVUS_LOCAL_URI。