1. 先搞清楚:Qwen3 训练代码到底指哪份代码
很多人搜「Qwen3 训练代码逐文件解析」,脑子里默认有一个仓库,clone 下来就能复现官方训练。我一开始也这么以为,翻完 QwenLM/Qwen3 官方仓库才发现不是——它更像模型发行总入口,README、docs、eval、docker、examples、技术报告 PDF 都在,但训练部分写的是「推荐你用 ms-swift / Axolotl / LLaMA-Factory 这些框架做后训练」。
所以真正能跑起来的训练代码,分散在三层里:官方说明层(仓库 README + 文档,告诉你入口在哪)、公开训练框架层(ms-swift / Megatron-SWIFT,承载 SFT、DPO、GRPO、MoE 训练)、模型定义层(Transformers 里的 Qwen3 / Qwen3-MoE 结构实现)。这篇就按这条链路逐文件拆,给你可复制的目录结构、关键文件职责、配置骨架,以及本地验证脚本能跑通的具体命令。适合已经会跑推理、想往训练流程里钻的开发者。
2. 前置准备:用 TaoToken 拿到可调用的模型与 Key
拆代码之前得有个能实际发请求的环境,不然改完配置不知道对不对。我习惯用 TaoToken 做统一入口,它把模型对话、API Key 管理、接入文档放在一个控制台里,省得在多个平台之间来回切。
你需要先拿到 API Key:进控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite ,在 API Keys 页面新建一个,复制保存。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite ,里面有 base_url 和请求格式说明。API 端点统一是 https://taotoken.net/api 。
注意:Key 只显示一次,丢了就重新建。别把 Key 写进会提交到 git 的配置文件里,用环境变量。
想先验证模型通不通,可以直接在模型对话页 https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 发一条消息,确认账号和额度正常,再去折腾训练脚本。
3. 目录结构:三层代码分别落在哪
先把「逐文件」的对象摆清楚。下面这份结构是我按公开仓库整理出来的,你可以照着建自己的学习目录:
qwen3-study/ ├── official/ # 官方说明层 │ ├── README.md # 模型系列说明、推理部署、训练框架推荐入口 │ ├── docs/ # 文档导航 │ ├── eval/ # 评测脚本 │ └── examples/ # 示例 ├── ms-swift/ # 公开训练框架层 │ ├── swift/ │ │ ├── cli/ │ │ │ ├── sft.py # SFT 命令行入口 │ │ │ └── _megatron/ │ │ │ └── sft.py # Megatron SFT 入口 │ │ ├── pipelines/ │ │ │ └── train/ │ │ │ └── sft.py # SFT 训练总控器 │ │ ├── trainers/ │ │ │ ├── trainer_factory.py │ │ │ └── rlhf_trainer/ │ │ │ └── grpo_trainer.py │ │ ├── template/ │ │ │ └── templates/ │ │ │ └── qwen.py # Qwen3 模板中枢 │ │ └── megatron/ │ │ ├── pipelines/train/sft.py │ │ └── trainers/base.py └── transformers/ # 模型定义层 └── src/transformers/models/ ├── qwen3/ │ ├── configuration_qwen3.py │ └── modeling_qwen3.py └── qwen3_moe/ └── modeling_qwen3_moe.py三层职责一句话概括:官方层告诉你「去哪训」,框架层负责「怎么训」,模型定义层决定「模型长什么样」。下面逐个文件拆。
4. 官方说明层:README 与文档里的训练入口
Qwen3 官方仓库的 README 训练部分,核心信息是「推荐外部框架」,不是「官方完整训练源码」。它主要包含 README、docs、eval、docker、examples、技术报告 PDF。对逐文件解析的影响是:你不能指望在官方仓库里找到预训练流水线,得把注意力转到 ms-swift 和 Transformers。
官方文档里对训练最有价值的是三类页面:MS-SWIFT 训练页面(给出 SFT / GRPO / Megatron-SWIFT 可运行样例)、Qwen3 Best Practices(think / no_think 数据格式、ignore_empty_think 等技巧)、Transformers 使用页面(环境版本要求与最小接入方式)。这三页建议先读,比直接啃源码省时间。
5. 框架层逐文件:从 CLI 到 Trainer 的完整链路
5.1 swift/cli/sft.py:命令行入口
这个文件很薄,职责是准备运行时、准备可选后端,然后调用sft_main()。伪代码大致是:
# 伪代码,示意结构 prepare_runtime() prepare_optional_backend() # 检查 --tuner_backend 是否用 unsloth from swift.pipelines import sft_main sft_main()它会尝试初始化单设备模式或 ray,检查--tuner_backend参数。你从命令行敲的swift sft ...最终落到这里。
5.2 swift/pipelines/train/sft.py:SFT 总控器
这是公开训练栈里最值得精读的文件,承担「单机 / 多机 SFT 训练总控器」角色。流程是:解析参数 → 构建模板 → 加载数据集 → 数据预处理 / packing → 构建 trainer → 启动训练 → 保存状态。
_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 怎么拼。这些属于模板层约束,不是权重。很多人微调 Qwen3 失败,不是优化器错了,而是模板没对上、非思考数据没做保护、packing 与模板不兼容。
_get_dataset()根据args.dataset/args.val_dataset调load_dataset,支持 split_dataset_ratio、数据乱序与分割,返回 train_dataset 和 val_dataset。数据来源统一接口:本地 JSON / JSONL / CSV、hub、多数据集混合、自动切训练验证。
_prepare_dataset()阶段让 template 把多轮对话编码成 token,用 EncodePreprocessor,需要时套 LazyLLMDataset,启用 packing 则用 PackingDataset 或 IterablePackingDataset。这是性能关键区:LazyLLMDataset 延迟编码避免全量预处理的内存压力;PackingDataset 把短样本拼成长序列提高 token 利用率;padding_free 进一步减少 padding 浪费。Qwen3 尤其依赖这些,因为 thinking 数据长、多轮格式复杂、长上下文开销大。
run()是总调度:准备数据集、统计参数、通过TrainerFactory.get_trainer_cls(args)选 trainer、构建 trainer、调self.train(trainer)、保存 checkpoint。整个体系是「配置驱动 + trainer 分发」。
5.3 swift/trainers/trainer_factory.py:训练器分发中心
文件短但地位高,维护两张映射表。TRAINER_MAPPING 把任务类型映射到 trainer 类:causal_lm → Seq2SeqTrainer,seq_cls → Trainer,embedding → EmbeddingTrainer,reranker → RerankerTrainer,grpo → GRPOTrainer,dpo / ppo / rm / kto / gkd 等 → 对应 RLHF trainer。TRAINING_ARGS_MAPPING 把任务类型映射到 training args 类:causal_lm → Seq2SeqTrainingArguments,grpo → GRPOConfig。
它把「训练方法」从主流程解耦,sft.py 不需要知道现在是不是 GRPO、embedding、reranker,只需要trainer_cls = TrainerFactory.get_trainer_cls(args)。Qwen3 训练不只 SFT,还有 DPO、GRPO 等 alignment 变体,有了工厂层就能统一抽象。
5.4 swift/template/templates/qwen.py:Qwen3 模板中枢
这是理解 Qwen3 hybrid thinking 的关键,不是外围小工具。模板层决定 thinking / non-thinking 怎么表达、assistant 的 think block 是否保留、query 控制标志如何生效、训练样本如何组织、推理时 response prefix 怎么拼。
Qwen3MixedTemplateMeta最重要的字段是non_thinking_prefix = '<think>\n\n</think>\n\n',和技术报告里的 thinking mode fusion 对齐。non-thinking 模式下 assistant 仍保留空 think block,好处是保持内部格式一致、避免模型把 non-thinking 理解成完全不同输出结构、让/no_think和 response prefix 更容易协作、mixed-mode 训练更稳定。如果直接去掉 think block,模型会学到两套回答外形,混合训练容易格式漂移;空 think block 相当于「保留骨架、缩掉思考内容」。
5.5 swift/trainers/rlhf_trainer/grpo_trainer.py: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 的 reasoning RL 偏向可验证问题的 RL,GRPO trainer 是公开生态里最接近这一思路的可运行入口。
5.6 Megatron 路线:MoE 与大模型训练加速入口
训练 Qwen3-30B-A3B 或更大 MoE 时,更重要的入口是megatron sft。关键文件路径:swift/cli/_megatron/sft.py、swift/megatron/pipelines/train/sft.py、swift/megatron/trainers/base.py、swift/megatron/trainers/trainer.py。结构是 CLI 入口 → Megatron SFT pipeline → Megatron trainer base → forward/backward schedule → 模型并行执行。
Qwen3 Best Practices 给的 MoE 示例命令里有几个关键参数:
--pipeline_model_parallel_size 2 --expert_model_parallel_size 8 --moe_permute_fusion true --moe_grouped_gemm true --sequence_parallel true --attention_backend flashpipeline_model_parallel_size把不同层切到不同 GPU 组;expert_model_parallel_size把不同专家切到不同设备组,对 MoE 至关重要;moe_grouped_gemm把多个专家的小矩阵运算做 grouped GEMM 融合提升吞吐;moe_permute_fusion优化 token 在专家间分发时的置换重排;sequence_parallel在长序列训练中摊薄显存压力。Qwen3-MoE 的重点不是模型文件怎么写,而是如何把专家并行、序列并行、流水并行、attention 优化和数据 packing 组合起来。
6. 模型定义层:Qwen3 结构真正落在哪
6.1 configuration_qwen3.py:配置对象
定义Qwen3Config,是所有模型实例化、保存、加载、导出的根配置。关键字段包括 vocab_size、hidden_size、intermediate_size、num_hidden_layers、num_attention_heads、num_key_value_heads、head_dim、max_position_embeddings、attention_bias、use_sliding_window、sliding_window、layer_types。它决定模型是 GQA 还是 MHA、是否启用 sliding attention、哪些层是 full 还是 sliding、attention 是否带 bias。想自己实现 mini-Qwen3 原型,这个文件是第一份蓝图。
6.2 modeling_qwen3.py:Dense 主实现
关键类逐个看。Qwen3RMSNorm实现 RMSNorm 替代 LayerNorm,对 deep decoder 更稳。Qwen3MLP采用 gate_proj / up_proj / down_proj 三层线性结构,对应标准 SwiGLU MLP。Qwen3Attention最值得看: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。Qwen3DecoderLayer是典型 pre-norm decoder block:residual → input_layernorm → self_attn → residual add → post_attention_layernorm → mlp → residual add。Qwen3Model负责 embedding、多层 decoder、final norm、rotary embedding、causal mask / sliding mask 生成。
6.3 modeling_qwen3_moe.py: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 路线的原因。
7. 可复制配置:SFT 与 GRPO 骨架
下面给一份 SFT 配置骨架,字段按 ms-swift 常见参数组织,你可以按自己环境改:
swift sft \ --model Qwen/Qwen3-8B \ --train_type lora \ --dataset your_data.jsonl \ --val_dataset your_val.jsonl \ --template qwen3 \ --num_train_epochs 3 \ --per_device_train_batch_size 2 \ --learning_rate 1e-4 \ --packing true \ --attn_impl flash_attn \ --loss_scale ignore_empty_think \ --output_dir ./output/qwen3-sftGRPO 入口骨架:
swift rlhf \ --rlhf_type grpo \ --model Qwen/Qwen3-8B \ --dataset your_rl_data.jsonl \ --reward_funcs accuracy \ --output_dir ./output/qwen3-grpo数据格式上,SFT 用 messages 数组,non-thinking 样本可以这样写:
{ "messages": [ {"role": "user", "content": "浙江的省会在哪? /no_think"}, {"role": "assistant", "content": "<think>\n\n</think>\n\n浙江的省会在杭州。"} ] }ignore_empty_think的本质是:对形如<think></think>的空 think block 不计算损失,避免模型被强迫学习「永远不思考」。非思考数据数量大时,直接当普通 teacher forcing 样本会让模型快速学到「think 里什么都不写才最优」,把 reasoning 能力磨掉。/no_think是从 query 侧显式控制模式,和ignore_empty_think可以单独用也可以组合。
8. 验证请求:确认脚本能跑通
配置改完,先别急着上大模型。用一个小模型和少量数据验证链路。第一步确认环境里 ms-swift 装好:
swift --version python -c "import swift; print(swift.__version__)"第二步用 0.5B 级别模型跑一个极小 SFT,只训几步看是否报错:
swift sft \ --model Qwen/Qwen3-0.6B \ --train_type lora \ --dataset your_data.jsonl \ --num_train_epochs 1 \ --max_steps 5 \ --per_device_train_batch_size 1 \ --output_dir ./output/smoke-test跑通后检查输出目录里有没有 adapter 权重和 trainer_state.json。第三步验证模型能加载并推理,用 TaoToken 的模型对话页 https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 发一条测试消息,确认服务侧正常;本地则用 transformers 加载刚训出的 adapter 做一次 generate,看输出格式是否符合模板预期。
如果你要长期做编码类任务或 Agent 训练,可以看 Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite ,把训练和调用串起来。
9. 本篇常见错排查
模板不匹配:报错里出现 template not found 或输出格式混乱,检查--template qwen3是否写对,以及 qwen.py 里的 non_thinking_prefix 是否被正确加载。Qwen3 的 hybrid thinking 对模板敏感,模板错了训练白跑。
packing 与 attention 不兼容:启用--packing true但没配--attn_impl flash_attn,会报 attention 实现相关错误。packing 改变 batch 中 token 排布,attention 层需要高效且兼容的实现。
显存爆掉:先降 per_device_train_batch_size,再考虑开 padding_free 或 LazyLLMDataset。长 thinking 数据尤其吃显存,packing 能提高利用率但不解决绝对峰值。
loss 不下降或 reasoning 退化:检查是否用了--loss_scale ignore_empty_think,以及非思考数据是否加了/no_think。这两者没配好,模型会学到「不思考」。
MoE 训练起不来:检查 expert_model_parallel_size 是否和实际 GPU 数匹配,moe_grouped_gemm 和 moe_permute_fusion 是否被当前后端支持。MoE 并行参数配错通常直接 OOM 或卡死。
Key 或接入报错:确认 base_url 是 https://taotoken.net/api ,Key 从 API Keys 页面 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 获取且未过期。接入细节看文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite 。
10. 按优先级读文件的顺序
如果时间有限,按这个顺序读:第一层先搞懂训练行为,看 Qwen3 Best Practices、MS-SWIFT 的 Qwen 页面、Command-line-parameters.md;第二层搞懂 SFT 主流程,看 swift/cli/sft.py、swift/pipelines/train/sft.py、trainer_factory.py;第三层搞懂模板与 hybrid thinking,看 qwen.py;第四层搞懂模型结构,看 configuration_qwen3.py、modeling_qwen3.py、modeling_qwen3_moe.py;第五层搞懂大模型 / MoE 训练,看 megatron 的 sft.py、base.py 和示例脚本参数组合。
自己实现原型时,最小可解释版本只需要 RMSNorm、RoPE、GQA、QK-Norm、SwiGLU MLP、Pre-Norm Decoder Layer、可选 Top-k Router + Sparse MoE block、简单的 thinking / non-thinking prompt 模板。不需要先实现 ZeRO、Megatron 并行、vLLM、GRPO 全训练环、expert grouped GEMM。先把核心 block 跑通,学习价值更高。
最后说句实话:很多人误判「Qwen3 已完整开源训练源码」,是因为技术报告、官方仓库、文档、训练示例、ms-swift、Megatron-SWIFT、Transformers 模型文件同时出现,视觉上很像全都在了。但更准确的结论是:Qwen3 已公开完整的模型权重、模型定义、推理接入与后训练接入栈,但并未公开一套可逐文件复现其内部全部预训练阶段的单体源码仓库。把这条链路理清,比纠结「为什么没有原厂预训练代码」有用得多。