Inspiration

For a student in Zimbabwe, a clinic worker in Harare, or a self-taught developer in Gweru, cloud AI is often out of reach — not because the tools don't exist, but because always-on internet, stable electricity, and API fees are luxuries, not defaults. Meanwhile, the machine already sitting on millions of desks is a modest laptop: 8 GB of RAM, integrated graphics, no GPU. That gap — genuinely useful AI vs. what actually runs offline on hardware people already own — is what Clair is built to close, specifically for programming education: tutoring, debugging, and code explanation in the language a student actually thinks in.

What it does

Clair is an offline coding tutor that runs entirely on an 8 GB laptop through llama.cpp — no internet, no cloud account, no data costs. It writes and debugs code, explains programming concepts step by step, and — uniquely for this challenge — does it in English, chiShona, isiNdebele, and Kiswahili, keeping code and technical keywords in English (the way programming is actually taught locally) while explaining in the learner's own language. It validates its own inputs rather than assuming happy paths, quotes the real compiler or interpreter error when debugging instead of guessing, and reasons about memory and performance limits appropriate to the hardware it runs on.

How I built it

Clair is a LoRA fine-tune of Qwen/Qwen3.5-2B (Apache-2.0), chosen after benchmarking five candidate base models on the actual CPU kernels the ADTC audit environment uses (all x86 SIMD disabled) rather than trusting a normal laptop build. On those kernels, Q8_0 quantization turned out to be both faster and more accurate than the conventional Q4_K_M choice — the opposite of the usual "quantize harder for speed" instinct.

The training data itself is execution-verified: I ran 36 real bugs across 12 programming languages through their actual toolchains and grounded every debugging example in the real compiler or interpreter output, rather than letting a teacher model guess at plausible-sounding errors. Human-translated data (google/smol, CC-BY-4.0) and my own hand-written chiShona anchor the African-language training. Fine-tuning happened on a free Colab GPU, after discovering that MLX (Apple's ML framework) disables its fast training kernel for Qwen3.5's recurrent attention layers — making local training on my M4 Pro genuinely impractical.

Challenges I ran into

The Round 1 result (19th of 20 semifinalists) was itself the biggest challenge: the judges were right on every count — no disclosed base model, no African-language use, code that recursed forever on negative numbers, and a debugging answer that invented a bug that didn't exist. Diagnosing why the performance score was so low led to the most interesting discovery of the whole project: the audit VM runs llama.cpp with every SIMD instruction set disabled, so a benchmark run on an ordinary laptop is measuring something almost unrelated to what the judges' hardware will see.

Rebuilding wasn't clean, either. My first fine-tuning attempt trained successfully but, on evaluation, hadn't actually learned Clair's identity, had baked in teacher-invented "Edge Cases" sections that the model then hallucinated from (inventing a nonexistent Git file), and its chiShona had degenerated into repeated phrases. I had to diagnose that from evaluation results, correct the dataset, and retrain — keeping both runs in the repo for honesty rather than quietly discarding the failure. Along the way: a nearly-full disk silently corrupted a build (caught before it shipped), a LoRA adapter that came in just over GitHub's 100 MB push limit, and a mid-flight update to the competition's own submission schema that needed reconciling against the actual validator, not just the announcement email.

Accomplishments that I'm proud of

Taking the judges' feedback and turning it into 46 concrete, checkable criteria, then watching the fine-tuned model go from 29/46 to 39/46 against the unmodified base — with the two headline Round 1 complaints fixed by name: it now correctly diagnoses the exact SyntaxError from the judges' own debugging prompt, and factorial now rejects negative and non-integer input instead of recursing forever. I'm also proud of not hiding the parts that didn't improve — HumanEval dropped slightly (57.3% → 54.3%) and I said so plainly rather than picking only the flattering number, and the African-language training data is explicitly labeled as not native-speaker reviewed rather than overclaimed.

What I learned

That an evaluation environment's specific compute constraints (SIMD disabled, in this case) can flip an optimization decision on its head, and the only way to know is to reproduce those constraints yourself rather than trust intuition. That "the model trained without errors" and "the model learned what I intended" are very different claims — only evaluation catches the gap. And that provenance isn't paperwork: rebuilding a model with full disclosure, from a named base model to real compiler-verified training data, produces a materially better and more trustworthy result than the alternative, not just a better-documented one.

What's next for Clair

Getting the chiShona and isiNdebele training data in front of an actual native speaker for review — right now it's mechanically filtered but not linguistically validated, and I know it shows. I'd also like to fix Clair's one remaining honesty gap (it can still occasionally claim to "read the latest documentation," which is false for an offline model) with more targeted identity training, expand beyond the coding-assistant domain now that the pipeline for grounded, execution-verified training data exists, and revisit local fine-tuning once Apple's MLX supports fast training kernels for Qwen's newer recurrent-attention architectures — so the whole loop, not just inference, can run offline on the hardware Clair is built for.

Built With

  • accelerate
  • c/c++
  • jsonlines
  • jypiter
  • llama.cpp
  • pandas
  • peft
  • transformers
Share this project:

Updates

Submission history