大语言模型工作原理:从文本分词到高维向量计算的完整解析
1. 从“你好”到数字矩阵大语言模型如何“看懂”世界我们每天都在和ChatGPT、文心一言这样的AI助手对话感觉它们像人一样理解我们的问题。但你是否想过当你在对话框里输入“帮我写一首关于春天的诗”时这台机器究竟“看到”了什么它真的理解“春天”的温暖、“诗”的韵律吗答案可能出乎你的意料它看到的只是一串经过复杂编码的数字。今天我们就来彻底拆解这个魔法背后的工程逻辑看看一句简单的人话是如何被大语言模型LLM拆解、转换并最终“计算”出回应的。这个过程远比你想象的更工程化、更精妙也充满了工程师们为了解决实际问题而设计的各种巧思和“补丁”。理解这个过程不仅有助于你更理性地使用AI工具更能让你洞察当前AI能力的边界。你会发现所谓的“智能”其起点竟是一个如此机械的“分词”动作而让模型显得“博学”的则是将词语映射到高维空间中的某个点。这趟从文本分词到高维向量的计算之旅正是现代大语言模型所有能力的基石。无论你是开发者想深入了解模型原理还是普通用户好奇AI的运作机制这篇文章都将带你走完这段从“字符”到“智能”的完整路径。2. 旅程的起点文本分词Tokenization的工程艺术大语言模型处理文本的第一步不是理解而是“切分”。这个步骤叫做分词Tokenization它的目标是把人类可读的连续字符序列切割成模型能够处理的离散单元这些单元被称为“词元”Token。这听起来简单实则充满了权衡和设计哲学。2.1 为什么需要分词字符级处理的困境最朴素的想法是让模型直接处理每一个字符Character-level。比如“hello”就处理为[‘h‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘]。这样做词汇表极小英文就几十个但效率极低。模型需要从零学习“h”“e”“l”“l”“o”组合成“hello”的含义这需要海量的数据和计算。更重要的是它无法有效利用常见的子词或单词的统计信息学习成本太高。另一种极端是单词级Word-level分词即按空格切分每个单词作为一个Token。这对于英语似乎可行但问题立刻浮现词汇表爆炸“run“, “runs“, “running“会被视为三个完全不同的词、无法处理未登录词OOV 如“ChatGPT“、对形态丰富的语言如德语、土耳其语极其不友好。因此现代大语言模型普遍采用子词分词Subword Tokenization策略。它的核心思想是将频繁出现的连续字符序列作为一个整体Token而将不常见的词拆分成更小的、可重复使用的子词单元。这就像我们背单词时会识别“un-“否定、“-ing“进行时这样的前缀后缀一样。2.2 主流分词算法实战解析目前有两大主流的分词算法家族BPEByte-Pair Encoding和WordPiece/SentencePiece。它们思路相近但细节和适用场景有差异。2.2.1 Byte-Pair Encoding (BPE)从GPT到Llama的基石BPE算法非常直观它通过迭代合并最高频的字符对来构建词表。我们通过一个简化例子来看它的训练过程假设我们有初始词汇字符级[‘l‘, ‘o‘, ‘w‘, ‘e‘, ‘r‘, ‘l‘, ‘o‘, ‘w‘, ‘e‘, ‘s‘, ‘t‘]对应单词“lower lowest“。统计所有相邻字符对频率lo出现2次ow出现2次we出现1次等。合并最高频对比如lo-lo 词汇变为[‘lo‘, ‘w‘, ‘e‘, ‘r‘, ‘lo‘, ‘w‘, ‘e‘, ‘s‘, ‘t‘]。重复此过程直到达到预设的词表大小例如5万。接下来可能合并we然后是low等等。最终像“lower“这样的常见词可能会被合并成一个Tokenlower而“lowest“可能被分成low和est两个Token。OpenAI的GPT系列、Meta的Llama系列都使用基于BPE的分词器。它的优点是生成的词元相对规整容易理解。注意BPE有一个关键变体叫字节级BPEBBPE这是GPT系列使用的。它的初始单元不是Unicode字符而是256个字节。这使得BBPE理论上可以编码任何文本包括任何语言、任何符号甚至是图片的二进制数据彻底解决了OOV问题因为任何未知文本都能被分解回这256个字节。这是工程上一个非常巧妙的设计。2.2.2 WordPiece与SentencePieceBERT与T5的选择WordPiece用于BERT和SentencePiece用于T5 mT5与BPE类似但合并策略不同。BPE根据频率合并而WordPiece根据一个似然函数合并这个函数倾向于合并能最大程度增加语言模型概率的字符对。SentencePiece则更进一步它直接在原始字节流上操作无需预分词如按空格分因此对不带空格分隔的语言如中文、日文更加友好。对于中文分词逻辑有所不同。由于中文没有天然的分隔符常见的做法是将每个汉字作为一个独立的Token字级别或者使用分词工具先切分成词再进行子词划分。例如“人工智能”可能被直接当作一个Token也可能被拆成“人工”和“智能”两个Token这取决于它在训练语料中的出现频率。2.3 分词带来的实际挑战与应对技巧分词不是一个完美的过程它会直接引入一些模型行为的“怪癖”。2.3.1 计算效率与上下文长度的博弈Token是模型计算的基本单位。模型的上下文长度如4096、128K限制的是Token的数量而非字符数。一个复杂的英文单词可能被拆成多个Token一个中文字符通常就是一个Token。这意味着用中文提问你可能比用英文“塞”进更多实质内容。在计算资源尤其是GPU显存固定的情况下Token数直接决定了单次处理文本的成本。这也是为什么长文本生成或处理非常消耗资源的原因——每个新Token的生成都需要模型对整个当前的Token序列进行一遍完整的“思考”前向传播。2.3.2 分词不一致性提示工程的隐藏变量同一个概念不同的分词方式可能导致完全不同的Token序列。例如“ChatGPT”在有些分词器里是一个Token在另一些里可能是Chat和GPT两个Token。这会导致模型对同一输入的内部表示产生微妙差异进而影响输出。在提示工程中有时微调一下措辞比如用“AI assistant”代替“ChatGPT”就能得到更好结果背后可能就是因为触发了更“优质”的分词模式。实操心得当你发现模型对某个关键词反应不佳时可以尝试用它的同义词、缩写或展开形式替换这本质上是换了一组分词可能绕过了模型在训练时因分词而产生的某些薄弱关联。2.3.3 数字与格式的“陷阱”数字的分词尤其棘手。“123“可能被分成12和3两个Token这会让模型难以进行精确的数学运算因为“123”的数值概念在分词阶段就被破坏了。这也是为什么大语言模型普遍不擅长精确算术的根本原因之一。对于代码、数学公式特殊的分词器如CodeLlama使用的会进行特殊处理尽量保持数字和运算符的完整性。3. 从符号到空间词嵌入Embedding的魔法分词之后我们得到了一串Token ID每个Token在词表中的索引号比如[2301, 3928, 1823, ...]。但模型是无法直接计算这些整数的。下一步就是通过词嵌入层将这些离散的符号映射到连续的、稠密的高维向量空间。这一步是赋予模型“理解”能力的关键转换。3.1 词嵌入的核心思想万物皆可向量想象一个巨大的高维空间比如4096维、8192维这个空间的每一个点都对应一个Token。词嵌入层就是一个巨大的查找表Look-up Table其行数等于词表大小如5万列数等于嵌入维度如4096。当输入Token ID为2301时模型就从这个表的第2301行取出那个4096维的向量。这个向量不是随机的。在模型训练过程中这些向量的数值会被不断调整优化。优化的目标是在语义或语法上相似的Token它们对应的向量在高维空间中的距离通常用余弦相似度衡量应该更近。例如“猫”和“狗”的向量距离应该比“猫”和“汽车”的近“奔跑”和“跳跃”的向量距离应该比“奔跑”和“睡觉”的近。3.2 静态嵌入 vs. 上下文动态嵌入早期的Word2Vec、GloVe等技术产生的是静态词嵌入。一个词无论出现在什么句子中它的向量是固定的。“苹果”在“我吃苹果”和“苹果股价上涨”中拥有同一个向量这显然无法区分“水果”和“公司”的不同含义。大语言模型使用的是上下文动态嵌入。注意在Transformer架构中词嵌入层产出的初始向量是静态的即上面提到的查找表输出。但是这个初始向量会立刻送入模型的第一层Transformer Block。经过多层自注意力机制Self-Attention和全连接层的计算后每个Token的向量都会融合整个句子中所有其他Token的信息。最终输出的向量才是这个词在当前特定上下文中的真正表示。因此同一个Token“苹果”在不同的句子中经过模型深层处理后的最终向量是不同的它动态地编码了上下文信息。3.3 嵌入维度的秘密为什么是768/1024/4096嵌入维度是一个超参数。维度越高理论上能编码的信息就越丰富、越精细但同时也带来了更大的计算量和模型参数嵌入层参数 词表大小 × 嵌入维度。选择多少维是模型效果、训练成本和推理速度之间的权衡。较低维度如768 在BERT-base中常见足以捕获丰富的语义信息计算效率高。较高维度如4096/8192 在GPT-3、Llama 2/3等大型模型中使用。更高的维度允许模型学习更微妙、更复杂的语义和语法特征为后续的注意力机制提供更丰富的“素材”是模型能力强大的基础之一。你可以把它理解为给每个词分配了更长的“描述清单”清单上的每一项每一维可能对应某种抽象的语义属性如“是生物”、“有情感”、“是动词过去式”等但这些属性是人类难以直接解读的。4. 计算的心脏Transformer架构中的高维向量运算当每个Token都变成了一个高维向量后真正的“计算”就开始了。这一切发生在Transformer架构的内部。我们可以把Transformer模型想象成一个极其复杂的“向量加工厂”输入一串向量经过层层加工输出另一串向量每个位置对应下一个Token的预测概率。4.1 自注意力机制向量间的“社交网络”这是Transformer最核心的发明。自注意力机制让序列中的每一个Token向量都能“关注”序列中所有其他的Token向量包括它自己并根据相关性动态地聚合信息。计算过程分三步走生成Q, K, V 对于每个输入向量分别乘以三个不同的权重矩阵得到查询向量Query、键向量Key和值向量Value。这三个矩阵是模型要学习的参数。计算注意力分数 用当前Token的Q向量去点乘序列中所有Token的K向量。点乘的结果经过缩放代表了当前Token与其他Token的“相关度”。这个相关度经过Softmax函数归一化变成一组权重和为1。加权求和 用这组权重对所有的V向量进行加权求和。得到的结果就是当前Token经过“注意力”聚合了全局信息后的新向量。为什么有效在“The animal didn‘t cross the street because it was too tired”这个句子里“it”的向量通过注意力机制会赋予“animal”的V向量很高的权重从而知道“it”指的是“animal”而不是“street”。这个过程完全是向量计算的结果。多头注意力 模型不会只做一次上述计算而是并行地做多次例如32个“头”每个头有不同的Q、K、V权重矩阵。这相当于让模型从多个不同的“表示子空间”或“理解角度”去关注输入信息最后把多个头的结果拼接起来。这大大增强了模型的表征能力。4.2 前馈神经网络每个位置的独立“思考”经过注意力层后每个Token的向量已经包含了上下文信息。接下来这个向量会进入一个前馈神经网络FFN。这是一个简单的全连接网络通常包含一个放大维度如从4096放大到11008的激活层如Swish/GELU和一个缩小回原维度的线性层。它的作用是什么注意力机制负责“收集信息”而FFN负责“处理信息”。你可以把FFN看作每个Token在获得了全局信息后进行的独立、深度的“思考”和“转化”。它为模型提供了强大的非线性变换能力是学习复杂模式的关键。4.3 残差连接与层归一化训练深度网络的稳定器Transformer的每个子层注意力层、FFN层都包裹着残差连接和层归一化。残差连接 将子层的输入向量直接加到其输出向量上。即输出 层归一化(子层(输入) 输入)。这解决了深度神经网络中的梯度消失问题使得训练数十层、数百层的模型成为可能。层归一化 对单个样本的所有特征维度进行归一化使其均值为0方差为1。这稳定了每一层的输入分布加速了模型训练收敛。这两项技术虽然看似简单但却是Transformer能够堆叠得如此之深、训练得如此稳定的工程基石。5. 输出的临门一脚从向量回退到文字经过数十层Transformer Block的层层处理我们最终得到了序列中每个位置的一个高维输出向量例如最后一个Token位置的向量通常用于预测下一个词。但这个向量还不是文字。最后一步需要将它“解码”成人类可读的Token。5.1 语言模型头向量到词表的映射模型的最后一层是一个线性层通常被称为“语言模型头”。它的权重矩阵形状是[隐藏层维度, 词表大小]。我们将最后一个输出向量假设是4096维乘以这个矩阵就会得到一个长度为词表大小如5万的向量。这个向量中的每一个数值对应了词表中每一个Token作为“下一个词”的未归一化的得分logits。数值越高表示模型认为该Token出现的可能性越大。5.2 采样策略决定性的最后一步得到logits向量后我们并不是简单地选择分数最高的那个Token贪婪搜索。为了生成更有创造性、更自然的文本通常会采用一些采样策略Softmax 首先将logits通过Softmax函数转换为概率分布。这样每个Token都有一个0到1之间的概率所有Token概率之和为1。温度参数 在Softmax之前将logits除以一个温度系数T。T 1 标准Softmax。T 1如0.8 概率分布更“尖锐”高分者更高低分者更低输出更确定、更保守。T 1如1.2 概率分布更“平滑”输出更多样、更有创造性但也更可能出错。采样方法贪婪搜索 直接选概率最高的。简单但容易导致重复、枯燥的文本。核采样 只从概率最高的前k个Token中随机采样。在创造性和可控性之间取得平衡。顶-p采样 从累积概率超过p的最小Token集合中随机采样。比核采样更自适应。选中的Token ID被追加到输入序列的末尾然后整个序列包括这个新Token再次送入模型预测下一个Token如此循环往复直至生成完整回答或达到长度限制。6. 实战中的挑战与调优经验理解了整个流程我们就能更好地应对实际使用和开发中的问题。6.1 显存瓶颈长上下文与高维向量的代价大语言模型推理时显存占用主要来自两部分模型参数和激活值。模型参数如Llama 3 70B的140GB在加载后基本固定。而激活值即每一层计算过程中产生的中间向量会随着批次大小和序列长度线性增长。例如处理一个长度为4096的序列在每一层Transformer中都需要为这4096个Token存储其对应的Key和Value向量用于后续Token生成时的注意力计算。这就是为什么长文本生成如此耗费显存。当出现“CUDA out of memory”错误时除了换更大显存的GPU可以尝试减小批次大小。使用更高效的注意力算法如FlashAttention-2它能大幅降低显存占用并提升速度。对于超长文本考虑使用外推或流式处理技术。6.2 生成质量与速度的权衡生成文本时有几个关键参数影响效果max_new_tokens 生成的最大Token数。设得太小可能回答不完整太大则浪费资源。temperature 如上所述控制随机性。对于代码生成、事实问答建议较低温度0.1-0.3对于创意写作可以调高0.7-1.0。top_p / top_k 控制采样范围。top_p0.9,top_k50是常见的平衡设置。实操心得不要盲目追求“最像人”的随机性。对于需要确定性和准确性的任务如数据提取、指令跟随低温度贪婪或小范围采样往往效果更可靠。观察模型输出的logits分布如果最高概率的Token优势极其明显如0.9那么采样带来的差异不大如果前几个Token概率相近采样就会导致输出波动较大。6.3 分词不一致导致的诡异行为这是提示工程中常遇到的坑。例如让模型“重复单词‘Hello‘五次”它可能完美执行。但如果你让它“重复单词‘HelloHelloHelloHelloHello‘”由于这个长串可能被分词成奇怪的片段模型输出可能会出错。再比如在系统提示词中用不同的方式表述同一指令仅仅因为分词不同就可能导致模型对其“重视程度”产生差异。排查技巧当你对模型的输出感到困惑时一个有用的诊断步骤是将你的输入提示文本用该模型对应的分词器进行分词看看究竟被切成了什么样。许多开源库如Hugging Face的transformers都提供了方便的.tokenize()和.decode()方法。这能帮你确认是不是分词引入的噪声干扰了模型的理解。6.4 本地部署与计算资源规划本地部署大模型如使用Ollama、text-generation-webui已成为趋势。你需要清楚自己的需求模型规模 参数量7B, 13B, 70B直接决定了对显存的最低要求。70B模型通常需要2张以上高端消费级显卡如4090才能以可接受的速度运行。量化技术 这是让大模型在消费级硬件上运行的关键。将模型权重从FP16精度量化到INT8甚至INT4可以大幅减少显存占用和提升推理速度但会带来轻微的质量损失。选择哪个量化版本Q4_K_M, Q8_0等需要在质量和效率间取舍。上下文长度 长上下文模型如128K在处理长文档时优势明显但同样会显著增加激活值显存。确保你的硬件能支撑你常用的上下文长度。从你输入一段文字开始到大语言模型给出回应这背后是一场精密、复杂且规模浩大的高维向量计算之旅。它始于将文本机械地切分成Token通过嵌入层将其投射到充满语义关联的高维空间再经由Transformer的注意力机制进行全局信息交换和深度非线性变换最后通过一个简单的线性层映射回我们的词汇世界。这个过程里没有魔法只有数学和工程。理解它能让你拨开AI神秘的面纱看到其能力的来源与边界从而更高效、更精准地利用这项强大的工具。无论是调整一个温度参数还是设计一段更有效的提示词你的每一个微调都是在与这个庞大的向量计算系统进行对话。