---
url: /basics/what-is-embedding.md
description: >-
  从文本到向量的完整链路讲起：维度是什么、为什么语义相近的向量夹角小、余弦相似度怎么算，并说清它为什么比关键词匹配强又不完全可靠，附常见模型维度与批量调用实践。
---

# Embedding 到底在做什么：从文本到向量

做搜索、做 RAG、做推荐，都绕不开 embedding（嵌入）。对前端来说最容易糊的是：几行接口调用而已，为什么它比关键词匹配强，又为什么有时候烂得莫名其妙。这篇只讲三件事：它把文本变成什么、相似度怎么比、什么时候不管用。

## Embedding 本质：把文本压成一串数字

模型不认识字符串，只认数字。embedding 就是把一段文本送进模型，拿回一个定长数字数组：

```ts
// 示意代码：一次典型的 embedding 调用
const res = await fetch("/api/embeddings", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ model: "text-embedding-3-small", input: "首屏加载优化" }),
});
const json = await res.json();
console.log(json.data[0].embedding.length); // 1536
```

可以先把它理解成一把哈希：文本进、数字数组出。区别是哈希只保证「相同文本结果相同」，embedding 还保证「意思相近的文本，数组也相近」。这就是它能干活的全部原因。

## 维度是什么：向量的长度

维度（dimension）就是数组里数字的个数，决定一条向量占多少内存、算一次相似度花多少算力。

* 1536 维用 float32 存，一条约 6KB，十万条就是几百 MB。
* 维度越高表达力越强，存储和检索成本也跟着涨。
* 有些模型支持用 dimensions 参数把向量截短（如 text-embedding-3 系列），拿精度换成本。

## 语义相近，就是方向相近

把 1536 维想成 1536 个坐标轴，每个向量是空间里的一个箭头。

* 箭头长短受文本长度影响，没有语义意义。
* 方向才承载语义，比较前一般先归一化再看夹角。
* 夹角越小越像：接近 0 度几乎同义，接近 90 度基本无关。

## 余弦相似度：一段能用的实现

余弦相似度（cosine similarity）就是夹角余弦值，落在 -1 到 1 之间，越接近 1 越像：

```ts
// 示意代码：余弦相似度
function cosine(a: number[], b: number[]): number {
  let dot = 0, na = 0, nb = 0;
  for (let i = 0; i < a.length; i++) {
    dot += a[i] * b[i];
    na += a[i] * a[i];
    nb += b[i] * b[i];
  }
  return dot / (Math.sqrt(na) * Math.sqrt(nb));
}
```

入库时若已归一化，这段退化成一次点积，省掉开方，代价是浮点误差，判阈值留点余量。

## 为什么它比关键词匹配强

* 「怎么让首屏快一点」和「页面加载优化方案」没有一个共同关键词，向量夹角却很小；同义改写、语序变化、错别字、跨语言都能容忍，也不用维护同义词表。
* 关键词是精确的字符串运算，embedding 是模糊的语义近似，两者互补而非替代。

## 为什么它又不完全可靠

* 同义词被压成一个点：「便宜」和「廉价」几乎分不开。
* 否定词常被吃掉：「支持退款」和「不支持退款」的向量可能非常接近。
* 长文本只能压成一个点，整篇文档挤进一个向量，细节会被抹平。
* 它不做精确判断：订单号、价格区间这类条件，关键词或结构化过滤更靠谱。

::: warning
别把它当成万能相似度：它是语义近似，不是事实正确，否定词、数字、专有名词常被抹平，精确条件该交给关键词或数据库。同一批向量必须出自同一个模型，换模型或换版本，向量空间就对不上，检索结果会莫名其妙地烂。模型名、维度、价格都会变，别把抄来的数字硬编码进业务代码。
:::

## 常见模型与维度（以官方文档为准）

* text-embedding-3-small：默认 1536 维，官方标价 0.02 美元 / 百万 token，单条输入有 token 上限，量级约 8k。
* text-embedding-3-large：默认 3072 维，官方标价 0.13 美元 / 百万 token。
* BGE-M3：1024 维，覆盖上百种语言，最长 8192 token。
* bge-large-zh-v1.5：1024 维，中文场景常见的开源选择。

## 一次能拿多少条，怎么批量

* 接口的 input 能直接传字符串数组，一次带一批文本，返回顺序与输入一一对应。
* 单条长度、批次条数、整批总 token 都有上限，超了会报错或被截断。
* 常规做法：长文档先切块（chunk），几百条一批发出，并发控速，失败重试。
* 落库时把原文、切块位置、模型名、维度一起存，将来换模型才算有据可依。

## 四种场景里它分别怎么用

* RAG 问答：文档切块入向量库；提问时把问题也转向量，取最近几个块拼进 prompt。
* 搜索：向量召回管「意思对得上」，关键词召回管「字面精确」，两路合并排序就是混合检索。
* 聚类：对一批文本的向量跑聚类，自动发现用户反馈主题，省掉人工打标。
* 去重：两两算余弦相似度，超阈值判重复；量大时先用向量索引做近邻搜索，别全量硬比。
