CoolFace
Modelpublic

mzoelfakar/Al-Khwarizmi-3B

sourceHugging Faceapache-2.0updated 2h agoView on Hugging Face
0likes1.3kdownloads
Model Card

<table> <tr> <td style="vertical-align:middle;">

<b><i style="font-size:1rem !important;">An AI math tutor named after Muhammad al-Khwarizmi, the 9th-century mathematician whose name is the origin of the word "algorithm". Clear, step-by-step reasoning in 9 languages.</i><br><br><i><span style="font-size:1.1rem !important;">**Chat online**</span><br></b>

</td> <td width="160" align="right" style="vertical-align:middle;"><img src="assets/banner.jpg" width="150"/></td> </tr> </table>

Fine-tune of HuggingFaceTB/SmolLM3-3B-Base, trained in three stages — full fine-tuning, LoRA, and a final DPO alignment pass — to solve grade-school math word problems.

Highlights

  • —Trained on the complete OpenAI GSM8K dataset (both main and socratic reasoning styles) across two LoRA passes, on top of an initial full fine-tune
  • —87.21% mean token accuracy on held-out validation data — up from 84.75% after the initial full fine-tune, and 82.4% at the very first checkpoint
  • —Validation loss reduced by ~19% across the full pipeline (0.678 → 0.462), with training and validation loss tracking closely throughout every stage — no overfitting observed
  • —Added a final DPO (Direct Preference Optimization) stage on custom translated dataset **Mini-GSM8K-Multilingual-Alignment** with full explained steps as 'chosen' and vague digits-only answers as 'rejected' to make sure the model reasons well in the user's language.
  • —This is confirmed by the perfect chosen-vs-rejected discrimination: reward accuracy reached 100%.
  • —Available in this repo as safetensors. GGUF version with quantization (BF16 and Q8_0) for efficient usage on CPU and a smaller size **available here**

[image] [image] [image]

Training Details

<b>Stage 1 — Full fine-tuning</b>

<table> <tr><td>Dataset</td><td>OpenAI/GSM8K (<code>main</code>), 1,000 samples, 90/10 train/val split</td></tr> <tr><td>Steps</td><td>450 (1 epoch)</td></tr> <tr><td>Learning rate</td><td>5e-5, cosine schedule</td></tr> <tr><td>Final validation loss / accuracy</td><td>0.569 / 84.75%</td></tr> </table>

<b>Stage 2 — LoRA fine-tuning</b>

<table> <tr><td>Method</td><td>LoRA, r=16, all-linear target modules</td></tr> <tr><td>Dataset</td><td>Full OpenAI/GSM8K — both <code>main</code> and <code>socratic</code> reasoning styles</td></tr> <tr><td>Steps</td><td>3,550 (combined across two passes)</td></tr> <tr><td>Learning rate</td><td>5e-5, cosine schedule</td></tr> <tr><td>Final validation loss / accuracy</td><td>0.462 / 87.21%</td></tr> </table>

<i>Run as two consecutive passes over the dataset, with the <code>main</code>/<code>socratic</code> split swapped between them so every problem was seen in both reasoning styles.</i>

<b>Stage 3 — Direct Preference Optimization (DPO)</b>

<table> <tr><td>Method</td><td>LoRA-based DPO (r=16, alpha=32, targeted layers: qproj, kproj, vproj, oproj), beta=0.5</td></tr> <tr><td>Dataset</td><td>mzoelfakar/Mini-GSM8K-Multilingual-Alignment, 480 samples</td></tr> <tr><td>Steps</td><td>30 (1 epoch)</td></tr> <tr><td>Learning rate</td><td>2e-5 peak, cosine schedule, 5 warmup steps</td></tr> <tr><td>Reward accuracy</td><td>100%</td></tr> </table>

Supported Languages

English, Arabic, French, Spanish, German, Italian, Portuguese, Chinese, and Russian.

Limitations

Fine-tuned primarily on GSM8K-style problems (single correct numeric answer, grade-school arithmetic/word problems) — performance on more complex, multi-part, or differently-structured math problems is untested. Occasional arithmetic slips on multi-step problems can still occur, consistent with known limitations of models at this scale.

Recommended Settings

For the best efficiency, please use the following:

  • —Temperature: 0.7
  • —Context length: The base model supports up to 128k, this model was fine-tuned with a max sequence length of 2,048 tokens

System prompt:

You are a professional math tutor called Al-Khwarizmi.

You are always careful. Before answering:

- Use only the numbers and quantities explicitly stated in the problem. Do not introduce, assume, or carry over any value that wasn't given.
- Compute each arithmetic operation one at a time, and verify each result before using it in the next step.
- If asked to recheck or redo a calculation, ignore your previous answer entirely and recompute from the stated numbers.
- Before finalizing your answer, check whether every quantity mentioned in the problem (fees, taxes, discounts, additions) has been included in the final result — not just the main calculation.
- When asked to redo or resolve a problem "based on" a previous correction, use that corrected value as the starting point. Do not revert to an earlier, uncorrected path.
- Avoid sharing numbers only, always include text explanations. Apologize if you don't know the answer.

LANGUAGE RULES:

- You MUST ALWAYS reply in the SAME LANGUAGE AND SCRIPT from the user's last message, NEVER use another lanaguage, examples:

Query: مرحبا
Reply: اهلا كيف يمكنني مساعدك؟

Query: Bojour
Reply: Bonjour ! Comment ça va ?

- If the user switched language and script mid-conversation, use their new language and script, example: 

Query: اسمك إيه؟
Reply: الخوارزمي
Query: All good?
Reply: I'm fine thanks, how about you?

REFRAIN from repeating unnecessary information.
NEVER help with ANY topics OTHER than math like cooking, sports etc. If asked, redirect gently.

Usage

python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model_name = "mzoelfakar/Al-Khwarizmi-3B"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, dtype=torch.bfloat16, device_map="auto")

messages = [
    {"role": "system", "content": "You are a math tutor. Solve problems step by step."},
    {"role": "user", "content": "If a train travels 120 miles in 2 hours, what is its average speed?"}
]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=300, temperature=0.7, do_sample=True)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

Calculator-in-the-loop

Al-Khwarizmi-3B writes GSM8K-style <<expression=result>> annotations, so at inference time you can pause generation as soon as the model emits = inside a <<…>> block, calculate the precise result with a calculator, append the exact result, and resume generating from the extended text (the online chat demo includes a ready-made StoppingCriteria loop), which corrects arithmetic slips without changing the weights.

Note on raw output formatting

Because this model was fine-tuned on GSM8K (including the socratic reasoning style), raw generations may contain training artifacts not meant for direct display:

  • —<<...>> — calculator intermediate annotations
  • —** — separator between a sub-question and its calculation in Socratic-style reasoning (not Markdown bold)
  • —#### <answer> — marker preceding the final numeric answer
  • —* — used as a multiplication sign (e.g. 8*9); if two or more appear in the same response, Markdown may pair them as emphasis delimiters, causing text between them to render in italic with the asterisks hidden

If you're piping output through a Markdown renderer or displaying it in a UI, you'll likely want to strip or reformat these first, since ** in particular can be misread as Markdown bold syntax if left unescaped.

Training Code

The full training code is available here.

Credits

Fine-tuned by Mohamed Zoelfakar, as part of Hugging Face's smol-course, at Nvidia Studio Cairo.

License

Released under the Apache License 2.0.