这页负责数学原理和概念直觉推导(向量空间、余弦、Embedding),不负责术语速查。 需要快速查定义请用 概念手册 rag-5d;工程调优请看 工程手册
适合任务
补齐 embedding、向量、维度和余弦的底层直觉,给后面的代码阅读打基础。
前置阅读
课程路线图,先知道这页位于整体学习链路里的什么位置。
Page Summary
这页解决什么
解释“文本为什么能变成向量”,并把余弦相似度和语义检索连接成一条完整因果链。
必须记住的结论
向量不是标签而是语义空间中的方向;余弦更适合比较主题一致而长度不同的文本。
读完后的动作
去看 V1 代码讲解,然后运行最小 RAG 循环,观察 query 和文档的相似度排序。
适合阶段
开始跑第一份代码前;需要补齐 embedding / 向量 / 余弦的底层直觉时。
相关代码
对应 `code/01_v1_最小RAG循环.py` 的 embedding 和 cosine 检索部分。
前置 / 下一步
Knowledge Units
Embedding
把语义转成向量,使“语义相近”可以变成“方向接近”。这是一切语义检索成立的起点。
余弦相似度
它比较的是方向而不是长度,所以更适合比较长短不同但主题接近的文本。
实践边界
如果还没理解“为什么用余弦”,先不要急着看模型榜单或向量库选型。
01 计算机为什么"只能做数学" 从手机联系人开始
第一步
你手机里的"张三",手机认识他吗
你手机里存了 500 个联系人。手机认识"张三"这个人吗?

不认识。 它只是记住了一串数字:13812345678

你在屏幕上看到的"张三",只是手机把那串数字"翻译"给你看的显示效果。 手机从来不理解"张三是谁"——它只存数字,只处理数字。

这不只是手机的限制,而是所有计算机的本质
第二步
你现在看的这段文字,也是数字
计算机的底层只有 0 和 1。所有东西,最终都是数字:

你看的视频 → 每一帧都是像素颜色值(一堆数字)
你听的音乐 → 声波振幅的采样值(一堆数字)
你发的消息 → 每个汉字都有编号,"你"是 20320,"好"是 22909

计算机处理的一切,最终都是数字的加减乘除。
它从来不"看",不"听",不"理解"——只是算。
第三步
那"意思"呢?
"猫很可爱"和"小猫咪特别萌",你知道这两句话意思一样

但在计算机眼里,这是两串完全不同的汉字编号,没有任何联系。 让计算机比较这两句话"有多像",它只会傻掉—— 没有规则告诉它"可爱"和"萌"是同一个意思。

核心矛盾:我们需要计算机理解语义,但计算机只会处理数字。
解决思路自然浮现:把"意思"也变成数字。
而且不是随便变——要让数字之间的关系,能反映语义之间的关系。
意思相近的文字 → 变成的数字要"方向相近"。这就是向量要做的事。
为什么
随便编号为什么不行
把"猫"编号为 1,"狗"编号为 2,"量子力学"编号为 3——

计算机会认为猫和狗的差距(1)等于狗和量子力学的差距(1)。 但现实是猫和狗非常相关,猫和量子力学几乎没关系。

普通编号只是给事物贴标签,不能表达它们之间的关系。 需要一种更好的数字表示:相关的事物在数字层面也"挨在一起"。
02 什么是向量 食物坐标系 → 语义空间
直觉
用两个维度描述食物
用"甜度"和"辣度"两个维度,可以在坐标图上定位任何食物:

番茄:甜度中等,辣度几乎为零 → [5, 0]
糖醋排骨:甜度高,辣度低 → [8, 1]
辣椒:甜度低,辣度极高 → [1, 9]

画在坐标图上,每种食物都是图上的一个点(更精确说是从原点出发的一个方向)。 番茄和糖醋排骨挨得很近,因为都偏甜。辣椒在另一个角落。
图示:方向相近 = 语义相近(夹角决定相似度)
甜度 → 辣度 0 番茄 糖醋排骨 辣椒 θ小 θ大 关键:看方向(夹角),不看距离 θ小 → 语义相近 番茄 ↔ 糖醋排骨 ≈ 0.97 θ大 → 语义无关 番茄 ↔ 辣椒 ≈ 0.11
向量就是:从原点出发的一条有方向的线,用一组数字表示坐标。
两条线的夹角越小,方向越相近——语义越相近。
余弦相似度量的正是这个夹角有多小(cos 0° = 1,cos 90° = 0)。

真实 Embedding 不是 2 维,而是 1024 维(BGE-M3)或 1536 维(text-embedding-3-small)。 道理完全一样,只是维度更多,能捕捉更复杂的语义关系。 下一节专门解释"1024 个维度,每个是什么意思"——这里有一个常见误解需要纠正。

03 1024 个维度,每个代表什么意思 最容易被误解的地方——用 RGB 颜色来理解
先纠正一个几乎所有人第一次都会犯的误解:
不是每个维度单独代表"动物相关性""甜度""是否有生命"这类可命名的特征。
单个维度对人类来说完全不可读,没有名字,没有独立意义。
类比
彩色照片是怎么存的——RGB 三个数字
每个像素存三个数字:红 R、绿 G、蓝 B。
没有任何一个数字单独"是"某种颜色。是三个数字的组合决定了颜色。
R=255, G=0, B=0 红色   (只有 R 有值)
R=255, G=255, B=0 黄色   (R 和 G 都有值,两者合力)
R=70, G=130, B=180 钢蓝色(三个数字合力,任何单个数字单独没意义)
扩展
Embedding 向量做的是同一件事,从 3 维扩到 1024 维
"猫" 的向量:[0.023, -0.018, 0.045, 0.012, ... (共1024个数字)]

没有哪个数字单独"是"动物相关性。
没有哪个数字单独"是"可爱程度。
没有任何一个维度有名字。

是 1024 个数字作为整体,在高维空间里的方向,决定了语义。

研究者偶尔发现某几个维度大致对应"性别"或"时态"这类概念, 但这是偶然观察到的,不是设计出来的。神经网络自己找到这种表示方式, 这些维度对人类不可读,是黑盒。
更准确的说法:1024 个数字合在一起,是这段文字语义的"数字指纹"。
就像一张照片里每个像素的 RGB 组合在一起才是那张照片,
向量的 1024 个数字组合在一起才是那段文字的语义。
任何单个数字单独拿出来,都毫无意义。
04 "变成向量"具体是怎么发生的 从语言学假设到神经网络训练
根源
一个关键假设:意思由上下文决定
1954 年,语言学家 Zellig Harris 提出了一个假设,后来成为所有词向量技术的根基:

"一个词的意思,可以从它经常出现的上下文来理解。"

"猫"经常和"养猫""猫粮""猫爪""可爱"一起出现。
"狗"经常和"养狗""狗粮""狗爪""可爱"一起出现。
两者上下文高度重叠 → 意思相近。
"量子力学"的上下文是"波函数""叠加态""薛定谔"——和"猫"几乎不重叠。
训练
神经网络从数十亿条文字里学这个关系
Embedding 模型是一个神经网络,在数十亿条文本上训练。

训练任务的本质是:"给你一段话,预测哪些段话和它相关。"

通过反复调整参数,让相关文本的向量越来越近,不相关的越来越远。 训练完成后固定下来——你喂给它一段文字,它输出 1024 维的语义指纹。
图示:文本输入 → Embedding 模型 → 语义向量输出
"猫很可爱" 任意文字输入 Embedding Model BGE-M3 / text-emb-3 数十亿文本训练而成 1024维 / 1536维 压缩 输出向量 (1024维) [ 0.023, -0.018, 0.045, 0.012, 0.031, -0.009, ... 共1024个 ] 固定长度的语义指纹
05 这是谁发明的,怎么想到的 170 年的接力:数学 → 语言学 → AI

向量表示语义,不是一个人想到的,是三个时代接力的结果。

1843
哈密顿(Hamilton)· 爱尔兰数学家
研究怎么用数字描述三维空间中的旋转,发展出"向量"的数学概念。 之后格拉斯曼系统化,吉布斯和亥维赛变成了今天物理课本里的样子。

这时候向量只是"描述空间方向和长度的工具",跟语言没有任何关系。
1954
Zellig Harris · 美国语言学家
提出"分布式语义假设":"一个词的意思,由它经常出现的上下文决定。"

这是纯语言学假设,不是技术。但它埋下了几十年后所有词向量技术的种子。 没有这个假设,就没有后面的一切。
2013 ★
Tomas Mikolov · 谷歌研究员 · 真正的转折点
发表论文,提出 Word2Vec

他用神经网络训练一个任务:"给你一个词,预测它周围会出现什么词"。 训练完之后,他没有关注输出,而是提取网络内部学到的参数—— 发现这些参数本身就是高质量的语义向量。

他展示了一个震惊所有人的例子:
国王 男人 + 女人 = 皇后 向量做加减法,结果在语义上完全正确。
这说明向量真的学到了语义关系,不是随机数字。整个 AI 学界都傻了。
2018+
BERT / GPT 时代 → 句子级 Embedding
Word2Vec 只能给单个词生成向量。BERT 等模型开始生成整句话、整段文章的向量, 同一个词在不同语境里有不同的向量("苹果手机"里的"苹果"和"苹果树"里的不一样)。

RAG 用的 BGE-M3、text-embedding-3,就是这条路走到今天的结果。
一句话总结:
数学家发明了向量来描述空间(1843)
→ 语言学家发现意思可以由上下文定义(1954)
→ Mikolov 用神经网络把两件事合在一起,"国王−男人+女人=皇后"(2013)
→ 今天的 Embedding 模型继承了这一切
06 1024 维能装多少词,维度能无限大吗 容量不是问题,三堵墙才是
容量
1024 维的空间,远比你想象的大
这个问题其实问反了——不是"能装多少词",而是"空间够不够用"。

类比:地球表面用经度和纬度两个维度就能定位任意一个点。 全球 80 亿人每人一个独立地址,两维就装得下,绰绰有余。 不是因为地球只有 80 亿个格子,而是坐标是连续的,理论上有无限个位置。

1024 维浮点数空间,能放下的不同位置数量,比宇宙里所有原子数量还大几百个数量级。

装下人类所有语言的所有词和句子,绰绰有余。
真正决定质量的不是维度够不够大,而是训练数据够不够多—— 语义相近的内容有没有被放到真正相近的位置上。
BGE-M3 用 1024 维,在中文场景里经常比 text-embedding-3-large(3072维)还好。
维度多不代表理解力强。瓶颈永远是训练质量,不是空间大小。

那维度能无限加吗?不能。有三堵墙:

第一堵墙
维度诅咒
数学上已经证明的现象:维度越高,"近"和"远"的区别越模糊。

在二维平面,邻居和远邻差别明显。但维度极高时,所有点之间的距离趋向相等—— 没什么东西明显更近或更远,"最相似"和"完全无关"越来越难区分。

就像站在超大房间的任意角落,到其他所有角落距离都差不多,"邻居"这个概念失去意义。
第二堵墙
数据不够填满
维度越高,需要的训练样本越多才能有效覆盖整个空间。

1 亿条训练语料,能有效填满的语义空间大概只需要几百到几千维。 再加维度,大量空间没有样本覆盖,模型不知道那些方向该放什么—— 等于浪费,反而引入噪声。
第三堵墙
成本线性增长
每次检索都要算余弦相似度。1024 维算一次,3072 维要贵 3 倍。

如果有 1000 万个文档,每次查询和它们全部算一遍—— 维度翻 3 倍,系统慢 3 倍,存储费用翻 3 倍。

成本是工程现实,不能无视。
维度三问 · 总结
问:每个维度代表什么特征? 答:没有名字,不可读。1024个数字整体才有意义。 如同 RGB 三个数字整体决定颜色,单个数字单独没意义。 问:1024维能装多少词? 答:问反了。空间容量远超需求。瓶颈是训练质量,不是空间大小。 问:维度可以无限大吗? 答:不行。三堵墙:维度诅咒(太高近远难分)、 数据不够填满(浪费引入噪声)、成本线性增长
07 为什么用余弦相似度,不用欧氏距离 文本长度 ≠ 语义差异
两种方式
各自在量什么
欧氏距离:两点之间的直线距离。量的是"你们离得多远"。

余弦相似度:两向量夹角的余弦值。完全不看距离,只看角度——"你们指的方向有多接近"。
夹角 0° → cos=1(完全相同方向);夹角 90° → cos=0(垂直,无关)。
问题
文本长度会影响向量模长,但不影响语义
"猫很可爱"(4个字)和"猫咪非常可爱,毛茸茸,爱睡觉,还会捉老鼠"(20个字), 语义几乎一样——都在说猫很可爱。

但后者文字多,模型处理了更多 token,输出向量的模长(长度)更大

如果用欧氏距离,这两句话"距离"会很大,尽管语义几乎相同。 两篇主题完全不同但都很短的文章,欧氏距离反而可能更小——这不是我们要的。
❌ 欧氏距离
公式:√Σ(aᵢ − bᵢ)²
量的是:两点间的直线距离

问题:文本越长 → 向量模长越大 → 欧氏距离越大
即使语义完全相同也一样。

一篇长文和一句短话说同一件事, 欧氏距离会"误判"为差距很大。
✅ 余弦相似度
公式:(A·B) / (|A| × |B|)
量的是:两向量方向的夹角

关键:分母 |A|×|B| 消除了模长影响。 不管文本长短,只要主题相同, 余弦相似度就会接近 1。

直觉:两人指向同一方向, 不管走了多远,夹角为零。
完整逻辑链 · 从零到余弦
01 计算机只处理数字,无法直接比较文字意思(手机只记号码,不认识张三) ↓ 需要把"意思"转化成数字 02 向量是"带方向的数字",方向相近 = 语义相近(食物坐标系) ↓ 普通编号不能反映语义关系 03 1024维向量没有每个维度的名字,是整体决定语义(类比 RGB 颜色) ↓ 神经网络训练学会这种表示 04 分布式假设(1954) + Word2Vec(2013) = 现代 Embedding 技术的根基 ↓ 维度太高会遇到维度诅咒 + 数据 + 成本三堵墙 05 "比较语义" = "比较向量方向",但欧氏距离被文本长度干扰 ↓ 余弦相似度的分母消除了模长影响,只看方向 ✓ 余弦相似度是 RAG 语义检索的正确工具
08 国内模型选型与快速接入 不依赖 OpenAI 的完整方案
推荐方案(最省事):硅基流动(SiliconFlow)
一个 key 同时提供 BGE-M3 embedding + Qwen chat,OpenAI 协议兼容,只改 base_url。有免费额度。
提供商Embedding 模型Chat 模型协议费用适用
硅基流动 ★BAAI/bge-m3 (1024维)Qwen2.5-7BOpenAI兼容有免费额度课程首选
智谱 AIembedding-3 (2048维)GLM-4-Flash原生SDKFlash免费中文强
通义千问text-embedding-v3Qwen-PlusOpenAI兼容按量计费企业稳定
DeepSeek❌ 无embeddingDeepSeek-ChatOpenAI兼容极低价格配合硅基流动
快速接入(硅基流动 · 5 分钟跑通)
# 1. 安装
pip install openai numpy

# 2. 注册并获取 key:https://siliconflow.cn
export SILICONFLOW_API_KEY="sf-xxx"

# 3. 修改 code/00_配置提供商_先改这个.py
PROVIDER = "siliconflow"

# 4. 验证连通性
python code/00_配置提供商_先改这个.py

# 5. 运行课程代码(无需其他改动)
python code/01_v1_最小RAG循环.py
读完这一页后
你现在应该会
解释为什么语义检索需要 embedding,为什么相似度通常用余弦而不是欧氏距离。
马上做的实验
运行 `code/01_v1_最小RAG循环.py`,观察 query 和文档的相似度排序。