# AI 合同平台 V2:RAG 检索 Explain 增强 日期:2026-06-24 ## 本轮目标 在完成 pgvector HNSW 和关键词 `search_vector` SQL 优化后,本轮补齐 RAG 检索可解释性: - 说明一次检索是否使用 HNSW。 - 说明一次检索是否使用 `search_vector`。 - 返回向量候选数、关键词候选数、融合去重后的候选数。 - 给每条候选返回来源和排序原因,帮助管理员判断“为什么命中这条依据”。 这属于 AI 中台能力,不把检索细节塞回合同系统,仍符合 V2 重构方案中“合同系统只做业务、AI 中台负责模型/知识库/RAG/审计”的边界。 ## 已完成代码 文件: - `yuqei-ai-platform/services/ai-platform-api/src/yuqei_ai_platform_api/repository.py` - `yuqei-ai-platform/services/ai-platform-api/tests/test_platform_data.py` ### 1. Explain 响应新增字段 `KnowledgeSearchExplain` 新增: - `vector_backend` - `keyword_backend` - `used_hnsw` - `used_search_vector` - `vector_candidate_count` - `keyword_candidate_count` - `merged_candidate_count` `KnowledgeSearchExplainItem` 新增: - `candidate_source` - `ranking_reason` ### 2. PostgreSQL explain 走真实检索路径 SQLAlchemy/PostgreSQL 仓库的 explain 不再只用“最近 N 条内存候选”模拟,而是按策略走真实数据库路径: - `hybrid`: - pgvector HNSW 取向量候选 - `search_vector @@ plainto_tsquery(...)` 取关键词候选 - 合并去重后计算关键词分、向量分、混合分 - `vector`: - 只走 pgvector HNSW - 与正式搜索保持一致:即使低于阈值,也解释 top vector 候选 - `keyword`: - 只走 `search_vector` ### 3. 排序原因 每条结果返回类似: ```text hybrid score 0.6326 = keyword 1.0000 * 0.55 + vector 0.1835 * 0.45; source=vector; matched_terms=押金 ``` 或: ```text vector score 0.2293; source=vector ``` 或: ```text keyword score 1.0000; source=keyword; matched_terms=租赁 ``` 这样管理员可以直接看到命中来源、分数构成和匹配词。 ## 本地验证 命令: ```powershell python -m pytest yuqei-ai-platform\services\ai-platform-api\tests -q python -m compileall yuqei-ai-platform\services\ai-platform-api\src\yuqei_ai_platform_api\repository.py ``` 结果: - `41 passed` - compileall 通过 新增/更新测试: - 内存 explain 仍返回基础字段,兼容原 explain 行为。 - explain 模型可以表达 `postgres-pgvector`、`pgvector-hnsw`、`search_vector`、候选数和排序原因。 ## V2 smoke 部署验证 部署命令: ```powershell $env:SSHPASS='YOUR_REMOTE_PASSWORD' powershell.exe -NoProfile -ExecutionPolicy Bypass -File yuqei-infra\scripts\deploy-v2-smoke-docker.ps1 -UseSshpass -AllowDirtyWorktree -SkipSmoke ``` 最终结果: - `V2_SMOKE_DOCKER_DEPLOY_PASS` - 产物目录:`project-docs/qa-artifacts/v2-smoke-docker-deploy/2026-06-24T21-53-40` 中间情况: - 第一次部署失败原因仍是 Docker 镜像代理 TLS 超时,不是代码问题。 - 重跑后部署通过。 ## 远端接口抽样 接口: ```http GET /api/v1/knowledge-chunks/search/explain ``` ### hybrid:押金 结果摘要: ```json { "retrieval_backend": "postgres-pgvector", "vector_backend": "pgvector-hnsw", "keyword_backend": "search_vector", "used_hnsw": true, "used_search_vector": true, "vector_candidate_count": 100, "keyword_candidate_count": 100, "merged_candidate_count": 200, "included_count": 3, "first_source": "vector" } ``` 排序原因: ```text hybrid score 0.6326 = keyword 1.0000 * 0.55 + vector 0.1835 * 0.45; source=vector; matched_terms=押金 ``` ### vector:deposit refund 结果摘要: ```json { "retrieval_backend": "postgres-pgvector", "vector_backend": "pgvector-hnsw", "keyword_backend": "none", "used_hnsw": true, "used_search_vector": false, "vector_candidate_count": 100, "keyword_candidate_count": 0, "merged_candidate_count": 100, "included_count": 3 } ``` 排序原因: ```text vector score 0.2293; source=vector ``` ### keyword:租赁 结果摘要: ```json { "retrieval_backend": "postgres-pgvector", "vector_backend": "not_used", "keyword_backend": "search_vector", "used_hnsw": false, "used_search_vector": true, "vector_candidate_count": 0, "keyword_candidate_count": 100, "merged_candidate_count": 100, "included_count": 3 } ``` 排序原因: ```text keyword score 1.0000; source=keyword; matched_terms=租赁 ``` ## 当前边界 - explain 现在能说明数据库检索路径和排序原因,但还没有记录每次 explain 的 SQL `EXPLAIN ANALYZE` 原文。 - 目前候选来源以 `vector`、`keyword`、`keyword+vector` 表达。对于同一 chunk 同时出现在两边的情况,可以进一步展示两边原始排名。 - explain 接口是管理员/调试用能力,正式法律问答仍通过 AI Trace 记录命中来源和质量标签。 ## 下一步建议 下一步可以继续做: 1. 在 AI Trace 详情页展示 RAG explain 摘要,让每次法律问答能回看“为什么引用这些依据”。 2. 给 explain 增加向量原始排名、关键词原始排名、去重前后候选数。 3. 用真实法规库问题集跑“依据命中率 / 错误引用率”质量基线。