Research / September 22, 2026
Swarm the prompts GRPO throws away
An RL training set is only the prompts the model sometimes gets right. The hardest ones never make it in, because every rollout fails. We gave 223 such prompts the same extra budget four ways. A swarm of attempts that share programs rescued one in ten. So did plain resampling. Spending the samples mattered. How we structured them did not.
The short version. GRPO learns from the spread inside a group of rollouts, so a prompt where all eight fail teaches it nothing and gets dropped. Those are your hardest prompts, and they vanish from the training set. We took 223 of them and gave each one 24 more samples four ways. Every way rescued about one task in ten, and the differences sit inside the noise of re-running the same arm. The caveat is the model: a 4B model with thinking off barely passes a single sample test on these problems, so there was little for the swarm to share.
Share of the 223 code_contests tasks where hosted Qwen3-4B failed all 8 base rollouts and the arm then found a program passing every hidden test. Same 24-sample budget per task per arm. Re-running the resample arm with two more seeds gave 9.0% and 10.8%, so a gap under 10.9 points is the eval re-running. Source: recipes/01-simulate/swarm-rescue/results.json.
| Item | Value | 95% interval |
|---|---|---|
| Resample, 24 independent tries | 7.2% | 4.1% to 10.3% |
| Solo, rewrite own best with the failing test | 6.7% | 3.3% to 10.1% |
| Ring swarm, plus two neighbours' best | 9.9% | 6.1% to 13.7% |
| Star swarm, plus the whole swarm's best | 9.9% | 6.1% to 13.7% |
Where the training set comes from
A reinforcement learning run on a verifier does not train on prompts. It
trains on groups: several rollouts of one prompt, scored pass or fail,
with the passing ones pushed up relative to the failing ones [1]. If the
whole group passes or the whole group fails, there is nothing to push, so
the prompt contributes no gradient and dynamic sampling skips it [2]. The
SDK's select(mode="rl") keeps the 20 to 80% band for the same reason.
That rule is right and it has a cost. The prompts that fail every time are the ones the model most needs, and they are exactly the ones the training set never contains. In our base pass, 223 of 275 tasks were in that pile.
A swarm is a different way to spend the same samples
Particle swarm optimization is a population search from 1995 [3]. Each particle keeps its own best position, looks at its neighbours' best, and moves toward a mix of the two. The part that transfers to language models is not the arithmetic. It is the social structure, and the one question the field studied for two decades: who sees whom.
We ran it in prose. A particle is one attempt at the problem. Its position is the program it wrote. Its fitness is how many of the visible tests that program passes. Each round, the model gets its own best program, the first visible test it failed with the expected and actual output, and one more thing that depends on the topology:
- Solo sees nothing else. This is the swarm with the social term off.
- Ring sees the best program of its two neighbours [4].
- Star sees the best program in the whole swarm.
Eight particles, three rounds, 24 samples. Resampling gets 24 fresh independent tries. Every arm stops on a task the moment one program passes the hidden tests, which no arm ever sees.
Round 0 is 8 fresh samples for every arm. The swarms found most of their rescues in the rounds that read a failing test and a neighbour's program, as the design predicts. The two resample re-runs found 20 and 24, so the gap is inside the seed-to-seed spread.
| Item | Value |
|---|---|
| Resample | 16 |
| Solo | 15 |
| Ring | 22 |
| Star | 22 |
What happened
Feedback alone did nothing. Solo refinement matched resampling. Sharing added six rescues for either topology, and the two resample re-runs moved by more than that between seeds. On the tasks nobody rescued, the best program passes 8% of the visible tests on average. The fitness the swarm moves on was almost always zero, and a particle shown a neighbour's zero-fitness program has no direction to move in.
The training set did move. Across the six runs, 43 of the 223 dropped prompts got at least one program that passes every hidden test. The four arms alone wrote 112 distinct passing programs on 37 tasks into a file of bare rows: the problem in, the program out, no swarm context.
What this teaches about post-training
The training set is not fixed. Which prompts carry signal depends on how much you sample, and on this model it did not depend on how you condition the later samples. QuestA rescues the same prompts with partial reference solutions as hints [5]; the swarm tried to write its own hints and, at this fitness floor, could not. Model Swarms ran PSO over adapter weights [6], where fitness is a held-out score and always graded. A swarm needs a graded fitness. Pass or fail on a task the model cannot touch is not one.
The rescued rows carry a warning label. They were written with a neighbour's program in the prompt, so they are off-policy for the bare prompt and cannot go through the GRPO importance ratio as plain rollouts. They enter as privileged data: rejection-sampled SFT, or the on-policy distillation we compared last week. That training run is the next post, and it does not need the swarm to win first.
For researchers
| Setting | Value |
|---|---|
| Tasks | code_contests test and valid splits [7], 275 problems after dropping interactive ones, median Codeforces rating 1900 |
| Tests | visible = public + 8 generated; hidden = private + 32 generated; pass = whitespace-token match, floats within 1e-6, 6 s a test |
| Model | hosted Qwen3-4B, thinking off, temperature 1, 2,048 tokens, seed per sample; 7.8% of replies hit the cap |
| Base | 8 rollouts a task; all-fail = 0 of 8 pass every test; 223 of 275 |
| Budget | 24 samples a task an arm: 8 particles x 3 rounds, or 24 independent draws |
| Fitness | share of visible tests passed; a tie goes to the newer attempt |
| Rescue | at least one program passing every visible and hidden test |
| Interval | wai.pass_at bootstrap over tasks; deltas vs resample by wai.compare_runs, paired, sign-flip p-value |
| Deltas | solo -0.4 [-4.0, +2.7]; ring +2.7 [-1.3, +6.7]; star +2.7 [-0.9, +6.3] points |
| Noise floor | resample at three seeds: 7.2, 9.0, 10.8%; run_std 1.8 points; band 10.9 (wai.eval_variance) |
| To resolve | wai.holdout_size: 547 paired tasks for +5 points at a 7% base, 1,382 for +3 |
| By rating | under 1500: 10 / 13 / 15 of 70 (resample / ring / star); 1500 to 2199: 2 / 3 / 4 of 57; 2200 up: 4 / 6 / 3 of 96 |
| Cost | about 24,000 model calls, 25M tokens, 3.5 hours on one L40S |
Run it
pip install whileai pyarrow
git clone https://github.com/whilehq/whileai-sdk
cd whileai-sdk/recipes/01-simulate/swarm-rescue
python run.py --dry-run # three toy tasks, a fake model, no key
python run.py --limit 20 # twenty tasks on the hosted model
python run.py --noise-runs 2 # every task, four arms, the noise bandReferences
- Shao, Z., Wang, P., Zhu, Q., Xu, R., Song, J., Bi, X., Zhang, H., Zhang, M., Li, Y. K., Wu, Y. and Guo, D. (2024). DeepSeekMath: Pushing the limits of mathematical reasoning in open language models. arXiv:2402.03300.
- Yu, Q., et al. (2025). DAPO: An open-source LLM reinforcement learning system at scale. arXiv:2503.14476.
- Kennedy, J. and Eberhart, R. (1995). Particle swarm optimization. Proceedings of IEEE International Conference on Neural Networks, 1942 to 1948.
- Kennedy, J. and Mendes, R. (2002). Population structure and particle swarm performance. Proceedings of the IEEE Congress on Evolutionary Computation, 1671 to 1676.
- Li, J., et al. (2025). QuestA: Expanding reasoning capabilities of LLMs via question augmentation. arXiv:2507.13266.
- Feng, S., Wang, Z., Wang, Y., Ebrahimi, S., Palangi, H., Miculicich, L., Kulshrestha, A., Rauschmayr, N., Choi, Y., Tsvetkov, Y., Lee, C.-Y. and Pfister, T. (2024). Model Swarms: Collaborative search to adapt LLM experts via swarm intelligence. arXiv:2410.11163.
- Li, Y., et al. (2022). Competition-level code generation with AlphaCode. Science 378(6624), 1092 to 1097. arXiv:2203.07814.