这道题其实是在问,怎么在语义理解、检索效率和工程复杂度之间找到平衡。我理解[[RAG]]的检索模块本质上是一个语义匹配问题,但落地时不能只靠向量检索一条腿走路。
具体说一下我的做法。首先是[[混合检索]]。纯向量检索对关键词、数字、实体匹配很弱,比如用户搜“订单号12345退款”,向量可能把“12345”当成语义噪声,但[[BM25]]能精准命中。所以我会把 向量召回和BM25结合起来,做一个Hybrid Search。向量负责语义相似,BM25负责精确匹配,两个分数线性加权或者用学习排序融合。这里有个坑:权重怎么设?我一般先看业务,比如客服场景退款问题语义更重要,BM25权重低一点;而搜政策条款时关键词更重要,权重调高。上线我会特别关注融合后的召回率,如果发现向量拉回一堆不相关但语义近的,就适当压低向量分数。
再一个是[[分块]]策略,这是很多人忽略的。Chunk大小直接影响检索粒度。块太大,比如一整个合同段落,语义完整但噪声多;块太小,比如一句话,容易上下文断裂。我偏向用 语义分块加[[滑动窗口]],比如先用[[Embedding]]检测主题边界,再在边界附近做重叠切分,确保每个块有上下文。举个例子,企业SOP文档里“退货流程”和“退款流程”是相邻的,如果硬切就把“退货需先退款”这个完整动作截断了。分块时我会预留前后各一两句的上下文,保证召回时信息完整。前提是你的Embedding模型能准确感知语义边界,否则切出来更乱。
检索执行层面,索引结构我常用[[HNSW]],它平衡了速度和召回。参数ef_search和M要调,一般M设16-32,ef_search设200-500,具体看延迟容忍度。如果[[向量库]]上亿,我会考虑[[IVF-PQ]]做量化压缩,但召回会掉一点,得看业务能不能接受。
落地最大的风险其实是 数据分布漂移。比如客服系统,用户query随时间变化,新政策发布后语义空间变了,但索引还是旧的,召回质量会逐渐下降。所以我会建一个反馈闭环:用户点击结果后,把正负样本回流,定期增量训练Embedding模型。索引更新也有讲究,全量重建太慢,我会用双缓冲影子索引,新索引构建完后原子切换,切换前用固定query回放,对比Recall@K和延迟,不通过就回滚。
说到反馈闭环,其实还有一个方向是[[Self-RAG]],让模型在生成时自己判断是否需要检索,以及检索结果的可靠性。这能解决很多不必要的检索开销和[[幻觉]]问题,但需要更多训练数据和控制。
最后收一下:我会把检索模块看成 一个系统工程,不是单一算法能解决的。混合检索、分块策略、索引更新、反馈闭环,这几个环节环环相扣。我更倾向先用简单方案跑通,比如BM25加向量,再逐步加[[重排]]和反馈,避免一开始就搞复杂导致维护成本失控。