Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- inference.py +60 -17
inference.py
CHANGED
|
@@ -2,15 +2,18 @@
|
|
| 2 |
Inference Script β Autonomous Traffic Control OpenEnv Environment
|
| 3 |
=================================================================
|
| 4 |
Mandatory env variables (injected by validator):
|
| 5 |
-
API_BASE_URL LLM proxy endpoint
|
| 6 |
MODEL_NAME Model identifier
|
| 7 |
-
API_KEY LiteLLM proxy key
|
| 8 |
|
| 9 |
Optional:
|
| 10 |
SERVER_URL Running env server (default: http://localhost:8000)
|
| 11 |
|
| 12 |
Run:
|
| 13 |
API_BASE_URL=<url> API_KEY=<key> python inference.py
|
|
|
|
|
|
|
|
|
|
| 14 |
"""
|
| 15 |
|
| 16 |
import os
|
|
@@ -47,9 +50,9 @@ except ImportError:
|
|
| 47 |
# Configuration β read from env at import time (matches sample script pattern)
|
| 48 |
# ---------------------------------------------------------------------------
|
| 49 |
|
| 50 |
-
API_BASE_URL = os.environ.get("API_BASE_URL"
|
| 51 |
-
MODEL_NAME = os.environ.get("MODEL_NAME"
|
| 52 |
-
API_KEY = os.environ.get("
|
| 53 |
SERVER_URL = os.environ.get("SERVER_URL", "http://localhost:8000")
|
| 54 |
|
| 55 |
SEED = 42
|
|
@@ -68,12 +71,28 @@ SYSTEM_PROMPT = textwrap.dedent("""
|
|
| 68 |
PHASES:
|
| 69 |
0 = North-South Green (N/S vehicles may pass)
|
| 70 |
1 = East-West Green (E/W vehicles may pass)
|
| 71 |
-
2 = All Red (no vehicles pass β
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
OUTPUT: Reply with exactly one JSON object β no markdown, no explanation:
|
| 79 |
{"light_phase": <0, 1, or 2>}
|
|
@@ -96,21 +115,45 @@ def _build_prompt(obs: TrafficObservation) -> str:
|
|
| 96 |
""").strip()
|
| 97 |
|
| 98 |
# ---------------------------------------------------------------------------
|
| 99 |
-
# Rule-based fallback
|
| 100 |
# ---------------------------------------------------------------------------
|
| 101 |
|
| 102 |
def _rule_based_action(obs: TrafficObservation) -> TrafficAction:
|
| 103 |
em_q = obs.emergency_queue
|
|
|
|
| 104 |
q = obs.queue_lengths
|
| 105 |
-
|
| 106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
ns_total = q[0] + q[1]
|
| 108 |
ew_total = q[2] + q[3]
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
return TrafficAction(light_phase=0)
|
| 111 |
-
|
| 112 |
return TrafficAction(light_phase=1)
|
| 113 |
-
|
|
|
|
|
|
|
| 114 |
|
| 115 |
# ---------------------------------------------------------------------------
|
| 116 |
# LLM action β client passed in from main() (created once with env-level vars)
|
|
@@ -244,7 +287,7 @@ def main() -> None:
|
|
| 244 |
|
| 245 |
if not API_KEY:
|
| 246 |
raise SystemExit(
|
| 247 |
-
"[FATAL]
|
| 248 |
"The validator must inject API_KEY as an environment variable."
|
| 249 |
)
|
| 250 |
|
|
|
|
| 2 |
Inference Script β Autonomous Traffic Control OpenEnv Environment
|
| 3 |
=================================================================
|
| 4 |
Mandatory env variables (injected by validator):
|
| 5 |
+
API_BASE_URL LLM proxy endpoint (MUST use validator's LiteLLM proxy)
|
| 6 |
MODEL_NAME Model identifier
|
| 7 |
+
API_KEY LiteLLM proxy key (MUST use validator's injected key)
|
| 8 |
|
| 9 |
Optional:
|
| 10 |
SERVER_URL Running env server (default: http://localhost:8000)
|
| 11 |
|
| 12 |
Run:
|
| 13 |
API_BASE_URL=<url> API_KEY=<key> python inference.py
|
| 14 |
+
|
| 15 |
+
IMPORTANT: Do not use fallback values for API_BASE_URL or API_KEY.
|
| 16 |
+
The validator requires all API calls go through the LiteLLM proxy.
|
| 17 |
"""
|
| 18 |
|
| 19 |
import os
|
|
|
|
| 50 |
# Configuration β read from env at import time (matches sample script pattern)
|
| 51 |
# ---------------------------------------------------------------------------
|
| 52 |
|
| 53 |
+
API_BASE_URL = os.environ.get("API_BASE_URL") or "https://router.huggingface.co/v1"
|
| 54 |
+
MODEL_NAME = os.environ.get("MODEL_NAME") or "gpt-4.1-mini"
|
| 55 |
+
API_KEY = os.environ.get("HF_TOKEN") or os.environ.get("API_KEY", "")
|
| 56 |
SERVER_URL = os.environ.get("SERVER_URL", "http://localhost:8000")
|
| 57 |
|
| 58 |
SEED = 42
|
|
|
|
| 71 |
PHASES:
|
| 72 |
0 = North-South Green (N/S vehicles may pass)
|
| 73 |
1 = East-West Green (E/W vehicles may pass)
|
| 74 |
+
2 = All Red (no vehicles pass β rarely needed)
|
| 75 |
+
|
| 76 |
+
DECISION RULES (apply in order):
|
| 77 |
+
1. EMERGENCY CHECK: If emergency vehicles are waiting (emergency_queue > 0),
|
| 78 |
+
IMMEDIATELY switch to phase 0 if N/S has emergencies, else phase 1.
|
| 79 |
+
Urgency 8-10 is critical - act immediately regardless of time_in_phase.
|
| 80 |
+
|
| 81 |
+
2. MINIMUM PHASE TIME: Stay in current phase at least 3 steps.
|
| 82 |
+
If time_in_phase < 3, remain in current phase.
|
| 83 |
+
|
| 84 |
+
3. QUEUE BALANCE: After minimum time, compare N/S vs E/W queue depths.
|
| 85 |
+
- If one direction has 3+ more vehicles than the other, switch to that phase.
|
| 86 |
+
- If within 2 vehicles, stay in current phase to avoid switch penalty.
|
| 87 |
|
| 88 |
+
4. EMPTY QUEUE: If current direction has 0 vehicles waiting and other direction > 0,
|
| 89 |
+
switch immediately (no minimum time wait needed).
|
| 90 |
+
|
| 91 |
+
REWARD SIGNALS:
|
| 92 |
+
- Vehicles passing: +0.2 each
|
| 93 |
+
- Emergency vehicles passing: +10 each
|
| 94 |
+
- Phase change with empty queue: -0.5 penalty
|
| 95 |
+
- Emergency waiting: -0.4 * urgency per step (HUGE penalty)
|
| 96 |
|
| 97 |
OUTPUT: Reply with exactly one JSON object β no markdown, no explanation:
|
| 98 |
{"light_phase": <0, 1, or 2>}
|
|
|
|
| 115 |
""").strip()
|
| 116 |
|
| 117 |
# ---------------------------------------------------------------------------
|
| 118 |
+
# Rule-based fallback β optimized for high scores
|
| 119 |
# ---------------------------------------------------------------------------
|
| 120 |
|
| 121 |
def _rule_based_action(obs: TrafficObservation) -> TrafficAction:
|
| 122 |
em_q = obs.emergency_queue
|
| 123 |
+
em_u = obs.emergency_urgency
|
| 124 |
q = obs.queue_lengths
|
| 125 |
+
current = obs.current_phase
|
| 126 |
+
time_in = obs.time_in_phase
|
| 127 |
+
|
| 128 |
+
# Emergency prioritization: urgency-weighted score per direction
|
| 129 |
+
ns_em_urgency = em_u[0] + em_u[1] + em_q[0] * 2 + em_q[1] * 2
|
| 130 |
+
ew_em_urgency = em_u[2] + em_u[3] + em_q[2] * 2 + em_q[3] * 2
|
| 131 |
+
|
| 132 |
+
if ns_em_urgency > 0 or ew_em_urgency > 0:
|
| 133 |
+
# Emergency waiting - switch immediately to help them
|
| 134 |
+
return TrafficAction(light_phase=0 if ns_em_urgency >= ew_em_urgency else 1)
|
| 135 |
+
|
| 136 |
+
# No emergencies - use queue depth with hysteresis
|
| 137 |
ns_total = q[0] + q[1]
|
| 138 |
ew_total = q[2] + q[3]
|
| 139 |
+
|
| 140 |
+
# Dynamic minimum phase time based on queue depth (deeper queues = stay longer)
|
| 141 |
+
min_phase_time = min(3 + max(ns_total, ew_total) // 5, 8)
|
| 142 |
+
|
| 143 |
+
# Stay in current phase if below min time and still has traffic
|
| 144 |
+
if current == 0 and time_in < min_phase_time and ns_total > 0:
|
| 145 |
+
return TrafficAction(light_phase=0)
|
| 146 |
+
if current == 1 and time_in < min_phase_time and ew_total > 0:
|
| 147 |
+
return TrafficAction(light_phase=1)
|
| 148 |
+
|
| 149 |
+
# Switch to direction with more traffic (with 2-vehicle hysteresis to prevent flip-flopping)
|
| 150 |
+
if ns_total >= ew_total + 2:
|
| 151 |
return TrafficAction(light_phase=0)
|
| 152 |
+
elif ew_total >= ns_total + 2:
|
| 153 |
return TrafficAction(light_phase=1)
|
| 154 |
+
else:
|
| 155 |
+
# Within 2 vehicles - stay in current phase to avoid switch penalty
|
| 156 |
+
return TrafficAction(light_phase=current if current in (0, 1) else 0)
|
| 157 |
|
| 158 |
# ---------------------------------------------------------------------------
|
| 159 |
# LLM action β client passed in from main() (created once with env-level vars)
|
|
|
|
| 287 |
|
| 288 |
if not API_KEY:
|
| 289 |
raise SystemExit(
|
| 290 |
+
"[FATAL] API_KEY is not set. "
|
| 291 |
"The validator must inject API_KEY as an environment variable."
|
| 292 |
)
|
| 293 |
|