spike: MolmoAct2 Docker Space (server + Dockerfile)
Browse files- DEPLOY.md +67 -0
- Dockerfile +41 -0
- README.md +28 -5
- __pycache__/molmoact2_server.cpython-312.pyc +0 -0
- molmoact2_server.py +133 -0
- requirements.txt +20 -0
DEPLOY.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Deploy MolmoAct2 as a HuggingFace Docker Space
|
| 2 |
+
|
| 3 |
+
This folder IS the Space contents (`Dockerfile`, `README.md`, `requirements.txt`,
|
| 4 |
+
`molmoact2_server.py`). `molmoact2_server.py` is a copy of the canonical
|
| 5 |
+
`../molmoact2_server.py` — after editing the canonical server, re-copy it:
|
| 6 |
+
|
| 7 |
+
```bash
|
| 8 |
+
cp ../molmoact2_server.py molmoact2_server.py
|
| 9 |
+
```
|
| 10 |
+
|
| 11 |
+
## Target
|
| 12 |
+
Space `NoriRobotics/molmoact2-space` (private, Docker SDK, GPU hardware).
|
| 13 |
+
|
| 14 |
+
## Path A — scripted (create repo + upload folder)
|
| 15 |
+
Uses the org token already in `nori-backend/.env` (`HF_ORG_ADMIN_TOKEN`), read
|
| 16 |
+
in-process, never printed. From `cloud_inference/space/`:
|
| 17 |
+
|
| 18 |
+
```bash
|
| 19 |
+
python - <<'PY'
|
| 20 |
+
import os
|
| 21 |
+
from dotenv import load_dotenv
|
| 22 |
+
from huggingface_hub import HfApi
|
| 23 |
+
load_dotenv("/Users/michael/Documents/Nori-Robotics/nori-backend/.env")
|
| 24 |
+
api = HfApi(token=os.environ["HF_ORG_ADMIN_TOKEN"])
|
| 25 |
+
repo = "NoriRobotics/molmoact2-space"
|
| 26 |
+
api.create_repo(repo, repo_type="space", space_sdk="docker", private=True, exist_ok=True)
|
| 27 |
+
api.upload_folder(repo_id=repo, repo_type="space", folder_path=".")
|
| 28 |
+
print("uploaded ->", repo)
|
| 29 |
+
PY
|
| 30 |
+
```
|
| 31 |
+
|
| 32 |
+
Creating the Space defaults to **free CPU** hardware; a CPU box cannot load the
|
| 33 |
+
model. After upload, finish in the UI (Path B steps 2-3).
|
| 34 |
+
|
| 35 |
+
## Path B — UI
|
| 36 |
+
1. huggingface.co → New Space → owner `NoriRobotics`, SDK **Docker**, **private**.
|
| 37 |
+
Clone it, copy this folder's files in, `git add . && git commit && git push`.
|
| 38 |
+
2. **Settings → Variables and secrets**: add secret `NORI_INFER_TOKEN` (the bearer
|
| 39 |
+
token the rollout sends). Add `HF_TOKEN` only if the model repo is gated.
|
| 40 |
+
3. **Settings → Hardware**: pick a GPU — `a10g-small` (~$1/hr) is enough.
|
| 41 |
+
|
| 42 |
+
## Verify
|
| 43 |
+
First boot downloads ~21GB. Poll health (no auth needed):
|
| 44 |
+
|
| 45 |
+
```bash
|
| 46 |
+
curl -s https://noribotics-molmoact2-space.hf.space/health
|
| 47 |
+
# {"ok":false,"status":"loading",...} -> {"ok":true,"status":"ready",...}
|
| 48 |
+
```
|
| 49 |
+
|
| 50 |
+
Smoke-test `/act` (needs the token; keep it out of shell history — read from a file):
|
| 51 |
+
|
| 52 |
+
```bash
|
| 53 |
+
TOKEN=$(cat ~/.nori_infer_token) # or your secret manager
|
| 54 |
+
curl -s https://noribotics-molmoact2-space.hf.space/act \
|
| 55 |
+
-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
|
| 56 |
+
-d '{"images":["<b64-jpeg>","<b64-jpeg>"],"state":[0,0,0,0,0,0],
|
| 57 |
+
"instruction":"pick up the red cup","num_steps":10}'
|
| 58 |
+
# -> {"actions":[[...6...], ...]} ~30 moves, robot scale
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
The exact subdomain is shown on the Space page (Embed → Direct URL). It is
|
| 62 |
+
`https://<owner>-<space-name>.hf.space`, lowercased with `/` → `-`.
|
| 63 |
+
|
| 64 |
+
## Cost note
|
| 65 |
+
A GPU Space bills while **Running**. Set **Sleep after inactivity** in Settings
|
| 66 |
+
(e.g. 15 min) for the spike so it pauses when idle; the robot rollout wakes it
|
| 67 |
+
(cold start ≈ first-boot download unless persistent storage is attached).
|
Dockerfile
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MolmoAct2-SO100_101 cloud-inference server as a HuggingFace **Docker** Space.
|
| 2 |
+
#
|
| 3 |
+
# WHY A DOCKER SPACE (not an Inference Endpoint): the managed Inference-Endpoint
|
| 4 |
+
# container bakes in `huggingface_inference_toolkit`, whose bootstrap imports
|
| 5 |
+
# `transformers.file_utils.is_tf_available` — REMOVED in the transformers >=4.57
|
| 6 |
+
# that MolmoAct2's processor requires (it needs `transformers.video_utils`). The
|
| 7 |
+
# two are mutually exclusive, so the toolkit path is a dead end. A Docker Space
|
| 8 |
+
# runs OUR uvicorn directly — the toolkit never enters the picture, and we own
|
| 9 |
+
# the exact transformers version.
|
| 10 |
+
#
|
| 11 |
+
# Base image = the SAME torch stack proven on HF Jobs (torch 2.5.1 + cu121):
|
| 12 |
+
# pinning transformers on top of it does NOT upgrade torch, so torchvision /
|
| 13 |
+
# torchaudio ABIs stay intact (the "-U torchvision" ABI break we hit earlier).
|
| 14 |
+
FROM pytorch/pytorch:2.5.1-cuda12.1-cudnn9-runtime
|
| 15 |
+
|
| 16 |
+
# HF Spaces run the container as uid 1000 with $HOME=/home/user. Point every
|
| 17 |
+
# cache at a writable dir so the ~21GB model download doesn't hit a read-only FS.
|
| 18 |
+
ENV HOME=/home/user \
|
| 19 |
+
PYTHONUNBUFFERED=1 \
|
| 20 |
+
HF_HOME=/home/user/.cache/huggingface \
|
| 21 |
+
HF_HUB_ENABLE_HF_TRANSFER=1
|
| 22 |
+
|
| 23 |
+
# libGL / glib for PIL+torchvision image ops; ffmpeg libs for PyAV (av) decode.
|
| 24 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 25 |
+
ffmpeg libgl1 libglib2.0-0 && \
|
| 26 |
+
rm -rf /var/lib/apt/lists/*
|
| 27 |
+
|
| 28 |
+
RUN useradd -m -u 1000 user
|
| 29 |
+
|
| 30 |
+
WORKDIR /app
|
| 31 |
+
COPY --chown=user:user requirements.txt .
|
| 32 |
+
RUN pip install --no-cache-dir -r requirements.txt hf_transfer
|
| 33 |
+
|
| 34 |
+
COPY --chown=user:user molmoact2_server.py .
|
| 35 |
+
|
| 36 |
+
RUN mkdir -p /home/user/.cache/huggingface && chown -R user:user /home/user /app
|
| 37 |
+
USER user
|
| 38 |
+
|
| 39 |
+
# HF Spaces expose the container on 7860 (declared as app_port in README.md).
|
| 40 |
+
EXPOSE 7860
|
| 41 |
+
CMD ["uvicorn", "molmoact2_server:app", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
CHANGED
|
@@ -1,10 +1,33 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: docker
|
|
|
|
| 7 |
pinned: false
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: MolmoAct2 SO100 101 Inference
|
| 3 |
+
emoji: 🤖
|
| 4 |
+
colorFrom: indigo
|
| 5 |
+
colorTo: blue
|
| 6 |
sdk: docker
|
| 7 |
+
app_port: 7860
|
| 8 |
pinned: false
|
| 9 |
+
short_description: Nori cloud-inference server for MolmoAct2-SO100_101 (/act)
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# MolmoAct2-SO100_101 — Nori cloud inference
|
| 13 |
+
|
| 14 |
+
Private Docker Space serving `allenai/MolmoAct2-SO100_101` for Nori robot rollout.
|
| 15 |
+
It runs our own FastAPI/uvicorn server (`molmoact2_server.py`) — **not** the HF
|
| 16 |
+
Inference-Endpoint toolkit, which is incompatible with the transformers version
|
| 17 |
+
this model needs.
|
| 18 |
+
|
| 19 |
+
## Endpoints
|
| 20 |
+
- `GET /health` → `{"ok", "status": "loading|ready|error", "error", "repo", "dtype"}`
|
| 21 |
+
- `POST /act` (Bearer `NORI_INFER_TOKEN`) →
|
| 22 |
+
`{ images:[b64...], state:[6 floats], instruction:str, num_steps? }`
|
| 23 |
+
→ `{ actions: [[...6 DOF...], ... up to 30 moves] }` (robot scale).
|
| 24 |
+
|
| 25 |
+
## Required setup (Space **Settings**)
|
| 26 |
+
1. **Hardware**: a GPU tier — `a10g-small` (A10G 24GB, ~$1/hr) is enough (bf16 <16GB).
|
| 27 |
+
2. **Secrets**:
|
| 28 |
+
- `NORI_INFER_TOKEN` — the bearer token the rollout client sends (required).
|
| 29 |
+
- `HF_TOKEN` — only if the model repo is gated (allenai's is public; usually not needed).
|
| 30 |
+
3. First boot downloads ~21GB, so `/health` reports `"loading"` for a few minutes,
|
| 31 |
+
then `"ready"`. Add **persistent storage** later to skip re-downloads on restart.
|
| 32 |
+
|
| 33 |
+
Deploy/update instructions: see `cloud_inference/space/DEPLOY.md` in the Nori-Lab repo.
|
__pycache__/molmoact2_server.cpython-312.pyc
ADDED
|
Binary file (7.91 kB). View file
|
|
|
molmoact2_server.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Nori cloud-inference server for MolmoAct2-SO100_101 (spike — task #38).
|
| 3 |
+
|
| 4 |
+
Runs on an AWS GPU instance (g5.xlarge / A10G 24GB is enough in bf16 <16GB).
|
| 5 |
+
Serves the robot rollout over plain JSON (NO pickle on the wire — avoids the
|
| 6 |
+
LeRobot PolicyServer CVE-2026-25874 class):
|
| 7 |
+
|
| 8 |
+
POST /act { images:[b64...], state:[6 floats], instruction:str, num_steps? }
|
| 9 |
+
-> { actions: [[...DOF...], ...] } # a 10-30 move chunk, ROBOT SCALE
|
| 10 |
+
|
| 11 |
+
The model is loaded once at startup. Inference is serialized behind a lock
|
| 12 |
+
(single GPU). Bearer-token auth (NORI_INFER_TOKEN) on every call.
|
| 13 |
+
|
| 14 |
+
The exact model API mirrors the allenai/MolmoAct2-SO100_101 model card:
|
| 15 |
+
model.predict_action(processor=..., images=[...], task=..., state=...,
|
| 16 |
+
norm_tag="so100_so101_molmoact2", inference_action_mode="continuous",
|
| 17 |
+
num_steps=10, normalize_language=True, enable_cuda_graph=True).actions
|
| 18 |
+
|
| 19 |
+
Deploy + test: see README.md in this directory.
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
import base64
|
| 23 |
+
import io
|
| 24 |
+
import os
|
| 25 |
+
import threading
|
| 26 |
+
from typing import Optional
|
| 27 |
+
|
| 28 |
+
import numpy as np
|
| 29 |
+
import torch
|
| 30 |
+
from fastapi import FastAPI, Header, HTTPException
|
| 31 |
+
from PIL import Image
|
| 32 |
+
from pydantic import BaseModel
|
| 33 |
+
from transformers import AutoModelForImageTextToText, AutoProcessor
|
| 34 |
+
|
| 35 |
+
REPO_ID = os.environ.get("MOLMOACT_REPO", "allenai/MolmoAct2-SO100_101")
|
| 36 |
+
NORM_TAG = os.environ.get("MOLMOACT_NORM_TAG", "so100_so101_molmoact2")
|
| 37 |
+
AUTH_TOKEN = os.environ.get("NORI_INFER_TOKEN") # REQUIRED — the rollout sends it
|
| 38 |
+
# bf16 fits <16GB (A10G/L4). Set MOLMOACT_BF16=0 to run fp32 (~26GB, needs L40S/48GB).
|
| 39 |
+
DTYPE = torch.bfloat16 if os.environ.get("MOLMOACT_BF16", "1") == "1" else torch.float32
|
| 40 |
+
|
| 41 |
+
app = FastAPI(title="nori-molmoact2")
|
| 42 |
+
_model = None
|
| 43 |
+
_processor = None
|
| 44 |
+
_lock = threading.Lock() # single GPU: serialize predict_action calls
|
| 45 |
+
_load_error: Optional[str] = None # set if the background load failed
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def _load_model() -> None:
|
| 49 |
+
"""Load weights in a background thread so the HTTP port is up immediately.
|
| 50 |
+
|
| 51 |
+
MolmoAct2 is ~21GB — a blocking startup event would keep the port dark for
|
| 52 |
+
minutes and a HuggingFace Space health-probe would kill the container as
|
| 53 |
+
unhealthy before the model ever finishes loading. /health reports progress.
|
| 54 |
+
"""
|
| 55 |
+
global _model, _processor, _load_error
|
| 56 |
+
try:
|
| 57 |
+
proc = AutoProcessor.from_pretrained(REPO_ID, trust_remote_code=True)
|
| 58 |
+
model = (
|
| 59 |
+
AutoModelForImageTextToText.from_pretrained(
|
| 60 |
+
REPO_ID, trust_remote_code=True, dtype=DTYPE
|
| 61 |
+
)
|
| 62 |
+
.to("cuda")
|
| 63 |
+
.eval()
|
| 64 |
+
)
|
| 65 |
+
_processor, _model = proc, model
|
| 66 |
+
print(f"[molmoact2] loaded {REPO_ID} dtype={DTYPE}", flush=True)
|
| 67 |
+
except Exception as exc: # surface load failures via /health instead of a dead port
|
| 68 |
+
_load_error = f"{type(exc).__name__}: {exc}"
|
| 69 |
+
print(f"[molmoact2] LOAD FAILED — {_load_error}", flush=True)
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
@app.on_event("startup")
|
| 73 |
+
def _startup() -> None:
|
| 74 |
+
if not AUTH_TOKEN:
|
| 75 |
+
raise RuntimeError("NORI_INFER_TOKEN must be set (bearer token for /act)")
|
| 76 |
+
threading.Thread(target=_load_model, name="molmoact2-load", daemon=True).start()
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
class ActRequest(BaseModel):
|
| 80 |
+
images: list[str] # base64 JPEG/PNG (optionally a data: URL), 2+ camera views
|
| 81 |
+
state: list[float] # robot joint state (6 for a single SO-100/101 arm)
|
| 82 |
+
instruction: str # natural-language task, e.g. "pick up the red cup"
|
| 83 |
+
num_steps: int = 10 # flow-matching integration steps (latency <-> quality)
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
class ActResponse(BaseModel):
|
| 87 |
+
actions: list[list[float]] # chunk: N moves x DOF, ROBOT SCALE (already de-normalized)
|
| 88 |
+
|
| 89 |
+
|
| 90 |
+
def _decode(b64: str) -> np.ndarray:
|
| 91 |
+
if b64.lstrip().startswith("data:") and "," in b64[:64]:
|
| 92 |
+
b64 = b64.split(",", 1)[1]
|
| 93 |
+
img = Image.open(io.BytesIO(base64.b64decode(b64))).convert("RGB")
|
| 94 |
+
return np.asarray(img)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
@app.get("/health")
|
| 98 |
+
def health() -> dict:
|
| 99 |
+
status = "ready" if _model is not None else ("error" if _load_error else "loading")
|
| 100 |
+
return {"ok": _model is not None, "status": status, "error": _load_error,
|
| 101 |
+
"repo": REPO_ID, "dtype": str(DTYPE)}
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
@app.post("/act", response_model=ActResponse)
|
| 105 |
+
def act(req: ActRequest, authorization: Optional[str] = Header(None)) -> ActResponse:
|
| 106 |
+
if authorization != f"Bearer {AUTH_TOKEN}":
|
| 107 |
+
raise HTTPException(status_code=401, detail="bad or missing bearer token")
|
| 108 |
+
if _model is None:
|
| 109 |
+
detail = f"model load failed: {_load_error}" if _load_error else "model not loaded yet"
|
| 110 |
+
raise HTTPException(status_code=503, detail=detail)
|
| 111 |
+
if len(req.images) < 1:
|
| 112 |
+
raise HTTPException(status_code=422, detail="need at least one camera image")
|
| 113 |
+
images = [_decode(b) for b in req.images]
|
| 114 |
+
state = np.asarray(req.state, dtype=np.float32)
|
| 115 |
+
with _lock, torch.no_grad():
|
| 116 |
+
out = _model.predict_action(
|
| 117 |
+
processor=_processor,
|
| 118 |
+
images=images,
|
| 119 |
+
task=req.instruction,
|
| 120 |
+
state=state,
|
| 121 |
+
norm_tag=NORM_TAG,
|
| 122 |
+
inference_action_mode="continuous",
|
| 123 |
+
num_steps=req.num_steps,
|
| 124 |
+
normalize_language=True,
|
| 125 |
+
enable_cuda_graph=True,
|
| 126 |
+
)
|
| 127 |
+
acts = out.actions
|
| 128 |
+
if torch.is_tensor(acts): # predict_action returns a CUDA tensor — move to host first
|
| 129 |
+
acts = acts.detach().float().cpu().numpy()
|
| 130 |
+
acts = np.asarray(acts, dtype=np.float32)
|
| 131 |
+
if acts.ndim == 3 and acts.shape[0] == 1: # (1, chunk, DOF) -> (chunk, DOF)
|
| 132 |
+
acts = acts[0]
|
| 133 |
+
return ActResponse(actions=acts.tolist())
|
requirements.txt
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Installed ON TOP OF the pytorch/pytorch:2.5.1-cuda12.1 base image.
|
| 2 |
+
#
|
| 3 |
+
# Do NOT list torch / torchvision / torchaudio here: the base image already
|
| 4 |
+
# ships a matched, ABI-compatible trio. Reinstalling/upgrading any one of them
|
| 5 |
+
# re-triggers the "libtorchaudio.so: undefined symbol" ABI break we hit on HF Jobs.
|
| 6 |
+
#
|
| 7 |
+
# transformers>=4.57.0 is MANDATORY — MolmoAct2's trust_remote_code processor
|
| 8 |
+
# imports transformers.video_utils.VideoInput (added in 4.57.0). Pinning it here
|
| 9 |
+
# is SAFE in a Docker Space (unlike the Inference-Endpoint toolkit, nothing else
|
| 10 |
+
# in this image imports the removed transformers.file_utils.is_tf_available).
|
| 11 |
+
transformers>=4.57.0
|
| 12 |
+
accelerate
|
| 13 |
+
fastapi
|
| 14 |
+
uvicorn[standard]
|
| 15 |
+
pillow
|
| 16 |
+
numpy
|
| 17 |
+
einops
|
| 18 |
+
av
|
| 19 |
+
scipy
|
| 20 |
+
requests
|