说明:这一份文档解析的是公开可获得的 Qwen3 训练代码栈,而不是“Qwen 团队内部完整原厂预训练源码”。
根据 Qwen3 官方仓库与官方文档,官方建议用户使用Axolotl / UnSloth / ms-swift / LLaMA-Factory等训练框架进行 SFT、DPO、GRPO 等后训练;Qwen 官方仓库本身并不提供一套完整的、可逐文件复现实验室内部 36T 预训练流水线源码。
因此,本文件按下面三层来拆解:
- Qwen 官方说明层:Qwen3 仓库与文档怎么组织训练入口
- 公开训练框架层:ms-swift / Megatron-SWIFT 的 SFT / RLHF / MoE 训练路径
- 模型定义层:Transformers 中
Qwen3/Qwen3-MoE的结构实现
1. Qwen3 的训练代码结构
1.1 官方公开内容主要分三块
A. Qwen3 官方仓库
负责:
- 模型系列说明
- 推理与部署指引
- 文档导航
- 训练框架推荐入口
B. Qwen 官方文档
负责:
- Qwen3 在 ms-swift / Transformers / vLLM 等框架下的使用方式
- SFT / GRPO / Megatron-SWIFT 最佳实践
- thinking / non-thinking 数据格式说明
C. 训练框架与模型实现
真正承载“可运行训练”的,是:
- ms-swift
- Megatron-SWIFT
- Transformers 中的 Qwen3 模型定义
- 以及可选的 Axolotl / LLaMA-Factory / UnSloth 等生态
所以,“Qwen3 训练代码逐文件解析”更合理的对象不是单一仓库,而是下面这条链路:
Qwen3 官方文档/README ↓ swift/cli/sft.py 或 swift rlhf / megatron sft ↓ swift.pipelines.train.sft / RLHF pipeline ↓ template + dataset + model prepare ↓ TrainerFactory ↓ Seq2SeqTrainer / GRPOTrainer / Megatron trainer ↓ Transformers Qwen3 / Qwen3-MoE 模型定义2. Qwen3 官方仓库
2.1 仓库定位
Qwen3 官方仓库更像“模型发行总入口”,主要包含:
- README
- docs
- eval
- docker
- examples
- 技术报告 PDF
README 的训练部分是“推荐外部训练框架”,不是“官方完整训练源码”。
3.QwenLM/Qwen3README 关键训练相关信息
3.1 README 的训练定位
- 官方强调的是“如何在公开生态中微调/对齐 Qwen3”;
- 而不是给出内部预训练代码。
3.2 对“逐文件解析”的影响
因此,后面我们会把“逐文件解析”分成:
- Qwen3 官方入口文件/文档
- ms-swift SFT / RLHF 训练入口
- Megatron-SWIFT MoE 训练入口
- Transformers 中的 Qwen3 模型文件
4. Qwen 官方文档中的训练路径
Qwen 官方文档对 Qwen3 训练最有价值的页面有三类:
- MS-SWIFT 训练页面
- Qwen3 Best Practices
- Transformers 使用页面
它们的作用分别是:
- MS-SWIFT 页面:给出 SFT / GRPO / Megatron-SWIFT 的可运行样例;
- Best Practices:给出 think / no_think 数据格式、
ignore_empty_think等关键技巧; - Transformers 页面:给出模型环境版本要求与推理/训练最小接入方式。
5.swift/cli/sft.py:
- 检查
--tuner_backend是否使用unsloth - 尝试初始化单设备模式
- 尝试初始化 ray
- 导入
swift.pipelines.sft_main - 调用
sft_main()
可以把它理解成:
# 伪代码prepare_runtime()prepare_optional_backend()fromswift.pipelinesimportsft_main sft_main()6.swift/pipelines/train/sft.py:
公开 Qwen3 训练代码栈里最值得精读的文件之一。
基本承担了“单机 / 多机 SFT 训练总控器”的角色。
可以把它理解为:
解析参数 → 构建模板 → 加载数据集 → 数据预处理/打包/packing → 构建 trainer → 启动训练 → 保存状态6.1_prepare_template():把“模型”与“模板规则”绑起来
负责:
args.get_template(self.processor)- 设置 template 为 train 模式
- 若 template 需要 model,则把当前 model 注入
- 检查
padding_free/packing是否被当前模板支持
注意
Qwen3 不是“裸 decoder”就能直接训好的模型。
它高度依赖聊天模板规范,尤其在 hybrid thinking 场景中:
- assistant 是否带
<think>...</think> - non-thinking 样本是否加空 think block
/no_think如何进入模板response_prefix如何拼接
这些不属于“模型权重”,而属于模板层约束。_prepare_template()就是把这些规则正式接入训练流程。
工程意义
很多人微调 Qwen3 失败,不是优化器错了,而是:
- 模板没对上;
- 非思考数据没做保护;
- packing 与模板不兼容。
这恰恰是训练成败的主要原因。
6.2_get_dataset():拉起训练/验证集
该函数主要做:
- 根据
args.dataset/args.val_dataset调用load_dataset - 支持
split_dataset_ratio - 支持数据乱序与分割
- 返回
train_dataset, val_dataset
关键点
这里说明 ms-swift 已经把“数据来源”做成统一接口:
- 可以从本地 JSON / JSONL / CSV 读取;
- 可以从 hub 读;
- 可以混多个数据集;
- 可以自动切训练/验证。
因此,Qwen3 的 SFT 并不需要自己写 dataloader 主逻辑,而是先把数据组织成对应格式即可。
6.3_prepare_dataset()/ post-process:数据集真正变成 token 样本
这个阶段会做的事包括:
- 让 template 把多轮对话编码成 token;
- 使用
EncodePreprocessor - 在需要时套上
LazyLLMDataset - 如果启用了
packing,则使用PackingDataset或IterablePackingDataset
这是性能关键区
这部分的关键不是“能不能训”,而是“训得快不快、显存省不省、吞吐高不高”。
1.LazyLLMDataset
- 延迟编码;
- 避免一次性全量预处理带来的内存压力;
- 适合大数据集。
2.PackingDataset
- 把多个短样本拼接到一个长序列中;
- 提高 token 利用率;
- 减少 padding 浪费;
- 但要求模板与 attention 实现兼容。
3.padding_free
- 进一步减少 padding 的显存/算力浪费;
- 但不是所有模板都支持。
与 Qwen3 的关系
Qwen3 尤其依赖这些优化,因为:
- thinking 数据经常很长;
- 多轮对话格式复杂;
- 长上下文训练开销大;
- packing 对吞吐的帮助很明显。
6.4run():总调度函数
run()的职责是:
- 准备数据集;
- 统计参数信息;
- 通过
TrainerFactory.get_trainer_cls(args)选择 trainer; - 构建 trainer;
- 调用
self.train(trainer); - 保存状态与 checkpoint。
这说明整个训练体系采用的是“配置驱动 + trainer 分发”设计,而不是写死某个 Trainer。
7.swift/trainers/trainer_factory.py:训练器分发中心
这个文件虽然短,但地位很高。
7.1 文件做什么
它维护两张映射表:
TRAINER_MAPPING
把任务类型映射到 trainer 类:
causal_lm→Seq2SeqTrainerseq_cls→Trainerembedding→EmbeddingTrainerreranker→RerankerTrainergrpo→GRPOTrainerdpo/ppo/rm/kto/gkd等 → 对应 RLHF trainer
TRAINING_ARGS_MAPPING
把任务类型映射到 training args 类:
causal_lm→Seq2SeqTrainingArgumentsgrpo→GRPOConfig- 其他 RLHF 类型 → 对应 config
7.2 为什么这个文件关键
因为它把“训练方法”从主流程中解耦了。
于是sft.py不需要知道:
- 现在是不是 GRPO;
- 现在是不是 embedding;
- 现在是不是 reranker;
- 现在是不是奖励模型。
它只需要:
trainer_cls=TrainerFactory.get_trainer_cls(args)对 Qwen3 的价值
Qwen3 训练不只包括 SFT,还常常包括:
- SFT
- DPO
- GRPO
- 其他 alignment 变体
有了这个工厂层,Qwen3 训练入口就能统一抽象。
8.swift/template/templates/qwen.py:Qwen3 的模板中枢
这份文件是理解 Qwen3 hybrid thinking 的关键。
8.1 这不是“外围小工具”,而是核心训练文件
很多人以为 template 只是做字符串拼接。
对于 Qwen3 来说不是。
模板层实际上决定了:
- thinking / non-thinking 怎么表达;
- assistant 的 think block 是否保留;
- 用户 query 中的控制标志如何生效;
- 训练样本如何组织;
- 推理时 response prefix 怎么拼。
所以它和模型行为强绑定。
8.2Qwen3MixedTemplateMeta
这个类最重要的一个字段是:
non_thinking_prefix='<think>\n\n</think>\n\n'这个设计和 Qwen3 技术报告里的 thinking mode fusion 完全对齐。
含义
在 non-thinking 模式下,assistant 仍然保留一个空 think block。
这样做的好处是:
- 保持内部格式一致;
- 避免模型把 non-thinking 理解成完全不同输出结构;
- 让
/no_think、response prefix、budget 截断等机制更容易协作; - 使 mixed-mode 训练更稳定。
为什么不是简单去掉 think block
如果直接去掉,模型会学到两套回答外形:
- 一套有
<think> - 一套没有
<think>
这会让混合训练更容易产生格式漂移。
空 think block 则相当于“保留骨架、缩掉思考内容”。
9. Qwen3 Best Practices:训练技巧文档
这是公开训练体系里极其实用的一页。
9.1 为什么它比源码还重要
因为 Qwen3 的很多有效训练技巧,不在单一函数里,而在参数组合与数据规范里。
例如:
--loss_scale ignore_empty_think/no_think--packing true--attn_impl flash_attn--response_prefix '<think>\n\n</think>\n\n'--use_vllm true--rlhf_type grpo
这些经验如果不知道,只看源码不一定能训对。
9.2ignore_empty_think:为什么它非常重要
官方最佳实践明确指出:
如果你用的是没有 CoT 的普通 SFT 数据,但你又不想破坏 Qwen3 的 thinking 能力,推荐使用:
--loss_scaleignore_empty_think本质含义
对于形如:
<think> </think> 最终回答这样的空 think block,不对其部分计算损失,避免模型被强迫学习“永远不思考”。
为什么这招有效
因为非思考数据在训练中通常数量很大。
如果直接把这些数据当作普通 teacher forcing 样本,模型会快速学到:
“哦,原来
<think>里什么都不写才是最优。”
这会把 reasoning 能力慢慢磨掉。ignore_empty_think就是在 loss 层做保护。
9.3/no_think:从 query 侧显式控制模式
另一种做法是直接在 query 中加入/no_think:
{"messages":[{"role":"user","content":"浙江的省会在哪? /no_think"},{"role":"assistant","content":"<think>\n\n</think>\n\n浙江的省会在杭州。"}]}它和ignore_empty_think的区别
ignore_empty_think:主要是loss 层保护/no_think:主要是行为显式控制
二者可以单独用,也可以组合用。
9.4packing与flash_attn
最佳实践明确提醒:
如果
--packing true,需要配合--attn_impl flash_attn
为什么
packing 会改变 batch 中 token 的排布方式。
要想把 packed 序列高效算出来,attention 实现层需要足够高效且兼容。
因此在大多数大模型训练实践里:
- packing
- flash attention
- 合适的模板编码
这三者往往要一起看。
10.swift rlhf --rlhf_type grpo:Qwen3 的公开 RL 入口
Qwen3 技术报告的 reasoning RL 使用的是GRPO。
而在公开可运行训练栈里,对应入口就是:
swift rlhf--rlhf_typegrpo...10.1 这一层的结构特点
从最佳实践和调用栈可以看出,RL 训练链路大致是:
swift rlhf ↓ 解析 rlhf_type=grpo ↓ TrainerFactory 选择 GRPOTrainer / GRPOConfig ↓ 采样 / 奖励 / logprob 计算 ↓ 反向更新10.2 数据格式特点
GRPO 数据和 SFT 数据很像,但通常不需要最终 assistant 响应列。
如果 reward 是 accuracy 这类可验证函数,还需要额外solution字段。
这正好对应 Qwen3 报告中“数学、代码、可验证任务”的 RL 路线。
11.swift/trainers/rlhf_trainer/grpo_trainer.py:GRPO 训练器
即使不逐行深挖内部实现,仅从公开调用栈也能确认这个文件是 GRPO 的核心执行器之一。
调用栈里可看到它承担如下职责:
_prepare_inputs_generate_and_score_completions_prepare_batch_inputs_get_per_token_logps_and_entropies
这意味着什么
它不只是一个“reward wrapper”,而是至少覆盖:
- 生成候选 completion
- 计算奖励 / 验证
- 计算 per-token log probability
- 可能还要处理 entropy / baseline / rollout 相关逻辑
为什么这和 Qwen3 强相关
Qwen3 的 reasoning RL 并不是普通 DPO 那种“对比 preference pair”范式,而是偏向可验证问题的 RL。
GRPO trainer 正是公开生态里最接近这一思路的可运行入口。
12.megatron sft路线:MoE / 大模型训练的真正加速入口
如果你训练的是:
- Qwen3-30B-A3B
- 更大的 MoE / dense 大模型
- 多机多卡大规模实验
那么公开训练体系里更重要的入口通常不是swift sft,而是:
megatron sft...12.1 为什么要单独有 Megatron 路线
因为大模型训练真正痛点在于:
- Tensor Parallel
- Pipeline Parallel
- Sequence Parallel
- Expert Parallel
- Activation Recompute
- Flash Attention
- Checkpoint 策略
单靠普通 HF Trainer 很难把这些都做到高效率。
Megatron-SWIFT 就是把 Megatron-LM 的并行化优势接入到 ms-swift 生态里。
12.2 从公开路径可以看到的 Megatron 关键文件
从实际调用栈可以定位到这些关键文件路径:
swift/cli/_megatron/sft.pyswift/megatron/pipelines/train/sft.pyswift/megatron/trainers/base.pyswift/megatron/trainers/trainer.py
结构理解
可大致概括成:
CLI 入口 ↓ Megatron SFT pipeline ↓ Megatron trainer base ↓ Megatron forward/backward schedule ↓ 模型并行执行12.3 Qwen3-30B-A3B 的 Megatron 示例脚本怎么看
Qwen3 Best Practices 给出了一个非常有代表性的命令:
--pipeline_model_parallel_size 2--expert_model_parallel_size 8--moe_permute_fusion true--moe_grouped_gemm true--moe_aux_loss_coeff ...--sequence_parallel true--attention_backend flash
逐个解释
pipeline_model_parallel_size
把不同层切到不同 GPU 组。
expert_model_parallel_size
把不同专家切到不同设备组。
这对 MoE 至关重要。
moe_grouped_gemm
把多个专家的小矩阵运算进行 grouped GEMM 融合,提升吞吐。
moe_permute_fusion
优化 token 在专家间分发时的置换/重排过程。
sequence_parallel
在长序列训练中进一步摊薄显存压力。
recompute_*
用重计算换显存,属于大模型训练常见策略。
你应如何理解
这说明公开训练栈里,Qwen3-MoE 的重点并不是“模型文件怎么写”,而是:
如何把专家并行、序列并行、流水并行、attention 优化和数据 packing 组合起来。
13.docs/source_en/Instruction/Command-line-parameters.md:参数语义总表
这份文档极其适合和源码对照看,因为它把命令行参数按类别做了统一说明。
它的作用
- 告诉你参数是怎么分层继承的
- 告诉你
model_kwargs一类模型专有参数怎么传 - 告诉你 base args / atomic args / integrated args 的关系
- 帮你把命令行训练脚本和 pipeline 源码对应起来
为什么建议重点看
很多训练失败,其实不是逻辑 bug,而是参数理解错了:
--modelvs--adapters--load_args--load_data_args--model_kwargs--attn_impl--task_type--use_hf
如果你在做自己的 Qwen3 工程集成,这页比单纯读源码更省时间。
14. Transformers 模型定义层:Qwen3 结构真正落在哪里
训练框架负责“怎么训”,
真正定义“模型长什么样”的,是 Transformers 中的这些文件:
src/transformers/models/qwen3/configuration_qwen3.pysrc/transformers/models/qwen3/modeling_qwen3.pysrc/transformers/models/qwen3_moe/modeling_qwen3_moe.py
14.1configuration_qwen3.py:Qwen3 配置对象
这个文件定义了Qwen3Config。
它是所有模型实例化、保存、加载、导出、权重兼容的根配置。
关键字段
vocab_sizehidden_sizeintermediate_sizenum_hidden_layersnum_attention_headsnum_key_value_headshead_dimmax_position_embeddingsattention_biasuse_sliding_windowsliding_windowlayer_types
这个文件为什么关键
因为它不只保存超参数,还决定了:
- 模型是 GQA 还是 MHA;
- 是否启用 sliding attention;
- 某些层是 full attention 还是 sliding attention;
- attention 是否带 bias;
- 模型保存/恢复时的结构一致性。
如果你想自己实现一个 mini-Qwen3 原型,这个文件就是第一份蓝图。
14.2modeling_qwen3.py:Dense Qwen3 主实现
这是 Dense 版最核心的实现文件。
关键类 1:Qwen3RMSNorm
作用:
- 实现 RMSNorm;
- 替代 LayerNorm;
- 对 deep decoder 更稳。
关键类 2:Qwen3MLP
它采用三层线性结构:
gate_projup_projdown_proj
对应的就是标准SwiGLU MLP。
关键类 3:Qwen3Attention
这是最值得看的一个类,它明确体现了 Qwen3 的几个结构特征:
- Q / K / V / O 全部线性层
- 默认
attention_bias=False - GQA:
num_key_value_groups = num_attention_heads // num_key_value_heads - QK-Norm:
q_norm/k_norm - RoPE:对 q/k 应用
apply_rotary_pos_emb - 可选 sliding window attention
关键类 4:Qwen3DecoderLayer
一个标准 Qwen3 decoder layer 的结构是:
residual └─ input_layernorm └─ self_attn └─ residual add └─ post_attention_layernorm └─ mlp └─ residual add这就是典型的pre-norm decoder block。
关键类 5:Qwen3Model
模型主干负责:
- embedding
- 多层 decoder
- final norm
- rotary embedding
- causal mask / sliding mask 生成
做自己的教育版实现,这一层就决定了 forward 总体骨架。
14.3modeling_qwen3_moe.py:MoE 结构实现
如果 Dense 文件回答的是“普通 Qwen3 长什么样”,
这个文件回答的是“Qwen3-MoE 是怎么路由专家的”。
关键类:Qwen3MoeTopKRouter
作用:
- 把 hidden states 拉平
- 线性映射得到
router_logits - 对专家维度做 softmax
topk选专家- 归一化 top-k 权重
这正是典型的稀疏路由逻辑。
关键类:Qwen3MoeSparseMoeBlock
作用:
- 调 router
- 得到
selected_experts与routing_weights - 把 token 分发给专家
- 再把专家输出汇总回来
你可以怎么理解
hidden_states ↓ router ↓ top-k experts ↓ expert MLPs ↓ weighted merge工程重点
真正的难点不在数学公式,而在:
- token 重排
- grouped GEMM
- 并行切分
- 路由负载均衡
- 通信开销控制
这也是为什么 MoE 训练通常要走 Megatron 路线。
15. Qwen3 训练代码的“真实调用图”
下面给出一个对公开训练栈更贴近真实的视图。
15.1 SFT 路线
swift/cli/sft.py ↓ swift.pipelines.sft_main ↓ swift/pipelines/train/sft.py ├─ _prepare_template() ├─ _get_dataset() ├─ _prepare_dataset() ├─ TrainerFactory.get_trainer_cls() └─ trainer.train() ↓ Transformers Qwen3Model / Qwen3ForCausalLM15.2 GRPO 路线
swift rlhf --rlhf_type grpo ↓ TrainerFactory ↓ GRPOTrainer / GRPOConfig ↓ 生成 rollout ↓ reward / verifier / accuracy ↓ per-token logprob / entropy ↓ update15.3 Megatron-MoE 路线
megatron sft ↓ swift/megatron/pipelines/train/sft.py ↓ swift/megatron/trainers/base.py ↓ Megatron schedules / TP / PP / SP / EP ↓ Qwen3-30B-A3B / MoE model16. 如果你要自己复现 Qwen3 训练,应该优先读哪些文件
按优先级,我建议这样读:
第一层:先搞懂训练行为
Qwen3 Best PracticesMS-SWIFT - QwenCommand-line-parameters.md
第二层:搞懂 SFT 主流程
swift/cli/sft.pyswift/pipelines/train/sft.pyswift/trainers/trainer_factory.py
第三层:搞懂模板与 hybrid thinking
swift/template/templates/qwen.py
第四层:搞懂模型结构
configuration_qwen3.pymodeling_qwen3.pymodeling_qwen3_moe.py
第五层:搞懂大模型 / MoE 训练
swift/megatron/pipelines/train/sft.pyswift/megatron/trainers/base.py- Megatron 示例脚本参数组合
17. 公开代码栈与技术报告的对应关系
下面把“技术报告里的概念”映射到“你能看到的公开代码/文档”。
| 技术报告概念 | 公开代码/文档中的落点 |
|---|---|
| thinking / non-thinking 融合 | qwen.py模板、Best Practices、response_prefix、/no_think |
| thinking budget | 技术报告 + tokenizer/chat template 侧能力,公开框架主要体现在 template 控制与推理侧参数 |
| SFT 数据构造 | Best Practices 数据格式说明 |
| Reasoning RL | swift rlhf --rlhf_type grpo+ GRPO trainer |
| Dense 架构 | modeling_qwen3.py |
| MoE 架构 | modeling_qwen3_moe.py |
| 大规模 MoE 微调 | megatron sft+ expert parallel 参数 |
| 完整预训练三阶段 | 公开文档中有描述,但原厂内部流水线未完整开源 |
18. 你自己实现 Qwen3 原型时,最值得复刻哪些部分
如果目标不是 1:1 复刻全功能,而是理解 Qwen3,本质上只需要先实现这些:
- RMSNorm
- RoPE
- GQA
- QK-Norm
- SwiGLU MLP
- Pre-Norm Decoder Layer
- 可选 Top-k Router + Sparse MoE block
- 简单的 thinking/non-thinking prompt 模板
也就是说,Qwen3 的“最小可解释原型”并不需要先实现:
- ZeRO
- Megatron 并行
- vLLM
- GRPO 全训练环
- expert grouped GEMM
先把核心 block 跑通,更有学习价值。
19. 一句实话:为什么很多人会误判“Qwen3 已经完整开源训练源码”
因为公开资料里同时出现了:
- 技术报告
- 官方仓库
- 文档
- 训练示例
- ms-swift
- Megatron-SWIFT
- Transformers 模型文件
视觉上很像“全都在了”。
但实际上这些内容来自不同层:
- 报告:描述训练方法
- 官方仓库:模型发行入口
- 文档:训练与部署指南
- ms-swift:后训练框架
- Transformers:模型定义实现
所以更准确的结论是:
Qwen3 已公开完整的模型权重、模型定义、推理接入与后训练接入栈;
但并未公开一套可逐文件复现其内部全部预训练阶段的单体源码仓库。
20. 总结
如果把“Qwen3 训练代码逐文件解析”说得最务实一点,它其实是在解析三件事:
第一件:官方如何定义训练入口
- README
- 文档
- 最佳实践
第二件:公开训练框架如何真正跑起来
swift/cli/sft.pyswift/pipelines/train/sft.pytrainer_factory.pyqwen.pyGRPOTrainerMegatron trainer
第三件:模型结构到底怎么写
configuration_qwen3.pymodeling_qwen3.pymodeling_qwen3_moe.py
如果你想真正掌握 Qwen3,建议按这条路径学习:
先看 Best Practices → 再看 SFT pipeline → 再看 template → 再看 trainer factory → 再看 Qwen3 Dense/MoE 模型定义 → 最后看 Megatron MoE 参数组合参考资料
- Qwen3 官方仓库 README
- Qwen 官方文档:MS-SWIFT - Qwen
- Qwen 官方文档:Qwen3 Best Practices
- ms-swift:
swift/cli/sft.py - ms-swift:
swift/pipelines/train/sft.py - ms-swift:
swift/trainers/trainer_factory.py - ms-swift:
swift/template/templates/qwen.py - Hugging Face Transformers:
configuration_qwen3.py - Hugging Face Transformers:
modeling_qwen3.py - Hugging Face Transformers:
modeling_qwen3_moe.py