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
| """ | |
| Turn out_synth/generations.jsonl into the finished synthetic corpus. | |
| Re-parses and re-validates every cached generation with synth_common (the generator's inline | |
| accounting is only a progress estimate; this is the authoritative pass), drops duplicates, and | |
| writes a parquet plus the SFT splits train_reasoning.py reads directly. | |
| Duplicates are keyed on the question with its numbers masked out, so "3 apples at 5 riyal" and | |
| "7 apples at 9 riyal" collapse to one template — this is the exact failure the translated GSM8K | |
| set has (142,969 rows from 2,814 templates), and the whole point of the variation grid is to not | |
| repeat it. The template count is reported so it can be checked rather than assumed. | |
| Writes: | |
| out_synth/arabic_math_reasoning_synth.parquet the corpus | |
| out_synth/rejects.jsonl every rejected item with its reason | |
| out_synth/build_stats.json counts, reject histogram, axis coverage | |
| data_synth_sft/{train,eval}.jsonl ready for train_reasoning.py | |
| """ | |
| import collections | |
| import json | |
| import os | |
| import random | |
| from pathlib import Path | |
| import pyarrow as pa | |
| import pyarrow.parquet as pq | |
| import synth_common as sc | |
| OUT_DIR = Path(os.environ.get("OUT_DIR", "out_synth")) | |
| CACHE = OUT_DIR / "generations.jsonl" | |
| SFT_DIR = Path(os.environ.get("SFT_DIR", "data_synth_sft")) | |
| EVAL_N = int(os.environ.get("EVAL_N", 2000)) | |
| LIMIT = int(os.environ.get("LIMIT", 0)) # 0 = keep everything that validates | |
| SEED = 42 | |
| def main(): | |
| stats = collections.Counter() | |
| rejects_by_reason = collections.Counter() | |
| axes_seen = collections.defaultdict(collections.Counter) | |
| rows, rejects = [], [] | |
| seen = {} | |
| with open(CACHE, encoding="utf-8") as fh: | |
| for line in fh: | |
| try: | |
| rec = json.loads(line) | |
| except json.JSONDecodeError: | |
| stats["truncated_lines"] += 1 # a crash mid-write; the rest is still good | |
| continue | |
| stats["tasks"] += 1 | |
| items = sc.parse_items(rec["raw"]) | |
| stats["parsed_items"] += len(items) | |
| if not items: | |
| stats["tasks_with_no_parsable_item"] += 1 | |
| for item in items: | |
| ok, reason = sc.validate(item) | |
| if not ok: | |
| rejects_by_reason[reason] += 1 | |
| rejects.append({**item, "reason": reason, "task_id": rec["task_id"]}) | |
| continue | |
| key = sc.dedup_key(item["instruction"]) | |
| if key in seen: | |
| stats["dropped_duplicate_template"] += 1 | |
| continue | |
| seen[key] = True | |
| for axis, value in rec["axes"].items(): | |
| axes_seen[axis][value] += 1 | |
| rows.append({**item, **{f"axis_{k}": v for k, v in rec["axes"].items()}, | |
| "task_id": rec["task_id"], | |
| # rows cached before multi-node generation carry no model field | |
| "gen_model": rec.get("model", "gemma-3-12b-it")}) | |
| for r in rows: | |
| stats[f"model_{r['gen_model']}"] += 1 | |
| stats["kept"] = len(rows) | |
| stats["rejected"] = sum(rejects_by_reason.values()) | |
| random.Random(SEED).shuffle(rows) | |
| if LIMIT: | |
| rows = rows[:LIMIT] | |
| OUT_DIR.mkdir(exist_ok=True) | |
| pq.write_table(pa.Table.from_pylist(rows), OUT_DIR / "arabic_math_reasoning_synth.parquet") | |
| with open(OUT_DIR / "rejects.jsonl", "w", encoding="utf-8") as fh: | |
| for r in rejects: | |
| fh.write(json.dumps(r, ensure_ascii=False) + "\n") | |
| SFT_DIR.mkdir(exist_ok=True) | |
| eval_rows, train_rows = rows[:EVAL_N], rows[EVAL_N:] | |
| for name, split in (("train", train_rows), ("eval", eval_rows)): | |
| with open(SFT_DIR / f"{name}.jsonl", "w", encoding="utf-8") as fh: | |
| for r in split: | |
| fh.write(json.dumps({"instruction": r["instruction"], "reasoning": r["reasoning"], | |
| "answer": r["answer"], "source": "synth_math_ar"}, | |
| ensure_ascii=False) + "\n") | |
| print(f"[+] {name}: {len(split):,} -> {SFT_DIR / f'{name}.jsonl'}") | |
| summary = { | |
| "stats": dict(stats), | |
| "reject_reasons": dict(rejects_by_reason.most_common()), | |
| "accept_rate": stats["kept"] / max(stats["parsed_items"], 1), | |
| "unique_templates": len(seen), | |
| "axis_coverage": {k: len(v) for k, v in axes_seen.items()}, | |
| } | |
| (OUT_DIR / "build_stats.json").write_text(json.dumps(summary, ensure_ascii=False, indent=2), | |
| encoding="utf-8") | |
| print(json.dumps(summary, ensure_ascii=False, indent=2)) | |
| print(f"[+] {OUT_DIR / 'arabic_math_reasoning_synth.parquet'}") | |
| if __name__ == "__main__": | |
| main() | |