首页
/ 使用 🤗 Transformers 运行 FlexOlmo:支持「数据灵活推理」的领域化 MoE 语言模型

使用 🤗 Transformers 运行 FlexOlmo:支持「数据灵活推理」的领域化 MoE 语言模型

2026-09-07 21:57:59作者:晏闻田Solitary

FlexOlmo 是 Allen AI 提出的一类新型 MoE(混合专家)语言模型,其核心创新在于:不同专家(expert)可以在相互隔离的封闭数据集上独立训练,推理时再通过「领域信息感知路由(domain-informed routing)」将它们灵活地包含或排除,整个过程无需任何联合训练。本文以官方模型文档 docs/source/en/model_doc/flex_olmo.md 为骨架,结合本仓库中 FlexOlmo 的配置、源码与测试实现,讲解其设计动机、在 Transformers 中的代码结构、基于 Pipeline / AutoModel 的文本生成、4-bit 权重量化(torchao)以及完整的 FlexOlmoConfig 参数语义,帮助读者直接上手加载并运行 allenai/FlexOlmo-7x7B-1T 等官方权重,并理解其在库内的底层架构。

一、FlexOlmo 是什么:一段背景导读

相关技术节点:2025-07-09 论文发布,2025-09-18 正式并入 Hugging Face Transformers(model_doc 文档页 首部说明),本文仓库对应实现路径为 src/transformers/models/flex_olmo/

FlexOlmo 的模型体系要解决两个长期困扰 MoE 的问题:

  1. 不共享数据的分布式训练(distributed training without data sharing):传统上,训练一个整体模型往往要求各方共享数据;FlexOlmo 让不同模型参数在不同的封闭数据集上独立完成训练。
  2. 数据灵活的推理(data-flexible inference):推理时,使用者可以像“开关”一样,把这些独立训练好的专家连同其关联数据,从一次前向计算中灵活地包含或排除,无需任何额外训练。这与“想增删一种能力就必须重训全模型”的传统范式有本质区别。

在工程架构上,FlexOlmo 采用 MoE 架构:每个专家在封闭数据集上独立训练,随后通过一个领域信息感知的路由器(domain-informed routing) 把它们整合起来。训练语料方面,FlexOlmo 在名为 FlexMix 的语料上训练,该语料由公开数据集与七个领域专属集合构成,用来近似模拟现实中“封闭数据子集”的真实分布。这一点尤其适合私有/合规数据敏感的场景——数据不必外泄,只把训练出的参数接入系统。

官方原始检查点集中收录于 Hugging Face 的 FlexOlmo collection,其中本文档示例所使用的旗舰权重为 allenai/FlexOlmo-7x7B-1T

在 Transformers 库内部,FlexOlmo 被定位为通用的因果语言模型(CausalLM)实现:自动模型映射表(modeling_auto.py)中注册了 ("flex_olmo", "FlexOlmoModel")("flex_olmo", "FlexOlmoForCausalLM"),因此可用 AutoModelForCausalLM / AutoTokenizer 一键加载。

二、仓库内的代码结构:模块化拼装而非全量重写

FlexOlmo 是本仓库 modular transformers 实践的典型产物。核心源码文件如下:

文件 职责
configuration_flex_olmo.py FlexOlmoConfig:全部超参数、RoPE 参数与 TP/PP/EP 并行策略声明(该文件由 modular 自动生成)
modeling_flex_olmo.py FlexOlmoModelFlexOlmoForCausalLMFlexOlmoPreTrainedModel 及注意力/MoE 子模块(同样自动生成)
modular_flex_olmo.py modular 源文件:所有类继承关系与改动意图的“原始出处”,CI 会校验生成文件与之一致
test_modeling_flex_olmo.py 通用 CausalLM 测试 + 针对真实检查点的集成测试

打开 modular_flex_olmo.py 即可发现,FlexOlmo 不是从零新写的架构,而是“组装”了库中三个成熟模型族的零件:

  • 基座模型(base model)复用 MixtralFlexOlmoModel 继承 MixtralModelFlexOlmoPreTrainedModel 继承 MixtralPreTrainedModel。modular 中的注释解释得很清楚——相比 OlmoE,Mixtral 与 Transformers 主库保持同步更新(例如采用了更新的子模块输出记录机制),因此被选为基座。唯一显著差异是 FlexOlmo 不使用 sliding window attention(见 modular_flex_olmo.py 的注释)。
  • 注意力与归一化沿用 OLMo 2FlexOlmoAttention 继承自 Olmo2AttentionFlexOlmoRMSNorm 继承自 Olmo2RMSNorm。原因在 modular_flex_olmo.py 注释中写明:OLMo 2 的 RMSNorm 与 apply_rotary_pos_emb 在低精度(如 bf16)下更忠实地复现原版 OLMo 代码库的数值行为。
  • MoE 部分复用 OLMoEFlexOlmoMLPFlexOlmoTopKRouterFlexOlmoSparseMoeBlockFlexOlmoForCausalLM 均直接继承或复用 olmoe 的实现。

一个值得注意的架构细节是解码层采用“后置归一化”。在 FlexOlmoDecoderLayer 中,代码先做自注意力、再施加 post_attention_layernorm,随后加残差;FFN/MoE 部分同样在计算后施加 post_feedforward_layernorm。这与大多数 pre-norm 的 LLaMA 系实现不同,modular 源注释(modular_flex_olmo.py)专门强调:“Norm is applied after attention/feedforward rather than before.” 读者如果要对比实现细节,应先看 modular 源文件,再对照自动生成的 modeling 文件。

三、快速开始:用 Pipeline、AutoModel 与命令行生成文本

官方模型文档给出了三种调用入口。以 allenai/FlexOlmo-7x7B-1T 为例,以下示例均围绕同一个提示语:"Plants create energy through a process known as"

3.1 方式一:Pipeline 一句话接入

如果你只需要最小化样板代码,直接使用高层 pipeline API(需要一张 CUDA 设备,device=0):

from transformers import pipeline


pipe = pipeline(
    task="text-generation",
    model="allenai/FlexOlmo-7x7B-1T",
    device=0,
)

result = pipe("Plants create energy through a process known as")
print(result)

3.2 方式二:AutoModel + AutoTokenizer 细粒度控制

需要控制生成参数、张量并行或缓存策略时,使用底层 API。官方文档示例显式指定了:

  • device_map="auto":自动把权重分配到可用设备(含 CPU offload);
  • attn_implementation="sdpa":使用 PyTorch 原生的 scaled dot-product attention 内核;
  • cache_implementation="static":配合 generate 使用静态 KV Cache(预分配缓存,降低逐 token 扩容开销)。
from transformers import AutoModelForCausalLM, AutoTokenizer


tokenizer = AutoTokenizer.from_pretrained(
    "allenai/FlexOlmo-7x7B-1T"
)

model = AutoModelForCausalLM.from_pretrained(
    "allenai/FlexOlmo-7x7B-1T",
    device_map="auto",
    attn_implementation="sdpa"
)
input_ids = tokenizer("Plants create energy through a process known as", return_tensors="pt").to(model.device)

output = model.generate(**input_ids, max_length=50, cache_implementation="static")
print(tokenizer.decode(output[0], skip_special_tokens=True))

3.3 方式三:命令行

官方文档同时说明同一能力可以从命令行使用(该模型同样注册在自动模型映射中)。命令行入口的具体用法可参考本仓库的 CLI 实现与测试(src/transformers/cli 目录)。

提示:文档页指出,FlexOlmo 家族包含面向不同语言任务(如对话、数学、代码等)的多个变体检查点,右侧侧边栏的模型列表提供了更多“不同语言任务 + FlexOlmo”的组合示例。例如仓库集成测试中还出现了领域化的 shanearora/Flex-reddit-2x7B-1Tallenai/FlexOlmo-1B-7B-0924 等权重,适合验证“不同领域专家自由组合”的用法。

3.4 关于生成结果的一致性验证

如果你希望在不下载大权重的前提下验证自己改动的实现与上游一致,可以参考 test_modeling_flex_olmo.py 中的两组慢速集成测试:

  • test_model_7b_logits:用 FlexOlmoForCausalLM.from_pretrained("shanearora/Flex-reddit-2x7B-1T", dtype=torch.bfloat16) 计算固定输入 [[1, 306, 4658, 278, 6593, 310, 2834, 338]] 的 logits,并与预期 logits 均值/切片做 assert_close(rtol/atol=1e-2);
  • test_model_7b_greedy_generation:用 dolma2-tokenizer 编码提示语 “Simply put, the theory of relativity states that ”,以贪心解码(do_sample=False)生成 64 个新 token,并与预期文本逐字比对。

该文件还展示了一个隐蔽的实现细节:FlexOlmoModelTesterattention_probs_dropout_prob 固定为 0.0,原因(见测试注释)是 TP 反向传播测试需要训练模式下非 TP 与 TP 两条前向的 dropout 掩码完全一致。

四、低资源部署:torchao 4-bit 权重量化

FlexOlmo-7x7B 级别的 MoE 权重体积可观,量化是降低显存负担的关键手段。官方文档指出:“Quantization reduces the memory burden of large models by representing the weights in a lower precision”,并引导读者参阅 量化总览 了解所有可用后端。除本小节外,仓库还提供了 量化后端选择指南 与各后端的专属文档。

下面示例用 torchaotorchao 文档)只把权重量化到 4-bit,group_size=128 意味着每 128 个权重共享一组缩放/零点,在精度与压缩率之间取平衡:

#pip install torchao
from transformers import AutoModelForCausalLM, AutoTokenizer, TorchAoConfig


torchao_config = TorchAoConfig(
    "int4_weight_only",
    group_size=128
)

tokenizer = AutoTokenizer.from_pretrained(
    "allenai/FlexOlmo-7x7B-1T"
)

model = AutoModelForCausalLM.from_pretrained(
    "allenai/FlexOlmo-7x7B-1T",
    quantization_config=torchao_config,
    device_map="auto",
    attn_implementation="sdpa"
)
input_ids = tokenizer("Plants create energy through a process known as", return_tensors="pt").to(model.device)

output = model.generate(**input_ids, max_length=50, cache_implementation="static")
print(tokenizer.decode(output[0], skip_special_tokens=True))

要点解读:

  • quantization_config=torchao_config 会在 from_pretrained 加载阶段完成“权重量化后加载”,推理时按量化格式计算;
  • int4_weight_only 是纯权重量化(weight-only),激活仍保持原精度,适合以生成/解码为主的推理场景;
  • 请留意模型文档给出的注意事项:示例中的方式只量化权重而非激活,对“数学生成 / 长文本编码”等对数值敏感的基准,量化会带来一定精度损失,实验时应结合领域任务实测取舍。

五、FlexOlmoConfig 参数全解

FlexOlmoConfig 的默认值与类型声明集中在 configuration_flex_olmo.pymodel_type = "flex_olmo"。核心字段及其语义如下:

参数(默认值) 语义
vocab_size = 100352 词表大小(含 padding/特殊 token),对应的 eos/pad id 见下方特殊 token 字段
hidden_size = 4096 隐藏层维度
intermediate_size = 11008 单个 MLP/专家的 FFN 中间维度(gate/up 侧)
num_hidden_layers = 32 Transformer 解码层数
num_attention_heads = 32 注意力头数
num_key_value_heads = None KV 头数;None 时在 __post_init__ 中回退为 num_attention_heads(见 configuration_flex_olmo.py),即默认为 MHA 而非 GQA
hidden_act = "silu" FFN 激活函数,FlexOlmoMLP 通过 ACT2FN[config.hidden_act] 解析(modeling 源码
max_position_embeddings = 4096 最大位置编码长度
initializer_range = 0.02 权重初始化标准差,专家参数与路由器权重均按其初始化(_init_weights 中单独处理 FlexOlmoExperts/FlexOlmoTopKRouter
rms_norm_eps = 1e-6 RMSNorm 的 epsilon
use_cache = True 是否缓存 KV,供生成加速
pad_token_id = 100277 padding token id
bos_token_id = None BOS 置空(直接使用 tokenizer 约定)
eos_token_id = 100257 EOS token id
tie_word_embeddings = False 不绑定输入/输出词嵌入(lm_head 独立可训练)
rope_parameters = None RoPE 参数容器(theta、rope_type 等);类属性 default_theta = 500000.0,默认旋转基频取自 OLMo 系
attention_bias = False Q/K/V/O 投影不加 bias
attention_dropout = 0.0 注意力 dropout(注意:推理时为 0,训练时使用该值)
num_experts_per_tok = 5 每个 token 路由到的专家数(top-k),对应路由器 self.top_k
num_experts = 7 专家总数
output_router_logits = False 是否输出各层路由器 logits
router_aux_loss_coef = 0.01 路由辅助损失(负载均衡损失)的加权系数
norm_topk_prob = False 是否对 top-k 路由概率做归一化(路由器中条件执行 router_top_value /= router_top_value.sum(dim=-1)

另外两个对并行开发者友好的类级映射需要留意:

  • attribute_map = {"num_local_experts": "num_experts"}:当外部 checkpoint 使用 “num_local_experts” 命名时自动映射到 num_expertsconfiguration_flex_olmo.py);
  • 并行策略声明:配置类内嵌 base_model_tp_plan(张量并行)、base_model_pp_plan(流水线并行)、base_model_ep_plan(专家并行)。其中 TP 计划把 q_proj/k_proj/v_proj 标为 colwise_gather_outputo_proj 标为 rowwise_split_input,注释说明这是“因为 q/k 上额外加了 norm,需要把输出复制回来”而做的特殊处理;EP 计划则为路由/分组 GEMM 配置了 ep_routergrouped_gemm 等策略(configuration_flex_olmo.py)。

快速以默认配置构造一个随机初始化的模型,可参考配置类 docstring 中的用法:

from transformers import FlexOlmoModel, FlexOlmoConfig

# Initializing a FlexOlmo style configuration
configuration = FlexOlmoConfig()

# Initializing a model from the FlexOlmo style configuration
model = FlexOlmoModel(configuration)

# Accessing the model configuration
configuration = model.config

六、从源码看推理与训练的关键机制

6.1 前向流程与因果掩码

FlexOlmoModel.forward 会:校验 input_idsinputs_embeds 二选一 → 若无 cache 则创建 DynamicCache → 由 create_causal_mask 统一生成因果掩码 → 一次计算位置编码后在所有解码层间共享 → 依序过层 → 末尾 RMSNorm,最终以 MoeModelOutputWithPast 形式返回(modeling_flex_olmo.py)。注释明确:与 Mistral 的唯一差异是把返回类型换成 MoE 专属的 MoeModelOutputWithPast

6.2 后置 LayerNorm 的注意力

FlexOlmoAttention 中除常规的 Q/K/V 投影与旋转位置编码外,最独特的是在投影后分别对 q、k 施加 RMSNorm(q_norm/k_normmodeling_flex_olmo.py),这与 OLMo2 一致。注意力实现通过统一的 ALL_ATTENTION_FUNCTIONS 接口按 _attn_implementation 分发(modeling_flex_olmo.py),所以能无缝切换 eager / SDPA / FlashAttention / FlexAttention。

FlexOlmoPreTrainedModel 声明了完整的后端能力标志(modeling_flex_olmo.py):

  • _supports_flash_attn = True_supports_sdpa = True_supports_flex_attn = True(对应文档头部 FlashAttention / SDPA 徽章);
  • _no_split_modules = ["FlexOlmoDecoderLayer"]:设备并行时按层切分;
  • supports_gradient_checkpointing = True 且解码层继承 GradientCheckpointingLayer
  • _can_record_outputsrouter_logitshidden_statesattentions 分别绑定到路由器/解码层/注意力模块的输出记录器上。

6.3 路由与负载均衡辅助损失

稀疏 MoE 推理的核心是 FlexOlmoTopKRoutermodeling_flex_olmo.py):把 token 展平后经线性层得到 router_logits,softmax(在 float 下计算)后取 top_k,得到每个 token 的专家下标与权重;若配置 norm_topk_prob=True 则对 top-k 概率归一。真正的专家计算在 FlexOlmoExperts 中完成——每层将所有专家权重压成三维张量(gate_up_proj 形状为 (num_experts, 2*intermediate_size, hidden_size)down_proj 为其转置形状),前向时用 one-hot 掩码找到命中专家,逐专家做线性 + SiLU 门控,再按路由权重累加回 token(modeling_flex_olmo.py)。这种“打包三维专家 + 按命中循环”的结构,也让该文件头部通过 @use_experts_implementation 注解预留了自定义 kernel 替换口子。

训练时若 output_router_logits=TrueFlexOlmoForCausalLM.forward 会把各层路由 logits 送入 load_balancing_loss_func(Switch Transformer 风格,modeling_flex_olmo.py)计算辅助损失,并按 router_aux_loss_coef 加进总 loss;lossaux_loss 会同时出现在 MoeCausalLMOutputWithPast 输出中。因此从该模型的“训练即多任务路由+LM 联合优化”设计可见,FlexOlmo 在库内不只是一次性推理模型——它同样支持带 labels 的标准微调与 lm_head 独立训练的完整 CausalLM 流程。

6.4 从“独立训练”到“灵活推理”的工程映射

回到文档描述的两个特性,对应到本仓库代码,可以这样理解其工程支撑:

  • 不同专家参数独立训练:从源码结构看,每个解码层的专家权重是相互独立的参数张量(按层、按专家独立存在),并没有跨层共享或联合投影约束——这正是“封闭数据集独立训专家”能成立的前提;
  • 推理时可灵活包含/排除数据(专家):文档强调这种包含/排除不需要再训练;在库内它首先体现为推理期路由是纯前向的 top-k 选择,某专家是否被使用仅取决于路由器输出。它不改变其余部分的计算图,因此把“某领域专家相关的数据”排除,在实现上等价于让路由避开对应专家,而无需重训模型权重

以上两点属于对代码结构的合理推断,超出本文档与当前源码证据之外的评测性结论,本文不做延伸。

七、公开 API 一览

官方模型文档的 API 引用部分([[autodoc]] 指令)对应以下四个公开类,它们是自动生成 docstring 的入口,可在交互式环境中用 help() 或文档自动补全查看每个方法签名:

  • FlexOlmoConfig:配置类(见第五节参数表),从 transformers 顶层导入;
  • FlexOlmoForCausalLM:带 lm_headGenerationMixin 的因果语言模型,同时覆盖 loss/aux_loss 计算、logits_to_keep 滑动解码切片(默认只算最后 1 个 token 的 logits 以省显存),支持 labels 微调与 model.generate 文本生成;
  • FlexOlmoModel:不含 lm_head 的裸主干,返回 MoeModelOutputWithPast,其 forward 文档覆盖 input_ids / attention_mask / position_ids / past_key_values / inputs_embeds / use_cache / kwargs 等参数;
  • FlexOlmoPreTrainedModel:基类,承载权重加载、初始化、后端能力标志与并行策略,forward 文档同样列出标准入参。

八、延伸阅读

需要注意的是:仓库中 modeling_flex_olmo.pyconfiguration_flex_olmo.py 均由 modular_flex_olmo.py 自动生成(文件头部有 CI 校验声明),任何对建模逻辑的改动都应落在 modular 源文件上;而本文给出的所有默认参数值均来自当前仓库配置类源码,若与历史版本或其他第三方 fork 存在出入,请以所加载 checkpoint 的 config.json 为准。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391