anurag-raapid/clinical-code-retrieval
Clinical Code Retrieval API
Hybrid semantic + graph retrieval for ICD-10-CM and CPT/HCPCS clinical codes, served from a single Hugging Face Space (Docker SDK, free CPU basic).
The Space runs three processes inside one container:
A tiny aiohttp proxy on 7860 (HF's exposed port) routes:
/cpt/*→http://127.0.0.1:8001/*(strips/cptprefix)- everything else →
http://127.0.0.1:8000/*
Endpoints
Quick test
# ICD
curl -s https://<user>-<space>.hf.space/health | python -m json.tool
curl -s https://<user>-<space>.hf.space/retrieve \
-H "Content-Type: application/json" \
-d '{"conditional_evidence": "Chest pain radiating to left arm; hypertension", "k": 5}'
# CPT
curl -s https://<user>-<space>.hf.space/cpt/health | python -m json.tool
curl -s https://<user>-<space>.hf.space/cpt/retrieve \
-H "Content-Type: application/json" \
-d '{"query_text": "Abdomen CT Scan", "k": 5}'What this Space downloads at startup
If an artifact is already on disk inside /data/, download_artifacts.sh skips it.
Secrets & environment variables
See [HF_SPACE_SETUP.md](HF_SPACE_SETUP.md) for the full step-by-step (creating the Space, adding secrets, adding variables, what to expect on first boot).
The TL;DR:
- Secrets (never in the repo):
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY - Variables:
AWS_DEFAULT_REGION,ICD_S3_CHECKPOINT_URI,ICD_S3_GRAPHMAE_EMB_URI,CPT_S3_CHECKPOINT_URI,CPT_S3_GRAPHMAE_EMB_URI
Everything else (device=cpu, ports, QuickUMLS=off, ...) has safe defaults baked into entrypoint.sh.
Repository layout
.
├── Dockerfile # single image, three services
├── entrypoint.sh # downloads S3, starts uvicorns, runs proxy
├── .dockerignore .gitignore
├── README.md # this file (also the HF Space README)
├── HF_SPACE_SETUP.md # detailed Space setup walkthrough
├── proxy/
│ ├── app.py # aiohttp reverse proxy on :7860
│ └── requirements.txt
├── icd/ # ICD-10-CM FastAPI service
│ ├── api/ src/ config/ data/
│ ├── pyproject.toml uv.lock
│ ├── .env.example
│ └── download_artifacts.sh
└── cpt/ # CPT/HCPCS FastAPI service
└── ... (mirrors icd/)Docker build notes
The Dockerfile copies pyproject.toml, uv.lock, and README.md for each subproject before running uv sync, so Hatchling can resolve readme = "README.md" while dependency layers are cached. The full icd/ and cpt/ trees are copied in a later layer.
docker build -t clinical-codes .Local development (optional)
docker build -t clinical-codes .
docker run --rm -p 7860:7860 \
-e AWS_ACCESS_KEY_ID=... -e AWS_SECRET_ACCESS_KEY=... -e AWS_DEFAULT_REGION=... \
-e ICD_S3_CHECKPOINT_URI=... -e ICD_S3_GRAPHMAE_EMB_URI=... \
-e CPT_S3_CHECKPOINT_URI=... -e CPT_S3_GRAPHMAE_EMB_URI=... \
clinical-codes
# open http://localhost:7860Cold-start note
The first request on a fresh Space boot takes 5–15 minutes (loads GatorTron from HF Hub, builds two FAISS indices, downloads ~20 GB of S3 artifacts). On free CPU the Space sleeps after 48 h of inactivity; the next cold start pays this cost again. The 9.4 GB emb_graphmae.npy files are downloaded as part of the same startup; they are memory-mapped (mmap_mode="r") at runtime so they do not consume 9.4 GB of RAM.
