Skip to content

[cfg, recipe, tests] feat: add MMK12 DAPO recipe on V1 omni loop (#446 Phase 4) - #541

Draft
OnePunchMonk wants to merge 11 commits into
verl-project:mainfrom
OnePunchMonk:dapo-p4-mmk12-recipe
Draft

[cfg, recipe, tests] feat: add MMK12 DAPO recipe on V1 omni loop (#446 Phase 4)#541
OnePunchMonk wants to merge 11 commits into
verl-project:mainfrom
OnePunchMonk:dapo-p4-mmk12-recipe

Conversation

@OnePunchMonk

Copy link
Copy Markdown
Contributor

Summary

Implements Phase 4 of #446 (Qwen3-Omni Thinker DAPO): applies the Phase 1-3
DAPO contract to a second modality/dataset, MMK12 math reasoning.

Stacked on #540 (Phase 3), which is stacked on #502 (Phase 2), which is
stacked on #456 (Phase 1) — none merged yet.
This branch is built on top of
dapo-p3-dynamic-sampling, so the diff against main includes all three
PRs' commits. Please review only the commit on top
(feat: add MMK12 DAPO recipe on V1 omni loop (#446 Phase 4)) until the
earlier phases land; I'll rebase and shrink the diff as each merges.

What's actually wired

Per #446's non-goals, this is explicitly not a new adapter or reward path —
it reuses the existing mmk12_reward.py scorer and
examples/gspo_trainer/data_process/mmk12.py data pipeline (already used by
the GSPO MMK12 recipe) and combines them with the DAPO policy/reward
contract from Phases 1-3:

  • Adds examples/dapo_trainer/qwen3_omni/run_qwen3_omni_thinker_dapo_lora_mmk12_v1.sh:
    same vanilla clip-higher / token-mean / GRPO / no-KL policy settings as the
    AVQA dynamic-sampling launcher, algorithm.filter_groups.enable=true, and
    the overlong buffer sized for MMK12's longer 12288-token max response
    (overlong_buffer_cfg.len=1024 vs AVQA's 128, scaled to the same ~8% of
    max_response_length).
  • Adds test_dapo_mmk12_example_launcher_has_phase_four_contract mirroring
    the existing AVQA contract tests.
  • Documents the recipe in examples/dapo_trainer/README.md.

Test plan

CPU (all green locally):

python3 -m pytest tests/utils/test_qwen3_omni_dapo_launcher_on_cpu.py -q

Not yet run: any GPU e2e on real MMK12 data or a tiny-random smoke. I
don't have further Modal/GPU access or the MMK12 dataset in this pass, so the
overlong_buffer_cfg.len=1024 sizing is a scaled estimate from the AVQA
value, not empirically tuned — flagging this explicitly. This PR stays in
draft until a GPU run validates it and until the earlier phases land
underneath it.

AI usage disclosure

Claude Code was used to derive this recipe from the existing AVQA DAPO
launchers and the GSPO MMK12 recipe, and to write the test above. A human
submitter (onepunchmonk) will review every changed line and run a GPU
validation before taking this out of draft.

WenzheWang and others added 11 commits August 28, 2026 15:38
Signed-off-by: Wenzhe Wang <w_wenzhe@163.com>
Signed-off-by: Wenzhe Wang <w_wenzhe@163.com>
Signed-off-by: Wenzhe Wang <w_wenzhe@163.com>
Signed-off-by: Wenzhe Wang <w_wenzhe@163.com>
Signed-off-by: Wenzhe Wang <w_wenzhe@163.com>
Assisted-by: AI tooling
Signed-off-by: Wenzhe Wang <w_wenzhe@163.com>
Assisted-by: AI tooling

Signed-off-by: Wenzhe Wang <w_wenzhe@163.com>
…i loop (verl-project#446 Phase 2)

Phase 1 (verl-project#456) left the overlong reward buffer disabled everywhere; verl's
registered DAPORewardManager already reads reward.reward_kwargs.overlong_buffer_cfg
and reward.reward_kwargs.max_resp_len off the config, but verl_omni's reward.yaml
never declared reward_kwargs, so any override there was silently dropped for the
autogenerated trainer configs.

- Add reward.reward_kwargs (overlong_buffer_cfg + max_resp_len) to reward.yaml
  and regenerate the four _generated_*.yaml trainer configs.
- Enable overlong shaping in the DAPO tiny-random smoke test
  (reward.reward_manager.name=dapo path only; the naive-manager AVQA example
  is unaffected and documented as such).
- Add a CPU test that drives DAPORewardManager directly and asserts the
  overlong penalty changes the reward on a truncated dummy response — the
  Phase 2 exit criterion from verl-project#446.
- Split the shared launcher-contract test helper so the "no overlong" check
  only applies to the naive-manager example, and add overlong-specific
  assertions for the dapo-manager smoke test.

This does not touch dynamic sampling (Phase 3) or the reward-loop metrics
plumbing beyond what DAPORewardManager already logs in reward_extra_info.

Draft: opened for early feedback while GPU LoRA validation on real
Qwen3-Omni-30B-A3B-Instruct + gsm8k is still pending (see PR description).

Co-authored-by: Claude Code
Co-authored-by: Claude Code
…op (verl-project#446 Phase 3)

Confirms the upstream V1 PPOTrainer replay buffer already implements group
filtering, so Phase 3 is config-only: adds a dynamic-sampling AVQA launcher
with algorithm.filter_groups.enable=true/metric=acc on the streaming DAPO
reward path, plus a CPU launcher-contract test.
…l-project#446 Phase 4)

Applies the Phase 1-3 DAPO contract (token-level clip-higher, dynamic
sampling, overlong shaping) to a second modality, MMK12 math reasoning,
reusing the existing mmk12_reward.py scorer and data pipeline. Adds a CPU
launcher-contract test mirroring the AVQA one.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The docs toctree references a missing examples/dapo_trainer.md page and a new CPU test uses AutoTokenizer.from_pretrained("gpt2"), which can break CI by requiring network access.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR extends the Qwen3-Omni Thinker DAPO “config + recipe” stack to a second dataset/modality (MMK12), while also wiring the shared DAPO config contract (overlong reward kwargs + dynamic sampling knobs) into the omni trainer config and adding CPU contract tests.

Changes:

  • Add DAPO launchers for AVQA (phase-1 baseline), AVQA + dynamic sampling (phase-3), and MMK12 + dynamic sampling + overlong shaping (phase-4).
  • Plumb reward.reward_kwargs (overlong buffer config + max_resp_len) into the omni reward config and regenerate trainer YAMLs.
  • Add CPU tests to validate the launcher/config “DAPO contract” and (directly) the DAPO overlong penalty behavior.
File summaries
File Description
verl_omni/trainer/config/reward/reward.yaml Adds reward.reward_kwargs so DAPO reward manager can receive overlong-buffer settings.
verl_omni/trainer/config/algorithm.py Updates OmniAlgoConfig to inherit upstream AlgoConfig so online/DAPO fields survive structured config conversion.
verl_omni/trainer/config/_generated_omni_trainer.yaml Regenerated to include reward.reward_kwargs defaults.
verl_omni/trainer/config/_generated_omni_megatron_trainer.yaml Regenerated to include reward.reward_kwargs defaults.
verl_omni/trainer/config/_generated_diffusion_veomni_trainer.yaml Regenerated to include reward.reward_kwargs defaults.
verl_omni/trainer/config/_generated_diffusion_trainer.yaml Regenerated to include reward.reward_kwargs defaults.
tests/workers/config/test_omni_config_on_cpu.py Adds assertions that OmniAlgoConfig is an AlgoConfig and that inherited online fields can be set via Hydra.
tests/utils/test_qwen3_omni_dapo_launcher_on_cpu.py Adds “launcher contract” tests for phase 1/3/4 DAPO scripts and the tiny-random smoke script.
tests/utils/test_dapo_overlong_reward_on_cpu.py Adds a CPU unit test asserting overlong penalty changes reward with DAPORewardManager.
tests/special_e2e/run_dapo_qwen3_omni_thinker_lora_v1_smoke.sh Adds a tiny-random GPU smoke script for DAPO + overlong shaping (no dynamic sampling).
examples/dapo_trainer/README.md Documents the phased DAPO recipes and how they map to AVQA/MMK12.
examples/dapo_trainer/qwen3_omni/run_qwen3_omni_thinker_dapo_lora_v1.sh Adds phase-1 AVQA DAPO launcher (no dynamic sampling, naive reward manager).
examples/dapo_trainer/qwen3_omni/run_qwen3_omni_thinker_dapo_dynamic_sampling_lora_v1.sh Adds phase-3 AVQA launcher with filter_groups enabled and streaming reward path via DAPO manager.
examples/dapo_trainer/qwen3_omni/run_qwen3_omni_thinker_dapo_lora_mmk12_v1.sh Adds phase-4 MMK12 launcher reusing mmk12 reward + overlong shaping + dynamic sampling.
docs/index.md Adds a Sphinx toctree entry for a DAPO example docs page.
Review details

Suppressed comments (1)

tests/utils/test_dapo_overlong_reward_on_cpu.py:51

  • Avoid from_pretrained("gpt2") here (Hub download). Build a minimal local tokenizer and pass that into DAPORewardManager so the test is fully offline/reproducible.
        }
    )
    tokenizer = AutoTokenizer.from_pretrained("gpt2")
    return DAPORewardManager(config, tokenizer, _compute_score)

  • Files reviewed: 16/16 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/index.md
examples/flowgrpo_trainer.md
examples/flowdppo_trainer.md
examples/dpo_trainer.md
examples/dapo_trainer.md
import numpy as np
import torch
from omegaconf import OmegaConf
from transformers import AutoTokenizer
Comment on lines +63 to +85
overrides=[
"algorithm.filter_groups.enable=true",
"algorithm.filter_groups.metric=acc",
"algorithm.filter_groups.max_num_gen_batches=7",
"algorithm.use_kl_in_reward=true",
"algorithm.kl_penalty=low_var_kl",
"algorithm.kl_ctrl.type=adaptive",
"algorithm.kl_ctrl.kl_coef=0.02",
"algorithm.kl_ctrl.target_kl=0.03",
"algorithm.rollout_correction.rollout_is=token",
"algorithm.rollout_correction.rollout_is_threshold=3.0",
],
)

algorithm_cfg: OmniAlgoConfig = omega_conf_to_dataclass(cfg.algorithm)

assert isinstance(algorithm_cfg, OmniAlgoConfig)
assert isinstance(algorithm_cfg, AlgoConfig)
assert isinstance(algorithm_cfg.filter_groups, FilterGroupsConfig)
assert algorithm_cfg.filter_groups.enable is True
assert algorithm_cfg.filter_groups.metric == "acc"
assert algorithm_cfg.filter_groups.max_num_gen_batches == 7
assert algorithm_cfg.use_kl_in_reward is True
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.

3 participants