Copy page "```python\nfrom modal_training_gym.train_recipes.slime_recipe.qwen3_6_35b import Qwen3_6_35b_Recipe\n```\n\nQwen3.6-35B-A3B (MoE) on 1×8×H100 with TP2/PP2/CP1/EP4.\n\n**Inherits from:** `SlimeRecipe`, `BaseTrainRecipe`\n\n## App Identity\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `recipe_type` | `RecipeType` | `slime` | Discriminator marking this recipe as slime; never override. |\n| `name` | `str` | `\"\"` | Modal app title; when empty the launcher derives one from the recipe class. |\n| `app_tags` | `dict` | `{}` | Extra tags merged into the Modal app metadata for dashboard auto-discovery. |\n\n## Modal Launcher\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `environment` | `dict` | `{'PYTHONPATH': '/root/Megatron-LM/', 'CUDA_DEVICE_MAX_CONNECTIONS': '1', 'NCCL_NVLS_ENABLE': '1'}` | Env vars set in the training containers (defaults include `PYTHONPATH` for Megatron and NCCL tuning). |\n| `async_mode` | `bool` | `False` | Run slime's `train_async.py` so rollout generation and training overlap (one-step off-policy) instead of alternating. |\n| `wandb` | `WandbConfig \\| None` | `None` | W&B settings; expands to slime's `--use-wandb`/`--wandb-project`/ `--wandb-group` flags. |\n| `image_overlay` | `collections.abc.Callable[[modal.image.Image], modal.image.Image] \\| None` | `None` | Callable that customizes the Modal image (e.g. `lambda img: img.pip_install(\"pkg\")`). |\n| `local_slime` | `str \\| None` | `None` | Path to a local slime checkout mounted over the image's copy — dev overlay for testing slime changes without an image rebuild. |\n| `memory` | `int \\| tuple[int, int] \\| None` | `None` | Modal Function memory request/limit in MiB. |\n| `cloud` | `str \\| None` | `None` | Modal cloud provider to pin the cluster to. |\n| `region` | `str \\| None` | `None` | Modal region to pin the cluster to. |\n| `slime_model_script` | `str` | `\"scripts/models/qwen3.5-35B-A3B.sh\"` | Script path relative to the slime repo, sourced before `train.py` to provide `MODEL_ARGS`; when set, model-architecture flags are not emitted from the attached `ModelConfig`. |\n| `source_hf_checkpoint` | `str \\| None` | `None` | HF repo fetched as the source checkpoint when it differs from the model's own (used by some recipes). |\n| `megatron_conversion_hf_checkpoint` | `str \\| None` | `None` | HF checkpoint used for the HF→Megatron conversion step instead of the training model's own weights. |\n| `patch_files` | `list[str]` | `[]` | Local patch scripts copied into the image at build time (applied to slime/Megatron sources). |\n| `image_run_commands` | `list[str]` | `[]` | Extra shell commands run while building the image. |\n| `image_env` | `dict[str, str]` | `{}` | Extra env vars baked into the image. |\n| `train_function_kwargs` | `dict[str, int]` | `{'ephemeral_disk': 1048576}` | Extra Modal Function options for the train function; supported keys: `secrets`, `experimental_options`, `ephemeral_disk`. |\n| `capture_trace` | `bool` | `False` | Attach slime's per-sample execution trace (generate/reward/tool-call timeline) to recorded rollouts for the dashboard. |\n| `trace_sample_limit` | `int` | `16` | With `capture_trace`, number of samples per rollout that get a trace attached (sampling keeps the added data volume small). |\n\n## Cluster and Parallelism\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `gpu_type` | `str` | `\"H100\"` | Modal GPU type for every node, e.g. `\"H100\"` or `\"B200\"`. |\n| `colocate` | `bool` | `True` | Trainer and rollout engines share the same GPUs, shifting memory between phases; `False` gives each its own GPUs (disaggregated). |\n| `actor_num_nodes` | `int` | `1` | Number of nodes for the Megatron actor (trainer). |\n| `actor_num_gpus_per_node` | `int` | `8` | GPUs per actor node. |\n| `rollout_num_gpus` | `int \\| None` | `None` | Total GPUs for rollout engines when disaggregated; `None` lets the allocation resolver size it. |\n| `rollout_num_gpus_per_engine` | `int` | `4` | GPUs per sglang engine — its tensor-parallel size. |\n| `tensor_model_parallel_size` | `int` | `2` | Megatron tensor-parallel size for the actor. |\n| `sequence_parallel` | `bool` | `True` | Megatron sequence parallelism (requires TP > 1). |\n| `use_critic` | `bool` | `False` | Train a separate critic model (PPO-style; GRPO runs without one). |\n| `critic_num_nodes` | `int \\| None` | `None` | Nodes for the critic when `use_critic` is set. |\n| `critic_num_gpus_per_node` | `int \\| None` | `None` | GPUs per critic node. |\n\n## Rollout and Sampling\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `num_rollout` | `int` | `3000` | Total rollout steps (= training steps) for the run. |\n| `rollout_batch_size` | `int` | `16` | Prompts sampled per rollout step; each prompt is expanded into a group of sampled responses. |\n| `rollout_max_response_len` | `int` | `16384` | Max generated tokens per sample. |\n| `rollout_temperature` | `float` | `1.0` | Sampling temperature for rollout generation. |\n| `rollout_shuffle` | `bool` | `True` | Shuffle the prompt dataset between epochs. |\n| `rollout_top_p` | `float` | `1.0` | Nucleus-sampling top-p for rollout generation. |\n| `rollout_stop_token_ids` | `list[int] \\| None` | `None` | Extra token ids that terminate generation. |\n\n## Fault Tolerance and Health Checks\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `use_fault_tolerance` | `bool` | `True` | Enable slime's fault tolerance so the run can recover from worker failures. |\n| `rollout_health_check_interval` | `int` | `30` | Interval in seconds between rollout engine /health_generate checks during generate/eval. |\n| `rollout_health_check_timeout` | `int` | `30` | Timeout in seconds to wait for a rollout engine /health_generate response before killing it. |\n| `rollout_health_check_first_wait` | `int` | `300` | Initial grace period (in seconds) before starting health checks. This allows time for model compilation and initialization. Increase this value significantly when using deepgemm. |\n\n## Checkpointing\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `save` | `str` | `\"/checkpoints\"` | Checkpoint output directory (the mounted `/checkpoints` volume). |\n| `save_interval` | `int` | `20` | Save a checkpoint every N rollout steps. |\n| `load` | `str` | `\"\"` | Checkpoint directory to resume from; empty starts from the converted HF weights. |\n| `no_save_optim` | `bool` | `True` | Omit optim state from checkpoints (smaller, but no exact resume). |\n| `megatron_to_hf_mode` | `str` | `\"\"` | Mode used to export saved Megatron checkpoints back to HF format; empty disables the export step. |\n| `freeze_params_name_list` | `list[str] \\| None` | `None` | Regex patterns (matched with `re.search`) of parameter names to freeze, e.g. a VL model's vision tower so RL only updates the language backbone. |\n\n## RL Algorithm\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `advantage_estimator` | `str` | `\"grpo\"` | Advantage estimator, e.g. `\"grpo\"`. |\n| `n_samples_per_prompt` | `int` | `8` | Responses sampled per prompt (the GRPO group size). |\n| `eps_clip` | `float` | `0.2` | PPO clip lower bound. |\n| `eps_clip_high` | `float` | `0.28` | PPO clip upper bound (asymmetric DAPO-style clipping). |\n| `use_kl_loss` | `bool` | `True` | Add a per-token KL loss term against the reference model. |\n| `kl_loss_type` | `str` | `\"low_var_kl\"` | KL formulation, e.g. `\"low_var_kl\"`. |\n| `kl_loss_coef` | `float` | `0.0` | Coefficient of the KL loss term. |\n| `kl_coef` | `float` | `0.0` | KL penalty coefficient applied in the reward. |\n| `entropy_coef` | `float` | `0.0` | Entropy bonus coefficient. |\n| `calculate_per_token_loss` | `bool` | `False` | Average the loss over tokens instead of over samples. |\n| `ref_load` | `str` | `\"/checkpoints/Qwen3.6-35B-A3B_torch_dist_tp2pp2\"` | Checkpoint path the reference model is read from (for KL terms). |\n\n## Dynamic Sampling\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `over_sampling_batch_size` | `int \\| None` | `None` | Prompts sampled beyond `rollout_batch_size` so groups rejected by the filter can be replaced (DAPO). |\n| `dynamic_sampling_filter_path` | `str \\| None` | `None` | Import path of the predicate deciding which sample groups to keep, e.g. dropping all-equal-reward groups. |\n| `balance_data` | `bool` | `True` | Rebalance kept samples across data-parallel ranks. |\n\n## Training and Optimizer\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `global_batch_size` | `int` | `128` | Training samples per optim step. |\n| `lr` | `float` | `1e-06` | Learning rate. |\n| `lr_decay_style` | `str` | `\"constant\"` | Schedule, e.g. `\"constant\"` or `\"cosine\"`. |\n| `weight_decay` | `float` | `0.1` | Weight decay. |\n| `adam_beta1` | `float` | `0.9` | Adam beta1. |\n| `adam_beta2` | `float` | `0.98` | Adam beta2. |\n| `optimizer` | `str` | `\"adam\"` | Optimizer name, e.g. `\"adam\"`. |\n\n## Memory and Precision\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `attention_dropout` | `float` | `0.0` | Attention dropout probability. |\n| `hidden_dropout` | `float` | `0.0` | Hidden-layer dropout probability. |\n| `attention_softmax_in_fp32` | `bool` | `True` | Compute attention softmax in fp32. |\n| `accumulate_allreduce_grads_in_fp32` | `bool` | `True` | Accumulate and all-reduce gradients in fp32. |\n| `use_distributed_optimizer` | `bool` | `False` | Shard optim state across data-parallel ranks (Megatron distributed optimizer). |\n| `recompute_granularity` | `str` | `\"full\"` | Activation recomputation granularity (`\"full\"` or `\"selective\"`). |\n| `recompute_method` | `str` | `\"uniform\"` | Recomputation method (`\"uniform\"` or `\"block\"`). |\n| `recompute_num_layers` | `int` | `1` | Layers per recomputation chunk. |\n| `qkv_format` | `str` | `\"thd\"` | QKV layout for the Megatron backend (`\"thd\"` or `\"bshd\"`), emitted as `--qkv-format`. |\n\n## Dynamic Batching\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `use_dynamic_batch_size` | `bool` | `True` | Pack variable-length samples into micro-batches up to `max_tokens_per_gpu` instead of a fixed micro batch size. |\n| `max_tokens_per_gpu` | `int` | `8192` | Token budget per GPU per micro-batch when dynamic batching is on. |\n\n## Eval\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `eval_interval` | `int \\| None` | `None` | Run eval every N rollout steps; `None` disables eval. |\n| `n_samples_per_eval_prompt` | `int` | `4` | Responses sampled per eval prompt. |\n| `eval_max_response_len` | `int` | `16384` | Max generated tokens per eval sample. |\n| `eval_top_p` | `float` | `1.0` | Nucleus-sampling top-p for eval generation. |\n| `eval_config` | `dict \\| None` | `None` | Inline dict materialized to a YAML file and passed as `--eval-config`; holds eval defaults and the eval dataset list. |\n\n## Weight Sync\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `update_weight_mode` | `str` | `\"full\"` | `\"full\"` rebroadcasts all weights each sync; `\"delta\"` pin-snapshots the last broadcast on CPU and ships only byte-level changes (~5-10x faster for large MoE models whose weights barely move per rollout). |\n| `update_weight_transport` | `str` | `\"nccl\"` | `\"nccl\"` or `\"disk\"`; disk requires trainer and rollout engines to share a filesystem. |\n| `update_weight_encoding` | `str` | `\"indices\"` | Encoding for delta payloads, e.g. `\"indices\"`. |\n| `update_weight_disk_dir` | `str` | `\"\"` | Shared directory used by the disk transport. |\n\n## Reward Model\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `rm_type` | `str \\| None` | `None` | Name of a slime built-in reward function (e.g. `\"deepscaler\"`); leave `None` when shipping a reward callable instead. |\n\n## Custom Functions and Hooks\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `custom_rm_function` | `collections.abc.Callable \\| None` | `None` | Reward callable shipped by value to the containers and registered as slime's `--custom-rm-path`. |\n| `custom_generate_function` | `collections.abc.Callable \\| None` | `None` | Callable replacing slime's generate step; shipped by value and registered via its resolved import path. |\n| `custom_reward_post_process_function` | `collections.abc.Callable \\| None` | `None` | Callable applied to rewards after generation. Prefer this over setting a raw dotted path yourself: functions defined in a `__main__` tutorial script have no reliably importable module name, so slime's own `importlib.import_module` on that path fails inside the Ray actor. |\n| `rollout_function` | `collections.abc.Callable \\| str \\| None` | `None` | Replaces slime's entire rollout loop (`--rollout-function-path`). |\n| `custom_rollout_log_function` | `collections.abc.Callable \\| str \\| None` | `None` | Called with each rollout's data for logging; the gym wraps it so phase reporting and dashboard capture still run. |\n| `custom_eval_rollout_log_function` | `collections.abc.Callable \\| str \\| None` | `None` | Same as above, for eval rollouts. |\n| `custom_megatron_before_log_prob_hook` | `collections.abc.Callable \\| str \\| None` | `None` | Hook run in the Megatron trainer before log-prob computation. |\n| `custom_megatron_before_train_step_hook` | `collections.abc.Callable \\| str \\| None` | `None` | Hook run in the Megatron trainer before each train step. |\n\n## Config Overrides\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `extra_config` | `dict \\| None` | `None` | The primary escape hatch: dict written to YAML and passed as `--custom-config-path`. Keys become attributes on slime's parsed args and always override same-named recipe fields. |\n| `sglang_config` | `dict \\| None` | `None` | Dict written to YAML and passed as `--sglang-config` — structured sglang engine config that isn't a flat flag (e.g. PD-disaggregation `server_groups`). |\n| `sglang_request_params` | `dict \\| None` | `None` | Extra request parameters injected into sglang generate calls (shipped via `extra_config`, read as `args.sglang_request_params` by generate paths such as on-policy distillation). |\n| `apply_chat_template_kwargs` | `dict \\| str` | `\"\"` | Kwargs forwarded to the tokenizer's `apply_chat_template`, passed as inline JSON. |\n| `train_env_vars` | `dict \\| str \\| None` | `None` | Env vars for the training processes, passed as inline JSON. |\n| `multimodal_keys` | `dict \\| str \\| None` | `None` | Dataset columns holding multimodal inputs, passed as inline JSON; auto-filled from the attached `DatasetConfig`. |\n\n## SGLang Rollout Engine\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `sglang_mem_fraction_static` | `float` | `0.75` | Fraction of GPU memory sglang reserves for weights + KV cache. |\n| `sglang_enable_dp_attention` | `bool` | `True` | Enable data-parallel attention across engine ranks. |\n| `sglang_dp_size` | `int \\| None` | `4` | Data-parallel size for the engines. |\n| `sglang_ep_size` | `int \\| None` | `4` | Expert-parallel size for MoE models. |\n| `sglang_enable_dp_lm_head` | `bool` | `True` | Data-parallel LM head (pairs with DP attention). |\n| `sglang_disable_custom_all_reduce` | `bool` | `False` | Fall back to NCCL all-reduce instead of sglang's custom kernel. |\n| `sglang_cuda_graph_bs` | `list[int] \\| None` | `[1, 2, 4, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232, 240, 248, 256]` | Batch sizes to capture CUDA graphs for. |\n| `sglang_max_running_requests` | `int \\| None` | `512` | Cap on concurrent in-flight requests per engine. |\n| `sglang_tool_call_parser` | `str \\| None` | `None` | Parser for tool-call output, e.g. `\"qwen25\"`. |\n| `sglang_reasoning_parser` | `str \\| None` | `None` | Parser for reasoning/thinking output. |\n\n## Other Fields\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `sglang_cuda_graph_backend_prefill` | `str \\| None` | `None` | |\n| `hf_checkpoint` | `str` | `\"Qwen/Qwen3.6-35B-A3B\"` | |\n| `pipeline_model_parallel_size` | `int` | `2` | |\n| `context_parallel_size` | `int` | `2` | |\n| `expert_model_parallel_size` | `int` | `4` | |\n| `expert_tensor_parallel_size` | `int` | `1` | |\n| `sglang_speculative_algorithm` | `str \\| None` | `\"EAGLE\"` | |\n| `sglang_speculative_num_steps` | `int \\| None` | `3` | |\n| `sglang_speculative_eagle_topk` | `int \\| None` | `1` | |\n| `sglang_speculative_num_draft_tokens` | `int \\| None` | `4` | |\n| `sglang_mamba_scheduler_strategy` | `str` | `\"extra_buffer\"` | |\n| `moe_token_dispatcher_type` | `str` | `\"flex\"` | |\n| `moe_enable_deepep` | `bool` | `True` | |\n| `optimizer_cpu_offload` | `bool` | `True` | |\n| `overlap_cpu_optimizer_d2h_h2d` | `bool` | `True` | |\n| `use_precision_aware_optimizer` | `bool` | `True` | |\n| `attention_backend` | `str` | `\"flash\"` | |\n\n## Methods\n\n### `cli_args(self, dataset: 'DatasetConfig | None' = None, model: 'ModelConfig | None' = None) -> list[str]`\n\n### `get_base_recipe(model_config: modal_training_gym.common.models.base.ModelConfig) -> 'SlimeRecipe'`\n\n### `validate_model_parallelism(self, model: 'ModelConfig') -> None`\n\n## Related Tutorials\n\n- [Cross-tokenizer agentic distillation on BFCL v3 multi-turn with live, execution-grounded rewards — DeepSeek V4 Flash teacher, Qwen3.6-35B-A3B student](/tutorials/rl/009_cross_tokenizer_distillation/)\n\n**Source:** [`modal_training_gym/train_recipes/slime_recipe/qwen3_6_35b.py`](https://github.com/modal-projects/training-gym/blob/main/modal_training_gym/train_recipes/slime_recipe/qwen3_6_35b.py)\n"