Rafael Pierre 六月在 Lighthouse newsletter 上发了篇东西,标题大意是:很多团队把 RAG 系统 overcomplicate 了——先上 embedding、上向量库、上 reranking,再做一堆增量优化,结果用户只是想要精确地找到一篇文档。我这两天才翻到这篇,读完之后的第一反应是:他说得对,而且对得这么朴素,反而更值得想想——"先试试全文搜索"这句话,为什么需要一整篇文章来论证?
先别急着谈技术选型。RAG 这个标签覆盖的光谱,宽得吓人。最简的那一头:一个 BM25 全文搜索,把 top-k 结果拼进 prompt 丢给生成模型,完事。复杂的那一头:文档进库前先过一遍解析、切块、embedding,向量存进专门数据库,查询时做向量检索加关键词召回,再过一道 rerank 模型。中间的每一层都是一整套管线,一个代价不小的运维实体。两者的成本差不是一个数量级,是几个数量级。
但你把"RAG 系统"四个字甩出去,同行脑子里浮现的默认形状,是复杂的那一头。这个默认值从哪来的?不是测量出来的。是供给端教的:模型厂商、向量库厂商、平台方,教程和样板代码全在带你跑通完整链路。没有人在 demo 里演示过"我用了 Postgres 全文索引,够了"——这件事信息量太薄,薄到不值得做一次 demo,但它恰恰是大量场景里的正确答案。
先看最便宜的这个方案为什么不该被跳过。BM25 的实现到处都是——Elasticsearch、Postgres 全文索引、SQLite FTS5——索引建完,查询就是本地算一个加权打分,10 毫秒以内出结果,零 API 成本,因为整个调用链里没有任何外部模型。调试的时候更省事:返回结果不对,打开词项匹配记录看一眼就懂了。
BM25 做的事严格说就是:对查询里的每个词,按文档频率做加权打分,然后排序。它只对字面出现过的词负责。用户说"怎么重置密码",文档标题就是"如何重置密码"——BM25 匹配这四个字节的序列,一次命中,返回的几乎就是你想要的那一篇。这里有个反直觉的地方:文档标题是人为内容起的名字,命名本身就是一个极强的对齐信号,等于语料自己留了锚点;embedding 检索反而把这个锚点稀释了,把它当成几十个语义维度里的一个微弱信号,然后给你一篇"账户安全最佳实践"。
所以我说,在精确查找的场景里,FTS 的"笨"恰恰是它的优势。它过拟合到了字面上,而你要的答案就焊死在字面上。这个特点不值得嘲笑,它对应的是一整类真实需求——用户找文档、找配置项、找历史记录,要的就是字面上那个东西。
当然,它也有明确的死穴:同义改写。用户搜"订单没到",文档里写的是"物流延误",字面前后对不上,它就真的一篇都返回不了。这正是 embedding 检索的主场——它赌的是"语义接近的东西值得看一遍",在查询和语料的措辞对不齐的场景里,这个赌赢得很值。所以别把 FTS 吹成万灵药,我不做这个推荐。Pierre 说的也不是"FTS 更好",他说的是"先试"。
这两个字的重量,比表面看起来大得多。
除了命中率,还有一条写 RAG 教程的人很少展开、但生产环境里最磨人的差异:预嵌入管线是重资产,它跟文档新鲜度几乎天生对头。Pierre 文章里有一句关于语料特征的判断,大意是高流转率或长尾语料适合即时处理而不是全量预嵌入——这句值得往下拆。预嵌入的完整代价不是一开始嵌入一次就完了:文档高频更新,意味着每次新文档进库都要过一遍"切块→调用 embedding 模型→入库"这条管线。更隐蔽的是,embedding 模型本身会升级。换一个新版本,语义空间就跟着变,新旧向量混在同一个索引里,相似度比较直接失效,你被迫做一次全量重嵌入。这个成本在 FTS 上不存在:倒排索引里存的是词频,模型换三版它都不在乎。也就是说,文档变动越多、越频繁,预嵌入方案的成本结构就越恶劣——它把每一次内容更新都变成了一笔需要重新审核的账。这笔账花五分钟就能算清楚,但选型文档里很少有人写过。
所以我从 Pierre 那篇文章里读到的,不是一份"该用简单方案还是复杂方案"的裁决——这种裁决本来就不该由一个写文章的人替你下。他说得最对的地方是"先试"这两个字:让数据先说话,用最简单的那条路径跑一遍(这里的"先",是测量意义上的先,不是口号上的先),看它在你自己的查询模式上漏多少,再决定要不要为那个缺口付出 embedding 和向量库的代价。大多数团队跳过了"测量"这一步,直接从"上复杂版"开始了。漏掉测量,选型就成了信仰之争。
这里还有个没法数据化、但真实得让人不舒服的因素:选型汇报。你回来说"我们上了 BM25 全文检索",和说"我们上了向量库加混合路由加 Rerank",在旁听者心里激起的涟漪完全不同。复杂方案的展示价值天然更高——它能证明团队在吃透新技术。这个激励结构不符合技术选型的逻辑,但它就在那里,参与每一次决策,只是没人承认。RAG 这个标签的存在让这个结构更拧巴了:那个词同时覆盖"查字典"和"做联想",而公众心智里的默认值几乎总是指向后者。结果是大多数团队还没想清楚自己要的是哪一种,就已经在跑 embedding 了。
所以 Pierre 那篇真正的价值,不是给了一张架构决策清单——他列的那些决策因素当然有用——而是把"先试一下最简单的"这句话重新说出口,并且说得让人不用觉得丢人。绕了这么一大圈,把他的话压缩成人话,就是:RAG 不是一种架构,是从"查字典"到"语义联想"的一整段光谱,你该落在哪一格,由你的语料和查询形态决定,不由默认值决定。懂了这层,再看自己管线里每一段复杂度,哪段是给真实需求买的单、哪段是在替默认值买单,你自己就能分清。
再往下就是 hybrid retrieval 里 BM25 和 embedding 的具体配比,以及怎么让两路结果在同一个分数尺度上可比——那是另一个坑,先留着,改天填。
