Results
Success rate on factorio-build (8 scenes per row, 16 rows × 4 samples,
temperature 0.6, thinking off):
Table with columns: Model, Validation, Holdout| Model | Validation | Holdout |
|---|
| Qwen3.5-9B | 2.1% | 1.6% |
| This model | 18.0% | 18.0% |
| This model + 20 GRPO steps | 93.8% | 79.5% |
| SFT, 800 programs (sft-800) | 67.0% | 57.4% |
| SFT, 800 programs + 20 GRPO steps (sft-800-grpo) | 85.9% | 84.0% |
Sampling matters: at temperature 1.0 this model's long programs drift into
syntax errors and success falls to ~0%.
Training
- Data: 93 distinct programs found by LLM-guided program search (
evolve
in factory-sim), each scoring ≥ 0.5 on training scenes and passing the
current sandbox, paired with real factorio-build training prompts. No
validation or holdout scene was used for selection.
- Method: LoRA (rank 32, alpha 64) on every attention, Gated DeltaNet and MLP
projection of the language model, merged into the weights. Loss on the
completion only; prompts rendered with the Qwen3.5 chat template and
enable_thinking=False.
- Schedule: 2 epochs, 24 optimizer steps (batch 8), AdamW, lr 1e-4 with
warm-up and cosine decay, bf16, one A100 80GB, ~8 minutes.
Recipe, configs and scripts:
recipes/grpo-factorio-build.
Use
Serve with vLLM and pass chat_template_kwargs={"enable_thinking": false}. The
prompt format is the one factorio-build produces; the model answers with a short
plan and one fenced Python block.
Limitations
- Trained for one task (
construct_smelting_line) and one API; it is not a
general coding model.
- Programs act only through the simulator's
world API, inside a sandbox.
- Numbers come from 64 samples per split; expect a few points of noise.