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-Instruct base 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 job ft-ce2b985d-1642 Β· augmented not-knowing, held-out probes Β· fabrication 40%β†’31%, sycophancy 24%β†’12%. Use this one.
    • adapter_v1/ ← natural-gold baseline Β· Together job ft-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/5 means 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:

  1. retrain β†’ qwen/finetune.py --run (new adapter)
  2. re-measure β†’ before_baseline.py β†’ judge_rescore.py β†’ leak_audit.py β†’ gen_convos.py
  3. rebuild results/ (scoreboard + transcripts + compare.html) and git push to the HF repo
  4. 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
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Model tree for IAO26/sim-student-3b

Base model

Qwen/Qwen2.5-3B
Adapter
(1282)
this model