向量化与嵌入模型:文本嵌入原理、常用模型对比与维度选择

好,咱们进入第四章。前面聊了文档解析和分块,那都是为了一件事——把文本变成计算机能理解的形式。说白了,就是向量化。

我刚开始做RAG那会儿,总觉得向量化就是个黑盒,把文字往里一扔,出来一串数字就完事了。后来踩了不少坑才明白,嵌入模型选得好不好,直接决定了检索质量的上限。今天咱们就把这块掰开揉碎了讲。

文本嵌入原理:从词到向量的魔法

先说说基本原理。文本嵌入,就是把一段文字映射到一个高维向量空间里。在这个空间里,语义相近的文本,它们的向量距离也近。

举个例子,“猫”和“狗”的向量距离,肯定比“猫”和“汽车”近。这就是嵌入模型要学的东西。

早期的Word2Vec、GloVe这些模型,每个词只有一个固定的向量。这就有个问题——一词多义搞不定。“苹果”是水果还是公司?上下文不同,意思完全不一样。

后来Transformer架构出来,BERT这类模型用注意力机制,能根据上下文动态生成每个词的表示。这就牛了。同一个“苹果”,在“吃苹果”和“买苹果”里,向量完全不同。

我习惯把嵌入模型的工作流程分成三步:

  1. 分词:把文本切成,中文可能是一个字或一个词
  2. 编码:通过Transformer层,每个都带上上下文信息
  3. 池化:把所有的向量聚合成一个句子向量,常见的有CLS向量、均值池化、最大池化

核心要点:池化方式对最终效果影响很大。均值池化在大多数场景下表现稳定,CLS向量在分类任务上更强。我个人做检索时,优先试均值池化。

下面这张图,把嵌入模型的核心流程画清楚了:

文本嵌入流程 输入文本 分词器 序列 Transformer编码器(多层注意力) 每个获得上下文感知的向量表示 池化层(均值/CLS/最大池化) 最终嵌入向量(768/1024维) 维度越高,信息越丰富 但存储和计算成本也越高

常用嵌入模型对比: / BGE / Cohere

市面上的嵌入模型多如牛毛,但真正在生产环境里经得起考验的,就那么几个。我这些年用过不下十种,最后常驻工具箱的是这三家。

Embeddings(text-embedding-3系列)

的嵌入模型,目前最新的是text-embedding-3-small和text-embedding-3-large。说实话,效果确实好,尤其是对英文场景。

我记得有一次做英文文档的RAG,用text-embedding-3-small,检索准确率直接比之前用的开源模型高了8个点。但代价也不小——API调用有延迟,而且按计费,量大了钱包疼。

有个小技巧:的模型支持通过dimensions参数动态降维。比如你传1536维,但指定只输出256维,效果损失很小。我在做原型验证时经常这么干,省成本。

BGE(BAAI General Embedding)

BGE是北京智源研究院开源的模型,中文场景的王者。我做过对比测试,在中文数据集上,BGE-large的表现经常超过的text-embedding-ada-002。

BGE有几个版本:BGE-small、BGE-base、BGE-large,参数量从30M到330M不等。我最常用的是BGE-base,性价比最高。

这里有个坑要注意:BGE模型在推理时,需要在文本前面加一个指令前缀。比如检索场景,要加“Represent this sentence for searching relevant passages:”。不加的话,效果会打折扣。我曾经因为这个吃了亏,排查了半天才发现是前缀的问题。

Cohere Embeddings

Cohere的嵌入模型在英文场景上和不相上下,而且它有个独特优势——支持多语言,包括中文。不过中文效果不如BGE。

Cohere的embed-multilingual-v3.0,我试过在跨国企业的多语言文档检索场景,效果还不错。但如果你只做中文,还是优先考虑BGE。

下面这个表格,把三个模型的差异列清楚了:

维度 text-embedding-3 BGE-large-zh Cohere embed-multilingual-v3
默认维度 1536(可降维) 1024 1024
中文效果 良好 优秀 良好
英文效果 优秀 良好 优秀
推理方式 API调用 本地/API API调用
成本 按计费 免费(自部署) 按计费
延迟 网络延迟 本地推理 网络延迟
适用场景 英文为主、预算充足 中文为主、需要本地部署 多语言、英文为主

我的选择建议:中文场景无脑上BGE-large,英文场景预算够用,需要本地部署且中文为主就BGE-base。别在模型选择上纠结太久,先跑起来再说。

嵌入维度选择:不是越大越好

嵌入维度这个事,很多人有个误区——觉得维度越高,信息越丰富,效果就越好。其实不然。

维度高了,确实能编码更多信息,但也会带来三个问题:

  • 存储成本飙升:100万条768维的向量,用float32存,大概3GB。换成1536维,直接翻倍到6GB。
  • 检索速度下降:高维向量做相似度计算,计算量线性增长。在百万级数据上,1536维比768维慢了将近一倍。
  • 维度诅咒:维度太高,向量在空间里变得稀疏,距离度量反而失去区分度。说白了,所有向量都差不多远了,检索精度反而下降。

我做过一个实验:用同样的数据,分别用256维、512维、768维、1024维的嵌入做检索。结果发现,768维到1024维之间效果最好,再往上提升就微乎其微了。所以我现在做项目,默认用768维,除非有特殊需求。

避坑指南:我曾经在一个项目里,为了追求“更精细的语义”,直接用了1536维的嵌入。结果检索延迟从50ms飙到200ms,召回率只提升了0.3%。最后乖乖降回768维。记住,嵌入维度不是越高越好,够用就行。

下面给个维度选择的参考:

数据规模 推荐维度 理由
10万以下 256-512 数据量小,低维度足够区分
10万-100万 512-768 平衡精度和性能
100万-1000万 768-1024 需要更高区分度
1000万以上 1024(配合降维) 必须考虑存储和检索效率

最后说一句,嵌入模型的选择和维度设置,没有银弹。最好的办法是拿你的真实数据做A/B测试。我每个项目都会先跑一个小规模的对比实验,用召回率和MRR(Mean Reciprocal Rank)两个指标来选模型和维度。花半天时间做实验,能省后面几个月的折腾。