datawhale 组队学习 RAG技术全栈指南task4打卡
混合检索不是简单的“拼凑”,而是为了弥补单一检索模态的数学缺陷。稠密检索(Dense Retrieval / Vector Search)的缺陷:基于语义向量。它擅长理解“意思”,但对精确匹配非常弱。例如,搜索“错误码 8023”,向量模型可能会将其关联到“网络连接错误”,但不一定能精准匹配到含有“8023”这个具体数字的文档。稀疏检索(Sparse Retrieval / Keyword Sea
1. 混合检索 (Hybrid Search):精度与广度的数学融合
混合检索不是简单的“拼凑”,而是为了弥补单一检索模态的数学缺陷。
核心痛点
-
稠密检索(Dense Retrieval / Vector Search)的缺陷:基于语义向量。它擅长理解“意思”,但对精确匹配非常弱。例如,搜索“错误码 8023”,向量模型可能会将其关联到“网络连接错误”,但不一定能精准匹配到含有“8023”这个具体数字的文档。
-
稀疏检索(Sparse Retrieval / Keyword Search)的缺陷:基于词频(如 BM25)。它擅长精确匹配字符,但无法理解语义。例如,搜索“苹果手机”,它无法匹配到只有“iPhone”字眼的文档,因为如果不建立同义词库,这两个词在字面上毫无重叠。
深度实现机制
混合检索通过同时执行上述两种检索,然后将结果融合。
A. 算法层:BM25 + Embedding
-
并行检索:
-
路 A (Sparse):对 Query 进行分词,去除停用词,在倒排索引中运行 BM25 算法,计算词项(Term)在文档中的 TF-IDF 权重。
-
路 B (Dense):将 Query 输入 Embedding 模型(如
text-embedding-3或bge-m3),生成 768 或 1024 维向量,在向量数据库中进行 ANN(近似最近邻)搜索。
-
-
结果池:你现在得到了两个列表,一个是 BM25 认为最重要的 Top-50,一个是向量认为最相关的 Top-50。
B. 融合层:RRF (Reciprocal Rank Fusion,倒数排名融合)
这是混合检索中最关键的一步。因为 BM25 的得分(可能是 0-15)和向量相似度(可能是 0.6-0.9)不在同一个量级,直接加权求和(Weighted Sum)非常难调参。RRF 是一种基于排名的“无参数”融合算法。
-
RRF 公式:
RRFscore(d) = \sum_{r \in R} \frac{1}{k + r(d)}
-
$d$:文档。
-
$R$:不同的检索器集合(BM25 和 Vector)。
-
$k$:平滑常数(通常设为 60)。
-
$r(d)$:该文档在某个检索器中的排名(Rank)。
-
-
原理详解:如果一个文档在 BM25 中排第 1,在 Vector 中排第 1,它的分数会极高。如果它只在其中一个列表中出现且排名靠后,分数就会很低。RRF 巧妙地规避了分值标准不统一的问题,只看“排名”。
应用场景建议
-
代码库搜索:必须用混合检索。函数名(精确)+ 功能描述(语义)。
-
电商搜索:必须用混合检索。产品型号(精确)+ 描述(语义)。
2. 查询构建 (Query Construction / Self-Querying):自然语言转结构化过滤
许多开发者误以为 RAG 只是把文本扔进向量库。但在实际业务中,数据往往带有大量的结构化元数据(Metadata)。查询构建的本质,是将用户的自然语言意图,转化为向量检索 + 结构化过滤的组合。
核心痛点
用户提问:“我想找去年、评分最高的几部科幻电影。”
-
纯向量检索的失败:Embedding 模型很难在向量空间中精确表达“去年(2024年)”这个时间概念,也很难通过距离来衡量“评分数值”。
-
解决方案:将“去年”和“评分最高”从向量搜索中剥离出来,转化为数据库的 Filter 条件。
深度工作流 (Self-Querying)
A. 属性提取 (Attribute Extraction)
利用 LLM 分析用户的 Prompt,提取出两部分信息:
-
查询内容 (Search Term):用于向量检索的文本(如:“科幻电影”)。
-
过滤条件 (Filter Conditions):用于 SQL 或 Metadata 过滤的结构化数据。
-
Prompt 示例:
用户输入:"推荐几双 100 美元以下的耐克跑步鞋。"
你的任务:提取品牌、价格区间和搜索关键词。
输出 JSON:
JSON{ "query": "跑步鞋", "filter": { "brand": "Nike", "price": {"$lt": 100} } }
B. 检索执行 (Execution Strategy)
得到 JSON 后,进入向量数据库执行,这里有两种核心策略:
-
Pre-filtering (前置过滤):推荐方式。先根据
brand="Nike" AND price < 100筛选出所有符合条件的文档,然后在这些文档中进行向量相似度搜索。这能保证结果 100% 符合硬性条件。 -
Post-filtering (后置过滤):先向量搜索 Top-100,然后再把不符合条件的剔除。缺点:如果符合条件的文档很少,可能都被过滤掉了,导致召回为零。
C. 难点与优化
-
基数过大 (High Cardinality):如果元数据字段有几万个可能的值(如具体的“作者名”),LLM 可能会产生幻觉或拼写错误。
-
优化:在 Prompt 中注入合法的 Enum 值列表;或者使用模糊匹配(Fuzzy Match)来校正 LLM 提取的过滤词。
-
3. Text-to-SQL:结构化数据的 RAG
企业的核心数据往往不在文档里,而是在关系型数据库(Relational DB)中。Text-to-SQL 是 RAG 的一个特殊分支,它不检索文本块,而是检索数据行。
工作流程详解
A. Schema Linking (模式链接)
LLM 不知道你的数据库长什么样。你需要将数据库的 Schema(表名、列名、外键关系、甚至几行示例数据)喂给 LLM。
-
Context Window 挑战:如果数据库有 100 张表,Prompt 放不下。
-
优化:先利用 RAG 检索出与用户问题最相关的那几张表的 Schema,只把这部分 Schema 放入 Prompt。
B. SQL 生成与校验
-
Prompt Engineering:使用 Few-Shot Prompting(少样本提示)。提供 3-5 个“问题 -> 正确 SQL”的示例,极大提升准确率。
-
Self-Correction (自愈):
-
LLM 生成 SQL。
-
代码尝试在数据库执行。
-
如果报错(如
Column not found),将错误信息回传给 LLM,让它进行自我修正并重新生成。
-
C. 结果合成
数据库返回的是 Rows (表格数据)。
-
直接把表格扔给用户体验不好。
-
最后一步是将用户的原始问题 + 执行的 SQL + 查询结果(表格) 一起喂给 LLM,让它生成一段通顺的自然语言回答。
Text-to-SQL 的特有优化
-
语义层 (Semantic Layer):数据库的列名往往是缩写(如
c_limit),LLM 看不懂。需要在中间加一层映射,告诉 LLMc_limit= "Credit Limit (信用额度)"。 -
安全控制:绝对禁止 LLM 生成
DROP,DELETE,UPDATE语句。务必在数据库权限层面限制为READ ONLY,并在生成层进行关键词拦截。
4. 查询重构与分发 (Refactoring & Routing):理解意图的艺术
这是 RAG 变得“智能”的分水岭。用户的原始提问往往是模糊、缺失上下文或极其复杂的。直接检索原始提问通常效果不佳。
A. 查询重构 (Query Refactoring / Transformation)
1. 多路查询 (Multi-Query / Query Expansion)
-
场景:用户问题可能可以用多种方式表述,或者包含多个子问题。
-
做法:让 LLM 基于原始问题生成 3-5 个不同角度的变体。
-
原始:“RAG 怎么优化?”
-
变体 1:“RAG 向量检索的各种索引对比”
-
变体 2:“基于 LLM 的重排序策略”
-
变体 3:“混合检索的实现原理”
-
-
执行:并行检索这 5 个问题,然后对结果去重。这能极大提升召回率(Recall)。
2. 分解 (Decomposition / Sub-Questioning)
-
场景:复杂推理问题。
-
例子:“GitHub 的创始人现在的公司的最新产品是什么?”
-
做法:LLM 拆解问题:
-
GitHub 创始人是谁? -> 检索 -> 得到“Chris Wanstrath”。
-
Chris Wanstrath 现在在哪家公司? -> 检索 -> 得到“B company”。
-
B company 的最新产品是什么? -> 检索 -> 最终答案。
-
-
这是 CoT (Chain of Thought) 在检索过程中的应用,通常通过 Agent 循环执行。
3. HyDE (Hypothetical Document Embeddings)
-
原理:向量相似度中,“问题”和“答案”的向量距离其实挺远的(一个是疑问句,一个是陈述句)。
-
做法:
-
用户提问。
-
让 LLM 瞎编一个假设性答案(哪怕事实是错的,但涵盖了相关领域的术语)。
-
将这个“假设性答案”向量化,去数据库检索。
-
-
优势:利用“答案”去找“答案”,语义匹配度显著提高。
B. 查询分发 (Query Routing / Logic Routing)
RAG 系统往往集成了多种数据源(SQL 库、向量库、Web 搜索、工具 API)。Router 就像是一个交通指挥官。
1. 逻辑路由 (Logical Routing)
利用 LLM 的分类能力。
-
Prompt:
"你是一个路由助手。基于用户的问题,选择以下工具之一:['SQL_Database' (用于查销售数据), 'Vector_DB' (用于查公司文档), 'Calculator' (用于数学计算)]。"
用户输入:"去年我们在上海的销售额是多少?"
输出:"SQL_Database"
2. 语义路由 (Semantic Routing)
这是一种更快速、低成本的方法。
-
做法:预先为每个 Tool 定义几个“典型问题”并计算向量。
-
执行:当用户新问题进来时,计算其向量,查找与哪个 Tool 的“典型问题”向量最接近,就路由给谁。这种方法不需要调用 LLM,仅需一次向量计算,速度极快。
总结:如何组合使用?
一个顶级的 RAG 系统通常是这样串联的:
-
用户提问。
-
查询路由:判断是去查 SQL 还是查向量库。
-
如果是 SQL -> Text-to-SQL 流程。
-
如果是文档 -> 查询重构(生成多个变体)。
-
-
查询构建:从变体中提取元数据过滤器(时间、分类)。
-
混合检索:带上过滤器,并行执行 BM25 + Vector Search。
-
RRF 融合:合并结果。
-
重排序 (Rerank):对 Top-K 结果精排。
-
生成:LLM 给出答案。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)