大语言模型文本处理核心:分词与嵌入技术详解

📅 2026/8/12 20:35:11
大语言模型文本处理核心:分词与嵌入技术详解
1. 从“字”到“数”理解LLM处理文本的第一步当我们和ChatGPT、Claude或者任何一个大语言模型对话时输入一段文字它就能理解并生成回复。这个看似简单的过程背后第一步就是将我们熟悉的、由字符组成的文本转换成模型能够“计算”的数学形式。这个过程就是分词与嵌入。你可以把它想象成教一个只会做数学题矩阵运算的超级大脑去读一本小说。我们得先把小说拆成一个个有意义的“词块”分词然后给每个“词块”分配一个独一无二的、富含信息的“身份证号码”嵌入向量这样大脑才能开始它的工作。为什么这步如此关键因为模型的核心——Transformer架构——处理的不是字符而是向量。它通过计算向量之间的“注意力”来理解上下文关系。如果输入的“身份证号码”质量不高或者含义模糊模型的理解就会出偏差导致“答非所问”或“胡言乱语”。因此分词和嵌入的质量直接决定了模型“读懂”输入的上限。最近大家热议的RAG、Agent、微调等技术其效果好坏很大程度上都依赖于底层文本到向量的转换是否精准。一个糟糕的分词器可能会把专业术语切得支离破碎一个粗糙的嵌入模型可能无法区分“苹果”水果和“苹果”公司。所以无论你是想深入理解LLM原理还是希望优化自己的AI应用搞懂这一环都至关重要。2. 分词将连续文本切割成模型的“单词”分词英文叫Tokenization其任务是把一串连续的字符序列切分成一系列离散的、有语义的基本单元这些单元被称为Token。对于英文这可能近似于单词加上标点对于中文则复杂得多因为中文没有天然的分隔符。2.1 主流分词算法与策略目前基于Transformer的LLM普遍采用子词分词算法它巧妙地平衡了词汇表大小和语义粒度。其核心思想是高频词保留为整体低频词或复杂词拆分成更小的、可重用的子词单元。2.1.1 Byte-Pair Encoding从字节到子词的构建BPE可以说是目前最流行的分词算法GPT系列、Llama等模型都使用它或其变种。它的工作方式非常直观像一个迭代合并的游戏初始化将训练语料中的所有文本拆分成最基本的单元比如UTF-8字节或字符。例如“hello world”初始化为[‘h’ ‘e’ ‘l’ ‘l’ ‘o’ ‘ ’ ‘w’ ‘o’ ‘r’ ‘l’ ‘d’]。统计与合并在整个语料库中统计所有相邻符号对出现的频率。找到出现频率最高的一对比如(‘l’ ‘l’)在“hello”中出现了(‘l’ ‘d’)在“world”中出现了。假设(‘l’ ‘l’)频率最高就将它们合并成一个新的符号‘ll’并加入词汇表。迭代重复步骤2不断合并高频的相邻符号对直到达到预设的词汇表大小例如5万、10万或合并次数。这样做的妙处在于“unhappy”可能会被拆成[‘un’ ‘happy’]其中‘un’和‘happy’都是高频子词可以独立用于构成“unlikely”、“happiness”等词。这极大地压缩了词汇表同时保持了构词能力。2.1.2 WordPiece与SentencePieceBPE的变体与扩展WordPiece被BERT家族模型采用。它与BPE流程类似但合并策略不同。BPE合并最高频的相邻对而WordPiece合并能最大程度提升语言模型概率的相邻对。它计算的是合并后对整个语料似然度的增益而不仅仅是频率。理论上这能产生更“自然”的子词划分。SentencePiece这是谷歌推出的一个开源库它最大的特点是将文本视为Unicode字符序列无需预分词。对于中文、日文等没有空格的语言这是一个巨大优势。它直接在原始字符序列上应用BPE或Unigram算法避免了因依赖空格分词而引入的偏差。你可以把它理解为一个语言无关的、更纯粹的分词工具。2.1.3 中文分词的独特挑战与工具英文分词有空格作为天然界限中文则不然。“南京市长江大桥”就有多种切分可能。传统的中文NLP任务依赖分词工具如Jieba、HanLP、PKUSeg等。这些工具基于词典匹配、统计模型如HMM、CRF或深度学习能较好地进行词语切分。但在LLM时代情况发生了变化。像ChatGLM、Qwen、Baichuan这样的中文大模型通常直接采用基于字的BPE或SentencePiece。例如它们可能将“人工智能”直接按字拆成[‘人’ ‘工’ ‘智’ ‘能’]作为初始单元然后通过BPE学习到[‘人工’ ‘智能’]这样的高频组合。这样做的好处是解决未登录词问题任何新字都能被拆成单个字符处理不会因为不在词典而失效。简化处理流程无需依赖外部分词工具流程统一。弊端可能会破坏一些固定短语的完整性对成语、专有名词的理解可能不如词语级分词精准。实操心得如果你在微调或部署中文LLM时遇到生成不连贯或理解偏差不妨检查一下分词结果。用模型的tokenizer对样例文本进行编码和解码看看它到底把句子切成了什么样。有时在专业领域如医学、法律加入一些领域专有名词作为特殊Token能显著提升模型在该领域的表现。2.2 分词器的实际影响与调优分词不是一个透明的过程它直接影响模型性能和用户体验。上下文长度限制模型的上下文窗口如4K、8K、128K限制的是Token的数量而非字符数。一个中文字符可能被编码成1个或更多Token取决于分词器。因此一段1000字的中文文本占用的Token数可能远超1000更容易触达窗口上限。计算Token数量必须使用模型配套的分词器而不是简单地按字计数。生成效率与成本模型生成文本时是以Token为单位进行自回归预测的。分词粒度越细生成相同字符内容所需的预测步骤可能越多影响速度。同时许多API服务按Token数计费低效的分词会直接增加成本。信息损失过于激进的分词可能会破坏语义单元。例如将“U.S.A”切成[‘U’ ‘.’ ‘S’ ‘.’ ‘A’]就丢失了其作为国家名称的整体性。如何应对理解你的分词器使用transformers库你可以轻松加载并测试任何Hugging Face模型的分词器。from transformers import AutoTokenizer tokenizer AutoTokenizer.from_pretrained(meta-llama/Llama-3.2-1B-Instruct) text 大语言模型很有趣。 tokens tokenizer.tokenize(text) # 查看分词结果 input_ids tokenizer.encode(text) # 查看对应的ID print(tokens) # 例如[大, 语言, 模型, 很, 有趣, 。] print(len(input_ids)) # 实际的Token数量处理长文本当文本超过上下文窗口时需要进行截断或滑动窗口处理。关键是确保截断点不在一个完整语义单元的中间这需要根据分词结果进行判断有时甚至需要回退到字符级别寻找合适的断点如句号、换行符。特殊Token处理分词器除了词汇表还定义了一系列特殊Token如[CLS],[SEP],[PAD],[UNK],|endoftext|等。在构建输入时如问答对、多轮对话必须正确使用这些Token来分隔不同部分模型才能理解结构。3. 嵌入为每个Token赋予“灵魂”的向量表示分词得到了Token序列和对应的ID如[2301, 3928, 1827, ...]。但这些ID只是索引是离散的、孤立的。嵌入层的作用就是将这些离散的ID映射到连续的、高维的向量空间中。这个向量就是该Token的嵌入。你可以把整个词汇表想象成一个巨大的抽屉柜每个抽屉对应一个Token ID里放着一个独一无二的、高维的“属性向量”。这个向量不是随机的而是在训练过程中根据该Token在数十亿文本中出现的上下文学习到的语义和语法特征的密集表示。3.1 嵌入层的原理与训练在Transformer模型中嵌入层通常是一个可训练的查找表其维度为[词汇表大小V, 隐藏维度D]。例如词汇表有5万个Token隐藏维度是4096那么这个嵌入矩阵就是一个50000 x 4096的庞大参数矩阵。前向过程当输入ID为2301时模型就从这个矩阵中取出第2301行一个4096维的向量作为该Token的初始表示。训练过程这个矩阵的数值是如何来的它是与模型的其他部分注意力层、前馈网络一起训练得到的。训练目标是让模型能够根据上下文预测下一个Token或完形填空。在这个过程中模型会不断调整每个Token的向量使得语义相似的Token如“猫”和“狗”在向量空间中的位置接近。有语法关联的Token如“吃”和“食物”也能产生关联。同一个词的不同形态如“run”, “running”, “ran”的向量也彼此相关。最终这个高维空间形成了一个复杂的“语义地图”模型所有的“理解”都基于在这个地图上的计算。3.2 位置编码为序列注入顺序信息原始的嵌入向量只包含了Token的语义信息但丢失了它在句子中的位置信息。“猫追老鼠”和“老鼠追猫”的Token集合一样但含义相反。因此必须向模型注入顺序信息。这就是位置编码的职责。3.2.1 绝对位置编码最经典的是Transformer论文中提出的正弦余弦位置编码。它为序列中的每个位置pos生成一个与嵌入维度d_model相同的向量。这个向量的每个元素都是由不同频率的正弦和余弦函数计算得出的PE(pos, 2i) sin(pos / 10000^(2i/d_model))PE(pos, 2i1) cos(pos / 10000^(2i/d_model))其中i是维度索引。这种编码的特点是对于固定的偏移量kPE(posk)可以表示为PE(pos)的线性函数这有助于模型学习相对位置关系。然后将这个位置编码向量直接加到对应的Token嵌入向量上。3.2.2 相对位置编码与旋转位置编码绝对位置编码在长文本上可能泛化性不佳。后续的研究提出了更优的方案相对位置编码不关注Token的绝对位置而是关注Token对之间的相对距离。在计算注意力分数时加入一个与相对距离相关的偏置项。这更符合语言的理解逻辑我们更关心词与词之间的关系而非它们离句子开头有多远。旋转位置编码这是当前许多先进模型如Llama、GPT-NeoX采用的方法。它不进行向量相加而是通过旋转矩阵对Query和Key向量进行变换。具体来说将嵌入向量的每两个维度看作一个复数根据位置信息对这个复数进行旋转。RoPE具有很好的外推性即训练在较短序列上推理时能一定程度上处理更长的序列这对扩展上下文窗口至关重要。注意事项当你尝试对模型进行长度外推即让训练时只见过2048个Token的模型处理4096个Token的文本时位置编码往往是最大的瓶颈。正弦编码或可学习的位置嵌入通常外推能力很差会导致超出训练长度的位置信息混乱。RoPE在这方面表现更好但也有其极限。这就是为什么“无损扩展上下文窗口”成为当前一个重要的研究方向。3.3 嵌入向量的性质与可视化训练好的嵌入空间具有一些有趣的数学性质类比关系经典的例子是vec(“国王”) - vec(“男人”) vec(“女人”) ≈ vec(“女王”)。这表示语义关系可以通过向量运算来捕捉。语义聚类相似主题的词会聚集在一起。所有关于“水果”的词向量在空间中会形成一个簇与“交通工具”的簇分开。我们可以通过降维技术如t-SNE、PCA将高维向量投影到2D或3D进行可视化直观地观察这些性质。这不仅是理解模型内部表示的好方法也能用于诊断问题比如检查某个领域的术语是否被正确编码。4. 从分词嵌入到实际应用场景理解了基本原理我们来看看这些技术如何在具体场景中发挥作用以及可能遇到的“坑”。4.1 在RAG中的核心作用检索的基石检索增强生成是当前让LLM获取最新、特定知识的主流架构。其核心步骤是将文档库分块 - 将文本块转换为向量 - 存储到向量数据库 - 用查询向量检索相关块 - 交给LLM生成答案。这里嵌入模型的质量直接决定了检索的精度。如果你用一个通用的、在维基百科上训练的嵌入模型去处理充满专业术语的医学论文或法律条款检索效果很可能不理想。因为“心肌梗死”和“心梗”在通用模型中的向量可能不接近但在医学场景下它们应该非常接近。解决方案领域微调嵌入模型使用你所在领域的文本数据对开源的嵌入模型如BGE、text2vec进行微调。这能让模型学习到领域特有的语义相似度。精心设计分块策略分块大小chunk size和重叠量overlap对检索效果影响巨大。块太大可能包含无关信息稀释核心内容块太小可能破坏完整语义。对于技术文档按章节或子章节分块可能比固定长度分块更好。重叠则可以避免在块边界丢失关键信息。混合检索除了向量检索语义搜索可以结合关键词检索BM25或元数据过滤日期、作者。这就是所谓的“混合搜索”能兼顾语义匹配和精确匹配提高召回率。4.2 在微调与提示工程中的隐式影响当你进行指令微调或使用提示词时分词和嵌入在暗中施加影响。微调全参数微调会更新嵌入层的参数。这意味着模型会为你在训练数据中频繁使用的特定术语或表达方式调整其向量表示使其更贴合你的领域。提示工程模型的输出对提示词的措辞非常敏感。这背后的一部分原因就是不同的措辞会导致完全不同的分词和嵌入序列。“请总结下文”和“烦请您对下面的文章进行要点归纳”这两个提示虽然人类看来意思一样但它们的Token序列和初始向量表示差异很大可能导致模型激活不同的内部路径从而产生不同的输出风格甚至内容。一个常见的坑是“系统提示词被忽略”。有些模型在训练时系统提示和用户提示是被区别对待的例如用特殊Token分隔。如果你在部署时没有正确格式化输入导致系统提示被分词后与用户消息混在一起模型可能就无法正确识别指令。务必查阅模型文档严格按照要求的格式如ChatML格式、Llama2对话格式构建输入。4.3 处理多语言与特殊格式的挑战现代LLM通常是多语言的这给分词器带来了巨大挑战。词汇表膨胀为了覆盖多种语言词汇表需要包含各种语言的字符和子词导致词汇表异常庞大增加了嵌入层的参数量和计算开销。不平衡表示训练数据中英语占主导导致英语Token的嵌入表示学习得最充分其他语言的Token可能表示质量较差这就是为什么有些模型在非英语任务上表现会下降。特殊格式代码、数学公式、化学式等具有严格的语法结构。通用的分词器处理这些内容时可能会产生无意义的切分。例如一个Python函数名calculate_loss被切成[‘calculate’ ‘_’ ‘lo’ ‘ss’]破坏了其作为一个标识符的整体性。针对代码的模型如CodeLlama会使用在代码库上训练的分词器以更好地保留编程语言的语义单元。应对策略对于特定领域应用如果可能优先选择在该领域或语言上有优势的模型和分词器。例如处理中文任务Qwen或ChatGLM通常比同等规模的通用英文模型更合适。5. 进阶话题嵌入模型与向量数据库的协同虽然LLM内部的嵌入层是随模型一起训练的但在RAG等外部检索场景中我们通常使用一个独立的、专门训练用于生成“检索友好”向量的嵌入模型。这与LLM内部的嵌入层目标不同前者旨在让语义相似的文本片段具有相似的向量用于检索后者旨在为下一个Token预测任务提供最佳上下文表示。5.1 专用嵌入模型的选择目前社区有很多优秀的开源嵌入模型如BGE系列智源研究院推出中文表现强劲有不同尺寸版本。text2vec朗朗上口的名字中文语义相似度计算效果很好。E5系列微软发布通过指令微调指令如“为这段文本生成用于检索的向量”在检索任务上表现优异。OpenAI的text-embedding-ada-002虽然非开源但作为API服务效果稳定是多语言任务的常见选择。选择时需要考虑维度通常有384维、768维、1024维等。维度越高表征能力越强但计算和存储开销也越大。对于千万级以下的文档库768维通常是个不错的平衡点。上下文长度嵌入模型本身也有上下文窗口限制如512、1024、2048。如果你的文本块很长需要选择支持长上下文的模型或者采用动态截断、分段编码再池化的策略。微调与领域适配正如前文所述在特定领域数据上微调嵌入模型是提升检索效果最有效的手段之一。5.2 向量数据库的集成与优化将文本转换为向量后需要存入向量数据库进行高效检索。Milvus、Pinecone、Qdrant、Weaviate等都是热门选择。集成时的关键点索引类型向量数据库使用近似最近邻搜索算法来加速检索。常见的索引有HNSW、IVF-Flat、SCANN等。HNSW分层可导航小世界在精度和速度的平衡上表现很好是默认的推荐选择。IVF倒排文件需要训练更适合分布相对稳定的海量数据集。距离度量向量之间的相似度如何计算最常用的是余弦相似度它只关注向量的方向而非长度非常适合嵌入向量。此外还有内积、欧氏距离等。必须确保嵌入模型训练时使用的度量方式与向量数据库检索时使用的度量方式一致否则结果毫无意义。元数据过滤这是生产级应用必须考虑的功能。除了向量相似度我们经常需要结合业务逻辑进行过滤例如“只检索2023年之后的文档”、“只检索A部门的报告”。优秀的向量数据库应支持在检索时高效地结合元数据过滤。性能调优对于亿级向量索引构建参数如HNSW的M和efConstruction、搜索参数ef对性能和精度影响巨大。需要在你的数据集上进行基准测试找到最佳参数。一个实战中的教训我曾遇到一个案例检索结果总是包含一些看似相关但实际过时的文档。检查后发现问题出在分块时没有把文档的“更新时间”这个元数据正确地继承到向量块上导致无法用时间进行过滤。最终我们修改了预处理流水线确保每个文本块都携带了来源文档的完整元数据问题才得以解决。从用户输入的一段文字到模型内部可以进行矩阵运算的向量序列分词与嵌入完成了这个关键的“翻译”工作。它不仅是技术实现的起点更是影响模型最终表现的质量基石。无论是为了更深入地理解LLM的“黑盒”还是为了构建更高效的RAG系统、进行更成功的模型微调投入时间理解并优化这一环节都将带来丰厚的回报。在实际操作中多动手实验用不同的分词器处理你的文本观察结果用不同的嵌入模型为同一句话生成向量计算它们的相似度在向量数据库中尝试不同的索引参数。这些实践经验远比单纯阅读理论更能让你把握其中的精妙之处。