OPENENV_RL_01 / app /tasks.py
Siddharaj Shirke
deploy: fresh snapshot to Hugging Face Space
3eae4cc
"""
tasks.py — Gov Workflow OpenEnv v2.0
Three deterministic benchmark tasks: easy, medium, hard.
"""
from app.models import (
TaskConfig, ServiceType, ScenarioMode, EventType, OfficerPool
)
TASK_EASY = TaskConfig(
task_id="district_backlog_easy",
display_name="District Backlog Clearance — Revenue Office",
difficulty="easy",
scenario_mode=ScenarioMode.NORMAL,
seed=42,
max_days=30,
enabled_services=[ServiceType.INCOME_CERTIFICATE],
arrival_rate_per_day={ServiceType.INCOME_CERTIFICATE: 12.0},
digital_intake_ratio=0.65,
initial_officer_pool=OfficerPool(
total_officers=8, available_officers=8,
allocated={ServiceType.INCOME_CERTIFICATE: 8},
),
missing_docs_probability_override={ServiceType.INCOME_CERTIFICATE: 0.20},
field_verification_probability_override={ServiceType.INCOME_CERTIFICATE: 0.15},
escalation_budget=5,
fairness_threshold=None,
event_probability=0.05,
allowed_events=[EventType.NO_EVENT],
)
TASK_MEDIUM = TaskConfig(
task_id="mixed_urgency_medium",
display_name="Mixed Urgency Backlog — Taluka Office",
difficulty="medium",
scenario_mode=ScenarioMode.NORMAL,
seed=123,
max_days=45,
enabled_services=[
ServiceType.INCOME_CERTIFICATE,
ServiceType.LAND_REGISTRATION,
ServiceType.PASSPORT,
ServiceType.DRIVING_LICENSE,
ServiceType.AADHAAR_CARD,
],
arrival_rate_per_day={
ServiceType.INCOME_CERTIFICATE: 8.0,
ServiceType.LAND_REGISTRATION: 4.0,
ServiceType.PASSPORT: 4.0,
ServiceType.DRIVING_LICENSE: 5.0,
ServiceType.AADHAAR_CARD: 6.0,
},
digital_intake_ratio=0.72,
initial_officer_pool=OfficerPool(
total_officers=14, available_officers=14,
allocated={
ServiceType.INCOME_CERTIFICATE: 4,
ServiceType.LAND_REGISTRATION: 2,
ServiceType.PASSPORT: 2,
ServiceType.DRIVING_LICENSE: 3,
ServiceType.AADHAAR_CARD: 3,
},
),
missing_docs_probability_override=None,
field_verification_probability_override=None,
escalation_budget=8,
fairness_threshold=None,
event_probability=0.15,
allowed_events=[EventType.DOCUMENT_REJECTION_SPIKE],
)
TASK_HARD = TaskConfig(
task_id="cross_department_hard",
display_name="Cross-Department Crisis — District Collectorate",
difficulty="hard",
scenario_mode=ScenarioMode.CRISIS,
seed=999,
max_days=60,
enabled_services=[
ServiceType.INCOME_CERTIFICATE,
ServiceType.LAND_REGISTRATION,
ServiceType.PASSPORT,
ServiceType.DRIVING_LICENSE,
ServiceType.AADHAAR_CARD,
],
arrival_rate_per_day={
ServiceType.INCOME_CERTIFICATE: 11.0,
ServiceType.LAND_REGISTRATION: 6.0,
ServiceType.PASSPORT: 6.0,
ServiceType.DRIVING_LICENSE: 7.0,
ServiceType.AADHAAR_CARD: 8.0,
},
digital_intake_ratio=0.80,
initial_officer_pool=OfficerPool(
total_officers=18, available_officers=18,
allocated={
ServiceType.INCOME_CERTIFICATE: 5,
ServiceType.LAND_REGISTRATION: 3,
ServiceType.PASSPORT: 3,
ServiceType.DRIVING_LICENSE: 3,
ServiceType.AADHAAR_CARD: 4,
},
),
missing_docs_probability_override=None,
field_verification_probability_override=None,
escalation_budget=10,
fairness_threshold=0.70,
event_probability=0.30,
allowed_events=[
EventType.SURGE_APPLICATIONS,
EventType.OFFICER_UNAVAILABLE,
EventType.DOCUMENT_REJECTION_SPIKE,
EventType.REVENUE_DB_DELAY,
EventType.SLA_ESCALATION_ORDER,
],
)
def make_extreme_variant(base_task: TaskConfig) -> TaskConfig:
variant = base_task.model_copy(deep=True)
variant.task_id = base_task.task_id + "_extreme"
variant.display_name = base_task.display_name + " [EXTREME]"
variant.scenario_mode = ScenarioMode.EXTREME_OVERLOAD
variant.event_probability = min(1.0, base_task.event_probability * 3.0)
variant.allowed_events = [e for e in EventType if e != EventType.NO_EVENT]
return variant
TASK_REGISTRY: dict = {
"district_backlog_easy": TASK_EASY,
"mixed_urgency_medium": TASK_MEDIUM,
"cross_department_hard": TASK_HARD,
"district_backlog_easy_extreme": make_extreme_variant(TASK_EASY),
}
def get_task(task_id: str) -> TaskConfig:
if task_id not in TASK_REGISTRY:
raise ValueError(f"Unknown task_id '{task_id}'. Available: {list(TASK_REGISTRY)}")
return TASK_REGISTRY[task_id]
def list_tasks() -> list:
return list(TASK_REGISTRY.keys())
def list_benchmark_tasks() -> list:
return ["district_backlog_easy", "mixed_urgency_medium", "cross_department_hard"]
TASKS = TASK_REGISTRY