微信扫码
添加专属顾问
我要投稿
掌握RAG检索策略,让你的知识库检索效率提升200%! 核心内容: 1. 检索前优化的三大策略:问题改写、多查询生成、子问题拆解 2. 关键词检索与向量检索的优劣对比 3. 生产环境中的定向优化方法与效果评估
咱们的知识库,经过清洗
、分块
、向量化
后,已经存入向量数据库中了。那么如何检索和召回这些知识?
今天就来聊聊RAG的检索策略。
如果想要达到比较好的检索效果,首先需要对检索的query进行优化。常见的优化策略如下:
通常在检索知识库之前,会需要调用大模型,结合上下文对用户的问题进行改写和优化。
# 原始对话
Q: 请给我推荐一门编程语言
A: python
Q: 我该如何开始?
----
# 说明
如果直接使用"我该如何开始"去检索知识库
显然效果是很不好的
# 基于上下文进行问题改写
Q: 我应该如何开始学习python?
# 说明
根据上下文改写后的问题,具备了比较好的语义完整度。
将单个查询拓展为多个相关的问题进行查询,从而丰富上下文内容的多样性和覆盖范围。
# 用户问题
Q: 我想学习PYTHON
# 提示词
你是一个AI语言模型助手。
你的任务是针对给定的用户问题生成五个不同版本的表述,以便从向量数据库中检索相关文档。
通过对用户问题生成多种角度的表述,你的目标是帮助用户克服基于距离的相似性搜索的一些局限性。
将这些替代问题用换行符分隔开。
原始问题:{{ question }}
# 改写后的问题
Q1: 如何高效掌握Python编程?
Q2: 学习Python的最佳路径是什么?
Q3: Python入门教程推荐有哪些?
Q4: 从零开始学Python应该怎么做?
Q5: Python编程技能提升方法有哪些?
-----
使用改写后的5个问题,分别检索知识库
得到5组不同的检索结果
最终再通过大模型把5种结果进行筛选合并
生成最佳答案
通过把一个复杂的问题,拆解成若干个简单的子问题,分步进行检索,最终回答用户的问题。
# 用户原始问题
Q: Coze和dify有啥区别?
# 改写后的问题
Q1: Coze的基本介绍
A1: Coze 是字节跳动旗下...
Q2: Dify基本介绍
A2: Dify 是一个开源的LLM应用平台...
Q3: Coze和Dify有啥区别?
A3: 基于上面的两个检索结果生成最佳答案
以上只列举了比较常见的优化策略,实际上检索词的优化会很大程度上决定后续检索的质量。
实际生产场景需要根据情况进行定向优化, 以达到最佳的检索效果。
经过优化后的检索词,已经具备较好检索效果了。接下来就是要通过检索词把对应的知识片段找出来。
这个是传统的检索策略,使用检索词对分段原文或者分段标签进行模糊匹配查询。
优点是能够精准匹配关键词,缺点是无法理解同义词、近义词。
# 知识原文
北京故宫中存放了超过180万件珍贵文物。
# 关键词
北京、故宫、文物
# 用户问题
Q: 故宫中有多少件文物?
# 匹配了关键词 "故宫"和"文物"
# 能够召回原文片段
A: 北京故宫中存放了超过180万件珍贵文物。
# 但问题如果变成
Q:紫禁城中有多少件宝贝?
# 这时候由于无法匹配关键词,召回就失败了
A: 不知道
语义检索就是通过把检索词
和待检索文章
都转换成密集向量后再进行检索。
语义上越接近的词,在向量数据库中的距离就越接近
不了解的同学也可以去看上一篇:
使用RAG构建高质量知识库(三)- 数据嵌入
核心代码实现,这里用到了openai-sdk
、Milvus向量数据库
、阿里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) {
returnawaitthis.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欧氏距离
作为度量单位,值越小,相似度越高。
其他的度量单位:
全文检索通过BM25算法
或者SPLADE预训练模型
把文档转换为稀疏变量。通过TF词频
、IDF逆文档频率
等统计算法指标,“猜”出文档和检索词之间的相关性。
核心代码实现:
# query不需要向量化,所以也不消耗token
const query = 'The founding time of Snow Beer';
# 直接调用向量数据库进行查询
const sparse_res = await milvusService.search(query, 3);
async search(query, limit = 10) {
returnawaitthis.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: 'Brave the World: Flagship product for mass markets, known for its slogan "Snow Beer, Brave the World."',
id: '460215000564761309'
}
]
这里度量单位只能只用BM25
,值越大,相关性越高。一般情况下BM25就可以替代传统的关键词检索来进行精确匹配了。当然也可以结合使用。
简单来说就是分别使用全文检索
和语义检索
得到结果,再通过一定的策略进行结果聚合。
当然一般的向量数据库都有封装好的方法可以直接调用。
例如Milvus使用例子:
const hybrid_res = await milvusService.search(search_vector, query, 10);
async hybrid_search(vector, query, limit = 10) {
returnawaitthis.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
},
}
})
}
混合检索后的结果通过RRF
或者Weighted
策略进行聚合。
那么RRF和Weight又是啥?
上面介绍了几种常见的检索策略。实际应用场景下,基本上都会使用多路召回
分别使用各种策略检索得到结果。然后通过重排序进行优中选优。
有点像足球世界杯,先通过小组赛进行海选(各种策略分别进行海选召回),然后各个小组的优胜者再进行淘汰赛决出冠军(重排序)。
这是一种仅使用每种结果的排名进行融合排序的算法。
一个例子:
你和你的朋友都在找一本丢失的书
每个朋友都有一个针对“书在哪里的猜测排名”
人员 书架 床下 桌上
朋友A 1 2 3
朋友B 3 1 2
朋友C 2 1 3
那么,针对每一个地方:
桌上:1/3 + 1/2 + 1/3 = 1.16
床下: 1/2 + 1/1 + 1/1 = 2.5
书架: 1/1 + 1/3 + 1/2 = 1.83
所以RRF算法在考虑了不同朋友的猜测后
得出书最可能在床下(2.5)
这种算法的好处是只考虑不同策略的排名,而完全不考虑分数,避免分数之间的差异化。
这种算法通过给每个分路设置一个权重值,然后根据每个分路的算法,对打分进行归一化处理(不同分数的尺度可能是不同的),然后加权计算最终结果。
一个简单的算法例子:
/**
* 合并结果并应用加权排序
* @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));
}
上面的两种算法都不消耗token,优点是简单速度快。但缺点都是其中不够精准。
所以现在主流的方案都是先通过RRF或者加权算法归并一轮,再调用Rerank Model进一步进行筛选。
咱们这里选用的是阿里的gte-rerank-v2
模型进行演示。
直接上代码:
// 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
}
})
});
returnawait response.json();
};
// 调用重排序算法
const rerankRes = await rerank(query, allResults.map(item => item.name));
// 找到最优解
const topIndex = rerankRes?.output?.results?.[0]?.index ?? 0;
console.log('重排序结果:', allResults[topIndex])
以上介绍的都是一些常见的优化策略,掌握这些大多数的文档都已经能够很好的进行召回了。但是实际生产场景,依然会面临不小的挑战。
更希望大家掌握的是调优的思路,当面临实际复杂场景时,可以生成自己的一套优化策略,定向进行知识库的优化效果更加。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-08-28
自适应RAG:用本地 LLM 构建更聪明的检索增强生成系统
2025-08-28
RAG检索后如何应用更有效?
2025-08-28
RAG 不止能检索!它还能在 LangGraph 中当“工具调用大脑”
2025-08-28
RAG进阶神技:让AI自动将“人话”翻译成SQL和Cypher查询!
2025-08-28
如何将 RAG 检索召回率从 50% 提高到 95% 以上
2025-08-28
告别“搜不到、搜不准”:用这套查询优化,让你的RAG检索召回率飙升
2025-08-28
比RAG提升27.4%,阿里等ComRAG利用“质心式”记忆机制实现实时社区问答
2025-08-27
如何评估RAG系统:给你的AI助手做个"体检"
2025-06-05
2025-06-06
2025-06-05
2025-06-05
2025-06-20
2025-06-20
2025-06-24
2025-07-15
2025-06-24
2025-06-05