NERUDO
Sign in
kcirtapfromspace/ClinIQPublicReplayed from github.com/kcirtapfromspace/ClinIQ
Loading community…

Files

Trunk
Browse repository

20 entries

README.md

357a0c1

ClinIQ — eICR → FHIR R4 on the edge with Gemma 4

A SwiftUI iPhone app that turns a clinician's dictation, paste, or eICR XML into a FHIR R4 Bundle ready for public-health surveillance — all on-device, no PHI off the phone.

Submission for the Gemma 4 Good Hackathon (Kaggle × Google DeepMind), targeting the Health & Sciences category and the Unsloth ($10K) prize track. Deadline 2026-05-18 23:59 UTC.

ClinIQ AI Review on iPhone — Gemma 4 extracts SNOMED/LOINC/RxNorm coded findings from a clinical narrative, clinician confirms each row.


Headline numbers

Plain text
F1 = 1.000 sustained across 80 deterministic reps   (combined-45 ×20 + combined-54 ×30 + combined-64 ×30, 0 FPs ×50 reps)F1 = 0.997 on the 64-case adversarial bench (recall = 1.000)F1 = 1.000 on 7 / 7 external CDC eICR test vectors (360 / 360 codes recovered)HL7 FHIR validator (Java IG): structural pass on every emitted BundleF1 = 1.000 on Jetson Orin NX 8 GB k8s pod (edge deployment)0 parse errors over 81 runs of the agent path (grammar stability)

Unsloth track delta (val-compact, 200 cases held out from training, Mac M-series Q3_K_M for like-for-like edge-deployment numbers):

base Q3_K_Mv62 (ships)v63 ⚠v63b ⚠
Micro-F10.3370.8370.5480.610
Micro-precision0.4690.8370.3930.474
Micro-recall0.2630.8370.9020.856
JSON-validity100%92%92%80%
Latency p50 (Mac)6.6 s3.08 s2.79 s2.81 s
LoRA tensors—490410 ⚠786
Train wall-clock (T4)—1h 04m3h 04m3h 04m

v62 is the shipped Unsloth-track LoRA. v63 and v63b are documented diagnostic work that found a silent toolchain regression: post-2026-04-30 releases of unsloth/peft drop LoRA k_proj + v_proj weights on Gemma 4's 20 global-attention layers (15–34) when transformers > 5.5.0 is installed. The bug hides at full precision (Kaggle PyTorch F1 = 0.9989) and only surfaces under Q3_K_M quantization (Mac F1 = 0.548). v63b's explicit layers_to_transform=list(range(35)) cleared the coverage gate (35/35 wrapping confirmed) but only recovered F1 to 0.610 — the remaining gap is the 786-tensor adapter wrapping the SigLIP vision tower in addition to the decoder. Ship gate (F1 ≥ 0.85) not met; v62 stays. Full diagnosis in tools/autoresearch/v63-experiment/EXPERIMENT.md and tools/autoresearch/v63b-experiment/EXPERIMENT.md; final submission narrative at tools/autoresearch/hackathon-submission-2026-05-18.md.


Try it

SurfaceURLWhat you'll see
Hosted demo (HF Spaces)https://huggingface.co/spaces/kcirtapfromspace/cliniq-eicr-fhirPaste an eICR narrative, watch the 3-tier pipeline emit a FHIR Bundle on ZeroGPU H200
iOS appapps/mobile/ios-app/ClinIQ/SwiftUI app, builds on iPhone17ProDemo simulator (UDID CADA1806-F64D-4B02-B983-B75F197D1EF3). Gemma 4 E2B Q3_K_M GGUF is side-loaded into the simulator's Documents/ on first demo run (see DEMO_SCRIPT.md step 0); the app's loader probes Documents/ → tmp/ → Bundle.main so seeded weights take precedence.
60-second demo scriptapps/mobile/ios-app/DEMO_SCRIPT.mdRead-along narration timed to a 7-beat sim walkthrough

How the pipeline works

Three tiers, escalated by latency:

TierWhatMedian latencyLLM?
1. DeterministicRegex over inline (SNOMED 12345) markers + CDA <code code="…" /> attrs + curated alias lookup with NegEx scope~5 msNo
2. RAG fast-pathCurated CDC NNDSS + WHO IDSR DB (~60 entries) with NegEx applied to the matched phrase~80 msNo
3. Gemma 4 agentNative function calling, 6-turn cap, GBNF-locked tool-call grammar5–35 sYes

Most cases never invoke the model. On the 54-case bench: 24 short-circuit at Tier 1, 14 at Tier 2, 16 reach the agent.

The Cand D gate decides when the deterministic + lookup path is trustworthy enough to bypass the agent entirely. See apps/mobile/convert/agent_pipeline.py and the c20 ledger in tools/autoresearch/c20-llm-tuning-2026-04-25.md.


What's in the repo

Plain text
apps/mobile/convert/      Python pipeline (regex / RAG / agent / bundle / score)apps/mobile/ios-app/      SwiftUI iOS appspaces/                   HF Spaces hosted demo (Gradio + ZeroGPU)kaggle-training/          Kaggle T4 training kernel (compact LoRA)tools/autoresearch/       Submission narrative + experiment ledgerstools/autoresearch/v62-submission/   Unsloth-track artifacts (model card, notebook plan)infra/                    Talos k8s overlays for Jetson clusterdata/eicr-samples/        CDC eICR test vectorsscripts/test_cases*.jsonl Bench cases (combined-27, adv4-7, longitudinal)

Read in this order (judges, 5-min path)

  1. This README — orientation
  2. tools/autoresearch/hackathon-submission-2026-05-18.md — final judge-facing one-pager (Health & Sciences + Unsloth)
  3. tools/autoresearch/v62-submission/MODEL_CARD.md — Unsloth-track model card (v62 shipped, v63 follow-up section appended)
  4. tools/autoresearch/v63-experiment/EXPERIMENT.md — v63 run record (max_seq=1024 retrain, F1=0.9989)
  5. HF Space — see it run

15-min path: add tools/autoresearch/c20-llm-tuning-2026-04-25.md (full ledger, 80-rep variance tables, every ablation) and apps/mobile/convert/build/c45_sustained_*.json (the 20 sustained-load reps).


Reproduce

bash
# Python venv with bench harness depspython -m venv scripts/.venv && source scripts/.venv/bin/activatepip install -e apps/mobile/convert​# Fetch the base Gemma 4 E2B Q3_K_M GGUF (2.4 GB):huggingface-cli download unsloth/gemma-4-E2B-it-GGUF \    gemma-4-E2B-it-Q3_K_M.gguf --local-dir models/​# Run the canonical bench against the local llama-server:llama-server --model models/gemma-4-E2B-it-Q3_K_M.gguf \             --port 8090 --jinja --ctx-size 32768 \             --parallel 4 --n-gpu-layers 99 --threads 8 &​scripts/.venv/bin/python apps/mobile/convert/agent_pipeline.py \    --cases scripts/test_cases.jsonl \            scripts/test_cases_adversarial{,2,3,4,5,6,7}.jsonl \    --out-json apps/mobile/convert/build/repro_combined64.json \    --endpoint http://127.0.0.1:8090

Expect F1 = 0.997 on combined-64. Single sustained rep takes ~6 minutes.

To bench the v62 Unsloth fine-tune:

bash
llama-server --model models/gemma-4-E2B-it-Q3_K_M.gguf \             --lora models/cliniq-gemma4-e2b-v62-lora.gguf \             --port 8091 --jinja --reasoning-format none --reasoning off \             --ctx-size 8192 --n-gpu-layers 99 --threads 8 &​scripts/.venv/bin/python apps/mobile/convert/bench_v62_singleshot.py \    --max-tokens 2048 --compare \    --out apps/mobile/convert/build/v62_val_compact_bench.json

What's novel

  • Three-tier extraction with a learned gate — most cases land on regex or RAG. The agent only fires when both lower tiers are uncertain or multi-axis-incomplete. F1 = 1.000 with median ~5 ms, not seconds.
  • Autoresearch loop — six bench → bug-find → fix → re-bench cycles grew the bench from 27 → 64 cases, surfacing 13 precision bugs, fixing 8 in Python and Swift. The model never moved.
  • External credibility — every Bundle structurally validates against HL7's official Java IG validator. 7/7 perfect on the official CDC eICR test vectors.
  • Unsloth-distilled single-shot path — unsloth/gemma-4-E2B-it v62 LoRA trained on a free Kaggle T4 in 1h 4m turns the base model from F1 = 0.34 into F1 = 0.84 on Mac Q3_K_M with 0.84 precision, 9% faster per inference than the v63 follow-up (which has a known Mac-quantization regression being addressed in v63b). The fine-tune isn't replacing the agent (which already hits 1.000) — it's the speed tier for known-format inputs.

Background

The canonical electronic Case Report processing path is cloud-only: NLP extraction (e.g., AWS Comprehend Medical) → ontology mapping (e.g., IMO Precision Normalize) → identity resolution (e.g., AWS Glue FindMatches) → jurisdiction-specific rules engine. ClinIQ is the on-device extraction tier of that pipeline — what an LMIC clinic would run when there's no AWS, no internet, no Verato, and no AIMS.

The longitudinal "what's new" view (see apps/mobile/ios-app/ClinIQ/ClinIQ/Views/Cases/PatientTimelineView.swift) is the edge-side analogue of the flat-CSV diff between case versions for the same patient that production eCR pipelines emit.


License + acknowledgements

Apache 2.0 (model adapter follows base model's Gemma TOU).

Built with: Gemma 4 E2B (Google DeepMind), Unsloth, llama.cpp, HuggingFace Transformers + PEFT + TRL, SwiftUI, Talos Linux, HL7 FHIR Validator, fhir.resources (Python).

Thanks to the Gemma team for the open weights.

Work history & code evidence

Code ecosystem

Explore repos →
Observed in repos on this profile

File and dependency evidence from up to six visible repos. Repository associations do not establish personal expertise or preference. Security tags describe tools and policies, without rating security.

Reading repo evidence…

Contribution activity

Filters

Commits, completed tasks and releases, grouped by recorded task or batch. Dates use UTC.

Loading recorded history…