FarmTwin
A cited agronomic advisor that runs entirely on a 2014 laptop with the network unplugged.
It runs offline on a laptop, so there is nothing to visit.
Model selection and benchmarking, knowledge base curation and chunking, retrieval pipeline, backend, frontend and design system, the speech-to-text evaluation, and the full submission artifacts including ADRs.
How it holds together
Step 1 of 6
Network on- Questiontext or voice (EN)
- Embedlocal embedding
- Retrievesqlite-vec · 45 chunks
- Groundcitation required
- Qwen2.5-3Bllama.cpp · Q4_K_M
- AnswerSSE · cited
Voice input ships as English-only and is labelled that way in the interface — 'Voice input (Nigerian English)' — rather than quietly underperforming on Pidgin.
The problem
Smallholder maize farmers in Nigeria make high-stakes agronomic decisions — planting dates, fertilizer timing and rates, pest response — largely without extension services. Where digital advisory tools exist they assume reliable connectivity, a modern smartphone and a cloud backend. That assumption fails in exactly the places the advice is most needed.
There is also a trust problem specific to AI advisory in agriculture. A chatbot answering how much urea to apply at six weeks with a plausible but ungrounded number is worse than no tool at all, because a wrong dose costs a season.
The agronomic knowledge is not missing — NAERLS, IITA, CIMMYT and FAO have published extensively. It sits in PDFs and extension bulletins that never reach the farm. Making that corpus queryable in natural language, on a device with no network, is the actual delivery problem. Offline is not a constraint imposed by a brief; it decides whether the system is usable at all.
What I built
A fully offline digital twin of a smallholder maize farm. It models the farm's state and answers agronomic questions in natural language, with every answer grounded in a curated knowledge base and cited back to source. No network calls, no API keys, no cloud inference — the model, the vector index and the data all live on the device.
Built in a seven-day sprint for the Africa Deep Tech Challenge 2026 Laptop LLM Challenge.

The architecture
45 curated chunks drawn from NAERLS, IITA, CIMMYT and FAO, embedded and stored in SQLite via sqlite-vec. Using SQLite as the vector store rather than a dedicated vector database keeps the whole system to a single file dependency and avoids running a second server process on a machine already CPU-bound by inference.
Qwen2.5-3B-Instruct at Q4_K_M quantization through llama.cpp. Queries are embedded, top-k chunks retrieved, and context assembled into a prompt that requires the model to cite the chunks it used.
FastAPI and SQLAlchemy over SQLite, exposing a streaming SSE endpoint with a non-streaming fallback preserved. On the client, a stripJsonBlock utility separates the structured citation payload from the prose stream as tokens arrive, so text renders progressively without raw JSON scrolling past.
Decisions
Benchmarked Qwen2.5-3B against Llama-3.2-3B on a structured rubric with manual grading against gold prompts. Llama was disqualified primarily because it hallucinated citations — inventing sources that were not in the retrieved context. For a system whose entire value is that an answer comes from IITA and here is the chunk, that is decisive rather than a rough edge. Qwen took the composite 83.5 to 72.9, driven by retrieval grounding.
Stack
- Inference
- llama.cpp · Qwen2.5-3B-Instruct · Q4_K_M
- Retrieval
- SQLite · sqlite-vec · semantic chunking
- Backend
- FastAPI · SQLAlchemy · SSE
- Interface
- Vite · React · TypeScript · Tailwind
- Evaluated
- whisper.cpp · Whisper base · Nigerian-accent fine-tune
- Sources
- NAERLS · IITA · CIMMYT · FAO
What it demonstrates
- Local quantized inference on decade-old consumer hardware
- Retrieval fidelity verified by a benchmark I re-graded against myself
- Citation enforcement as a model selection criterion
- Streaming prose and structured payload separated client-side
- A decision trail in ADRs, so the tradeoffs are auditable rather than folklore