Commit Graph
18 Commits
Author SHA1 Message Date
张胜宇 9aaacc242f chore: 清理违反底座规则的死代码并修正接口文档编号
- 删除生产死代码 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 个源文件)。
2026-09-12 11:15:24 +08:00
张胜宇 ef701c844c merge: integrate ZSY customer service and profile capabilities 2026-09-11 22:31:51 +08:00
Windows bbf623a464 merge: integrate advisor capabilities on latest qyqy base 2026-09-11 21:03:58 +08:00
张胜宇 cbcf7c7444 feat: add milvus profile projection 2026-09-11 20:45:50 +08:00
张胜宇 5e848f5690 feat: wire neo4j projection into worker 2026-09-11 20:19:34 +08:00
张胜宇 f167390a8a feat: add neo4j profile projection adapter 2026-09-11 19:54:46 +08:00
qyqy cbd6de2721 Merge remote-tracking branch 'origin/qyqy_develop' into nl-merge-latest
# Conflicts:
#	app/service/model_gateway.py
2026-09-11 15:38:11 +08:00
wangjianlong_0626 e4c4099aaa wip: 客服Agent + RAG + 画像收尾(基于 6516ccb) 2026-09-11 14:46:40 +08:00
Windows 8ffd08b4ce feat: add portfolio graph enrichment 2026-09-11 14:14:50 +08:00
lzf_0626 d896a906cd fix(risk): 规则扫描加跨进程锁——手工触发与定时扫描此前可以同时跑
docs/25 P2 最后一项。核实后分清了两层,报告没区分:

- **定时扫描是安全的**:risk_scan_scheduler.py 已有 MySQL 连接级咨询锁
  (GET_LOCK,锁名 jr_risk_scan_schedule),跨进程互斥。
- **HTTP 端点不安全**:POST /api/v1/risk/alerts/scan → RiskScanService.scan() 只用了
  **进程内** asyncio.Lock。多 Web worker、或 Worker 与 API 同时运行时形同虚设。

而扫描的幂等只有应用层的 _exists 查重 —— fin_risk_alert 的 trigger_rule_codes 是 JSON
数组,**无法建唯一索引兜底**(同一交易可命中多条规则,唯一键本应是"交易+规则",而规则
埋在 JSON 里)。所以两条路径并发时会同时查不到、同时插入,产生重复预警。

**改动**:

1. 把 mysql_scan_lock 与锁名移到 pp/infrastructure/db.py —— 端点与调度器**必须共用
   同一把锁**,放在基础设施层两个入口才都能引用(service 不该反向依赖 worker)。
   调度器改为从那里 import。
2. **端点层加锁**(controllers/risk.py 的 scan 端点):取不到锁就抛 RiskScanBusyError
   (与 service 内部那把进程内锁用同一错误类型与文案)。

**为什么不加在 RiskScanService.scan() 内部**:GET_LOCK 是**连接级**的,而调度器已经在
它自己的 session 上持锁;被两个入口共用的服务方法若再取同一把锁,取锁的连接并不是持锁的
那一个、必然返回 0 —— 会**把定时扫描自己挡死**。所以锁加在入口层,每个入口只取一次。

**实测**:
- 无人持锁时扫描 → **200**「规则扫描完成」
- 本进程先取得跨进程锁后再调端点 → **409**「规则扫描正在执行,请稍后重试」
  (同一进程内不同 session 也互斥,说明它是连接级的,正是跨进程所需)
- 释放后再调 → **200**,恢复正常

顺带第 4 次遇到 409 复用错误码 RUN_NOT_CANCELLABLE,语义不符;属 P3 待处理项。

ruff / mypy(136 文件) / 639 unit+contract 全绿。
2026-09-11 13:57:22 +08:00
张胜宇 c76b763101 feat: configure local customer service knowledge runtime 2026-09-11 10:13:48 +08:00
lzf_0626 75dff088d4 feat: 接通 Neo4j 图能力(驱动实现 + 装配),并实测确认图模型标签不一致
第 2 步(图库)的地基部分。

1. 新增 app/infrastructure/graph.py:GraphDriver 协议的 neo4j 实现。
   这层此前是空的——relationship_service.py 里的 GraphDriver 只有 Protocol 声明、没有任何
   具体实现,组装层也没有装配它,因此图读服务在运行期必然降级(neo4j_unavailable)。
   这正是"Neo4j 连读适配器都没有"的根因。
   降级取向与 Milvus 侧一致:本层不吞异常(由调用方决定降级方式),但构造失败返回 None
   ——图库不可用不该让应用起不来,也不该阻塞主链路。

2. bootstrap 新增 get_relationship_service():装配图读服务。
   该服务只读,关系类型受 ALLOWED_RELATIONSHIPS 白名单约束;写入走 GraphProjectionWorker
   (由领域事件驱动),这里不提供任意写接口——避免出现绕过事件链路的直写路径。

3. 实测确认一处既有缺陷(本次不改,方案待定):投影 worker 写入的节点标签是
   :Entity {entity_id}(字符串属性),而 RelationshipService.neighbors 查询的是
   :Customer {customer_id}(整数属性),两侧从未对齐,写进去的关系读不出来。
   Neo4j 在执行读查询时直接给出三条警告佐证:未知标签 Customer、未知属性 customer_id、
   未知关系类型 PREFERS——这也说明业务图从未被真正投影过(库中只有 Neo4j 自带的
   Person/Movie 示例数据,共 5 个节点)。

验证:ruff 通过、mypy 110 文件无错;get_relationship_service() 返回 RelationshipService,
neighbors 与 paths 正常执行并返回空集(非降级),非法关系类型被白名单拒绝。
2026-09-10 21:40:00 +08:00
张胜宇 511a8ca18f feat: add governed public knowledge retrieval 2026-09-10 18:42:44 +08:00
张胜宇 8e36a9941d merge: preserve existing business features on new foundation 2026-09-10 17:26:52 +08:00
lzf_0626 6516ccb385 feat: 第二版——接口契约对齐 docs/05,修复静默故障与数据库基线
相对第一版 46fc976 的完整变更。组员迁移对照表见 docs/20。

一、对外契约对齐 docs/05(破坏性,共 4 处,组员需按 docs/20 调整)
1) 配置发布端点改为文档规定的复数资源名:submit→validations、
   approve→reviews(需 body decision)、activate→activations、
   rollback→rollbacks;第一版这 4 个动词式路径 docs/05 从未定义过。
2) 错误码由 8 个笼统码改为 15 个具体语义码(FORBIDDEN→AGENT_PERMISSION_DENIED、
   UNAUTHORIZED→AUTHENTICATION_REQUIRED、CONFLICT→RESOURCE_VERSION_CONFLICT、
   RESOURCE_NOT_FOUND→RUN_NOT_FOUND/SESSION_NOT_FOUND 等),
   输入类错误状态码 400→422。
3) POST /api/v1/agent-runs 与 GET /api/v1/agent-runs/{run_id} 统一为
   {data, meta} 信封(data 内字段名与语义未变)。
4) 错误响应体统一为 {error:{code,message,retryable,field_errors}, meta:{trace_id}},
   不再返回 FastAPI 默认的 {"detail": ...}。

二、数据库基线与约束
新增 39 张表的基线迁移(链根)与联合唯一键纠偏(4 张表、删 8 增 4,幂等收敛);
撤下 config_release 的双人复核 CHECK(应用层已允许自审,审核节点保留,
自审如实写入 reviewer_id);记忆 active key 生成列与唯一键;
activate 开始记录 supersedes_release_id 使版本链可追溯。
docs/00 基线未修改,未重命名或删除任何表与字段。

三、修复会静默出错或无报错的缺陷
- 跑完集成测试后平台会静默失去生效配置:清理只删自己创建的版本,却没有恢复被它
  顶成 superseded 的原生效版本,且审计一并删除因而完全无痕,表现为所有工具被拒
  但没有任何报错。已修清理逻辑并加恢复。
- Worker 单轮异常导致进程退出;记忆抽取调用方的“事务已开始”异常;
  召回缓存丢失 degraded 标记;连接时区未生效导致 created_at/updated_at 差 8 小时;
  .env 与 os.getenv 密钥来源分裂导致“没有可用的已批准模型端点”。
- 记忆信号识别漏判与跨键误命中;SSE 未带 Accept 的协商行为。

四、功能补齐
记忆链路 P1/P2/P3(抽取、受控词表、召回与缓存、生命周期级联及投影事件)、
fin_* 场内交易只读 ORM 层、agent_intent_config 状态流转并在运行期真正生效、
限流(Redis 固定窗口、故障一律放行)、游标校验、trace_id 中间件、
示例业务 Agent fund_query_demo 与一键端到端验证脚本,以及审计/指纹/迁移状态工具。

五、文档与验证
新增 docs/19(业务 Agent 接入实操)、docs/20(第一版迁移指南)与 docs/evidence 证据;
docs/01/02/06/08/09/17 同步实现现状。

验证结果:ruff 通过、mypy 103 文件无错、unit+contract 447 passed、
integration 29 passed、acceptance_check --production 7 PASS、
demo_agent_e2e 9/9 PASS(含失败关闭反证)。
2026-09-10 15:55:54 +08:00
yuancong_0626 5907fcd6d2 袁聪的第一次提交,包含nl2sql,行情数据,场外申购 2026-09-10 09:23:22 +08:00
lzf_0626 46fc976b24 feat: add shared fund quote capability 2026-09-09 23:40:35 +08:00
Codex b1497fd2c6 chore: initialize project repository 2026-09-09 21:55:37 +08:00