EcoGrid / server /ecogrid_environment.py
Loosebag's picture
fix: stabilize deployment, action safety, and benchmark reproducibility
30bdd62
Raw
History Blame Contribute Delete
2.71 kB
from typing import Any, Dict
from uuid import uuid4
from pydantic import BaseModel, Field
from openenv.core.env_server.interfaces import Environment
from openenv.core.env_server.types import State
from env.action_utils import coerce_grid_action
from env.environment import EcoGridEnv
from models.schemas import GridAction, GridState
class ServerObservation(BaseModel):
observation: GridState
reward: float
done: bool
info: Dict[str, Any] = Field(default_factory=dict)
class ServerEcoGridEnv(Environment):
"""
Wrapper around EcoGridEnv to strictly satisfy openenv.core.Environment
interfaces without breaking the local UI/CLI scripts.
"""
SUPPORTS_CONCURRENT_SESSIONS: bool = True
def __init__(self):
self._env = EcoGridEnv()
self._oe_state = State(episode_id=str(uuid4()), step_count=0)
self._current_task = "easy"
def reset(self) -> ServerObservation:
self._oe_state = State(episode_id=str(uuid4()), step_count=0)
# Default reset. The specific task is usually set prior, or defaults to easy.
initial_state = self._env.reset(task=self._current_task, seed=42)
return ServerObservation(
observation=initial_state,
reward=0.0,
done=False,
info={}
)
def step(self, action: GridAction | dict) -> ServerObservation:
self._oe_state.step_count += 1
safe_default = GridAction(
renewable_ratio=0.5,
fossil_ratio=0.5,
battery_action=0.0,
)
parsed_action, action_warning = coerce_grid_action(
action_like=action,
default_action=safe_default,
)
try:
result = self._env.step(parsed_action)
except Exception as exc:
# Never crash the API on malformed/edge payloads.
fallback_state = self._env.state() if not self._env.is_done else self._env.reset()
return ServerObservation(
observation=fallback_state,
reward=0.001,
done=self._env.is_done,
info={
"error": f"step_failed:{type(exc).__name__}",
"detail": str(exc),
"action_warning": action_warning or "step_exception_fallback",
},
)
info = dict(result.info)
if action_warning:
info["action_warning"] = action_warning
return ServerObservation(
observation=result.observation,
reward=result.reward,
done=result.done,
info=info,
)
@property
def state(self) -> State:
return self._oe_state