Appearance
02. Embeddings 详解
版本:
v1.1最后更新:
2026-07-06适用对象:希望系统理解文本向量、语义检索、相似度计算、向量索引、RAG 检索质量与生产落地的学习者和工程开发者
1. 什么是 Embedding
Embedding 可以理解为:
- 把文本、图片、音频、用户、商品、代码片段等对象映射成一组数字向量。
这组数字不是为了还原原始内容,而是为了让系统能计算对象之间的关系。
在文本场景里,一个 embedding 通常是这样的:
json
[-0.018, 0.042, 0.007, -0.031, ...]OpenAI Embeddings 文档把 embedding 描述为一组浮点数向量,并说明向量之间的距离可以表示文本之间的相关性。距离越小,通常说明语义越相关。
更通俗一点:
- 关键词搜索看的是词有没有出现。
- Embedding 搜索看的是意思是否接近。
这就是为什么用户问“怎么退款”,系统也可能召回“售后退费流程”。
2. Embedding 解决了什么问题
传统程序更擅长处理精确匹配:
status = paiduser_id = 123- 文本里是否包含
退款
但现实中的语言经常不是精确匹配:
- “怎么退钱”
- “能不能把订单撤了”
- “我买错了,想取消”
- “售后费用返还怎么走”
这些表达不一定共享相同关键词,但语义相近。Embedding 的价值就是把“相近”变成可计算的向量距离。
常见用途包括:
| 用途 | 说明 |
|---|---|
| 语义搜索 | 根据含义而不是关键词找资料 |
| RAG | 检索相关知识片段,再交给模型回答 |
| 推荐 | 找相似商品、文章、用户或问题 |
| 聚类 | 把相似文本自动分组 |
| 分类 | 用标签向量或训练分类器识别类别 |
| 去重 | 找语义重复或近重复内容 |
| 异常检测 | 找与整体分布差异很大的样本 |
| 多模态匹配 | 把图片和文本映射到可比较空间 |
3. Embedding 的核心直觉
Embedding 空间可以想成一个高维语义地图。
在这个地图里:
- “猫”和“狗”可能比较近。
- “PostgreSQL”和“数据库”可能比较近。
- “退款流程”和“售后退费”可能比较近。
- “退款流程”和“天气预报”应该比较远。
这个空间不是人工规则写出来的,而是模型从大量数据中学出来的。
需要注意:
- 向量接近不等于事实正确。
- 向量接近不等于业务上该召回。
- 向量空间表达的是相似性,不是完整推理能力。
Embedding 是检索和匹配的强工具,但不是知识库本身。
4. Embedding 和 Token Embedding 的区别
初学者容易把两种 embedding 混在一起。
| 类型 | 出现位置 | 作用 |
|---|---|---|
| Token embedding | 模型内部 | 把 token 变成模型可处理的内部向量 |
| Text embedding / Sentence embedding | 应用层 API 或模型输出 | 把一段文本变成可检索、可比较的向量 |
在 RAG、语义检索、聚类里,我们通常说的是第二种:文本级 embedding。
它可以表示:
- 一个短句
- 一个问题
- 一个文档 chunk
- 一个商品描述
- 一条工单
- 一段代码
而不是单个 token。
5. Embedding 是怎么生成的
一个典型流程是:
text
Text
-> Tokenizer
-> Embedding Model
-> Pooling / Projection
-> Vector5.1 Tokenizer
模型先把文本切成 token。不同模型的 tokenizer 不同,所以同一段文本的 token 数可能不同。
这会影响:
- 最大输入长度
- 调用成本
- 长文本是否需要切分
OpenAI Embeddings API Reference 说明,创建 embedding 的输入可以是字符串或 token 数组,但必须满足模型的最大 token 限制。
5.2 Embedding Model
Embedding 模型会把输入文本编码成向量。现代 embedding 模型通常基于 Transformer 编码器或类似架构训练。
5.3 Pooling 或投影
模型需要把 token 级信息合成一个文本级向量。常见方式包括:
- 取特殊 token 表示
- mean pooling
- attention pooling
- 模型内部专门的 projection head
不同模型的训练方法和 pooling 方式会明显影响向量质量。
6. 从 BERT 到 Sentence-BERT
理解 Embedding 发展,可以先看一个关键问题:普通 BERT 并不天然适合大规模语义相似度搜索。
Sentence-BERT 论文指出,如果直接用 BERT 做句子对相似度,需要把句子对一起送进模型。对大量候选句子做两两比较时,计算量会非常大。SBERT 使用 siamese / triplet 网络结构,让句子可以先独立编码成向量,再用余弦相似度比较。
这个变化非常关键:
- 原来是每个 query 和每个候选都要一起过模型。
- 现在是文档可以提前算好向量,查询时只算 query 向量。
这就是现代语义检索能规模化的基础。
text
传统 Cross-Encoder:
Query + Document -> Model -> Score
Embedding / Bi-Encoder:
Query -> Vector
Document -> Vector
Vector Similarity -> Score6.1 Bi-Encoder 的优点
- 文档向量可以离线预计算。
- 查询速度快。
- 适合大规模召回。
- 易接入向量数据库。
6.2 Bi-Encoder 的缺点
- query 和 document 分开编码,细粒度交互较弱。
- 有时只能判断大致语义相近,无法精确判断是否真正回答问题。
所以工程里常见组合是:
text
Embedding Retriever
-> Candidate Documents
-> Cross-Encoder / Reranker
-> Final ContextEmbedding 负责召回,reranker 负责更细的排序。
7. 相似度怎么计算
拿到两个向量后,需要计算它们有多接近。
常见方式有三种。
7.1 Cosine Similarity
余弦相似度关注两个向量方向是否接近。
适合:
- 语义相似度
- 归一化向量
- 文本 embedding 检索
直觉:
- 两个向量方向越一致,语义越接近。
7.2 Dot Product
点积同时受方向和向量长度影响。
适合:
- 模型训练时就是按 dot product 优化的场景
- 已经做好归一化或长度有业务含义的场景
7.3 Euclidean Distance
欧氏距离关注两个向量在空间中的直线距离。
适合:
- 某些传统向量空间任务
- 特定索引结构和模型假设
7.4 怎么选
| 情况 | 推荐 |
|---|---|
| 文本语义相似度,不确定模型细节 | 优先试 cosine |
| 模型或向量库明确推荐 dot product | 用 dot product |
| 向量已归一化 | cosine 和 dot product 排序常常接近 |
| 使用向量库默认配置 | 确认它和模型推荐方式一致 |
最重要的一点:
- 文档向量和查询向量必须使用同一套模型和同一套相似度假设。
8. 维度、归一化和压缩
OpenAI 文档说明,text-embedding-3-small 默认向量长度是 1536,text-embedding-3-large 默认向量长度是 3072,并支持通过 dimensions 参数控制输出维度。
8.1 维度越高越好吗
不一定。
更高维度通常可能表达更多信息,但也带来:
- 存储成本更高
- 内存占用更大
- 检索计算更重
- 网络传输更大
- 索引构建更慢
工程上要看任务结果,而不是迷信维度。
8.2 降维什么时候有用
降维适合:
- 数据量很大
- 成本敏感
- 延迟敏感
- 召回精度要求不是极限
- 需要在边缘设备或较小数据库里运行
降维前后必须评测:
- Recall@k
- MRR
- nDCG
- 业务命中率
- 线上延迟
8.3 归一化是什么
归一化通常是把向量长度缩放到 1。
归一化的好处:
- 让相似度更关注方向
- 便于 cosine / dot product 使用
- 减少向量长度差异带来的影响
是否需要归一化,要看模型和向量库的推荐。
9. Embedding 模型怎么训练
不用掌握所有训练细节,但要知道模型为什么能学到“相似”。
常见训练信号包括:
9.1 对比学习
让相似样本靠近,不相似样本远离。
例如:
- query 和正确文档靠近
- query 和错误文档远离
9.2 Triplet Loss
三元组通常包括:
- anchor:基准文本
- positive:相关文本
- negative:不相关文本
目标是让 anchor 更接近 positive,而不是 negative。
9.3 监督检索数据
用真实搜索点击、问答数据、人工标注数据训练。
9.4 多任务训练
MTEB 论文强调,embedding 不是只有一个任务。它覆盖检索、聚类、分类、语义相似度、reranking 等多个方向。一个模型在某类任务上强,不代表在所有任务上都强。
这也是为什么选 embedding 模型时不能只看一个榜单总分,要看你的具体任务。
10. Embedding 在 RAG 里的位置
RAG 里的 embedding 主要发生在两个地方。
text
Offline:
Document -> Chunk -> Embedding -> Vector Store
Online:
Question -> Embedding -> Similarity Search -> Retrieved Chunks10.1 文档侧 embedding
文档入库时:
- 解析文档。
- 清洗文本。
- 切成 chunk。
- 为每个 chunk 生成 embedding。
- 写入向量库。
10.2 查询侧 embedding
用户提问时:
- 对问题做标准化或改写。
- 生成 query embedding。
- 在向量库里找相似 chunk。
- 结合 metadata filter、关键词检索、rerank。
10.3 关键原则
- 文档和查询要用同一个 embedding 模型。
- 文档更新后要更新对应向量。
- chunk 内容变化后要重新 embedding。
- metadata 不应该丢,它决定过滤、权限和回溯。
11. Chunk Embedding 的细节
在 RAG 中,很多质量问题不是 embedding 模型本身造成的,而是 chunk 设计造成的。
11.1 好 chunk 的特点
- 主题单一
- 上下文完整
- 保留标题路径
- 保留表格列名
- 保留来源信息
- 长度适中
11.2 坏 chunk 的表现
- 一个 chunk 里混了多个主题
- 标题和正文分开
- 表格行脱离列名
- 错误码和说明被切开
- 只有很短一句话,缺少语义
- 太长导致向量表达被稀释
11.3 推荐 metadata
每个 chunk 至少建议带:
json
{
"chunk_id": "string",
"document_id": "string",
"title": "string",
"section_path": ["string"],
"source_url": "string",
"page": 1,
"updated_at": "datetime",
"language": "zh",
"tenant_id": "string",
"permission_scope": ["string"]
}Embedding 只负责语义相似,metadata 负责业务过滤和可追溯。
12. 向量数据库和 ANN 索引
当数据量很小时,可以直接暴力计算 query 和所有向量的相似度。
但数据量变大后,需要近似最近邻搜索,也就是 ANN。
Faiss 文档把它描述为针对 dense vectors 的高效相似度搜索和聚类库,支持大规模向量集合、批量搜索、精度和速度权衡、最大内积搜索、范围搜索等能力。
pgvector 则把向量检索带到 PostgreSQL 里,支持 exact 和 approximate nearest neighbor search,也支持 L2、inner product、cosine 等距离方式。
12.1 Exact Search
精确搜索会比较所有向量。
优点:
- 结果最准确
- 适合小规模数据
缺点:
- 数据量大时慢
- 成本随数据量线性增长
12.2 Approximate Search
近似搜索通过索引结构快速找到大概率接近的结果。
优点:
- 速度快
- 适合大规模数据
缺点:
- 可能漏掉真正最近的向量
- 需要调索引参数
12.3 HNSW
HNSW 是常见的图索引方法。它会构建多层近邻图,查询时从稀疏上层逐步导航到密集下层。
适合:
- 高召回
- 低延迟
- 在线查询
常见参数会影响:
- 构建时间
- 内存占用
- 查询速度
- 召回率
12.4 IVF / PQ / Quantization
大规模场景还会用:
- IVF:先把向量分桶,再查部分桶
- PQ:压缩向量,降低内存
- Scalar quantization:用更低精度存储向量
- Rerank:先粗召回,再用原始向量或更强模型重排
工程上永远是在做权衡:
- 更快
- 更准
- 更省内存
- 更容易更新
13. Embedding 和关键词搜索的关系
Embedding 不应该完全替代关键词搜索。
13.1 Embedding 擅长
- 同义表达
- 口语化问题
- 概念匹配
- 语义召回
13.2 关键词搜索擅长
- 精确编号
- 人名
- 产品型号
- 错误码
- 法条条款
- 特定字段名
13.3 混合检索更稳
真实企业知识库通常需要:
text
Semantic Search
+ Keyword Search
+ Metadata Filter
+ RerankingEmbedding 是强召回工具,但它不该孤军奋战。
14. 评测 Embedding 质量
Embedding 评测不能只凭“搜起来感觉不错”。
14.1 通用基准
MTEB 是一个常见文本 embedding 评测基准,覆盖检索、聚类、分类、语义相似度、reranking 等多个任务和多语言数据。MTEB 论文也指出,没有某一种 embedding 方法能在所有任务上都占优。
这对工程选型很重要:
- 不要只看总分。
- 要看与你业务最接近的任务。
- 中文、代码、法律、医疗、客服等领域要单独评测。
14.2 业务评测指标
| 指标 | 说明 |
|---|---|
| Recall@k | 正确文档是否进入前 k |
| Precision@k | 前 k 里有多少真正相关 |
| MRR | 第一个正确结果排多靠前 |
| nDCG | 排序质量 |
| Hit Rate | 是否至少命中一个正确结果 |
| Query Coverage | 哪些 query 类型效果差 |
| Latency | 检索耗时 |
| Cost | 入库和查询成本 |
14.3 评测集应该覆盖什么
- 普通语义问题
- 精确编号问题
- 同义表达问题
- 缩写和别名
- 中英文混合
- 长问题
- 多意图问题
- 证据不足问题
- 容易误召回的问题
14.4 最小评测记录
json
{
"query": "如何申请退款?",
"positive_chunk_ids": ["refund_policy_003"],
"hard_negative_chunk_ids": ["after_sales_intro_001"],
"query_type": "policy_lookup",
"notes": "用户表达口语化,需要召回退费流程"
}如果没有 positive 和 hard negative,就很难判断 embedding 召回是不是变好了。
15. Hard Negative 很重要
Hard negative 是看起来很像、但其实不是正确答案的样本。
例如用户问:
- “退款多久到账?”
正确文档:
- “退款到账时间说明”
Hard negative:
- “退款申请入口”
- “退货物流说明”
- “售后服务总览”
这些文档语义相关,但不能回答到账时间。
Embedding 系统如果经常召回 hard negative,说明:
- chunk 太泛
- query 太短
- embedding 模型区分度不足
- 需要 reranker
- 需要关键词或 metadata 辅助
16. 选择 Embedding 模型
选择模型时,可以按下面维度看。
| 维度 | 要问的问题 |
|---|---|
| 语言 | 中文、英文、多语言表现如何 |
| 领域 | 是否适合你的行业词汇 |
| 任务 | 检索、分类、聚类还是 rerank |
| 维度 | 存储和检索成本能否接受 |
| 输入长度 | 长 chunk 是否会超限 |
| 成本 | 入库和查询是否可控 |
| 延迟 | 是否满足在线链路 |
| 部署 | API 调用还是本地部署 |
| 隐私 | 数据是否能发给外部服务 |
| 可迁移 | 以后换模型是否容易重建索引 |
16.1 小模型还是大模型
小模型适合:
- 成本敏感
- 低延迟
- 大规模入库
- 一般语义检索
大模型适合:
- 复杂语义
- 多语言
- 高召回要求
- 领域表达复杂
但最终必须以评测集结果为准。
16.2 API 还是本地模型
| 方案 | 优点 | 风险 |
|---|---|---|
| API | 易用、效果稳定、维护少 | 数据合规、成本、网络依赖 |
| 本地模型 | 数据可控、可定制 | 部署和调优成本高 |
企业场景经常会混合使用:敏感数据走本地模型,公共资料或低风险场景走 API。
17. Embedding 检索的典型失败模式
| 失败模式 | 表现 | 常见原因 | 修复方向 |
|---|---|---|---|
| 召回泛化过度 | 找到相关但不能回答的内容 | chunk 太泛、query 太短 | query 改写、rerank、hard negative |
| 精确字段丢失 | 错误码、编号搜不到 | 纯向量对精确匹配弱 | 混合检索、关键词索引 |
| 长文被稀释 | 文档主题多,向量不聚焦 | chunk 太大 | 重新切分 |
| 语义断裂 | 召回片段不完整 | chunk 太小 | 增加 overlap、保留标题路径 |
| 模型不匹配 | 中文或领域词效果差 | embedding 模型不适合 | 换模型或微调 |
| 索引不一致 | 新文档搜不到或旧文档还在 | 增量更新失败 | 建立索引版本和重建机制 |
| 权限污染 | 召回无权文档 | metadata filter 缺失 | 权限前置过滤 |
| 排序不稳 | 正确结果在后面 | 初始召回不足或无 rerank | 增加 rerank |
18. Embedding 与 Reranker 的分工
Embedding retriever 和 reranker 的分工很像粗筛和精排。
text
Embedding Retriever:
从大量文档里快速召回 50-200 个候选
Reranker:
对候选做更精细的 query-document 相关性排序18.1 为什么需要 reranker
Embedding 是把 query 和 document 分开编码,速度快,但交互弱。
Reranker 通常会同时看 query 和 document,因此更擅长判断:
- 这个片段是否真正回答问题
- 是否只是语义相似
- 是否包含关键约束
- 是否比其他候选更直接
18.2 什么时候可以先不加 reranker
- 文档量小
- 查询简单
- top-k 已经很准
- 延迟极其敏感
- 业务允许人工二次筛选
18.3 什么时候应该加 reranker
- top-k 命中但顺序差
- hard negative 多
- 需要压缩上下文
- 答案依赖精确证据
- 文档主题相似度很高
19. 生产系统里的版本管理
Embedding 不是一次生成就永远不动。
以下变化都可能要求重建索引:
- embedding 模型变更
- chunking 策略变更
- 文档解析规则变更
- 清洗规则变更
- metadata 结构变更
- 权限模型变更
19.1 建议记录的版本字段
json
{
"embedding_model": "text-embedding-3-small",
"embedding_dimensions": 1536,
"chunker_version": "chunker-v3",
"parser_version": "pdf-parser-v2",
"index_version": "kb-2026-07-06",
"created_at": "2026-07-06T10:00:00Z"
}19.2 为什么要记录版本
没有版本记录,线上效果变差时很难判断:
- 是模型变了
- 是文档变了
- 是 chunk 变了
- 是索引没更新
- 是 query 变了
RAG 的可维护性很大一部分来自这些朴素的工程记录。
20. 成本估算
Embedding 成本通常由三部分组成:
- 入库生成向量的成本
- 向量存储和索引成本
- 在线 query embedding 和检索成本
20.1 入库成本
影响因素:
- 文档数量
- chunk 数量
- 每个 chunk 的 token 数
- 是否重复入库
- 是否频繁重建索引
20.2 存储成本
粗略估算:
text
向量存储大小 ≈ chunk 数量 × 向量维度 × 每个数值字节数例如 float32 是 4 字节。
如果有 100 万个 chunk,每个向量 1536 维,单纯向量数据大约:
text
1,000,000 × 1536 × 4 ≈ 6.1 GB实际系统还会有:
- 索引开销
- metadata
- 文档原文
- 副本
- 日志
所以大规模知识库必须关注维度、压缩和索引策略。
20.3 在线成本
在线查询通常包括:
- query embedding
- 向量检索
- rerank
- 生成模型回答
RAG 系统里,生成模型 token 成本通常更显眼,但 embedding 和向量库成本在大规模场景也会累积。
21. 安全与隐私
Embedding 不等于脱敏。
向量虽然不是原文,但仍可能泄露语义信息,甚至在某些攻击方式下被反推出敏感内容的线索。
21.1 敏感数据处理
入库前要考虑:
- 是否包含 PII
- 是否包含商业机密
- 是否需要脱敏
- 是否允许发给外部 API
- 是否需要本地模型
- 是否需要加密存储
21.2 权限过滤
权限应该作用在检索阶段。
text
User
-> Allowed Scope
-> Metadata Filter
-> Vector Search
-> Authorized Chunks用户没有权限的文档,不应该进入候选集。
21.3 日志风险
日志里可能包含:
- 原始 query
- 召回片段
- 文档标题
- 用户身份
- 权限范围
这些都要按敏感数据处理。
22. 一个最小 Embedding 检索系统
从零搭建时,可以先做最小闭环。
text
Documents
-> Parse
-> Chunk
-> Embed
-> Store Vectors + Metadata
-> Embed Query
-> Search Top-k
-> Show Results
-> Collect Feedback22.1 最小实现要点
- 每个 chunk 有唯一 ID。
- 原文和向量分开存,但能互相定位。
- 保存 document_id、source、updated_at。
- 先做 exact search 或简单 ANN。
- 准备小评测集,不靠肉眼看几条结果。
22.2 最小评测流程
text
Prepare Queries
-> Mark Positive Chunks
-> Run Search
-> Compute Recall@k / MRR
-> Inspect Failures
-> Adjust Chunk / Model / Index23. 实践建议
23.1 从简单开始
不要一开始就上最复杂的向量数据库、reranker 和多路召回。
建议顺序:
- 文档清洗和 chunking。
- 单一 embedding 模型。
- 基础向量检索。
- metadata filter。
- 评测集。
- hybrid search。
- reranker。
- 索引版本和回归测试。
23.2 优先修数据问题
如果文档解析和 chunking 很差,换 embedding 模型通常只是把问题换个形状。
23.3 先按 query 类型评测
不要只看平均分。
要拆开看:
- FAQ 型问题
- 错误码问题
- 政策条款问题
- 多文档综合问题
- 口语化问题
- 中英文混合问题
23.4 失败样例要沉淀
每次线上搜错,都应该记录:
- query
- 召回结果
- 正确结果
- 失败类型
- 修复动作
这些样例会变成后续模型、chunking、rerank 的评测资产。
24. 常见问题
24.1 Embedding 能不能替代数据库查询
不能。
Embedding 适合语义相似,不适合严格条件查询。
例如:
- 查
订单金额 > 1000 - 查
状态 = paid - 查
创建时间在本周
这些应该用 SQL 或结构化查询。
24.2 Embedding 能不能保证事实正确
不能。
Embedding 只能帮你找相似内容。事实正确还要依赖:
- 原始知识质量
- 检索命中
- rerank
- 生成约束
- 引用校验
24.3 是否应该给整篇文档做一个向量
大多数 RAG 场景不建议只给整篇文档做一个向量。
更常见做法是:
- 文档级向量用于粗召回
- chunk 级向量用于精确召回
- section metadata 用于过滤和引用
24.4 换 embedding 模型要注意什么
换模型通常意味着旧向量不能混用。
要处理:
- 重建索引
- 重新评测
- 灰度切流
- 保留旧索引回滚
- 比较失败样例
25. 上线检查清单
数据和 chunk
- 文档解析是否保留标题、表格、页码
- chunk 是否主题单一且上下文完整
- 是否保留 section_path
- 是否有 document_id 和 chunk_id
- 是否有更新时间和来源
模型和索引
- 文档和查询是否使用同一 embedding 模型
- 相似度方式是否和模型匹配
- 是否记录 embedding_model 和 dimensions
- 是否支持重建索引
- 是否有索引版本
检索和评测
- 是否有 Recall@k / MRR / nDCG
- 是否覆盖 hard negative
- 是否按 query 类型评测
- 是否能观察 top-k 结果
- 是否有失败样例回流
安全和权限
- 是否在检索阶段做权限过滤
- 敏感文档是否可控
- 日志是否脱敏
- 是否明确哪些数据不能发给外部 API
26. 推荐搭配阅读
27. 参考资料
以下资料在 2026-07-06 检查时可访问:
官方文档
- OpenAI Embeddings Guide: https://developers.openai.com/api/docs/guides/embeddings
- OpenAI Create Embeddings API Reference: https://developers.openai.com/api/reference/resources/embeddings/methods/create/
- OpenAI Retrieval Guide: https://developers.openai.com/api/docs/guides/retrieval
- Faiss Documentation: https://faiss.ai/index.html
- pgvector: https://github.com/pgvector/pgvector
- Hugging Face Sentence Similarity: https://huggingface.co/tasks/sentence-similarity
论文与基准
- Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks: https://arxiv.org/abs/1908.10084
- MTEB: Massive Text Embedding Benchmark: https://arxiv.org/abs/2210.07316
- Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs: https://arxiv.org/abs/1603.09320
28. 一句话总结
Embedding 是把文本等对象映射到向量空间的表示方法,它让语义相似性可以被计算。真正把 Embedding 用好,不只靠选一个模型,还要处理 chunking、metadata、相似度、索引、混合检索、rerank、评测、权限和版本管理。