游乐游手机版
首页/AI热点日报/热点详情

RAG构建高质量知识库(四)数据检索实用方法详解

类型:热点整理2026-07-22
RAG检索流程包括检索前优化、知识检索与重排序三大环节。优化阶段通过问题改写、多查询生成和子问题拆解提升查询质量。检索阶段采用关键词、语义、全文或混合检索方式召回相关知识。重排序阶段利用RRF算法融合多路结果,确保最佳答案优先呈现。

掌握RAG(检索增强生成)检索策略,能让你的知识库在海量数据中精准、快速地定位所需信息。本教程将深入解析RAG检索的三大核心环节,助你轻松驾驭检索全流程,显著提升知识库的响应质量与效率。

检索前优化:让提问更精准

在正式检索知识库之前,我们首先需要优化用户提出的问题(query)。一个模糊或不完整的问题,很可能导致检索结果不理想。以下是三种常见且高效的优化策略:

1. 原始问题改写

当用户提出一个问题后,调用一个大语言模型,结合对话上下文对这个原始问题进行改写,使其具备更完整的语义。

# 原始对话
Q: 请给我推荐一门编程语言
A: python
Q: 我该如何开始?
----
# 说明
如果直接使用"我该如何开始"去检索知识库
显然效果是很不好的

# 基于上下文进行问题改写
Q: 我应该如何开始学习Python?

# 说明
根据上下文改写后的问题,具备了比较好的语义完整度。

小提示: 问题改写是提升检索召回率的第一步,尤其适用于用户提问不够完整或带有指代关系的场景。

2. 多查询生成 (Multi-Query)

将单个用户问题扩展为多个角度不同、表达方式不同的子问题,分别进行检索,从而覆盖更广的相关信息。

# 用户问题
Q: 我想学习PYTHON

# 提示词
你是一个AI语言模型助手。
你的任务是针对给定的用户问题生成五个不同版本的表述,以便从向量数据库中检索相关文档。
通过对用户问题生成多种角度的表述,你的目标是帮助用户克服基于距离的相似性搜索的一些局限性。
将这些替代问题用换行符分隔开。
原始问题:{{ question }}

# 改写后的问题
Q1: 如何高效掌握Python编程?
Q2: 学习Python的最佳路径是什么?
Q3: Python入门教程推荐有哪些?
Q4: 从零开始学Python应该怎么做?
Q5: Python编程技能提升方法有哪些?
-----
使用改写后的5个问题,分别检索知识库
得到5组不同的检索结果

最终再通过大模型把5种结果进行筛选合并
生成最佳答案

3. 子问题拆解 (Sub-Question)

当用户提出的问题比较复杂,包含多个方面时,可以将其拆解成一系列更简单、更具体的子问题。然后分别检索每个子问题的答案,最后综合所有信息形成最终回答。

# 用户原始问题
Q: Coze和dify有啥区别?

# 改写后的问题
Q1: Coze的基本介绍
A1: Coze 是字节跳动旗下...

Q2: Dify基本介绍
A2: Dify 是一个开源的LLM应用平台...

Q3: Coze和Dify有啥区别?
A3: 基于上面的两个检索结果生成最佳答案

小提示: 以上只是几种基础优化策略。实际应用中,检索词的优化程度直接决定了后续检索的成败,你需要根据业务场景灵活选择或组合使用。

常见问题: 检索前优化是否总是必要的?

  • 不一定。对于已经非常明确、完整且简单的问题(如“北京故宫有多少件文物?”),可以直接进行检索。但对于不完整、模糊或有歧义的问题,优化能显著提升检索效果。

知识检索:高效召回相关知识

问题优化后,接下来就是利用这些检索词,从知识库中找出最相关的知识片段。目前主流的方法有四种:

1. 关键词检索(传统检索)

这是最基础的检索方式,使用检索词对文本或文本标签进行精确的模糊匹配(如正则匹配)。

优点: 能够精准匹配关键词。
缺点: 无法理解同义词、近义词,容易造成漏检。

# 知识原文
北京故宫中存放了超过180万件珍贵文物。
# 关键词
北京、故宫、文物

# 用户问题
Q: 故宫中有多少件文物?
# 匹配了关键词 "故宫"和"文物"
# 能够召回原文片段
A: 北京故宫中存放了超过180万件珍贵文物。

# 但问题如果变成
Q:紫禁城中有多少件宝贝?
# 这时候由于无法匹配关键词,召回就失败了
A: 不知道

注意: 当用户使用“紫禁城”代替“故宫”,或用“宝贝”代替“文物”时,传统的关键词检索就会失效。

2. 语义检索(向量检索)

语义检索通过Embedding模型将检索词和文档都转换为多维向量(密集向量),然后在向量空间中计算它们的相似度。语义上越接近的内容,其向量距离就越近。

核心步骤: 检索词向量化 ——> 在向量数据库中搜索最相似的向量。

以下是一个使用openai-sdkMilvus向量数据库阿里text-embedding-v4嵌入模型的代码示例:

# Step1: 检索词向量化
const search_vector = await embedding(query);
// 调用Embedding Model进行向量化
const embedding = async (text) => {
const response = await openai.embeddings.create({
    model: "text-embedding-v4",
    input: text,
  });
return response.data[0].embedding;
};

# Step2: 密集向量检索
const vector_res = await milvusService.search(search_vector, 3);
# 查询向量数据库
async search(vector, limit = 10) {
    return await this.client.search({
        collection_name: 'test',
        vector: vector,
        limit: limit,
        output_fields: ['id', 'block_id', 'name'],
        metric_type: 'L2',
        params: { nprobe: 10 }
    });
}

检索结果如下:

# 检索词
`The founding time of Snow Beer`

# 检索词向量化
[
     0.03072373941540718,  -0.010284383781254292,  -0.006375404074788094,
    -0.06936439871788025,  0.0009934211848303676,   -0.04058944061398506,
  ... 924 more items
]

# 密集向量检索结果
[
  {
    score: 0.46093612909317017,
    block_id: '94',
    name: 'Below is a detailed introduction to Snow Beer:',
    id: '460215000564761333'
  },
  {
    score: 0.517002284526825,
    block_id: '95',
    name: '1. Brand History & Development Origins: Snow Beer traces its roots to Shenyang Beer Factory, established in 1957.',
    id: '460215000564761323'
  },
  {
    score: 0.790127158164978,
    block_id: '94',
    name: "Snow Beer is one of China's most renowned beer brands, owned by China Resources Snow Breweries (China) Co., Ltd. (CR Snow), a joint venture between the state-owned China Resources Group and the global beer giant SABMiller.",
    id: '460215000564761331'
  }
]

注意: 示例中使用的是L2欧氏距离作为度量单位,L2值越小,代表两个向量越相似。

常见的向量度量单位对比表:

度量单位说明取值范围
L2(欧氏距离)值越小表示相似度越高。[0, ∞)
IP(内积)值越大,表示相似度越高。[-1, 1]
COSINE(余弦相似度)数值越大,表示相似度越高。[-1, 1]
JACCARD值越小,表示相似度越高。[0, 1]
MHJACCARD根据 MinHash 签名位估算 Jaccard 相似度;距离越小 = 越相似[0, 1]
HAMMING值越小表示相似度越高。[0,dim(向量)
BM25根据术语频率、反转文档频率和文档规范化对相关性进行评分。[0, ∞)

3. 全文检索(稀疏检索)

全文检索通过BM25算法SPLADE等模型将文档转换为稀疏向量,利用TF-IDF等统计方法,评估文档与检索词之间的相关性。 与语义检索不同,它无需进行Query向量化,因此不消耗Embedding模型的Token。

代码示例:

# query不需要向量化,所以也不消耗token
const query = 'The founding time of Snow Beer';
# 直接调用向量数据库进行查询
const sparse_res = await milvusService.search(query, 3);

async search(query, limit = 10) {
    return await this.client.search({
        collection_name: 'test',
        anns_field: 'sparse_vector',
        limit: limit,
        data: [query],
        metric_type: 'BM25',
        output_fields: ['id', 'block_id', 'name']
    });  
}

检索结果:

# 检索词
'The founding time of Snow Beer'

# 稀疏向量检索结果: 
[
  {
    score: 4.728769302368164,
    block_id: '94',
    name: "Snow Beer is one of China's most renowned beer brands, owned by China Resources Snow Breweries (China) Co., Ltd. (CR Snow), a joint venture between the state-owned China Resources Group and the global beer giant SABMiller.",
    id: '460215000564761331'
  },
  {
    score: 3.9664859771728516,
    block_id: '108',
    name: 'Domestic Dominance: Snow has been the world’s top-selling single beer brand since 2006, with 2022 sales reaching ~11 billion liters (30% of China’s market share).',
    id: '460215000564761291'
  },
  {
    score: 3.210528612136841,
    block_id: '100',
    name: 'Bra ve the World: Flagship product for mass markets, known for its slogan "Snow Beer, Bra ve the World."',
    id: '460215000564761309'
  }
]

注意: 全文检索只能使用BM25作为度量单位,BM25值越大,代表相关性越高。 它可以在一定程度上替代传统的关键词检索,实现更灵活的精确匹配。很多场景会结合全文检索和语义检索一起使用。

4. 混合检索

混合检索是结合了语义检索全文检索两种方式的综合方案,旨在取长补短。

流程: 分别执行语义和全文检索,得到两组结果,然后通过一定的策略(如RRF或加权)进行结果融合与排序。

许多向量数据库(如Milvus)都提供了封装好的混合检索接口。 以下是Milvus的使用示例:

const hybrid_res = await milvusService.search(search_vector, query, 10);

async hybrid_search(vector, query, limit = 10) {
    return await this.client.hybridSearch({
        collection_name: 'test',
        limit: limit,
        output_fields: ['id', 'block_id', 'name'],
        data: [{
            // 密集向量检索
            anns_field: 'vector',
            data: [vector],
            metric_type: 'L2',
            params: { nprobe: 10 }
        }, {
            // 稀疏向量检索
            anns_field: 'sparse_vector',
            data: [query],
            metric_type: 'BM25'
        }],
        // 排序策略
        rerank: {
            strategy: "rrf", // 使用RRF(Reciprocal Rank Fusion)策略
            params: {
              k: 60, // RRF参数k,默认60
            },
        }
    })
}

常见问题: 我应该选择哪种检索方式?

  • 关键词检索: 适用于需要完全精确匹配的场景,如代码片段、专有名词检索。
  • 语义检索: 推荐作为默认选择,能处理同义词、近义词,理解能力更强。
  • 全文检索: 适合处理包含大量罕见词的查询,或在不消耗Embedding Token的情况下进行统计相关性分析。
  • 混合检索: 综合了语义和全文的优势,通常在复杂场景下效果最好,是生产环境的首选。

重排序:优中选优,排出最佳顺序

通过上述多种策略(多路召回)得到大量候选结果后,我们需要一个“裁判”来对这些结果进行重新排序和筛选,确保最相关的结果排在第一位。这个过程叫重排序。

1. RRF(Reciprocal Rank Fusion)

这是一种仅依赖不同检索结果中每个项目的排名的算法,不关心具体的分数。

核心思想: 如果一个项目在所有检索结果中的排名都很靠前,那么它的综合排名就高。

原理示例:
想象你和你的朋友都在找一本丢失的书,每个人都有一个关于书可能在哪里的猜测排名。

人员和地方 书架 床下 桌上
朋友A 1 2 3
朋友B 3 1 2
朋友C 2 1 3

计算每个地方的综合得分:
桌上:1/(1+3) + 1/(1+2) + 1/(1+3) = 1/4 + 1/3 + 1/4 = 0.833
床下:1/(1+2) + 1/(1+1) + 1/(1+1) = 1/3 + 1/2 + 1/2 = 1.333
书架:1/(1+1) + 1/(1+3) + 1/(1+2) = 1/2 + 1/4 + 1/3 = 1.083

得出最终结论:书最有可能在床下(得分最高)。

优点: 简单、快速、不消耗Token,且能有效消除不同检索方法因打分尺度不同带来的偏差。

常见问题: RRF的k参数有什么作用?

  • k是一个常数,用于平滑排名带来的影响。默认值通常是60。它的作用是防止某个项目因为排名靠后而得分过低。增大k值会使得排名较低的项目对最终结果的影响力变大,而减小k值则会放大排名靠前项目的影响力。

2. Weighted加权策略

这种算法需要为每个检索策略设置一个权重,然后对每个策略返回的结果分数进行归一化处理,最后计算加权总分。

一个简单的代码实现示例:

/**
 * 合并结果并应用加权排序
 * @param {array} resultsList 各个搜索的结果列表
 * @param {number[]} weights 权重数组
 * @param {number} limit 最终返回结果数量
 * @returns {object} 格式化后的搜索结果
 */
function mergeAndWeightResults(resultsList, weights, limit) {
// 结果合并表 {id: {data: 文档数据, scores: [各搜索的分数]}}
const merged = {};

// 归一化权重
const sumWeights = weights.reduce((sum, w) => sum + w, 0);
const normalizedWeights = weights.map(w => w / sumWeights);

// 收集所有结果并记录各搜索的分数
  resultsList.forEach((results, searchIndex) => {
    results.results.forEach(item => {
      if (!merged[item.id]) {
        merged[item.id] = {
          data: item,
          scores: newArray(resultsList.length).fill(0)
        };
      }
      merged[item.id].scores[searchIndex] = item.score;
    });
  });

// 计算加权分数并排序
const weightedResults = Object.values(merged).map(item => {
    // 计算加权分数
    let weightedScore = 0;
    for (let i = 0; i < normalizedWeights.length; i++) {
      weightedScore += normalizedWeights[i] * normalizeScore(item.scores[i], i);
    }
    
    return {
      ...item.data,
      weightedScore, // 加权后的综合分数
      originalScores: item.scores // 保留原始分数供调试
    };
  });

// 按加权分数降序排序
  weightedResults.sort((a, b) => b.weightedScore - a.weightedScore);

// 返回格式与Milvus原生搜索一致
return {
    status: { error_code: "Success", reason: "" },
    results: weightedResults.slice(0, limit),
    recalls: resultsList.map(r => r.recalls?.[0] || 0)
  };
}

/**
 * 分数归一化处理(不同搜索的分数可能尺度不同)
 * @param {number} score 原始分数
 * @param {number} searchIndex 搜索索引
 * @returns {number} 归一化后的分数
 */
function normalizeScore(score, searchIndex) {
// 实际应用中应根据不同搜索类型调整归一化方法
// 这里使用简单的sigmoid归一化示例
return1 / (1 + Math.exp(-score));
}

常见问题: RRF和加权策略,我该选哪个?

  • RRF: 当你对各个检索策略的评分置信度不高,或者各策略的评分尺度差异巨大时(如语义检索得分在0-1之间,而BM25得分可达10以上),RRF是不错的选择,因为它只看排名。
  • 加权策略: 当你对各个检索策略的效果有明确认知,并愿意为其分配不同的重要性时,加权策略更灵活,能精细调优。

3. Rerank Model(重排序模型)

RRF和加权策略虽然速度快,但精确度有限。目前最主流的方案是:先使用RRF或加权策略进行初步筛选,再调用一个专门的Rerank Model做最终的精细筛选和排序。

这里以阿里的gte-rerank-v2模型为例,演示如何使用Rerank Model:

// rerank方法,直接使用https的方式
const rerank = async (query, documents) => {
    const response = await fetch('https://dashscope.aliyuncs.com/api/v1/services/rerank/text-rerank/text-rerank', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${openai.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        model: 'gte-rerank-v2',
        input: {
          query: query,
          documents: documents
        },
        parameters: {
          top_n: 1 // 只返回最相关的一个结果
        }
      })
    });
    return await response.json();
};
// 调用重排序算法
const rerankRes = await rerank(query, allResults.map(item => item.name));
// 找到最优解
const topIndex = rerankRes?.output?.results?.[0]?.index ?? 0;
console.log('重排序结果:', allResults[topIndex])

小提示: Rerank Model 能够更准确地衡量查询和文档之间的相关性,但会消耗Token和响应时间。在实践中,建议在可接受的性能和成本范围内,对重要的查询使用Rerank Model。

结语

本教程系统地介绍了从检索前优化到多路召回,再到最终重排序的完整RAG检索流程。掌握这些常见的优化策略,已经能够应对大多数知识库的检索需求。

然而,每个实际的生产环境都可能面临独特的挑战。真正的价值在于掌握调优的思路。建议你在理解每种策略的原理和优缺点后,根据自己业务的特点(如数据类型、查询模式、性能要求),灵活组合并定制一套专属的优化方案,以实现最佳的检索效果。

来源:https://www.53ai.com/news/RAG/2025082847981.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。