Configuration¶
Configuration is YAML, resolved by OmegaConf
with Hydra-style overrides, then validated into a Pydantic MasterConfig
(algorithms/grpo.py). A run is fully described by one config file plus any CLI
overrides.
The override flow¶
YAML file ──▶ OmegaConf ──▶ apply CLI overrides ──▶ resolve ${...} ──▶ MasterConfig(**dict)
MasterConfig is declared extra="allow", so configs can carry keys beyond the
documented schema (subsystems read their own sub-trees), but the listed
top-level sections are required.
CLI overrides¶
Everything after --config is a Hydra dot-notation override:
python3 examples/run_grpo_swe.py --config examples/configs/grpo_swe.yaml \
policy.model_name=Qwen/Qwen2.5-14B-Instruct \
grpo.num_prompts_per_step=32 \
loss_fn.reference_policy_kl_penalty=0.02
Interpolation and resolvers¶
Configs use OmegaConf interpolation (${policy.max_total_sequence_length}) to
keep derived values in sync, plus custom resolvers registered by
register_omegaconf_resolvers(). For example mul: multiplies, used to derive
micro-batch token budgets:
train_mb_tokens: ${mul:${policy.max_total_sequence_length}, ${policy.train_micro_batch_size}}
Top-level sections¶
MasterConfig has these sections:
Section |
Type |
Controls |
|---|---|---|
|
dict |
The trained model: name, precision, batch sizes, sequence length, the parallelism backend ( |
|
|
The clipped policy-gradient loss: clip ranges, reference-KL (Kullback–Leibler) penalty and type, importance-sampling correction, token- vs. sequence-level reduction. |
|
|
The RL loop: prompts/generations per step, rollout turns, advantage estimator, reward shaping/scaling, invalid-action penalty, structured tool use, async-GRPO settings, validation cadence. |
|
dict |
Per-environment settings (for SWE: scoring workers, reward mode, integrity check, sandbox URLs, task timeout). |
|
dict |
Datasets and dataloaders: train/validation dataset names, splits, prompt-length caps, the default processor and environment. |
|
|
Cluster shape: |
|
dict |
Logging backends (W&B, TensorBoard, MLflow, SwanLab), GPU monitoring, sample printing. |
|
dict |
Save cadence, top-k retention by metric, save format ( |
|
|
Optional external experience-transfer plane for non-colocated fleets. |
Key knobs¶
A few settings disproportionately shape a run:
RL group size —
grpo.num_prompts_per_step×grpo.num_generations_per_prompt. This is the number of rollouts per step and should matchpolicy.train_global_batch_size.Sequence budget —
policy.max_total_sequence_lengthbounds prompt + response and feeds the packing/dynamic-batching token budgets.Async GRPO —
grpo.async_grpo.enabledswitches loops. When on, several features are unsupported (dynamic sampling, reward scaling/shaping, multiple dataloaders) and IS correction is mandatory; these are validated at launch.Parallelism —
policy.dtensor_cfgselects tensor/context/expert parallel degrees for the trainer;policy.generation.vllm_cfgselects the independent inference-side parallelism.Precision and FP8 —
policy.precisionis the training/master precision;policy.generation.vllm_cfg.precision=fp8serves the inference fleet in FP8 while training stays in bf16 (weights are quantized on each refit).Generation engine —
policy.generationconfigures sampling and the inference backend (vLLM or SGLang). Two knobs beyond the usual sampling fields:ignore_eoslets a rollout keep generating past the end-of-sequence token (off by default; useful when a reward needs a fixed-length completion), andpolicy.generation.vllm_cfg.env_varspasses a per-recipe map of environment variables through to the vLLM workers — for example to select a fused-MoE backend for a particular model without baking it into the image.temperatureandtop_pare validated for finiteness at worker startup — a NaN/Inf value is rejected rather than forwarded to the engine. Per-sample image inputs are gated byallow_multimodal_inputs(defaultfalse): a VLM/CUA recipe must set it totrueto forward images to vLLM, and when enabled each image is normalized before the engine sees it — EXIF orientation applied, transparency flattened to RGB, and multi-frame inputs pinned to their first frame (GHSA-8jr5-v98p-w75m).max_image_pixelscaps a single image’s decoded size (decompression-bomb guard) andmax_images_per_samplecaps how many images one sample may carry; both reject oversized inputs at the worker boundary. The SGLang backend applies the same gate but does not yet forward images — image inputs are surfaced as an explicit error rather than silently dropped. The text generation path is unaffected by the flag.Logging backends —
loggerenables any of W&B, TensorBoard, MLflow, and SwanLab together. W&B receives full per-step series (including the per-worker generation timeline) as-is. Scalar-only backends (MLflow) cannot hold a list metric, so a list-valued metric is summarized to<name>/{mean,p50,p90,max}and the per-worker generation timeline is merged across workers before that reduction — one bounded set of scalar keys per metric instead of one key per element.
The config family¶
examples/configs/ holds one config per target environment; they share the
GRPO core and differ in dataset, environment, and rollout shape:
Config |
Target |
|---|---|
|
SWE-bench coding agent (single-shot patch). |
|
SWE-bench Pro variant. |
|
SWE-bench on the SGLang generation backend. |
|
SWE-bench with the JAX (Flax NNX) trainer backend. |
|
Program-synthesis benchmark. |
|
Terminal-bench agentic tasks. |
|
OSWorld computer-use agent. |
|
GDPval file-producing tasks. |
|
Humanity’s Last Exam. |
|
Multi-teacher on-policy distillation — stage 2 of a V4-style recipe. |
Each config’s header comment documents the topology and target hardware it was written for.
The V4-style two-stage recipe¶
v4_consolidation.yaml is the one config that composes several of the others
rather than targeting an environment. DeepSeek-V4’s post-training trains a
separate expert per domain and only then distils them into one student, so each
domain reaches its own optimum instead of every domain compromising against the
others in a single joint run. Run it in three passes:
Per-domain SFT —
sft.yaml, once per domain, keeping each checkpoint.Per-domain GRPO — the environment config matching that domain (
grpo_swe.yamlfor code,grpo_hle.yamlorgpqa.yamlfor reasoning,grpo_terminal_bench.yamlfor agentic work), each starting from its stage-1 checkpoint.Consolidation —
v4_consolidation.yaml, with the stage-2 checkpoints as teachers.grpo.adv_estimator.name: "opd"replaces the environment reward with = sg[log π_teacher − log π_student], andon_policy_distillation.teacher_model_by_agent_nameselects which teacher scores which rollout from the agent name — V4’s per-context teacher selection.
Three constraints are enforced in code and the config satisfies all three: the
OPD collector lives on the async path, so grpo.async_grpo.enabled must stay
true; OPD on the data plane raises NotImplementedError, so data_plane stays
undeclared; and the advantage subtracts prev_logprobs, so a config that zeroes
them is refused at startup.
One difference from V4 worth stating plainly: this is the token-level
estimator, not KL over the full vocabulary. The teacher-side full-vocab logit
exporter does not exist yet — see HV-49 in the hardware-deferred validation
ledger — so full-vocab KL is a build, not a config change.
Exporting a trained model to GGUF¶
After training, utils/native_checkpoint.py::convert_dcp_to_hf converts a DCP
checkpoint to a regular Hugging Face build. utils/gguf_export.py then produces a
switchable GGUF build alongside it so the released model also runs under llama.cpp /
ollama and other native GGUF runtimes:
convert_hf_to_gguf(hf_ckpt_path, out_path, quant_type=...)emits one GGUF;f16/bf16/f32are written directly, quantized types (Q4_K_M,Q8_0, …) go throughllama-quantize.export_gguf_variants(...)produces several at once.Conversion shells out to llama.cpp’s
convert_hf_to_gguf.pyandllama-quantize(a build-time dependency located viaDOCKYARD_LLAMA_CPP_DIRor thellama_cpp_dirargument — not a Python package), run withsys.executable.Each output is validated with the
ggufpackage (validate_gguf): architecture and tensor presence plus float-tensor finiteness.
Security: the GGUF dequant advisory (GHSA-5jv2-g5wq-cmr4) lives in vLLM’s dequant kernel, and is patched upstream in vLLM 0.24.0. This export+validation path never invokes vLLM, so producing and checking a GGUF does not exercise that kernel at all. dockyard has no GGUF-in-vLLM serve mode, so the advisory is unreachable here on either path. If such a serve mode is added, re-check the advisory against the pinned vLLM version at that point rather than assuming this note still applies.