Zero-latency pharmacogenomic sentinel — preventing fatal adverse drug reactions in real-time.
PharmaShield is a multimodal Live Agent that listens to a doctor's consultation via ambient audio, identifies drug prescriptions in context, and triggers a nanosecond-speed pharmacogenomic risk check. If a critical genetic contraindication is detected, Gemini interrupts the doctor with a voice barge-in before the prescription is validated.
Built for the Gemini Live Agent Challenge — Live Agents category.
- How It Works
- Architecture
- Prerequisites
- Quick Start (Local)
- Deploy to GCP
- Data Sources
- How to Demo
- Known Limitations
Doctor speaks → Gemini Live API (audio stream)
↓
Extracts: patient_id + drug + current_meds
↓
Tool call: check_pharmacogenomics()
↓
C++23 Sentinel Core (mmap + binary search, 40ns)
↓
Pharmacogenomic risk score (PGx + physiology)
↓
If critical → Gemini voice barge-in interrupts doctor
The system is split into two strict layers:
- Intelligence layer (Gemini 2.5 Flash Live) — ambient listening, entity extraction, natural language barge-in. The LLM makes zero clinical decisions.
- Deterministic engine (C++23) — all risk logic is hardcoded from CPIC guidelines, auditable, reproducible.
40-nanosecond lookups via
mmap+std::ranges::equal_rangeon a sorted binary file.
See ARCHITECTURE.md for the full system diagram.
┌─────────────────────────────────────────────────────────┐
│ Clinical Env (Browser) │
│ Doctor mic → Telemetry UI → WebSocket → Cloud Run │
└─────────────────────────────────────────────────────────┘
│ WSS (audio PCM16 + events)
┌─────────────────────────▼───────────────────────────────┐
│ FastAPI Orchestrator (Cloud Run) │
│ uvloop + WebSocket manager + tool call dispatcher │
└──────┬──────────────────────────────────────┬──────────┘
│ GenAI SDK (audio stream) │ pybind11
▼ ▼
┌─────────────────┐ ┌─────────────────────────┐
│ Gemini 2.5 │ │ Sentinel Core (C++23) │
│ Flash Live │ │ genetic_core.so │
│ Vertex AI │ │ mmap(patients.bin) │
│ │ │ 40ns O(log N) lookup │
└─────────────────┘ └──────────┬──────────────┘
│
┌──────────▼──────────────┐
│ Cloud Storage │
│ patients.bin (1.8 MB) │
└─────────────────────────┘
| Tool | Version | Install |
|---|---|---|
| Python | 3.12+ | python.org |
| CMake | ≥ 3.31 | apt install cmake or cmake.org |
| GCC / Clang | C++23 support (GCC ≥ 13 or Clang ≥ 16) | apt install build-essential |
| Docker | 24+ | docs.docker.com |
| gcloud CLI | latest | cloud.google.com/sdk |
GCP requirements:
- A GCP project with billing enabled
- APIs enabled: Cloud Run, Cloud Build, Cloud Storage, Vertex AI
gcloud auth application-default loginconfigured locally
Environment variables (required):
export GOOGLE_CLOUD_PROJECT=your-project-id
export GCP_LOCATION=us-central1
export FRONTEND_SECRET=your_secret_here # shared between backend and browser
export TMP_DATA_PATH=/tmp/patients.bin # path to the binary data file
export DATA_BUCKET=${GOOGLE_CLOUD_PROJECT}-pharmashield-storagegit clone https://github.com/riyaneel/pharmashield.git
cd pharmashieldpython -m venv .venv && source .venv/bin/activate
pip install pandas pybind11 fastapi uvicorn uvloop httptools \
websockets google-cloud-storage google-genaiNo real patient data is included in this repository (see Data Sources).
Generate a realistic synthetic patients.bin for local testing:
python tools/synthetic_data_generator.py --patients 1000 --out /tmp/patients.binExpected output:
[+] Generating 1000 synthetic patients...
[+] CYP2D6: PM=8.1% IM=30.9% EM=58.7% UM=2.3%
[+] CYP2C19: PM=4.2% IM=26.1% EM=56.3% UM=13.4%
[+] 3247 risk records written → /tmp/patients.bin (38.9 KB)
[!] Demo patient: ID 99999001 → CYP2D6 UM + codeine = GUARANTEED ALERT
cd core
cmake -DCMAKE_BUILD_TYPE=Release .
make -j$(nproc)
cd ..This compiles genetic_core.so — the pharmacogenomic lookup engine using mmap and std::ranges::equal_range. The
.so is automatically placed in the Python site-packages by the CMake build script.
Verify the build:
python -c "import genetic_core; print('Engine OK')"
# → Engine OKexport GOOGLE_CLOUD_PROJECT=your-project-id
export FRONTEND_SECRET=dev_secret
export TMP_DATA_PATH=/tmp/patients.bin
uvicorn app.main:app --host 0.0.0.0 --port 8080 --loop uvloopExpected startup output:
[INFO] Bootstrapping PharmaShield Asynchronous Orchestrator...
[INFO] Binary data already in RAM.
[INFO] Direct memory mapping via engine...
[INFO] Engine loaded.
[INFO] System ready to process WSS streams.
Health check:
curl http://localhost:8080/health
# → {"status":"healthy","engine":"generic_core","concurrency_model":"uvloop_threadpool"}Open frontend/index.html in your browser (no build step required — vanilla HTML/JS).
The frontend auto-detects
localhostand connects tows://127.0.0.1:8080/api/v1/stream.
The entire infrastructure is provisioned by a single script.
gcloud auth login
gcloud config set project your-project-idchmod +x setup_iac.sh
bash setup_iac.shThis script does the following in order:
- Enables APIs — Cloud Run, Cloud Build, Cloud Storage, Vertex AI
- Creates a dedicated service account (
pharmashield-runner) with minimum required permissions (Storage objectViewer + Vertex AI user) - Provisions the GCS bucket for
patients.bin - Triggers Cloud Build to build and push the Docker image
- Deploys to Cloud Run (gen2, min 1 instance, 2Gi RAM,
--no-cpu-throttlingfor C++ performance)
# Using synthetic data (for judges / public demo):
python tools/synthetic_data_generator.py --patients 10000 --out patients_sample.bin
gsutil cp patients_sample.bin gs://${GOOGLE_CLOUD_PROJECT}-pharmashield-storage/patients.bin
# The service downloads this file at startup and mmap it into RAM.SERVICE_URL=$(gcloud run services describe pharmashield-core \
--region=us-central1 --format='value(status.url)')
curl ${SERVICE_URL}/health
# → {"status":"healthy","engine":"generic_core",...}The following env vars are set automatically by setup_iac.sh.
To set FRONTEND_SECRET securely via Secret Manager:
echo -n "your_secret" | gcloud secrets create pharmashield-frontend-secret \
--data-file=- --replication-policy=automatic
# setup_iac.sh already adds --set-secrets to the deploy commandThe production dataset is derived from three sources that require institutional data access agreements:
| Source | Description | Access |
|---|---|---|
| MIMIC-IV | 300k+ ICU patient admissions, demographics, labs | PhysioNet credentialed access |
| PharmGKB | Pharmacogenomic variant-drug association database | Free registration required |
| NHLBI CCDG WGS | Whole genome sequencing VCFs (chr1–3) | dbGaP access required |
The ETL pipeline that processes these sources lives in tools/data_transfo.py.
tools/synthetic_data_generator.py generates a statistically realistic synthetic dataset using:
- Allele frequencies from gnomAD v4 (EUR baseline, with AFR/EAS/AMR variants) via Hardy-Weinberg simulation
- CPIC diplotype-phenotype tables for CYP2D6, CYP2C19, CYP2C9, CYP3A5, CYP2B6
- Published CNV prevalences: CYP2D6 duplication (UM) ~2% EUR, deletion ~1%
- Realistic physiological distributions: age N(55,15), eGFR proportional to age, pregnancy 3%
- Hardcoded demo patient (ID
99999001) guaranteed to trigger an alert for easy judging
# Generate 10,000 synthetic patients (~1.8 MB)
python tools/synthetic_data_generator.py --patients 10000 --out /tmp/patients.binNo real patient data, no PII, fully reproducible.
This scenario is guaranteed to trigger a pharmacogenomic alert with the synthetic dataset.
Setup:
- Start the backend (local or Cloud Run)
- Open
frontend/index.html - Click the microphone button to enable ambient listening
- Wait for "PharmaShield Live Armed" status
Script — speak naturally into the microphone:
"Okay, so for patient ninety-nine-ninety-nine-zero-zero-one, I'm thinking of prescribing codeine for the post-operative pain. Standard dose, 30 milligrams every six hours."
What you should see:
- Gemini extracts
patient_id=99999001anddrug=codeinefrom the audio - The C++ engine is called — lookup completes in ~40ns
- Patient 99999001 is a CYP2D6 Ultra-Rapid Metabolizer — codeine is converted to morphine at 4× the normal rate → fatal respiratory depression risk
- The
Patient IDandDrugfields are pre-filled automatically in the UI - A voice barge-in from Gemini interrupts: "Warning Doctor — patient 99999001 has a critical genetic contraindication for codeine. CYP2D6 ultra-rapid metabolizer. Risk of fatal morphine accumulation. Consider tramadol or a non-opioid alternative."
- The red alert banner appears in the Diagnostics panel
Alternative high-impact scenario (clopidogrel + CYP2C19 PM):
"The patient is number ten-zero-zero-four-two-three-five. She had a stent placed last week, and I want to start her on clopidogrel 75 milligrams daily."
→ Triggers alert for CYP2C19 Poor Metabolizer — clopidogrel is a prodrug that requires CYP2C19 activation. PM patients cannot activate it → stent thrombosis risk.
While typing a patient ID in the Patient ID field, the backend sends hardware prefetch instructions (
__builtin_prefetch) to warm the CPU cache for that patient's data. By the time you press "Run Check," the data is
already in L1/L2 cache — hence the ~40ns lookup.
You can observe this in the backend logs:
[INFO] Prefetch → partial_id=1000423 (keystroke event)
[INFO] Tool call → patient=10004235, drug=clopidogrel
[INFO] Lookup completed in 41ns
- The
patients.binfile included in the demo is 100% synthetic. It is generated from published allele frequency distributions (gnomAD v4) and does not contain real patient data. The production pipeline (tools/data_transfo.py) requires institutional access to MIMIC-IV, PharmGKB, and NHLBI WGS data. - The synthetic generator covers CYP2D6, CYP2C19, CYP2C9, CYP3A5, CYP2B6 phenotypes. UGT1A1, NAT2, TPMT/NUDT15, and HLA typing are planned for the next iteration.
- This is not a certified medical device. PharmaShield is a research prototype and hackathon submission. It must not be used for real clinical decisions without formal validation and regulatory clearance (FDA SaMD Class II / CE MDR 2017/745).
- Drug-drug interaction pairs currently cover ~50 critical documented combinations. A comprehensive formulary would require integration with a licensed drug database (Micromedex, Lexicomp).
- Phenoconversion (functional phenotype override when a strong CYP inhibitor is co-prescribed) is modeled in
tools/pgx_pipeline.pybut not yet fully wired into the runtime C++ scoring engine — it is the primary target for the next development sprint. - The QTc prolongation layer and geriatric risk scoring (Beers Criteria 2023) are implemented in
tools/pgx_pipeline.pybut not yet connected to the binary format.
- The current deployment uses Cloud Run with
--min-instances 1to keep the C++ engine warm. Cold starts take ~8 seconds (GCS download + mmap). This is acceptable for a demo but would require a different strategy for production (Cloud Run Jobs warm-up or GKE). FRONTEND_SECRETis currently passed as an environment variable. Production deployments should use Google Secret Manager (scaffold provided insetup_iac.sh, commented).
| Component | Technology |
|---|---|
| AI model | Gemini 2.5 Flash Live (gemini-live-2.5-flash-native-audio) |
| AI SDK | Google GenAI Python SDK (google-genai) |
| Backend | FastAPI + uvloop + WebSockets |
| PGx engine | C++23, pybind11, mmap, std::ranges::equal_range |
| Cloud compute | Google Cloud Run (gen2) |
| Data storage | Google Cloud Storage |
| AI platform | Google Vertex AI |
| Frontend | Vanilla HTML5/JS, Web Audio API (PCM16 @ 16kHz) |
| IaC | Bash + gcloud CLI (setup_iac.sh) |
pharmashield/
├── app/
│ ├── api/router.py # WebSocket handler, Gemini Live session, tool calls
│ ├── core/config.py # Settings, system prompt, model config
│ ├── core/engine.py # PharmaShieldEngine singleton (Python ↔ C++ bridge)
│ └── main.py # FastAPI app, lifespan, health check
├── core/
│ ├── GeneticCore.cpp # C++23 sentinel engine (mmap, binary search, prefetch)
│ └── CMakeLists.txt # Build config (C++23, -O3, -march=native, LTO)
├── frontend/
│ ├── index.html # Telemetry UI
│ └── js/
│ ├── webrtc.js # AudioCapture (PCM16 @ 16kHz)
│ ├── socket.js # WebSocket client (PSSocket)
│ └── ui.js # UI logic, AudioPlayer (PCM16 → Web Audio API)
├── tools/
│ ├── data_transfo.py # ETL pipeline (PharmGKB + MIMIC-IV + VCF → CSV)
│ ├── builder.py # CSV → patients.bin binary compiler
│ └── synthetic_data_generator.py # Synthetic patient generator (no real data)
├── ARCHITECTURE.md # System diagram (Mermaid)
├── PROJECT_OVERVIEW.md # Product definition and workflow
├── Dockerfile # Multi-stage build (C++ compiler + Python runtime)
├── setup_iac.sh # Full GCP infrastructure provisioning (IaC)
└── Pipfile # Python dependencies
Apache 2.0 — see LICENSE.