Skip to content

hylo-policy-openpi

Hylo adapter that drives an openpi policy server (pi0, pi0-FAST, pi0.5) over its websocket protocol

Repository hylo-harness, adapters/hylo-policy-openpi. Licence: Apache-2.0. Depends on: hylo-core, websockets>=13, pillow>=10.

Registered entry points
Group Name Object
agents openpi hylo.policies.openpi.agent:OpenPIAgent
Module Summary
hylo.policies.openpi
hylo.policies.openpi.agent OpenPIAgent: an Agent backed by an openpi policy server (scripts/serve_policy.py in openpi), so pi0 /

hylo.policies.openpi

META module-attribute

META = {'contracts': {'agents': 'hylo.agent/v0.1'}, 'maturity': 'implemented', 'plugins': {'agents/openpi': {'maturity': 'unverified', 'notes': 'needs an openpi policy server and its checkpoint', 'weights': 'PaliGemma-based checkpoints: Gemma Terms of Use (openpi ships LICENSE_GEMMA.txt)'}}}

hylo.policies.openpi.agent

OpenPIAgent: an Agent backed by an openpi policy server (scripts/serve_policy.py in openpi), so pi0 / pi0-FAST / pi0.5 checkpoints run in openpi's own JAX or PyTorch stack on a GPU box while the Hylo kernel, safety shield and trace stay here.

agent: {type: openpi, params: {url: "ws://gpu-box:8000", preset: libero, execution_steps: 5}}

The input mapping follows openpi's examples/libero/main.py: both cameras resized-with-pad to 224, state = eef_pos + eef_axis_angle + gripper_qpos (8), prompt = the instruction; the server returns {"actions": (H, 7)} and the client executes the first execution_steps ("replan_steps" there) before asking again. Our LIBERO adapter already rotates images by 180 degrees as openpi does.

PRESETS module-attribute

PRESETS: dict[str, dict[str, str]] = {'libero': {'observation/image': 'camera:agentview', 'observation/wrist_image': 'camera:wrist', 'observation/state': 'state:eef_pos,eef_axis_angle,gripper_qpos', 'prompt': 'instruction'}}

OpenPIAgent

OpenPIAgent(url: str = 'ws://127.0.0.1:8000', preset: str | None = 'libero', inputs: dict[str, str] | None = None, image_size: int | None = 224, execution_steps: int = 5, action_dim: int = 7, api_key: str | None = None, connect_timeout_s: float = 300.0, weights_license: str = 'see openpi checkpoint licence (Gemma terms for PaliGemma-based models)')

inputs instance-attribute

inputs = dict(PRESETS[preset]) if preset else {}

weights_license instance-attribute

weights_license = weights_license

spec

spec() -> AgentSpec

reset

reset(ctx: EpisodeContext) -> None

request

request(obs: Observation) -> dict[str, Any]

act

act(observation: Observation) -> ActionChunk

on_step

on_step(result: StepResult) -> None

on_episode_end

on_episode_end(outcome: EpisodeOutcome) -> None

close

close() -> None

resize_with_pad

resize_with_pad(img: ndarray, height: int, width: int) -> np.ndarray

Aspect-preserving bilinear resize, zero padded and centred (tf.image.resize_with_pad semantics).