LLM 分词与向量化:大模型是如何"读懂"文字的?——Tokenization × Embedding 原理与实战

6 阅读9分钟

LLM 分词与向量化:大模型是如何"读懂"文字的?——Tokenization × Embedding 原理与实战

本文深入解析 LLM 的两大底层机制:Tokenization(分词)与 Embedding(向量化)。从为什么必须分词,到 js-tiktoken 的编码解码实战,再到阿里百炼 Embedding API 调用与余弦相似度计算——彻底搞懂大模型"读懂"文本的背后原理。


前言

我们每天都在和 LLM 对话,但有没有想过这样一个问题:

神经网络只能处理数字(向量、矩阵),看不懂中文、英文等字符——那大模型是怎么"读懂"你输入的 Prompt 的?

答案藏在两个关键步骤中:

  1. 分词(Tokenization):将文本切割为 Token ID(一串数字)
  2. 嵌入(Embedding):将 Token ID 映射为高维向量(数字语义)

本文将带你深入理解这两大底层机制,并用代码动手实践。


一、LLM 处理文本的完整流水线

1.1 从输入到输出的四个步骤

Prompt(文本输入)
    │
    ▼
① Tokenizer(分词器)
   └── 文本 → Token IDs(一串数字)
    │
    ▼
② Embedding(嵌入层)
   └── Token IDs → 高维向量(语义数字表达)
    │
    ▼
③ Transformer(核心计算)
   └── Attention → MLP → 推理
    │
    ▼
④ Decoder(解码器)
   └── 输出 Token IDs → 文本
    │
    ▼
回答(文本输出)

1.2 为什么必须分词?

计算机底层只能处理 01

字符 'A' → ASCII 编码 → 65(一个数字)
字符 '吃' → Unicode 编码 → 21505(一个数字)

问题:
  - 把一整段文本"映射"为一个数字?→ 信息量太大,无法表达语义关系
  - 把每个字符"映射"为一个数字?→ 太过细碎,单字符无语义

解决方案:
  → 切成 token(比字符大、比句子小、语义相关的最小单位)

💡 核心洞察:Token 不能切成字符(太细碎,无意义),也不能不切(一段文本无法整体编码)。Token 是"语义相关的最小单位"——它介于字符和单词之间。


二、Tokenization(分词):文本到数字的第一次转换

2.1 Token 是什么?

Token 是大模型计价和处理的最小单位。

文本类型1 个字符 ≈示例Token 数
英文0.3 个 token"Hello"~1 token
中文0.6 个 token"你好"~1.2 tokens
特殊符号视编码而定"👋"1~2 tokens

定价参考:百万 Token 约几元人民币(不同模型价格不同)。

2.2 分词过程图解

输入文本: "Hello, 世界!"

分词器编码(encode):
  → Token IDs: [15496, 11, 91387, 235, 120]
                     ↑     ↑  ↑     ↑    ↑
                    Hello  ,  世   界   !

解码(decode):
  [15496, 11, 91387, 235, 120] → "Hello, 世界!"

⚠️ 注意事项:Token 不等于单词。中文一个字可能占 0.6 个 token,英文一个完整单词一般 1 个 token。实际分词结果取决于分词器使用的编码规则(如 cl100k_base)。

2.3 实战:js-tiktoken 编码解码

// index.mjs
import { getEncoding } from 'js-tiktoken';

// GPT-4 官方分词器:cl100k_base
const enc = getEncoding('cl100k_base');

// 原始文本
const text = "Hello, tiktoken! 你好,世界!";

// 编码:文本 → Token IDs
const tokens = enc.encode(text);
console.log("Token IDs:", tokens);
// 输出示例:[15496, 11, 125262, 0, ...]
console.log("Token 数量:", tokens.length);

// 解码:Token IDs → 文本(无损还原)
const decodedText = enc.decode(tokens);
console.log("解码文本:", decodedText);
// 输出:"Hello, tiktoken! 你好,世界!"

执行流程

文本 → cl100k_base 映射规则 → Token ID
  ↑                               ↑
  不一定是单词,而一定是 Token   每个 ID 对应 100k+ 词汇表中的一个

2.4 为什么 Token 数量影响费用?

输入:用户的 Prompt → 编码为 Token IDs → 计算消耗
输出:模型生成的回答 → 编码为 Token IDs → 计算消耗
                               ↓
                总 Token 数 = 输入 Token + 输出 Token
                费用 = 总 Token 数 × 单价

三、Embedding(嵌入):从数字 ID 到语义向量

3.1 Token ID 的局限

Token ID: 15496"Hello"

问题:
  1549615497 之间没有语义关系
  "Hello""Hi" 的 Token ID 可能相差很远
  数字大小不代表语义远近

Token ID 只是字典中的序号,不包含任何语义信息。

3.2 Embedding 的作用

Embedding 将 Token ID 映射为高维空间中的向量,让语义相近的词在空间中距离更近。

Token ID 空间:                  Embedding 向量空间:
┌──────────┐                  ┌──────────────────────┐
│ 15496 →  │                  │  [0.12, -0.35, ...]  │
│ "Hello"  │                  │   ↑ 语义相近的词      │
│          │                  │   │ 向量"距离"近      │
│ 16492 →  │    Embedding     │  [0.11, -0.33, ...]  │
│ "Hi"     │ ──────────────→  │   "Hi"               │
│          │                  │                      │
│ 91387 →  │                  │  [0.87, 0.22, ...]   │
│ "世界"   │                  │   语义不同 → 向量远  │
└──────────┘                  └──────────────────────┘

3.3 Embedding 的核心特性

特性说明意义
语义相似相似词 → 相近向量找到"意思相近"的内容
维度高1024~4096 维容纳足够的语义信息
数值范围[-1, 1]方便计算相似度
连续空间非离散值可进行算术运算

💡 经典案例vector("国王") - vector("男人") + vector("女人") ≈ vector("女王") — 向量空间允许语义算术。

3.4 实战:阿里百炼 Embedding API

// main.mjs
import OpenAI from 'openai';
import dotenv from 'dotenv';
dotenv.config();

const client = new OpenAI({
  apiKey: process.env.DASHSCOPE_API_KEY,
  baseURL: 'https://dashscope.aliyuncs.com/compatible-mode/v1'
});

/**
 * 获取文本的 Embedding 向量
 * @param {string} text - 输入文本
 * @returns {number[]} - 1024 维向量
 */
async function getEmbedding(text) {
  const res = await client.embeddings.create({
    model: 'text-embedding-v4',  // 阿里百炼嵌入模型
    input: text,
    dimensions: 1024             // 指定向量维度
  });

  return res.data[0].embedding;
}

向量是什么?

// 一个 1024 维的向量示例(截取前 5 维)
const embedding = [0.015, -0.023, 0.087, -0.001, 0.054, ...];
// 每一个数值代表文本在某个"语义维度"上的强度
// 1024 个维度共同构成文本的语义指纹

四、余弦相似度:计算语义距离

4.1 数学原理

两个文本的相似度 = 它们的 Embedding 向量之间的余弦值

cos(θ) = (A · B) / (|A| × |B|)

A · B    = 点积(对应位置相乘再相加)
|A|      = 向量 A 的模长
|B|      = 向量 B 的模长

4.2 JavaScript 实现

function cosineSimilarity(vecA, vecB) {
  let dot = 0;      // 点积
  let magA = 0;     // 向量 A 模长平方
  let magB = 0;     // 向量 B 模长平方

  for (let i = 0; i < vecA.length; i++) {
    dot += vecA[i] * vecB[i];      // 对应位置相乘累加
    magA += vecA[i] ** 2;          // 平方累加
    magB += vecB[i] ** 2;
  }

  return dot / (Math.sqrt(magA) * Math.sqrt(magB));
}

4.3 完整语义相似度对比

async function run() {
  // 准备三段文本
  const text1 = "Andrej Karpathy LLM Tokenization 分词原理";
  const text2 = "卡帕西讲解大模型BPE字词分词";
  const text3 = "今天天气晴朗,适合出门散步";

  // 获取 Embedding 向量(1024 维)
  const vec1 = await getEmbedding(text1);
  const vec2 = await getEmbedding(text2);
  const vec3 = await getEmbedding(text3);

  // 计算余弦相似度
  console.log("text1 vs text2:", cosineSimilarity(vec1, vec2));
  // ↑ 语义相关(都是 LLM 分词),输出 ≈ 0.7~0.8

  console.log("text1 vs text3:", cosineSimilarity(vec1, vec3));
  // ↑ 语义无关(分词 vs 天气),输出 ≈ 0.1~0.2
}

结果解读

text1: "Andrej Karpathy LLM Tokenization 分词原理"
text2: "卡帕西讲解大模型BPE字词分词"

余弦相似度 ≈ 0.75
→ 语义相近!都讲 LLM 分词

text1: "Andrej Karpathy LLM Tokenization 分词原理"
text3: "今天天气晴朗,适合出门散步"

余弦相似度 ≈ 0.15
→ 语义无关,话题完全不同

五、Embedding 的典型应用

5.1 语义搜索

用户搜索:"大模型是怎么分词的?"

传统搜索:匹配关键词
  ❌ 没有"分词"二字 → 搜不到

语义搜索(基于 Embedding):
  ✅ "Tokenization"的向量与"分词"的向量相近 → 能搜到

5.2 知识库 RAG

用户提问 → Embedding 向量化
    │
    ▼
向量数据库检索(余弦相似度)
    │
    ▼
找到最相关的 Top N 知识片段
    │
    ▼
注入 LLM 上下文 → 生成回答

5.3 文本聚类

10000 条用户评论 → 每条 Embedding 向量化
    │
    ▼
K-Means 聚类
    │
    ▼
发现 5 大类主题:
  ├── 产品质量
  ├── 配送速度
  ├── 客服态度
  ├── 价格优惠
  └── 使用体验

六、LLM 学习建议

6.1 学习路径

第一步:搞懂 AI 是什么
  ├── 吴恩达 AI for Everyone(入门)
  ├── Karpathy 3小时大模型入门视频(原理)
  └── https://www.bilibili.com/video/BV16cNEeXEer/

第二步:动手用起来
  ├── Claude Code / Codex:日常编码
  ├── NotebookLMRAG 实践
  └── Obsidian:第二大脑

第三步:做个人作品
  ├── Vibe Coding:从想法到应用
  └── Agent 开发:真正的自动化

第四步:持续关注
  ├── 晓辉博士(专业深度)
  ├── 42章经(行业洞察)
  ├── 宝玉AIPrompt Engineering)
  └── 归藏(AI 产品)

6.2 需要了解的底层概念

概念说明难度
Tokenization分词,本文已讲★☆☆
Embedding向量化,本文已讲★☆☆
Attention注意力机制★★☆
Transformer整体架构(Google 提出)★★★
Fine-tuning微调★★☆

七、知识图谱

LLM 分词与向量化
├── LLM 处理流水线
│   ├── Tokenizer(分词)
│   ├── Embedding(嵌入)
│   ├── Transformer(计算)
│   └── Decoder(解码输出)
├── Tokenization 分词
│   ├── 为什么必须分词?
│   ├── Token 的概念
│   ├── Token 定价(中英文差异)
│   └── js-tiktoken 实战
│       ├── encode:文本 → Token IDs
│       └── decode:Token IDs → 文本
├── Embedding 嵌入
│   ├── Token ID 的局限
│   ├── Embedding 的作用(语义向量化)
│   ├── 核心特性(高维/连续/语义相似)
│   └── 阿里百炼 Embedding API
│       ├── text-embedding-v4 模型
│       └── 1024 维向量
├── 余弦相似度
│   ├── 数学原理(cos θ)
│   ├── JavaScript 实现
│   └── 语义相似度对比
└── 应用场景
    ├── 语义搜索
    ├── RAG 知识库
    └── 文本聚类

八、总结

本文深入解析了 LLM 的两大底层机制:

  1. Tokenization 是将文本切割为 Token ID 的过程。计算机看不懂文字,只能处理数字。Token 是介于字符和单词之间的语义最小单位。
  2. Embedding 是将 Token ID 映射为高维向量的过程。Token ID 只是字典序号,不包含语义;Embedding 向量让语义相近的词在空间中距离更近。
  3. js-tiktoken 是 OpenAI 官方的分词库,支持 cl100k_base(GPT-4 编码器),可完成 encode/decode 操作。
  4. 阿里百炼 Embedding API 提供了 text-embedding-v4 模型,支持指定维度(如 1024),将文本向量化。
  5. 余弦相似度 是衡量两个向量方向的指标,在语义搜索、RAG、文本聚类等场景中广泛应用。
  6. LLM 学习路径应遵循"先理解原理,再动手使用,最后做个人作品"的渐进式路线。

🚀 学习建议:一定要亲手跑一遍 js-tiktoken 的 encode/decode,以及 Embedding API 的余弦相似度计算。理解"文本 → Token ID → 向量 → 语义"这条完整链路,才能真正理解大模型的工作原理。


参考资源


📌 标签:#LLM #Tokenization #Embedding #分词 #向量化 #余弦相似度 #大模型 #js-tiktoken

💬 互动:你在使用 LLM 时考虑过 Token 消耗吗?有没有试过用 Embedding 做语义搜索?欢迎在评论区分享!