Embedding 与语义空间:为什么「相似」不等于「相关」

T0-4模块 0 · 大模型基础面试权重 更新于 2026-08
前置T0-1
关联题目Q1-06

这篇学完你能回答什么

  1. Embedding 是什么?为什么语义相近的两句话,向量距离就近?
  2. 「哪些费用能报销」和「哪些费用不能报销」,向量距离远吗?
  3. 换一个 embedding 模型的代价有多大?为什么它是检索优化里最后才动的一步?

从一个真实故障讲起

一个企业内部知识库的检索服务,上线一周后收到三条投诉,运维一开始以为是三个不同的 bug:

  • 用户问「哪些费用不能报销」,召回的第一条是《可以报销的费用清单》——答案正好相反
  • 用户问「A 型号和 B 型号有什么区别」,召回的全是 A 型号介绍和 B 型号介绍,没有一条讲对比
  • 用户问「2025 年的差旅标准」,召回了 2023 版的同名文档,内容高度相似,年份不对

三个症状,一个根因:向量相似度衡量的是「话题接近」,不是「回答了你的问题」。

否定词在向量空间里几乎不改变方向(整句话谈的还是报销);「区别」这种关系型意图,在只有单篇文档向量的空间里根本没有对应的点;年份这种精确 token,在稠密向量里被稀释成了几乎无差别的信号。

这三类失真不是模型没训好,是这套机制的设计边界。搞清边界,比记住哪个模型排名高有用得多。

三个症状,同一条设计边界
内部知识库上线一周收到三条投诉,运维一开始以为是三个不同的 bug

  1. 用户提问

    「哪些费用不能报销」

  2. 按余弦相似度排序

    整段话谈的还是报销,话题一致

  3. 否定几乎不改方向断点

    「不」只是一个低权重信号

  4. 召回《可以报销的费用清单》

    投诉里的第一条,答案正好相反

否定词问「不能报销」返回《可以报销的费用清单》
关系型意图问「A 型号和 B 型号有什么区别」全是 A 介绍和 B 介绍,没有一条讲对比
精确 token问「2025 年的差旅标准」召回 2023 版同名文档,内容高度相似
三个症状的根因以为是三个 bug衡量的是话题接近,不是回答了你的问题
这三类失真不是模型没训好,是这套机制的设计边界。搞清边界比记住哪个模型排名高有用 —— 而这条边界与「回答了你的问题」之间的缺口,正是分块、混合检索、rerank、query 改写整条流水线存在的理由。

核心概念:先打比方,再给定义

Embedding(嵌入 / 向量表示)。把一段文本压成一个定长的实数向量,比如 1024 个数字。比喻:给每段话在一张巨大的地图上钉一个坐标,意思相近的话钉得近。

但比喻到这里必须补一句关键的:这张地图上「什么算近」,是训练时定义出来的,不是天然的。 这句话是本篇的主轴。

Semantic space(语义空间 / 向量空间)。所有这些坐标构成的高维空间。

Cosine similarity(余弦相似度)。只看两个向量的方向夹角,不看长度。这是检索里最常用的度量——因为文本长度不该影响「说的是不是一回事」。

Contrastive learning(对比学习)。训练 embedding 模型的主流方法:给一大堆(查询,相关文档)配对作为正样本,再配上不相关的作为负样本,用损失函数把正样本拉近、负样本推远。

稠密向量 vs 稀疏向量。稠密向量(本篇主角)每一维都是有值的实数,捕捉语义;稀疏向量(如 BM25 的词频表示)绝大多数维是 0,捕捉字面命中。二者互补,这是混合检索的地基(T2-5 展开)。

比喻只能带你到「钉坐标」
再往下一句才是主轴:这张地图上「什么算近」,是训练时定义出来的

地图 · 给每段话钉个坐标

意思相近的两段话,钉得也近

但「什么算近」不是天然的 —— 比喻到这里就该停,后半句才是这一篇的主轴

对应
Embedding · 向量表示

把一段文本压成定长实数向量

比如 1024 个数字;所有坐标构成的高维空间就是语义空间。检索最常用余弦相似度:只看方向夹角,不看长度

Semantic spaceCosine similarity定长实数向量
钉法 · 有人反复纠正过

该挨着的拉到一起,不该挨着的推开

没人纠正过的那种关系,它就学不会 —— 比如一句话和它的否定形式

对应
Contrastive learning · 对比学习

正样本拉近,负样本推远

训练 embedding 模型的主流方法:(查询,相关文档)配对作正样本,不相关的作负样本,交给损失函数

正样本对负样本对损失函数
还有一对术语要配套记住:稠密向量每一维都是有值的实数、捕捉语义;稀疏向量(如 BM25 的词频表示)绝大多数维是 0、捕捉字面命中。二者互补,是混合检索的地基(T2-5)。

原理拆解

「近」的定义写在训练数据里
这一问最容易答含糊:正确答案不是「因为模型理解了语义」

训练阶段
正样本对「怎么申请年假」配「年假申请流程说明」
负样本对配「打印机维修指南」
反复优化之后
编码器学到映射被判为相关 → 方向接近
检索阶段
在线算query 编码
离线算好,存进向量库文档编码
余弦相似度只看方向夹角,不看长度
Top-K
三个必须记住的已知失真
失真为什么会这样该由谁来接
否定不敏感整段话题一致,否定只是一个低权重信号结构化过滤,别指望向量
精确匹配被稀释年份、型号、金额、人名、错误码在稠密向量里没有专属维度这才是必须搭配 BM25 的根本原因
一段多义被平均一个 chunk 讲三件事,向量落在三件事的平均位置分块策略:chunk 讲一件事(T2-2)

所以「近」等于训练数据里被标成正样本的那种关系。理解这一点,开篇三个故障就全部自解:训练数据里几乎没有「一句话和它的否定形式应该被推远」这样的样本,模型自然没学会区分;也几乎没有「查询是关系、答案要跨两篇文档」这样的样本,空间里根本没有对应的点。

归一化之后,余弦相似度等价于点积 —— 这就是向量库通常要求你先归一化、再用内积检索的原因:更快,而且等价。

为什么语义相近的两句话向量就近?

这是本篇最容易答得含糊的一问。正确答案不是「因为模型理解了语义」,而是:

原文示意
训练阶段
  正样本对:("怎么申请年假", "年假申请流程说明")  → 损失函数把它们拉近
  负样本对:("怎么申请年假", "打印机维修指南")    → 损失函数把它们推远
                      │
                      ▼
        反复优化后,编码器学到一种映射:
        "训练数据里被判为相关的文本对" → 方向接近
                      │
检索阶段              ▼
  query ──► 编码 ──► 向量 ──┐
                            ├──► 余弦相似度 ──► Top-K
  文档 ──► 编码 ──► 向量 ──┘   (文档侧离线算好,存进向量库)

所以「近」的定义,等于训练数据里被标成正样本的那种关系。理解这一点,前面三个故障就全部自解了:训练数据里几乎没有「一句话和它的否定形式应该被推远」这样的样本,模型自然没学会区分;也几乎没有「查询是关系,答案要跨两篇文档」这样的样本,模型自然给不出。

import numpy as np

def cosine(a, b):
    a, b = np.asarray(a), np.asarray(b)
    return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))

# 归一化之后,余弦相似度等价于点积——
# 这就是为什么向量库通常要求你先归一化,然后用内积检索:更快,且等价。
def normalize(v):
    v = np.asarray(v)
    return v / np.linalg.norm(v)

三个必须记住的已知失真

  1. 否定不敏感。「能报销」和「不能报销」余弦相似度极高,因为整段话的话题一致,否定只是一个低权重信号。
  2. 精确匹配被稀释。年份、型号、金额、人名、错误码这类 token,在稠密向量里没有专属维度。这正是必须搭配 BM25 的根本原因,而不只是「工程上稳一点」。
  3. 一段多义会被平均掉。如果一个 chunk 同时讲了三件事,它的向量落在三件事的「平均位置」,结果是对哪一件都不够像。这条把 Embedding 和分块策略直接绑在一起(T2-2)。

工程实践(截至 2026-08)

表 1:两种「相似」,别混用

类型 场景 说明
对称相似(symmetric) 找相似问题、去重、聚类 两侧是同类文本,「像不像」
非对称检索(asymmetric) query → 文档 两侧不同类:短问句 vs 长段落,要的是「答不答得上」

主流 embedding 模型多为指令感知:query 侧和文档侧要加不同的前缀或指令模板。前缀用错、或者只给一侧加,掉点会很明显,而且这种掉点不会报错,只会悄悄拉低召回。这是新手最常踩、也最难自查的一个坑——务必对着模型卡确认。

表 2:几个容易答错的选择

问题 结论
维度越大越好吗 不是。维度上去了,存储、内存、检索耗时都涨,收益递减。部分模型支持维度截断(套娃式表示),可以按需要在精度和成本之间取一档
用什么距离度量 必须和模型训练时一致。训练用余弦却在库里配 L2,结果会莫名其妙地差
向量能跨模型混用吗 绝对不能。不同模型的空间毫无可比性,混用等于随机检索
换模型代价多大 全库重新编码 + 重建索引 + 重跑评测。所以它是检索优化里最后才动的一步

避坑清单

  1. 先确认前缀/指令用法,再谈调优。这一条能救回相当一部分「模型不行」的误判。
  2. 归一化和度量方式在离线建库和在线检索两侧必须一致,包括重建索引时。
  3. 别指望 embedding 处理否定和精确值,那是 BM25 和结构化过滤的活(T2-5)。
  4. chunk 讲一件事。一段多义是向量检索最隐蔽的效果杀手。
  5. 换模型前先证伪其他假设(覆盖率、分块、rerank、query 改写),因为它的迁移成本最高。

本篇只打地基:Embedding 是什么、边界在哪。具体怎么选型、看哪些评测指标、中英文场景差异,见 T2-3

换 embedding 是最后一步棋
截至 2026-08:前缀、维度、度量、对称性四件事定了,再谈调优

六个决策点
要定的事结论代价与依据
query 和文档同一个前缀吗最难自查的一个坑主流模型多为指令感知,两侧要加不同的前缀或指令模板用错、或只给一侧,掉点很明显,而且不会报错
维度越大越好吗不是,收益递减存储、内存、检索耗时都涨;部分模型支持维度截断(套娃式表示),可按需取一档
用什么距离度量必须和模型训练时一致训练用余弦却在库里配 L2,结果会莫名其妙地差
向量能跨模型混用吗绝对不能不同模型的空间毫无可比性,混用等于随机检索
换模型代价多大全库重新编码 + 重建索引 + 重跑评测所以它是检索优化里最后才动的一步
对称相似还是非对称检索找相似问题、去重、聚类是对称;query → 文档是非对称非对称两侧不同类:短问句 vs 长段落,要的是「答不答得上」
避坑清单
先确认前缀用法
再谈调优 —— 这一条能救回相当一部分「模型不行」的误判
两侧必须一致
归一化和度量方式,离线建库与在线检索两侧一致,重建索引时也一样
别指望它做的事
否定和精确值是 BM25 与结构化过滤的活(T2-5)
chunk 讲一件事
一段多义是向量检索最隐蔽的效果杀手
换模型前先证伪
覆盖率、分块、rerank、query 改写全排查完再动它,它的迁移成本最高
本篇的边界
只打地基;怎么选型、看哪些评测指标、中英文场景差异见 T2-3
这几个坑都不会报错:前缀只加了一侧、库里把余弦换成 L2、重建索引时两侧不一致 —— 它们只会悄悄拉低召回。前缀那条务必对着模型卡逐项确认。

面试视角

「为什么就近」,答得出的人不多
Q1-06 是一面送分题,但凡 RAG 相关岗位一定会追到这两问

  1. 一句定义定长向量表示,比如 1024 个数字
  2. 讲清「近」是训练出来的对比学习的正负样本,别说「模型理解了语义」
  3. 主动给出边界否定、精确值、一段多义
  4. 落到工程动作所以配了 BM25 / 改了分块 / 上了 rerank
只读过:这些回答会暴露你
  • 「把文字变成向量,模型理解了语义所以就近了」
  • 认为维度越大越好,没听说过收益递减和维度截断
  • 不知道 query 和文档要用不同前缀
  • 被追问「否定怎么办」就卡住 —— 大多数人卡在这一问
  • 相信「换个排名更高的模型就能解决召回问题」
真做过:这些细节骗不了人
  • 能说出「近的定义来自训练数据里的正样本关系」
  • 知道维度上去了,存储、内存、检索耗时一起涨
  • 说得出自己项目里前缀用法踩过什么坑
  • 主动提否定不敏感和精确值稀释,并给得出工程解法
  • 知道换 embedding 要全库重建,把它排在优化序列最后
「否定怎么办」是能不能进 T2 章节深聊的门票 —— 答得出前一问的人不多,答得出这一问的人更少。会背模型排行榜没用,讲得清边界才有用。配套题目:Q1-06

面试官怎么问。 Q1-06 是一面送分题;但凡是 RAG 相关岗位,一定会追到「为什么向量就近」和「否定怎么办」。答得出前者的人不多,答得出后者的人更少——后者是能不能进入 T2 章节深聊的门票。

答题结构建议

  1. 一句定义(定长向量表示);
  2. 讲清「近」是训练出来的(对比学习,正负样本),不要说「模型理解了语义」;
  3. 主动给出边界(否定、精确值、一段多义);
  4. 落到工程动作(所以我们配了 BM25 / 改了分块 / 上了 rerank)。

分水岭信号

  • 只读过:说「embedding 就是把文字变成向量,模型理解了语义所以就近了」;认为维度越大越好;不知道 query 和文档要用不同前缀;相信「换个排名更高的模型就能解决召回问题」。
  • 真做过:能说出「近的定义来自训练数据里的正样本关系」;一被问就主动提否定不敏感和精确值稀释这两个坑,并且给得出对应的工程解法;知道换 embedding 要全库重建,因此把它排在优化序列的最后;说得出自己项目里前缀用法踩过什么坑。

小结与延伸

一句话收口:Embedding 给你的是「话题接近」,不是「回答了你的问题」;这两者之间的缺口,正是分块、混合检索、rerank、query 改写这一整条流水线存在的理由。

  • 关联题目:Q1-06
  • 延伸:T2-2(分块与语义切割)、T2-3(Embedding 选型与评估)、T2-5(混合检索:BM25 + 向量 + RRF)、T2-6(Rerank)

继续深入

本篇归属第 1 章「LLM 与 Prompt 基础」,去做这一章的题