Views
No views yet
<think>…</think> reasoning, then GRPO to reinforce correct final answers while discouraging overly long hidden reasoning.<final> tag in this project. The final answer is emitted as \boxed{...} after the <think> block.The model can emit<think>…</think>tokens. Examples below strip this by default.
google/gemma-3-270m= 1.0 if the boxed answer matches ground truth (numeric or sympy-equivalent), else 0.0, minus a small penalty proportional to tokens inside <think>…</think>. KL regularization to the SFT reference.<final> tag):1<prompt>
2<YOUR_QUESTION_HERE>
3</prompt>
4<think>
5…(internal scratch work)…
6</think>
7\boxed{FINAL_ANSWER}format_sft_example(question, reasoning, final_answer)<prompt>…</prompt>\n<think>\n and expect the model to write reasoning + \boxed{...}.1from transformers import AutoTokenizer, AutoModelForCausalLM
2import torch, re
3
4MODEL_ID = "nirav-madhani/gemma3-270m-grpo-math" # change if different
5
6tok = AutoTokenizer.from_pretrained(MODEL_ID, use_fast=True)
7if tok.pad_token is None:
8 tok.pad_token = tok.eos_token
9
10device = "cuda" if torch.cuda.is_available() else "cpu"
11model = AutoModelForCausalLM.from_pretrained(
12 MODEL_ID,
13 torch_dtype=torch.float32,
14 low_cpu_mem_usage=True,
15 attn_implementation="eager",
16).to(device).eval()
17
18BOX_RE = re.compile(r"\\boxed\\{([^{}]+)\\}")
19
20def generate(question, max_new_tokens=160, temperature=0.2, top_p=0.95, return_boxed=True, show_think=False):
21 prompt = f"<prompt>\n{question}\n</prompt>\n<think>\n"
22 inputs = tok(prompt, return_tensors="pt").to(device)
23 with torch.no_grad():
24 out = model.generate(
25 **inputs,
26 max_new_tokens=max_new_tokens,
27 do_sample=temperature > 0,
28 temperature=temperature,
29 top_p=top_p,
30 eos_token_id=tok.eos_token_id,
31 pad_token_id=tok.pad_token_id,
32 use_cache=True,
33 )
34 text = tok.decode(out[0], skip_special_tokens=True)
35 if not show_think:
36 text = re.sub(r"<think>.*?</think>\s*", "", text, flags=re.S)
37 if return_boxed:
38 m = BOX_RE.search(text)
39 return m.group(1).strip() if m else text.strip()
40 return text
41
42print(generate("If 3x + 5 = 17, what is x?"))transformers==4.55.x, trl==0.21.0pad_token = eos_tokenTrainer + DataCollatorForLanguageModelingmax_seq_length = prompt_len + completion_len; small per-device batch with grad accumulation; BF16/FP16 on Ampere, else FP32.trl==0.21.0)+1.0 if \boxed{...} equals ground truth (float tolerance or sympy equivalence)−λ * (#tokens inside <think>…</think>)num_generations (K): 2–8per_device_train_batch_size: 1–2gradient_accumulation_steps: 4–8batch * accum * world_size is divisible by K)max_prompt_length: ~160–256max_completion_length: ~128–192beta (KL): ~0.02attn_implementation="eager"; enable use_cache=True if you have headroom/kaggle/working.checkpoint-XXXX/, else RL root → SFT → base.\boxed{…} and checking numeric or sympy-equivalence. Track:license: gemma. Review Gemma’s terms before commercial use/redistribution.attn_implementation="eager" to avoid FA mismatches.0.0 — monitor reward/KL/length.TRANSFORMERS_NO_TORCHVISION=1,numpy/scikit-learn on Kaggle if transformers.generation pulls sklearn.google/gemma-3-270mtrl==0.21.0)1@software{nirav_gemma3_270m_grpo_math_2025,
2 title = {Gemma-3-270M GRPO (math + CoT)},
3 author = {Nirav Madhani},
4 year = {2025},
5 url = {https://huggingface.co/nirav-madhani/gemma3-270m-grpo-math}
6}