import os.path
# ruff: noqa: E402
import json_numpy
json_numpy.patch()
import json
import logging
import traceback
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Dict, Optional, Union
import draccus
import torch
import uvicorn
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from PIL import Image
from transformers import AutoModelForVision2Seq, AutoProcessor
# === Utilities ===
SYSTEM_PROMPT = (
"A chat between a curious user and an artificial intelligence assistant. "
"The assistant gives helpful, detailed, and polite answers to the user's questions."
)
def get_openvla_prompt(instruction: str, openvla_path: Union[str, Path]) -> str:
if "v01" in openvla_path:
return f"{SYSTEM_PROMPT} USER: What action should the robot take to {instruction.lower()}? ASSISTANT:"
else:
return f"In: What action should the robot take to {instruction.lower()}?\nOut:"
# === Server Interface ===
class OpenVLAServer:
def __init__(self, openvla_path: Union[str, Path], attn_implementation: Optional[str] = "flash_attention_2") -> Path:
"""
A simple server for OpenVLA models; exposes `/act` to predict an action for a given image + instruction.
=> Takes in {"image": np.ndarray, "instruction": str, "unnorm_key": Optional[str]}
=> Returns {"action": np.ndarray}
"""
self.openvla_path, self.attn_implementation = openvla_path, attn_implementation
self.device = torch.device("cuda:0") if torch.cuda.is_available() else torch.device("cpu")
# Load VLA Model using HF AutoClasses
self.processor = AutoProcessor.from_pretrained(self.openvla_path, trust_remote_code=True)
self.vla = AutoModelForVision2Seq.from_pretrained(
self.openvla_path,
attn_implementation=attn_implementation,
torch_dtype=torch.bfloat16,
low_cpu_mem_usage=True,
trust_remote_code=True,
).to(self.device)
# [Hacky] Load Dataset Statistics from Disk (if passing a path to a fine-tuned model)
if os.path.isdir(self.openvla_path):
with open(Path(self.openvla_path) / "dataset_statistics.json", "r") as f:
self.vla.norm_stats = json.load(f)
def predict_action(self, payload: Dict[str, Any]) -> str:
try:
if double_encode := "encoded" in payload:
# Support cases where `json_numpy` is hard to install, and numpy arrays are "double-encoded" as strings
assert len(payload.keys()) == 1, "Only uses encoded payload!"
payload = json.loads(payload["encoded"])
# Parse payload components
image, instruction = payload["image"], payload["instruction"]
unnorm_key = payload.get("unnorm_key", None)
# Run VLA Inference
prompt = get_openvla_prompt(instruction, self.openvla_path)
inputs = self.processor(prompt, Image.fromarray(image).convert("RGB")).to(self.device, dtype=torch.bfloat16)
action = self.vla.predict_action(**inputs, unnorm_key=unnorm_key, do_sample=False)
if double_encode:
return JSONResponse(json_numpy.dumps(action))
else:
return JSONResponse(action)
except: # noqa: E722
logging.error(traceback.format_exc())
logging.warning(
"Your request threw an error; make sure your request complies with the expected format:\n"
"{'image': np.ndarray, 'instruction': str}\n"
"You can optionally an `unnorm_key: str` to specific the dataset statistics you want to use for "
"de-normalizing the output actions."
)
return "error"
def run(self, host: str = "0.0.0.0", port: int = 8000) -> None:
self.app = FastAPI()
self.app.post("/act")(self.predict_action)
uvicorn.run(self.app, host=host, port=port)
@dataclass
class DeployConfig:
# fmt: off
openvla_path: Union[str, Path] = "openvla/openvla-7b" # HF Hub Path (or path to local run directory)
# Server Configuration
host: str = "0.0.0.0" # Host IP Address
port: int = 8000 # Host Port
# fmt: on
@draccus.wrap()
def deploy(cfg: DeployConfig) -> None:
server = OpenVLAServer(cfg.openvla_path)
server.run(cfg.host, port=cfg.port)
if __name__ == "__main__":
deploy()
这段代码放到我终端的python中出现了报错
>>> self.processor = AutoProcessor.from_pretrained(self.openvla_path, trust_remote_code=True)
File "<stdin>", line 1
self.processor = AutoProcessor.from_pretrained(self.openvla_path, trust_remote_code=True)
IndentationError: unexpected indent
>>> self.vla = AutoModelForVision2Seq.from_pretrained(
File "<stdin>", line 1
self.vla = AutoModelForVision2Seq.from_pretrained(
IndentationError: unexpected indent
>>> self.openvla_path,
File "<stdin>", line 1
self.openvla_path,
IndentationError: unexpected indent
>>> attn_implementation=attn_implementation,
File "<stdin>", line 1
attn_implementation=attn_implementation,
IndentationError: unexpected indent
>>> torch_dtype=torch.bfloat16,
File "<stdin>", line 1
torch_dtype=torch.bfloat16,
IndentationError: unexpected indent
>>> low_cpu_mem_usage=True,
File "<stdin>", line 1
low_cpu_mem_usage=True,
IndentationError: unexpected indent
>>> trust_remote_code=True,
File "<stdin>", line 1
trust_remote_code=True,
IndentationError: unexpected indent
>>> ).to(self.device)
File "<stdin>", line 1
).to(self.device)
IndentationError: unexpected indent
>>>
>>> # [Hacky] Load Dataset Statistics from Disk (if passing a path to a fine-tuned model)
>>> if os.path.isdir(self.openvla_path):
File "<stdin>", line 1
if os.path.isdir(self.openvla_path):
IndentationError: unexpected indent
>>> with open(Path(self.openvla_path) / "dataset_statistics.json", "r") as f:
File "<stdin>", line 1
with open(Path(self.openvla_path) / "dataset_statistics.json", "r") as f:
IndentationError: unexpected indent
>>> self.vla.norm_stats = json.load(f)
File "<stdin>", line 1
self.vla.norm_stats = json.load(f)
IndentationError: unexpected indent
>>>
>>> def predict_action(self, payload: Dict[str, Any]) -> str:
File "<stdin>", line 1
def predict_action(self, payload: Dict[str, Any]) -> str:
IndentationError: unexpected indent
>>> try:
File "<stdin>", line 1
try:
IndentationError: unexpected indent
>>> if double_encode := "encoded" in payload:
File "<stdin>", line 1
if double_encode := "encoded" in payload:
IndentationError: unexpected indent
>>> # Support cases where `json_numpy` is hard to install, and numpy arrays are "double-encoded" as strings
>>> assert len(payload.keys()) == 1, "Only uses encoded payload!"
File "<stdin>", line 1
assert len(payload.keys()) == 1, "Only uses encoded payload!"
IndentationError: unexpected indent
>>> payload = json.loads(payload["encoded"])
File "<stdin>", line 1
payload = json.loads(payload["encoded"])
IndentationError: unexpected indent
>>>
>>> # Parse payload components
>>> image, instruction = payload["image"], payload["instruction"]
File "<stdin>", line 1
image, instruction = payload["image"], payload["instruction"]
IndentationError: unexpected indent
>>> unnorm_key = payload.get("unnorm_key", None)
File "<stdin>", line 1
unnorm_key = payload.get("unnorm_key", None)
IndentationError: unexpected indent
>>>
>>> # Run VLA Inference
>>> prompt = get_openvla_prompt(instruction, self.openvla_path)
File "<stdin>", line 1
prompt = get_openvla_prompt(instruction, self.openvla_path)
IndentationError: unexpected indent
>>> inputs = self.processor(prompt, Image.fromarray(image).convert("RGB")).to(self.device, dtype=torch.bfloat16)
File "<stdin>", line 1
inputs = self.processor(prompt, Image.fromarray(image).convert("RGB")).to(self.device, dtype=torch.bfloat16)
IndentationError: unexpected indent
>>> action = self.vla.predict_action(**inputs, unnorm_key=unnorm_key, do_sample=False)
File "<stdin>", line 1
action = self.vla.predict_action(**inputs, unnorm_key=unnorm_key, do_sample=False)
IndentationError: unexpected indent
>>> if double_encode:
File "<stdin>", line 1
if double_encode:
IndentationError: unexpected indent
>>> return JSONResponse(json_numpy.dumps(action))
File "<stdin>", line 1
return JSONResponse(json_numpy.dumps(action))
IndentationError: unexpected indent
>>> else:
File "<stdin>", line 1
else:
IndentationError: unexpected indent
>>> return JSONResponse(action)
File "<stdin>", line 1
return JSONResponse(action)
IndentationError: unexpected indent
>>> except: # noqa: E722
File "<stdin>", line 1
except: # noqa: E722
IndentationError: unexpected indent
>>> logging.error(traceback.format_exc())
File "<stdin>", line 1
logging.error(traceback.format_exc())
IndentationError: unexpected indent
>>> logging.warning(
File "<stdin>", line 1
logging.warning(
IndentationError: unexpected indent
>>> "Your request threw an error; make sure your request complies with the expected format:\n"
File "<stdin>", line 1
"Your request threw an error; make sure your request complies with the expected format:\n"
IndentationError: unexpected indent
>>> "{'image': np.ndarray, 'instruction': str}\n"
File "<stdin>", line 1
"{'image': np.ndarray, 'instruction': str}\n"
IndentationError: unexpected indent
>>> "You can optionally an `unnorm_key: str` to specific the dataset statistics you want to use for "
File "<stdin>", line 1
"You can optionally an `unnorm_key: str` to specific the dataset statistics you want to use for "
IndentationError: unexpected indent
>>> "de-normalizing the output actions."
File "<stdin>", line 1
"de-normalizing the output actions."
IndentationError: unexpected indent
>>> )
File "<stdin>", line 1
)
IndentationError: unexpected indent
>>> return "error"
File "<stdin>", line 1
return "error"
IndentationError: unexpected indent
>>>
>>> def run(self, host: str = "0.0.0.0", port: int = 8000) -> None:
File "<stdin>", line 1
def run(self, host: str = "0.0.0.0", port: int = 8000) -> None:
IndentationError: unexpected indent
>>> self.app = FastAPI()
File "<stdin>", line 1
self.app = FastAPI()
IndentationError: unexpected indent
>>> self.app.post("/act")(self.predict_action)
File "<stdin>", line 1
self.app.post("/act")(self.predict_action)
IndentationError: unexpected indent
>>> uvicorn.run(self.app, host=host, port=port)
File "<stdin>", line 1
uvicorn.run(self.app, host=host, port=port)
IndentationError: unexpected indent
>>>
>>>
>>> @dataclass
... class DeployConfig:
... # fmt: off
... openvla_path: Union[str, Path] = "openvla/openvla-7b" # HF Hub Path (or path to local run directory)
...
>>> # Server Configuration
>>> host: str = "0.0.0.0" # Host IP Address
File "<stdin>", line 1
host: str = "0.0.0.0" # Host IP Address
IndentationError: unexpected indent
>>> port: int = 8000 # Host Port
File "<stdin>", line 1
port: int = 8000 # Host Port
IndentationError: unexpected indent