ClinIQ: Building an On-Device Pharmacist for Small Clinics

Community Article
Published June 8, 2026

Small clinics are drowning in paper. A nurse uploads a hospital discharge summary, last week's intake note, and a specialist consult — all as separate files. Nobody has time to cross-reference all three. A medication prescribed in one document may conflict with an allergy documented in another. These conflicts get missed. Patients get hurt.

image

I built ClinIQ to fix this. It reads all the documents together and flags dangerous combinations automatically — before any question is asked.

What I Built

ClinIQ is a privacy-first clinical document assistant. Upload patient records and you instantly get:

  • Proactive Drug Safety Alerts — automatic cross-document conflict detection the moment files are uploaded
  • Clinical Q&A — ask anything in plain English, get grounded answers in ~2 seconds
  • Structured Extraction — ask for a list, get a formatted table (medications, allergies, diagnoses, vitals)
  • Cross-Document Reasoning — pulls context from all uploaded files simultaneously
  • OCR Support — works on scanned PDFs and image files too

The Stack

The whole thing runs on a 3B model. Here is why that is enough.

Clinical document extraction is a retrieval and pattern matching problem, not a general reasoning problem. The hard work is done upstream.

LangGraph 5-Node Agent:

CLASSIFY → DECOMPOSE → RETRIEVE → GENERATE → REFLECT
  • CLASSIFY: rule-based, no LLM call
  • DECOMPOSE: breaks complex questions into focused sub-queries
  • RETRIEVE: hybrid BM25 + dense retrieval (sentence-transformers), score fusion, top-6 chunks
  • GENERATE: Qwen2.5-3B-Instruct synthesizes the answer
  • REFLECT: heuristic word-overlap check catches hallucinations without an extra LLM call

Drug Safety Pipeline (two steps):

Step 1 — Regex extraction: covers 20+ medication header variants and 15+ allergy header variants, no LLM needed, instantaneous.

Step 2 — LLM reasoning: feeds clean extracted lists to Qwen, asks about dangerous interactions, returns structured JSON with DANGER / WARNING / INFO severity.

Inference stack:

  • HF Space (CPU): gr.Server + LangGraph + hybrid retriever
  • Modal A10G (GPU): llama.cpp with Qwen2.5-3B-Instruct Q4_K_M GGUF
  • The Space calls Modal over HTTP — roughly $0.001 per query

The Gradio gr.Server Choice

I used gr.Server instead of standard Gradio components. This gave me a completely custom HTML/CSS/JS frontend with streaming responses, a real-time trace inspector, color-coded safety alerts, and structured data tables — none of which would be easy with standard Gradio blocks.

The tradeoff: much more frontend work. But the result looks and feels like a real clinical tool, not a demo.

What Surprised Me

Regex beats LLM for extraction. My first version used the model to extract medication and allergy lists. It was slow, inconsistent, and sometimes hallucinated entries. Replacing it with a regex pipeline that covers real-world clinical header formats made it faster and more reliable.

Heuristic reflection works. I replaced an LLM-based reflection step with a simple word-overlap check between the answer and the retrieved context. It catches the same hallucinations, adds zero latency, and uses no tokens.

3B is enough when retrieval is good. Qwen2.5-3B-Instruct handles structured JSON output and clinical reasoning well when the right context is in its window. The retriever's job is to make sure it always is.

What Went Into This

The frontend is built entirely with gr.Server — a fully custom HTML, CSS, and JavaScript interface with no standard Gradio components. Every query streams in real time through a LangGraph agent running on the Space, while the actual model inference happens on llama.cpp deployed on Modal. The model is Qwen2.5-3B-Instruct loaded from HuggingFace Hub and quantized to Q4_K_M — a 3 billion parameter model that handles the full clinical reasoning pipeline. Every agent trace is automatically pushed to a HuggingFace dataset so every query is logged and reproducible.

Try It

Space: build-small-hackathon/cliniq

Load the sample documents, watch the drug safety check run automatically, then ask questions. The sample docs have an intentional cross-document conflict — Aspirin prescribed in the discharge summary, Aspirin allergy documented in the intake note — to show exactly what the safety checker catches.

Demo: loom.com/share/d72ef56097194dd08fdaa734ff64d90f

Community

Sign up or log in to comment