Instructions to use IAO26/sim-student-3b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use IAO26/sim-student-3b with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
Sim-Student 3B β a LoRA adapter for simulated struggling-student fidelity
Open release (public good). The adapter weights here are a derivative of the Apache-2.0
Qwen2.5-3B-Instructbase and are released openly so others can study and reuse the method. Not included: the SFT training data (it's distilled from a frontier model β its redistribution is a separate question and is deliberately left out of this repo). What's published is the adapter, the card, and the measured before/after results β enough to load, evaluate, and reproduce the recipe.
A LoRA adapter that turns Qwen2.5-3B-Instruct into a simulated struggling-student learner β
a synthetic teen the team can use to train and evaluate college-advising systems (human advisors or
advising AI) against realistic learner failure modes.
- Base model:
Qwen/Qwen2.5-3B-Instruct(Apache-2.0) - Adapter: LoRA r=16 / Ξ±=32, dropout default,
all-linear, assistant-only loss - Training: SFT, 3 epochs, 212 frontier-distilled + rubric-filtered student turns (v1) / 197 augmented-not-knowing turns (v2, eval probes held out); ~81k train tokens
- Two adapters shipped in this repo (so you can compare training regimes):
adapter_v2/β the headline model Β· Together jobft-ce2b985d-1642Β· augmented not-knowing, held-out probes Β· fabrication 40%β31%, sycophancy 24%β12%. Use this one.adapter_v1/β natural-gold baseline Β· Together jobft-d8c56013-d7deΒ· sycophancy 24%β8%, fabrication flat 40% (the run that revealed the train/eval data gap).
- Cost: ~$4 per LoRA run Β· ~$12 total across the whole beforeβafter program
What it's for β and what it is NOT
Intended use (internal): drive a synthetic, in-character teen learner so advisors / advising-AI can practice against realistic failure modes β sycophancy under bad advice, partial not-knowing, in-persona affect β and so we can measure an advising system's quality against a consistent simulated student.
NOT for:
- β a student-facing tutor or chatbot β it role-plays a learner, it does not advise
- β a source of real financial-aid / policy facts β it will confidently state wrong ones (see limits)
- β representing a real person β the personas are synthetic composites
Measured results β prompted-3B "before" β fine-tuned "after"
Same 60-probe battery, same ruler (A1's de-biased gpt-4o judge + correctness audit), applied identically to both arms. Directional (n is small β see limits), not tight confidence intervals.
| dimension | scale / direction | BEFORE (prompted 3B) | AFTER (LoRA) | read |
|---|---|---|---|---|
| sycophancy (cave) | % failed, β better | 24% | 8β12% | WIN β ~2β3Γ cut, lands at the Qwen3-4B-Instruct reference (8%) |
| confident-fabrication | % failed, β better | 40% | 31% | moved on held-out probes = generalization, not memorization |
| true-leak (correct expert content) | % failed, β better | 6% | 3β6% | low both arms |
| overshoot (competence-beyond-profile) | x/5, β better | ~5/5 | 5/5 | clean both arms β 3B doesn't overshoot; not a differentiator at this scale |
| drift (persona consistency, PFC) | 0β1, β better | 1.0 | 1.0 | clean both β artifact of per-turn persona re-grounding (uninformative) |
| affect (in-persona emotion) | x/5, β better | ~4.5 | ~3.75 | mild regression β FT flattened emotion slightly (honest trade-off; low-conf scorer) |
β οΈ Read the scale direction per row. The probe dims are % failures (higher = worse); the transcript dims are fidelity scores (higher = better).
overshoot 5/5means no overshoot (good), not "everyone has the issue."
Headline (defensible): a $4 LoRA on 212 frontier-distilled examples cut a cheap open model's sycophancy ~2β3Γ (24%β8β12%), to frontier-reference levels, and moved confident-fabrication 40%β31% on held-out probes β directional proof the open-model + SFT method works on the fidelity axis.
Cost story (the thesis): ~$4 to train, ~$12 total; at saturated inference the open 3B is ~10β40Γ cheaper per conversation than GPT-4o. Framed as fidelity-per-dollar β the cheapest open model moved measurably toward frontier behavior. (Cheap only when the serving endpoint is busy; idle = waste.)
Limitations (read before trusting any number)
- Small n β 25 cave / 35 leak probes (5 samples each): directional, not tight CIs.
- Confabulation only partly fixed (40%β31%). Root cause is verified, not under-training: natural
advising transcripts never quiz a policy fact (0/212 advisor turns do), so "not-knowing on a specific
fact" can't be learned from natural gold β a train/eval distribution mismatch, not a method failure.
Full writeup:
METHOD_FINDING_train_eval_gap.md. The fabrication drop is uneven (driven by one persona, yesenia; tasha flat β a per-persona topic-coverage gap = the concrete next lever). - Overshoot / drift are uninformative at 3B scale β clean in both arms (drift is suppressed by per-turn re-grounding). Don't read them as wins; read them as "not measurable here."
- Affect ticked the wrong way (~4.5β3.75) β a mild, disclosed regression from the FT.
- Not production-grade β 212 examples is a small demo LoRA, well under the 500β3,000 spec.
How to load / serve
The weights are in this repo under adapter_v2/ (headline) and adapter_v1/ (baseline) β each a
full LoRA adapter + tokenizer. Load either with PEFT (point at the subfolder you want):
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
from huggingface_hub import snapshot_download
repo = "IAO26/sim-student-3b"
local = snapshot_download(repo) # private repo β needs `huggingface-cli login`
base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-3B-Instruct")
tok = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-3B-Instruct")
model = PeftModel.from_pretrained(base, f"{local}/adapter_v2") # or adapter_v1 to compare
Re-export from Together (if you ever need to):
together fine-tuning download <job-id> --output-dir <out> --checkpoint-type adapter β unpack the
.tar.zst (it's zstdβtar). Job IDs: v2 = ft-ce2b985d-1642, v1 = ft-d8c56013-d7de.
To reproduce the serving we used: qwen/endpoint.py (Together dedicated endpoint) +
qwen/together_client.py. The endpoint name is the working model-id (the slug 400s).
How the internal "view" stays current (the retrain loop)
The comparison view in this repo is static but regeneratable β each new training round updates it:
- retrain β
qwen/finetune.py --run(new adapter) - re-measure β
before_baseline.pyβjudge_rescore.pyβleak_audit.pyβgen_convos.py - rebuild
results/(scoreboard + transcripts +compare.html) andgit pushto the HF repo - each push is a versioned commit/tag β IAO can compare v1 vs v2 vs v3 over time, not just before-vs-after
- Downloads last month
- -