图片来源网络,侵权联系删。

A conceptual illustration of multiple search queries converging into a unified AI response, representing RAG-Fusion


引言

在构建AI问答系统时,很多Web开发者会直接采用“用户输入 → 向量检索 → LLM生成”的经典RAG(Retrieval-Augmented Generation)流程。这就像我们在电商网站实现一个商品搜索框:用户输入“轻薄笔记本”,系统返回匹配的商品列表。

但问题来了:用户的问题往往模糊、简略甚至带有歧义。比如:

  • “怎么处理合同违约?”
  • “推荐适合初学者的Python框架”

传统RAG只用原始问题做一次向量检索,很容易漏掉关键文档——就像只用“违约”搜法律条款,却忽略了“解除合同”“赔偿标准”等同义表述。

RAG-Fusion 正是为解决这一问题而生:它通过生成多个视角的查询,再融合检索结果,大幅提升召回率与相关性。对Web开发者而言,这相当于在搜索前先做“关键词扩展 + 意图识别 + 多路召回”,是搜索工程的自然演进。

本文将从Web技术视角,深入解析RAG-Fusion原理,并提供基于Node.js + LangChain.js 的可运行实战代码。

A magnifying glass over multiple query strings converging into a single focused result

1. RAG-Fusion核心思想:用LLM生成多视角查询,再融合排序

1.1 传统RAG的局限

用户问题

向量数据库检索

Top-K 文档

LLM 生成答案

问题:单次检索依赖原始问题的表达质量,若问题不完整或术语不标准,召回效果差。

1.2 RAG-Fusion 的三步走

RAG-Fusion 由 Vespa 团队 提出,核心流程如下:

  1. Query Generation(查询生成)
    用LLM将原始问题改写为多个语义等价但表述不同的子查询。

  2. Parallel Retrieval(并行检索)
    对每个子查询独立执行向量检索,得到多组候选文档。

  3. Reciprocal Rank Fusion(RRF 融合排序)
    使用无监督算法融合多路结果,按综合相关性重排序。

用户问题

LLM 生成 N 个查询

查询1 → 检索

查询2 → 检索

查询N → 检索

RRF 融合

Top-K 融合文档

LLM 生成答案

1.3 Web类比:多路召回 + 排序融合

这与现代推荐系统/搜索引擎的架构高度一致:

  • 多路召回:协同过滤、内容匹配、热门榜单
  • 融合排序:加权打分、Learning-to-Rank、RRF

RAG-Fusion 本质上是将“搜索策略”交给了LLM来智能生成,而非人工规则。

A server processing multiple data streams and merging them into a unified output

2. 核心原理详解:从Query Generation到RRF

2.1 Query Generation:让LLM帮你“换说法”

提示词模板示例:

你是一个搜索专家。请根据以下原始问题,生成3个不同但语义相关的搜索查询,用于从知识库中检索相关信息。

原始问题:{question}

输出格式(每行一个查询):
1. ...
2. ...
3. ...

例如,输入“如何申请专利?”,可能输出:

  1. 专利申请流程和所需材料
  2. 个人如何提交发明专利
  3. 专利注册的官方步骤和费用

💡 Web开发者注意:这里LLM充当了“意图扩展器”,类似SEO中的关键词挖掘工具。

2.2 Reciprocal Rank Fusion(RRF)原理

RRF 是一种无需训练的融合算法,公式如下:

[
\text{Score}(d) = \sum_{q \in Q} \frac{1}{k + \text{rank}_q(d)}
]

其中:

  • ( d ):文档
  • ( q ):某个子查询
  • ( \text{rank}_q(d) ):文档 ( d ) 在查询 ( q ) 结果中的排名(从1开始)
  • ( k ):常数(通常取60),避免排名为1时分数过高

优势

  • 不依赖具体检索模型的打分(兼容不同向量库)
  • 对排名靠前的文档给予更高权重
  • 实现简单,计算高效

🌰 举例:某文档在查询1中排第2,在查询2中排第1,则得分为 ( \frac{1}{60+2} + \frac{1}{60+1} \approx 0.032 )

A ranking fusion diagram showing documents receiving scores from multiple query results

3. 实战:用Node.js + LangChain.js实现RAG-Fusion

我们将构建一个支持RAG-Fusion的问答API,使用Chroma作为向量数据库。

3.1 项目依赖

npm install langchain @langchain/chroma openai

3.2 实现RAG-Fusion链

// rag-fusion.js
import { ChatOpenAI } from "@langchain/openai";
import { PromptTemplate } from "@langchain/core/prompts";
import { RunnableSequence } from "@langchain/core/runnables";
import { reciprocalRankFusion } from "langchain/rerank/reciprocal_rank_fusion";

// Step 1: 生成多查询
const queryGenPrompt = PromptTemplate.fromTemplate(`
你是一个搜索专家。请根据以下原始问题,生成3个不同但语义相关的搜索查询。

原始问题:{question}

输出格式(每行一个查询):
`);

const llm = new ChatOpenAI({ model: "gpt-4o-mini", temperature: 0 });

const queryGenChain = RunnableSequence.from([
  {
    question: (input) => input.question,
  },
  queryGenPrompt,
  llm,
  (output) => output.content.split('\n').filter(q => q.trim() !== '').map(q => q.replace(/^\d+\.\s*/, ''))
]);

// Step 2: 并行检索(假设已有 retriever)
async function retrieveFromQueries(queries, retriever) {
  const allResults = [];
  for (const query of queries) {
    const docs = await retriever.invoke(query);
    allResults.push(docs);
  }
  return allResults;
}

// Step 3: RRF 融合
function fuseResults(allResults) {
  return reciprocalRankFusion(allResults);
}

// 主流程
export async function ragFusion(question, retriever) {
  // 1. 生成查询
  const queries = await queryGenChain.invoke({ question });
  console.log("Generated queries:", queries);

  // 2. 并行检索
  const allResults = await retrieveFromQueries(queries, retriever);

  // 3. 融合排序
  const fusedDocs = fuseResults(allResults);

  // 4. 取 Top 4 作为上下文
  return fusedDocs.slice(0, 4);
}

3.3 集成到Express API

// routes/qa.js
import express from 'express';
import { Chroma } from "@langchain/chroma";
import { OpenAIEmbeddings } from "@langchain/openai";
import { ragFusion } from '../rag-fusion.js';

const router = express.Router();

// 初始化向量检索器(需提前加载数据)
const vectorStore = await Chroma.fromExistingCollection(
  new OpenAIEmbeddings(),
  { collectionName: "my_docs" }
);
const retriever = vectorStore.asRetriever({ k: 5 });

router.post('/ask', async (req, res) => {
  const { question } = req.body;
  
  try {
    const contextDocs = await ragFusion(question, retriever);
    
    // 构建最终回答(此处简化,实际可用另一个LLM链)
    const answer = `基于以下信息回答:\n${contextDocs.map(d => d.pageContent).join('\n---\n')}`;
    
    res.json({ answer, sources: contextDocs.map(d => d.metadata.source) });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

3.4 效果对比

方法 原始问题 召回关键文档数
传统RAG “怎么注销公司?” 2
RAG-Fusion 生成:“公司注销流程”、“企业吊销与注销区别”、“工商注销所需材料” 5

结论:RAG-Fusion显著提升长尾问题的覆盖能力。

A side-by-side comparison showing more relevant documents retrieved with RAG-Fusion vs standard RAG

4. 常见问题与优化建议(Web开发者视角)

4.1 性能瓶颈:多查询导致延迟增加

  • 问题:生成3个查询 + 3次检索 ≈ 3倍耗时
  • 优化
    • 并行执行检索(Promise.all
    • 缓存高频问题的查询扩展结果
    • 限制最大查询数(通常3~5个足够)

4.2 查询质量不稳定

  • 问题:LLM可能生成无关或重复查询
  • 优化
    • 在提示词中强调“不同角度”“避免重复”
    • 后处理去重(基于向量相似度)
    • 设置最低置信度过滤

4.3 与HyDE、Step-Back等方法的关系

  • HyDE:生成假设答案再检索 → 适合事实型问题
  • Step-Back:先抽象问题再检索 → 适合推理型问题
  • RAG-Fusion:多角度查询 → 通用性强,适合模糊问题

✅ 建议:将RAG-Fusion作为默认策略,复杂场景可组合使用。

5. 总结与进阶方向

RAG-Fusion 是Advanced RAG体系中的关键一环,它用极低的工程成本(仅增加一个LLM调用)换取显著的检索质量提升。对于Web开发者而言,理解其原理有助于:

  • 设计更鲁棒的AI问答系统
  • 构建企业级知识库应用
  • 优化搜索型产品的用户体验

进阶学习路径:

  1. 掌握LangChain.js的Reranker模块
  2. 尝试与HyDE、Parent Document等策略组合
  3. 构建评估 pipeline(使用RAGAS等工具)
  4. 部署到Serverless平台(如Vercel Edge Functions)

推荐资源:

AI搜索不是终点,而是智能交互的起点。用好RAG-Fusion,让你的知识库真正“懂”用户。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐