---
library_name: peft
base_model: Qwen/Qwen3-8B
tags:
- peft
- lora
- safetensors
- negotiation
- multi-agent
- reinforcement-learning
- grpo
- fairness
datasets:
- siddharthmb/2026.RA.Fairness-GRPO-v2
- siddharthmb/2026.RA.Fairness-GRPO
---
# 2026.RA.Fairness-GRPO-v2 — trained LoRA adapters (the λ-frontier)
The **trained LoRA adapters** from the fairness-GRPO v2 campaign: can outcome-aligned RL (GRPO on an engine-computed, text-blind log-Nash reward) make an LLM negotiator distribute surplus more *fairly* on held-out games — not merely close more deals — and generalize to settings where the numbers are not machine-readable?
**The evaluation record for these adapters is the dataset [siddharthmb/2026.RA.Fairness-GRPO-v2](https://huggingface.co/datasets/siddharthmb/2026.RA.Fairness-GRPO-v2)** (contrasts, telemetry, verdicts). This repo is the weights those numbers were computed from. Full methodology + the machine-derived final tables: research note `experiments/rational_agents/research-notes/0028-fairness-grpo-v2.md`; narrative hub: .
## What this is
Each folder `_checkpoint-/` is a complete PEFT adapter (r32/α64, LoRA on q/k/v/o/gate/up/down) over **Qwen/Qwen3-8B**, thinking off, saved at global training step `STEP`. `STEP` is continuous within an arm across its resume segments (see "Training provenance"). Three arms trace the **λ-mixture**, the swept variable — seat *i* trains on `R_i(λ) = (1−λ)·g(z_i) + λ·R_table`, where `g` is the smoothed clipped log-Nash utility (`g_floor = −17.5`) and `R_table` is the mean over seats:
| arm | λ | reward | checkpoints (global step) |
|---|---|---|---|
| `lam1` | 1.0 | pure table welfare | 5, 10, 15, 25, 30, 35, 40, 45, 50 |
| `lam05` | 0.5 | mixture | 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 |
| `lam0` | 0.0 | pure self-interest (selfish control, shaping off) | 5, 10, 15 |
## Headline result: the north-star answer is **no**
Every interpretable rung of every arm **fails the preregistered POSITIVE gate**. Held-out primary deal-rate degrades at every λ; prose-transfer fairness never resolves favorable. The verdict is a clean, fully-measured negative for this reward family — for negotiation fairness specifically, an algorithmic agent + a parser dominates the RL'd LLM.
**Held-out primary deal-rate delta vs untrained Qwen3-8B** (paired, game-cluster bootstrapped; the eval bank is `instances_grpo_eval_v1`):
| step | 5 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 |
|---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
| **λ=1.0** | −0.052 | −0.143 | −0.147 | — | −0.226 | — | — | −0.453 | −0.641 | **−0.746** |
| **λ=0.5** | −0.058 | −0.046 | −0.058 | −0.151 | −0.267 | −0.240 | −0.445† | −0.173 | −0.271 | **−0.369** |
| **λ=0** | −0.028 | −0.075 | (partial‡) | | | | | | | |
*(closure-conditional fairness metrics are stamped **VOID** at any rung whose deal rate falls >0.10 below base — a viability screen, Amendment 5(a). † rung 35 sits immediately after a fresh-Adam restart and is anomalously deep. ‡ λ=0 rung 15 stopped for cost, 346 eps, reported partial.)*
**What the frontier means:** closure decay scales with how much a seat is paid on the *table* rather than on itself. λ=1.0 collapses monotonically to a policy that will not sign at all (prose closes 0.002, ultimatum closes nothing). λ=0.5 buys *robustness of closure* (half the depth, oscillation not monotone collapse) but never fairness. λ=0 (walk fully priced to self) shows **no closure collapse** through rung 10 — isolating table-welfare payment as the collapse mechanism, not GRPO-on-this-task.
**The sharpest single finding — boundary extraction (from `lam1_checkpoint-25`):** on the ultimatum family the policy learned a **100/0 split accepted every time**, placing the responder *exactly* on its walk-away point (z<ε). Every closure-conditional guard reads this as perfect; only a share/dispersion term (`max_share`) sees it. Standing program rule: any below-threshold gate carries a share term beside the deal-rate floor.
## How to use an adapter
```python
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-8B", dtype=torch.bfloat16, device_map="cuda")
tok = AutoTokenizer.from_pretrained("Qwen/Qwen3-8B")
model = PeftModel.from_pretrained(base, "siddharthmb/2026.RA.Fairness-GRPO-v2-Adapters", subfolder="lam1_checkpoint-25")
```
## Reproduce the training
Per arm (via `experiments/rational_agents/grpo_v2/train.py`), Qwen3-8B LoRA r32/α64, thinking off, `g_floor=−17.5`, GRPO groups=22 × k=8, frozen population-opponent zoo `{bayes-rational, passive-gate, greedy-anchor}`:
```bash
# λ=1.0 (arm lam1): steps 5-25 at groups=22; resumed from checkpoint-25 for the dense tail 30-50.
python -m grpo_v2.train --lam 1.0 --steps 50 --groups 22 --k 8 --bank instances_grpo_v2_train \
--checkpoint-steps 5 10 15 25 30 35 40 45 50 --g-floor -17.5 \
--wandb-run-name grpo_v2_lam1 --wandb-group fairness-grpo-v2
# λ=0.5 (arm lam05): --lam 0.5, same knobs; groups reduced 22→14→12 across resume segments (see provenance).
# λ=0 (arm lam0): --lam 0.0 --shaping-weight 0 --steps 15 --checkpoint-steps 5 10 15 (selfish control, note 0050).
```
## Training provenance (width changes across resume segments)
Both larger arms were trained across compute migrations (RunPod balance exhaustion → Lambda), so the rollout **width** (`groups`) changed mid-arm. This is recorded because the GRPO group-relative baseline normalizes per-instance, so width does not confound the *contrasts*, but consumers comparing rungs should know it (0028 Amendments 9–11):
- **λ=1.0**: steps 5–25 and the resume 30–50 both at **groups=22** (B200). One fresh-Adam discontinuity at the step-25→30 resume boundary.
- **λ=0.5**: steps 1–15 at **groups=22** (RunPod B200) → 16–31 at **14** → 32–50 at **12** (Lambda H100, 80 GB fit). Fresh Adam at each resume; a completion-token-alignment guard change (drop small-drift rows) landed mid-arm.
- **λ=0**: 15 steps single segment, shaping off.
## Weights & Biases
Project `wandb.ai/siddharth-stanford/rational_agents_fairness_grpo`, group `fairness-grpo-v2`. Runs: `grpo_v2_lam1` ([npz11gav](https://wandb.ai/siddharth-stanford/rational_agents_fairness_grpo/runs/npz11gav)) → `grpo_v2_lam1_resume25`; `grpo_v2_lam05` → `grpo_v2_lam05_resume15` → `grpo_v2_lam05_resume30b`; `grpo_v2_lam0`.
## Cluster paths
- Adapters (source): `/nlp/scr/siddharth/ii_mats/rational_agents/grpo_v2/{lam1,lam1_resume25,lam05,lam05_resume15,lam05_resume30b,lam0}/checkpoint-*`
- Eval verdicts (JSON): `experiments/rational_agents/results/fairness_grpo_v2/eval_*.json`
- Eval run dirs: `/nlp/scr/siddharth/ii_mats/rational_agents/grpov2eval_*`
- Rollout transcripts: `.../grpo_v2/*/transcripts/`; training telemetry `.../*/steps.jsonl`
- Log: `experiments/rational_agents/self_benefit/LOG.md`; note: `research-notes/0028-fairness-grpo-v2.md`; λ=0 control: `research-notes/0050-lam0-selfish-control-prereg.md`
## Relation
Supersedes the v1 pilot adapters ([2026.RA.Fairness-GRPO-lam1](https://huggingface.co/siddharthmb/2026.RA.Fairness-GRPO-lam1), [-lam0](https://huggingface.co/siddharthmb/2026.RA.Fairness-GRPO-lam0); dataset [2026.RA.Fairness-GRPO](https://huggingface.co/datasets/siddharthmb/2026.RA.Fairness-GRPO)), whose "discipline without distribution" negative (note 0023) is v2's design input. Base model: [Qwen/Qwen3-8B](https://huggingface.co/Qwen/Qwen3-8B).