在 AI 和大语言模型(LLM)的领域,常常听过类似的声音:“我们需要一个向量数据库”、“把这些文档做成 Embedding(嵌入/向量化)”。
这个“向量”简直无处不在,它就像是 AI 的灵魂桥梁,连接着人类的自然语言与计算机的数字编码。
那么,向量究竟是什么?大模型和 AI Agent 是怎么利用它的?不同模型之间的向量有什么区别? 本文将带你用最通俗易懂的语言,从零搞懂大模型向量的秘密。
要理解向量,可以从一个生活中的小例子开始。
假设你开了一家水果店,你想向顾客推荐水果。你可以根据两个特征来给水果打分:甜度 和 酸度。分值范围是 0 \sim 1
\rightarrow 甜度 0.8 ,酸度 0.2\rightarrow 甜度 0.1 , 酸度 0.9\rightarrow 甜度 0.95, 酸度 0.05如果我们将这些分数连起来,就得到了一个个数字列表:
[0.8, 0.2][0.1, 0.9][0.95, 0.05]这串数字,在数学上就是一个“二维向量”!
在这个二维空间里,甜度和酸度就是两个**“维度(Dimensions)”**。每一个水果,在这个空间里都有一个唯一的坐标。
大模型做的事情也是一模一样的,只不过它考虑的特征不是 2 个,而是成千上万个(比如 OpenAI 的 Embedding 模型有 1536 个维度,Llama-3 模型甚至有 4096 个维度)。大模型能为一段文字评估成千上万个维度,包括情感色彩、词性、主题、语境等,最终生成一串几千个数字组成的超长数组——这就是特征向量。
在数学和几何学中,向量最直观的解释是:有方向和长度的箭头。
(x, y) 中的一个点,或者从原点指向该点的一个箭头。(x, y, z) 中的一个箭头。当人类说“很高兴认识你”和“认识你我真开心”时,字面上的中文字符完全不同。但对于 AI 来说,这两句话被转化为高维向量后,它们的箭头方向几乎是指向同一个地方的。
在数学上,我们常用 余弦相似度(Cosine Similarity) 来衡量两个向量的相似程度。它计算的是两个箭头之间的夹角 \theta:
\text{Cosine Similarity} = \cos(\theta) = \frac{A \cdot B}{\|A\| \|B\|}
0^\circ 时(\cos(0^\circ) = 1),意味着方向完全相同,语义完全一致。90^\circ 时(\cos(90^\circ) = 0),意味着互相垂直,风马牛不相及。180^\circ 时(\cos(180^\circ) = -1),方向相反,意思完全相反。最著名的向量代数例子莫过于经典公式:
\text{国王 (King)} - \text{男人 (Man)} + \text{女人 (Woman)} \approx \text{女王 (Queen)}
如果我们将这些概念转化为大模型中的向量数据,可能会呈现如下情况:
国王 Vector: [ 0.25, 0.88, -0.12, 0.45 ]
男人 Vector: [ 0.22, 0.85, -0.78, 0.02 ]
女人 Vector: [ 0.18, -0.15, 0.75, 0.05 ]
女王 Vector: [ 0.21, -0.12, 1.39, 0.48 ]
当我们用 国王 的向量减去 男人 的向量,就“抽离”了性别中的男性属性(只剩下了“皇室统治者”的纯粹概念);接着加上 女人 向量的女性特征,得到的计算结果坐标就会和 女王 的真实高维坐标极度接近。这就是高维向量的魔力——语义是可以进行数学加减法的。
很多 AI 初学者容易把 Embedding 模型与像 GPT-4、Claude 或 Gemini 这样的大语言模型(LLM)混为一谈,认为同一个模型既能生成向量,又能思考回答。
实际上,它们是分工完全不同的两套模型:
| 模型类别 | 代表模型 | 核心优化目标 | 最终输出物 |
|---|---|---|---|
| 大语言模型 (LLM) | GPT-4o, Claude 3.5, Llama-3 | 预测下一个 Token (生成通顺、符合人类偏好的回答) | 自然语言文本 (Text) |
| Embedding 模型 | text-embedding-3-small, bge-large-zh | 学习将语义投影到高维坐标系 (使得语义越相近的文本,空间距离越近) | 高维浮点数数组 (Vector) |
Embedding 模型的训练机制通常采用 对比学习(Contrastive Learning)。它的训练目标非常纯粹:
将一段普通文本转化为向量的过程,被称为 Embedding(嵌入)。我们必须借助专门的 Embedding 模型 来完成它。
以下是一个使用 Python 调用 OpenAI API 获取文本向量的实际例子:
from openai import OpenAI
# 1. 初始化客户端
client = OpenAI(api_key="your-api-key-here")
text_content = "人工智能正在改变世界。"
# 2. 调用 Embedding 模型 (例如 text-embedding-3-small)
response = client.embeddings.create(
input=[text_content],
model="text-embedding-3-small"
)
# 3. 提取生成的向量数组
vector = response.data[0].embedding
print(f"向量的维度数: {len(vector)}")
print(f"向量的前 5 个数字: {vector[:5]}")
# 输出类似于: [-0.01254, 0.03451, -0.00789, 0.05612, -0.02341]
大模型技术栈里,向量在以下核心场景中发挥作用:
在大语言模型内部,你输入的所有字词在最开始就会被映射为向量。模型在理解上下文时,利用 注意力机制(Attention Mechanism) 将注意力分配给相关的单词,这在底层就是多个向量之间的矩阵乘法运算。
由于大模型有上下文长度限制且无法动态获取实时信息,AI Agent 常常采用 RAG 架构来充当大模型的“外接硬盘”。
RAG 分为三个解耦的阶段:
1. 提问 (Question) ──> Embedding 模型 ──> 提问向量
│
▼
2. 检索 (Retrieval) ──> 向量数据库检索 ──> Top-K 原始文本块 (Context)
│
▼
3. 生成 (Generation) ──> 拼接 Prompt ──> 大语言模型 (LLM) ──> 最终回答
新人易混淆误区:发给大模型的是什么?
很多人误以为,Agent 会把检索出来的“向量数据(一堆数字数组)”发给大模型。这是错误的!
向量在这里只扮演了语义搜索钥匙的角色。Agent 根据提问向量在数据库中匹配到最相似的向量后,会取出该向量关联的原始文本(如一段产品手册的文字)。
从 API 接口角度看,大模型当然可以接收一串数字文本。但这些数字并不处于模型自身训练出的语义空间中,因此模型无法像向量数据库那样直接利用它们进行语义匹配。
最终 Agent 发送给大模型(GPT-4、Claude 等)的,是合并了这段背景知识的纯自然语言文本(Prompt)。大模型的输入端只认识自然语言与 Token(即大模型把自然语言文本切碎后的基本字符/单词片段,包括普通文本 Token 和用于标记对话边界的结构化特殊 Token),它根本无法识别、也不接受纯浮点数数字组成的向量数组来作为语义输入。
追问:既然输入大模型的是 Token,那分词(Tokenization)是在 Agent 本地做,还是在大模型服务器上做?
答:最终的分词转换是在大模型 API 服务器上进行的。
当数据离开 Agent 时,它只是一个标准的 UTF-8 编码的自然语言字符串(通过 HTTP 以 JSON 报文发送)。大模型服务器接收到这个字符串后,在云端使用与其神经网络完全匹配的分词算法将其转化为 Token,并喂给底层的 GPU。
但为什么我们经常看到 Agent 代码里也会导入 Tokenizer(如 tiktoken)呢?
Agent 在本地运行 Tokenizer 并不是为了给大模型分担计算,而是为了:
关键词搜索:如果用户搜索“汽车”,数据库只会查找包含单词“汽车”的文档。如果文档写着“越野车”或“vehicle”,就会被漏掉。
语义搜索:在向量空间中,car、automobile 和 vehicle 的高维坐标和夹角非常接近。即使字面完全没有重复,向量数据库也能感知到它们是“同类事物”,从而精准匹配。
在生产环境中,纯向量搜索并不是万能的。比如,如果用户搜索一个特定的产品型号“iPhone 15 Pro Max”,因为在向量语义空间里所有 iPhone 型号的特征都极其相近,纯向量检索可能会错误地返回 iPhone 16 的文档。
因此,现代生产级 RAG 架构都会采用混合搜索(Hybrid Search):
\text{混合检索} = \text{传统关键词检索 (如 BM25)} + \text{向量语义检索 (Vector Search)}
利用关键词检索保证特定名词、型号、编码的“精确度”,利用向量检索保证整体意思的“泛化度”,两者结合,检索成功率能获得质的提升。
当我们通过向量数据库捞出了前 20 条相关文本(High Recall, 高召回率)后,这些结果的顺序不一定最符合大模型阅读偏好(Precision,精度一般)。
在将它们塞给大模型前,我们需要引入一个 重排序模型(Re-ranker)(如 Cohere Rerank、BGE-Reranker)。
Re-ranker 使用更昂贵但更强大的 Cross-Encoder 架构,把“问题”和“候选文档”拼在一起同时输入模型,对这 20 个文本进行高精度的相关性重新打分,筛选出最相关的 Top-3 文本送给大模型。
传统关系型数据库如果没有专门的向量索引,面对寻找高维向量相似度的需求,通常需要进行全表扫描(对每一行计算余弦相似度并排序),检索效率会随着数据规模增长迅速下降。
因此,向量数据库 应运而生。它们采用专门的 ANN(近似最近邻搜索)算法(如 HNSW、IVF 等),能在毫秒内从数亿个向量中找出最接近的那几个。
为什么叫“近似最近邻 (ANN)”而不是“绝对最近邻 (KNN)”?
为了追求毫秒级的极限检索速度,向量数据库通常不会把提问向量跟库里每一个向量都计算一次精确距离(这叫暴力搜索或 KNN)。
相反,它们通过特定的图结构(如 HNSW 的多层图导航)或聚类算法(如 IVF 的倒排索引分组)快速“逼近”最近邻居。因此,向量数据库返回的往往是近似最优解,而不是数学意义上绝对完全匹配的最近邻,但这在语义搜索中已足够准确。
很多人常误以为向量数据库只存,比如:
{
"Hello LLM": [0.1, 0.2, -0.8]
}
实际上通常存:
{
"id": "123",
"embedding": [0.81, 0.5, -0.1, -0.22],
"text": "OpenAI released GPT-4",
"metadata": {
"source": "news",
"author": "..."
}
}
一个典型的向量数据库记录(Document/Entity)通常由以下四部分组成:
{ "source": "news", "author": "Rick", "createdAt": "2025-10-02" })。在进行向量检索前,我们可以利用元数据进行传统精确过滤。常用的存储方案有:
Chroma, Faiss(适用于小型项目或本地 Agent 记忆)。Pinecone, Milvus, Qdrant(适用于大规模企业级生产)。pgvector(传统关系型数据库如果没有专门的向量索引,检索会随规模增长变慢。但对于支持 pgvector 的 PostgreSQL,可以通过创建 HNSW 或 IVF 索引实现高效向量检索,适合现有 Web 应用升级)。切勿直接混合存储与检索!
不同 Embedding 模型生成的向量通常处于不同的语义空间(Embedding Space),因此不应直接混合存储或直接计算相似度。
虽然在学术界和某些特定高阶工程中,可以通过**向量空间对齐(Vector Space Alignment)**算法,或使用 Cross-Encoder 重排序模型、多语言统一 Embedding 模型进行跨模型关联,但在普通开发实践中,这种混用会导致语义计算彻底错乱,检索精度降为零。
例如:
text-embedding-3-small,输出 1536 维向量。其第 1 个维度可能代表“情感色彩中的喜悦程度”。512 维向量。其第 1 个维度可能代表“名词的单复数性质”。如果你把用 模型 A 向量化后的知识库数据扔给使用 模型 B 提取向量的检索器去查询,结果无异于“鸡同鸭讲”,余弦相似度计算出来会是一团乱码。项目一旦确定了 Embedding 模型,库内存储的向量就必须全部保持该模型的一致性。
关于维度:单个维度代表人能看懂的概念吗?
⚠️ 上述「第 1 个维度可能代表“情感色彩中的喜悦程度”」只是一种让你便于理解而给的直观的例子
实际上,现代大模型 Embedding 中单个维度通常并不具有明确的可解释意义。并不是“第 1 维代表喜悦程度、第 2 维代表性别”。
相反,每个概念的语义特征是由成百上千个维度共同编码、分散表示的,这在深度学习中被称为分布式表示(Distributed Representation)。因此,不同模型之间的各个维度权重含义是天差地别的。
此外,向量维度越高越好吗? 维度过高会消耗成倍的内存空间与磁盘 I/O,并降低数据库检索速度,甚至引发“维度灾难”。在实际工程中,很多只有 384 维度的精悍模型在垂直领域的效果,往往可以匹配或超越通用大厂的 1536 维度模型。因此适合场景才是最好的,并非维度越高越好。
在把长篇文章转换成向量前,不能直接把几万字一次性喂给 Embedding 模型(模型通常有单次输入长度限制)。我们通常需要对其进行切片(Chunking)。
但在切片时,如果直接粗暴切开,可能导致完整的意思被“拦腰截断”。因此,我们通常会设置一个重叠区间(Overlap)。
假设我们有如下的长句子:
“大模型能够处理长文本,但是生成向量时依然需要合理分块。为了防止信息在切片边缘断裂,我们会设计重叠区间。”
如果我们设置 分块大小(Chunk Size)为 24 个字,重叠大小(Overlap)为 8 个字。
什么是“重叠 8 个字”?
它指相邻两个分块之间有 8 个字是完全相同(重合)的。也就是说,前一个分块的最后 8 个字,会原封不动地出现在后一个分块的开头 8 个字。
通过滑动窗口切分后,得到的三个分块如下:
大模型能够处理长文本,但是生成向量时依然需要合理 (共 24 字)
末尾 8 个字是:量时依然需要合理【量时依然需要合理】分块。为了防止信息在切片边缘断裂 (共 24 字,开头 8 字与第一块重叠)
末尾 8 个字是:息在切片边缘断裂【息在切片边缘断裂】,我们会设计重叠区间。 (共 19 字,开头 8 字与第二块重叠)通过这种方式,原本可能会在切片交界处被拦腰切断的信息,在相邻的分块中都得到了完整保留,避免了因为句子被强行切断而导致向量化后语义丢失的问题。
除了机械地按字数或 Token 数切片外,现代 AI Agent 架构中越来越流行语义分块(Semantic Chunking)。 它利用自然语言处理算法(如分析相邻句子的余弦相似度突变),识别出文章中的标题、段落、章节或语义发生突变转折的边界。它让切片本身天然契合文章的内在逻辑结构,从而让每个向量分块都代表一个独立、完整的思想,大幅度提升了 RAG 检索的关联准确度。
马特廖什卡嵌入 (Matryoshka Representation Learning, MRL)
近期(如 OpenAI 的最新接口)支持了一种叫做套娃嵌入 (Matryoshka) 的技术。它允许你直接把原本 1536 维度的向量“截断”保留前 256 维。令人惊叹的是,由于特殊的训练方式,被截断后的 256 维向量依然保留了几乎所有的关键语义特征,但占用的存储空间和检索耗时却降低了数倍,是非常好用的工程调优手段。
在传统的机器学习和向量检索系统中,使用单一维度(如 768 维或 1536 维)会带来部署困境:
MRL 的突破:
No comments yet. Be the first!