Submit a recipe

OpenRecipes takes two kinds of contribution: a faster recipe for a model and GPU type, including a pair the catalog does not list yet, and a search procedure that finds recipes, such as a tuner, an agent or a set of rules. Submit a procedure through the recipes it finds; each is one recipe file, and its notes describe or link the procedure.

A recipe is one YAML file at recipes/<model-slug>/<gpu>/<handle>-<layout>.yaml: the layout, the command as run, the measured result, the stack it ran on, the correctness evidence and, where needed, notes. You run the commands below yourself and open a pull request with the file.

Steps

  1. Pick the pair and the reference recipe. Recipes rank within a model and GPU type, on any number of GPUs. The reference recipe is the one you tune from: a public recipe, the pair's current best or one you wrote. You need not publish it. Apply the objective conventions to both.
  2. Build the rows with data/ (its README gives the command per tokenizer) and check them with python3 data/verify_rows.py <rows.parquet> --recipe <a recipe of the same model>.
  3. Measure. Run the recipe once under the protocol: 8,192-token rows, global batch 128, BF16, 20 steps with the profiler off, scored over steps 5–19. Record the score, the step-time CV, the GPU-hours and the framework versions.
  4. Check correctness. Run a 20-step arm of the reference recipe on the same image and rows, compare its per-step loss with the measured run's using Megatron-Bridge's validate_convergence, and class every argument that differs between the two. Each same-math swap needs a passed component test at the model's shape. OpenRecipes lists a recipe once all of them pass.
  5. Write the recipe from the template below. Count N with python3 tools/active_params.py <hf-repo>, take the rate from gpus.yaml, and add notes only for what is specific to the recipe: the steps every recipe shares are under Running a recipe, and those a model's recipes share go in the model's notes in models.yaml. Add the model to models.yaml if it is missing, and put any code beyond the stock stack under patches/.
  6. Validate and build. python3 tools/validate.py checks the file against the schema and recomputes the cost, the MFU, the data-parallel size and the window; python3 tools/build.py rebuilds site/, and python3 tools/build.py --check and python3 -m pytest -q tests must pass. Commit the rebuilt site/ with the recipe.
  7. Open a pull request with the recipe, any new patches and the rebuilt site.

Leave out internal paths, image registry addresses, account or cluster names, and datasets you may not cite.

The recipe file

The full schema is schema/recipe.schema.yaml; every recipe in recipes/ is a worked example.

recipes/<model-slug>/<gpu>/<handle>-<layout>.yaml
schema_version: 1
model: Qwen3.5-122B-A10B          # as in models.yaml; add the model there if it is missing
gpu: {type: H200, memory_gb: 141, count: 32, per_node: 8, instance: AWS p5en.48xlarge}
author: {github: your-handle}     # or {name: <tool>, url: https://...}
status: verified
stack:                            # the versions the measured run used; "not pinned" when unknown
  framework: slime <version> (THUDM/slime <commit>)
  megatron_lm: <commit> (megatron-core <version>)
  transformer_engine: <version>
  pytorch: <version>
  cuda: <version>
  nccl: <version>
workload:
  row_tokens: 8192
  rows: SFT conversations
  global_batch: 128
  precision: bf16
  dataset:
    name: Tulu 3 SFT mixture
    source: allenai/tulu-3-sft-mixture
    revision: b14afda60f1bbebe55d5d2fa1e4df5042f97f8be
    license: ODC-By 1.0
    rows_sha256: <printed by data/verify_rows.py>
    build: {name: qwen35-tulu3-fixed8192-v1, tokenizer: <name and tokenizer.json sha256>, loss_mask: qwen3_5,
            rows: 6400, row_tokens: 8192, seed: 42, builder: data/generate_fixed_sft.py}
layout:
  label: TP1 PP4 EP8 DP8
  summary: <the full layout in words>
  highlights: <the settings that set the recipe apart>
  tp: 1
  pp: 4
  vpp: 1
  cp: 1
  ep: 8
  etp: 1
  dp: 8                           # gpu.count / (tp x pp x cp)
  sequence_parallel: false
  layer_split: null               # or {first: 11, last: 10}
  max_tokens_per_gpu: 8192
  rows_per_microbatch: 1
  recompute: {granularity: full, method: uniform, num_layers: 1}
  offload: null                   # or {optimizer_fraction: 0.9, overlap_d2h_h2d: true}
  dispatcher: alltoall
result:
  tokens_per_s_per_gpu: <score over steps 5-19>
  usd_per_million_tokens: <rate in gpus.yaml / (tokens/s/GPU x 3600) x 1e6, to the cent>
  step_time_cv_percent: <CV of the step time over the window>
  mfu: <6 x N x tokens/s/GPU / peak, or null>
  mfu_note: null                  # why, when mfu is null
  active_params: {count: <N from tools/active_params.py>, source: https://huggingface.co/<repo>, revision: <commit>}
  measured: 2026-10-14
  steps_per_run: 20
  window: [5, 19]
  window_tokens: 15728640         # 15 steps x 128 rows x 8,192 tokens
  runs: 1
  profiler: false
  gpu_hours: <GPUs x (admission to finish)>
  gpu_hours_note: GPUs x (scheduler admission to finish), including startup
correctness:
  result: pass
  summary: <one line>
  reference: <the reference recipe, or "Not published.">
  configuration: pass
  component_tests: []             # one entry per same-math swap: test, shape, gpu, date, result, detail
  convergence: {steps: 20, result: pass, correlation: <r>, final_loss_difference: <d>, pointwise_failures: 0}
  rules: <the rule lists the check used>
env: {CUDA_DEVICE_MAX_CONNECTIONS: "1"}
patches: []                       # files under patches/ the recipe needs
run: |
  <the training command as run, with paths replaced by variables>
notes: |                          # optional; plain text, blank lines separate paragraphs, "- " starts a list item
  <what a reader needs to run this recipe that the protocol and the model's notes do not say>

Fields

Generated from the schema. tools/validate.py also checks the cross-field rules listed at the top of the schema file.

FieldTypeRequiredMeaning
schema_versionalways 1yes
modelstringyesThe model's name exactly as in models.yaml.
gpuobjectyes
gpu.typestring: H100, H200, B200yesA GPU type listed in gpus.yaml.
gpu.memory_gbintegeryes
gpu.countintegeryesGPUs the measured run used.
gpu.per_nodeintegeryes
gpu.instancestringyesThe machine, for example "AWS p5en.48xlarge".
authorobjectyesWho submitted the recipe: a GitHub handle for a person or team, or a name and a link for a tool. At least one of github and url.
author.githubstring
author.namestring
author.urlstring
author.paperstringA paper that describes the author's method.
statusone of verifiedyesverified = measured under the protocol and passed the correctness check. The site lists verified only.
stackobjectyesThe versions the measured run used. A version the run's evidence does not show reads "not pinned".
stack.frameworkstringyesslime or miles, with its commit.
stack.megatron_lmstringyes
stack.transformer_enginestringyes
stack.pytorchstringyes
stack.cudastringyes
stack.ncclstringyes
stack.deepepstring
stack.pythonstring
stack.networkstringGPUs per node and the inter-node network.
stack.runtime_fixesstringRun-time patches the run loaded.
stack.sourcestringHow the versions were read.
workloadobjectyes
workload.row_tokensintegeryesTokens in every row; rows are packed to exactly this length.
workload.rowsstringyes
workload.global_batchintegeryesRows per optimizer step.
workload.precisionone of bf16yes
workload.datasetobjectyes
workload.dataset.namestringyes
workload.dataset.sourcestringyesThe Hugging Face dataset id.
workload.dataset.revisionstringyes
workload.dataset.licensestringyes
workload.dataset.rows_sha256stringyessha256 of the rows' row_hash values in file order, one per line (data/verify_rows.py).
workload.dataset.buildobjectyesHow the rows were built (data/README.md); any further keys describe the build.
workload.dataset.build.namestringyes
workload.dataset.build.tokenizerstringyes
workload.dataset.build.loss_maskstringyes
workload.dataset.build.rowsintegeryes
workload.dataset.build.row_tokensintegeryes
workload.dataset.build.padding_tokensinteger
workload.dataset.build.seedintegeryes
workload.dataset.build.parquet_sha256string
workload.dataset.build.builderstringyes
layoutobjectyes
layout.labelstringyesShort form for tables, for example "TP1 PP4 EP8 DP8".
layout.summarystringyesThe full layout in words.
layout.highlightsstringyesThe non-parallel settings that set the recipe apart
layout.tpintegeryes
layout.ppintegeryes
layout.vppintegeryesVirtual pipeline stages per pipeline rank; 1 means none.
layout.cpintegeryes
layout.epintegeryes
layout.etpintegeryes
layout.dpintegeryes
layout.sequence_parallelbooleanyesTrue when sequence parallelism is on with TP above 1 (Megatron turns it off at TP 1).
layout.layer_splitobject or nullyesLayers on the first and last pipeline stages when the split is uneven; null for an even split.
layout.layer_split.firstintegeryes
layout.layer_split.lastintegeryes
layout.max_tokens_per_gpuinteger or nullyesDynamic batching budget; null without it.
layout.rows_per_microbatchintegeryes⌊max_tokens_per_gpu×cprow_tokens⌋ under dynamic batching, else the micro-batch size.
layout.recomputeobject or nullyes
layout.recompute.granularityone of full, selectiveyes
layout.recompute.methodone of uniform, block, nullyes
layout.recompute.num_layersinteger or nullyes
layout.offloadobject or nullyesCPU optimizer offload; null when the optimizer stays on the GPU.
layout.offload.optimizer_fractionnumberyes
layout.offload.overlap_d2h_h2dbooleanyes
layout.dispatcherone of alltoall, flex, allgather, nullyesThe MoE token dispatcher; null for a dense model.
resultobjectyes
result.tokens_per_s_per_gpunumberyes∑windowtokensGPUs×∑windowstep time
result.usd_per_million_tokensnumberyes
result.step_time_cv_percentnumberyes
result.mfunumber or nullyes
result.mfu_notestring or nullyes
result.active_paramsobjectyes
result.active_params.countinteger or nullyesN of the MFU (tools/active_params.py).
result.active_params.sourcestringyes
result.active_params.revisionstringyes
result.measureddateyes
result.steps_per_runintegeryes
result.windowarrayyes
result.window_tokensintegeryes
result.runsintegeryes
result.profileralways falseyes
result.gpu_hoursnumberyes
result.gpu_hours_notestringyes
correctnessobjectyes
correctness.resultone of pass, failyes
correctness.summarystringyes
correctness.referencestringyesThe reference recipe the recipe was checked against
correctness.configurationone of pass, failyesThe configuration check (layer 1): every argument that differs from the reference recipe is structural or a same-math swap with a passed component test.
correctness.component_testsarrayyes
correctness.component_tests[].teststringyes
correctness.component_tests[].shapestringyes
correctness.component_tests[].gpustringyes
correctness.component_tests[].datedateyes
correctness.component_tests[].resultone of pass, failyes
correctness.component_tests[].detailstringyes
correctness.component_tests[].notestring
correctness.convergenceobjectyesThe 20-step loss comparison against the reference recipe (Megatron-Bridge validate_convergence).
correctness.convergence.stepsintegeryes
correctness.convergence.resultone of pass, failyes
correctness.convergence.correlationnumberyes
correctness.convergence.final_loss_differencenumberyes
correctness.convergence.pointwise_failuresintegeryes
correctness.convergence.worst_step_tolerance_rationumber
correctness.convergence.notestring
correctness.rulesstringyesThe rule lists the check used.
envobjectyesEnvironment variables the run sets, in the command or in the container, as name -> value.
patchesarrayyesFiles under patches/ the recipe needs (patches/README.md).
runstringyesThe training command as run, with paths replaced by variables.
notesstringWhat a reader needs that is specific to this recipe, if anything; the site shows it with the recipe. Steps every recipe shares are on the protocol page (Running a recipe), and those a model's recipes share are its notes in models.yaml.