cace-env / cace_env /client.py
Sunnycodes3114's picture
Upload folder using huggingface_hub
7e24fa5 verified
Raw
History Blame Contribute Delete
3.87 kB
"""
cace_env/client.py
CACEEnvClient — typed async/sync client for the CACE environment.
Inherits from openenv.core.EnvClient.
Usage (async):
async with CACEEnvClient(base_url="ws://localhost:7860") as env:
result = await env.reset()
result = await env.step(CACEAction(action_int=0))
Usage (sync):
with CACEEnvClient(base_url="ws://localhost:7860").sync() as env:
result = env.reset()
result = env.step(CACEAction(action_int=0))
Usage (from Docker):
env = await CACEEnvClient.from_docker_image("cace-env:latest")
async with env:
result = await env.reset()
Usage (from HF Space):
env = await CACEEnvClient.from_env("YOUR_USERNAME/cace-env")
async with env:
result = await env.reset()
"""
from typing import Any, Dict, Optional
from openenv.core.env_client import EnvClient
from cace_env.models import CACEAction, CACEObservation, CACEState
class CACEEnvClient(EnvClient[CACEAction, CACEObservation, CACEState]):
"""
Typed async client for the Cultural Context Arbitration Environment.
Implements the two abstract parse methods required by EnvClient:
_parse_result(payload) → StepResult[CACEObservation]
_parse_state(payload) → CACEState
"""
def _parse_result(self, payload: Dict[str, Any]):
"""Parse server step/reset response into StepResult[CACEObservation]."""
from openenv.core.env_client import StepResult
obs_data = payload.get("observation", payload)
if isinstance(obs_data, str):
obs = CACEObservation(
observation=obs_data,
case_id=payload.get("case_id", "unknown"),
language=payload.get("language", "Unknown"),
region=payload.get("region", "Unknown"),
complexity=payload.get("complexity", "medium"),
done=payload.get("done", False),
reward=payload.get("reward", None),
)
else:
obs = CACEObservation(**obs_data)
return StepResult(
observation=obs,
done=payload.get("done", obs.done),
reward=payload.get("reward", obs.reward),
info=payload.get("info", {}),
)
def _parse_state(self, payload: Dict[str, Any]) -> CACEState:
"""Parse server state response into CACEState."""
return CACEState(**{k: v for k, v in payload.items() if k in CACEState.model_fields})
# ── Convenience methods ───────────────────────────────────────────────────
async def reset_v1(self, seed: Optional[int] = None):
"""Reset in V1 mode (single case)."""
return await self.reset(mode="v1", seed=seed)
async def reset_v2(self, seed: Optional[int] = None):
"""Reset in V2 mode (network batch of 20 posts)."""
return await self.reset(mode="v2", seed=seed)
async def decide(self, action_int: int, selected_indices: list[int] | None = None):
"""Shorthand for step with a moderation decision."""
action = CACEAction(action_int=action_int, selected_indices=selected_indices)
return await self.step(action)
# ── Class methods for easy instantiation ──────────────────────────────────
@classmethod
async def from_local(cls, port: int = 7860, **kwargs):
"""Connect to a locally running server."""
client = cls(base_url=f"ws://localhost:{port}", **kwargs)
await client.connect()
return client
# Inherited from EnvClient:
# CACEEnvClient.from_docker_image("cace-env:latest")
# CACEEnvClient.from_env("username/cace-env")
# .sync() → SyncEnvClient wrapper for synchronous use