Eleven parts ago the clinic could not have an assistant, because every assistant on offer wanted its patients' questions sent somewhere else. Now it has two, running on a box in the building, answering from its own documents, citing them, refusing what they do not cover, and scoring ninety percent on an exam written to trip them. This is the retro: the gallery, the meter with its method shown, every mistake in one list, and the verdict on whether affordable hardware gives a clinic a private assistant worth having.

The staff Assistant page answering what a first-time patient should bring, citing Patient information > Before your appointment. Staff (Part 7)
The kiosk refusing a staff-only question with the fixed sentence: I don't know that; please ask reception. Kiosk (Part 9)
The two faces of the same pipeline. The staff page cites a document; the kiosk, asked for a staff-only number, gives the fixed refusal because its query never sees the document. Part 5's insurance-card answer, the picture that started the knowledge work, is the one to hold these against.

What was built

  • A runtime on the server (Part 4): Ollama as a systemd service on loopback, warm-up timer, four settings each with a measured reason.
  • A model chosen by exam (Part 2): Qwen 2.5 14B, after Llama over-called tools and Gemma was refused them.
  • A sizing table from measurements (Part 3): CPU-only waits, four users as the knee on a 16 GB card, 120 W above idle while answering.
  • Knowledge in the clinic's own PostgreSQL (Parts 6 and 7): heading-aware chunks, pgvector, an audience filter in SQL, citations enforced by a guard, one fixed refusal.
  • A live question through a tool (Part 8): get_queue, with a classifier in code deciding when a tool is even offered.
  • A patient assistant (Part 9): public documents only, rate-limited, on the kiosk and in the phone app.
  • An exam (Part 10) and a runbook (Part 11).

The number

Fifty questions, fifty-eight evaluations, three models. The chosen model passed 52, answered every grounded question, refused every dose and medicine name, invented nothing in sixteen questions built to tempt it, and answered in 0.7 seconds at the median. Its failures were four over-helpful answers to staff questions asked as a patient, none of which leaked a staff fact, and two over-refusals on trap questions. The 8-billion fallback scored 79 percent; the 3-billion model 62 and failed every safety question, which is the number that retires it.

The meter, and how it is measured

Seasons one to three closed at about $6.20, $3.60 and $7.20. This season's method changed, and the reading must say so. The application parts were built by a coding assistant working from written briefs, and the harness reports each build's token usage. Those runs, Parts 5 to 11 plus the initial code survey, consumed about 1.1 million tokens. Priced at the list rate of the model that ran them, with a typical input-heavy split, that is about $9. What the harness does not meter is the session that wrote the briefs, read the results, took the measurements and wrote these posts, which in this season did more of the thinking than in any previous one. So the honest reading is: about $9 of metered build, plus an unmetered author's session. The running cost, measured rather than estimated, is about 28 kWh a month for the worked example in Part 11.

PartMetered tokensWall timeTool uses
Code survey74k2 min12
5 plumbing114k7 min52
6 knowledge110k8 min53
7 retrieval145k13 min75
8 tools198k25 min115
9 patient212k21 min121
10 evaluation156k17 min78
11 operations99k13 min39

Every mistake, in one list

  • Part 1: the model embellished "previous prescriptions" into "or medical records".
  • Part 2: the exam's refusal check could not read "don't"; question 19 had no scale.
  • Part 3: the first sizing run measured a prompt cache and a serialised queue, not a CPU and not concurrency.
  • Part 4: an install hung on a sudo prompt nobody could see; then failed on missing zstd.
  • Part 5: a test-critical sentence wrapped across a line; a field named after its own class; keep-alive had no path through the abstraction.
  • Part 6: an int-returning entry point broke the web path; a tool manifest in the wrong folder.
  • Part 7: the citation guard threw away a correct inline-cited answer; the insurance "refusal" was a legitimate answer.
  • Part 8: a using directive; Part 7's rule blocking every queue question; a test in someone else's slot; a Thai preamble before a tool call.
  • Part 9: a refusal shown with two source lines under it.
  • Part 10: the harness misread refusals and citations; one impossible exam question.
  • Part 11: a warm-up unit panicking on a missing HOME after doing its job.

Count them by who made them. The local model: the embellishment, the Thai, the over-helpful answers, the source line under a refusal. The coding assistant: most of the rest. The human: the exam bugs, the insurance section, the impossible question, the sudo prompt. Three parties, and the largest share of mistakes belonged to whoever was writing the test at the time. The season's refrain, test the test, earned its place.

What the bench could not prove

Three things stayed unproven and are recorded rather than faked. The Android build of the Pocket app was not exercised in Part 9; the shared screen was photographed on the web host. The kiosk's sixty-second reset was built on the proven success-screen pattern but not photographed. And the retrieval cut-off from Part 7 never fired during the evaluation, so its behaviour on a truly distant question is asserted by a unit test, not by the exam. A later revision needs questions chosen to miss.

The verdict

Yes, with the boundaries drawn. On a single 16 GB card, a free model, given the clinic's documents and a citation rule, is a private assistant a front desk can use: correct on what the documents say, silent on what they do not, safe on medicine, and fast. It is not a general assistant, it will not reason about a patient's condition, and it needs a person who owns the box for a few hours a quarter. For a clinic whose alternative was sending patient questions out of the building, that trade is the right one, and the numbers that say so are in the repository for anyone to re-run when the models change.

How the meter is measured: the coding assistant's token usage as reported by the harness for each build run, priced at the running model's list rate with an input-heavy split; the author's own session is unmetered and said to be so. Electricity from Part 3's measured idle and answering draw. Both perishable.

Model pick, the season's rule: high effort wrote the briefs, the sizing analysis, the exam design and the prose; the cheaper model executed briefs that named every file and behaviour. Where a build went long, Part 8 and Part 9, it was a model behaviour nobody could have briefed for.

Checkpoint: tags private-02 to private-11 in the repo, and note that the commit order reads 5, 6, 4, 7, 8, 11, 9, 10, because the server documentation was committed after the first two builds; the tags are the map. Start at Part 1 if you arrived here first.