RAG(检索增强生成)是当前落地最广的大模型应用范式之一。业务系统接入RAG之后,常见的问题是召回不准、答案过时、索引重建成本高。这些问题多数出在向量数据库选型和检索策略上,而不是模型本身。本文围绕向量库选型与混合检索两条主线,给出可直接复用的工程方案。
RAG的工程痛点:召回质量决定生成上限
大模型回答依赖上下文窗口内的信息,RAG的价值是把外部知识在生成前注入上下文。流程上分四段:文档切块、向量化入库、检索召回、拼装提示词。实际项目中召回环节最容易出问题:纯向量检索对专有名词、ID、版本号这类精确匹配不敏感,余弦相似度排序会把语义相近但事实错误的片段排到前面。
解决思路不是换更强的embedding模型,而是引入混合检索加重排。线上数据表明,混合检索对长尾查询的召回率提升通常在15%到30%之间,代价是多一次BM25倒排索引查询。
向量数据库选型:FAISS、Milvus、Qdrant与pgvector对比
向量库按部署形态分三类:嵌入式库、独立服务、数据库插件。选型依据是数据量和运维边界。
FAISS适合单机原型,内存索引速度快,但缺少增量更新和持久化服务能力,适合数据量在百万级以下、模型离线更新的场景。Milvus是独立分布式向量库,支持Collection分区、标量过滤和动态Schema,适合千万级以上的生产环境,代价是部署组件多。Qdrant用Rust实现,单机性能好,支持Payload过滤和自定义距离函数,中小团队上手成本低。pgvector直接嵌在PostgreSQL里,和业务数据放同一套事务,适合数据一致性要求高、向量量级在百万以内的场景,省掉一套独立服务。
经验值:数据在200万条以下优先pgvector或Qdrant,超过500万条再考虑Milvus。向量维度越高,暴力检索越慢,务必建索引。
混合检索:BM25关键词与向量召回融合
混合检索的思路是把BM25倒排召回和向量召回的结果做加权合并。典型实现:BM25处理精确匹配与术语检索,向量处理语义近义表达,两者取TopN后再合并去重。合并分数计算如下:
import numpy as np
from rank_bm25 import BM25Okapi
def hybrid_search(query, vector_index, corpus, tokenized, bm25, top_k=20, alpha=0.5):
# 向量召回
vec_score = vector_index.search([query], k=top_k)
# BM25 召回
bm_scores = bm25.get_scores(tokenized(query))
# 合并:归一化后加权
fused = {}
for doc_id, score in vec_score:
fused[doc_id] = alpha * score
for doc_id, score in enumerate(bm_scores):
fused[doc_id] = fused.get(doc_id, 0) + (1 - alpha) * score
return sorted(fused.items(), key=lambda x: x[1], reverse=True)[:top_k]
实际部署时alpha权重不用固定,根据线上反馈调节。alpha偏高时偏语义,偏低时偏字面,保险做法是从0.5起步,观察一段时间的效果再调整。
重排序:用交叉编码器修正召回顺序
混合检索给出的候选集仍需精排。粗排阶段用双塔模型(快,向量匹配),精排阶段用交叉编码器(慢,但准确)。典型做法:混合召回Top20,交给交叉编码器逐条打分,取Top3到Top5拼进提示词。
from sentence_transformers import CrossEncoder
reranker = CrossEncoder('BAAI/bge-reranker-base')
pairs = [(query, corpus[did]) for did, _ in candidates]
scores = reranker.predict(pairs)
order = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)
重排阶段注意控制延迟:交叉编码器逐对计算,Top20文档一次推理约几十毫秒,与向量召回加起来,单次RAG调用可控制在200ms以内。
切块策略:固定窗口与语义切块的取舍
切块大小直接影响检索效果。固定256到512字符的窗口实现简单,但会把逻辑完整的段落拦腰截断,造成检索片段上下文缺失。语义切块(按标题、段落边界切)召回质量更好,但引入分割模型依赖。实践上,技术文档建议按标题层级切分,代码片段保留原有代码块,切块之间保留100字符重叠。
索引更新与数据一致性
线上文档持续更新时要处理删除与过期。方案是在文档ID上携带版本时间戳,刷新任务定时把旧版本标记为无效。向量库的删除接口逐条操作成本高,建议批量删除再重建索引。生产环境拆成热数据分区(当天写入)与冷数据分区(历史归档),查询时按业务标签过滤分区,避免全库扫描。
评测反馈:RAG上线前必做的三组测试
第一组是标准答案评测集,至少覆盖30条业务真实问题,标注参考答案,上线后自动计算命中率。第二组是负面查询,验证系统在无答案时的拒答能力,防止硬检索出无关内容。第三组是回归测试,每次换向量模型、调切块参数都要重跑历史数据集,防止召回效果回退。三组测试跑通,RAG系统才具备长期可维护性。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rag-xi-tong-shi-zhan-xiang-liang-shu-ju-ku-xuan-xing-yu-hun/