RAG 中如何计算文本相似度?常见算法有哪些?
RAG 中如何计算文本相似度?常见算法有哪些?
这道题考的是 RAG 检索环节的核心——向量相似度计算。从文本怎么变成向量,到向量之间怎么比远近,再到大规模数据怎么快速检索,这是一条完整的技术链路。
我从四个方面来讲:Embedding 原理和三种距离度量、RAG 场景下距离怎么选、向量索引算法有哪些、HNSW 怎么调参和数据库怎么选。
Embedding:文本怎么变成向量
先说 Embedding。你可以把 Embedding 理解成一个"翻译官",把人类能看懂的语言翻译成机器能算的数字。
举个例子,"什么是 RAG" 这句话经过 Embedding 模型处理后,会变成一个 1536 维的向量,大概长这样:
[0.123, -0.456, 0.789, ..., 0.321](1536 个数字)
这个过程不是随机的。语义相近的文本,在向量空间里的位置也相近。"狗是动物"和"猫是宠物"这两个句子,转换后的向量会靠得很近。
向量维度越高,能表达的意思就越精细。OpenAI 的 ada-002 用 1536 维,BERT -base 是 768 维,现在的模型还在往更高维度走。
三种距离度量:向量之间怎么比远近
拿到向量之后,下一步就是计算"相似度"。这里有三种主要方法:
余弦相似度。看的是两个向量的方向,而不是长度。公式是向量夹角的余弦值,范围在 -1 到 1 之间。两个向量方向越一致,夹角越小,余弦值越接近 1。
欧氏距离。就是你高中学的那种距离,两点之间的直线长度。公式是两个向量对应位置相减再平方求和开根号。距离越小,说明向量越接近。
内积。把对应位置的数字乘起来,再全部加起来。计算最快。在向量已经归一化的情况下,内积和余弦相似度是等价的。
这三种方法各有各的场景。简单记法:方向看余弦,绝对距离看欧氏,要速度用内积。
RAG 场景下,为什么推荐余弦距离
这是面试常考的点。
RAG 检索的核心需求是:找到语义最相关的文本片段,不管它长短。
余弦相似度只比较方向,不比较长度。这意味着,一篇 5000 字的文章和一个 10 字的查询,只要意思相近,向量方向就一致。
反过来,欧氏距离会同时考虑方向和长度。长文本的向量模长通常更大,在欧氏距离下会"天然远离"短查询,容易出问题。
内积速度最快,但前提是你得把向量归一化处理。没归一化的话,内积反映的是方向加模长的综合结果,不是纯方向相似度。
工程实践里,Milvus、pgvector 这些数据库默认都支持余弦距离。很多系统直接用内积替代余弦(因为做了归一化处理),性能更好,效果一样。
向量索引算法:小规模用 Flat,大规模用 HNSW
数据量小的时候,直接算就行了。Flat 就是暴力遍历,每个查询都跟所有向量算一遍距离。优点是 100% 准确,缺点是慢。100 万条数据,你一个个比,要比 100 万次。
数据量上来之后,必须加索引。
HNSW 是现在最主流的选择。全称是 Hierarchical Navigable Small World,分层可导航小世界图。
它的思想是:把向量组织成多层图,上层稀疏下层密集。查询的时候从最上层开始,快速定位到一个局部区域,再逐层往下精确找。
类比一下,就像去一个超级大图书馆找一本书。Flat 的做法是逐本翻目录。HNSW 的做法是先分区——人文区在东边、社科区在西边——进了人文区再找经济学书架,经济学里再找微观经济学那层。
HNSW 的优点:快,召回率高,百万级数据毫秒级响应。
HNSW 的缺点:内存消耗大,构建索引慢。
除了 HNSW,还有几个备选:
IVFFLAT:先对向量做聚类,查询时只在相关聚类里找。内存友好,但召回率比 HNSW 略低。
IVF_PQ:聚类加量化,进一步压缩内存。适合超大规模数据,但精度有损失。
RABITQ:2024 年新出的算法,用随机旋转加比特量化,可以用位运算加速。适合对速度要求极高的场景。
选型建议:百万级以下用 HNSW,超大规模考虑 IVF_PQ 或 RABITQ。
HNSW 参数怎么调
HNSW 有三个核心参数:
m:每个节点最多连接多少个邻居。默认值 16。越大索引越大、召回越高、查询越慢。
ef_construction:构建索引时的搜索范围。默认值 64。越大构建越慢、索引越大、召回越高。
ef_search:查询时的搜索范围。默认值 40。这个参数最实用——建好索引后可以在线调,不用重建。
调参的核心原则:召回不够就加大 ef_search,内存不够就减小 m。
pgvector 默认配置是 m=16、ef_construction=64、ef_search=40。实用做法是先用默认参数,有问题了在线调 ef_search。
有个坑要注意:大量删除数据后,索引会有"空洞",需要定期 REINDEX 加上数据库的 VACUUM 操作,不然查询性能会逐渐下降。
向量数据库怎么选
看数据量来选:
100 万向量以下:用 pgvector。它集成在 PostgreSQL 里,SQL 查询和向量检索可以无缝结合。pgvector 0.7+ 支持 halfvec 类型(16 位浮点),内存省一半。0.8.0+ 支持迭代索引扫描,复杂查询更稳定。
100 万到 10 亿级:用 Milvus 或者 Qdrant。Milvus 分布式做得好,Qdrant 部署简单。
任意规模:考虑云服务。Pinecone、Weaviate Cloud、阿里云 OpenSearch 向量检索版。不用自己运维,按量付费。
选型口诀:小数据用 pgvector,中等规模用 Milvus,不想运维用云服务。
面试怎么答
基础版(100 字左右):
文本相似度计算分为两步。第一步用 Embedding 模型把文本转成向量,语义相近的文本在向量空间里距离更近。第二步用距离度量来比较,主要有余弦相似度、欧氏距离和内积三种。RAG 场景推荐用余弦相似度,因为它只比较向量方向,不受文本长度影响。大规模检索需要加向量索引,HNSW 是目前最主流的算法,通过分层图结构实现快速高召回检索。HNSW 核心参数是 m(连接数)、ef_construction(构建范围)和 ef_search(查询范围)。
加分版(200 字左右):
Embedding 把文本映射到高维向量空间,常用的有 OpenAI ada-002(1536 维)、Cohere(1024 维)等。距离度量方面,余弦相似度适合语义检索,欧氏距离适合几何意义明确的场景,内积在归一化后等价于余弦且计算更快,是工业级首选。RAG 检索推荐余弦距离,不受文本长度干扰。向量索引算法,精确召回用 Flat,高召回快速检索用 HNSW,超大规模用 IVF_PQ 或 RABITQ 压缩内存。HNSW 调参重点是 ef_search,可以在线调整不用重建索引。数据库选型方面,百万级以下用 pgvector,百万到十亿级用 Milvus,不想运维用云服务。另外需要注意索引维护,频繁删除后要做 REINDEX 加 VACUUM。
一句话总结
RAG 文本相似度计算的核心是:Embedding 把文本变成向量,余弦相似度比较方向,HNSW 索引加速检索,数据库按数据量级来选。
