- ModernBERT(2024 年 12 月)是最近发布的小型语言模型,由 Answer.AI、LightOn 和 HuggingFace 共同开发。它利用了现代优化技术,如用于 8,192 token 上下文窗口的 RoPE 和 GeGLU layers,在保持效率的同时提升性能。
jina-XLM-RoBERTa
(2024 年 9 月)是一个基于 Meta 的XLM-RoBERTa
的多语言文本嵌入模型。原始XLM-RoBERTa
使用 XLM 大型多语言数据集增强了RoBERTa
,而jina-XLM-RoBERTa
通过扩展上下文训练、RoPE 实现和 FlashAttention-2 支持进一步改进。这个模型是 jina-embeddings-v3 的基础。RoBERTa-large
(2019 年 7 月)由 Meta 开发,是 BERT 的增强版本,拥有 3.55 亿参数。通过扩展训练、更大的数据集和动态掩码等创新,它在包括 GLUE、SQuAD 和 RACE 在内的关键基准测试中取得了出色的成果。这使其非常适合从文本分类到问答等各种 NLP 任务。
通过比较这些模型的三个核心方面,我们旨在为模型开发者突出 ModernBERT 的有效设计选择,并为未来的 BERT 类模型开发确定关键洞察。我们还将分享开发 jina-embeddings-v3 的经验,并讨论 jina-embeddings-v4
和 jina-reranker-v3
的计划改进。
ModernBERT 的参数效率
让我们首先研究 ModernBERT 在参数效率方面的方法——它借鉴了最近大语言模型开发的几个关键见解。ModernBERT 利用了三个核心策略:更深但更窄的架构、可控的词汇表大小,以及从较小模型开始的渐进式模型扩展。
深而窄的架构
ModernBERT-large 采用了 28 层的更深架构,而 jina-XLM-RoBERTa
和 RoBERTa-large
是 24 层。但有趣的是,尽管增加了层数,它的参数数量与 RoBERTa-large
持平。jina-XLM-RoBERTa
需要更多参数是因为它要处理 89 种语言,而另外两个只专注于英语。
对于小型大语言模型来说,深度(层数)比宽度(隐藏单元数)更重要。深而窄的模型结构在捕捉抽象概念方面表现出色,最终带来更好的性能。
transformer 的大部分参数来自注意力层和全连接层。ModernBERT 通过采用"更窄"的方式保持竞争力——在 28 层中使用 2,624 个隐藏单元,相比之下 RoBERTa-large 在 24 层中使用 4,096 个单元。这种"更深"但更窄的设置使他们能够在不增加模型体积的情况下达到性能目标。
ModernBERT-large | jina-XLM-RoBERTa |
RoBERTa-large |
|
---|---|---|---|
参数量 | 400M | 550M | 355M |
隐藏状态 | 1,024 | 1,024 | 1,024 |
中间维度 | 2,624 | 4,096 | 4,096 |
注意力头 | 16 | 16 | 16 |
层数 | 28 | 24 | 24 |
词汇表大小 | 50,368 | 250,002 | 50,265 |
这种方法与 Meta 的 MobileLLM 研究结果相符,该研究发现对于较小的模型来说,在捕捉复杂模式和提升性能方面,深度比宽度更重要。本质上,通过更多 transformer 层处理信息的能力比拥有更宽的层进行并行处理更有价值。
让我们看看这种深而窄架构的性能数据。
与使用传统浅而宽架构的同类模型相比,ModernBERT 在检索和 STS 等关键任务上表现更好——同时保持了类似的参数数量。
ModernBERT-large | jina-XLM-RoBERTa |
RoBERTa-large |
|
---|---|---|---|
STS12 | 72.6 | 72.7 | 68.9 |
STS13 | 84.9 | 83.9 | 81.0 |
STS14 | 77.5 | 77.7 | 74.8 |
STS15 | 84.8 | 85.8 | 84.1 |
STS16 | 79.4 | 79.6 | 78.6 |
STS17 | 87.5 | 87.2 | 87.2 |
TRECCOVID | 61.1 | 59.6 | 49.3 |
FiQA | 44.4 | 40.0 | 40.7 |
NFCorpus | 32.6 | 30.6 | 27.9 |
SciFact | 68.6 | 65.5 | 63.1 |
平均值 | 69.3 | 68.2 | 65.6 |
以 jina-XLM-RoBERTa
为例——它在 RoBERTa-large
的浅而宽架构基础上将词汇表从 5 万扩大到 25 万个 token,并训练了更多数据。但 ModernBERT 仍然略胜一筹,这表明架构的改变确实在效率方面产生了实质性的差异。
“词汇表大小很重要”)词汇表大小很重要
首先,让我们看看 transformer 中词汇表参数是如何计算的。对于任何 transformer,词汇表参数 = 不同 token 数量 × 隐藏维度
。以 jina-XLM-RoBERTa
为例:有 25 万个 token 和 1,024 维度,仅词汇表编码就需要 2.56 亿参数——这还是在处理任何实际语言任务之前!
在 transformers 中,第一层通过权重矩阵(即词汇权重)将词元映射为隐藏状态。考虑到使用所有 UTF-8 码点(1,112,064)与 1,024 个隐藏维度 - 仅用于词元转换就需要巨大的 1,112,064 × 1,024 = 1 B
参数。虽然更大的 LLM(超过 100B 参数)可以处理这种开销,但对于较小的模型来说这是一个严重的限制。这正是我们使用 BPE 等分词器的原因,它可以高效地将常见的 UTF-8 码点合并为单个词元。
但关键是:**词汇权重不参与注意力机制 - 它们只是查找表。**对于在固定参数预算下工作的 SLM,更大的词汇表意味着用于实际语言处理的注意力层可用参数更少。这解释了为什么仅支持英语的 ModernBERT-large 尽管规模较小却优于多语言 jina-XLM-RoBERTa
- jina-XLM-RoBERTa
分配了更多参数(47%!)来支持多种语言。ModernBERT 的专注词汇表不仅提高了性能,还加快了推理速度,使其特别适合资源受限的应用。
所以现在如果我们只看核心模型参数(不包括词汇权重),ModernBERT 实际上比其同行具有更强的计算能力:ModernBERT 在实际语言建模上比 jina-XLM-RoBERTa
多 19% 的参数,比 RoBERTa-large
多 15%!
模型规格 | ModernBERT-large | jina-XLM-RoBERTa |
RoBERTa-large |
---|---|---|---|
语言支持 | 仅英语 | 89 种语言 | 仅英语 |
词汇量大小 | 50.4K | 250K | 50.3K |
总参数 | 400M | 550M | 355M |
词汇参数 | 51M | 256M | 51M |
词汇参数比例 | 13% | 47% | 14% |
核心模型参数 | 349M | 294M | 304M |
通过"权重平铺"进行模型扩展’)通过"权重平铺"进行模型扩展
ModernBERT 通过一种称为权重平铺的智能初始化方法解决了这个问题 - 本质上是从其较小的基础版本的权重引导 ModernBERT-large。
这种技术并不完全是新的 - 它建立在 DeepMind 的 Gopher 工作基础上,在微软的 Phi-2 模型中也有体现。但它在这里的应用对解决 SLM 训练瓶颈特别有效。
ModernBERT 使用 Gopher 团队的深度初始化策略从 22 层扩展到 28 层。对于那些额外的层(23-28),他们使用 ModernBERT-base 原始 22 层中的权重初始化每一层。对于每层的权重矩阵,他们使用 Phi-2 的中心平铺方法。工作原理是这样的:他们将 ModernBERT-base 的权重放在 ModernBERT-large 矩阵的中间。对于仍然空着的边缘怎么办?他们循环包装原始权重来填充它们。
这种初始化策略给 ModernBERT-large 带来了显著优势 - 它不是从零开始,而是利用了其较小版本预先学习的模式。它在扩展这个规模范围内的语言模型方面特别有效。
我们发现热启动模型能够从初始的高损失(由于增加的参数)中快速恢复,达到接近基础模型的损失水平。我们能够将 417M 参数扩展超过 3 倍,并保持优于从头开始训练到收敛的等效新模型的性能,这意味着收益不仅限于训练初期。然而,在更大的规模下,收敛时获得的相对收益会减少,特别是在宽度扩展方面。
循环权重包装不仅仅是为了方便 - 它与注意力矩阵自然呈现周期性模式的方式很好地吻合。Gopher 的研究表明,这种方法在 SLM(小于 9B 参数)中特别有效,但随着模型规模增大,这些优势开始减弱。
分词器的优势
ModernBERT 使用的是专门针对代码训练的 OLMo tokenizer,而不是标准的 BERT/RoBERTa 分词器。
分词器将 UTF-8 文本分解成映射到向量的 token - 这些才是模型实际处理的内容。在训练过程中,它学会将频繁出现的字符序列组合成单个 token。区别在哪里?标准分词器可能会把 init
分解为 in
+ it
,忽略了编程上下文。但 ModernBERT 的代码感知分词器则可以完整保留它。
在空格处理方面就更有意思了:ModernBERT 将 Python 的前导空格保留为单个 token,并区分 4 个和 8 个空格的差异 - 这对代码结构至关重要。** 这意味着 ModernBERT 的编码器在处理代码时能获得更清晰、更有意义的输入,而其他模型则要处理破碎、连贯性较差的 token。
ModernBERT 将 Python 的前导空格保留为单个 token,并区分 4 个和 8 个空格的差异 - 这对代码结构至关重要;而其他模型则需要处理破碎、连贯性较差的 token。
ModernBERT 的长文本处理能力
ModernBERT 在处理长文本方面取得了重大进展,这要归功于其庞大的训练语料库(包含 8,192 token 样本的 300B tokens)和全局与局部注意力相结合的先进技术。
ModernBERT 的卓越性能不仅仅归功于其广泛的长文本训练 - 很大程度上要归功于其创新的全局和局部注意力机制组合。与在每一层都使用计算成本高昂的全局注意力的 jina-XLM-RoBERTa
不同,ModernBERT 采用了更高效的方法。它在全局注意力(每三层使用一次,theta
为 160,000)和局部注意力(使用 128 token 的滑动窗口,theta
为 100,000)之间交替使用。这种混合策略在保持高性能的同时大大减少了训练时间。
在 ModernBERT 中,每三层会使用一次全局注意力,RoPE theta 为 160,000,其余层使用 128 token 的局部滑动窗口注意力,RoPE theta 为 10,000。—— ModernBERT
SpeedBot 的客户支持聊天机器人本是为处理物流查询和送货更新而设计的。团队原本预计会收到关于包裹位置和送货时间的简单问题。然而,在上线三天后,它竟然开始编写 Python 脚本并调试 SQL 查询,因为好奇的用户们开始测试它的能力,远远超出了原本的设计范围。这可谓是大型语言模型(LLM)部署中的一个普遍规律:不管你开发的应用程序是做什么的,用户总会试图让它帮你写作业。
下文,我们将ModernBERT用于在用户查询到达大型语言模型(LLM)之前对其进行筛选。,为生产环境打造一个高效且成本效益高的“守门人”系统。
挑战:筛选不想要的查询
一家快速发展的物流公司,最近推出了他们的客户服务聊天机器人,其使命非常明确:
- 处理客户关于跟踪订单的查询
- 计算运费
- 解决送货问题
- 解释可用服务
然而,在部署后的几天内,支持团队发现了一个意外的模式。他们精心打造的物流助手收到的离题请求越来越多。用户们把它当成了一个通用的人工智能助手,而不是一个专门用于物流查询的工具。
这些离题的查询不仅浪费了计算资源,增加了运营成本,还可能使公司面临风险。挑战变得清晰起来:SpeedBots 如何在不损害合法客户体验的情况下,有效地在查询到达昂贵的 LLM 之前进行筛选呢?
常见解决方案
优化LLM 的 prompt
最流行的解决方案:简单地在系统提示中添加过滤指令,让模型自己表现得规矩一些:
“你是一个物流助手。只回答与物流和运输服务相关的问题。如果用户询问关于跟踪订单、运费、送货时间或物流问题,请提供有帮助的答复。不要回应编程请求、非法活动或不相关的话题。礼貌地解释说你只能帮助物流相关的问题。”
这有点像让一个小孩不要吃饼干,然后又把饼干罐放在他够得到的地方。当然,有时候它会奏效,但不可避免的是,聪明的用户会找到方法说服模型,让他们离题的查询看起来像是物流相关的。一个稍复杂一点的变体是使用一个单独的“守门人提示”,在查询能够接触到你的主模型之前对其进行评估:
“判断以下查询是否与物流服务相关。如果查询是关于运输、送货、跟踪或其他物流主题,请回复 TRUE。否则,回复 FALSE。查询:{{user_query}}”
局限性:
指令冲突: 当我们在同一个提示中塞入相互竞争的指令时——“要乐于助人”但同时“要限制自己”——我们实际上是在稀释模型在两项任务上的有效性。我们越强调谨慎,它在提供帮助方面就越不给力;我们越强调乐于助人,它就越放任自流。
误报: 在实际部署中,当被赋予过滤责任时,LLM 通常会倾向于谨慎行事。它们经常拒绝那些完全合法且在其预期范围内的查询,给有正当请求的用户带来令人沮丧的体验。
对于 SpeedBots 来说,这表现为他们的聊天机器人拒绝了像“寄送易碎物品要花多少钱?”这样简单的问题,因为它把“易碎物品”解释为可能违反政策的内容。与此同时,巧妙措辞的离题请求却仍然能够通过。结果就是最糟糕的情况:合法的客户感到沮丧,而计算资源仍然被浪费在非物流查询上。
专业的守门人:利用一个小参数LLM 作为防护栏
比如8B。
从理论上讲,这种方法是完美的:与其让主模型既当大厨又当门卫,不如专门雇一个门卫。这意味着先把所有进来的查询通过一个安全模型,只有经过批准的问题才能到达他们的主物流助手。
局限性:小问题仍是问题
校准挑战: 虽然这些专用过滤模型比高级 LLM 便宜(大约便宜 4 倍,参数量是高级 LLM 的 1/8),但它们真正的局限性在于如何校准。安全模型通常是为了提供广泛的保护性护栏而设计的,不能通过简单地更新提示来针对特定领域进行定制。
过度热情: 安全模型倾向于为最大保护而校准,往往以牺牲可用性为代价。这意味着关于“易碎物品处理”的合法物流查询被标记为危险的,而巧妙伪装的不当内容有时却能溜过去。通用安全模型在捕捉明显有害内容方面表现出色,但在处理对专业应用最重要的行业特定细微差别方面却很吃力——这既产生了误报也产生了漏报,限制了它们的有效性。
尽管这些模型确实比“礼貌请求”的方法有所改进,但无法精确控制过滤的内容是一个重大限制。对于像 SpeedBots 这样有特定领域需求的公司来说,这种方法仍然存在太多不确定性。
定制的守门人:微调 LLM
下一步合乎逻辑的方法是通过微调来定制你的过滤模型。
这意味着训练一个模型来理解物流问题与其他所有问题之间的精确界限。
局限性:当治疗变成疾病
资源密集型开发: 即使是微调一个“小”的 80 亿参数模型,也需要专业的硬件、相当多的工程时间以及大量的计算资源。这个过程需要机器学习操作方面的专业知识,以及精心策划的数据集,通常需要配备高内存显卡(如 A100 显卡)的专用 GPU 集群,每次训练运行的计算成本可能高达数百美元。
无休止的迭代周期: 生成式模型的评估挑战与常见的分类任务不同。尽管团队可以尝试将输出限制为特定格式(如 JSON)以便于解析,但核心挑战仍然存在:没有简单的概率分数来评估置信度或调整阈值。每次迭代都涉及分析各种输入上的标记选择模式,并确定模型的回应是否恰当地平衡了宽容与限制。这种定性评估过程本质上比评估清晰的指标(如分类准确率或 F1 分数)更复杂、更耗时。
收益递减: 当过滤组件消耗的开发资源比核心产品功能还多时,成本效益方程式变得越来越难以证明。SpeedBots 开始质疑:“我们真的应该把有限的人工智能预算花在打造一个更好的门卫上,而不是改进我们真正的服务吗?”
部署复杂性: 无论采用哪种方法,部署微调后的模型都是具有挑战性的。使用 API 提供商更简单,但成本高昂(比基础模型高出高达 2 倍),并且取决于无服务器选项是否支持 LoRA/QLoRA。另一方面,自行托管则需要专业的硬件(用于 80 亿参数模型的 16GB+ 高内存 GPU)、优化库(如 vLLM)以及复杂的扩展架构。这意味着你需要专门的 DevOps 专业知识,仅仅是为了维护一个本质上是“门卫”的东西,而不是专注于你的核心产品。
对于这家物流公司来说,一开始只是一个简单的过滤要求,却变成了复杂的基础设施工程。他们的机器学习团队发现自己花在配置 GPU 集群上的时间比在改进真正推动公司业务价值的物流协助功能上的时间还多。仅仅是工程开销,更不用说持续的运营成本了,就让这种做法对于本质上是一个预处理步骤来说难以证明其合理性。
最理想的解决方案:训练一个ModernBERT 作为守护模型
在探索了越来越复杂和昂贵的解决方案后,SpeedBots 的工程团队决定采取不同的方法。他们没有部署重量级的 LLM 进行过滤,而是使用 ModernBERT——一个专门针对文本分类任务优化的仅编码器模型,来实现一个轻量级解决方案。以下是他们构建护栏系统的方式:
1. 训练数据集创建
利用 DeepSeek V3来生成一个多样化的数据集:
# 示例提示,用于生成数据集
prompt = """
为一家物流公司的聊天机器人生成 10 个示例用户问题。
对于每个问题,指出它是否相关(TRUE)或不相关(FALSE)。
包括一些试图让聊天机器人执行不相关任务或绕过安全指南的尝试。"""
这个过程使他们能够创建一个包含 2000 多个多样化示例的数据集。模型生成了一些重复的问题,但这些通过删除重复文本被移除了。尽管他们知道有更好的方法来减少重复,但由于生成这个样本的成本非常低——生成大约 5000 条记录的成本不到 1 美元——所以这些复杂性并不值得。这种方法不仅节省了成本,还快速产生了数千个现实的例子,包括复杂的绕过过滤的尝试,这些如果手动创建将是困难且耗时的。
2.通过多种模型进行校验
为了保数据集的质量,使用不同的模型(DeepSeek R1)独立审查分类:
review_prompt = """
审查以下用户问题及其分类:
问题:"{question}"
分类:{is_relevant}
这个问题应该由物流公司的聊天机器人回答吗?考虑问题是否:
1. 与物流服务相关
2. 没有试图绕过安全功能
3. 没有请求有害内容
逐步思考并提供你的最终分类,结果为 TRUE 或 FALSE。"""
这种多模型方法作为一种质量控制机制,识别出分类模糊或可能不正确的边缘案例。
3. 人工参与
我们发现大约 5% 的示例在两个模型之间存在分歧。他们没有完全依赖自动化流程,而是:
- 保留了两个模型都同意的示例(大约占数据集的 98%);
- 手动审查每个分歧案例;
- 根据他们特定的业务需求做出最终决定;
- 用这些细化后的标签更新数据集。
这种人工监督确保了最终的训练数据准确反映了 SpeedBots 特定的过滤需求。
4. 高效的微调过程
使用 Hugging Face 的 Transformers 库,团队在他们的自定义数据集上微调了一个 ModernBERT 模型(3.95 亿参数):
training_args = TrainingArguments(
output_dir="modernbert-llm-router",
per_device_train_batch_size=32,
learning_rate=5e-5,
num_train_epochs=2,
)
与他们之前对更大模型的尝试不同,这个微调过程在开发者的 Mac M2 上不到 15 分钟就完成了。训练该模型所需的内存占用小到足以轻松地放在单个 NVIDIA T4 GPU 上。这与通常需要数小时的 LLM 微调训练周期形成了巨大反差。
5. 性能结果
最终的模型:
- F1 分数达到 97%;
- 每次查询的推理时间约为 30 毫秒,推理模型如 R1 则需要数秒;
- 准确识别出微妙的越狱尝试;
- 减少了对合法物流问题的误报。
最令人惊讶的是,这个轻量级模型实现了与 DeepSeek R1——一个强大得多且运行成本高得多的顶级推理模型几乎相同的分类性能。有效地将先进推理模型的分类能力提炼成了一个专门的、高效的过滤器。
该系统:
- 精准定位:专为他们的物流领域设计;
- 资源高效:几乎不需要计算开销;
- 高度准确:性能优于更大、更复杂的模型;
- 操作简单:易于部署和维护。
有时最有效的人工智能解决方案并不是最大或最复杂的模型,而是最适合手头特定任务的模型。
完整的代码以及微调 ModernBert 的实验过程,包括生成数据集,可以在这个 github 仓库中找到。