Embedding Lab

交互式 Embedding 原理实验室 — 理解向量空间、分片策略与检索范式

什么是 Embedding?

Embedding 是将文本映射到高维向量空间的过程。每段文本被转换为一个固定维度的数字向量(如 384 维),语义相似的文本在向量空间中距离更近

"这个手机拍照很好"
→ Embedding 模型 →
[0.12, -0.34, 0.56, ..., 0.78]384维

这个过程是有损压缩——不管文本多长,最终都压缩成固定维度的向量。因此,文本内容的质量和纯度直接影响向量的表达能力。

余弦相似度:衡量语义距离

两个向量之间的余弦相似度衡量它们方向的一致性(0=无关,1=完全相同)。试试下面的预设句子对:

或输入自定义句子(需加载浏览器模型,约 23MB):

Transformer 中的 Q·K·V 与 Embedding 检索

Query (Q) 我在找什么? Key (K) 我身上有什么标签? Q·K 注意力权重 softmax(Q·K/√d) Value (V) 实际携带的信息 加权求和 Attention × V ≈ Embedding 检索 Query · Document → 相似度分数 → 返回最近结果

本质上,Transformer 内部的 Q·K 注意力和 Embedding 检索中的 query·document 余弦相似度是同一个操作——在高维空间中做相似性匹配。区别在于:Attention 是模型内部的软检索(每层都在做),Embedding 检索是模型外部的硬检索(在知识库上做一次)。

分片策略如何影响 Embedding 分布

Chunk 太大 / 多主题混杂

向量被"拉扯"到多个语义簇的中间地带,谁都沾点边但都不精确匹配。

Chunk 语义纯粹 / 单主题

向量在空间中的位置"尖锐"明确,容易被精准召回。

含转折词

正面和负面语义对冲,向量落在两个方向的折中位置。

序号列表

同主题列表:强化信号。跨主题列表:等同于多主题混杂。

Q2Q / Q2A / A2A 检索范式

Q2Q

问题 → 问题

知识库存的是问题,用新问题匹配已有问题,再返回对应答案。典型相似度:0.85-0.95

Q2A

问题 → 文档

知识库存的是文档/答案,用问题直接匹配文档。非对称匹配,典型相似度:0.50-0.70

A2A

文档 → 文档

用文档匹配文档,用于去重、聚类、相似推荐。对称匹配。

Embedding Playground

输入多段文本,实时看到它们在向量空间中的位置和相互间的相似度。

预设示例:

分片实验室

选择预设实验,观察不同分片策略下的 Embedding 分布和召回效果。

自定义文本

输入自定义 chunk,叠加到当前实验的散点图(需加载浏览器模型):

检索范式对比

同一个 Query,在 Q2Q、Q2A、A2A 三种模式下的检索效果对比。

当前 Query:

Q2Q — 问题匹配问题

知识库 = 问题库,匹配最相似的已有问题

Q2A — 问题匹配文档

知识库 = 文档 chunks,直接匹配内容

A2A — 文档匹配文档

文档之间的聚类和相似度关系

三模式相似度对比

Bi-Encoder 架构

Query Encoder 共享权重 vec_q Document Encoder 共享权重 vec_d 共享权重 cosine(q, d) 相似度分数

Bi-Encoder 是当前主流的 Embedding 模型架构。它的核心思想是:将 Query 和 Document 分别独立编码为向量,然后通过余弦相似度衡量语义相关性。两个编码器共享同一组参数(共享权重),这意味着同一个模型同时负责处理查询和文档。这种架构的优势是文档向量可以离线预计算并存入向量数据库,检索时只需编码一次 Query 然后做最近邻搜索,速度极快。

训练三元组(Training Triplets)

Embedding 模型通过三元组(Triplet)进行训练,每个三元组包含:一个查询(Query)、一个正例文档(Positive)和一个负例文档(Negative)。训练目标是让模型学会将 Query 的向量拉近 Positive,同时推远 Negative。例如:对于查询"怎么申请退款?",正例是退款流程文档,负例是物流查询文档。经过大量三元组训练后,模型学会了将语义相关的文本映射到向量空间中的相邻位置。

对比学习动画(Contrastive Loss)

对比学习(Contrastive Learning)的损失函数驱动整个训练过程。每个 batch 中,模型计算 Query 与所有 Positive/Negative 的相似度,然后通过 InfoNCE Loss 使 Query-Positive 相似度最大化、Query-Negative 相似度最小化。左图展示了训练过程中向量空间的演变——随着训练推进,同类文本聚拢、异类文本分离;右图展示了 Loss 曲线的下降过程。

难负例与数据质量(Hard Negatives)

负例的选择对训练效果影响巨大。随机负例(左图)通常与 Query 毫不相关,模型很容易区分——训练信号弱,学不到细粒度的语义差异。难负例(Hard Negatives)(右图)是与 Query 表面相似但实际不相关的文档(如同主题但不同子问题),模型必须捕捉细微语义差别才能区分——训练信号强,学到的向量表示更精确。优质的训练数据应尽量使用难负例来提升模型的判别能力。

为什么我的 Chunk 检索不到?

即使 Embedding 模型质量很高,检索仍然可能失败。理解失败模式是优化 RAG 系统的关键。以下是三种最常见的检索失败原因——语义稀释、语义鸿沟和否定陷阱。点击切换查看每种模式的具体表现。

Top-K 和阈值该怎么设?

在 RAG 系统中,Top-K(返回多少条结果)和相似度阈值(多低的分数可以接受)是两个关键参数。设得太高会引入噪声,设得太低会遗漏相关内容。理解相似度分数的分布特征,才能做出合理的参数选择。选择一个查询,观察其相似度分布:

相似度分布

Precision / Recall 权衡 与 Top-K 分析

Bi-Encoder vs Cross-Encoder:为什么 Reranker 有用?

Bi-Encoder(独立编码)

Query Encoder vec_q Doc Encoder vec_d cosine 相似度

Cross-Encoder(联合编码)

Query Doc Encoder Cross-Attention 相关性 分数 联合编码,交叉注意力

Bi-Encoder 将 Query 和 Document 独立编码为向量,速度快(文档可预计算),但无法捕捉 Query 和 Document 之间的细粒度交互。Cross-Encoder 将 Query 和 Document 拼接后联合输入 Transformer,通过 Cross-Attention 捕捉每个 token 之间的交互关系,精度更高但速度慢(每对都要过一次模型)。因此实际应用采用 两阶段模式:先用 Bi-Encoder 快速召回 Top-N 候选,再用 Cross-Encoder(Reranker)对候选精排。

排序对比:Bi-Encoder vs Cross-Encoder

上方展示同一 Query 下,Bi-Encoder(余弦相似度)排序与 Cross-Encoder(相关性分数)排序的对比。注意观察排名变化——某些文档在 Bi-Encoder 中排名较低,但被 Cross-Encoder 提升到前列(因为联合编码捕捉到了更深层的语义关联)。这就是 Retrieve-then-Rerank 的核心价值:用快速粗排筛选候选,用精排模型修正排序。

HyDE:假想文档 Embedding

HyDE(Hypothetical Document Embeddings)解决的核心问题是:用户提问和知识库文档之间存在天然的语义空间偏移——提问是"问题空间"的表达,文档是"答案空间"的表达,两者在向量空间中可能距离较远。HyDE 的做法是:先让 LLM 根据 Query 生成一个假想答案(不需要准确),然后用这个假想答案的 Embedding 去检索。因为假想答案和真实文档都属于"答案空间",它们在向量空间中更近。

Query
→ LLM →
假想答案
→ Embedding →
假想向量
→ 检索 →
真实文档

关键洞察:假想答案不需要事实正确,只需要在文体和语义结构上接近真实文档即可。因为 Embedding 模型关注的是语义空间位置而非事实准确性。

向量空间可视化

上方散点图展示了 Query、假想答案和真实文档在向量空间中的位置关系。箭头从 Query 指向假想答案、再指向真实文档,直观展示了 HyDE 如何"桥接"问题空间和答案空间。柱状图对比了 Query→文档 的直接相似度与 假想答案→文档 的相似度——后者通常更高,因为假想答案已经被"转换"到了文档所在的语义空间。

稀疏检索 vs 稠密检索:何时用哪个?

稀疏检索(BM25)基于精确的词汇匹配——统计查询词在文档中出现的频率和稀有程度,适合精确关键词和专有名词。稠密检索(Embedding)基于语义匹配——即使查询和文档用词完全不同,只要语义相近就能匹配,适合口语化提问和同义改写。两种方法各有擅长场景,理解它们的差异是构建高质量检索系统的基础。

排序对比:BM25 vs Embedding

混合检索:Reciprocal Rank Fusion (RRF)

单独使用 BM25 或 Embedding 都会有盲区。混合检索通过融合两种排序来互补优缺点。RRF 是最常用的融合算法,其公式为:

RRF(d) = Σ 1 / (k + ranki(d)),   k = 60

RRF 只使用排名而非原始分数,因此不受 BM25 分数无界(0~20+)和余弦相似度有界(0~1)的尺度差异影响。参数 k=60 是原始论文推荐的常数,用于平滑排名差异。

分数分布对比

上图叠加展示了 BM25 分数和 Embedding 余弦相似度的分布。注意 BM25 分数是无界的(通常 0~20+),而余弦相似度被限制在 0~1 之间。这种尺度差异意味着不能简单地将两个分数相加——BM25 的高分会"压制"Embedding 分数。这正是 RRF 使用排名而非原始分数进行融合的原因。

Chunk 构建质量:噪声如何影响 Embedding

Embedding 模型的输入就是你的 chunk 文本——文本里的每一个字符都会变成 token 参与向量计算。JSON 括号、时间戳、页眉页脚、装饰符号……这些"噪声"都会占据有限的表示容量,稀释核心语义信号。下面通过 6 类常见噪声源,量化它们对检索相似度的真实影响。

测试 Query: 基准纯文本:

各变体详情

实践建议

检索评估指标:MRR / NDCG / MAP

检索系统的核心问题是:返回的结果排序够不够好?不同的评估指标从不同角度衡量排序质量。拖动下方文档改变排序,实时观察各指标的变化。

MRR (Mean Reciprocal Rank)

MRR = 1 / rankfirst_relevant

只关心第一个相关结果的位置。排在第1位=1.0,第2位=0.5,第3位=0.33…

NDCG@K (Normalized DCG)

DCG = Σ (2rel - 1) / log₂(rank+1)

支持多级相关度(0/1/2/3),高相关度排在前面得分更高,除以理想排序 (IDCG) 归一化到 0~1。

MAP (Mean Average Precision)

AP = Σ P@k · rel(k) / |relevant|

在每个相关文档位置计算 Precision@K 取平均。同时奖励数量多排序靠前

交互实验:拖动文档,观察指标变化

当前排序 (点击 ▲▼ 调整顺序)

实时指标

指标选择指南

MRR — 适合只需要找到"一个最佳答案"的场景(如问答系统)
NDCG — 适合有多级相关度标注的场景(如搜索引擎,区分"完美匹配"和"部分相关")
MAP — 适合需要找到"所有相关结果"的场景(如法律文书检索、专利搜索)

Embedding 模型选型指南

选择合适的 Embedding 模型是 RAG 系统的基础决策。模型的维度、语言支持、速度和精度各有权衡。通过下面的实验数据和对比表,帮助你做出明智的选择。

维度截断实验:维度越高越好吗?

将同一模型(384维)的向量截断到不同维度,观察相似度的变化。这模拟了选择不同维度模型的效果。

实验使用 Query「」与 5 篇文档的相似度计算。

查询风格对检索效果的影响

同一个意图,用不同风格表达,检索效果差异很大。关键词查询、口语化提问、书面查询——模型对哪种更友好?

主流模型对比

根据你的场景选择合适的模型:

选型建议

  • 纯中文场景:优先 bge-base-zh / bge-large-zh,中文效果显著优于多语言通用模型
  • 多语言场景:multilingual-MiniLM 或 cohere-embed-v3
  • 追求极致精度:text-embedding-3-large 或 bge-large-zh,但成本和延迟更高
  • 预算有限:all-MiniLM-L6-v2(英文)或 multilingual-MiniLM(多语言),可自部署
  • Matryoshka (套娃) 模型:支持运行时维度截断,如 text-embedding-3 系列

ColBERT:Late Interaction 检索

Bi-Encoder 把整段文本压缩成一个向量,信息损失大。Cross-Encoder 让 Query 和 Document 全交叉注意力,精度高但无法预计算。ColBERT 提出了折中方案——Late Interaction(延迟交互):分别编码 Query 和 Document 的每个 token,然后在 token 级别做匹配。

Stage 1: 独立编码
Query → [vec_q₁, vec_q₂, …]
Doc → [vec_d₁, vec_d₂, …]
Stage 2: MaxSim
对每个 q_token,找到最匹配的 d_token
MaxSim = Σ max(sim(qᵢ, dⱼ)) / |Q|
最终得分
聚合 token 级匹配分数
保留细粒度语义信号

Token 级相似度矩阵

下方热力图展示 Query token 与 Document token 之间的逐对相似度。每行高亮的 cell 是该 query token 的 MaxSim(最佳匹配),所有 MaxSim 的均值即为 ColBERT 总分。

Bi-Encoder vs ColBERT 对比

ColBERT 的 Token 级匹配能捕捉到 Bi-Encoder 遗漏的局部语义对齐。例如 Query 中的「退款」token 可以精确匹配到文档中的「退款」和「申请退款」,而 Bi-Encoder 只能依赖整个句子的平均语义。

三种架构对比

分片策略对比:怎么切才最好?

RAG 系统的第一步是把文档切成 chunk。切法不同,检索效果天差地别。下面用同一篇文档、同一个 Query,对比四种常见分片策略的召回效果。

策略效果对比

分片详情:

所有分片 UMAP 分布

不同颜色代表不同分片策略。可以看到粒度越细的策略(如按句子分割)产生的点越分散,而固定长度切分的 chunk 可能跨越多个语义区域。

Contextual Retrieval:给 Chunk 补上下文

Chunk 被从文档中切出后,失去了文档级别的上下文信息。比如一个 chunk 说"金额将在3-5个工作日内退回",但不知道这是在说退款、工资还是退税。Contextual Retrieval 的核心思想是:在每个 chunk 前面加上一段由 LLM 生成的上下文摘要,让 chunk 自己"说清楚"自己是什么。

原始 Chunk
金额将在3-5个工作日内退回…
+ LLM →
增强 Chunk
来自「退款政策」文档…
金额将在3-5个工作日内退回…

实验对比:有无上下文的相似度变化

关键结论

Embedding 量化:精度 vs 存储 vs 速度

一个 384 维的 float32 向量占 1,536 字节。当知识库有百万文档时,仅向量就需要 ~1.5GB 内存。量化通过降低每个维度的精度来压缩向量,但会引入误差。关键问题是:精度损失多少才能接受?

32-bit
float32 原始精度
1,536 字节/向量
8-bit
int8 量化
384 字节/向量 (4x)
4-bit
int4 量化
192 字节/向量 (8x)
2-bit
int2 量化
96 字节/向量 (16x)
1-bit
Binary 量化
48 字节/向量 (32x)

精度悬崖:从哪一级开始有损?

下图展示不同量化精度的平均误差和排名相关性。注意 int8 的误差肉眼不可见,但从 int4 开始误差急剧上升——这就是"精度悬崖"。

量化对相似度的影响

精度损失总结

维度 × 量化:低维度让量化更脆弱

高维向量的量化误差会在求和中抵消(中心极限定理)。维度越低,抵消效果越弱,量化损失越大。下图展示同一量化精度在不同维度下的误差变化。

向量索引与近似最近邻(ANN)

前面所有的检索实验都默认了一件事:我们可以快速从数十万甚至数百万向量中找到最相似的那几条。但现实中,暴力遍历每一条向量(Flat Search)的计算量随数据规模线性增长,很快就不可行。近似最近邻(ANN)通过构建索引结构,用少量精度损失换取数量级的速度提升。

数据规模与检索延迟

拖动滑杆改变知识库大小,观察暴力检索和 ANN 的延迟差异:

HNSW:分层可导航小世界图

HNSW(Hierarchical Navigable Small World)是目前最流行的 ANN 算法。它在向量之间建立多层图结构——顶层是稀疏的"高速公路",底层是稠密的"本地道路"。检索时从顶层入口点出发,逐层向下跳跃,每层贪心地走向离目标最近的节点,直到底层找到候选集。

点击播放,观察 HNSW 如何从入口逐层导航到目标

关键参数

M
每个节点的最大连接数。M 越大,图越稠密,精度越高,但构建和内存成本也越高。
典型值:16~64
efConstruction
构建时的候选队列大小。越大则构建越慢但索引质量越高。
典型值:100~500
efSearch
检索时的候选队列大小。这是运行时最重要的旋钮——直接控制精度与速度的权衡。
典型值:50~400

Recall vs 延迟:efSearch 调参

增大 efSearch 可以提升召回率,但也会增加延迟。下面模拟了不同 efSearch 值下的权衡曲线。拖动滑杆选择你的工作点:

四种索引类型对比

不同场景适合不同的索引策略。理解它们的核心机制和权衡,才能选对方案:

索引选型决策

< 10 万条
Flat(暴力搜索)
数据量小,暴力搜索延迟在 10ms 以内,无需引入索引复杂度。
10 万 ~ 1000 万条
HNSW
最主流选择。延迟低(<10ms),召回率高(>95%),支持增量插入。内存够用即选它。
> 1000 万条且内存受限
IVF + PQ
PQ 把每个向量压缩到数十字节,IVF 只搜索相关分区。牺牲部分召回率换取大幅降低内存。
超大规模 + 实时更新
HNSW + PQ 混合
用 PQ 压缩存储,用 HNSW 图结构做路由。在 Milvus、Qdrant 等引擎中常见此组合。

训练数据从哪里来?

在"模型训练"中我们了解了 Embedding 模型通过三元组(Query, Positive, Negative)训练。但在真实项目中,最大的挑战不是训练过程,而是获取高质量的训练数据。下面是四种最常见的数据来源,从零成本到高成本排列:

📋
FAQ / 知识库配对
成本:零
已有的 FAQ 自带 (问题, 答案) 对,直接当作正样本。如果知识库有标题,标题和内容天然构成配对。
正样本:"怎么退款?" → 退款流程文档
负样本:同批次其他 FAQ 的答案(in-batch negatives)
🔍
搜索日志 / 点击日志
成本:低
用户搜索后点击的结果是弱正样本,展示但未点击的是弱负样本。数据量大但噪声也大,需过滤。
正样本:搜索 "退款" → 点击了第 3 条结果
过滤规则:停留 >30s 的点击更可靠
🤖
LLM 生成合成数据
成本:中
给 LLM 一段文档,让它生成可能的用户问题。批量生产 (query, document) 对。质量取决于 prompt 设计。
Prompt:"根据以下文档生成 3 个用户可能会问的问题"
验证:抽样检查生成质量,过滤低质问题
👨‍💻
人工标注
成本:高
标注员对 (query, document) 对打相关性分数(0~3)。质量最高,但成本随数据量线性增长。
标注任务:这个 query 和 document 相关吗?(0=无关, 1=部分相关, 2=高度相关, 3=完美匹配)
规模建议:至少 1000~5000 对

负样本质量:从随机到困难

负样本的选择直接决定训练效果。下面展示了同一个 Query 在不同负样本策略下,相似度分数和模型学到的区分能力差异。注意观察正负样本之间的分数差(margin)——margin 越小,训练信号越强:

什么时候该微调?

微调 Embedding 模型是一个成本不低的决策。用错了时机会浪费资源,用对了可以显著提升效果。根据以下条件判断是否需要微调:

通用模型在你的数据上 Recall@10 是否 > 80%?
是 → 通用模型可能够用
你的领域有大量专有术语或行话?
是 → 考虑微调
微调收益:中等
专有术语的语义关系是通用模型没见过的
否 → 暂不微调
先优化 chunking、prompt 和 reranker,这些成本更低
否 → 需要干预
你有 ≥ 1000 条标注数据或高质量配对?
是 → 微调
微调收益:高
数据充足 + 现有模型不足 = 微调的最佳时机
否 → 先攒数据
用 LLM 合成数据 + 搜索日志收集,积累到足够规模再微调

微调的成本与收益

收益

  • 领域术语的语义对齐提升 10~30%
  • 专有名词和缩写的召回率显著改善
  • 在特定任务上超越更大的通用模型
  • 更小模型 + 微调 = 更大模型同等效果,推理更快

成本与风险

  • 需要 GPU 资源和训练时间(小模型约 1~4 小时)
  • 微调后模型版本独立,需重新计算所有向量
  • 数据质量差会导致模型退化(比通用模型更差)
  • 过拟合风险:在训练集上表现好,其他数据上变差

微调前检查清单

✓ 已经尝试过优化 chunking 策略
✓ 已经尝试过 query 改写或 HyDE
✓ 已经尝试过 Reranker
✓ 有 ≥ 1000 条高质量标注数据
✓ 有量化的评估基线(MRR/NDCG/Recall)
✓ 接受微调后需要重建所有向量索引

Token 截断:长文档的隐形杀手

Embedding 模型有固定的 max_length(通常 128~512 tokens)。超过这个长度的文本会被静默截断——尾部内容直接丢失,不会报错。这意味着如果关键信息在文档末尾,embedding 完全"看不到"它。

核心启示:分片长度的设计不是"越长越好",而是必须在模型 max_length 范围内。超长文档分片必须考虑截断风险。

截断对 Embedding 质量的影响

选择不同长度的文本,观察在不同截断长度下 embedding 与完整文本 embedding 的相似度。注意:本实验使用的模型 max_seq_length = 128 tokens。超过 128 tokens 的内容会被模型静默丢弃,因此 128 tokens 之后的曲线不会再变化——不是因为"几乎无损",而是因为模型根本看不到更多内容。

截断对检索的影响

同一文本在不同截断长度下,对 3 个 query 的检索相似度变化。关注:当截断长度不够时,与某些 query 的相似度可能大幅下降。

尾部信息丢失实验

"跨境订单配送要多久?"这个 query 的答案在文档末尾。当文档被截断到 128 tokens 时,跨境相关内容完全丢失。

什么时候该微调 Embedding 模型?

微调能让 embedding 模型更好地理解你的领域术语和业务表述。但它有成本:需要标注数据、GPU 资源、重建所有向量。关键问题不是"能不能微调",而是 "值不值得微调"

决策树:是否需要微调?

跟随下面的决策流程,判断你当前是否需要微调 Embedding 模型。

通用 Query vs 领域 Query 效果对比

通用表述(如"怎么申请退款")在预训练模型上效果不错;但领域术语(如"RMA 流程"、"SLA 时效")的检索效果明显更差。微调后领域术语的检索效果显著提升。

微调前检查清单

已尝试优化 chunking 策略(分片长度、重叠、按语义切分)
已尝试 query 改写或 HyDE
已尝试 Reranker 进行二阶段精排
有 ≥ 1000 条高质量 (query, positive, negative) 标注数据
已有量化评估基线(MRR / NDCG / Recall)
接受微调后需要重建所有向量索引

多语言 / 跨语言检索

多语言 Embedding 模型(如 multilingual-MiniLM)将不同语言映射到共享的向量空间。这意味着中文 query 可以直接检索英文文档,反之亦然——无需翻译。

核心机制:多语言模型在训练时使用平行语料(同一内容的多语言版本),迫使模型将相同语义的不同语言文本编码到相近位置。

跨语言对齐:中英 Query 的向量相似度

相同语义的中英文 query 在向量空间中距离多近?下图展示语义等价的中英文 query 对之间的 cosine similarity。

跨语言检索矩阵

选择查询方式,观察不同语言的 Query × Doc 检索效果。跨语言检索的精度略低于同语言,但仍保持较高水平。

向量空间 UMAP 可视化

中英文的 query 和 document 在向量空间中的分布。注意语义等价的中英文内容聚集在一起。

从实验到生产:向量检索系统的工程挑战

在 Playground 里跑通了检索,离生产上线还有很大距离。向量检索系统的核心工程问题不在于"能不能检索到",而在于数据变了怎么办、模型升级了怎么办、线上出问题怎么排查

索引生命周期

文档不是一次性导入就完事的。新增、修改、删除文档都需要更新索引。不同更新策略的复杂度和一致性保证差异很大:

全量重建
删除旧索引 → 重新切分所有文档 → 重新 Embedding → 构建新索引 → 切换
优势:一致性最强,无残留脏数据
劣势:耗时长(百万级需要数小时),服务有切换窗口
适用:模型升级、分片策略变更、低频更新场景
增量更新
检测变更文档 → 仅对变更部分重新切分 + Embedding → 插入/替换索引条目
优势:速度快,对服务影响小
劣势:需要维护文档 → chunk → 向量的映射关系,可能积累碎片
适用:高频更新场景(文档每天变化)
双索引蓝绿切换
后台构建新索引(不影响线上)→ 验证通过 → 原子切换流量 → 下线旧索引
优势:零停机,可回滚
劣势:需要双倍存储,构建期间数据可能不一致
适用:对可用性要求高的生产服务

模型版本迁移

当你升级 Embedding 模型时,新旧模型产生的向量处于不同的向量空间——即使是相同文本,不同模型的向量也不能直接比较。这意味着:

1
新旧向量不可混用

用旧模型编码的 query 去搜索新模型编码的文档,相似度分数没有意义。必须保证 query 和 document 用同一个模型。

2
全量重算是最安全的做法

升级模型后,对所有文档重新计算向量并重建索引。通过蓝绿切换实现零停机迁移。

3
维度变化需要重建索引结构

从 384 维升级到 768 维,索引不能复用。存储、内存、检索延迟都会变化,需要重新规划容量。

4
评估基线必须对齐

在切换前用同一份测试集分别跑新旧模型,确认新模型在你的数据上确实更好,再执行迁移。

线上监控:看什么指标?

上线后最怕的是"悄悄变差"。以下指标帮你及时发现问题:

空结果率
阈值: < 5%
没有返回任何结果的查询占比。飙升通常意味着索引损坏、模型加载失败或 chunk 覆盖不足。
Top-1 相似度中位数
关注趋势变化
最高相似度分数的中位数。持续下降可能说明新增文档的质量在下降,或者 query 的分布在漂移。
P99 延迟
阈值: < 100ms
99% 请求的检索延迟。突然增高可能是索引碎片化、内存不足导致换页、或并发量超出预期。
用户反馈/点击率
代理 Recall 指标
用户是否点击了检索结果、是否给出负面反馈。这是离线评估指标(MRR/NDCG)在线上的代理。
向量维度一致性
必须 100%
所有入库向量的维度必须和索引声明一致。维度不匹配会导致静默错误(返回随机结果)。
索引大小 / 文档数
应与源文档同步
如果索引文档数显著少于源文档数,说明有数据丢失。如果显著多于,说明删除操作没有同步到索引。

交互式故障排查剧本

线上向量检索系统出问题时,选择你遇到的症状,跟随排查路径一步步定位根因:

选择你遇到的症状:

Embedding 缓存与去重

生产中,知识库常有大量近似重复内容(如不同版本的文档、微调后的 FAQ)。重复 embed 相同内容既浪费算力,又让检索结果充斥冗余。缓存避免重复计算,去重清理冗余文档。

近似重复检测

近似重复(措辞微调)vs 语义相关但不同的内容——cosine similarity 能区分它们吗?阈值设多高才不误杀有用内容?

去重阈值与精度

调高阈值可以减少误判,但也会漏掉更多真正的重复。下图展示不同阈值下的去重效果。

缓存策略:节省多少算力?

假设 15% 的文档是重复的,使用 hash→embedding 缓存可以节省多少 embed 调用?

推荐流程

1
文本 Hash
对原始文本计算 SHA-256,命中缓存直接返回已有向量
2
Embed + 存缓存
未命中则调用模型计算,将 hash→vector 写入缓存
3
语义去重
入库后用 cosine similarity ≥ 0.95 检测近似重复,保留最新版本
4
定期清理
全量扫描去重,清理过期缓存,重建索引

多模态 Embedding:从文本到图片、音频

传统 Embedding 只处理文本。多模态模型(如 CLIP)将不同模态的数据映射到同一个向量空间,实现跨模态检索——用文字搜图片、用图片搜文字。

核心原理:训练时用大量(图片, 文本描述)配对数据,迫使模型将匹配的图文对编码到相近位置,不匹配的推远。这和文本 embedding 的对比学习思路完全一致。

跨模态对齐实验

用文本 query 检索"图片描述"(模拟图文检索)。匹配的 query-图片对 vs 不匹配对的相似度差异有多大?

文本 Query × 图片描述 检索矩阵

对角线是语义匹配的 query-图片对。理想情况下对角线应该最亮。

向量空间 UMAP 可视化

图片描述和文本 query 在向量空间中的分布。语义匹配的图文对应该聚集在一起。

多模态模型对比