Views
No views yet
Thesis: behavior from data, not smarts from scale. This 1.7B model does not out-think a frontier model. It does one narrow thing reliably that a well-prompted base model cannot: apply a fixed pedagogy policy every time, in character, without drifting.
PROBLEM and the STUDENT's latest message:PROBLEM: What is 15 * 3?
STUDENT: I got 43.1{
2 "expected_answer": "45",
3 "student_state": "wrong_answer",
4 "diagnosis": "arithmetic_slip",
5 "move": "give_hint",
6 "message": "Your method is right, so slow down and recheck the arithmetic in your last step.",
7 "reveals_answer": false
8}expected_answer — the correct answer, computed privately first (never shown to the
student). Forcing this as the first field is a "compute-then-classify" step: the model must
work out the answer before it can judge whether the student is right or wrong.student_state — no_attempt · asking_for_answer · stuck · partial · wrong_answer · correct_answerdiagnosis — none · arithmetic_slip · wrong_operation · order_of_operations · misread_problem · concept_gap · incomplete_stepsmove — ask_probing_question · give_hint · affirm_and_confirm · redirect_no_answer · encourage_retrymessage — the tutor's reply (≤ 2 sentences), calibrated to the diagnosis, never a
restatement of the problem, never containing the answer.reveals_answer — true only when the student already stated the correct answer.| student_state | legal moves | reveals_answer |
|---|---|---|
no_attempt | ask_probing_question, give_hint | false |
asking_for_answer | redirect_no_answer | false |
stuck | give_hint, ask_probing_question, encourage_retry | false |
partial | give_hint, ask_probing_question, encourage_retry | false |
wrong_answer | give_hint, ask_probing_question (diagnosis must be specific) | false |
correct_answer | affirm_and_confirm | true |
| metric | base (well-prompted) | tuned | delta |
|---|---|---|---|
| structured_exact (whole move correct) | 0.167 | 0.833 | +0.666 |
| diagnosis_exact (right misconception) | 0.458 | 0.917 | +0.459 |
| policy_ok (legal move + correct flags) | 0.542 | 1.000 | +0.458 |
| leak_ok (never reveals the answer) | 0.750 | 1.000 | +0.250 |
Qwen/Qwen3-1.7B. Use the same system prompt it was trained
with (below), and greedy decoding.1from transformers import AutoModelForCausalLM, AutoTokenizer
2from peft import PeftModel
3import torch
4
5BASE = "Qwen/Qwen3-1.7B"
6ADAPTER = "mokshpshah/qwen3-1.7b-socratic-tutor"
7
8tok = AutoTokenizer.from_pretrained(BASE)
9model = AutoModelForCausalLM.from_pretrained(BASE, torch_dtype="auto", device_map="auto")
10model = PeftModel.from_pretrained(model, ADAPTER).eval()
11
12SYSTEM_PROMPT = (
13 "You are a Socratic math tutor. Given a math PROBLEM and the STUDENT's latest "
14 "message, respond with a SINGLE JSON object and nothing else (no markdown, no prose).\n\n"
15 'Think first. The FIRST key, "expected_answer", is the correct final answer that YOU '
16 "compute privately (the student never sees it). Use it to judge whether the student's "
17 "number is right.\n\n"
18 "Schema (all keys required, in this exact order): expected_answer, student_state, "
19 "diagnosis, move, message, reveals_answer.\n"
20 "Policy: asking_for_answer -> redirect_no_answer (reveals false); correct_answer -> "
21 "affirm_and_confirm (reveals true); wrong_answer -> a specific diagnosis + give_hint/"
22 "ask_probing_question (reveals false); never put the final answer in message unless the "
23 "student already stated it correctly."
24)
25
26user = "PROBLEM: What is 15 * 3?\nSTUDENT: I got 43."
27text = tok.apply_chat_template(
28 [{"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user}],
29 tokenize=False, add_generation_prompt=True, enable_thinking=False,
30)
31inputs = tok(text, return_tensors="pt").to(model.device)
32with torch.no_grad():
33 out = model.generate(**inputs, max_new_tokens=200, do_sample=False,
34 pad_token_id=tok.eos_token_id)
35print(tok.decode(out[0][inputs.input_ids.shape[-1]:], skip_special_tokens=True))The full system prompt used in training lives intutor/policy.py(SYSTEM_PROMPT) in the project repo — copy it verbatim for best results.
Qwen/Qwen3-1.7B (Instruct)