02.3 - Embedding 模型与向量化
定位: RAG 语义理解的基石——将文本表示为向量的技术和模型选型 面试高频度: ⭐⭐⭐⭐⭐ 考查方式: Embedding 原理、模型选型、维度权衡、开源 vs 商业模型
一、这是什么?为什么需要它?
是什么
Embedding(嵌入)是将文本(词、句子、段落)映射到高维空间中的向量(数字数组)的过程。语义相似的文本在向量空间中距离相近。
"公司年假政策" --> [0.12, 0.87, -0.34, ..., 0.56] (768维)
"远程工作规定" --> [0.15, 0.82, -0.31, ..., 0.52] (距离近:语义相似)
"牛顿第一定律" --> [-0.45, 0.12, 0.78, ..., -0.23] (距离远:语义不同)为什么需要 Embedding?
计算机无法理解"语义"——只能理解数字。Embedding 是文本和计算机之间的桥梁。
检索本质上是在找"语义相似":
用户问:"年假有多少天?"
我们希望检索到:"根据员工手册,每年享有15天年假..."
关键:查询和文档使用不同的词,但语义相同
"年假有多少天" vs "每年享有15天年假"
Embedding 的作用:把不同表述但相同语义的文本映射到相近的向量位置二、原理拆解
2.1 Embedding 模型的工作原理
向量空间(示意)
+------------------+
| - 猫 |
| - 狗 | 宠物相关
| |
| - 年假 |
| - 远程工作 | 公司政策
| - 员工手册 |
| |
| - 牛顿 |
| - 引力 | 科学领域
| - 量子 |
+------------------+
Embedding 模型 = 一个神经网络
输入:文本序列 --> 输出:固定维度向量
训练目标:语义相近的文本 -> 向量距离(余弦相似度)大2.2 主流 Embedding 模型对比
| 模型 | 维度 | 最大输入 | 语言 | 特点 |
|---|---|---|---|---|
| OpenAI text-embedding-3-small | 512/1536 | 8191 tokens | 多语言 | 性价比高、API 调用 |
| OpenAI text-embedding-3-large | 256/1024/3072 | 8191 tokens | 多语言 | 最高精度 |
| BGE-large-zh-v1.5 | 1024 | 512 tokens | 中文 | 中文效果最优 |
| BGE-m3 | 1024 | 8192 tokens | 多语言 | 支持多向量密度 |
| multilingual-e5-large | 1024 | 512 tokens | 多语言 | 多语言均衡 |
| m3e-large | 768 | 512 tokens | 中文 | 国产开源 |
| Cohere embed-multilingual-v3.0 | 1024 | 512 tokens | 多语言 | API 服务 |
| Jina Embeddings v3 | 1024 | 8192 tokens | 多语言 | 长文本 + 任务特定 |
选型原则:
维度权衡:
高维度(1536-3072):表达更精细,但计算和存储成本更高
低维度(384-512):更快速,更省存储,精度略降
经验:768-1024 是性价比最佳区间
语言偏好:
纯中文场景 -> BGE 系列 / m3e(专门优化中文)
多语言场景 -> multilingual-E5 / OpenAI / Cohere
英文为主 -> OpenAI / E5 / Instructor
成本考虑:
商业 API(OpenAI/Cohere):按 token 计费,零运维
开源自建(BGE/E5):需 GPU 部署,按量付费
混合策略:商用 API 验证 -> 数据够多时迁移到开源2.3 向量维度对性能的影响
| 维度 | 相对召回 | 相对存储成本 | 适用场景 |
|---|---|---|---|
| 128 | 0.45 | 1.0x | 极简场景、移动端 |
| 256 | 0.58 | 2.0x | 快速原型 |
| 384 | 0.66 | 3.0x | 轻量级系统 |
| 512 | 0.71 | 4.0x | 通用(性价比高) |
| 768 | 0.75 | 6.0x | 通用推荐 |
| 1024 | 0.76 | 8.0x | 高质量场景 |
| 1536 | 0.77 | 12.0x | OpenAI 默认 |
| 3072 | 0.78 | 24.0x | 最高精度需求 |
结论:768-1024 维度是性价比 sweet spot,1536+ 的精度提升很小但成本翻倍。
2.4 Embedding 模型选择的影响
错误的 Embedding 选择会导致:
1. 中文文档用英文模型检索
查询:年假
结果:返回了不相关英文结果
因为:模型没学过中文语义空间
2. 短文本用长文本模型
查询:请假
结果:匹配到包含"请假"但不相关的大段文档
因为:512维度不足以区分细粒度语义
3. 领域术语用通用模型
查询:通过率(在芯片行业指良率)
结果:返回了教育行业的"考试通过率"
因为:模型没有领域知识三、图解全景
Embedding 在 RAG 中的全流程
+------------------------------------------------------------------+
| Embedding 在 RAG 中的角色 |
| |
| 离线索引阶段: |
| +--------+ +-------------+ +----------+ |
| | 文本块 |--> | Embedding |--> | 向量数据库 | |
| | Chunk 1 | | 模型 encode | | [0.1...] | |
| | Chunk 2 | | 输出 768维 | | [0.3...] | |
| | ... | | | | [...] | |
| +--------+ +-------------+ +----------+ |
| ^ |
| 在线推理阶段: | |
| +--------+ +--------------+ | |
| | 用户查询 |--> | 同款 Embedding |------------------+ |
| | "年假..."| | 模型 encode | 查询向量 |
| +--------+ +--------------+ |
| | |
| v |
| +----------+ +----------+ |
| | 向量检索 | | 文本块 | |
| | ANN搜索 |--> | Chunk 3 | |
| | Top-K | | Chunk 7 | |
| +----------+ +----------+ |
| |
| 核心原则:索引和检索必须使用同一款 Embedding 模型 |
| 否则:向量分布不同 -> 语义无效 |
+------------------------------------------------------------------+四、实战验证
4.1 快速体验 Embedding
python
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer("all-MiniLM-L6-v2")
sentences = [
"公司年假政策",
"员工每年享有15天带薪年假",
"如何申请远程工作",
"请假流程说明",
]
embeddings = model.encode(sentences)
query = "年假有多少天"
query_vec = model.encode([query])[0]
for i, sent in enumerate(sentences):
sim = np.dot(query_vec, embeddings[i]) / (
np.linalg.norm(query_vec) * np.linalg.norm(embeddings[i])
)
print(f"相似度 {sim:.3f}: {query[:12]} <-> {sent[:12]}")五、面试视角
| 问题 | 答案要点 |
|---|---|
| Embedding 模型的训练目标是什么? | 对比学习:让语义相似的文本向量距离近,语义不同的距离远。通过 (query, positive, negative) 三元组训练 |
| 为什么索引和检索必须用同一 Embedding 模型? | 不同模型生成的向量分布不同。用模型A索引文档、模型B编码查询,两个向量在空间中不可比,导致检索无效 |
| 向量维度高低如何选择? | 高维(1536+)精度略高但存储和计算成本翻倍;低维(384)速度快但精度有限。768-1024 是性价比最佳的区间 |
| 中文场景推荐什么 Embedding 模型? | BGE 系列(BAAI/bge-large-zh)或 m3e。专门针对中文优化,效果显著优于通用模型 |
| Embedding 模型的最大输入长度意味着什么? | 超过最大长度的文本会被截断,丢失信息。如果文本较长(>512 tokens),需选择长文本模型(BGE-m3 8192)或先分块再编码 |
六、参数速查
Sentence-Transformers 常用命令
bash
# 安装
pip install sentence-transformers torch
# 用 GPU 加速
import torch
device = "cuda" if torch.cuda.is_available() else "cpu"
model = SentenceTransformer("BGE-large-zh-v1.5", device=device)
# 批量编码
embeddings = model.encode(documents, batch_size=32, show_progress_bar=True)📚 相关链接
- **文本分块策略** — 分块决定了 Embedding 的输入质量
- **向量数据库选型与对比** — Embedding 向量的存储和检索
- **检索与重排序** — 向量检索的实际应用
- <- 返回 **检索系统索引**