Commit Graph

389 Commits (ba10c4d17ba41cfed4bab5cbea7b6561c1d1cc7e)

Author SHA1 Message Date
Linxiushen ba10c4d17b [fix] float16 下 attention mask 的 -1e9 溢出成 -inf,导致整条序列输出 NaN
Attention.forward 的手写 softmax 分支(flash SDPA 关闭时走这里):

    scores = (xq @ xk.transpose(-2, -1)) / math.sqrt(self.head_dim)
    ...
    if attention_mask is not None: scores += (1.0 - mask) * -1e9
    output = ... F.softmax(scores.float(), dim=-1) ...

scores 的 dtype 跟随 xq/xk。float16 模型下它是 float16,而
torch.finfo(torch.float16).min ≈ -65504,把 -1e9 累加进去会饱和成 -inf
(不是一个很大的有限负数)。当某个 query 在因果范围内可见的 key 全被 mask
掉时(左 padding 必然出现),softmax 整行 = NaN,并在下一层通过 K/V 投影
扩散到同序列里 mask=1 的有效 token 上。

.float() 加在 softmax 那一刻已经太晚——溢出发生在它之前。

修复:把 float32 提升提前到加 mask 之前,两处共 2 行。
fp32/bf16 路径数值等价(fp32 下原来的 .float() 本就是 no-op)。
2026-09-20 11:50:28 +08:00
jingyaogong cc312c1cc6 [fix] unify Ctrl+C handling 2026-09-18 16:33:09 +08:00
jingyaogong e2ee878519
Merge pull request #857 from wbbeyourself/fix-ctrl-c-exception
fix: eval_llm.py Ctrl+C 退出异常修复
2026-09-18 15:54:43 +08:00
jingyaogong b63a9565e3 [fix] restore top-1 router gradient #858 2026-09-18 15:28:50 +08:00
jingyaogong 1aae25911b
Merge pull request #859 from basil-k-aji-dev/fix/moe-router-gradient-topk1
[fix] keep the MoE router trainable at num_experts_per_tok=1
2026-09-18 15:03:36 +08:00
basil-k-aji-dev 1c876435ef [fix] keep the MoE router trainable at num_experts_per_tok=1
Normalising a single top-k weight by its own sum gives exactly 1.0 for every
token, so the gate leaves the graph entirely: topk_idx is a discrete index and
the weight is now a constant, which leaves the LM loss no differentiable path
to the router. It then trains on aux_loss alone, whose optimum is a uniform
distribution, and the experts never specialise.

Measured on MOEFeedForward with router_aux_loss_coef=0, so only the LM path can
contribute a gradient:

  num_experts_per_tok=1, norm_topk_prob=True   7.02e-10   <- current default
  num_experts_per_tok=1, norm_topk_prob=False  1.02e-02
  num_experts_per_tok=2, norm_topk_prob=True   1.67e-02

Only normalise when there is more than one weight to normalise.

Note this changes the forward pass for existing num_experts_per_tok=1 MoE
checkpoints: the expert output was scaled by a constant 1.0 and is now scaled
by the gate probability.

Closes #858.
2026-09-17 21:31:41 +05:30
wbbeyourself 9fa620e2e5 fix: eval_llm.py Ctrl+C 退出异常修复 2026-09-16 17:47:55 +08:00
jingyaogong 7a9137d2e9 [update] trim verbose ddp comments 2026-09-15 14:53:11 +08:00
jingyaogong 7988bc81a3
Merge pull request #855 from basil-k-aji-dev/perf/ddp-followups
[perf] skip the per-forward RoPE buffer broadcast in the RL trainers
2026-09-15 14:51:37 +08:00
basil-k-aji-dev 37ac206e9a [perf] skip the per-forward RoPE buffer broadcast in the RL trainers
Follow-up to the review on #854.

DDP re-broadcasts every registered buffer from rank 0 on each forward. The only
buffers here are freqs_cos / freqs_sin, which each rank computes deterministically
from config and never mutates from data, so the broadcast moves identical bytes
every step for nothing.

Verified with a two-rank CPU/Gloo run: with broadcast_buffers=False the
gradients stay identical across ranks and so do the buffers.

Also document the critic's tied-embedding assumption. CriticModel.forward never
calls lm_head, which is only safe under DDP because tie_word_embeddings (default
True) makes lm_head.weight the same Parameter as embed_tokens.weight. Untied, it
becomes a genuinely unused parameter and DDP raises.
2026-09-14 22:22:00 +05:30
jingyaogong 21ec325dba [update] simplify safe math eval 2026-09-14 23:55:32 +08:00
jingyaogong cdf0a93e02
Merge pull request #847 from a0917-cell/fix/safe-math-eval
[fix] 用 AST 求值器替换工具里的 eval(),并修复 Windows 上工具调用全部静默失败
2026-09-14 23:34:28 +08:00
jingyaogong c367572702
Merge pull request #854 from basil-k-aji-dev/fix/rl-ddp-grad-sync
[fix] route RL trainer forward through DDP so gradients all-reduce
2026-09-14 22:28:03 +08:00
basil-k-aji-dev 9c088dd3a5 [fix] route RL trainer forward through DDP so gradients all-reduce
train_grpo.py, train_ppo.py and train_agent.py wrap the policy in
DistributedDataParallel but run the loss-bearing forward through
.module, bypassing the wrapper. DDP arms its gradient all-reduce hooks
inside DistributedDataParallel.forward(), so calling .module directly
means backward() performs no all-reduce: every rank steps on purely
local gradients and the replicas silently diverge. Only rank 0 is
saved, so multi-GPU RL training quietly degrades to single-GPU
training on 1/N of the data with no error.

The supervised trainers are unaffected; they already call the wrapped
module. no_grad uses of .module (rollout generation, checkpoint
saving) are left untouched, where unwrapping is correct.

Single-GPU behaviour is unchanged: with no process group, model is the
bare module and these calls are identical to before.
2026-09-14 14:54:07 +05:30
jingyaogong a3c7b01cc0 [fix] keep agent rollout token-aligned #850 2026-09-10 11:44:05 +08:00
tkgcc 0f6803e551 [fix] replace tool eval() with an AST math evaluator
execute_tool() relied on signal.SIGALRM, which does not exist on Windows.
The AttributeError was swallowed by a bare except, so every tool call
silently returned None and the model always observed
{"error": "tool not found"} (issue #846).

calculate_math also ran eval() on model-generated text. Two of the three
call sites (scripts/eval_toolcall.py, scripts/web_demo.py) passed no
globals at all, leaving full builtins reachable from sampled output.

safe_math_eval() in trainer_utils.py parses the expression with ast and
walks it, allowing only arithmetic operators and a math whitelist, with
caps on expression length and exponent size. It cannot loop forever, so
the signal-based timeout is no longer needed and is removed. Both sqrt(x)
and math.sqrt(x) spellings keep working.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 07:53:33 +08:00
jingyaogong 6fc918beb6 [update] remove expert args 2026-09-04 22:16:38 +08:00
jingyaogong 4bd6062ead
Merge pull request #836 from JustinGuese/moe-cli-flags
Expose num_experts / num_experts_per_tok / seed on the trainer CLIs
2026-09-04 22:10:18 +08:00
jingyaogong 4d7a74acab
Merge pull request #840 from JustinGuese/readme-benchmark-resolution
docs: state the measurement resolution of the objective benchmark table
2026-09-04 22:10:00 +08:00
Justin Guese 77946fda00 [docs] 在客观评测表下补充各数据集的测量分辨率
lm_eval 对每个指标都会输出 stderr,但表格只保留了点估计。这里按测试集
大小给出各任务的 ± 标准误(obqa ±1.9 到 cmmlu ±0.4),并说明比较两个
模型时差值的标准误约为单项的 √2 倍,方便读者判断表中哪些差距是可以
解读的。中英文 README 同步。
2026-09-03 17:10:52 +07:00
Justin Guese fc585a9bf9 [update] 把随机种子暴露到命令行
trainer 里的种子此前硬编码为 42(setup_seed(42 + rank) 与每轮的
setup_seed(42 + epoch)),要跑多种子实验只能改源码。新增 --seed,
默认 42,与改动前完全一致。
2026-09-03 15:36:14 +07:00
Justin Guese c3199c7240 [update] 把 num_experts / num_experts_per_tok 暴露到命令行
此前要改专家数只能去编辑 model_minimind.py。三个入口
(train_pretrain / train_full_sft / eval_llm)的默认值与 MiniMindConfig
一致(4 / 1),默认行为不变;RL 与 agent 相关的 trainer 不动。
2026-09-03 15:13:29 +07:00
jingyaogong 7a6fddd63a [update] readme 2026-08-31 18:08:05 +08:00
jingyaogong c9a8ab4632 [update] dependency version 2026-08-31 17:54:37 +08:00
jingyaogong e84156818a [update] dependency version 2026-08-29 15:12:28 +08:00
jingyaogong d65ef2c00e [update] readme content 2026-08-21 16:49:00 +08:00
jingyaogong ed5ea9e02a [update] readme content 2026-08-21 16:30:30 +08:00
jingyaogong eabad706da [update] readme content 2026-08-21 16:25:20 +08:00
jingyaogong 393e387e9a [update] supporter charts 2026-08-06 22:07:29 +08:00
jingyaogong 89d674b8a5 [refactor] PPO cleanup 2026-07-23 11:11:05 +08:00
jingyaogong 2d4c385b0f [fix] PPO rollout mode
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 11:05:51 +08:00
jingyaogong e9f46506da
Merge pull request #814 from FloatFrank/fix/ppo-logp-autocast-align-v3
[fix] PPO: align mb_resp_logp with old_resp_logp under autocast to stabilize training
2026-07-23 10:32:06 +08:00
FloatFrank 1191fc8e9f [fix] PPO: align mb_resp_logp with old_resp_logp under autocast
Move log_softmax for mb_resp_logp inside autocast_ctx so it is upcast
to fp32, matching the rollout path (compute_per_token_logps runs under
no_grad+autocast). Previously log_softmax ran outside autocast on
fp16/bf16 logits, introducing a ~1e-2 systematic bias between
mb_resp_logp and old_resp_logp, so ratio != 1 and KL != 0 even before
any weight update. Under sparse rule-based rewards (e.g. math PPO)
this bias destabilises training.

Also add:
- --rollout_eval_mode (default 1): switch actor to eval during rollout
  to disable dropout and keep old/new logp consistent.
- --debug_log_ratio: optional diagnostic printing |mb-old| on the first
  minibatch to verify ratio ~= 1.
2026-07-21 18:51:42 +08:00
jingyaogong 512eed0b65 [fix] robustness 2026-06-28 18:03:34 +08:00
jingyaogong 3f1a7cc25b [fix] ddp exit hang 2026-06-01 17:50:39 +08:00
jingyaogong 4a68da72d5 [fix] lora dims 2026-05-31 13:38:51 +08:00
jingyaogong 4497610ec0 [fix] issue#771 2026-05-19 17:40:03 +08:00
jingyaogong 9da8e1ab18 [update] requirements 2026-05-16 18:08:37 +08:00
jingyaogong dddedc6881 [fix] repetition_penalty 2026-05-07 19:08:52 +08:00
jingyaogong 802c15b2b4 [feat] reduce RL memory 2026-05-06 15:07:28 +08:00
jingyaogong e73a407f7a
Merge pull request #759 from TKiteRunner/fix/grpo-oom-reorder-rewards
fix: resolve CUDA OOM in train_grpo.py on GPUs with <=8GB VRAM
2026-05-06 15:00:17 +08:00
TKiteRunner 10776417aa fix: resolve CUDA OOM in train_grpo.py on GPUs with <=8GB VRAM 2026-05-06 14:14:15 +08:00
jingyaogong 5020dc9dd4 [update] readme 2026-05-06 13:41:46 +08:00
jingyaogong bdee223036 [fix] inference bug 2026-05-03 20:48:48 +08:00
jingyaogong 06d882e4ef [update] readme 2026-05-01 12:06:47 +08:00
jingyaogong da865af63d [update] readme 2026-04-28 17:22:25 +08:00
jingyaogong 773e451b11 [fix] bugs 2026-04-27 19:16:08 +08:00
jingyaogong 6361510016 [fix] rollout bugs 2026-04-27 17:54:09 +08:00
jingyaogong d4c6bc5c7e [update] readme 2026-04-27 10:59:41 +08:00
jingyaogong 24896cd2c4 [update] readme 2026-04-24 20:16:06 +08:00