TrueTrendआरोग्य वही

Hacktoberfest Weekend Challenge · Build for a Friend

My mother has three years of blood reports in WhatsApp.
This finally lets her read them.

TrueTrend keeps every lab report a family has, builds one timeline per test across labs, says whether a change is real or just normal variation, and explains it in Marathi — out loud. It runs on a home laptop with Gemma 4, and the reports never leave it.

It never speaks a number it can't find in the report.

The summary screen: three Marathi sentences about what changed, with a Listen button and questions for the doctor.
34 / 34values verified against the source PDF
603tests, none of which touch the network
0bytes of her data sent anywhere
15tests read, with sourced variation constants

The promise, and what it cost

A language model reading a lab report will sometimes produce a number that is not on the page. Not often — often enough that if the app says 6.9 and the report says 8.9, I have built something worse than the problem. So the model is not allowed to produce numbers at all.

Gemma proposes. Python verifies.

A value is marked verified only if it appears as its own word on that page with the same qualifier, ends its cell in the table, sits in a row that names the test, and has its unit printed in that row. The normal range counts only when both its limits are printed there too.

Anything unproven is never spoken.

A value that fails goes to a queue for a person to confirm against the original. It is never charted, never summarised, never read aloud, and never used in an answer — it is shown as “please check” until someone says.

Templates that cannot hold a digit.

Every sentence the app says is a template with placeholders, and a test enforces that none of them contains a digit of its own. Every number is inserted by code, from a value already located in a PDF.

She asks in her own words

Gemma never writes the answer. It reads the question and returns two things — which test, and which of five question types — as a constrained schema checked against the catalog. Code builds the sentence from stored, verified values.

माझी साखर वाढली आहे का?
HbA1c (सरासरी साखर): २० मे २०२६ रोजी ७.६ %, आता ८.९ % — आकडा वाढला आहे. From: 12 Jan 2026 – 28 Sep 2026 · 3 reports
is my cholesterol normal?
Total cholesterol: it is 236 mg/dL, above the lab's upper limit (200). Worth asking the doctor about. From: 28 Sep 2026 · Maitri Pathology Laboratory
what should I eat today?
I did not follow that question. Which test did you mean? Not guessed at — the app says when it does not know.
The Ask screen with a Marathi question and its answer, showing which reports the answer came from.

Real change, or just noise?

Blood values move between tests even when nothing has changed. If the app cried “your cholesterol went up!” at a 4% wobble, she would worry about nothing — and then ignore it when it mattered. So it compares every difference against the Reference Change Value for that specific test.

σ = √ln(1 + CV²)        where CV = √(CVa² + CVi²)
rise = e^(1.96·√2·σ) − 1
fall = 1 − e^(−1.96·√2·σ)

The log-normal form EFLM recommends, because a 30% rise and a 30% fall are not equally surprising. Every CVi comes from the EFLM Biological Variation Database, with its URL and access date in the data file. Where no published value exists — post-prandial glucose — the app never judges that test. It says “not compared” rather than inventing a constant.

The Changes screen: one row per test with its latest value and a verdict — real increase, normal variation, or not compared.

Why it runs on a laptop

Because of what the data is.

This is my mother's HbA1c, her thyroid, her haemoglobin, over three years. Sending it to a company so it can be summarised is a trade I am not entitled to make for her.

Because the pipeline had to be mine.

The promise is only keepable if I control every step between the PDF and the sentence — raw page text, constrained decoding, rejection, re-verification. An API that hands back prose gives you none of those seams.

Because it has to work in a power cut.

Only one step in the whole app needs the internet: downloading the Marathi voice, once. After that a laptop with no connection reads reports perfectly.

Gemma 4 runs through Ollama on 127.0.0.1. A non-loopback host is refused unless explicitly overridden, and OLLAMA_HOST from the environment is ignored, so a stray shell variable cannot quietly send her reports elsewhere.

Run it yourself

It ships with four synthetic sample reports — three labs, three layouts, one invented family — so you need nobody's real data to try it.

git clone https://github.com/DnyaneshU/TrueTrend
cd TrueTrend
pip install -e ".[voice]"

ollama pull gemma4:e4b
truetrend-voice install          # the Marathi voice, ~77 MB, once
truetrend-serve

Open http://127.0.0.1:8000, make an account, and add the PDFs from samples/. Needs Python 3.11+, about 6 GB of free RAM, and roughly 30 seconds a page.

There is no hosted demo, on purpose. Putting this on a server would mean uploading someone's medical reports to a machine they don't own — which is the thing the project exists to avoid. It runs where the reports already are.

What it does not do