# AI 合同平台 V2 数据库优化:pgvector HNSW 查询形态收口 日期:2026-06-24 ## 本轮目标 按照《AI 合同平台 V2 重构版开发方案》和《AI 合同平台 V2 数据库优化重构方案》的 DB-5 性能基线推进,本轮聚焦 AI 中台知识库检索: - 将知识库向量检索从可用的 pgvector 查询,收口为稳定命中 HNSW 索引的查询形态。 - 避免 pgvector 成功执行但返回空结果时回退到 Python 全量扫描。 - 保留合同系统和 AI 中台职责边界:合同系统只调用 AI 中台,知识库、向量检索、法条依据仍在 `yuqei-ai-platform` 内部完成。 ## 已完成代码 ### 1. pgvector 查询形态对齐 HNSW 表达式索引 文件: - `yuqei-ai-platform/services/ai-platform-api/src/yuqei_ai_platform_api/repository.py` 核心变化: - 默认 64 维 embedding 查询使用: ```sql CAST(embedding AS vector(64)) <=> CAST(:query_vector AS vector(64)) ``` - 与迁移中已创建的 HNSW 表达式索引保持一致: ```sql CREATE INDEX ix_knowledge_chunks_embedding_hnsw ON knowledge_chunks USING hnsw ((embedding::vector(64)) vector_cosine_ops) WHERE embedding IS NOT NULL AND embedding_dimension = 64; ``` - 非默认维度仍保留兼容查询: ```sql embedding <=> CAST(:query_vector AS vector) ``` 这样做的原因是当前生产级默认 embedding 维度已经统一为 64,查询必须与表达式索引形态一致,PostgreSQL 才能使用 HNSW,而不是退化为顺序扫描。 ### 2. pgvector 成功执行后不再误回退全量扫描 之前逻辑里,pgvector 查询返回空列表时会继续走 repository 的 Python 全量排序路径。真实数据量上这会造成慢查询,也会掩盖向量检索本身的问题。 已调整为: - `None` 表示 pgvector 执行失败,可以回退。 - `[]` 表示 pgvector 成功执行但没有命中,不再回退全量扫描。 ### 3. 向量候选池收口 新增候选池范围: - 最小候选数:100 - 最大候选数:500 - 默认按 `limit * 25` 计算后夹紧 这样既保留混合排序的候选空间,又避免无限拉取候选造成接口变慢。 ### 4. 中文法律核心词检索修正 文件: - `yuqei-ai-platform/services/ai-platform-api/src/yuqei_ai_platform_api/embeddings.py` - `yuqei-ai-platform/services/ai-platform-api/src/yuqei_ai_platform_api/main.py` 调整: - 不再把“合同”“风险”作为 embedding 检索泛词过滤掉。 - 知识库检索接口现在可以正常搜索“合同”“风险”“押金”“租赁”。 - 法律问答层增加“泛合同问题”保护:例如“这个合同需要注意什么?”不强行召回某条不相干的劳动合同法,而是回到默认合同风险回答和民法典兜底依据。 这保持了两个目标: - 知识库检索要能搜领域核心词。 - 法律问答不能因为泛词而错误引用不相关法条。 ## 本地验证 命令: ```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\main.py yuqei-ai-platform\services\ai-platform-api\src\yuqei_ai_platform_api\repository.py yuqei-ai-platform\services\ai-platform-api\src\yuqei_ai_platform_api\embeddings.py ``` 结果: - `39 passed` - compileall 通过 新增测试覆盖: - 默认 64 维 pgvector 查询表达式必须包含 `CAST(embedding AS vector(64))` 和 `CAST(:query_vector AS vector(64))`。 - 非默认维度仍走兼容查询表达式。 - “合同”“风险”作为中文法律核心词必须可搜索。 ## 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-03-01` 远端数据库状态: - `ai_platform_alembic_version = 20260624_0015` - `knowledge_chunks = 60002` - `embedding` 非空数量:`60002` - `embedding_dimension`:最小 `64`,最大 `64` - HNSW 索引存在:`ix_knowledge_chunks_embedding_hnsw` ## EXPLAIN ANALYZE 结果 验证 SQL: ```sql EXPLAIN (ANALYZE, BUFFERS) SELECT id FROM knowledge_chunks WHERE embedding IS NOT NULL AND embedding_dimension = 64 ORDER BY CAST(embedding AS vector(64)) <=> CAST(:query_vector AS vector(64)) LIMIT 10; ``` 关键结果: ```text Index Scan using ix_knowledge_chunks_embedding_hnsw on knowledge_chunks Execution Time: 1.668 ms ``` 结论: - 代码当前使用的 `CAST(embedding AS vector(64))` 可以命中迁移创建的 `embedding::vector(64)` HNSW 表达式索引。 - pgvector 查询已经从原来的顺序扫描风险,收口为 HNSW 索引扫描。 ## API 抽样验证 远端 smoke 环境接口: - `GET /api/v1/knowledge-chunks/search` - `POST /api/v1/legal/qa` 知识库搜索抽样: | 关键词 | 策略 | 结果数 | 首条分数 | 说明 | | --- | --- | ---: | ---: | --- | | 合同 | hybrid | 3 | 0.5711 | 中文核心词可检索 | | 风险 | hybrid | 3 | 0.5365 | 中文核心词可检索 | | 押金 | hybrid | 3 | 0.6326 | 租赁押金场景命中 | | 租赁 | hybrid | 3 | 0.55 | 租赁场景命中 | | deposit refund | vector | 3 | 0.2281 | 纯向量路径返回候选 | 法律问答抽样: | 问题 | 首条依据 | 结果 | | --- | --- | --- | | 这个合同需要注意什么? | 中华人民共和国民法典 第五百零九条 | 泛合同问题回到默认兜底 | | 房屋租赁合同押金退还应注意什么? | 租赁押金法条片段 | 具体问题走知识库命中 | | 劳动合同试用期最长可以约定多久? | 知识库片段 | 具体问题走知识库命中 | ## 当前边界 - 本轮已经解决 pgvector/HNSW 查询形态,不继续扩大为全文检索重写。 - chunk 的 `title/reference/content` 已有 `pg_trgm` GIN 索引,但当前 SQL 使用 `lower(...) LIKE`,对部分泛词仍可能不是最优。后续如要继续压缩“合同/风险”这类超高频词耗时,可以单独做关键词 SQL 形态优化或生成列索引。 - 当前 smoke 数据中存在大量性能样本 chunk,返回的法条标题会带有测试数据特征。生产数据导入后需要结合真实法规库重新跑质量抽样。 ## 下一步建议 DB-5 的 pgvector 查询形态已经收口。下一步更自然进入: 1. 关键词检索 SQL 形态优化:将 `lower(...) LIKE` 调整为更容易命中 trigram/tsvector 的查询方式,并做高频中文词基线。 2. RAG 可解释接口增强:在 explain 中显示是否走 HNSW、候选数量、关键词候选补充数量和最终混合排序原因。 3. 真实法规库导入质量验证:用民法典、劳动合同法、公司法等真实文本重新跑“主要依据”命中质量和延迟基线。