这道题其实是在问,怎么把人对语义的理解,转换成机器能算的距离。我们做[[RAG]]、做知识库的时候,核心就是靠这个。
先说一下基本原理。文本进来,我会用[[Embedding]]模型把它变成一个向量,比如768维或者1024维的稠密向量。你理解成把一句话压缩成一个坐标点,语义相近的,坐标就挨得近。这一步的前提是模型本身质量够,如果模型不行,后面全白搭。
然后算相似度,最常用的是余弦相似度,它只看方向不看模长,适合大部分场景。欧氏距离也行,但得先归一化。说白了,选哪个度量取决于你的向量空间长什么样。
但真正要落地,你不能每次都暴力算所有向量的距离,那太慢了。所以得用[[ANN]]算法,也就是近似最近邻搜索。我实际项目里用得最多的是[[HNSW]],它是个图结构,查询快、精度高,但内存吃得多,百万级数据很适合。如果数据量到亿级,我会换[[IVF]]加[[Product Quantization]],也就是倒排加乘积量化,省内存,但精度会掉一点。选哪个取决于你的延迟容忍度和精度要求。
这里有个坑:很多人以为向量检索就能解决一切,其实不是。关键词检索在精确匹配上比向量强得多,比如订单号、错误码这些,向量可能找偏,但[[BM25]]一搜一个准。所以真正落地的方案,我倾向做[[Hybrid Search]],也就是向量和关键词两条路一起走,然后合并排序。
举个例子,电商客服场景里,用户问“退款怎么还没到”,向量检索能召回相似语义的退款政策文档,但用户如果报了一串订单号,关键词检索能精准定位那条订单记录。两个互补,缺一个体验都会崩。
再说RAG里的召回环节。检索质量直接决定了生成的天花板。我上线前会特别关注几个点:一是chunk切分策略,切太碎丢失上下文,切太长噪声多,得根据文档类型调;二是query改写,用户问题可能很口语化,我会先改写一下再去做检索;三是[[Rerank]],初召回Top100,再用[[Cross-Encoder]]重排一次,把最相关的Top5送进生成。
还有一个点值得聊,就是检索的置信度问题。有时候召回来的文档跟问题根本不相关,但模型还是硬用,就会产生[[Hallucination]]。我一般会在检索后加一层相关性过滤,低于阈值的直接丢弃。这个阈值怎么定,其实跟业务场景和模型能力都有关系。
所以整体上,我会把相似性检索看成整个RAG系统的漏斗入口,入口质量不行,后面生成再怎么调也救不回来。我更倾向把检索和生成当整体来优化,而不是各自独立调参数。