cliniq / README.md
karthikmulugu08's picture
Update README.md
1649dde verified
|
Raw
History Blame Contribute Delete
9.27 kB

A newer version of the Gradio SDK is available: 6.20.0

Upgrade
metadata
title: ClinIQ  Clinical Document Assistant
emoji: 🩺
colorFrom: blue
colorTo: green
sdk: gradio
sdk_version: 6.11.0
app_file: app.py
python_version: '3.11'
pinned: false
license: apache-2.0
tags:
  - medical
  - rag
  - qwen
  - privacy
  - langgraph
  - llama-cpp
  - hackathon
  - build-small-2026
  - tiny-titan

ClinIQ — Privacy-First Clinical Document Assistant

ClinIQ is an AI-powered clinical document assistant built for small medical clinics. Upload patient records — discharge summaries, intake notes, consult reports, scanned documents — and instantly get answers, structured extractions, and proactive drug safety alerts.

Model: Qwen2.5-3B-Instruct (Q4_K_M) · Inference: llama.cpp on Modal A10G GPU · Framework: Gradio gr.Server + LangGraph


The Problem

Small clinics handle dozens of patients daily. Nurses upload a discharge summary from the hospital, an intake note from last week, and a specialist consult from yesterday — 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.

ClinIQ solves this by reading all documents together and flagging dangerous combinations automatically — before any question is asked.


What ClinIQ Does

1. Proactive Drug Safety Check

The moment documents are uploaded, ClinIQ automatically scans every medication and allergy across all files and flags dangerous combinations. No question needed.

Example: a discharge summary prescribes Aspirin 81mg. An intake note documents an Aspirin allergy causing bronchospasm. These are two separate files from two different visits. ClinIQ catches the conflict instantly:

DANGER  Aspirin allergy contraindication
        Patient prescribed Aspirin 81mg but has documented bronchospasm reaction
        Recommendation: Switch to Clopidogrel (noted in cardiology consult)

2. Clinical Q&A

Ask any question in plain English. ClinIQ retrieves relevant chunks from all uploaded documents and generates a precise, grounded answer in ~2 seconds.

  • "Who is the attending physician?" → direct fact lookup
  • "What are the follow-up instructions?" → extracts from discharge summary
  • "Is it safe to give this patient aspirin?" → reasons across multiple documents
  • "What alternative was recommended instead of aspirin?" → retrieves from consult note

3. Structured Extraction

Ask for a list and get a formatted table — not a paragraph of text.

  • "List all medications" → table with name, dose, frequency, route
  • "What are all the allergies?" → table with substance, reaction, severity
  • "List all diagnoses" → primary and secondary conditions
  • "What are the vital signs?" → structured vitals object

4. Cross-Document Reasoning

ClinIQ retrieves context from all uploaded documents simultaneously. A question about drug interactions can pull the medication list from the discharge summary, the allergy list from the intake note, and the cardiology recommendation from the consult — combining all three into a single coherent answer.

5. OCR Support

Supports scanned PDFs and image files (JPG, PNG, TIFF). Tesseract OCR extracts text from scanned documents automatically before indexing.


Architecture

Document Ingestion Pipeline

Upload (PDF / TXT / JPG / PNG / TIFF / scanned PDF)
        ↓
Text Extraction
  ├── Native PDF  → pypdf (fast, text-selectable)
  ├── Scanned PDF → pdf2image + tesseract OCR
  ├── Image       → tesseract OCR (upscaled to 1000px for accuracy)
  └── TXT / MD    → direct read
        ↓
Chunking — 400 character chunks with 80 character overlap
        ↓
Dual Indexing
  ├── BM25 index  (rank_bm25) — keyword matching
  └── Dense index (sentence-transformers/all-MiniLM-L6-v2) — semantic matching

Query Pipeline — LangGraph 5-Node Agent

User Question
      ↓
  [1] CLASSIFY
      Rule-based classification — no LLM call
      Detects query type: simple / structured / complex / comparison
      ↓
  [2] DECOMPOSE
      For complex and comparison queries only
      Qwen breaks the question into 2-3 focused sub-queries
      ↓
  [3] RETRIEVE
      Runs each sub-query through hybrid retrieval:
      ├── BM25 score (keyword overlap)
      ├── Dense score (semantic similarity via cosine)
      └── Score fusion → top-6 unique chunks across all documents
      ↓
  [4] GENERATE
      Qwen2.5-3B-Instruct synthesizes an answer from retrieved chunks
      Structured queries → returns JSON parsed into a table
      Free-text queries → returns a concise clinical answer
      ↓
  [5] REFLECT
      Heuristic grounding check — verifies answer overlaps with context
      Flags potential hallucinations without an extra LLM call
      ↓
Streaming response → custom HTML/JS frontend (gr.Server)

Drug Safety Pipeline (runs in parallel with Q&A)

All uploaded documents
        ↓
Step 1 — Regex Extraction (no LLM, instantaneous)
  Scans for 20+ medication section header variants:
  MEDICATIONS, Current Medications, Active Meds, Home Meds, Rx, Drug List...
  Scans for 15+ allergy section header variants:
  ALLERGIES, Drug Allergies, Known Allergies, Sensitivities, Adverse Reactions...
  Also handles inline format: "Allergies: Penicillin, Sulfa"
  Deduplicates across all documents
        ↓
Step 2 — LLM Safety Reasoning (Qwen2.5-3B)
  Feeds clean extracted lists to the model
  Asks: "are there dangerous drug-allergy or drug-drug interactions?"
  Returns structured JSON: alerts with DANGER / WARNING / INFO severity
        ↓
Colour-coded alert panel in the UI

Inference Stack

HF Space (CPU)                    Modal Cloud (GPU)
─────────────────                 ──────────────────────────────
gr.Server (Gradio 6.11)          nvidia/cuda:12.4.0-devel image
LangGraph agent                   llama.cpp built with CUDA
Hybrid retriever                  Qwen2.5-3B-Instruct Q4_K_M GGUF
Safety checker                    llama-server on A10G
        │                                   │
        └──── HTTP POST ────────────────────┘
              (httpx, timeout=300s)
              payload: {prompt, n_predict, temperature: 0.0}

Tech Stack

Component Technology
Frontend Custom HTML/CSS/JS via gr.Server (Gradio 6.11)
Agent framework LangGraph (StateGraph, 5 nodes)
Retrieval BM25 (rank_bm25) + Dense (sentence-transformers)
Vector index FAISS (faiss-cpu)
LLM Qwen2.5-3B-Instruct via llama.cpp Q4_K_M
Inference server llama-server (llama.cpp) on Modal A10G
OCR tesseract-ocr + pdf2image + pytesseract
PDF parsing pypdf
Trace sharing HuggingFace Hub API (huggingface_hub)

Why a 3B Model Works Here

Clinical document extraction is a retrieval + pattern matching problem, not a general reasoning problem. The hard work is done by the hybrid retriever (finds the right chunks) and the two-step safety checker (regex extracts reliably, LLM only reasons on clean lists). The model's job is to synthesize well-retrieved context into a clean answer.

Qwen2.5-3B-Instruct handles this well:

  • Instruction-tuned for structured output (JSON tables)
  • Fast — ~2 seconds on A10G at Q4_K_M quantization
  • Efficient — ~1.8GB on disk, ~$0.001 per query
  • Accurate enough for fact retrieval from clinical text

Model

bartowski/Qwen2.5-3B-Instruct-GGUF — Q4_K_M quantization — Apache 2.0 license

Base model: Qwen/Qwen2.5-3B-Instruct


Dataset

Demo documents are synthetic clinical notes styled after MTSamples — a discharge summary, an intake note, and a cardiology consult for two fictional patients. They contain an intentional cross-document drug-allergy conflict (Aspirin prescribed in one, Aspirin allergy in another) to demonstrate the safety checker.

Live agent traces from queries are published at karthikmulugu08/cliniq-traces.


Running Locally

pip install -r requirements.txt
python app.py
# visit http://localhost:7860

Deploying to Modal + HF Space

# 1. Deploy the GPU inference server
pip install modal
modal setup
modal deploy modal_inference.py
# Copy the printed endpoint URL

# 2. Set Space secrets
# MODAL_ENDPOINT → URL from modal deploy
# HF_TOKEN       → your HF write token
# HF_DATASET_REPO → karthikmulugu08/cliniq-traces

Submission Links