Skip to content

Embedding 与向量化:从 Token 到语义搜索

摘要: Embedding(嵌入)是将离散符号映射至连续向量空间的核心技术,其「语义相近则向量相近」的基本性质使其成为语义搜索、RAG 检索与向量数据库的数学基石。本文首先严格区分了 Token Embedding(上下文无关的查表向量)与 Sentence Embedding(上下文感知的句级表示)两种易混淆的嵌入类型及其工程误区,随后系统对比了 LLM 自回归训练与专用 Embedding 模型对比学习范式之间的本质差异,并梳理了主流嵌入模型的选型参考。在应用层面,本文深入解析了语义搜索的三步流程、三种向量相似度度量、ANN 近似最近邻搜索的核心算法(HNSW、IVF、PQ)及其精度与速度权衡,以及混合搜索作为 RAG 系统最稳健检索方案的技术原理。

📄
图集速览:Embedding、向量化与语义检索如果你对 Embedding 与向量化还比较陌生,建议先读这篇图集速览。用可视化图片集合和要点摘要,帮你快速理清从 Token 到语义搜索的向量世界。
Embedding向量化语义搜索RAG

1. Embedding(嵌入)基本概念

Embedding(嵌入) 是将离散的符号(文字、图片、用户 ID)映射为连续向量空间中的点。其核心思想是:语义相近的东西,在向量空间中距离也近。

使用类比理解 Embedding:

想象你有一张巨幅世界地图——

传统表示:   "巴黎" = 一个离散符号,计算机只知道这是字符串 "巴黎"
Embedding:  "巴黎" = [0.82, -0.31, 0.45, ..., 0.17]  (768 维向量)
            "上海" = [0.79, -0.28, 0.41, ..., 0.15]
            "狗"   = [-0.12, 0.88, -0.33, ..., -0.56]

向量空间中:
  巴黎 vs 上海: cosine_sim ≈ 0.92 → 都是大城市!
  巴黎 vs 狗:   cosine_sim ≈ 0.03 → 完全无关

1.1 Token Embedding vs Sentence Embedding

两个关键维度区分:

这两种 Embedding 服务于完全不同的场景,核心区别在于:粒度不同、上下文感知不同、用途不同

维度Token Embedding(词元嵌入)Sentence Embedding(句嵌入)
粒度一个 Token → 一个向量一整句话/段落 → 一个向量
上下文感知上下文无关:同一个「苹果」无论出现在科技新闻还是水果食谱,Embedding 层的向量都一样上下文相关:「苹果很好吃」和「苹果发布了新品」得到完全不同的整体向量
上下文来源自身不带上下文,需通过后续 Attention 层融入向量本身已经编码了整个句子的语义
获取位置LLM 的第一层(Embedding 层),训练前就已存在从模型中间层或专用模型提取,是计算后的结果
典型维度768 ~ 12288(与模型 d_model 一致)768 / 1024 / 4096(专用 Embedding 模型)
主要用途LLM 内部表示——作为 Attention/FFN 的输入语义搜索、文本聚类、相似度计算、RAG 检索
典型模型GPT、LLaMA 的 Embedding 层text-embedding-3、bge-large、GTE-Qwen2

Token Embedding 工作方式:

  "苹果很好吃" → Tokenizer → ["苹果", "很", "好吃"]
       │            │            │
       ▼            ▼            ▼
  查 Embedding 表,各自独立得到向量(此时三个向量互不感知)
       │            │            │
       └────────────┴────────────┘


          进入 Attention 层后才开始互相"交流"

Sentence Embedding 工作方式:

  "苹果很好吃" ──→ Embedding 模型 ──→ [0.15, 0.83, -0.42, ...]  ← 一个向量代表整句
  "苹果发布了新品" ──→ 同一模型 ──→ [0.72, -0.31, 0.58, ...]  ← 截然不同的向量

  虽然都包含"苹果",但两句的整体向量差异很大:
  cosine_sim("苹果很好吃", "苹果发布了新品") ≈ 0.32  ← 语义完全不同

为什么这个区分很重要?

很多人混淆这两者,导致实际工程中用错工具。常见误区:想用 LLM 的 Token Embedding 做语义搜索——但 Token Embedding 是上下文无关的,同一个「苹果」永远是同一个向量,无法区分「吃苹果」和「买苹果手机」。

正确的做法是用专门的 Sentence Embedding 模型(如 text-embedding-3bge-large)来生成句子级向量。

Embedding 维度与语义空间

Embedding 向量的维度(如 768、1024、4096)决定了语义空间的"分辨率"。类比理解如下:
维度太低(如 2 维):
  只能表达"正面-负面"这一个维度,无法区分"愤怒"与"悲伤"

维度适中(如 768 维):
  可以同时表达"情绪""主题""风格""语言""正式度"等数十个语义维度

维度太高(如 4096 维):
  表达力更强,但存储和计算成本更大;向量检索时维度灾难现象加剧

常见模型的 Embedding 维度:OpenAI text-embedding-3-small(512/1536 可选)、BGE-M3(1024)、GTE-Qwen2-7B(3584)。

2. Embedding Model

Embedding 不是"大模型顺手做的事"——有专门的嵌入模型(Embedding Model)针对"把文本变成好向量"这个目标做专门训练。

LLM vs 专用 Embedding Model 的本质差异:

LLM(如 GPT-4)专用 Embedding Model
目标预测下一个 token(生成)让相似文本的向量近,不相似文本的向量远(对比学习)
输出概率分布(词表大小)固定长度向量(如 1536 维)
训练范式自回归(Next-Token Prediction)对比学习(Contrastive Learning)
架构Decoder-Only TransformerEncoder-Only 或 Decoder 池化
典型任务聊天、写作、编程搜索、聚类、分类、RAG 检索

主流专用 Embedding Model 一览:

模型维度多语言特点
OpenAI text-embedding-3-small512/1536多语言API 调用,无需部署
OpenAI text-embedding-3-large256/1024/3072多语言更强,更贵
BGE-M3(BAAI)1024中英为主开源 SOTA,支持稠密+稀疏混合检索
GTE-Qwen2-7B(阿里)3584多语言基于 Qwen2,中文表现顶尖
Jina Embeddings v31024多语言支持任务特定 LoRA adapters
Cohere Embed v31024多语言压缩表示,适合大规模检索
Nomic Embed Text768/1376英文全开源(数据+代码+权重)

通用 LLM 做 Embedding:可行但"大材小用"。 你可以取 LLM 最后一层隐状态的均值作为文本 Embedding,但专用模型用更少的参数达到更好效果——7B 参数的 GTE-Qwen2 在 MTEB 检索基准上超越了多数通用 LLM。

3.1 语义搜索的完整流程

语义搜索(Semantic Search) 是基于向量相似度匹配的搜索方式,核心流程只有三步:

语义搜索的完整流程:

┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│  1. 向量化    │     │  2. 相似计算   │     │  3. 结果排序   │
│              │     │              │     │              │
│ 查询: "怎么   │     │ cos(查询, 文档1) │    │ 文档3: 0.92  │
│  部署模型?"  │ →   │ cos(查询, 文档2) │ →  │ 文档1: 0.87  │
│   ↓          │     │ cos(查询, 文档3) │    │ 文档2: 0.34  │
│ [0.1, -0.3]  │     │ ...            │     │ ...          │
│              │     │              │     │              │
│ 文档库:      │     │              │     │              │
│  文档1 → [..]│     │              │     │              │
│  文档2 → [..]│     │              │     │              │
│  文档3 → [..]│     │              │     │              │
└─────────────┘     └──────────────┘     └──────────────┘

三种向量相似度度量对比:

度量方式公式值域适用场景
余弦相似度(A·B) / (A·
欧氏距离sqrt(Σ(Aᵢ-Bᵢ)²)[0, ∞)关心绝对距离(长度+方向)
点积A·B = Σ AᵢBᵢ(-∞, ∞)向量已归一化时等价于余弦相似度
余弦相似度的几何直觉(二维示意):

         查询向量 Q

          /  夹角 ≈ 15°
         /
        * 文档向量 D₁(相关)

             查询向量 Q

              /
             /
        ←──→ 夹角 ≈ 130°
        *
    文档向量 D₂(不相关)

cos(15°) ≈ 0.97 → 高度相关!
cos(130°) ≈ -0.64 → 几乎无关

ANN(Approximate Nearest Neighbor,近似最近邻搜索): 当文档库达到百万甚至亿级时,逐个计算余弦相似度不可行。ANN 算法(如 HNSW、IVF、PQ)通过牺牲一点精度换取巨大速度提升——检索 1 亿条向量从"几分钟"变成"几毫秒"。主流向量数据库(Milvus、Qdrant、Pinecone)在内部都使用了 ANN 索引。

3.2 ANN (Approximate Nearest Neighbor,近似最近邻搜索)

ANN 是一种在百万甚至亿级向量中快速找到与查询向量最相似的 Top-K 个向量的算法。它的核心取舍是:用少量精度换取数量级的搜索速度提升

为什么需要 ANN?

暴力搜索(逐一对比所有向量)在数据量小时完全可行,但向量数据库的规模往往是百万到十亿级:

暴力搜索(Brute Force):
   1 亿条向量 × 768 维浮点数 × 两次浮点运算 = 每秒约 5000 次比对
   → 检索一次需要 20000 秒 ≈ 5.5 小时 ❌

ANN 索引:
   先在索引中快速定位候选区域(几毫秒),再对候选集做精确比对(几毫秒)
   → 检索一次只需 1~10 毫秒 ✅

ANN 的基本原理——用索引代替全量对比:

ANN 的核心思路是在建库时花时间构建索引结构,把相似向量预组织在一起;查询时用索引快速缩小搜索范围,只在小范围内做精确计算:

阶段操作耗时
建库(离线)对所有向量建索引,相当于给整个向量空间画一张「地图」数分钟到数小时(只做一次)
查询(在线)根据查询向量在索引中定位候选区域,只计算候选区域内的向量1~10 毫秒

主流 ANN 算法:

算法原理特点
HNSW(分层可导航小世界图)构建多层图结构,上层做「高速公路」快速跳到目标区域,下层做精确查找当前综合性能最强,查询快、召回率高,但内存开销较大
IVF(倒排文件索引)用 K-Means 把所有向量聚成 N 个簇,查询时只在最近几个簇内搜索简单高效,内存友好,适合大规模数据
PQ(乘积量化)将高维向量切分成多段,每段独立做量化压缩,用近似距离代替精确距离内存极度节省,但召回率略低,常与 IVF 组合使用
IVF-PQIVF 做粗定位 + PQ 做压缩存储工业界最常用的组合,兼顾速度与内存
DiskANN将索引存在 SSD 上,只按需加载需要的部分到内存超大规模(十亿级)、内存有限时的首选

HNSW 直观理解

 
   层级 2(稀疏,长距离跳跃):
     ● ──────────── ●
 
   层级 1(中等密度):
     ● ───● ───● ───●
 
   层级 0(最密,精确搜索):
     ●─●─●─●─●─●─●─●
 
   查询路径:从顶层快速跳到目标区域 → 逐层下降 → 底层精确比对 → 返回结果

精度 vs 速度的权衡:

ANN 索引通常有一个可调节的参数来控制这个权衡。以 HNSW 为例,ef_search 越大(搜索时探索更多候选),召回率越高但越慢:

配置召回率查询延迟适用场景
ef_search=16~90%~1ms对延迟敏感的在线服务
ef_search=64~97%~3ms一般推荐场景
ef_search=256~99.5%~10ms对精度要求极高的场景

主流向量数据库的 ANN 实现:

向量数据库ANN 算法特点
MilvusHNSW, IVF-PQ, DiskANN功能最全,支持十亿级向量
QdrantHNSWRust 实现,性能优异,API 友好
Pinecone自研(不公开)全托管,零运维,按量付费
WeaviateHNSW, Flat自带向量化模块
ChromaHNSW轻量级,适合原型开发

为什么语义搜索是 RAG 的基石?

传统关键词搜索:          语义搜索(向量搜索):
用户: "怎么保持健康?"    用户: "怎么保持健康?"
  ↓                         ↓
匹配"保持""健康"           向量化 query
  ↓                         ↓
找到含这些词的文档          找到向量最接近的文档
  ↓                         ↓
❌ 漏掉 "养生秘诀"         ✅ "养生秘诀" 高相似度!(语义匹配)
❌ 漏掉 "锻炼身体"         ✅ "锻炼身体" 也高相似度

这就是为什么 RAG 系统中,检索通常使用混合搜索(Hybrid Search):BM25 关键词匹配 + 向量语义匹配,再通过 Reranker 做最后排序,是最稳健的方案。