Qwen/Qwen3-4B-Instruct-2507, built to run on-prem / offline on a customer's own GPU — privacy is the point.⚠️ Read the honest eval below before using. v0 is excellent on validity and grounding but has a real-world recall blind spot on narrative diagnoses/procedures. SeeMIRA3_LEARNINGS.mdfor the full analysis and how to fix it.
adapter/ — the shipping adapter (epoch 3, best by eval)epochs/epoch_{1,2,3}/ — per-epoch adapters (for reproducibility / best-epoch verification)training/metrics.json, training/env_versions.json — training run + exact dependency stackeval/probe_scorecard_v11.json — real-doc probe validity + hallucination + leakeval/phase25_gate_v11.json — Phase-2.5 exit gate verdict (PASS)eval/realdoc_eval_v11.json — the honest labeled real-doc field-F1 (with adjudicated gold)MIRA3_LEARNINGS.md — detailed, reusable playbook (generalizes to other extraction/OCR verticals, e.g. résumé parsing)| Base | Qwen/Qwen3-4B-Instruct-2507 (Unsloth 4-bit) |
| Method | QLoRA (4-bit + LoRA r16/α32, dropout 0.05), Unsloth, sequence packing |
| Data | 21k rows: 15k ladder + 3k schema-variant + 3k PII-abstention (synthetic + public) |
| Schedule | 3 epochs, lr 2e-4 cosine, warmup 3%, effective batch 16, max_seq 3072 |
| Compute | Kaggle T4, 2 sessions (~20.7h) via lossless checkpoint/resume |
| Loss | 1.363 → 0.133 (clean cosine decay; natural completion at 867/867 steps) |
| Probe (real docs) | JSON validity | Hallucination (↓ better) |
|---|---|---|
| mtsamples_282 | 1.00 | 0.28 |
| extraction_relevant_150 | 1.00 | 0.52 |
| synthetic_v2_150 | 1.00 | 0.13 |
| identifier leak | — | 0 everywhere |
Diagnoses:-style blocks (as in the synthetic training data) but misses them when stated in prose (real clinical notes). This is a data-coverage issue, targeted for v1. Do not rely on v0 for complete diagnosis capture from free-text notes.1import torch
2from unsloth import FastLanguageModel # load with Unsloth, NOT vanilla PeftModel (4-bit quant mismatch)
3
4model, tok = FastLanguageModel.from_pretrained(
5 "dilr/mira-3-v11/adapter", max_seq_length=4096, dtype=torch.float16, load_in_4bit=True)
6FastLanguageModel.for_inference(model)
7
8SYSTEM = ("You are a clinical information extraction system. Read the clinical document and "
9 "output a single JSON object matching the schema. Extract ONLY information explicitly "
10 "stated ... Output valid JSON only - no prose, no markdown.") # full prompt in the training data
11
12msgs = [{"role": "system", "content": SYSTEM}, {"role": "user", "content": document_text}]
13text = tok.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True)
14out = model.generate(**tok(text, return_tensors="pt").to("cuda"), max_new_tokens=2048, do_sample=False)
15raw = tok.decode(out[0], skip_special_tokens=True)
16# NOTE: Qwen3 prepends a <think>...</think> block — strip it before json.loads():
17import re, json
18pred = json.loads(re.sub(r"^\s*<think>.*?</think>\s*", "", raw.split("assistant")[-1], flags=re.DOTALL))