什么是 Embedding
计算机不理解文字。当你在代码里写下「用户退款」四个字,对程序来说这只是四个 Unicode 编码,它不知道这和「申请退货」有什么关系,也不知道这和「股票退市」完全不同。要让机器处理自然语言,我们需要一种翻译方式——把文字变成数字,而且这种数字还要能保留语义信息。Embedding 就是这种翻译。
Embedding 是什么
Embedding(嵌入)是一种将离散数据——文本、图像、音频——映射到高维连续向量空间的表示方法。输出的结果是一个浮点数数组,也叫向量(Vector)。例如,一句话经过 Embedding 后可能变成一个 1536 维的浮点数列表:
[0.0231, -0.0187, 0.0412, ..., -0.0095] // 1536 个数字
这些数字不是随机的。Embedding 的核心特性是:语义相近的内容,在向量空间中的距离更近。「如何申请退款」和「退款流程是什么」这两句话字面上不完全相同,但经过 Embedding 后它们的向量会非常接近;而「如何申请退款」和「今天天气不错」的向量则相距甚远。
这种能力使得 Embedding 成为 RAG(检索增强生成)、语义搜索、文本分类、推荐系统等场景的基础设施。
Embedding 能处理的数据类型
| 数据类型 | 输入示例 | 输出 | 典型应用 |
|---|---|---|---|
| 文本(词) | "退款" | 768-3072 维向量 | 词义分析 |
| 文本(句子/段落) | "用户询问退款流程" | 768-3072 维向量 | 语义搜索、RAG |
| 图像 | 产品截图 | 512-1024 维向量 | 以图搜图 |
| 音频 | 语音片段 | 变长向量 | 语音识别 |
| 结构化数据 | 用户画像 | 变长向量 | 推荐系统 |
本文聚焦于文本 Embedding,这是 AI 产品出海场景中使用最广泛的类型。
文本 Embedding 的工作原理
从词向量到句向量
Embedding 技术的发展经历了几个阶段。最早的方法是一词一码——每个词对应一个唯一的整数 ID,但这种表示完全无法体现语义关系。后来出现了 Word2Vec 和 GloVe 等方法,将每个词映射为一个稠密向量,使得语义相似的词在向量空间中距离相近。Word2Vec 的经典发现是:vec("国王") - vec("男人") + vec("女人") ≈ vec("女王"),这说明向量确实捕获了语义结构。
但词向量有一个局限:同一个词在不同语境下含义不同。「苹果」可以是水果,也可以是公司。为了解决这个问题,基于 Transformer 架构的预训练模型(如 BERT)引入了上下文感知的表示——同一个词在不同句子中会产生不同的向量。
当前的主流做法是使用专门的 Embedding 模型将整段文本编码为一个句向量或段向量。这些模型通常基于 Transformer 的双塔(Bi-Encoder)架构,将输入文本编码为一个固定长度的向量。
语义空间与距离度量
Embedding 将文本投射到一个高维「语义空间」中。在这个空间里:
- 距离近 = 语义相似:「产品功能介绍」和「特性说明」靠得很近
- 距离远 = 语义不同:「产品功能介绍」和「员工工资单」相距很远
衡量两个向量之间「相似度」的常用方法:
| 度量方式 | 公式特点 | 适用场景 | 注意事项 |
|---|---|---|---|
| 余弦相似度(Cosine Similarity) | 衡量方向,不归一化幅度 | 大多数文本语义任务 | OpenAI 模型已内置归一化,余弦相似度等于点积 |
| 欧氏距离(Euclidean Distance) | 衡量空间直线距离 | 需要绝对位置信息的场景 | 对向量长度敏感 |
| 点积(Dot Product) | 同时考虑方向和幅度 | 已归一化的向量 | 与余弦相似度等价(当向量已归一化时) |
在实际工程中,余弦相似度是最常用的选择。大多数向量数据库(Pinecone、Milvus、Qdrant 等)都默认支持余弦相似度检索。
文本 Embedding 的完整流程
下面用一个 Mermaid 流程图展示文本 Embedding 从输入到检索的完整链路:
这个流程是 RAG 系统的核心骨架。文档先被分块、Embedding 后存入向量数据库;用户提问时,问题同样经过 Embedding,然后在向量数据库中检索最相似的文档块。
Embedding 模型选择
主流 Embedding 模型对比
选择 Embedding 模型时需要综合考虑性能、成本、多语言支持和部署方式。以下是当前(2026 年)主流模型的横向对比:
| 模型 | 提供商 | 默认维度 | 最大输入 Token | MTEB 得分 | 价格(每百万 Token) | 多语言支持 |
|---|---|---|---|---|---|---|
text-embedding-3-small | OpenAI | 1536(可缩至 64+) | 8192 | 62.3% | $0.02 | 良好 |
text-embedding-3-large | OpenAI | 3072(可缩至 256+) | 8192 | 64.6% | $0.13 | 良好 |
embed-v4 | Cohere | 1024 | 512 | 64.2% | $0.10 | 优秀(100+ 语言) |
voyage-3-large | Voyage AI | 1024 | 32000 | 67.5% | $0.12 | 良好 |
bge-large-zh-v1.5 | BAAI(开源) | 1024 | 512 | — | 免费(自部署) | 中文优秀 |
nomic-embed-text | Nomic(开源) | 768 | 8192 | 62.0% | 免费(自部署) | 良好 |
gemini-embedding-001 | 3072 | 2048 | 64.6% | $0.00(免费额度) | 优秀 |
选型建议:
- 快速原型 / 中小项目:
text-embedding-3-small,性价比最高,API 调用 3-5 行代码搞定 - 追求精度:
text-embedding-3-large或voyage-3-large,后者在长文本和技术文档上表现突出 - 多语言场景(出海必备):
embed-v4支持 100+ 语言,适合多语种知识库 - 中文专属场景:
bge-large-zh-v1.5在中文语义理解上表现优异,且可本地部署,无 API 费用 - 需要本地部署 / 数据敏感:选择开源模型(BGE、Nomic),可在自己的 GPU 上推理
维度选择指南
维度是 Embedding 模型的关键参数——维度越高,理论上能表达的语义信息越丰富,但存储和检索成本也越高。
| 维度范围 | 适用场景 | 存储成本(每向量) | 典型模型 |
|---|---|---|---|
| 64-256 | 简单分类、低精度匹配 | 极低 | OpenAI 3-small(缩至 256) |
| 384-768 | 一般语义搜索、RAG 入门 | 中等 | nomic-embed-text(768)、bge-base(768) |
| 1024 | 中大型知识库、多语言 RAG | 较高 | embed-v4(1024)、bge-large-zh(1024) |
| 1536-3072 | 高精度语义检索、大规模生产环境 | 高 | text-embedding-3-small(1536)、text-embedding-3-large(3072) |
一个值得注意的特性:OpenAI 的 v3 模型支持通过 dimensions 参数在 API 调用时直接缩短向量长度,而不会显著损失语义表达能力。例如,text-embedding-3-large 缩短到 256 维后,性能仍然优于未缩短的 text-embedding-ada-002(1536 维)。这意味着你可以用更高的维度获取向量,再按实际需要缩短,兼顾精度和成本。
Embedding API 使用方法
OpenAI Embedding API
OpenAI 的 Embedding API 是目前使用最广泛的方案。以下是核心调用方式:
Python 调用:
from openai import OpenAI
client = OpenAI()
response = client.embeddings.create(
input="用户询问如何申请退款",
model="text-embedding-3-small"
)
vector = response.data[0].embedding
print(f"维度: {len(vector)}") # 输出: 维度: 1536
print(f"前5个值: {vector[:5]}")批量输入(一次传入多段文本,减少网络开销):
texts = [
"用户询问如何申请退款",
"退款流程说明",
"产品功能介绍文档",
]
response = client.embeddings.create(
input=texts,
model="text-embedding-3-small"
)
# 返回结果与输入顺序一一对应
for i, item in enumerate(response.data):
print(f"文本 {i}: 维度 = {len(item.embedding)}")自定义维度(降低存储成本):
response = client.embeddings.create(
input="用户询问如何申请退款",
model="text-embedding-3-large",
dimensions=256 # 从 3072 维缩短到 256 维
)JavaScript / TypeScript 调用:
import OpenAI from "openai";
const openai = new OpenAI();
const embedding = await openai.embeddings.create({
model: "text-embedding-3-small",
input: "用户询问如何申请退款",
encoding_format: "float",
});
console.log(embedding.data[0].embedding);开源模型本地部署
以 BGE 系列模型为例,使用 sentence-transformers 库进行本地推理:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("BAAI/bge-large-zh-v1.5")
texts = ["用户询问如何申请退款", "退款流程说明"]
embeddings = model.encode(texts, normalize_embeddings=True)
print(f"向量形状: {embeddings.shape}") # 输出: (2, 1024)注意:BGE 系列模型需要手动做归一化(normalize_embeddings=True),而 OpenAI 模型已内置归一化,无需额外处理。
Token 计数与成本控制
Embedding API 按输入 Token 数量计费。在调用前估算 Token 数有助于控制成本。OpenAI 的 v3 系列模型使用 cl100k_base 分词方案:
import tiktoken
encoding = tiktoken.get_encoding("cl100k_base")
text = "用户询问如何申请退款"
tokens = encoding.encode(text)
print(f"Token 数: {len(tokens)}") # 中文大约 1-2 个字 ≈ 1-3 个 Token常见问题
1. 检索和入库使用了不同的 Embedding 模型
这是最常见的错误之一。向量数据库里存的是模型 A 生成的向量,检索时却用了模型 B 生成的查询向量——两个向量空间不一致,检索结果毫无意义。核心规则:入库和检索必须使用同一个模型。如果中途更换模型,需要全量重建向量索引。
2. 文本分块策略不合理
Embedding 模型有最大输入长度限制(通常 512-8192 Token)。对于长文档,需要先做分块(Chunking)。分块过大,超出模型上下文限制会被截断;分块过小,语义不完整,检索质量下降。常见的分块策略包括:
| 分块方式 | 适用场景 | 注意事项 |
|---|---|---|
| 按固定 Token 数(如 512) | 通用文档 | 注意 overlap,避免语义被切断 |
| 按段落/标题 | 结构化文档 | 保持段落语义完整性 |
| 按语义边界 | 高质量检索 | 需要额外的分割模型或算法 |
3. 跨语言误用模型
用英文 Embedding 模型处理中文文本,效果会大打折扣。不同模型的训练语料侧重不同语言:
| 场景 | 推荐方案 |
|---|---|
| 纯中文知识库 | bge-large-zh-v1.5 或 bge-base-zh |
| 中英混合 | text-embedding-3-small / text-embedding-3-large |
| 多语言(100+) | embed-v4(Cohere) |
4. 忽略归一化步骤
不同模型对归一化的处理不同。OpenAI 的 Embedding 模型输出时已经做了 L2 归一化,可以直接使用点积代替余弦相似度。但 BGE 等开源模型需要手动归一化,否则相似度计算结果不可靠。
5. 向量数据库选型不当
向量数据量从小到大有不同选择:
| 数据规模 | 推荐方案 |
|---|---|
| < 1 万条 | 内存计算即可,无需向量数据库 |
| 1 万 - 100 万 | Pinecone(托管)、Qdrant(自部署) |
| 100 万+ | Milvus、Pinecone、Weaviate |
6. 成本失控
Embedding API 按 Token 计费,大规模使用时成本不可忽视。以 OpenAI 为例:
| 操作 | 每百万 Token 价格 | 10 万条文档(平均 500 Token/条) |
|---|---|---|
text-embedding-3-small | $0.02 | $1.00 |
text-embedding-3-large | $0.13 | $6.50 |
控制成本的手段包括:选择合适维度(dimensions 参数)、批量输入减少请求次数、合理分块避免冗余 Token、优先用 3-small 做原型验证。
实战案例
案例 1:跨境电商知识库的语义搜索
某跨境电商平台需要为客服系统构建知识库。客服人员输入用户问题后,系统自动检索最相关的帮助文档。
方案设计:
- 将帮助中心文档按段落分块(每块 300-500 Token,overlap 50 Token)
- 使用
text-embedding-3-small对每个文档块生成 Embedding - 存入 Pinecone 向量数据库
- 用户提问时,对问题做 Embedding,在 Pinecone 中检索 Top-5 相关文档块
- 将检索结果送入 LLM 生成最终回答
关键决策:选择 text-embedding-3-small 而非 3-large,因为该场景对精度要求不高(客服辅助而非全自动),但调用量大,成本控制重要。最终 10 万条文档块的 Embedding 成本约 $1,检索响应时间 < 100ms。
案例 2:多语言产品文档的智能问答
某 SaaS 产品面向全球市场,帮助文档有英文、日文、西班牙文三个版本。需要构建统一的多语言问答系统。
方案设计:
- 选择 Cohere
embed-v4(支持 100+ 语言),统一所有语种到同一个向量空间 - 各语种文档分别做 Embedding,存入同一个 Qdrant 索引(通过元数据标记语言类型)
- 用户用任意语言提问,Embedding 后在向量库中检索,同时过滤语言类型
- 将检索结果和原始问题一起送入 LLM 生成回答
关键决策:选择 embed-v4 而非为每种语言选不同模型。原因是多语言模型将所有语种映射到同一向量空间,跨语言检索天然支持——用户用中文提问也能检索到英文文档。
检查清单
在将 Embedding 集成到你的 AI 产品之前,逐项确认:
- 已根据业务场景选择合适的 Embedding 模型(考虑维度、多语言、成本)
- 入库和检索使用同一个 Embedding 模型
- 文本分块策略已确定,分块大小不超过模型最大输入限制
- 分块时设置了合理的 overlap(通常 10-20%)
- 已确认模型是否需要手动归一化(OpenAI 不需要,BGE 需要)
- 使用了合适的距离度量(余弦相似度适用于大多数场景)
- Token 成本已估算,且在预算范围内
- 向量数据库选型匹配数据规模(小数据无需向量数据库)
- 多语言场景使用了支持目标语言的模型
- 批量调用 API 以提高效率、降低网络开销
- 已设计向量索引的重建策略(更换模型时需要全量重建)
- 对检索结果做了基础的质量抽检(不能只依赖自动化指标)
总结
Embedding 是让计算机「理解」文字的基础技术。它将文本变成向量,将语义变成距离,使得机器能够在数学空间中寻找含义相近的内容。对于 AI 产品出海的开发者来说,Embedding 是构建 RAG 系统、实现语义搜索的第一步,也是关键一步。选对模型、用对方法、避开常见陷阱,就能为后续的 LLM 推理提供高质量的上下文。