Letter Decoder: Your AI Friend for Scary Official Letters (Runs 100% Offline) A developer built Letter Decoder, an open-source, local-first app that explains official letters such as tax notices, fines and insurance rejections in plain language, producing an answer card with a verdict, deadline countdown, next steps and a draft reply. The app runs fully offline with Ollama and the Qwen2.5 7B model, using a pipeline where deterministic regex and dateparser extraction finds dates, amounts and reference numbers while the LLM only explains them, and a verifier checks every factual claim against the extracted facts to prevent hallucinations. A public demo API runs in mock mode replaying 14 canonical examples so no real letters are uploaded. This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle https://dev.to/challenges/hacktoberfest-week2-2026-10-12 Letter Decoder https://letter-decoder.vercel.app — a local-first, open-source app that reads your official letters and explains them in plain language. Tax notices. Fines. Insurance rejections. Bank letters. Landlord warnings. Drop one in as a photo, PDF, screenshot, or pasted text, and get back an answer card : .ics calendar export Every date and amount links back to the exact line of the original letter it came from. If the model can't verify a claim against the extracted facts, it says so — no confident hallucinations. Who would pay for this? Anyone who has ever frozen looking at a government envelope, hired a solicitor at £150/hour just to be told "this is a routine payment reminder", or simply had a letter in their second language. The realistic addressable market is anyone who receives official correspondence — which is everyone. The letter never leaves your device. No accounts, no cloud, no telemetry. That's the product differentiator and the privacy guarantee rolled into one. | | URL | Notes | |---|---|---| | Frontend | https://letter-decoder.vercel.app https://letter-decoder.vercel.app | React 19 app, deployed on Vercel | | Public API | https://letter-decoder-api-qvxs.onrender.com https://letter-decoder-api-qvxs.onrender.com | FastAPI — runs in ENGINE MODE=mock , replays 14 canonical examples through the full SSE pipeline with realistic delays | For real decoding with a local model, clone the repo and run with Ollama see below . The public endpoint intentionally uses mock mode so no real letters are ever uploaded to a server. "A patient friend read it for me, and now I know what to do." A local-first, open-source app that explains official letters in plain language. Tax notices, fines, insurance rejections, bank letters, landlord notices — drop one in as a photo, PDF, screenshot, or pasted text, and get back an answer card : a one-line verdict, a deadline countdown, severity, three concrete next steps, a document checklist, and an editable draft reply. Every date and amount links back to the exact line of the original letter it came from. No cloud calls. No telemetry. No accounts. The letter never leaves your device. | URL | What it is | | |---|---|---| | Frontend | https://letter-decoder.vercel.app https://letter-decoder.vercel.app | React app Vercel | | API | https://letter-decoder-api-qvxs.onrender.com https://letter-decoder-api-qvxs.onrender.com | FastAPI engine Render | The public API runs ENGINE MODE=mock , replaying canonical examples through the same endpoints and SSE event streams with realistic delays. For real decoding with an open-weight model, run it locally… Quick start with a real model: Terminal 1 — start the inference server ollama serve ollama pull qwen2.5:7b Terminal 2 — start the app git clone https://github.com/RAMBO-LC/letter-decoder.git cd letter-decoder uv sync --all-extras uv run python -m api.main Open http://127.0.0.1:8000 — everything runs fully offline from here. The core design principle is: code finds facts, the model explains them. Input → Preprocess → Extract Text → Deterministic Facts → Classify → Notice Pack → LLM Explain → Verify → Answer engine/preprocess.py — OpenCV deskew and denoise for photos/scans. engine/extract text.py — native PDF text extraction, falling back to Tesseract OCR. engine/deterministic extract.py — regex + dateparser pull every date, amount, and reference number from the raw text. The LLM engine/classifier.py — keyword and embedding matching identifies the notice type and loads the right notices/ . engine/llm constrained.py — engine/verifier.py — every factual claim in the LLM output is checked against the deterministically extracted facts. A fact the model invented that wasn't in the source text fails verification — you get a clean error, not a confident lie. | Layer | Tool | License | |---|---|---| | Local inference | Ollama https://ollama.ai | MIT | | Default model | Qwen 2.5 7B https://huggingface.co/Qwen/Qwen2.5-7B-Instruct | Apache 2.0 | | OCR | Tesseract https://github.com/tesseract-ocr/tesseract | Apache 2.0 | | Image processing | OpenCV https://opencv.org | Apache 2.0 | | API framework | FastAPI https://fastapi.tiangolo.com | MIT | | Frontend | React 19 https://react.dev | MIT | Every layer is open source. You can swap qwen2.5:7b for Gemma, Llama, Mistral, or a fine-tuned checkpoint by changing one environment variable. Most contributions to this project are YAML files, not Python PRs. Adding support for a new country is: notices/fr/tax reminder.yaml name: "Avis de rappel fiscal" keywords: "Trésor public", "DGFIP", "avis d'imposition" severity default: act soon mock simple: "This is a French tax reminder." That's it. CI validates it against the JSON Schema automatically. A letter contains income, legal status, financial history, and sometimes your immigration situation. Explaining it with a closed API means uploading it. There is no enterprise tier, privacy toggle, or data-processing agreement that un-does the fact that your letter travelled to someone else's data center. With an open local model: tests/test local only.py fails the CI build if Open weights made this project's privacy guarantee credible. A closed API could promise the same guarantee; open weights prove it.