ReTime / deployment /model_server /tools /websocket_policy_client.py
mmmmmcyaaa's picture
Add Florence-Bridge code and handoff documentation
977b06e verified
Raw History Blame Contribute Delete
2.79 kB
# Copyright 2025 starVLA community. All rights reserved.
# Licensed under the MIT License, Version 1.0 (the "License");
# Implemented by [Jinhui YE / HKUST University] in [2025].
import logging, argparse
import time, os
from typing import Dict, Optional, Tuple
from typing_extensions import override
import websockets.sync.client
from . import msgpack_numpy
class WebsocketClientPolicy:
"""Implements the Policy interface by communicating with a server over websocket.
See WebsocketPolicyServer for a corresponding server implementation.
"""
def __init__(self, host: str = "127.0.0.1", port: Optional[int] = 10093, api_key: Optional[str] = None) -> None:
# 0.0.0.0 cannot be used as a connection target, here default 127.0.0.1
self._uri = f"ws://{host}"
if port is not None:
self._uri += f":{port}"
self._packer = msgpack_numpy.Packer()
self._api_key = api_key
self._ws, self._server_metadata = self._wait_for_server()
def get_server_metadata(self) -> Dict:
return self._server_metadata
def _wait_for_server(self, timeout: float = 300) -> Tuple[websockets.sync.client.ClientConnection, Dict]:
logging.info(f"Waiting for server at {self._uri}...")
start_time = time.time()
for k in ("HTTP_PROXY", "http_proxy", "HTTPS_PROXY", "https_proxy", "ALL_PROXY", "all_proxy"):
os.environ.pop(k, None)
while True:
if time.time() - start_time > timeout:
raise TimeoutError(f"Failed to connect to server within {timeout} seconds")
try:
headers = {"Authorization": f"Api-Key {self._api_key}"} if self._api_key else None
conn = websockets.sync.client.connect(
self._uri,
compression=None,
max_size=None,
additional_headers=headers,
open_timeout=150,
ping_interval=None,
ping_timeout=None,
)
metadata = msgpack_numpy.unpackb(conn.recv())
return conn, metadata
except ConnectionRefusedError:
logging.info(f"Still waiting for server {self._uri} ...")
time.sleep(2)
def close(self) -> None:
try:
self._ws.close()
except Exception:
pass
@override
def predict_action(self, query_info: Dict) -> Dict:
data = self._packer.pack(query_info)
self._ws.send(data)
response = self._ws.recv()
if isinstance(response, str):
raise RuntimeError(f"Error in inference server:\n{response}")
return msgpack_numpy.unpackb(response)