albaraahegaz/Fahman

Fahman — Arabic reading tutor for ages 6-9

TypeScript

0

4 commits

updated Sep 12, 2026

See the code

README

فَهْمان — Fahman

Arabic-first reading tutor for ages 6–9.

نقرأ سوا. والإجابة تيجي منك.

Fahman doesn’t read it for them. It teaches them to read it.

Hackathon: GDG on Campus ECU × Union Mindz — Build AI that earns its impact.

Fahman leaderboard score


1. The problem (30 seconds)

A generic bot sees بَابْ and says the word. The child copies. That is not reading.

Fahman never says or writes the full word first. It shows the word, asks Socratic questions about letter shape and dots, then (only after the child succeeds) speaks the word and gives the meaning.


2. What to demo (judges — 2 minutes)

Do this path. Do not start with photo or microphone.

  1. Contrast (optional): ChatGPT / any bot → type بَابْ → it reads the word. That is the gap.
  2. Open http://localhost:3000
  3. أو اختَر كلمة من القائمة → حصان or ثعلب
  4. Tap a wrong letter (e.g. ت instead of ن on حصان).
    • You should see a guiding question such as: بص على الحرف الأخير. النقط فوق ولا تحت؟ وكم نقطة؟
    • Fahman must not say the full word.
  5. Finish every letter. Success: صح. دي قراءتك. + meaning.
  6. اسمع الكلمة (normal). اسمعها بطيء (slower). Needs internet (Edge TTS).
  7. حروفي — gold = strong, terracotta = weak.

Photo / mic / upload use the same lesson. If they fail, the list still works. JSON questions work even if Nile-Chat is down.


3. Product rules (final form)

RuleWhat we do
Never spoil the wordNo correct full-word button. Choices are letters only (ث / ت / ب).
Whole wordChild walks letter by letter. Full word is spoken only at the end.
3 wrongs on one letterPlay that letter’s sound, show it, stay on the same letter. Do not skip to the next word.
New / unknown wordsStill a lesson (unknownItem). No crash on empty JSON match.
OCR mistakesConfirm/edit screen. We do not train OCR.
VowelsMishkal only. Dataset JSON is the question bank, not the vocalizer.
VoiceEdge TTS ar-EG-SalmaNeural. No MMS-TTS.
Tutor LLMNile-Chat via Ollama /api/generate. If it fails or says the blocked word → JSON q_level_*.

Dropped on purpose (do not bring back): MMS-TTS, Tashkeel-50M, fine-tuning Qari/Whisper/Edge on the 189-row sheet.


4. Architecture

Browser (Next.js :3000, RTL, Cairo + Amiri)
    │
    ├─ /              photo, mic, upload, 22-word list
    ├─ /lesson        letter walk + Nile/JSON questions
    └─ /dashboard     حروفي (localStorage memory)
            │
            ▼
FastAPI (Python :8001)
    ├─ /tashkeel      Mishkal (+ JSON tashkeel fallback for known words)
    ├─ /ocr           Qari-OCR-v0.3 (CPU, first call is slow)
    ├─ /transcribe    Whisper-small (ffmpeg → WAV → numpy)
    ├─ /tutor         Ollama Nile-Chat-4B generate, else fallback
    └─ /tts           Edge TTS (internet). ?slow=1 → slower rate
            │
            ▼
Ollama :11434   model: hf.co/mradermacher/Nile-Chat-4B-GGUF:Q4_K_M

UI: paper #F6F0E6, indigo #1B2A4A, teal #0F7B6C, gold #E8A838, terracotta #D4654A.


5. How the lesson works

  1. Word comes from the list (JSON word_tashkeel), OCR confirm, mic, or upload.
  2. Current letter is highlighted. Buttons are three letters, never the full word.
  3. First question is positional (إيه الحرف الأول؟ / إيه آخر حرف؟).
  4. Wrong tap loads the matching curriculum row (letter_true + letter_wrong) and shows:
    • 1st wrong → q_level_1 (dots above/below, how many)
    • 2nd wrong → q_level_2 (e.g. نقطة واحدة فوق. يبقى الحرف إيه؟)
    • 3rd wrong → letter TTS + q_level_3 (ن ولا ت؟)
  5. Correct letter → next slot. Last letter correct → meaning + full-word TTS.
  6. Student memory (localStorage key fahman-memory-v1) marks letters weak/strong for حروفي.

Nile-Chat is asked on the first question of a letter (flavor). After a wrong tap, JSON is the source of truth so the demo does not depend on Ollama latency.


6. Data

FileRole
data/fahman.jsonApp + tutor. 189 rows, 22 unique words.
data/fahman_dataset.xlsxSame curriculum in Excel.

Each row includes: word_tashkeel, error_code, letter_true / letter_wrong, q_level_1…q_level_4, blocked_word, nile_facts, meaning.

This JSON is not used to train OCR or Whisper.


7. Models (working, not fine-tuned)

PieceModelNotes
TutorNile-Chat-4B GGUF Q4_K_M via OllamaMust use /api/generate (chat returns empty).
OCRNAMAA-Space/Qari-OCR-v0.3-VL-2B-InstructFirst call loads ~2B on CPU. Can confuse س/ش, ع/غ. Confirm/edit.
ASRopenai/whisper-smallArabic transcribe. First load is slow.
DiacritizeMishkalDo not swap.
TTSEdge ar-EG-SalmaNeuralNeeds internet.
ffmpegBundled imageio-ffmpeg in the venvConverts uploads to WAV.

Weights for OCR/Whisper live in the Hugging Face cache (not inside this repo), usually:

C:\Users\<you>\.cache\huggingface

Ollama weights live in Ollama’s own directory, not this repo.


8. Run (this machine)

Teammates: double-click setup.cmd once, then run.cmd every time. Details in HOW-TO-RUN.md.

Need Node, Python 3.12, Ollama, and internet (TTS).

Leave three processes running.

Terminal A — Ollama

ollama serve

If you see bind: Only one usage of each socket address on port 11434, Ollama is already running. Skip this terminal.

Pull once (if missing):

ollama pull hf.co/mradermacher/Nile-Chat-4B-GGUF:Q4_K_M

Terminal B — API (port 8001, not 8000)

cd C:\Users\Mosta\OneDrive\Documents\Education-system
.venv\Scripts\activate
python -m uvicorn server.main:app --port 8001

Wait for: Uvicorn running on http://127.0.0.1:8001

Terminal C — website

cd C:\Users\Mosta\OneDrive\Documents\Education-system
npm run dev

If npm is missing: "C:\Program Files\nodejs\npm.cmd" run dev

Open http://localhost:3000

.env.local:

NEXT_PUBLIC_API_URL=http://127.0.0.1:8001

9. Copy to another PC or disk

Copying this folder alone is not enough.

Copy

  • This repo: app/, lib/, data/, server/, package.json, package-lock.json, .env.local, setup.cmd, run.cmd, HOW-TO-RUN.md
  • Optional: skip node_modules, .next, .venv (recreate them with setup.cmd)

Does not live in the repo (copy separately or re-download)

  • Hugging Face cache (OCR + Whisper)
  • Ollama + Nile-Chat model
  • Python / Node / Ollama installs

On the new Windows PC

  1. Install Python 3, Node.js, Ollama.
  2. Recreate venv (do not reuse another machine’s .venv paths):
python -m venv .venv
.venv\Scripts\activate
pip install -r server\requirements.txt

server/requirements.txt lists the direct packages. If install is incomplete, on the original PC run pip freeze > server\full-freeze.txt and install that file.

  1. npm install then npm run dev
  2. ollama pull hf.co/mradermacher/Nile-Chat-4B-GGUF:Q4_K_M
  3. Start uvicorn on 8001

Edge TTS still needs internet on the new machine.


10. API (for judges who ask)

MethodPathRole
GET/health{ ok, ollama }
POST/tashkeelMishkal diacritics
POST/ocrImage → Arabic word
POST/transcribeAudio → text
POST/tutorNile question or JSON fallback
GET/tts?text=Speak. Add letter=1 for a single letter. Add slow=1 for slow word.

11. Honest limits (say this if asked)

  • TTS needs Microsoft Edge online. Offline → الصوت مش جاهز دلوقتي. القراءة شغالة. The lesson still stands.
  • Mic / upload need Whisper. First load can take a minute. Prefer the word list in a noisy hall.
  • OCR is not trained on our sheet. Confirm/edit is the product answer to س/ش mistakes.
  • Nile can be slow on CPU. Wrong-letter questions come from JSON so the child is never stuck.
  • Port 8000 was blocked on the build machine; API is 8001.

12. How we got here (build log)

  1. Curriculum — 189 error rows / 22 words from the curated Excel → fahman.json with q_level_*, blocked_word, error_code.
  2. App — Next.js 15 App Router + FastAPI. Three screens only.
  3. Vowels — Tashkeel-50M hallucinated; switched to Mishkal and kept it.
  4. TTS — MMS said لاب for باب; switched to Edge Salma. Slow rate only on اسمعها بطيء; normal play uses the original Edge call (no extra rate).
  5. Tutor — Ollama /api/chat returned empty; switched to /api/generate.
  6. OCR — Qari 0.2.2.1 had no weights; 0.3 VL 2B. No fine-tune. Confirm/edit screen.
  7. Lesson — Removed full-word spoiler buttons. Letter-only choices. Walk the whole word. 3-fail → that letter’s sound, stay on slot.
  8. List vs Mishkal — Catalog used to call /tashkeel; if the API hiccuped, all 22 words failed. List now opens from JSON word_tashkeel.
  9. Upload — Whisper needed ffmpeg; venv bundles imageio-ffmpeg, converts to WAV, then numpy (no “ffmpeg not found” on filename load).

13. Repo map

app/page.tsx              Home: photo, mic, upload, word list
app/lesson/ui.tsx         Letter lesson
app/dashboard/page.tsx    حروفي
lib/engine.ts             JSON, memory, unknown words
lib/letters.ts            Letter choices + JSON guiding questions
lib/mic.ts                WAV recording
lib/api.ts                FastAPI client
server/main.py            OCR, Whisper, Mishkal, Edge, Nile
data/fahman.json          Question bank

14. One-line pitch

Fahman is an Arabic reading tutor that refuses to say the word first — it teaches the child to read it, letter by letter, with questions from a real error dataset and a local Arabic tutor model as backup.

albaraahegaz/Fahman

Fahman — Arabic reading tutor for ages 6-9

TypeScript

0

4 commits

updated Sep 12, 2026

See the code

README

فَهْمان — Fahman

Arabic-first reading tutor for ages 6–9.

نقرأ سوا. والإجابة تيجي منك.

Fahman doesn’t read it for them. It teaches them to read it.

Hackathon: GDG on Campus ECU × Union Mindz — Build AI that earns its impact.

Fahman leaderboard score


1. The problem (30 seconds)

A generic bot sees بَابْ and says the word. The child copies. That is not reading.

Fahman never says or writes the full word first. It shows the word, asks Socratic questions about letter shape and dots, then (only after the child succeeds) speaks the word and gives the meaning.


2. What to demo (judges — 2 minutes)

Do this path. Do not start with photo or microphone.

  1. Contrast (optional): ChatGPT / any bot → type بَابْ → it reads the word. That is the gap.
  2. Open http://localhost:3000
  3. أو اختَر كلمة من القائمة → حصان or ثعلب
  4. Tap a wrong letter (e.g. ت instead of ن on حصان).
    • You should see a guiding question such as: بص على الحرف الأخير. النقط فوق ولا تحت؟ وكم نقطة؟
    • Fahman must not say the full word.
  5. Finish every letter. Success: صح. دي قراءتك. + meaning.
  6. اسمع الكلمة (normal). اسمعها بطيء (slower). Needs internet (Edge TTS).
  7. حروفي — gold = strong, terracotta = weak.

Photo / mic / upload use the same lesson. If they fail, the list still works. JSON questions work even if Nile-Chat is down.


3. Product rules (final form)

RuleWhat we do
Never spoil the wordNo correct full-word button. Choices are letters only (ث / ت / ب).
Whole wordChild walks letter by letter. Full word is spoken only at the end.
3 wrongs on one letterPlay that letter’s sound, show it, stay on the same letter. Do not skip to the next word.
New / unknown wordsStill a lesson (unknownItem). No crash on empty JSON match.
OCR mistakesConfirm/edit screen. We do not train OCR.
VowelsMishkal only. Dataset JSON is the question bank, not the vocalizer.
VoiceEdge TTS ar-EG-SalmaNeural. No MMS-TTS.
Tutor LLMNile-Chat via Ollama /api/generate. If it fails or says the blocked word → JSON q_level_*.

Dropped on purpose (do not bring back): MMS-TTS, Tashkeel-50M, fine-tuning Qari/Whisper/Edge on the 189-row sheet.


4. Architecture

Browser (Next.js :3000, RTL, Cairo + Amiri)
    │
    ├─ /              photo, mic, upload, 22-word list
    ├─ /lesson        letter walk + Nile/JSON questions
    └─ /dashboard     حروفي (localStorage memory)
            │
            ▼
FastAPI (Python :8001)
    ├─ /tashkeel      Mishkal (+ JSON tashkeel fallback for known words)
    ├─ /ocr           Qari-OCR-v0.3 (CPU, first call is slow)
    ├─ /transcribe    Whisper-small (ffmpeg → WAV → numpy)
    ├─ /tutor         Ollama Nile-Chat-4B generate, else fallback
    └─ /tts           Edge TTS (internet). ?slow=1 → slower rate
            │
            ▼
Ollama :11434   model: hf.co/mradermacher/Nile-Chat-4B-GGUF:Q4_K_M

UI: paper #F6F0E6, indigo #1B2A4A, teal #0F7B6C, gold #E8A838, terracotta #D4654A.


5. How the lesson works

  1. Word comes from the list (JSON word_tashkeel), OCR confirm, mic, or upload.
  2. Current letter is highlighted. Buttons are three letters, never the full word.
  3. First question is positional (إيه الحرف الأول؟ / إيه آخر حرف؟).
  4. Wrong tap loads the matching curriculum row (letter_true + letter_wrong) and shows:
    • 1st wrong → q_level_1 (dots above/below, how many)
    • 2nd wrong → q_level_2 (e.g. نقطة واحدة فوق. يبقى الحرف إيه؟)
    • 3rd wrong → letter TTS + q_level_3 (ن ولا ت؟)
  5. Correct letter → next slot. Last letter correct → meaning + full-word TTS.
  6. Student memory (localStorage key fahman-memory-v1) marks letters weak/strong for حروفي.

Nile-Chat is asked on the first question of a letter (flavor). After a wrong tap, JSON is the source of truth so the demo does not depend on Ollama latency.


6. Data

FileRole
data/fahman.jsonApp + tutor. 189 rows, 22 unique words.
data/fahman_dataset.xlsxSame curriculum in Excel.

Each row includes: word_tashkeel, error_code, letter_true / letter_wrong, q_level_1…q_level_4, blocked_word, nile_facts, meaning.

This JSON is not used to train OCR or Whisper.


7. Models (working, not fine-tuned)

PieceModelNotes
TutorNile-Chat-4B GGUF Q4_K_M via OllamaMust use /api/generate (chat returns empty).
OCRNAMAA-Space/Qari-OCR-v0.3-VL-2B-InstructFirst call loads ~2B on CPU. Can confuse س/ش, ع/غ. Confirm/edit.
ASRopenai/whisper-smallArabic transcribe. First load is slow.
DiacritizeMishkalDo not swap.
TTSEdge ar-EG-SalmaNeuralNeeds internet.
ffmpegBundled imageio-ffmpeg in the venvConverts uploads to WAV.

Weights for OCR/Whisper live in the Hugging Face cache (not inside this repo), usually:

C:\Users\<you>\.cache\huggingface

Ollama weights live in Ollama’s own directory, not this repo.


8. Run (this machine)

Teammates: double-click setup.cmd once, then run.cmd every time. Details in HOW-TO-RUN.md.

Need Node, Python 3.12, Ollama, and internet (TTS).

Leave three processes running.

Terminal A — Ollama

ollama serve

If you see bind: Only one usage of each socket address on port 11434, Ollama is already running. Skip this terminal.

Pull once (if missing):

ollama pull hf.co/mradermacher/Nile-Chat-4B-GGUF:Q4_K_M

Terminal B — API (port 8001, not 8000)

cd C:\Users\Mosta\OneDrive\Documents\Education-system
.venv\Scripts\activate
python -m uvicorn server.main:app --port 8001

Wait for: Uvicorn running on http://127.0.0.1:8001

Terminal C — website

cd C:\Users\Mosta\OneDrive\Documents\Education-system
npm run dev

If npm is missing: "C:\Program Files\nodejs\npm.cmd" run dev

Open http://localhost:3000

.env.local:

NEXT_PUBLIC_API_URL=http://127.0.0.1:8001

9. Copy to another PC or disk

Copying this folder alone is not enough.

Copy

  • This repo: app/, lib/, data/, server/, package.json, package-lock.json, .env.local, setup.cmd, run.cmd, HOW-TO-RUN.md
  • Optional: skip node_modules, .next, .venv (recreate them with setup.cmd)

Does not live in the repo (copy separately or re-download)

  • Hugging Face cache (OCR + Whisper)
  • Ollama + Nile-Chat model
  • Python / Node / Ollama installs

On the new Windows PC

  1. Install Python 3, Node.js, Ollama.
  2. Recreate venv (do not reuse another machine’s .venv paths):
python -m venv .venv
.venv\Scripts\activate
pip install -r server\requirements.txt

server/requirements.txt lists the direct packages. If install is incomplete, on the original PC run pip freeze > server\full-freeze.txt and install that file.

  1. npm install then npm run dev
  2. ollama pull hf.co/mradermacher/Nile-Chat-4B-GGUF:Q4_K_M
  3. Start uvicorn on 8001

Edge TTS still needs internet on the new machine.


10. API (for judges who ask)

MethodPathRole
GET/health{ ok, ollama }
POST/tashkeelMishkal diacritics
POST/ocrImage → Arabic word
POST/transcribeAudio → text
POST/tutorNile question or JSON fallback
GET/tts?text=Speak. Add letter=1 for a single letter. Add slow=1 for slow word.

11. Honest limits (say this if asked)

  • TTS needs Microsoft Edge online. Offline → الصوت مش جاهز دلوقتي. القراءة شغالة. The lesson still stands.
  • Mic / upload need Whisper. First load can take a minute. Prefer the word list in a noisy hall.
  • OCR is not trained on our sheet. Confirm/edit is the product answer to س/ش mistakes.
  • Nile can be slow on CPU. Wrong-letter questions come from JSON so the child is never stuck.
  • Port 8000 was blocked on the build machine; API is 8001.

12. How we got here (build log)

  1. Curriculum — 189 error rows / 22 words from the curated Excel → fahman.json with q_level_*, blocked_word, error_code.
  2. App — Next.js 15 App Router + FastAPI. Three screens only.
  3. Vowels — Tashkeel-50M hallucinated; switched to Mishkal and kept it.
  4. TTS — MMS said لاب for باب; switched to Edge Salma. Slow rate only on اسمعها بطيء; normal play uses the original Edge call (no extra rate).
  5. Tutor — Ollama /api/chat returned empty; switched to /api/generate.
  6. OCR — Qari 0.2.2.1 had no weights; 0.3 VL 2B. No fine-tune. Confirm/edit screen.
  7. Lesson — Removed full-word spoiler buttons. Letter-only choices. Walk the whole word. 3-fail → that letter’s sound, stay on slot.
  8. List vs Mishkal — Catalog used to call /tashkeel; if the API hiccuped, all 22 words failed. List now opens from JSON word_tashkeel.
  9. Upload — Whisper needed ffmpeg; venv bundles imageio-ffmpeg, converts to WAV, then numpy (no “ffmpeg not found” on filename load).

13. Repo map

app/page.tsx              Home: photo, mic, upload, word list
app/lesson/ui.tsx         Letter lesson
app/dashboard/page.tsx    حروفي
lib/engine.ts             JSON, memory, unknown words
lib/letters.ts            Letter choices + JSON guiding questions
lib/mic.ts                WAV recording
lib/api.ts                FastAPI client
server/main.py            OCR, Whisper, Mishkal, Edge, Nile
data/fahman.json          Question bank

14. One-line pitch

Fahman is an Arabic reading tutor that refuses to say the word first — it teaches the child to read it, letter by letter, with questions from a real error dataset and a local Arabic tutor model as backup.