13. Appointment Scheduling
Appointment scheduling involves matching patient needs with provider availability. AI assistance can match patients to appropriate visit types, suggest optimal times based on urgency, and handle routine scheduling requests.
Local AI enables scheduling interfaces that understand natural language requests, extract scheduling parameters, and interface with scheduling systems—all without patient data leaving the organization.
# appointment_scheduler.py
from dataclasses import dataclass
from typing import Optional, List
from datetime import datetime, timedelta
from enum import Enum
class VisitType(Enum):
ROUTINE = "routine"
URGENT = "urgent"
FOLLOW_UP = "follow_up"
WELLNESS = "wellness"
PROCEDURE = "procedure"
@dataclass
class SchedulingRequest:
patient_id: str
visit_type: VisitType
preferred_provider: Optional[str]
preferred_dates: List[datetime]
duration_minutes: int
reason: str
urgency_score: int # 1-5, higher = more urgent
class AppointmentScheduler:
"""AI-assisted appointment scheduling."""
def __init__(self, ollama_client, schedule_db_connection):
self.ollama = ollama_client
self.schedule_db = schedule_db_connection
def parse_scheduling_request(self, text_request: str) -> SchedulingRequest:
"""Parse natural language scheduling request."""
prompt = f"""Extract scheduling parameters from this request.
Request: {text_request}
Return JSON with:
- visit_type: routine/urgent/follow_up/wellness/procedure
- preferred_provider: provider name or null
- preferred_dates: array of dates mentioned (YYYY-MM-DD format)
- duration_minutes: estimated appointment length
- reason: brief reason for visit
- urgency_score: 1-5 where 5 is most urgent"""
response = self.ollama.generate(prompt)
try:
import json
data = json.loads(response)
return SchedulingRequest(
patient_id=data.get("patient_id", ""),
visit_type=VisitType(data.get("visit_type", "routine")),
preferred_provider=data.get("preferred_provider"),
preferred_dates=[datetime.fromisoformat(d) for d in data.get("preferred_dates", [])],
duration_minutes=data.get("duration_minutes", 30),
reason=data.get("reason", ""),
urgency_score=data.get("urgency_score", 3)
)
except:
return self._fallback_parse(text_request)
def suggest_appointments(self, request: SchedulingRequest) -> List[dict]:
"""Suggest optimal appointment slots."""
# Get available slots
available_slots = self._get_available_slots(
request.visit_type,
request.preferred_provider,
request.preferred_dates,
request.duration_minutes
)
# Rank by urgency and patient preference
ranked_slots = self._rank_slots(available_slots, request)
return ranked_slots
def confirm_appointment(self, slot_id: str, patient_id: str) -> dict:
"""Confirm and book appointment."""
# Verify slot still available
slot = self._get_slot(slot_id)
if not slot or slot["booked"]:
return {"success": False, "error": "Slot no longer available"}
# Book slot
confirmation = self._book_slot(slot_id, patient_id)
return {
"success": True,
"confirmation_number": confirmation["confirmation_id"],
"datetime": slot["datetime"],
"provider": slot["provider"],
"location": slot["location"],
"preparation_instructions": self._generate_prep_instructions(slot)
}
def handle_reschedule(self, current_appointment_id: str,
new_preferences: dict) -> dict:
"""Handle appointment rescheduling."""
current = self._get_appointment(current_appointment_id)
# Parse new preferences
new_request = SchedulingRequest(
patient_id=current["patient_id"],
visit_type=VisitType(current["visit_type"]),
preferred_provider=new_preferences.get("provider"),
preferred_dates=new_preferences.get("dates", []),
duration_minutes=current["duration"],
reason="Reschedule",
urgency_score=3
)
# Suggest new slots
suggestions = self.suggest_appointments(new_request)
return {
"current_appointment": current,
"suggested_slots": suggestions[:5]
}
def _get_available_slots(self, visit_type: VisitType,
provider: Optional[str],
preferred_dates: List[datetime],
duration: int) -> List[dict]:
"""Query schedule database for available slots."""
# Implementation queries schedule database
return []
def _rank_slots(self, slots: List[dict],
request: SchedulingRequest) -> List[dict]:
"""Rank appointment slots by fit with patient needs."""
prompt = f"""Rank these appointment slots for the patient.
Consider: urgency (higher urgency = sooner preference),
patient preference dates, provider preference.
Patient urgency score: {request.urgency_score}
Preferred dates: {[d.isoformat() for d in request.preferred_dates]}
Preferred provider: {request.preferred_provider}
Slots: {slots}
Return ranked list with ranking explanation."""
response = self.ollama.generate(prompt)
# Parse and return ranked slots
return slots
def _get_slot(self, slot_id: str) -> dict:
"""Get slot details from schedule database."""
pass
def _book_slot(self, slot_id: str, patient_id: str) -> dict:
"""Book appointment slot."""
pass
def _generate_prep_instructions(self, slot: dict) -> str:
"""Generate appointment preparation instructions."""
pass
Scheduling systems handle protected health information (appointment reason, provider seen). Local AI parsing keeps this data on-premises. Integration requires careful API design to prevent timing attacks that could infer health conditions from scheduling patterns.
Design a scheduling conversation flow that handles: initial booking, rescheduling, cancellation, and waitlist management. Implement the natural language parsing component and test with 20 varied scheduling requests.