Views
No views yet
Qwen/Qwen3-4B-Instruct-2507 that turns the base model
into a phonics-aware early-reading story generator. Given a feasible request,
it produces exactly one original six-sentence story whose every word is either
a reviewed short-vowel / decodable word or an explicitly approved irregular word,
and whose plot has a complete narrative arc (character, goal, problem, relevant
attempt, causal consequence, satisfying resolution).Qwen/Qwen3-4B-Instruct-2507, pinned revision
cdbee75f17c01a7cc42f958dc650907174af0554r=16, alpha=32,
dropout=0.05License note:apache-2.0is chosen to match the base model's permissive license and is a copyright license only — it does not authorize classroom/student or production use (see limitations). Override thelicensefield if your jurisdiction or dataset terms require something different.
config/v3/r4/behavior_spec.json,
spec_id: phonics-story-slm-v3-r4-behavior-20260711). A response must satisfy:. ! ?.q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj).2e-4, cosine schedule, warmup
ratio 0.03, weight decay 0.0, max grad norm 1.0, effective batch size 16
(micro-batch 8 × grad-accum 2), seed 20260712.r=16, alpha=32, dropout=0.05, bias="none",
task_type="CAUSAL_LM".-100, only the assistant story supervised, a single terminal
<|im_end|> (id 151645) as the final supervised label with no trailing
newline, every serialized row <= 512 tokens (observed max 360).data/v3/r6/train_combined_661/, train SHA-256
00f00bba45ff7de53ce71ca10b63db28b3116daaa7fc6884d0d5b2ea496e078f) — the
pinned 288-row train-only handoff used verbatim as the exact byte prefix
followed by 373 audited r6 mass-expansion rows. Band distribution:
{1:101, 2:130, 3:52, 4:72, 5:97, 6:110, 7:99}. There are no internal
validation/test rows in this file.Trainer + PEFT + bitsandbytes.notebooks/train_qwen3_4b_lora_661_colab.ipynb in the GitHub repo.1import torch
2from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
3from peft import PeftModel
4
5BASE_MODEL_ID = "Qwen/Qwen3-4B-Instruct-2507"
6BASE_MODEL_REVISION = "cdbee75f17c01a7cc42f958dc650907174af0554"
7ADAPTER_REPO = "ravensh12/phonics-story-slm-qwen3-4b-661"
8
9tokenizer = AutoTokenizer.from_pretrained(
10 BASE_MODEL_ID, revision=BASE_MODEL_REVISION, trust_remote_code=False
11)
12
13quant_config = BitsAndBytesConfig(
14 load_in_4bit=True,
15 bnb_4bit_quant_type="nf4",
16 bnb_4bit_use_double_quant=True,
17 bnb_4bit_compute_dtype=torch.bfloat16,
18)
19base = AutoModelForCausalLM.from_pretrained(
20 BASE_MODEL_ID,
21 revision=BASE_MODEL_REVISION,
22 trust_remote_code=False,
23 quantization_config=quant_config,
24 torch_dtype=torch.bfloat16,
25 device_map="auto",
26)
27model = PeftModel.from_pretrained(base, ADAPTER_REPO)
28model.eval()
29
30messages = [
31 {"role": "system", "content": "You write one short decodable phonics story."},
32 {"role": "user", "content": "Write a six-sentence story about a lid on a bin."},
33]
34inputs = tokenizer.apply_chat_template(
35 messages, add_generation_prompt=True, return_tensors="pt", return_dict=True
36).to(model.device)
37
38with torch.inference_mode():
39 generated = model.generate(
40 **inputs,
41 do_sample=False,
42 max_new_tokens=384,
43 eos_token_id=151645, # <|im_end|>
44 pad_token_id=tokenizer.eos_token_id,
45 )
46print(tokenizer.decode(generated[0, inputs["input_ids"].shape[1]:], skip_special_tokens=True).strip())config/story_only_chat_template_v2.jinja) and a curated per-request "binding"
(target word, sense/role, authorized phonics skill+band, scaffold-word
allowlist, goal contract). For the tightest reproduction of the trained behavior,
use those bindings and template from the GitHub repo rather than free-form
prompts.DeterministicComparisonScorer scores each
candidate story on six dimensions — phonics_legality, target_sense_role,
six_sentence, one_paragraph, narrative, semantic_goal — and a
best-of-K / generate → validate → retry → fail-closed loop releases the first
candidate that passes all dimensions (or refuses). This is how the system
turns a strong-but-imperfect generator into a guaranteed-valid one; see
scripts/generate_with_validator_retry_v1.py and
scripts/run_model_comparison_v3_r4.py in the repo.Numbers below are ILLUSTRATIVE — from the earlier 288-row adapter. They are shown only to indicate the shape of the base→tuned lift. The 661-adapter figures are still being generated and will replace these once the three-way comparison (scripts/run_model_comparison_v3_r4.py) completes.
| Metric (raw single-shot, greedy) | Base Qwen3-4B | Tuned adapter (288, illustrative) |
|---|---|---|
| Legal-token rate | 71% | 99% |
| Narrative complete | 4% | 68% |
| One-paragraph / format | 40% | 100% |
| Semantic-goal satisfied | 17% | 63% |
semantic_goal remaining the hardest and
lowest-scoring dimension.docs/LIMITATIONS_V3.md in the repo for the full list):semantic_goal check enforces narrow
plan/goal consistency, not real-world common sense or literary quality.data/v3/r6/train_combined_661/ in the GitHub repo
(train SHA-256 00f00bba45ff7de53ce71ca10b63db28b3116daaa7fc6884d0d5b2ea496e078f)config/v3/r4/behavior_spec.json