This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle.
PlainRay turns radiology reports into plain-language patient explainers — on the clinic's own machine, with an open-weight model, for zero rupees per report.
It reads a report and produces, in one pass:
Who would pay for this: the kind of clinic that runs two radiologists, one front desk, and a stack of reports whose first word is usually "IMPRESSION:". Behind that desk sits a person who answers "what does effusion mean?" eleven times a week. Every hosted "AI patient portal" wants a per-report meter and a copy of the report on someone else's server. PlainRay flips it: flat license, zero usage cost, nothing ever leaves the machine.
The side-hustle math that makes it a real product instead of a demo: the clinic already owns the laptop, and the model runs on an RTX 4060. So the unit economics are: model = free forever, electricity = what the lamp costs, product = one flat fee per workstation. There is no other version of this offer where the cost driver of the whole business is $0 — that's only possible because the model is an open-weight one you can download.
Three synthetic reports are in the repo (samples/sample_reports.json — no real PHI is ever committed). Here is the actual flow, captured locally while the machine was offline for everything else:
The second frame is the mammography screening sample — the star of the show, because screening reports are the least readable of all (see it here).
No login, no cloud, no network. Unplug the ethernet cable and it keeps working — that is the demo. Run it yourself:
git clone https://github.com/4-thkind/plainray
ollama pull gemma3:4b # one time, ~3 GB
python -m plainray serve # http://127.0.0.1:7860
python -m plainray explain --file report.txt # JSON on stdout
python -m plainray selftest # prompts + validator + readability, no model needed
Everything lives in the 4-thkind/plainray repo:
plainray/llm.py — a minimal local Ollama client in stdlib urllib, ~40 lines. No pip, no SDK. plainray/prompts.py — the patient-safety prompt, readable in plain text by whoever deploys it.plainray/app.py — CLI (explain / serve / selftest) and a validator that enforces the JSON shape: caps list lengths, dedupes glossary terms, refuses an empty summary.plainray/readability.py — a Flesch-Kincaid grader in stdlib. Numbers, not promises.static/index.html — the UI; the server binds to 127.0.0.1 on purpose._validate() rebuilds the JSON from scratch. A 4B model | Sample report | Raw grade | PlainRay explainer |
|---|---|---|
| Chest X-ray, consolidation | 10.4 | 7.6 |
| Knee MRI, meniscus tear | 10.0 | 7.6 |
| Mammography screening | 12.3 | 6.7 |
http.server). Clinic IT never touches a package manager. PLAINRAY_MODEL): gemma3:12b on a bigger box, or the medical-tuned sibling medgemma — same code, same prompt.
This project was built in one working session with an AI coding agent — I set the problem, the constraints ("small, specific, useful, and it must actually run on this laptop") and reviewed everything it produced. The short form of that session — constraints discovered first, the decisions worth keeping, and what was hard — is checked into the repo as AGENT_NOTES.md. No DevRelay install for this build; the notes file is the session, honestly summarized.
Honest version: my first real user test hasn't happened yet. During this challenge window I built the product and ran it end-to-end on my own machine against three synthetic reports; nobody's real report went through it, because the right first user is a clinic that will trade one afternoon for a demo, and setting that up properly takes longer than the window. Rather than report a fake ten, here is the actual next step: one call to my cousin's ortho clinic, a printed example made from samples/, and two questions I'll log verbatim in the repo — would you pay, and how much per year?
If you're a radiologist or run a small clinic and want to be user #1: the demo runs from a fresh clone in under two minutes, and my contact is on my profile.
Best Use of Gemma — Gemma 3 4B runs entirely on-device through Ollama, powers the whole product, and the architecture keeps gemma3:12b / medgemma as one-variable drop-ins.
(Solo build — no teammates.)