检索与重排
索引做完之后,线上只有一件事:用问题找到该给 LLM 看的块。默认路径是稠密向量 top-k;质量上不去时再加过滤、关键词混合、可选 rerank。
过滤可以在向量库内部做(Chroma where、pgvector WHERE、Qdrant query_filter),不必先取出 1000 条再在 Python 里丢。
top-k 怎么选
k 不是越大越好:窗口被噪声填满后,模型更容易忽略真正相关的那一段。先固定 k,用 评估 的 hit@k 再改切块。
元数据过滤
问题「人事部的请假天数」不应检索到工程 Wiki。索引时写入 dept、lang、source,查询时带上:
- Chroma:
where={"dept": "hr"} - pgvector:
WHERE dept = 'hr' ORDER BY embedding <=> %s - Qdrant:
Filter(must=[FieldCondition(...)])
过滤是权限边界,不是「提分技巧」。租户 ID 必须在服务端强制,不能让模型自己挑。
混合检索(向量 + 关键词)
稠密向量擅长同义改写(「退货」≈「退款」);关键词擅长条款号、SKU、错误码(KH-8842、ECONNRESET)。简单融合:各取 top-n,按 Reciprocal Rank Fusion 合并。
真正的 BM25 可用 PostgreSQL 全文检索、或 Qdrant sparse vector(见 Qdrant 预告)。不要在没测量 hit@k 之前上复杂混合。
可选 rerank
粗召回 20 条后,用「问题 + 文档」对重新打分,只把前 4 条送进 LLM。CPU 上可用交叉编码器(不必 GPU):
没有余力装模型时,用词面重叠做教学级 rerank(不能替代交叉编码器):
LangChain / LlamaIndex / Dify 里的 Rerank 组件做的是同一件事,见 LangChain RAG、Dify 知识库。
提示词约束
检索再准,提示词若允许「发挥」,模型仍会编。固定三句:
- 只根据下列上下文回答。
- 上下文没有的事实不要编造(含数字、工号、日期)。
- 依据不足时明确说不知道,并列出你参考过的
source。
生成质量用忠实度检查,见下一章。