Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- README.md +117 -147
- inference.py +1 -1
- server/PharmaDDIEnv_environment.py +1 -1
README.md
CHANGED
|
@@ -1,195 +1,165 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
emoji: 💊
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: purple
|
| 6 |
sdk: docker
|
| 7 |
-
|
| 8 |
-
app_port: 8000
|
| 9 |
base_path: /web
|
| 10 |
-
tags:
|
| 11 |
-
- openenv
|
| 12 |
---
|
| 13 |
|
| 14 |
-
# PharmaDDI
|
| 15 |
|
| 16 |
-
|
| 17 |
|
| 18 |
-
|
| 19 |
|
| 20 |
-
|
| 21 |
|
| 22 |
-
|
| 23 |
|
| 24 |
-
|
| 25 |
-
from PharmaDDIEnv import PharmaDDIAction, PharmaDDIEnv, InteractionReport
|
| 26 |
-
|
| 27 |
-
# Create environment from Docker image
|
| 28 |
-
env = PharmaDDIEnv.from_docker_image("PharmaDDIEnv-env:latest")
|
| 29 |
-
|
| 30 |
-
try:
|
| 31 |
-
result = env.reset()
|
| 32 |
-
print(f"Patient: {result.observation.patient_id}")
|
| 33 |
-
print(f"Medications: {[m.name for m in result.observation.medications]}")
|
| 34 |
-
|
| 35 |
-
# Submit interaction analysis
|
| 36 |
-
action = PharmaDDIAction(interactions_found=[
|
| 37 |
-
InteractionReport(
|
| 38 |
-
drug_a="warfarin", drug_b="aspirin",
|
| 39 |
-
severity="major",
|
| 40 |
-
clinical_effect="Increased bleeding risk",
|
| 41 |
-
recommendation="monitor"
|
| 42 |
-
)
|
| 43 |
-
])
|
| 44 |
-
result = env.step(action)
|
| 45 |
-
print(f"Score: {result.observation.score}")
|
| 46 |
-
print(f"Feedback: {result.observation.feedback}")
|
| 47 |
-
finally:
|
| 48 |
-
env.close()
|
| 49 |
-
```
|
| 50 |
|
| 51 |
-
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
| 54 |
-
# Build Docker image
|
| 55 |
-
docker build -t PharmaDDIEnv-env:latest -f server/Dockerfile .
|
| 56 |
|
| 57 |
-
|
| 58 |
-
uvicorn server.app:app --reload --host 0.0.0.0 --port 8000
|
| 59 |
|
| 60 |
-
#
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
```
|
| 63 |
|
|
|
|
|
|
|
| 64 |
## Action Space
|
| 65 |
|
| 66 |
-
|
| 67 |
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
-
|
| 73 |
|
| 74 |
-
|
| 75 |
-
|-------|------|--------|
|
| 76 |
-
| `drug_a` | `str` | Drug name (lowercase) |
|
| 77 |
-
| `drug_b` | `str` | Drug name (lowercase) |
|
| 78 |
-
| `severity` | `str` | `minor` \| `moderate` \| `major` \| `contraindicated` |
|
| 79 |
-
| `clinical_effect` | `str` | Description of the interaction mechanism |
|
| 80 |
-
| `recommendation` | `str` | `monitor` \| `adjust_dose` \| `substitute` \| `discontinue` |
|
| 81 |
|
| 82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
| Field | Type | Description |
|
| 87 |
-
|-------|------|-------------|
|
| 88 |
-
| `task_name` | `str` | `easy_pair_check` \| `medium_multi_drug` \| `hard_polypharmacy` |
|
| 89 |
-
| `task_difficulty` | `str` | `easy` \| `medium` \| `hard` |
|
| 90 |
-
| `patient_id` | `str` | Unique patient identifier |
|
| 91 |
-
| `patient_age` | `int` | Patient age in years |
|
| 92 |
-
| `patient_conditions` | `List[str]` | Medical conditions |
|
| 93 |
-
| `medications` | `List[MedicationInfo]` | Current medication list |
|
| 94 |
-
| `num_medications` | `int` | Number of medications |
|
| 95 |
-
| `instructions` | `str` | Task-specific instructions |
|
| 96 |
-
| `feedback` | `str` | Grading feedback after submission |
|
| 97 |
-
| `score` | `float` | Score achieved (0.01.0) |
|
| 98 |
-
| `total_interactions` | `int` | Hint for easy mode only |
|
| 99 |
-
|
| 100 |
-
## Tasks
|
| 101 |
-
|
| 102 |
-
### Task 1: Easy - Pair Check (2 drugs)
|
| 103 |
-
- Given 2 medications, identify if a DDI exists
|
| 104 |
-
- Classify severity level
|
| 105 |
-
- **Scoring**: 60% pair identification + 40% severity false positive penalty
|
| 106 |
-
|
| 107 |
-
### Task 2: Medium - Multi-Drug Review (5 drugs)
|
| 108 |
-
- Review 5 concurrent medications
|
| 109 |
-
- Find ALL interacting pairs and classify severity
|
| 110 |
-
- **Scoring**: 40% pairs + 35% severity + 10% recommendations + 15% precision critical miss penalty
|
| 111 |
-
|
| 112 |
-
### Task 3: Hard - Polypharmacy (8 drugs)
|
| 113 |
-
- Complex elderly patient with 8 medications
|
| 114 |
-
- Find all interactions, classify severity, AND recommend clinical actions
|
| 115 |
-
- **Scoring**: 30% pairs + 25% severity + 25% recommendations + 10% precision + 10% completeness critical miss penalty
|
| 116 |
|
| 117 |
## Reward Function
|
| 118 |
|
| 119 |
-
|
| 120 |
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
- **False positive penalty**: Deduction per hallucinated interaction
|
| 125 |
-
- **Critical miss penalty**: Extra penalty for missing major/contraindicated interactions
|
| 126 |
|
| 127 |
-
|
| 128 |
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
- CNS/Psychiatric (fluoxetine, sertraline, diazepam, tramadol, lithium, etc.)
|
| 132 |
-
- Antibiotics (ciprofloxacin, metronidazole, erythromycin, rifampin, etc.)
|
| 133 |
-
- Analgesics (ibuprofen, naproxen, acetaminophen)
|
| 134 |
-
- Diabetes (metformin, glipizide)
|
| 135 |
-
- Other (omeprazole, levothyroxine, spironolactone)
|
| 136 |
|
| 137 |
-
|
| 138 |
|
| 139 |
-
##
|
| 140 |
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
python inference.py
|
| 146 |
-
```
|
| 147 |
|
| 148 |
-
|
| 149 |
|
| 150 |
-
|
| 151 |
-
|------|---------------|------------|
|
| 152 |
-
| `easy_pair_check` | ~0.851.0 | Easy |
|
| 153 |
-
| `medium_multi_drug` | ~0.550.75 | Medium |
|
| 154 |
-
| `hard_polypharmacy` | ~0.350.55 | Hard |
|
| 155 |
|
| 156 |
-
##
|
| 157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
```
|
| 159 |
-
PharmaDDIEnv/
|
| 160 |
-
-- inference.py # Baseline inference script
|
| 161 |
-
-- openenv.yaml # OpenEnv manifest with 3 tasks
|
| 162 |
-
-- pyproject.toml # Project metadata & dependencies
|
| 163 |
-
-- README.md # This file
|
| 164 |
-
-- models.py # Action/Observation Pydantic models
|
| 165 |
-
-- client.py # PharmaDDIEnv client
|
| 166 |
-
-- __init__.py # Module exports
|
| 167 |
-
-- server/
|
| 168 |
-
-- drug_data.py # Drug & interaction knowledge base
|
| 169 |
-
-- PharmaDDIEnv_environment.py # Core environment + grading logic
|
| 170 |
-
-- app.py # FastAPI application
|
| 171 |
-
-- Dockerfile # Container image definition
|
| 172 |
-
-- requirements.txt # Server dependencies
|
| 173 |
-
```
|
| 174 |
|
| 175 |
-
|
|
|
|
|
|
|
| 176 |
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
5. **Deploy**: `openenv push`
|
| 182 |
|
| 183 |
-
|
|
|
|
|
|
|
| 184 |
|
| 185 |
```bash
|
| 186 |
openenv push
|
| 187 |
-
# or with options:
|
| 188 |
-
openenv push --repo-id your-username/PharmaDDIEnv --private
|
| 189 |
```
|
| 190 |
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: PharmaDDIEnv
|
| 3 |
emoji: 💊
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: purple
|
| 6 |
sdk: docker
|
| 7 |
+
app_port: 7860
|
|
|
|
| 8 |
base_path: /web
|
|
|
|
|
|
|
| 9 |
---
|
| 10 |
|
| 11 |
+
# PharmaDDI: Clinical Drug-Drug Interaction RL Environment
|
| 12 |
|
| 13 |
+
### Empowering AI Agents to Prevent Adverse Drug Events in Complex Polypharmacy
|
| 14 |
|
| 15 |
+
---
|
| 16 |
|
| 17 |
+
## Motivation & Real-World Utility
|
| 18 |
|
| 19 |
+
Drug-Drug Interactions (DDIs) are a major cause of preventable medical errors, hospitalizations, and mortality worldwide. As patients age and develop multiple chronic conditions, the complexity of their medication regimens (polypharmacy) increases significantly.
|
| 20 |
|
| 21 |
+
In a typical clinical workflow, a pharmacist must:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
+
1. Identify all interacting drug pairs within a list of medications
|
| 24 |
+
2. Assess the clinical severity of each interaction
|
| 25 |
+
3. Recommend appropriate actions to reduce patient risk while maintaining treatment effectiveness
|
| 26 |
|
| 27 |
+
PharmaDDI provides a clinically grounded reinforcement learning (RL) environment to benchmark AI agents on these critical healthcare decision-making tasks.
|
|
|
|
|
|
|
| 28 |
|
| 29 |
+
---
|
|
|
|
| 30 |
|
| 31 |
+
## Environment Overview
|
| 32 |
+
|
| 33 |
+
The PharmaDDI environment provides an agent with a structured patient profile that includes:
|
| 34 |
+
|
| 35 |
+
* Demographics (age and medical conditions)
|
| 36 |
+
* Medication list (drug name, class, dosage, and frequency)
|
| 37 |
+
|
| 38 |
+
The goal of the agent is to detect and report all clinically significant drug-drug interactions, simulating the reasoning process of a clinical pharmacist.
|
| 39 |
+
|
| 40 |
+
---
|
| 41 |
+
|
| 42 |
+
## Observation Space
|
| 43 |
+
|
| 44 |
+
The agent receives a structured observation object:
|
| 45 |
+
|
| 46 |
+
```python
|
| 47 |
+
class MedicationInfo(BaseModel):
|
| 48 |
+
name: str
|
| 49 |
+
therapeutic_class: str
|
| 50 |
+
common_dose: str
|
| 51 |
+
frequency: str
|
| 52 |
+
|
| 53 |
+
class PharmaDDIObservation(Observation):
|
| 54 |
+
patient_id: str
|
| 55 |
+
patient_age: int
|
| 56 |
+
patient_conditions: List[str]
|
| 57 |
+
medications: List[MedicationInfo]
|
| 58 |
+
num_medications: int
|
| 59 |
+
instructions: str
|
| 60 |
```
|
| 61 |
|
| 62 |
+
---
|
| 63 |
+
|
| 64 |
## Action Space
|
| 65 |
|
| 66 |
+
The agent returns detected interactions in the following format:
|
| 67 |
|
| 68 |
+
```python
|
| 69 |
+
class InteractionReport(BaseModel):
|
| 70 |
+
drug_a: str
|
| 71 |
+
drug_b: str
|
| 72 |
+
severity: str # minor | moderate | major | contraindicated
|
| 73 |
+
clinical_effect: str
|
| 74 |
+
recommendation: str # monitor | adjust_dose | substitute | discontinue
|
| 75 |
+
|
| 76 |
+
class PharmaDDIAction(Action):
|
| 77 |
+
interactions_found: List[InteractionReport]
|
| 78 |
+
```
|
| 79 |
+
|
| 80 |
+
---
|
| 81 |
|
| 82 |
+
## Tasks & Evaluation
|
| 83 |
|
| 84 |
+
The environment includes three levels of difficulty:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
|
| 86 |
+
| Task ID | Medications | Objective | Difficulty |
|
| 87 |
+
| ----------------- | ----------- | ----------------------------------- | ---------- |
|
| 88 |
+
| easy_pair_check | 2 | Detect interaction for a given pair | Easy |
|
| 89 |
+
| medium_multi_drug | 5 | Identify all interacting pairs | Medium |
|
| 90 |
+
| hard_polypharmacy | 8 | Handle complex multi-drug cases | Hard |
|
| 91 |
|
| 92 |
+
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
|
| 94 |
## Reward Function
|
| 95 |
|
| 96 |
+
A weighted scoring system (0.0 to 1.0) evaluates agent performance:
|
| 97 |
|
| 98 |
+
* Identification Accuracy (30–60%)
|
| 99 |
+
* Severity Classification (25–40%)
|
| 100 |
+
* Recommendation Quality (10–25%)
|
|
|
|
|
|
|
| 101 |
|
| 102 |
+
Penalties include:
|
| 103 |
|
| 104 |
+
* False positives (incorrect interaction detection)
|
| 105 |
+
* Missing critical interactions (major or contraindicated)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
|
| 107 |
+
---
|
| 108 |
|
| 109 |
+
## Example Workflow
|
| 110 |
|
| 111 |
+
1. Input: Patient with multiple medications
|
| 112 |
+
2. Agent analyzes all possible drug pairs
|
| 113 |
+
3. Outputs structured interaction reports
|
| 114 |
+
4. Environment scores the response based on correctness
|
|
|
|
|
|
|
| 115 |
|
| 116 |
+
---
|
| 117 |
|
| 118 |
+
## Setup & Usage
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
|
| 120 |
+
### Local Development
|
| 121 |
|
| 122 |
+
```bash
|
| 123 |
+
pip install -e .
|
| 124 |
+
uvicorn server.app:app --host 0.0.0.0 --port 8000
|
| 125 |
+
python vall.py
|
| 126 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
|
| 128 |
+
---
|
| 129 |
+
|
| 130 |
+
### Docker Deployment
|
| 131 |
|
| 132 |
+
```bash
|
| 133 |
+
docker build -t pharmaddi-env:latest -f Dockerfile .
|
| 134 |
+
docker run -p 8000:8000 pharmaddi-env:latest
|
| 135 |
+
```
|
|
|
|
| 136 |
|
| 137 |
+
---
|
| 138 |
+
|
| 139 |
+
### Hugging Face Deployment
|
| 140 |
|
| 141 |
```bash
|
| 142 |
openenv push
|
|
|
|
|
|
|
| 143 |
```
|
| 144 |
|
| 145 |
+
---
|
| 146 |
+
|
| 147 |
+
## Project Structure
|
| 148 |
+
|
| 149 |
+
| File | Description |
|
| 150 |
+
| ---------------------------------- | ----------------------------------------- |
|
| 151 |
+
| server/PharmaDDIEnv_environment.py | Core RL environment and grading logic |
|
| 152 |
+
| server/drug_data.py | Drug database and interaction rules |
|
| 153 |
+
| models.py | Data schemas for observations and actions |
|
| 154 |
+
| inference.py | Baseline agent implementation |
|
| 155 |
+
| openenv.yaml | OpenEnv configuration |
|
| 156 |
+
|
| 157 |
+
---
|
| 158 |
+
|
| 159 |
+
## License & Acknowledgements
|
| 160 |
+
|
| 161 |
+
This project was developed for the Meta x Hugging Face OpenEnv Hackathon.
|
| 162 |
+
|
| 163 |
+
The drug interaction knowledge base is derived from publicly available clinical sources and research literature.
|
| 164 |
+
|
| 165 |
+
Disclaimer: This project is intended for research and educational purposes only. It should not be used for real clinical decision-making.
|
inference.py
CHANGED
|
@@ -21,7 +21,7 @@ MODEL_NAME = os.getenv("MODEL_NAME") or "Qwen/Qwen2.5-72B-Instruct"
|
|
| 21 |
ENV_BASE_URL = os.getenv("ENV_BASE_URL") or "http://localhost:8000"
|
| 22 |
|
| 23 |
BENCHMARK = "PharmaDDIEnv"
|
| 24 |
-
MAX_STEPS =
|
| 25 |
TEMPERATURE = 0.1
|
| 26 |
MAX_TOKENS = 500
|
| 27 |
|
|
|
|
| 21 |
ENV_BASE_URL = os.getenv("ENV_BASE_URL") or "http://localhost:8000"
|
| 22 |
|
| 23 |
BENCHMARK = "PharmaDDIEnv"
|
| 24 |
+
MAX_STEPS = 15
|
| 25 |
TEMPERATURE = 0.1
|
| 26 |
MAX_TOKENS = 500
|
| 27 |
|
server/PharmaDDIEnv_environment.py
CHANGED
|
@@ -284,7 +284,7 @@ class PharmaDDIEnvironment(Environment):
|
|
| 284 |
critical_penalty
|
| 285 |
)
|
| 286 |
|
| 287 |
-
final_score = min(max(raw_score, 0.
|
| 288 |
|
| 289 |
# Build summary feedback
|
| 290 |
summary = (
|
|
|
|
| 284 |
critical_penalty
|
| 285 |
)
|
| 286 |
|
| 287 |
+
final_score = min(max(raw_score, 0.01), 0.99)
|
| 288 |
|
| 289 |
# Build summary feedback
|
| 290 |
summary = (
|