optichain-env / client.py
Padmanava's picture
Upload folder using huggingface_hub
d5338b4 verified
Raw
History Blame Contribute Delete
3.16 kB
"""
OptiChain Inventory Environment Client.
Provides a synchronous HTTP client for interacting with the
OptiChain supply chain environment server.
"""
from __future__ import annotations
import requests
from models import SupplyChainAction, SupplyChainObservation, SupplyChainState
class OptiChainEnv:
"""
HTTP client for the OptiChain supply chain environment.
Wraps the REST endpoints exposed by server/app.py.
Example:
>>> client = OptiChainEnv(base_url="http://localhost:7860")
>>> obs = client.reset("task_01_easy")
>>> while not obs.done:
... action = SupplyChainAction(orders=[])
... obs = client.step(action)
>>> print(client.grader_score())
"""
def __init__(self, base_url: str = "http://localhost:7860") -> None:
self.base_url = base_url.rstrip("/")
self._session = requests.Session()
# ------------------------------------------------------------------
# Core OpenEnv endpoints
# ------------------------------------------------------------------
def reset(self, task_id: str = "task_01_easy") -> SupplyChainObservation:
"""Reset the environment and load a task. Returns initial observation."""
resp = self._session.post(
f"{self.base_url}/reset",
json={"task_id": task_id},
timeout=10,
)
resp.raise_for_status()
return SupplyChainObservation.model_validate(resp.json())
def step(self, action: SupplyChainAction) -> SupplyChainObservation:
"""Advance the simulation one day. Returns updated observation."""
resp = self._session.post(
f"{self.base_url}/step",
json=action.model_dump(),
timeout=10,
)
resp.raise_for_status()
data = resp.json()
return SupplyChainObservation.model_validate(data["observation"])
def state(self) -> SupplyChainState:
"""Return current episode metadata without advancing time."""
resp = self._session.get(f"{self.base_url}/state", timeout=10)
resp.raise_for_status()
return SupplyChainState.model_validate(resp.json())
def grader_score(self) -> float:
"""Return the normalised grader score in [0.0, 1.0]."""
resp = self._session.get(f"{self.base_url}/grader", timeout=10)
resp.raise_for_status()
return float(resp.json()["score"])
def health(self) -> bool:
"""Return True if the server is healthy."""
try:
resp = self._session.get(f"{self.base_url}/health", timeout=5)
return resp.status_code == 200 and resp.json().get("status") == "healthy"
except requests.RequestException:
return False
def close(self) -> None:
"""Close the underlying HTTP session."""
self._session.close()
# ------------------------------------------------------------------
# Context manager support
# ------------------------------------------------------------------
def __enter__(self) -> "OptiChainEnv":
return self
def __exit__(self, *_) -> None:
self.close()