Skip to content

feat: add experimental Qwen3.8-Flash-Next post-training support - #502

Draft
ruijieguo wants to merge 45 commits into
alibaba:mainfrom
ruijieguo:feat/qwen38-flash-next-training
Draft

ruijieguo wants to merge 45 commits into
alibaba:mainfrom
ruijieguo:feat/qwen38-flash-next-training

Conversation

@ruijieguo

@ruijieguo ruijieguo commented Sep 27, 2026 •

Copy link
Copy Markdown

What this changes

Qwen3.8-Flash-Next needs its GR residual streams, PLE external N-gram table, QSA attention and hybrid GDN layers preserved throughout training, checkpointing and rollout. This PR adds the model adapter and the ROLL/runtime paths for frozen-table backbone training with CPU optimizer offload, LoRA SFT/RL/OPD, save/resume, and teacher/reference handling.

Numerical fixes included: native GR FP32 FMA and BF16 materialization with the padded GEMM geometry; the router keeps the checkpoint's model-dtype projection unless FP32/FP64 is requested explicitly; SFT honors explicit step limits; Flash-Next LoRA workers use a single K partition for the dense Triton LoRA shrink, which removes nondeterministic FP32 atomic accumulation (scoped to this model type; it does not enable global batch invariance).

Rebase onto upstream v0.4.0

The branch now contains alibaba/ROLL v0.4.0 (581046a) as a merge, so it no longer conflicts with main. 16 files conflicted; roll/third_party/megatron/offload_states_patch.py was re-expressed on upstream's new backend-based offload store.

Re-running the real 8-GPU paths on the merged tree found regressions that unit tests did not. All are fixed in this branch:

  • Grouped expert LoRA rank. Upstream dropped r // moe_router_topk; restored, so expert adapters are rank 6 for r=64 and topk=10 as this branch's checkpoints and export expect. The 2-rank grouped-LoRA test went from 4 failed to 6 passed.
  • moe_permute_fusion default. The new TrainingArguments default False overrode the model config's True and moved the frozen-reference sentinel by up to 0.35 nats across data-parallel ranks. It now defaults to None; an explicit value still wins.
  • CPU-master offload. Parked parameters keep full-shaped zero-storage views, Hybrid fp16 shards are rebound, and checkpoint loading hands the offload backend to the leaf optimizers.
  • Rollout dumps. NonTensorStack columns made every dump file empty under the now-default TransferQueue backend (reproduces on pristine v0.4.0). Fixed.
  • Upstream defect, fixed in 4725516. roll/pipeline/rlvr/rewards/__init__.py eagerly imports Geo3kRewardWorker, which needs mathruler, declared in no requirements file, so RLVR jobs abort in an offline environment. Replaced by a PEP 562 lazy export with tests/pipeline/test_rewards_lazy_exports.py.
  • vLLM expert-parallel dev builds are judged by capability instead of the release tuple; SFTWorker honors auto_resume; stale fixtures updated.

Upstream defaults that now apply to Flash-Next runs: use_sequence_packing is True by default and Flash-Next Megatron roles reject packed sequences, so the configs set it to false; transfer_backend defaults to TransferQueue; pure_opd_pipeline_type resolves to "rlvr" in pure-OPD mode. Test failures shared with pristine v0.4.0 (10 of 20 upstream offload-state variants, multimodal beam search) or with the pre-merge branch (hybrid-Adam padding) are not from this merge.

Validation on the merged tree (8 x H800, 67c67e8)

The head 4725516 differs from 67c67e8 only in test files and the lazy-export fix above.

Job Result Key evidence
LoRA SFT, 6 updates, EP8, 8K passed run.exit=0, all seven checks; train loss 2.40 → 1.78; adapter ranks 64 / 6 as before
SFT cold resume from checkpoint-3 bit-exact failure_count: 0 over 408,806 tensor leaves and 297,936 optimizer items
GRPO, 20 updates, LoRA student, seed 70 passed driver and independent verifier exit 0; 20 updates on each of 8 ranks; reference and backbone unchanged across 21 versions; 344 of 344 N-gram table checks
LoRA OPD, 20 updates, rank-64 student passed 20 updates on each of 8 ranks, 52 effective prompt groups, reference and frozen backbone unchanged across 21 versions; teacher is the rebuilt opd-teacher-v3, not the one of the earlier verified run
Full-backbone RL, 20 updates passed on a clean host run.exit=0; independent verifier exit 0: 8 ranks × 20 updates, 46 prompt groups, frozen reference unchanged
Full-backbone OPD, 20 updates 12 of 20, then the job's 6 h timeout (exit 124, not memory) cleared the same step-1 boundary; teacher probe unchanged over 13 versions, student changed every version, 112 of 112 N-gram checks; steps 1 onward ran about 3.8× slower than the pre-merge pass for a reason not yet determined. Not a 20-update pass
Two-node LoRA SFT, two hosts over InfiniBand ran 4+4 GPUs: 6 of 6 updates twice, bit-identical between runs; 8+8 GPUs: 6 of 6. The driver exits 1 only because its checkpoint inspection cannot see the other node's RNG files; the merged checkpoint passes the validator's contract
HF adapter export of SFT checkpoint-5 (CPU) matches the earlier export 148,808 tensors; no reload or inference on this export
Env-gated Megatron CUDA suites passed 41 + 12 cases, plus the grouped expert LoRA test on each rank
Eight-rank suites 16 passed / 2 failed the examined failure depends on the convolution-patched Megatron checkout, not on this code

Notes:

  • Full-backbone RL and OPD were first killed at the start of step 1 on the original validation host by Ray's memory monitor (0.97 of 2015.5 GiB). The same RL job passed on a second, idle host, and worker-side memory traces of all four runs agree on total consumption to within 1%, so the kills come from host memory headroom (Ray processes left by earlier sessions and other tenants), not from the merge. On a 2 TiB host this job needs at least about 1,810 GiB of MemAvailable at launch.
  • GRPO uses seed 70 because with seed 42 one step drew only responses that hit the 128-token cap; the pipeline's existing skip guard skipped that update and the driver's end-of-run check, which expects an update every step, failed. Only the validation driver's seed changed; validator and verifier are untouched.
  • The two-node runs are not bit-identical to the 2026-10-01 single-node run (lora_B relative L2 about 0.15), but fresh single-node controls on both hosts differ from it by the same amount, so the two-node split is not the cause. The remaining candidate is the container network and InfiniBand device difference. This is an environment finding, not a code change.
  • These runs write no checkpoint and show lifecycle behavior only, not convergence, numerical parity or checkpoint acceptance.

Pre-merge validation (September 27, H800): 58 GR tests including exact native BF16 forward comparisons and FP64 derivative checks; router tests against real Megatron gates; the LoRA SFT save and restore lifecycle (checkpoint-3 → updates 4–5 → checkpoint-5 at e6de032); 2-update full-backbone RL and OPD probes on all 8 ranks; LoRA adapter export with exact native reload and sleep/wake on 8 EP ranks after the shrink fix (before it, identical requests drifted by up to 2.94); a TP2/EP8 capacity run at 72.05 GiB per GPU; and 16 deterministic-shrink CUDA regressions at 37e5756. Lifecycle evidence, not convergence or numerical acceptance.

Remaining acceptance gates

  • A full 20-update full-backbone OPD pass on the merged tree.
  • Full-model native probability parity still fails at atol=rtol=0.02. Fixing native prefill chunks to 2,048 tokens gives a stable native reference, but actor/native parity still fails; the tolerance has not been relaxed.
  • Checkpoint and save/resume numerical parity for full-backbone training, and export acceptance (the historical continuation comparison reported 864 FP32 alignment-gap differences).
  • Workload-level throughput of the deterministic LoRA shrink; the kernel microbenchmark is 1.01 to 2.10× the native selection, geometric mean 1.22.
  • External N-gram validation does not hash every payload byte, so referenced model assets must stay immutable during a run; N-gram tables remain frozen in this scope.

Per-step timings, memory traces and verifier receipts are kept in a separate validation log.

🤖 Generated with Claude Code

Add Qwen hybrid architecture, bounded RL statistics, CPU-offloaded full-backbone training, frozen N-gram lifecycle, distributed checkpoint integrity, and SFT/RL/OPD validation coverage.
@ruijieguo ruijieguo changed the title feat: add Qwen3.8-Flash-Next post-training support feat: add experimental Qwen3.8-Flash-Next post-training support Sep 27, 2026
@ruijieguo
ruijieguo marked this pull request as draft September 27, 2026 06:18
ruijieguo and others added 14 commits September 27, 2026 15:00
qsa_indexer_temperature defaulted to 1.0, but the HF reference divides the
summed relu(qk) indexer score by sqrt(index_head_dim) before both top-k
selection and the KL target. Top-k is scale-invariant, so this only mattered
for indexer_distillation_loss: every shipped SFT/RL/OPD config left the
default in place, making the trained indexer's KL target ~sqrt(128)=11.3x
sharper than the reference calibration -- the design spec explicitly flagged
this as a value that must not be silently conflated.

qsa_indexer_temperature is now Optional[float] = None; Qwen4ExpConfig
resolves an unset value to qsa.default_indexer_temperature(indexer_head_dim)
in __post_init__ (falling back to 1.0 when QSA is not configured at all), and
still honors and validates an explicit override. Verified on .181: the new
config-level regression (test_qwen4_exp_qsa_indexer_temperature.py) passes
under the real Megatron/TE environment, and the full local CPU-runnable
qwen4_exp suite is unaffected.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Resolve 16 conflicts against alibaba/ROLL v0.4.0 (581046a), keeping the
Qwen3.8-Flash-Next adaptations on top of upstream's new designs:

- offload_states_patch.py: port onto upstream's backend-based offload store
  (put_tensors/get_tensors/delete_tensors). Re-express CPU-master model
  offload, HybridDeviceOptimizer phase handling, grad-buffer release/restore
  and checkpoint-failure frame clearing as layers over the backend API.
  offload_adam_states tolerates the legacy (optimizer, device) call.
- megatron_strategy.py: load_states/offload_states keep include_frozen_parameters
  and CpuMasterWeightProvider on upstream's backend flow; streaming checkpoint
  save strategy retained (bounded memory for full-backbone checkpoints).
- vllm: keep dev-build-safe compat dispatch (call_maybe_await, signature-driven
  vllm_utils, ray_distributed_executor), adopt upstream headless/mp paths plus
  Qwen3.8 GDN backend and frozen-ngram loading hooks.
- user_defined_rollout_loop.py: re-inject per-sample sampling_params provenance
  into upstream's _default_token_postprocess; keep module-level wrapper.
- protocol.py / upload_utils.py / context_managers.py / model_update.py: keep
  both sides' additions (timeout sentinel + strip_multi_modal_for_reward,
  _link_or_copy + register(), NCCL suspend/resume, weight_provider + convert_kwargs).
- sft_worker.py: upstream dispatch (DP_MP_COMPUTE, prefetch) plus torch.no_grad.
- tests: chained-optimizer fixture gains the backend attributes upstream requires.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- vllm: dev builds expose the modern Ray executor but no legacy "<pkg>.v1"
  package; bind CustomRayDistributedExecutor as the v1 executor directly
  instead of importing a module that does not exist.
- sft_worker: honor upstream's auto_resume alongside resume_from_checkpoint
  (latest checkpoint first, explicit path as fallback), matching BaseWorker.
- tests: supply the new required config fields (auto_resume,
  reward_system_config) and attach an explicit offload backend to the real
  optimizers the gated Hybrid phase tests build.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… store

- offload_states_patch: rebind Hybrid float16 shards onto the parked DDP
  buffer so old CUDA allocations are released; in CPU-master mode park
  full-shaped zero-storage views so shard validation still passes while the
  model is parked; checkpoint_grad_buffer_offload hands each leaf the
  backend and key prefix it needs.
- megatron_strategy: load_checkpoint attaches the offload backend and key
  prefix to the optimizer before releasing gradients.
- tests: resume/LoRA-phase fixtures supply the backend, strategy_args and
  the now-required parametrized arguments.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- asset lifecycle: the fake config exposes use_value_head and the fake
  converter streams tensors through iter_mca_state_dict_from_hf, the API the
  per-parameter loader now calls.
- RL statistics: inner_forward_step reads strategy.model.config for router
  replay; stub it and the R2 record probe.
- beam search: stub roll.third_party.vllm.compat.call_maybe_await, which
  vllm_strategy now imports.

Two failures remain in these files and are not caused by the merge: the
hybrid-Adam padding check in test_checkpoint_write_memory fails identically
on the pre-merge branch, and the beam-search multimodal DataProto ndarray
assertion fails identically on pristine upstream v0.4.0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ream merge

Upstream v0.4.0 dropped the per-expert rank division in the grouped row and
column LoRA layers, but this branch's checkpoints, validators and export
tests all rely on expert adapters carrying rank r // topk (6 for r=64,
topk=10) while shared modules keep r.

Restored at both sites. On 2 H800 ranks the real grouped-LoRA Megatron/TE
test failed 4 of 6 cases without it and passes 6 of 6 with it. The 8-GPU LoRA
SFT validation had also failed its native rank check on the merged tree:
expert tensors were saved at rank 64 where the verified checkpoints use 6.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ability

Upstream's gate compares the release tuple, which rejects development builds
reporting 0.1.devN even though they expose the modern Ray executor API. Judge
dev builds by capability, matching roll/third_party/vllm/__init__.py, and add
a regression test; released versions below 0.16 are still rejected.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
With the TransferQueue backend now on by default, materialized batches carry
NonTensorStack columns that the dump process cannot json-encode, so every
rollout dump file came out empty (TypeError in the writer process). Convert
anything exposing tolist(), not just ndarrays. The regression test fails the
same way on pristine upstream v0.4.0 and passes with the change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Upstream v0.4.0 added TrainingArguments.moe_permute_fusion defaulting to
False. update_with_args writes any non-None argument over the model config,
so every Flash-Next run silently lost Qwen4ExpConfig's True default. That
swaps TE's deterministic FP32 top-k combine for an unfused BF16 scatter_add,
and the GRPO frozen-reference sentinel then differed by up to 0.35 nats
across data-parallel ranks (bitwise equal before the merge), failing the
run's own check. Default the argument to None so the model default survives;
an explicit True or False still overrides. The new test fails on the merged
default and passes with this change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
vllm_strategy asserts torch.distributed is not initialized, which fails when
earlier tests in the same pytest process leave a process group behind. Patch
the check in the new test, as the sweep showed it failing only in that order.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Upstream v0.4.0 added ModelConfig.use_value_head and post_converter now
reads mca_config.use_value_head on both the weight and the metadata path.
Our two hand-built SimpleNamespace config stubs predate that field, so
collecting either file raised AttributeError before any assertion ran.

Add the field with the upstream default. On an 8xH800 node this takes the
LoRA conversion suite to 12 passed and streaming export to 8 passed plus 2
CPU skips, 10 passed with the native vLLM gate on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Upstream v0.4.0 added two eager re-exports to the rewards package, and one of
them, Geo3kRewardWorker, imports mathruler at module scope. mathruler is not
installed by the base image and is declared in no requirements file, so
importing roll.pipeline.rlvr.rewards raises ModuleNotFoundError.

base_pipeline.create_clusters_parallel pre-imports each cluster's worker by
path, which imports that package, so every RLVR pipeline now aborts with
"Failed to pre-import worker class" no matter which reward worker it
configured. Three Flash-Next validation runs died this way while asking only
for MultipleChoiceBoxedRuleRewardWorker, which has no such dependency.

Resolve the geo3k export lazily through PEP 562 __getattr__. The attribute
stays importable and __all__ still advertises it, so a run that wants the
worker gets it, and a run that wants mathruler still sees its own
ModuleNotFoundError. The new test covers both directions; it errors on
collection before this change and passes after. It also makes upstream's own
gsm8k reward test collectable, which exposes a separate pre-existing failure
in that file that this change does not address.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ruijieguo added a commit to ruijieguo/ROLL that referenced this pull request Oct 14, 2026
…0.4.0+

Brings in the full history of alibaba/ROLL PR alibaba#502 (Qwen3.8-Flash-Next
training, head 4725516) on top of upstream main (d96d0cc, v0.4.0 plus two
later fixes). The PR range already contains alibaba/ROLL PR alibaba#497 (Qwen3.6-27B
hybrid attention training fix, bd6335b).

Both PRs are still open upstream; this repository keeps them usable now.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant