23 向量检索
向量检索
向量检索的核心是把用户问题也转换成向量,再到向量库里找语义最接近的 chunks,作为大模型回答前的上下文。
[TOC]
1. 学完本节要达到什么程度
前面已经完成了 chunk 向量入库。
现在要实现查询链路:
用户问题
-> 问题向量
-> 向量数据库检索
-> 返回 topK chunks
本节先做最小向量检索。
混合检索和 Rerank 后面再加。
2. 检索流程
graph TD;
A["用户问题"] --> B["生成问题 Embedding"]; B --> C["携带 tenantId 和权限条件"];
C --> D["查询 pgvector 相似 chunks"]; D --> E["按距离排序取 topK"]; E --> F["过滤低相似度结果"];
F --> G["返回 chunks 和 sources"];
注意:
问题向量和 chunk 向量必须来自同一个 Embedding 模型
否则相似度没有意义。
3. topK 是什么
topK 表示返回最相关的前 K 个 chunk。
比如:
topK = 5
就返回 5 个候选片段。
topK 太小:
可能漏掉答案
topK 太大:
上下文太长
噪声太多
成本变高
学习阶段可以先用:
topK = 4 或 5
4. 相似度和距离
向量库常见计算方式:
cosine distance
inner product
L2 distance
RAG 里常用 cosine。
在 pgvector 中,常见写法类似:
SELECT
id, document_id, chunk_index, content, metadata, embedding <=> :query_embedding AS distanceFROM rag_chunk
WHERE embedding IS NOT NULL
ORDER BY embedding <=> :query_embedding
LIMIT :top_k;
距离越小,通常表示越相似。
如果要展示 score,可以转换一下。
例如:
score = 1 - distance
5. metadata 过滤
企业 RAG 不能只按向量搜。
还要带过滤条件:
tenantId
knowledgeBaseId
documentStatus
documentType
permissionScope
示例:
WHERE embedding IS NOT NULL
AND tenant_id = :tenant_id AND status = 'EMBEDDED'
权限过滤一定要在检索阶段做。
不要指望 Prompt 告诉模型“不要回答没权限的内容”。
6. 返回结构
检索接口可以返回:
{
"query": "上传文件大小限制是多少?",
"topK": 4, "chunks": [ { "chunkId": "c1", "documentId": "d1", "documentName": "接口文档.md",
"content": "单个上传文件最大 20MB。",
"score": 0.87, "metadata": { "pageStart": 2, "titlePath": "上传限制"
} } ]}
这个接口很适合调试。
先看检索结果对不对,再看大模型回答。
7. 检索质量检查
每次出问题先看检索。
不要一上来就换模型。
检查顺序:
问题向量是否生成成功
topK 结果是否相关
score 是否太低
metadata 是否过滤错
chunk 是否切得太碎
content 是否包含答案
只有检索结果靠谱,后面的生成才有意义。
8. 检索服务的工程化设计
检索接口应当是一个稳定、可观测的服务契约,而不是散落在业务代码里的几段向量 SQL。这样才能持续调整 topK、过滤条件和索引参数。
8.1 查询契约
一次检索请求至少要明确查询文本、查询向量、租户、知识库、权限范围、topK、阈值和使用的模型版本。返回结果应包含稳定的 chunk ID、文档 ID、距离或分数、标题路径、页码和必要的来源信息。
距离和相似度不要混用命名。数值越小越好还是越大越好,必须在接口层写清楚,并统一转换为前端和日志可理解的 score。
8.2 过滤顺序和降级
权限、租户、知识库和文档状态过滤必须进入数据库查询条件,不能先全库召回再在应用层删除。过滤条件很严格时,可以适当扩大候选数量,但不能绕过安全边界。
向量服务或索引异常时,可以降级到关键词检索或返回明确错误。不要悄悄取消过滤条件来换取“有结果”,这种降级会产生安全问题。
8.3 可观测性和调试
建议记录 topK、过滤条件摘要、查询耗时、候选数量、最高分、最低分和最终采用的 chunk ID。日志中避免保存完整敏感问题与正文,可以记录脱敏文本或摘要。
排查召回问题时按“查询向量是否正确、过滤是否过严、距离运算符是否匹配、候选是否进入 topK、阈值是否误删”的顺序检查,比直接更换模型更有效。
9. 常见问题
9.1 为什么明明有答案却搜不到
常见原因:
chunk 太小,答案被切断
chunk 没带标题
问题和文档表达差异太大
topK 太小
metadata 过滤条件太严格
embedding 模型中文效果差
9.2 是否要把整篇文档返回给模型
不要。
RAG 的核心就是先检索,再只放相关片段。
整篇塞进去成本高、噪声大、也不利于引用来源。
9.3 score 阈值怎么设
先不要硬设太死。
学习阶段可以先记录 score。
积累问题后再根据分布设置阈值。
10. 练习清单
完成几件事:
能写出向量检索流程
能解释 topK能写出 pgvector 查询 SQL能说明 metadata 过滤为什么重要
能设计检索结果返回结构
能排查检索不到答案的问题
11. 小结
本节的结论:
向量检索是 RAG 问答质量的第一道关,先确认 topK chunks 相关,再让大模型生成答案。