| from __future__ import annotations |
|
|
| import json |
| from typing import Any |
|
|
| from openenv.core.env_server import Action, Observation, State |
| from pydantic import ConfigDict, Field, field_validator |
|
|
|
|
| class AgenticTrafficAction(Action): |
| model_config = ConfigDict( |
| extra="forbid", |
| validate_assignment=True, |
| arbitrary_types_allowed=True, |
| validate_default=True, |
| ) |
|
|
| use_llm: bool = Field( |
| default=False, |
| description=( |
| "When true, use the bundled district LLM adapter to generate district_actions " |
| "for districts not explicitly provided." |
| ), |
| ) |
| district_actions: dict[str, Any] = Field( |
| default="{}", |
| description=( |
| "JSON object keyed by district_id. Use {} for a no-op step, or provide " |
| 'entries like {"d_00":{"strategy":"hold","phase_bias":"NS","duration_steps":10}}.' |
| ), |
| json_schema_extra={ |
| "type": "string", |
| "maxLength": 4000, |
| "default": "{}", |
| }, |
| ) |
| llm_max_new_tokens: int = Field( |
| default=128, |
| ge=16, |
| le=512, |
| description="Maximum new tokens to generate per district when use_llm=true.", |
| ) |
|
|
| @field_validator("district_actions", mode="before") |
| @classmethod |
| def parse_district_actions(cls, value: Any) -> dict[str, Any]: |
| if value is None or value == "": |
| return {} |
| if isinstance(value, str): |
| parsed = json.loads(value) |
| if not isinstance(parsed, dict): |
| raise ValueError("district_actions must decode to a JSON object.") |
| return parsed |
| if isinstance(value, dict): |
| return value |
| raise ValueError("district_actions must be a dict or JSON object string.") |
|
|
|
|
| class AgenticTrafficObservation(Observation): |
| city_id: str | None = None |
| scenario_name: str | None = None |
| decision_step: int = 0 |
| sim_time: int = 0 |
| district_summaries: dict[str, Any] = Field(default_factory=dict) |
|
|
|
|
| class AgenticTrafficState(State): |
| scenario: dict[str, Any] | None = None |
| controller: dict[str, Any] = Field(default_factory=dict) |
| district_decision_interval: int = 0 |
| district_summaries: dict[str, Any] = Field(default_factory=dict) |
| llm: dict[str, Any] = Field(default_factory=dict) |
| last_info: dict[str, Any] = Field(default_factory=dict) |
|
|