polyglot-tutor / README.md
blizzarman's picture
feat: M0 walking skeleton (app, service protocols, CI/CD, Space deploy)
00d5ae5
|
Raw
History Blame Contribute Delete
4.79 kB
metadata
title: Polyglot Tutor
emoji: 🌍
colorFrom: indigo
colorTo: green
sdk: docker
app_port: 7860
pinned: false

🌍 Polyglot Tutor

Adaptive language tutor covering the four skills (reading, listening, writing, speaking), driven by a CEFR classifier and a predictive spaced-repetition learner model. Runs for free on a Hugging Face Space (CPU) with an optional local-GPU "premium" mode.

Status: M0 β€” walking skeleton. CI, Docker β†’ GHCR, HF Space deploy and all service contracts (LLM / ASR / TTS / storage) are live; features land milestone by milestone.

TL;DR (for recruiters)

  • ML core: fine-tuned multilingual CEFR (A1–C2) text classifier benchmarked against a published baseline; FSRS-style spaced repetition evaluated offline on public review logs; LLM-generated exercises gated by an LLM-as-judge.
  • Engineering: provider-agnostic services (typing.Protocol + env-driven factories), pinned toolchain (uv, ruff, pre-commit), tested fakes, CI β†’ GHCR, free-tier deployment with documented constraints (ephemeral disk, cold starts, rate limits).
  • Honest evals: every milestone ships metrics with caveats, tracked in MLflow (see docs/evals/).

Architecture

flowchart LR
    UI[Gradio UI<br/>4 skill tabs] --> EX[Exercise generators<br/>+ cache]
    EX --> LLM[LLMClient<br/>Gemini / Mistral / Ollama / fake]
    EX --> ASR[ASRClient<br/>faster-whisper / remote / fake]
    EX --> TTS[TTSClient<br/>edge-tts / local / fake]
    EX --> CEFR[CEFR classifier<br/>ONNX int8, CPU]
    UI --> SRS[Learner model<br/>FSRS + ability estimate]
    SRS --> DB[(Repository<br/>memory / SQLite / Supabase)]
    EX --> DB

Each box on the right is a Protocol with swappable implementations selected by environment variables β€” the same image runs as the free Space ("light") or against a local GPU box over Tailscale ("premium"). See docs/adr/ for the reasoning.

Quickstart (dev)

uv sync                      # runtime + dev deps (pinned via uv.lock)
uv run pre-commit install
cp .env.example .env         # defaults to the offline fake provider
uv run python -m tutor.app.main   # http://localhost:7860
uv run pytest

To talk to a real LLM, set in .env: LLM_PROVIDER=gemini, LLM_API_KEY=... (free key at https://aistudio.google.com/apikey), then check the Diagnostics tab β†’ Ping LLM.

Dataset download / EDA (kept out of the runtime image):

uv run --group data python scripts/download_data.py

Deployment

  1. CI (GitHub Actions) β€” lint + tests on every push/PR; on main, the Docker image is pushed to ghcr.io/<owner>/polyglot-tutor.
  2. HF Space (Docker, cpu-basic) β€” create the Space once, then set:
    • GitHub β†’ Secrets: HF_TOKEN (write) Β· Variables: HF_SPACE=<user>/<space>
    • Space β†’ Settings: LLM_PROVIDER, LLM_MODEL, LLM_API_KEY, GRADIO_AUTH_USERNAME, GRADIO_AUTH_PASSWORD Every push to main syncs the repo to the Space, which rebuilds from the same Dockerfile (a Docker Space cannot pull the GHCR image β€” GHCR is the CI artifact, see ADR 0001).

Roadmap

Milestone Scope Headline eval
M0 βœ… Walking skeleton: CI, GHCR, Space, Protocols + fakes CI green, live Space
M1 CEFR classifier + reading comprehension (LLM questions, cached & judge-gated) macro-F1 / adjacent acc. / QWK vs published UniversalCEFR baseline
M2 TTS + dictation with light ASR WER (incl. non-native audio) justifying tiny vs small
M3 Supabase persistence + writing correction (typed errors via ERRANT, per-learner profile) error-type P/R on W&I+LOCNESS sample
M4 Learner model: FSRS scheduling + ability estimate, next-exercise policy AUC / log-loss / calibration on public Anki review logs
M5 Pronunciation scoring + premium local-GPU mode (Tailscale) correlation with expert scores on speechocean762
M6 (stretch) Real-time voice conversation tab (Gemini Live API behind a ConversationClient Protocol) qualitative demo; latency budget documented

Data & licensing

This is a non-commercial portfolio/demo project. CEFR-labeled corpora come from UniversalCEFR (per-subset, mostly research-only licenses β€” original papers cited); SRS benchmarks use the open Anki review-log datasets; pronunciation evaluation uses speechocean762 (free for any use). No licensed text is committed to this repo; data/ is gitignored and rebuilt by scripts/download_data.py. Details and caveats: docs/adr/0003-datasets-and-licensing.md.