《AI 知识卡片》第 09 期 · 把文字变成坐标,意思近的就挨在一起
比如你家有一本秘制私房菜谱,做成 AI 能查的知识库——这些菜只有你家会做,AI 训练时压根没见过。
你输入“番茄炒蛋要放糖吗”,它却能找出了菜谱里《西红柿炒鸡蛋》那一页。
注意,“番茄”和“西红柿”这两个词,一个字都不挨着。换成关键词搜索,这就是零结果,但 RAG 的检索找到了。这一期讲清它凭什么能“按意思”找,以及它凭什么知道这俩是一回事。
关键词匹配检索的弊端
RAG 第一步就是“检索”:拿问题去资料库找相关片段,那怎么算“相关”?——老办法是关键词匹配:你搜的词和文档里的词对上了就算命中,但有个死穴,换个说法就抓瞎了:
- “番茄”对不上“西红柿”,“土豆”对不上“马铃薯”。同一样东西,两个完全不重合的词条;
- “怎么做”对不上“制作方法”。一个意思,词不同也没戏;
这种关键词匹配的问题我们叫做词汇鸿沟:字面不重合,机器就默认你俩没关系。
把每段文字变成一串“坐标”
RAG 换了思路:别对字了,对“意思”。做法是,把菜谱里每一段文字都变成一串数字,相当于给它在一张巨大的语义坐标图上标一个坐标。这个动作正式叫 Embedding(中文译作“嵌入”),得到的那串数字叫向量。
一段文字有多少个数字?这取决于模型的规格——常用的中文 Embedding 模型bge-small-zh是 512 个。关键在于它是定长的:不管你喂进去 5 个字还是 500 个字,出来永远是这 512 个数。比如:
[0.0135, -0.0587, 0.0232, 0.0376, -0.0008, ... ] 共 512 个
两个反直觉的点:
- 单个数字没有含义。文字意思是被这 512 个数字整体表达的,单看一维毫无意义。
- 文字不是“查表”查出来的,是“算”出来的。每段文字都要真的跑一遍 Embedding 模型(这里的“模型”不等同于LLM,完全是两个东西,职责也不一样)才得到坐标。
这张坐标图最妙的规矩是:意思越近的文字,坐标离得越近。
它凭什么知道“番茄=西红柿”?
没人告诉过它,它也没查任何同义词词典。这张坐标图是它自己“学”出来的。它学到的不是“字面像”,而是“用法像、语境像”。
Embedding 模型在训练时读过海量文本。它会发现:“番茄炒蛋”和“西红柿炒鸡蛋”这两个说法,出现的语境几乎一模一样。既然它们总在同样的场合、被同样的词围绕,模型就把它们的坐标拽到了一起。
训练时的核心手段叫对比学习,说白了就一句:把相关的拉近,把不相关的推远。
- 喂进“一个问题 + 它的正确答案”这种成对的相关文本 → 拉近;
- 再随便配一段无关文本 → 推远;
- 千万次这样拉拉推推之后,一张“意思近就挨着”的坐标图就成型了;
本地实测结果对比
我在本地拿 bge-small-zh 跑了一组,比较不同提问和它的余弦相似度(0~1,越大越近):
第二行是重点:“番茄”和“西红柿”一个字都不挨着,相似度却有 0.61,远远高于“红烧肉”的 0.43。在语义坐标图上,它俩确实是邻居。
语义检索的短板
语义检索的本事是“找意思差不多的”——这既是它的强项,也正是它的短板:它只会“差不多”,不擅长“一模一样”。
- 该精确的时候它不精确。你搜一个准确的产品型号、一个函数名,要的是一字不差那一条,它可能把几个“长得很像”的一起端上来。
- 谁排第一它常拿不准。相关的内容它能一并捞进来,但真正最贴题的那条,未必就在第一位。
所以实际工程里很少让它一条腿走路:一般再搭一条关键词检索兜住精确匹配,捞回来之后还会再重排一遍,把最贴题的顶到前面。后续有机会可以深入聊聊。
一句话总结
关键词搜索对比的是“字”,语义检索对比的是“意思”。RAG 把每段文字变成语义坐标图,而这张图不是谁编的词典,是模型从海量文本里把相关的拉近、不相关的推远,一点点学出来的。