超越向量RAG:确定性稀疏检索
检索增强生成(RAG)已成为在私有或特定领域知识上构建LLM应用最常见的架构之一。
标准方法是熟悉的:
文档 → 嵌入模型 → 向量数据库 → 相似性搜索 → 检索上下文 → LLM
它工作得非常好。
但它也引入了基础设施、计算成本、延迟和操作复杂性。
每个文档都需要转换为向量表示。这些向量需要存储和索引。查询需要在检索发生之前通过嵌入模型。根据规模和架构,系统可能还需要向量数据库、嵌入服务、GPU资源或外部API调用。
然而,对于许多企业工作负载,检索问题比语义搜索看起来的要简单得多。
如果用户问:
"显示客户ACME的发票"
我们可能不需要神经嵌入模型来理解ACME、客户和发票是重要的检索信号。
经典的信息检索技术如TF-IDF可以极其高效地识别这些信号。
这引出了不同的架构:
文档 → TF-IDF索引 → 查询 → 稀疏检索 → 检索上下文 → LLM
没有嵌入API。
没有稠密向量。
没有向量数据库。
没有神经检索模型。
只有确定性索引和极快的词汇检索。
本文探讨这种方法,它何时有效,何时失败,以及为什么它对于大规模RAG系统可能出奇地有效。
1. 现代RAG的问题
典型的RAG管道看起来像这样:
1. 摄入文档
文档从文件、数据库、API、源代码或其他系统加载。
2. 将文档分割成块
大型文档被分成更小的部分。
3. 生成嵌入
每个块通过嵌入模型。
4. 存储向量
嵌入存储在向量数据库或另一个相似性搜索索引中。
5. 嵌入查询
用户的问题也被转换为向量。
6. 执行相似性搜索
查询向量与文档向量进行比较。
7. 将检索到的块发送给LLM
最相关的块被放入模型上下文。
这种架构提供语义检索。
例如,查询如:
"我们在交通上花了多少钱?"
可能检索到包含以下内容的文档:
"物流和差旅总支出为€82,000。"
单词不必完全匹配。
这是语义嵌入的主要优势。
然而,这种能力是有代价的。
2. 基于嵌入的RAG的隐性成本
假设我们有:
1000万文档
每个文档产生多个块。
如果每个块需要嵌入,我们现在可能有数千万甚至数亿个向量。
这些向量消耗存储空间,需要被索引。
管道还需要在以下情况下执行嵌入生成:
- 新文档到达,
- 文档更改,
- 文档重新索引,
- 嵌入模型更改,
- 或查询到达。
查询本身也需要被嵌入。
因此架构变为:
查询 → 嵌入模型 → 向量搜索 → 检索
而不是简单地:
查询 → 搜索索引 → 检索
还有另一个重要问题:
确定性。
嵌入模型在检索中引入了机器学习组件。
检索结果可能取决于:
- 嵌入模型,
- 模型版本,
- 预处理,
- 分块,
- 向量索引配置,
- 相似性度量,
- 有时是近似最近邻参数。
对于许多企业应用程序,特别是结构化或半结构化数据,这种复杂性可能是不必要的。
3. TF-IDF:1970年代的想法用于现代RAG
TF-IDF代表:
词频-逆文档频率
它是信息检索中的经典技术之一。
基本思想很简单:
如果一个词在文档中频繁出现,但在整个集合中不频繁出现,那么它对文档很重要。
例如,想象三个文档:
文档A
ACME软件许可证发票
文档B
ACME咨询服务发票
文档C
ACME硬件发票
单词发票无处不在。
因此它携带相对较少的判别信息。
然而,单词软件只出现在文档A中。
它成为更强的检索信号。
TF-IDF从数学上捕捉这一点。
4. TF-IDF详解
第一个组件是词频(TF)。
简单版本是:
TF(t,d) = 词项t在文档d中出现的次数
归一化版本可以是:
TF(t,d) = count(t,d) / total_terms(d)
第二个组件是逆文档频率(IDF)。
常见公式是:
IDF(t) = log(N / DF(t))
其中:
- N = 文档总数
- DF(t) = 包含词项
t的文档数
最终的TF-IDF分数是:
TF-IDF(t,d) = TF(t,d) × IDF(t)
这创建了文档集合的稀疏表示。
不是将文档表示为稠密向量如:
[0.132, -0.721, 0.043, …, 0.912]
我们主要通过实际出现的词项来表示它。
例如:
文档:
"ACME软件许可证发票"
TF-IDF表示:
ACME → 0.42
software → 0.81
license → 0.73
invoice → 0.21
大多数可能的词汇词项值为零。
这就是为什么TF-IDF被称为稀疏表示。
5. 从TF-IDF到检索
一旦语料库被索引,查询可以使用相同的词汇进行转换。
假设查询是:
"ACME软件发票"
系统计算查询的TF-IDF表示,并与索引文档进行比较。
常见的相似性函数是余弦相似性。
公式是:
cosine_similarity(A,B) = (A · B) / (|A| × |B|)
换句话说:
相似性 = 点积 / 向量长度的乘积
结果范围大约从:
0 → 不相关
到
1 → 高度相似
因为TF-IDF向量是稀疏的,系统不需要在每个可能的词汇维度上执行昂贵的比较。
相反,它可以对实际存在的词项进行操作。
6. 重要区别:稀疏与稠密检索
现代嵌入系统通常产生稠密向量。
例如:
[-0.021, 0.442, -0.118, 0.731, ...]
每个维度通常包含一个值。
TF-IDF产生稀疏向量:
ACME → 0.42
software → 0.81
invoice → 0.21
这种区别很重要。
稠密嵌入试图编码语义含义。
TF-IDF主要捕获词汇相关性。
这意味着:
"软件许可证"
和
"应用程序订阅"
对人类来说可能语义相关,但词汇重叠很少。
稠密嵌入可能识别这种关系。
TF-IDF通常不能。
但反过来也很有价值。
对于精确标识符、名称、代码、ID、错误消息、API名称、数据库字段、产品代码和技术术语,词汇匹配可能非常强大。
7. 关键洞察:并非每个RAG问题都是语义搜索问题
这是这种方法的核心思想。
考虑包含以下内容的企业系统:
- 5000万数据库记录
- 1000万发票
- 500万客户记录
- 源代码仓库
- 配置文件
- API规范
- UI定义
- 技术文档
- 日志
- 元数据
许多检索问题不是真正的语义问题。
它们更接近于:
"找到包含此标识符的记录。"
或:
"找到提及此API的文件。"
或:
"找到包含此字段的规范。"
或:
"找到与此客户号相关的文档。"
在这些情况下,引入神经嵌入模型可能是不必要的。
确定性词汇索引通常可以直接回答问题。
8. 架构
架构变得非常简单:
离线
│
▼
文档
│
▼
文本提取
│
▼
分词
│
▼
TF-IDF索引
│
▼
稀疏搜索索引
│
│
┌────────┴────────┐
│ │
▼ ▼
查询 查询元数据
│ │
└────────┬────────┘
▼
TF-IDF搜索
│
▼
Top-K结果
│
▼
上下文构建器
│
▼
LLM
关键区别是昂贵的检索表示是一次性构建的。
LLM不负责发现信息。
确定性检索层首先找到它。
9. 检索成为编译步骤
思考这种架构有一个有趣的方式。
不是让LLM反复推理信息可能存在的位置,我们可以将部分工作转移到确定性预处理层。
系统有效地执行:
文档 → 索引 → 查询 → 确定性检索 → 上下文
然后LLM从已经组装好的相关信息开始。
这对于代理系统特别有用。
代理可能传统上执行:
推理
↓
搜索
↓
读取结果
↓
推理
↓
再次搜索
↓
读取结果
↓
推理
确定性检索系统可以构建更大的初始状态:
所需信息
↓
确定性检索
↓
上下文构建
↓
LLM推理
检索层因此表现得几乎像代理内存的编译器。
它将大型外部信息空间转换为紧凑的推理状态。
10. 示例:企业客户搜索
想象一个包含1亿记录的数据库。
用户问:
"找到与客户ACME GmbH相关的所有内容。"
向量RAG管道可以:
- 嵌入查询。
- 搜索向量数据库。
- 检索语义相似的块。
- 将它们传递给LLM。
TF-IDF系统可以识别高度判别的词项:
ACME
GmbH
customer
索引可以立即定位包含这些词项的文档。
检索到的文档可能包括:
Customer: ACME GmbH
Customer ID: C-18492
Invoices:
INV-10293
INV-10384
INV-10922
Projects:
PRJ-421
PRJ-882
Contracts:
CTR-182
CTR-193
LLM不需要搜索客户。
它接收相关信息。
11. 示例:源代码检索
这种方法对软件工程系统可以变得更有趣。
假设仓库包含200万行代码。
开发人员问:
"reconcileUIController在哪里使用?"
TF-IDF检索自然适合这类问题。
搜索索引可以识别:
reconcileUIController
reconcile.ui.spec.ts
reconcile.uicontroller.ts
reconcileUIController.test.ts
精确标识符成为极强的检索信号。
语义嵌入可能理解以下两者之间的关系:
"UI协调控制器"
和
"负责同步UI状态的组件"
但对于找到实际符号:
reconcileUIController词汇检索通常正是我们想要的。
12. 示例:错误检索
考虑包含数百万历史错误的应用程序。
开发人员收到:
TypeError: Cannot read properties of undefined
词汇检索系统可以立即搜索:
TypeError
Cannot
read
properties
undefined
并检索历史出现。
然后它可以向LLM提供:
先前出现 #1
----------------------
File: user.controller.ts
Line: 184
Cause: user object was not initialized.
先前出现 #2
----------------------
File: project.service.ts
Line: 92
Cause: missing database result.
这可能非常有效,因为错误消息包含高度判别的词项。
13. 为什么它可以非常快
主要的性能优势来自稀疏检索的性质。
想象一个词汇表:
1,000,000个词项
稠密嵌入可能为每个文档生成具有数百或数千个维度的向量。
稀疏索引只需要维护实际出现的词项的倒排列表。
概念上:
"ACME"
↓
文档17
文档92
文档19382
文档84722
这类似于传统搜索引擎的架构。
不是问:
"这些数百万向量中哪个在数学上最接近?"
我们可以问:
"哪些文档包含这些高价值词项?"
该查找可能非常高效。
14. 索引是重要的部分
性能不仅仅来自计算TF-IDF。
重要的架构决策是预计算索引。
不是在每个查询上执行:
文档
↓
分词
↓
计算TF-IDF
↓
搜索
我们做:
离线
文档
↓
分词
↓
计算TF-IDF
↓
构建倒排索引
↓
持久化索引
然后查询变为:
查询
↓
分词
↓
查找词项
↓
评分候选
↓
Top-K
这种分离至关重要。
昂贵的工作发生在索引期间。
在线路径保持轻量级。
15. 倒排索引
底层数据结构可以是倒排索引。
例如:
词项 文档
------------------------------
ACME [12, 18, 42, 91]
invoice [12, 18, 19, 42, 91]
software [12, 42]
license [12, 42, 77]
当查询包含:
ACME software
系统只需要考虑相关倒排列表的交集或并集。
因此候选集可以比整个语料库小得多。
这是经典搜索引擎能够以极低延迟操作巨大集合的原因之一。
16. TF-IDF不需要向量数据库
这是一个重要的架构区别。
TF-IDF检索系统本质上不需要向量数据库。
你可以使用以下方式存储索引:
- 倒排索引,
- 搜索引擎,
- 内存映射文件,
- SQLite,
- 自定义二进制结构,
- 本地文件,
- 或专用稀疏矩阵结构。
重要的对象是稀疏检索索引,而不是向量数据库。
这可以大大简化部署。
一个小服务可以执行:
索引加载
↓
查询
↓
稀疏检索
↓
Top-K文档
而无需运行单独的向量数据库集群。
17. 内存效率
稀疏表示也可以比稠密表示小得多。
假设词汇表包含:
1,000,000个词项
稠密表示概念上在所有维度上分配空间。
稀疏表示只存储出现的词项。
对于包含500个有意义词项的文档,我们可能存储大约:
词项ID
权重
而不是维护百万维的稠密结构。
实际内存消耗很大程度上取决于:
- 词汇表大小,
- 平均文档长度,
- 文档数量,
- 索引结构,
- 数值精度,
- 压缩,
- 和实现。
但基本优势仍然存在:
存储存在的内容,而不是存储零。
18. 检索质量
显而易见的问题是:
如果TF-IDF如此简单,为什么我们需要嵌入?
因为嵌入解决的是不同的问题。
考虑:
查询:
"如何终止员工?"
文档:
"雇佣关系可由任何一方在适用的通知期后终止。"
词汇重叠可能很少。
语义嵌入可能连接这些概念。
TF-IDF可能不能。
这就是语义检索获胜的地方。
因此,正确的结论不是:
TF-IDF比嵌入更好。
更准确的结论是:
当词汇信号足够时,TF-IDF通常是更好的检索机制。
19. TF-IDF特别有效的场景
基于TF-IDF的检索对以下情况特别有吸引力:
精确标识符
CUST-18293
INV-92881
PRJ-182
名称
ACME GmbH
Everest Systems
技术术语
reconcileUIController
actionType
EveDocument
columnDefs
错误消息
TypeError
ECONNREFUSED
ENOENT
配置键
database.connection.timeout
feature.enablePlaybook
API名称
getCustomerInvoices()
createProject()
结构化业务数据
customer
invoice
contract
project
employee
timesheet
具有一致术语的文档
企业系统通常使用受控词汇表。
这使得词汇检索出奇地强大。
20. 混合检索更加强大
最实用的架构可能不是:
TF-IDF 或 嵌入
而是:
TF-IDF + 嵌入
例如:
查询
│
┌────────┴────────┐
│ │
▼ ▼
TF-IDF搜索 向量搜索
│ │
└────────┬────────┘
▼
合并结果
│
▼
重新排序
│
▼
LLM
TF-IDF可以提供高度精确的词汇匹配。
嵌入可以恢复语义匹配。
两种检索机制互补。
21. 更有趣的优化:使用查询本身
还有另一种可能性。
不是嵌入每个文档,我们可以使用TF-IDF首先识别重要的查询词项。
例如:
"显示ACME GmbH与软件许可相关的所有发票。"
检索系统可以识别:
ACME
GmbH
invoice
software
licensing
并优先处理最强的词项。
然后LLM接收检索到的上下文。
这创建了一个管道,其中机器学习在提供最大价值的地方使用:
推理 → LLM
而检索保持:
确定性 → TF-IDF
这种分离可以使整个系统更容易调试和操作。
22. 确定性是一个特性
词汇检索最被低估的属性之一是确定性。
给定:
相同文档
+
相同索引
+
相同查询
+
相同评分配置
检索系统应该产生相同的结果。
这使得调试变得简单得多。
假设LLM给出了错误的答案。
使用确定性检索,你可以检查:
查询
↓
检索到的文档
↓
上下文
↓
LLM
↓
答案
你可以确定故障发生在:
检索
或
推理。
这种分离在生产AI系统中很有价值。
23. RAG变得更容易观察
传统RAG管道可能难以调试,因为许多组件交互:
分块
嵌入
向量索引
相似性度量
ANN参数
查询嵌入
检索
重新排序
提示构建
LLM
确定性TF-IDF管道更容易检查:
查询
↓
词项
↓
词项权重
↓
候选文档
↓
分数
↓
Top-K
↓
上下文
你几乎可以解释为什么文档被检索到。
例如:
文档:invoice_18293
匹配词项:
ACME → 0.82
invoice → 0.31
software → 0.67
总分:
1.80
这使得检索可解释。
24. 实用架构
生产实现可能如下所示:
┌────────────────────┐
│ 数据源 │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ 文档处理器 │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ 分词 │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ TF-IDF构建器 │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ 倒排索引 │
└─────────┬──────────┘
│
│
在线路由
│
▼
用户查询
│
▼
┌────────────────────┐
│ 查询分词 │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ 稀疏检索 │
└─────────┬──────────┘
│
▼
Top-K
│
▼
┌────────────────────┐
│ 上下文构建 │
└─────────┬──────────┘
│
▼
LLM
25. 示例伪代码
最小实现概念上如下所示:
documents = load_documents()
vectorizer = TfidfVectorizer(
lowercase=True,
stop_words="english"
)
document_matrix = vectorizer.fit_transform(documents)
def search(query, k=10):
query_vector = vectorizer.transform([query])
scores = cosine_similarity(
query_vector,
document_matrix
)[0]
top_indices = scores.argsort()[-k:][::-1]
return [
(documents[i], scores[i])
for i in top_indices
]
重要的观察是需要多少基础设施。
索引可以构建一次并重复使用。
26. 扩展方法
对于小型数据集,稀疏矩阵实现可能已经足够。
对于更大的数据集,架构可以演变为:
分词器
↓
词汇表
↓
词项 → 倒排列表
↓
压缩索引
↓
候选检索
↓
评分
系统可以额外支持:
- 文档过滤,
- 元数据过滤,
- 字段特定权重,
- 前缀匹配,
- 精确匹配,
- 短语匹配,
- 词干提取,
- 停用词移除,
- 同义词扩展,
- 查询扩展,
- BM25,
- 结果缓存,
- 增量索引。
到那时,系统开始类似于传统搜索引擎。
这不是巧合。
RAG检索从根本上是一个信息检索问题。
27. TF-IDF vs BM25
TF-IDF不一定是最终的经典检索算法。
自然的演进是BM25。
BM25改进了传统TF-IDF检索的几个方面,特别是:
- 文档长度归一化,
- 词频饱和,
- 相关性评分。
BM25分数可以表示为:
score(D,Q) = Σ IDF(qᵢ) × [ TF(qᵢ,D) × (k₁ + 1) ] / [ TF(qᵢ,D) + k₁ × (1 — b + b × |D| / avgdl) ]
其中:
qᵢ是查询词项TF(qᵢ,D)是它在文档D中的频率|D|是文档长度avgdl是平均文档长度k₁控制词频饱和b控制长度归一化
对于生产词汇RAG系统,BM25可能比原始TF-IDF更强的基线。
更广泛的思想保持不变:
确定性稀疏检索而不是神经嵌入。
28. 真正的权衡
TF-IDF和稠密嵌入之间的比较不应简化为:
旧 vs 新 或 简单 vs 先进
它们解决不同的检索问题。
TF-IDF / BM25
TF-IDF和BM25主要使用词汇相似性。
当重要信息已经直接存在于文本中时,它们特别有效。
典型示例包括:
- 标识符
- 客户名称
- API名称
- 数据库字段
- 错误消息
- 配置键
- 技术术语
- 产品代码
例如:
查询:reconcileUIController
如果文档包含精确标识符reconcileUIController,稀疏检索可以为其分配非常强的相关性分数。
不需要语义解释。
稠密嵌入
稠密嵌入主要使用语义相似性。
当查询和相关文档使用不同单词表达相同想法时,它们很有用。
例如:
查询:如何终止雇佣合同?
相关文档可能包含:
终止雇佣需要四周通知期。
精确单词重叠有限,但含义密切相关。
这就是稠密嵌入有价值的地方。
实践中的差异
思考这两种方法的一种有用方式是:
TF-IDF / BM25
精确单词
↓
标识符
↓
名称
↓
技术术语
↓
错误消息
↓
高度精确的词汇检索
稠密检索工作方式不同:
稠密嵌入
含义
↓
同义词
↓
释义
↓
相关概念
↓
不同措辞
↓
语义检索
操作差异也很重要。
使用TF-IDF或BM25:
文档
↓
本地索引
↓
稀疏索引
↓
快速查询
检索路径中没有嵌入模型。
使用稠密检索:
文档
↓
嵌入模型
↓
稠密向量
↓
向量索引
查询
↓
嵌入模型
↓
向量搜索
这引入了额外的模型依赖。
如果嵌入模型更改,语料库可能也需要重新嵌入。
使用TF-IDF,更改LLM不需要重建检索表示。
考虑源代码
想象一个仓库包含:
actionType
ProjectTimesheet
reconcileUIController
ERR_CONNECTION_TIMEOUT
customerId
这些值已经提供强烈的检索信号。
搜索:
customerId
不需要理解客户标识符的含义。
标识符本身就足够了。
在这种情况下,将每个源代码块转换为稠密嵌入可能会增加成本和复杂性,而不会提供显著的额外检索价值。
现在考虑自然语言
假设用户问:
如何取消我的雇佣合同?
但知识库包含:
雇员可以通过提供书面通知来终止协议。
TF-IDF可能因为重要单词不同而遇到困难:
cancel ≠ terminate
contract ≠ agreement
语义嵌入可以识别这些表达描述相关概念。
这就是稠密检索提供明确价值的场景类型。
那么应该使用哪一个?
决策不应该是:
TF-IDF还是嵌入?
更好的问题是:
数据中存在什么样的信息信号?
如果相关性主要由精确术语决定:
使用稀疏检索。
如果相关性严重依赖于含义而非措辞:
使用稠密检索。
如果两种类型的信息都存在:
使用混合检索。
例如:
查询
│
┌────────┴────────┐
│ │
▼ ▼
TF-IDF / BM25 稠密搜索
│ │
▼ ▼
精确匹配 语义匹配
│ │
└────────┬────────┘
▼
合并结果
│
▼
LLM
因此目标不是在所有地方都替换嵌入。
目标是避免在检索问题已经可以确定性解决时支付语义检索的成本。
一个有用的设计原则是:
当必须推断含义时使用语义检索。当信息已经明确时使用确定性检索。
29. 检索的经济学
考虑一个语料库频繁变化的系统。
使用嵌入,每个新修改的块可能需要嵌入操作。
使用TF-IDF,可以执行本地索引。
这改变了成本结构。
不是:
数据 → 外部嵌入API → 向量数据库
我们可以有:
数据 → 本地索引 → 本地搜索
因此系统可以减少:
- API成本
- 网络延迟
- 外部依赖
- 基础设施需求
- 操作复杂性
对于处理大量数据的组织,节省可能变得显著。
30. 最重要的限制
有一点这种方法不应该声称:
TF-IDF不能替代语义理解。
考虑:
"如何解雇员工?"
和:
"终止雇佣关系的流程是什么?"
人类看到这些是相关的。
TF-IDF看到的是大部分不同的单词。
这是根本限制。
因此,最强的架构通常是选择性的。
当查询包含强词汇信号时使用词汇检索。
当语义相似性必要时使用语义检索。
当问题受益于两者时同时使用两者。
31. 思考RAG的新方式
RAG通常被呈现为:
让LLM访问外部知识。
但实际上有两个独立的问题:
1. 信息检索
找到正确的信息。
2. 信息推理
理解信息并产生答案。
这些不一定需要相同的技术。
LLM非常擅长推理。
它并不意味着它也必须负责每个检索操作。
确定性检索层可以处理第一个问题。
LLM可以专注于第二个。
这导致更清晰的架构:
外部知识
│
▼
确定性检索
│
▼
相关上下文
│
▼
LLM
│
▼
最终答案
32. 检索作为编译器
这个想法可以更进一步。
编译器将高级表示转换为高效的可执行表示。
确定性RAG检索层可以执行类似的转换:
大型知识库
↓
检索规则
↓
稀疏索引
↓
查询执行
↓
相关上下文
↓
LLM
LLM不是从空状态开始。
检索系统已经构建了推理所需的信息状态。
从这个意义上说:
检索可以被视为将外部知识编译为LLM就绪的推理上下文。
这种观点对代理系统特别有趣。
33. 走向确定性RAG
这暗示了一个更广泛的架构,可以称为:
确定性RAG
原则是:
将不需要概率推理的检索工作从LLM中移出,转移到确定性算法中。
可能的组件包括:
精确搜索
+
TF-IDF
+
BM25
+
元数据过滤
+
结构化查询
+
图遍历
+
语义检索
+
LLM推理
目标不是消除AI。
目标是仅在AI提供独特价值的地方使用它。
34. 简单的决策框架
构建RAG系统时,问:
查询是否包含精确标识符?
使用:TF-IDF / BM25
语料库是否使用一致的领域术语?
使用:TF-IDF / BM25
语义相似性是否必要?
使用:嵌入
文档是否高度异构?
考虑:混合检索
检索成本是否变得显著?
考虑:先稀疏检索
可解释性是否重要?
优先:确定性词汇检索
你是否在构建基于结构化企业数据的代理?
考虑:确定性检索 + 结构化查询 + LLM
35. 更大的教训
LLM的兴起导致许多系统默认用神经模型替换经典算法。
但并非每个问题都需要神经解决方案。
搜索在LLM之前就存在了。
索引在嵌入之前就存在了。
信息检索背后有数十年的优化。
有趣的问题不是:
"嵌入模型能检索这个吗?"
当然可以。
更好的问题是:
"我需要嵌入模型来检索这个吗?"
如果答案是否定的,经典稀疏索引可能提供:
- 更低成本,
- 更低延迟,
- 更低基础设施复杂性,
- 确定性行为,
- 更好的可解释性,
- 和出色的检索质量。
36. 结束语
基于嵌入的RAG很强大,但它不应该自动成为每个检索问题的默认架构。
当信息主要通过词汇信号识别时,TF-IDF提供了出奇强大的替代方案。
架构很简单:
索引一次。快速搜索。给LLM正确的上下文。
重要的概念分离是:
如果信息空间已经提供强烈的确定性信号,检索不需要是智能的。
对于标识符、名称、技术术语、错误消息、配置键、源代码、结构化业务数据和许多企业数据集,稀疏词汇检索可以是非常有效的基础。
当语义理解真正必要时,TF-IDF不需要消失。
它可以与嵌入一起工作。
因此RAG的未来可能不是:
一切都变成向量。
它可能是:
使用解决检索问题的最简单检索机制,并将昂贵的神经推理保留给真正需要它的问题。
原文链接:Beyond Vector RAG: Deterministic Sparse Retrieval with TF-IDF for Large-Scale LLM Applications
汇智网翻译整理,转载请标明出处