ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

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

2026/8/12 20:43:56 拓冰建站 浏览量
大语言模型文本处理核心:分词与嵌入技术详解

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等模型都使用它或其变种。它的工作方式非常直观,像一个迭代合并的游戏:

  1. 初始化:将训练语料中的所有文本拆分成最基本的单元,比如UTF-8字节或字符。例如,“hello world”初始化为[‘h’, ‘e’, ‘l’, ‘l’, ‘o’, ‘ ’, ‘w’, ‘o’, ‘r’, ‘l’, ‘d’]
  2. 统计与合并:在整个语料库中,统计所有相邻符号对出现的频率。找到出现频率最高的一对,比如(‘l’, ‘l’)在“hello”中出现了,(‘l’, ‘d’)在“world”中出现了。假设(‘l’, ‘l’)频率最高,就将它们合并成一个新的符号‘ll’,并加入词汇表。
  3. 迭代:重复步骤2,不断合并高频的相邻符号对,直到达到预设的词汇表大小(例如5万、10万)或合并次数。

这样做的妙处在于:“unhappy”可能会被拆成[‘un’, ‘happy’],其中‘un’‘happy’都是高频子词,可以独立用于构成“unlikely”、“happiness”等词。这极大地压缩了词汇表,同时保持了构词能力。

2.1.2 WordPiece与SentencePiece:BPE的变体与扩展

  • WordPiece:被BERT家族模型采用。它与BPE流程类似,但合并策略不同。BPE合并最高频的相邻对,而WordPiece合并能最大程度提升语言模型概率的相邻对。它计算的是合并后对整个语料似然度的增益,而不仅仅是频率。理论上,这能产生更“自然”的子词划分。
  • SentencePiece:这是谷歌推出的一个开源库,它最大的特点是将文本视为Unicode字符序列,无需预分词。对于中文、日文等没有空格的语言,这是一个巨大优势。它直接在原始字符序列上应用BPE或Unigram算法,避免了因依赖空格分词而引入的偏差。你可以把它理解为一个语言无关的、更纯粹的分词工具。

2.1.3 中文分词的独特挑战与工具

英文分词有空格作为天然界限,中文则不然。“南京市长江大桥”就有多种切分可能。传统的中文NLP任务依赖分词工具,如Jieba、HanLP、PKUSeg等。这些工具基于词典匹配、统计模型(如HMM、CRF)或深度学习,能较好地进行词语切分。

但在LLM时代,情况发生了变化。像ChatGLM、Qwen、Baichuan这样的中文大模型,通常直接采用基于字的BPESentencePiece。例如,它们可能将“人工智能”直接按字拆成[‘人’, ‘工’, ‘智’, ‘能’]作为初始单元,然后通过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’],就丢失了其作为国家名称的整体性。

如何应对?

  1. 理解你的分词器:使用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数量
  2. 处理长文本:当文本超过上下文窗口时,需要进行截断或滑动窗口处理。关键是确保截断点不在一个完整语义单元的中间,这需要根据分词结果进行判断,有时甚至需要回退到字符级别寻找合适的断点(如句号、换行符)。
  3. 特殊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, 2i+1) = cos(pos / 10000^(2i/d_model))其中i是维度索引。这种编码的特点是,对于固定的偏移量k,PE(pos+k)可以表示为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生成答案。

这里,嵌入模型的质量直接决定了检索的精度。如果你用一个通用的、在维基百科上训练的嵌入模型,去处理充满专业术语的医学论文或法律条款,检索效果很可能不理想。因为“心肌梗死”和“心梗”在通用模型中的向量可能不接近,但在医学场景下,它们应该非常接近。

解决方案

  1. 领域微调嵌入模型:使用你所在领域的文本数据,对开源的嵌入模型(如BGEtext2vec)进行微调。这能让模型学习到领域特有的语义相似度。
  2. 精心设计分块策略:分块大小(chunk size)和重叠量(overlap)对检索效果影响巨大。块太大,可能包含无关信息,稀释核心内容;块太小,可能破坏完整语义。对于技术文档,按章节或子章节分块可能比固定长度分块更好。重叠则可以避免在块边界丢失关键信息。
  3. 混合检索:除了向量检索(语义搜索),可以结合关键词检索(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服务,效果稳定,是多语言任务的常见选择。

选择时需要考虑:

  1. 维度:通常有384维、768维、1024维等。维度越高,表征能力越强,但计算和存储开销也越大。对于千万级以下的文档库,768维通常是个不错的平衡点。
  2. 上下文长度:嵌入模型本身也有上下文窗口限制(如512、1024、2048)。如果你的文本块很长,需要选择支持长上下文的模型,或者采用动态截断、分段编码再池化的策略。
  3. 微调与领域适配:正如前文所述,在特定领域数据上微调嵌入模型,是提升检索效果最有效的手段之一。

5.2 向量数据库的集成与优化

将文本转换为向量后,需要存入向量数据库进行高效检索。Milvus、Pinecone、Qdrant、Weaviate等都是热门选择。

集成时的关键点

  1. 索引类型:向量数据库使用近似最近邻搜索算法来加速检索。常见的索引有HNSW、IVF-Flat、SCANN等。HNSW(分层可导航小世界)在精度和速度的平衡上表现很好,是默认的推荐选择。IVF(倒排文件)需要训练,更适合分布相对稳定的海量数据集。
  2. 距离度量:向量之间的相似度如何计算?最常用的是余弦相似度,它只关注向量的方向而非长度,非常适合嵌入向量。此外还有内积、欧氏距离等。必须确保嵌入模型训练时使用的度量方式与向量数据库检索时使用的度量方式一致,否则结果毫无意义。
  3. 元数据过滤:这是生产级应用必须考虑的功能。除了向量相似度,我们经常需要结合业务逻辑进行过滤,例如“只检索2023年之后的文档”、“只检索A部门的报告”。优秀的向量数据库应支持在检索时高效地结合元数据过滤。
  4. 性能调优:对于亿级向量,索引构建参数(如HNSW的MefConstruction)、搜索参数(ef)对性能和精度影响巨大。需要在你的数据集上进行基准测试,找到最佳参数。

一个实战中的教训:我曾遇到一个案例,检索结果总是包含一些看似相关但实际过时的文档。检查后发现,问题出在分块时没有把文档的“更新时间”这个元数据正确地继承到向量块上,导致无法用时间进行过滤。最终,我们修改了预处理流水线,确保每个文本块都携带了来源文档的完整元数据,问题才得以解决。

从用户输入的一段文字,到模型内部可以进行矩阵运算的向量序列,分词与嵌入完成了这个关键的“翻译”工作。它不仅是技术实现的起点,更是影响模型最终表现的质量基石。无论是为了更深入地理解LLM的“黑盒”,还是为了构建更高效的RAG系统、进行更成功的模型微调,投入时间理解并优化这一环节,都将带来丰厚的回报。在实际操作中,多动手实验:用不同的分词器处理你的文本,观察结果;用不同的嵌入模型为同一句话生成向量,计算它们的相似度;在向量数据库中尝试不同的索引参数。这些实践经验,远比单纯阅读理论更能让你把握其中的精妙之处。