Skip to content

riyaneel/PharmaShield

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PharmaShield

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 ChallengeLive Agents category.


Table of Contents


How It Works

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_range on a sorted binary file.

Architecture

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)  │
                                 └─────────────────────────┘

Prerequisites

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 login configured 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-storage

Quick Start (Local)

1. Clone the repository

git clone https://github.com/riyaneel/pharmashield.git
cd pharmashield

2. Install Python dependencies

python -m venv .venv && source .venv/bin/activate
pip install pandas pybind11 fastapi uvicorn uvloop httptools \
            websockets google-cloud-storage google-genai

3. Generate the synthetic patient dataset

No 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.bin

Expected 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

4. Build the C++23 Sentinel Core

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 OK

5. Run the backend

export 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 uvloop

Expected 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"}

6. Open the frontend

Open frontend/index.html in your browser (no build step required — vanilla HTML/JS).

The frontend auto-detects localhost and connects to ws://127.0.0.1:8080/api/v1/stream.


Deploy to GCP

The entire infrastructure is provisioned by a single script.

Prerequisites

gcloud auth login
gcloud config set project your-project-id

One-command deploy

chmod +x setup_iac.sh
bash setup_iac.sh

This script does the following in order:

  1. Enables APIs — Cloud Run, Cloud Build, Cloud Storage, Vertex AI
  2. Creates a dedicated service account (pharmashield-runner) with minimum required permissions (Storage objectViewer + Vertex AI user)
  3. Provisions the GCS bucket for patients.bin
  4. Triggers Cloud Build to build and push the Docker image
  5. Deploys to Cloud Run (gen2, min 1 instance, 2Gi RAM, --no-cpu-throttling for C++ performance)

Upload the patient data

# 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.

Verify the deployment

SERVICE_URL=$(gcloud run services describe pharmashield-core \
  --region=us-central1 --format='value(status.url)')

curl ${SERVICE_URL}/health
# → {"status":"healthy","engine":"generic_core",...}

Environment variables on Cloud Run

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 command

Data Sources

Why patients.bin is not in this repository

The 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.

Synthetic data for testing and judging

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.bin

No real patient data, no PII, fully reproducible.


How to Demo

Recommended demo scenario for judges

This scenario is guaranteed to trigger a pharmacogenomic alert with the synthetic dataset.

Setup:

  1. Start the backend (local or Cloud Run)
  2. Open frontend/index.html
  3. Click the microphone button to enable ambient listening
  4. 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:

  1. Gemini extracts patient_id=99999001 and drug=codeine from the audio
  2. The C++ engine is called — lookup completes in ~40ns
  3. Patient 99999001 is a CYP2D6 Ultra-Rapid Metabolizer — codeine is converted to morphine at 4× the normal rate → fatal respiratory depression risk
  4. The Patient ID and Drug fields are pre-filled automatically in the UI
  5. 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."
  6. 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.

Keystroke prefetching demo

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

Known Limitations

Data

  • The patients.bin file 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.

Clinical scope

  • 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.py but 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.py but not yet connected to the binary format.

Infrastructure

  • The current deployment uses Cloud Run with --min-instances 1 to 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_SECRET is currently passed as an environment variable. Production deployments should use Google Secret Manager (scaffold provided in setup_iac.sh, commented).

Tech Stack

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)

Project Structure

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

License

Apache 2.0 — see LICENSE.

About

Zero-latency pharmacogenomic multimodal live agent

Topics

Resources

License

Stars

Watchers

Forks

Contributors