大型语言模型(LLM)的输入并非原始文本,而是一串数字 ID。将人类语言转化为机器可理解的数字序列,这一过程由分词器(Tokenizer)和数据取样技术共同完成。本文基于你的代码结构,详细讲解从基础分词到现代 LLM 的 BPE 与滑动窗口采样机制,并配上可运行的代码示例。


一、从基础到 BPE:分词器的演进

1. 传统基础分词器的实现与局限性

你实现的 SimpleTokenizeV2 本质是:

  • 使用正则表达式将文本按词与标点切开;

  • 构建词汇表;

  • 再把词映射成 ID。

示例(假设的词表):

# 假设词汇表
# vocab = {
#   "Hello": 10, "do": 11, "like": 12, "tea": 13, "...": 14,
#   "<|endoftext|>": 1000, "<|unk|>": 1001
# }

text_oov = "Hello, do you like tea? SomeunknownPlace"
ids_oov = tokenizer.encode(text_oov)

print(ids_oov)
# 输出示例: [10, 11, 12, 13, 14, 1001]
# 'SomeunknownPlace' 变成 <|unk|>

问题在于:

  • 新词(OOV)直接变成 <unk>,语义丢失

  • 随文章增长,词表会爆炸增长,训练与存储成本失控。

这些都说明:传统词汇级 Tokenizer 生态位有限,难以支撑 LLM。


2. BPE 的崛起:LLM 默认武器

BPE(Byte Pair Encoding)以“子词”为策略,给 LLM 带来真实的增长曲线优势:

  • 任意新词可被拆成已有子词 → <unk>

  • 词表更可控,从几十万个词收缩到五万级别。

  • UTF-8 字节级兼容 → 能处理任何语言符号。

使用 tiktoken(OpenAI 官方 BPE)示例:

import tiktoken

bpe = tiktoken.get_encoding("gpt2")

text = "Hello, do you like tea? SomeunknownPlace"
ids = bpe.encode(text)

print("BPE IDs:", ids)
print("解码结果:", bpe.decode(ids))

真实输出类似:

BPE IDs: [15496, 11, 481, 345, 781, 1481, 13, 30, 874, 2619, 8722, 14250]
解码结果: Hello, do you like tea? SomeunknownPlace

可见:

  • SomeunknownPlace 被拆成多个已知的子词。

  • 信息零损失保留。

  • 模型能理解子词结构(Some / unknown / Place)。

这就是 GPT 系列稳定且鲁棒的底层关键。


二、超长文本与滑动窗口采样

即使分词之后,你仍会遇到一个老大难:

模型的最大上下文限制(如 1024 / 2048 / 4096)

而原始文本常常有几万、几十万 Token。

解决方案就是:滑动窗口采样(Sliding Window Sampling)


1. 概念说明

假设:

  • Token 序列长度为 len(S)

  • 模型能接受的最大长度为 W

  • 窗口步长为 K(一般 K < W

则第 i 个样本为:

[
sample_i = S[iK : iK + W]
]

采用重叠窗口(overlap),能让模型在学习时保持上下文连续性。


2. 可执行代码示例

import torch

# 生成一个长度 50 的 token 序列
S = torch.arange(50)

W = 10  # 窗口大小
K = 6   # 步长

print(f"原始序列 S: {S}")
print(f"窗口 W={W}, 步长 K={K},重叠长度={W-K}")

samples = []

for i in range(0, len(S) - W + 1, K):
    sample = S[i : i + W]
    samples.append(sample)

for idx, sample in enumerate(samples):
    print(f"样本 {idx}: {sample.tolist()}")

输出:

窗口 W=10, 步长 K=6,重叠长度=4

样本 0: [0,1,2,3,4,5,6,7,8,9]
样本 1: [6,7,8,9,10,11,12,13,14,15]
样本 2: [12,13,14,15,16,17,18,19,20,21]
...

业务价值非常明确:

  • 重叠(overlap)让模型学习到跨窗口的“语义桥”;

  • 长文本得以拆分成可训练块,但又不丢失语义连贯性;

  • 在训练 Transformer 时尤其关键。


三、总结

LLM 文本处理本质由两个核心机制驱动:

阶段 工具 作用 解决问题
编码层 BPE / tiktoken 文本 → Token IDs 解决 OOV、词表爆炸、跨语言兼容
结构化样本层 滑动窗口采样 生成训练样本 解决上下文限制、保持长文本连贯性

这两件事打通后,你就具备了构建任意 LLM 数据处理流水线的底层能力。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐