Skip to main content

Multi-speaker spoken dialogue simulation framework for emergency department triage

Project description

TriageSim

TriageSim is an open-source Python framework for generating synthetic, multi-speaker spoken dialogues for emergency department (ED) triage. It produces paired structured EHR → dialogue data grounded in real clinical vignettes, enabling controlled evaluation of speech and language systems in healthcare.


Features

  • Nurse ↔ patient dialogue simulation via LLM agents (OpenRouter)
  • Two triage algorithms: ESI (Emergency Severity Index) and ATS (Australasian Triage Scale)
  • Persona-conditioned generation: diverse patient and nurse personas (ethnicity, experience, communication style, etc.)
  • Structured run artifacts: belief state, red-flag trace, per-turn triage reasoning
  • Pluggable LLM backends: any OpenRouter-compatible model (Claude, Gemini, GPT, etc.)
  • Optional audio rendering: XTTS-v2 voice cloning for multi-speaker TTS synthesis

Installation

pip install triagesim

With Redis state store:

pip install "triagesim[redis]"

With audio rendering (requires PyTorch):

pip install "triagesim[audio]"

Or install the latest development version directly from GitHub:

pip install "git+https://github.com/dipankarsrirag/triage-sim.git"

Configuration

Set your OpenRouter API key as an environment variable or in a .env file at your project root:

export OPENROUTER_API_KEY=sk-or-...
# .env
OPENROUTER_API_KEY=sk-or-...

Quick Start

from triagesim import TriageRunner, RunnerConfig
from triagesim.agents import OpenRouterLLM, NurseAgent, PatientAgent
from triagesim.core import NurseOutput, PatientOutput
from triagesim.personas import (
    load_patient_personas,
    load_nurse_personas,
    sample_patient_personas,
    sample_nurse_personas,
)

# Load personas from YAML files
patients = load_patient_personas("path/to/patient.yaml")
nurses = load_nurse_personas("path/to/nurse.yaml")

patient_persona = sample_patient_personas(patients, k=1, seed=42)[0]
nurse_persona = sample_nurse_personas(nurses, k=1, seed=42)[0]

# Ground-truth clinical vignette (NOT visible to agents)
ground_truth = {
    "chiefcomplaint": "Syncope",
    "vitals": {
        "temperature": 99.1,
        "heartrate": 112,
        "resprate": 26,
        "o2sat": 91,
        "sbp": 98,
    },
    "acuity": 2,
    "pain": 7,
}

# Instantiate LLM backends — one per agent, each typed to its output schema
model = "anthropic/claude-sonnet-4-5"
patient_llm = OpenRouterLLM(model_name=model, output_type=PatientOutput)
nurse_llm = OpenRouterLLM(model_name=model, output_type=NurseOutput)

# Instantiate agents
patient = PatientAgent(llm=patient_llm, persona=patient_persona)
nurse = NurseAgent(llm=nurse_llm, persona=nurse_persona, algorithm="esi")  # or "ats"

# Run
config = RunnerConfig(max_turns=20, store_backend="memory", seed=42)
runner = TriageRunner(
    nurse_agent=nurse,
    patient_agent=patient,
    ground_truth=ground_truth,
    config=config,
)
artifact = runner.run()

Persona Format

Personas are loaded from YAML files. Each file is a list of persona dicts.

Patient persona fields:

- age_group: adult
  gender: female
  ethnicity: Australian
  socioeconomic_status: middle
  language_proficiency: high
  recall_accuracy: high
  cognitive_state: clear
  trust_in_healthcare: high
  pain_expression: moderate
  reactivity_to_clinician_emotion: low
  emotion_regulation: stable
  disfluency_rate: low
  topic_drift: low
  response_length: medium

Nurse persona fields:

- gender: female
  ethnicity: Australian
  experience_level: senior
  risk_tolerance: low
  guideline_adherence: high
  communication_style: direct
  verbosity: medium
  emotional_expression: neutral

Run Artifact

runner.run() returns a dict:

Key Description
run_id Unique run identifier
ground_truth The input clinical vignette
history Full dialogue turn list (utterances + vitals + events)
trace Per-turn nurse cognition trace (actions + reasoning)
belief Final inferred belief state
red_flags Red flags logged during triage
state Final simulation state

Evaluation Metrics

from triagesim.utils import compute_all_metrics

metrics = compute_all_metrics(
    trace=artifact["trace"],
    belief=artifact["belief"],
    ground_truth=ground_truth,
)
# Returns: triage accuracy, belief coverage, red-flag P/R/F1, explanation stats

Using Redis State Store

config = RunnerConfig(
    max_turns=20,
    store_backend="redis",
    redis_db=0,
    seed=42,
)

Requires a running Redis instance and pip install "triagesim[redis]".


Custom LLM Backends

Subclass BaseLLM to use any model provider:

from triagesim.agents import BaseLLM

class MyLLM(BaseLLM):
    def generate(self, prompt, **kwargs):
        # call your model here
        ...

Citation

If you use TriageSim in your research, please cite:

@misc{srirag2026triagesimconversationalemergencytriage,
      title={TriageSim: A Conversational Emergency Triage Simulation Framework from Structured Electronic Health Records}, 
      author={Dipankar Srirag and Quoc Dung Nguyen and Aditya Joshi and Padmanesan Narasimhan and Salil Kanhere},
      year={2026},
      eprint={2603.10035},
      archivePrefix={arXiv},
      primaryClass={cs.CL},
      url={https://arxiv.org/abs/2603.10035}, 
}

License

MIT © Dipankar Srirag

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

triagesim-0.1.0.tar.gz (40.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

triagesim-0.1.0-py3-none-any.whl (44.5 kB view details)

Uploaded Python 3

File details

Details for the file triagesim-0.1.0.tar.gz.

File metadata

  • Download URL: triagesim-0.1.0.tar.gz
  • Upload date:
  • Size: 40.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for triagesim-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ecc565bf09a23242f6923e630407f4253ee56addff74408baae95d6643c7ea17
MD5 e41a3e66459998c3812321376061357a
BLAKE2b-256 fec6870ca6e995b128792cd3728cde3b4ab37ec784d5bc11381f7c7ae7703aac

See more details on using hashes here.

File details

Details for the file triagesim-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: triagesim-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 44.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for triagesim-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 54c1a7f6da96a69a5b8d98e58702d4779a40266b5802d10490a54c50580a5923
MD5 237cb4fe041db5b67fff99aebcd378b7
BLAKE2b-256 20945e09fd21fe034285a65720ef1c182818fe8fa674d2b5d0e287834b695b55

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page