Presenting problem
Clinicians lose time reading long, multi-report patient histories, and cloud LLMs are off the table for protected health data.
A clinical assistant that reads a patient's report PDFs and writes a structured summary — medical journey, current status, action plan — where every claim links back to the exact source passage. It runs fully on-premise: a local Llama 3 through Ollama and an encrypted PostgreSQL store.
Procedure
- T+00:07 · STEP 01
Parse
PDFs are read with PyMuPDF (Tesseract OCR as fallback) and split into ~500-character chunks with overlap.
- T+00:14 · STEP 02
Encrypt & embed
Each chunk is stored encrypted with pgcrypto beside a 768-dim nomic-embed-text vector in pgvector.
- T+00:21 · STEP 03
Hybrid retrieve
Section regex (FINDINGS / IMPRESSION), vector cosine distance and keyword search run together — text is decrypted only inside SQL.
- T+00:28 · STEP 04
Continuity
The previous summary and the doctor's edits are fed back as high-priority context, so summaries evolve instead of restarting.
- T+00:35 · STEP 05
Parallel generation
The specialty is classified (universal, oncology, speech), then journey, status and plan are extracted concurrently, plus specialty-specific data.
- T+00:42 · STEP 06
Safety & render
Deterministic temporal filters drop stale plan items, output is schema-validated, and the UI renders cards with clickable citations.
Vitals
Treatment plan
Glass-box citations
Every line of the summary opens the source PDF at the cited passage.
Patient RAG chat
Ask questions about a patient's history, with citations and speech-to-text input.
Allergy safety gate
A drug-specific allergy check blocks printing the digital prescription.
Oncology & audiology views
Tumour-size trends, TNM staging and biomarkers, plus audiogram charts.
Doctor edits
Append-only edits are merged at read time and carried into the next summary.
Clinician notes
Encrypted-at-rest RAG. Chunks stay encrypted in Postgres; decryption happens inside the retrieval SQL while vector search still runs.[1]
Parallel specialty routing. One classification call routes the case, then the summary sections are generated concurrently with asyncio.gather.[2]
Temporal safety filter. A deterministic pass removes plan items that are already completed, past-dated or duplicated before anything reaches the doctor.[3]
Prescription
| Frontend | React 19 · Vite · Tailwind · react-pdf · Recharts · jsPDF |
|---|---|
| Backend | FastAPI · SQLAlchemy · psycopg2 |
| Data | PostgreSQL · pgvector · pgcrypto |
| AI | Ollama · Llama 3 8B · nomic-embed-text · PyMuPDF · Tesseract |