Text Generation
Transformers
Safetensors
Arabic
llama
arabic
reasoning
chain-of-thought
math
gsm8k
small-language-model
slm
sft
conversational
text-generation-inference
Instructions to use oddadmix/Nawah-Math-Reasoning with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use oddadmix/Nawah-Math-Reasoning with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="oddadmix/Nawah-Math-Reasoning") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("oddadmix/Nawah-Math-Reasoning") model = AutoModelForCausalLM.from_pretrained("oddadmix/Nawah-Math-Reasoning", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use oddadmix/Nawah-Math-Reasoning with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "oddadmix/Nawah-Math-Reasoning" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "oddadmix/Nawah-Math-Reasoning", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/oddadmix/Nawah-Math-Reasoning
- SGLang
How to use oddadmix/Nawah-Math-Reasoning with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "oddadmix/Nawah-Math-Reasoning" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "oddadmix/Nawah-Math-Reasoning", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "oddadmix/Nawah-Math-Reasoning" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "oddadmix/Nawah-Math-Reasoning", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use oddadmix/Nawah-Math-Reasoning with Docker Model Runner:
docker model run hf.co/oddadmix/Nawah-Math-Reasoning
| """ | |
| Assemble the Arabic dataset from the translation cache and validate it. | |
| Validation per row (a translation is only kept if it passes): | |
| * both segments translated and non-empty | |
| * the numbers in the Arabic text match the English exactly (order-insensitive multiset) | |
| * no degenerate repetition loop from the translator | |
| * not left largely untranslated (Latin-script residue) | |
| Writes out_gsm/gsm8k_reasoning_ar.parquet plus a rejects file for inspection/retry. | |
| """ | |
| import collections | |
| import json | |
| import re | |
| import sys | |
| from pathlib import Path | |
| import pyarrow as pa | |
| import pyarrow.parquet as pq | |
| sys.path.insert(0, ".") | |
| from gsm_common import build_record | |
| OUT = Path("out_gsm") | |
| AR_DIGITS = str.maketrans("٠١٢٣٤٥٦٧٨٩", "0123456789") | |
| NUM_RE = re.compile(r"\d+(?:\.\d+)?") | |
| LATIN_RE = re.compile(r"[A-Za-z]") | |
| ARABIC_RE = re.compile(r"[-ۿ]") | |
| def numbers(text): | |
| return NUM_RE.findall(text.translate(AR_DIGITS).replace(",", "")) | |
| def has_repetition_loop(text, n=6, times=3): | |
| """Detect the translator getting stuck repeating an n-word window.""" | |
| words = text.split() | |
| if len(words) < n * times: | |
| return False | |
| counts = collections.Counter( | |
| " ".join(words[i : i + n]) for i in range(len(words) - n + 1) | |
| ) | |
| return counts.most_common(1)[0][1] >= times | |
| VERBALISABLE_MAX = 12 # Arabic writes small quantities as words ("ضعف" for 2, "الستة" for 6) | |
| def check(en, ar, strict=True): | |
| """ | |
| strict=True (reasoning chains): every numeral must survive exactly — the arithmetic depends | |
| on it. strict=False (questions): a small number may be verbalised, but a number the source | |
| never contained is a translation error (observed: '$13751' -> '13571', '4 × 44' -> '4 × 46'), | |
| which silently corrupts the math and is always rejected. | |
| """ | |
| if not ar or not ar.strip(): | |
| return "empty" | |
| en_n, ar_n = collections.Counter(numbers(en)), collections.Counter(numbers(ar)) | |
| if ar_n - en_n: | |
| return "invented_number" | |
| missing = en_n - ar_n | |
| if missing: | |
| if strict: | |
| return "number_dropped" | |
| if any(float(v) > VERBALISABLE_MAX for v in missing): | |
| return "number_dropped" | |
| if has_repetition_loop(ar): | |
| return "repetition" | |
| if not ARABIC_RE.search(ar): | |
| return "not_arabic" | |
| latin = len(LATIN_RE.findall(ar)) | |
| if latin > 0.25 * len(ar.replace(" ", "")): | |
| return "latin_residue" | |
| return None | |
| def main(): | |
| trans = {} | |
| with open(OUT / "translations.jsonl", encoding="utf-8") as fh: | |
| for line in fh: | |
| try: | |
| r = json.loads(line) | |
| except json.JSONDecodeError: | |
| continue | |
| trans[r["src"]] = r["tgt"] | |
| print(f"[*] {len(trans)} cached translations") | |
| rows = [json.loads(l) for l in open(OUT / "selected_rows.jsonl", encoding="utf-8")] | |
| print(f"[*] {len(rows)} selected rows") | |
| kept, rejects = [], [] | |
| reasons = collections.Counter() | |
| for r in rows: | |
| q_ar, t_ar = trans.get(r["question"]), trans.get(r["thinking"]) | |
| if q_ar is None or t_ar is None: | |
| reasons["missing"] += 1 | |
| rejects.append({**r, "reason": "missing"}) | |
| continue | |
| why = check(r["question"], q_ar, strict=False) or check(r["thinking"], t_ar, strict=True) | |
| if why: | |
| reasons[why] += 1 | |
| rejects.append({**r, "question_ar": q_ar, "thinking_ar": t_ar, "reason": why}) | |
| continue | |
| kept.append( | |
| { | |
| "text": build_record(q_ar, t_ar, r["answer"]), | |
| "question": q_ar, | |
| "thinking": t_ar, | |
| "answer": r["answer"], | |
| "question_en": r["question"], | |
| "thinking_en": r["thinking"], | |
| "source_index": r["idx"], | |
| } | |
| ) | |
| print(f"[*] kept {len(kept)}/{len(rows)} ({len(kept)/len(rows):.2%})") | |
| print(f"[*] rejects: {dict(reasons)}") | |
| table = pa.table({k: [row[k] for row in kept] for k in kept[0]}) | |
| pq.write_table(table, OUT / "gsm8k_reasoning_ar.parquet", compression="zstd") | |
| print(f"[+] wrote {OUT / 'gsm8k_reasoning_ar.parquet'} ({table.num_rows} rows)") | |
| with open(OUT / "rejects.jsonl", "w", encoding="utf-8") as fh: | |
| for r in rejects: | |
| fh.write(json.dumps(r, ensure_ascii=False) + "\n") | |
| print(f"[+] wrote {OUT / 'rejects.jsonl'} ({len(rejects)} rows)") | |
| stats = { | |
| "selected": len(rows), | |
| "kept": len(kept), | |
| "kept_pct": 100 * len(kept) / len(rows), | |
| "rejects": dict(reasons), | |
| "unique_translations": len(trans), | |
| } | |
| (OUT / "build_stats.json").write_text(json.dumps(stats, ensure_ascii=False, indent=2), encoding="utf-8") | |
| for row in kept[:3]: | |
| print("-" * 70) | |
| print("EN:", row["question_en"][:120]) | |
| print("AR:", row["question"][:120]) | |
| print("AR think:", row["thinking"][:160]) | |
| if __name__ == "__main__": | |
| main() | |