LFED / docs /PLAN.md
Kasualdad's picture
Initial commit: Kasualdad LFED — Phases 0-8 complete
17674c2
|
Raw
History Blame Contribute Delete
7.18 kB

A newer version of the Gradio SDK is available: 6.19.0

Upgrade

Full Plan — Kasualdad LFED

Reference: produced 2026-06-06 in session 1, used to drive HANDOFF.md


Why this project

A school-district admin (principal, superintendent, dept. head) types a natural-language question → the app returns the answer as a table + chart, with the SQL shown for transparency. All inference is local (llama.cpp, GGUF). No data leaves the machine. Model is a small open LLM fine-tuned on text-to-SQL via Modal. Runs on a free Hugging Face Space.

Target: win the HF "Build Small" Hackathon (Chapter One: Backyard AI) + produce a credible demo slice for clients/employers.


9-Day Schedule (Locked)

Day Date Phase Work Output
1 Jun 6 0 Bootstrap (3.12 venv, packages.txt, pinned requirements) Working 3.12 env
1 Jun 6 1 Model sanity check (Qwen2.5-Coder-7B Q4_K_M) Locked model name
1 Jun 6 2 Refactor: data_engine.py / model_inference.py / prompts.py / app.py Modular codebase
2 Jun 7 3 Robustness: column validation, read-only wrap + LIMIT, timeout, JSON parser, streaming, per-request DuckDB conn Bulletproof pipeline
2 Jun 7 4 Data: realistic seed (5 schools × 4 years, populated chronically-absent flag) Demoable queries
3 Jun 8 5 UI polish (Linear/Vercel + teal + Off-Brand criteria) Polished Space
3 Jun 8 6 Tests (execution_guard, data_engine, model_inference) Green pytest
3 Jun 8 7a Synthetic NL→SQL pairs (2–3k) train.jsonl
3→4 Jun 8–9 7b Modal Unsloth QLoRA (A10G, ~3–6 hrs, overnight) Fine-tuned adapter
4 Jun 9 7c Merge → GGUF Q4_K_M → push to HF → swap REPO_ID Custom model live
4–5 Jun 9–10 8 README (frontmatter, mermaid, badges, design doc, demo GIF) Submission-ready README
5–6 Jun 10–11 9 Deploy to Space, cold-start verify, end-to-end smoke test Live demo URL
7–8 Jun 12–13 10 Buffer: prompt iteration, UX hardening, retrain if needed Polish
9 Jun 14 11 Final verification + submit Submitted

Critical path: Phase 7 (fine-tuning). Starting it on Day 3 gives a full day of compute buffer if a re-train is needed.


Phase Details

Phase 0 — Bootstrap ✅ DONE

  • Project copied to ~/projects/build-small-hackathon/Kasualdad_LFED/
  • venv at Python 3.12.8
  • requirements.txt: gradio==6.16.0, duckdb==1.5.3, llama-cpp-python==0.3.26, huggingface_hub==1.18.0
  • packages.txt: cmake, build-essential, libopenblas-dev
  • All imports verified

Phase 1 — Model sanity check 🟡 IN PROGRESS

  • ✅ Identified candidate GGUFs (mradermacher quantizer for both)
  • ✅ Downloaded Qwen2.5-Coder-7B-Instruct.Q4_K_M.gguf to /tmp/lfed-models/qwen/ (4.4 GB)
  • ❌ Run inference on 10 hand-crafted prompts to confirm SQL quality
  • ⏸️ Llama-3.1-8B-Instruct Q4_K_M — only download if Qwen fails

Sanity-check command is in HANDOFF.md under "Phase 1: Sanity-Check Resume".

Phase 2 — Refactor

  • Extract data_engine.py (DuckDB, schema introspection, execute_safe())
  • Extract model_inference.py (Llama lifecycle, generate_sql(), streaming)
  • Extract prompts.py (system prompt + few-shot examples + schema docstring)
  • Slim app.py to UI + controller

Phase 3 — Robustness

  • Parse the JSON {sql, explanation} envelope (fall back to sql block)
  • Validate column names exist in schema (AST parse, not regex)
  • Reject any non-SELECT; wrap as SELECT * FROM (<user_query>) LIMIT 1000
  • Per-query timeout via duckdb.set_query_timeout
  • Thread safety: per-request DuckDB connection (cheap, in-memory)
  • Streaming: yield tokens to Gradio's stream=True callback
  • Error UX: surface clean messages in UI

Phase 4 — Data

  • 5 schools, 4 school years (2021-20222024-2025), 12 grade levels
  • Attendance with is_chronically_absent populated ~15% true
  • Document schema in README

Phase 5 — UI polish (Off-Brand badge)

  • Custom CSS injected via gr.Blocks(css=...) on top of Gradio default
  • Inter (UI) + JetBrains Mono (code)
  • Single accent color (#14b8a6 teal), neutral grays
  • Single column, max-width 960px
  • Smooth state changes (120ms ease-out), 200ms result reveal
  • Honors prefers-reduced-motion
  • Example-query chips: 4–6 one-click starters
  • Mobile/responsive sanity

Phase 6 — Tests

  • test_execution_guard.py: malicious inputs, malformed JSON, missing columns, multi-statement
  • test_data_engine.py: schema introspection, timeout, empty result
  • test_model_inference.py: mock the LLM, verify prompt assembly and JSON parsing

Phase 7 — Modal fine-tuning (Well-Tuned badge)

  • generate_synthetic.py: 2–3k (NL question, SQL) pairs from seed schema
  • train.py: Unsloth + QLoRA, ~3 epochs, A10G on Modal (free credits)
  • export_gguf.py: merge LoRA → GGUF Q4_K_M → push to new HF repo
  • app.py swaps REPO_ID to fine-tuned model
  • Verify accuracy improvement on a held-out prompt set

Modal config:

import modal
app = modal.App("kasualdad-lfed-train")
# image: unsloth + transformers + trl + bitsandbytes
# volume: /data for training pairs
# secret: HF_TOKEN (for Phase 7c push)
@app.function(gpu="A10G", timeout=4*3600, secrets=[modal.Secret.from_name("huggingface")])
def train(...):
    ...

HF repo name (TBD username): <hf-username>/lfed-qwen2.5-coder-7b-sql-gguf

Phase 8 — README

  • Frontmatter: tags: text-to-sql, education, local-first, llama-cpp, duckdb
  • Mermaid architecture diagram
  • Badge checklist with links
  • 30-second demo GIF
  • "How to run locally" section

Phase 9 — Deploy & verify

  • python app.py boots, sample queries return correct results
  • Push to HF Space, watch cold start (model download, GGUF cache)
  • Submit to hackathon with Space URL + HF model repo + brief write-up

Out of Scope (defer or skip)

  • ❌ Real Parquet/CSV data lake loader — seed tables only
  • ❌ Per-request data file upload — fixed schema
  • ❌ User accounts / auth — single-user demo
  • ❌ Chart auto-generation — basic dataframe display only
  • ❌ Detailed observability/logging beyond stderr

Risks & Mitigations

Risk Mitigation
gradio==6.16.0 may not exist on Spaces Verified on PyPI; if Space rejects, downgrade to 5.x
Modal cold start eats the A10G budget Cache image; warm-up job; free credits = no budget pressure
Synthetic data quality is too low → bad fine-tune Hand-validate 50 pairs before training; iterate prompt template if model can't generalize
HF Space cold start > 5 min (8B model download) Q4_K_M (~4.4 GB) fits well; add startup log
llama-cpp-python wheel not available for Py 3.12 packages.txt includes build tools; pin a known-good version
User provides wrong HF username Repo name is a one-line swap on Day 4

Outstanding Dependencies (chronological)

When Need Status
Day 1 (now) ✅ Unblocked
Day 3 Modal secret huggingface (HF token) ⏳ Pending
Day 4 HF username (user said kasualdad was wrong) ⏳ Pending