Inspiration
Most Nigerians — most West Africans — don't know the law that governs their own lives. Today, that knowledge sits almost entirely with legal professionals. The result is that the average person is either breaking the law without realizing it, or missing out on protections the law already gives them because they never knew to ask.
You hear it constantly: a landlord chases a tenant out with no warning, or a worker gets sacked on the spot after years of service, and in both cases the person on the losing end doesn't know what they were owed or entitled to under the law. Nigeria has roughly one lawyer per 4,000 people, concentrated almost entirely in Lagos and Abuja. For a worker sacked without notice, a tenant handed an illegal rent increase, or a shopkeeper unsure of their PAYE, the real options are folklore, an expensive consultation, or nothing.
That gap is what inspired Òfin. I wanted something simple that helps people understand the law, stay compliant with it, and use it to their own advantage — without needing a lawyer, legal fees, or even an internet connection. Cloud AI assistants aren't a real answer either: they hallucinate statutory law with total confidence, and mobile data in Nigeria is intermittent and costly. It had to run offline, on the device people already own.
What it does
Òfin is an offline legal companion for Nigerian labour, tenancy, and tax law. It runs entirely on an everyday laptop — no internet connection needed at any point during use — and answers in English or Nigerian Pidgin.
It's built on eight Nigerian statutes across three legal domains, and every
legal claim it makes is backed by a verifiable citation back to the actual
statutory text — [Labour Act 2004, s.11(2)] — not a paraphrase, not a
guess. If a claim can't be verified against the corpus, it's flagged or
stripped before the user ever sees it.
Beyond citations, Òfin does real computation: PAYE income tax, employment termination notice periods, Lagos tenancy notice bands, and redundancy entitlements are all calculated by deterministic code, not the language model — so a worker asking "what am I owed after 6 years?" gets an answer that's arithmetically correct, not just plausible-sounding.
How we built it
Òfin rests on three pillars:
- A Verified Citation Engine. Every answer carries citation tokens that a deterministic verifier checks against the local corpus in three layers — existence, quantity consistency, and semantic support — before anything reaches the UI. Claims that fail get one constrained regeneration against the correct source text. Prose citations ("Section 11(3) of the Labour Act 2004"), not just bracket tokens, are parsed and resolved, which tripled verified-claim coverage over the bracket-only version.
- A Deterministic Computation Engine. All PAYE, notice-period, tenancy notice, and redundancy arithmetic is pure Go code implementing the statutes directly — the model only extracts parameters from the question and narrates the result. It never touches a figure.
- Naija-native interaction. Nigerian Pidgin is a first-class language, not an afterthought.
Under the hood: the base model is Llama 3.2 3B Instruct (Q4_K_M GGUF),
chosen after a 20-question bake-off against Qwen 2.5 3B and Phi-3.5-mini —
it was the decisive winner on natural, legally-accurate Pidgin, which was
the whole point of building this for Nigeria in the first place. Retrieval
is a hybrid of SQLite-vec and FTS5 combined with Reciprocal Rank Fusion over
678 chunks from 8 statutes, enriched at build time with AI-generated
summaries and cross-reference edges (Summary-Augmented Chunking) — all of
that cloud usage happens once, at build time, never at runtime. The runtime
itself is llama.cpp plus a Go engine (verifier, rules engine, retrieval
server) talking only to 127.0.0.1 — genuinely zero network calls while
answering a question.
Because this had to run on an 8 GB laptop, every architecture decision was checked against that ceiling: f16 KV-cache with flash attention over q8_0 (faster prefill for a manageable memory cost), speculative decoding rejected outright (too much RSS for too little gain), and certification run on a RAM-capped VM rather than better hardware, so the numbers we report are numbers a judge's machine would actually reproduce.
Challenges we ran into
The hardest bugs weren't in the model — they were in the gap between "the
benchmark passed" and "the app actually works." During the first full VM
certification run, llama-bench scored cleanly, but the real ofin ask /
ofin serve commands crashed outright: the default config silently enabled
a draft (speculative-decoding) model that download_model.sh never
actually ships, and a Go flag-parsing quirk meant --no-draft was silently
ignored unless it came before the subcommand. Nothing in the profiler score
would have caught either bug — only running the full integrated stack on
the actual constrained hardware did. That experience is the reason every
later certification round is treated as incomplete until it's exercised
end-to-end on the target VM, not just scored.
Scoping the language support honestly was another hard call. I wanted Òfin to understand Yoruba, Hausa, and Igbo queries too, not just Pidgin — but testing showed the 3B model hallucinates translations at temperature 0, and retrieval quality collapses once you're off English embeddings. Rather than ship something that answers confidently in the wrong language, the scope was cut back to Pidgin-only and stated plainly in the metadata rather than overclaimed.
The corpus itself was its own slog: statutes gazetted as scanned PDFs came with margin-note artifacts, reconstructed section numbers, and formatting noise that had to be verified section-by-section against official text rather than trusted wholesale — with every reconstruction explicitly marked and logged rather than silently smoothed over.
And the target kept moving: the official adtc-profiler itself changed
underneath the project mid-build — thirteen upstream commits, a schema
version bump, throughput pinned to CPU-only, thermal-throttle detection
added — which meant re-certifying more than once to make sure "passing" on
our machine still meant passing under the current rules.
Accomplishments that we're proud of
- Citations that actually hold up. 84% citation precision across 207 claims in the hardened three-domain evaluation, with every single claim marked verified, flagged, or failed in the UI — not a vibes-based accuracy number.
- Genuinely offline, verified, not just claimed. Zero non-loopback network calls during generation, confirmed on the certification VM.
- Caught a "silently broken" ship-blocker before a judge could. The draft-model bug would have made the app fail out-of-the-box on exactly the kind of constrained hardware it's graded on — found and fixed weeks before the deadline because we tested the real app, not just the score.
- Comfortably inside the 8 GB budget. Full-stack peak RSS around 4.2 GB on the certification VM, with performance well above the scoring threshold (31.5 TPS against a 15 TPS cap).
- Pidgin support that earned its place. It's there because it decisively won a real head-to-head bake-off against two other candidate models, not because it's a checkbox.
What we learned
A 3B model on an 8 GB laptop cannot be trusted with legal arithmetic or with languages it wasn't strong in — and the fix isn't a better prompt, it's architecture: pull the arithmetic out into deterministic code entirely, and be honest about what the model can't safely do rather than papering over it. The same lesson applies to evaluation itself — a profiler or benchmark score is necessary but not sufficient; the only way to know an offline, resource- constrained product actually works is to run the real thing on the real constraint. And for a project meant to serve people who don't have a lawyer on speed dial, stating limitations plainly — Lagos-only tenancy law, no case law, statute-as-at dates — builds more trust than a bigger-sounding claim would have.
What's next for Òfin
- Cross-domain query understanding. Questions that mix domains (e.g. "do I pay tax on rent I collect?") currently split into sub-queries that don't always carry the right domain vocabulary — a lightweight keyword-injection layer on top of the existing decomposition would close most of the remaining misses.
- A Pidgin normalization glossary to map common Pidgin phrasing to the statutory English terms retrieval is built on, ahead of any Pidgin fine-tuning.
- Coverage beyond Lagos. Tenancy law is state-level in Nigeria; Lagos was the necessary starting point, not the ceiling.
- Closing remaining corpus gaps — a handful of sections are still missing from source transcription and tracked openly rather than silently filled in.
- Signed, notarized desktop builds for Mac and Windows so people can install Òfin the same way they install any other app, without a Gatekeeper or SmartScreen warning in the way.

Log in or sign up for Devpost to join the conversation.