检索增强生成RAG已经成为企业大模型应用的事实标准。但随着文档数量、查询复杂度和业务要求的提升单一向量检索的局限性越来越明显向量擅长语义匹配却容易漏掉专有名词和精确事实关键词检索精准但缺乏语义泛化能力知识图谱能捕获实体关系但构建成本高。多路召回Multi-Channel Retrieval正是在这个背景下成为生产级 RAG 的标配架构。一、为什么单一检索不够用了向量检索基于嵌入空间中的相似度对于自然语言表达的语义近义词非常有效。例如“如何提升模型推理速度”和“大模型推理加速方法”在向量空间中通常很接近。但向量检索在以下场景表现不佳-专有名词和编号产品型号、身份证号、订单号等精确匹配需求。-低频概念训练数据中出现较少的专业术语嵌入质量差。-多条件组合查询需要同时满足多个属性的约束例如“2024年发布且支持中文的向量数据库”。-关系推理需要跨越多个文档片段推断实体关系例如“某客户的所有关联订单”。因此生产环境的 RAG 通常需要结合多种检索方式取长补短。## 二、三路召回的核心机制### 1. 向量召回Dense Retrieval向量召回负责语义层面的匹配。它的核心流程包括- 将文档切分为 chunk- 使用嵌入模型如 BGE-M3、OpenAI text-embedding-3生成向量- 存储到向量数据库如 Milvus、Qdrant、Weaviate- 查询时同样生成向量按余弦相似度或点积排序返回 Top-Kpythonfrom langchain.embeddings import OpenAIEmbeddingsfrom langchain.vectorstores import Chromaembeddings OpenAIEmbeddings(modeltext-embedding-3-small)vectorstore Chroma.from_documents(chunks, embeddings)results vectorstore.similarity_search(query, k10)text向量召回的优势在于语义泛化但需要注意嵌入模型的领域适配。通用嵌入在医疗、法律、金融等专业领域往往效果一般建议使用领域数据微调或选用专用嵌入模型。### 2. 关键词召回Sparse Retrieval关键词召回使用传统信息检索方法如 BM25、TF-IDF或者基于稀疏向量的模型如 SPLADE、BGE-M3 的稀疏向量。它擅长处理精确匹配、专有名词和 acronym。pythonfrom rank_bm25 import BM25Okapicorpus [chunk.page_content for chunk in chunks]tokenized_corpus [doc.split( ) for doc in corpus]bm25 BM25Okapi(tokenized_corpus)doc_scores bm25.get_scores(query.split( ))top_indices np.argsort(doc_scores)[-10:][::-1]text关键词召回通常不需要重新训练实现成本低适合作为向量召回的互补通道。### 3. 知识图谱召回Graph Retrieval知识图谱召回将文档中的实体、关系和事件抽取为图结构支持复杂的关系查询和推理。例如- “某疾病的常见并发症”- “某公司的所有子公司及其产品”- “某项目的负责人和上游依赖”cypherMATCH (p:Product)-[:OWNED_BY]-(c:Company {name: OpenAI})RETURN p.name, p.release_datetext知识图谱构建通常涉及实体识别、关系抽取、实体对齐和图存储。对于已有结构化数据的业务可以直接将数据库导入图数据库对于非结构化文档则需要使用 LLM 或 NLP 工具抽取三元组。## 三、多路召回的融合策略多路召回的核心挑战在于如何将不同通道的结果融合为一个统一的候选集并排序返回给 LLM。常见方法包括### 1. 简单合并与去重最直接的方法是将各路结果合并按相似度或得分排序去除重复。这种方法实现简单但忽略了不同召回通道的得分分布差异。### 2. Reciprocal Rank FusionRRFRRF 是一种经典的融合方法不需要对得分归一化适用于不同召回通道的不可比得分pythondef reciprocal_rank_fusion(rank_lists, k60): scores {} for rank_list in rank_lists: for rank, doc_id in enumerate(rank_list): scores[doc_id] scores.get(doc_id, 0) 1 / (k rank 1) return sorted(scores.items(), keylambda x: x[1], reverseTrue)vector_rank [d.metadata[id] for d in vector_results]bm25_rank [d.metadata[id] for d in bm25_results]graph_rank [d[id] for d in graph_results]fused reciprocal_rank_fusion([vector_rank, bm25_rank, graph_rank])textRRF 稳健、易实现是生产环境中的常见选择。### 3. 学习排序LTR对于数据量大的场景可以使用轻量级模型对多路召回结果进行重排序。例如使用 Cross-Encoder 或小型 LLM 对候选文档与查询的相关性打分再重新排序。LTR 能显著提升最终精度但增加了推理成本和延迟。## 四、多路召回的工程架构一个典型的多路召回 RAG 架构如下text用户查询 ├── 向量召回 → 向量数据库 → Top-K 候选 ├── 关键词召回 → 倒排索引/BM25 → Top-K 候选 ├── 知识图谱召回 → 图数据库 → 子图/实体路径 └── 融合排序 → 重排序模型 → 最终上下文 → LLM 生成text工程落地时需要注意-索引一致性不同通道的文档 chunk 需要统一 ID便于去重和融合。-查询改写复杂查询在进入各通道前可进行重写或扩展例如 HyDE假设文档嵌入。-延迟控制知识图谱和重排序可能较慢可以设置超时和降级策略。-结果解释记录每条候选来自哪个通道便于调试和优化。## 五、总结RAG 的检索层已经从“向量一条腿走路”演变为“多路召回协同作战”。向量、关键词和知识图谱三种召回方式各有优劣只有根据业务场景合理组合才能在召回率、精度和延迟之间取得平衡。多路召回不是简单的技术堆砌而是需要精细的融合策略、统一的索引管理和持续的效果评估。对于正在构建企业知识库的团队来说多路召回是通往生产级 RAG 的必经之路。