Swap GH200 layer for Quadro RTX 6000 (Turing) Docker setup
Browse files- .claude/settings.local.json +8 -0
- README-GH200.md +0 -114
- README-RTX6000.md +105 -0
- docker/docker-gh200/Dockerfile +0 -56
- docker/docker-rtx6000/Dockerfile +58 -0
- docker/{docker-gh200 → docker-rtx6000}/docker-compose.yml +15 -9
- gradio/mme.py +18 -7
- gradio/mme_gradio.py +22 -6
- gradio/narration_gradio.py +24 -7
- gradio/proactive_gradio.py +22 -6
- requirements-gh200.txt → requirements-rtx6000.txt +31 -13
- scripts/{gh200 → rtx6000}/download_model.sh +1 -2
- scripts/{gh200 → rtx6000}/run_demo.sh +19 -13
.claude/settings.local.json
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"permissions": {
|
| 3 |
+
"allow": [
|
| 4 |
+
"Bash(git rm *)",
|
| 5 |
+
"Bash(echo \"=== EXIT $? ===\")"
|
| 6 |
+
]
|
| 7 |
+
}
|
| 8 |
+
}
|
README-GH200.md
DELETED
|
@@ -1,114 +0,0 @@
|
|
| 1 |
-
# Running ROMA reproducibly on an NVIDIA GH200
|
| 2 |
-
|
| 3 |
-
This guide reproduces the **inference / real-time streaming demos** of
|
| 4 |
-
[ROMA (arXiv:2601.10323)](https://arxiv.org/abs/2601.10323) on an **NVIDIA GH200**
|
| 5 |
-
(ARM64/aarch64 Grace CPU + Hopper GPU, sm_90), using Docker for reproducibility.
|
| 6 |
-
|
| 7 |
-
It covers the **real-time proactive** path (ROMA's headline capability — the model decides
|
| 8 |
-
*when* to speak via its Speak Head), plus the narration and reactive-QA demos.
|
| 9 |
-
|
| 10 |
-
> Training and the full evaluation suite are **out of scope** for this image (training needs the
|
| 11 |
-
> 136K dataset + dataset registration and a non-cluster launcher; evaluation needs many external
|
| 12 |
-
> benchmark datasets and a GPT-judge API key).
|
| 13 |
-
|
| 14 |
-
## Why a GH200-specific image?
|
| 15 |
-
|
| 16 |
-
The GH200 is **aarch64**. The upstream `requirements.txt` pins **x86_64-only** wheels —
|
| 17 |
-
`torch==2.6.0+cu124`, `torchvision/torchaudio +cu124`, `xformers`, `flash_attn==2.7.4.post1`,
|
| 18 |
-
and a set of `nvidia-*-cu12` wheels. On ARM, `pip install -r requirements.txt` **fails** (those
|
| 19 |
-
`+cu124` wheels aren't published for aarch64; `flash_attn` has no ARM wheel). The upstream
|
| 20 |
-
`docker/docker-cuda/` image runs that same install, so it does **not** work on a GH200.
|
| 21 |
-
|
| 22 |
-
This image instead bases on the **NGC PyTorch container** (`nvcr.io/nvidia/pytorch:24.12-py3`),
|
| 23 |
-
whose ARM64/sbsa variant is auto-selected on the GH200 and already ships PyTorch, flash-attention
|
| 24 |
-
and transformer-engine built for aarch64 + Hopper. We then install only a **filtered**
|
| 25 |
-
requirements list ([`requirements-gh200.txt`](requirements-gh200.txt)) plus ROMA's custom
|
| 26 |
-
`transformers` fork and the editable `llamafactory` package.
|
| 27 |
-
|
| 28 |
-
## Prerequisites (on the GH200 host)
|
| 29 |
-
|
| 30 |
-
- NVIDIA driver + **NVIDIA Container Toolkit** installed (`docker run --rm --gpus all nvidia/cuda:12.6.0-base-ubuntu22.04 nvidia-smi` should work).
|
| 31 |
-
- Docker with Compose v2.
|
| 32 |
-
- ~60 GB free disk (NGC base image + checkpoint).
|
| 33 |
-
- Network access to `nvcr.io`, `pypi.org`, `github.com`, and `huggingface.co`.
|
| 34 |
-
|
| 35 |
-
## 1. Build
|
| 36 |
-
|
| 37 |
-
```bash
|
| 38 |
-
git clone <your-fork-url> ROMA && cd ROMA
|
| 39 |
-
docker compose -f docker/docker-gh200/docker-compose.yml build
|
| 40 |
-
```
|
| 41 |
-
|
| 42 |
-
On the GH200 this automatically pulls the `linux/arm64` NGC image — no extra flags needed.
|
| 43 |
-
|
| 44 |
-
## 2. Start an interactive container
|
| 45 |
-
|
| 46 |
-
```bash
|
| 47 |
-
docker compose -f docker/docker-gh200/docker-compose.yml run --rm --service-ports roma bash
|
| 48 |
-
```
|
| 49 |
-
|
| 50 |
-
The checkpoint, HF cache and demo media are bind-mounted to the host (`./whole_model`,
|
| 51 |
-
`./hf_cache`, `./demo_media`) so they persist across runs.
|
| 52 |
-
|
| 53 |
-
## 3. Download the released checkpoint (inside the container)
|
| 54 |
-
|
| 55 |
-
```bash
|
| 56 |
-
bash scripts/gh200/download_model.sh # -> whole_model/model (~16-22 GB)
|
| 57 |
-
```
|
| 58 |
-
|
| 59 |
-
(If the pull is rate-limited/gated, set `HF_TOKEN` — uncomment it in the compose file or
|
| 60 |
-
`export HF_TOKEN=...` before running.)
|
| 61 |
-
|
| 62 |
-
## 4. Run a real-time demo (inside the container)
|
| 63 |
-
|
| 64 |
-
```bash
|
| 65 |
-
bash scripts/gh200/run_demo.sh proactive # real-time proactive event alert (default)
|
| 66 |
-
# or
|
| 67 |
-
bash scripts/gh200/run_demo.sh narration # real-time streaming narration
|
| 68 |
-
bash scripts/gh200/run_demo.sh mme # reactive multimodal QA
|
| 69 |
-
```
|
| 70 |
-
|
| 71 |
-
Then open **`http://<gh200-host>:7860`** and click **▶ Start Detection Stream**. ROMA streams
|
| 72 |
-
its output live, with the Speak Head triggering above its threshold.
|
| 73 |
-
|
| 74 |
-
### Using your own clips
|
| 75 |
-
|
| 76 |
-
The demos ship default media paths; some referenced files aren't in the repo. Point them at your
|
| 77 |
-
own clips (place files under `./demo_media`, mounted at `/app/demo_media`):
|
| 78 |
-
|
| 79 |
-
```bash
|
| 80 |
-
ROMA_VIDEO=/app/demo_media/my_clip.mp4 \
|
| 81 |
-
ROMA_AUDIO=/app/demo_media/my_clip.wav \
|
| 82 |
-
bash scripts/gh200/run_demo.sh proactive
|
| 83 |
-
```
|
| 84 |
-
|
| 85 |
-
A ready-to-use sample video bundled in the repo: `gradio/aCkbw-aI4xU_cut80s.mp4`
|
| 86 |
-
(the default for the `narration` demo).
|
| 87 |
-
|
| 88 |
-
## Smoke test (verify the environment)
|
| 89 |
-
|
| 90 |
-
Inside the container:
|
| 91 |
-
|
| 92 |
-
```bash
|
| 93 |
-
python -c "import torch, flash_attn, transformers; \
|
| 94 |
-
print('torch', torch.__version__); \
|
| 95 |
-
print('flash_attn', flash_attn.__version__); \
|
| 96 |
-
print('transformers', transformers.__version__); \
|
| 97 |
-
print('gpu', torch.cuda.get_device_name(0))"
|
| 98 |
-
python -c "from transformers import Qwen2_5OmniModel; print('Qwen2_5OmniModel OK')"
|
| 99 |
-
```
|
| 100 |
-
|
| 101 |
-
You should see a Hopper / GH200 device name and a successful `Qwen2_5OmniModel` import from the
|
| 102 |
-
patched transformers fork.
|
| 103 |
-
|
| 104 |
-
## Troubleshooting
|
| 105 |
-
|
| 106 |
-
- **`flash_attn` import fails:** confirm the NGC base actually selected the arm64 variant
|
| 107 |
-
(`docker run --rm roma-gh200:latest python -c "import platform; print(platform.machine())"` →
|
| 108 |
-
`aarch64`). If you built on x86 by mistake, rebuild on the GH200.
|
| 109 |
-
- **transformers version conflict:** the fork is installed `--no-deps` so it can't downgrade the
|
| 110 |
-
NGC torch. If a dependency complains about the transformers version, it's safe to ignore for the
|
| 111 |
-
demos; report it if a demo actually fails to import.
|
| 112 |
-
- **UI not reachable:** ensure you started the container with `--service-ports` (or the compose
|
| 113 |
-
`ports:` mapping) and that the demo bound to `0.0.0.0` (it does by default via
|
| 114 |
-
`GRADIO_SERVER_NAME`).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
README-RTX6000.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Running ROMA reproducibly on Quadro RTX 6000 (×4)
|
| 2 |
+
|
| 3 |
+
This guide reproduces the **inference / real-time streaming demos** of
|
| 4 |
+
[ROMA (arXiv:2601.10323)](https://arxiv.org/abs/2601.10323) on a workstation with
|
| 5 |
+
**4× Quadro RTX 6000** (Turing, sm_75, x86_64, 24 GB each = 96 GB), driver 570.x / CUDA 12.8, using
|
| 6 |
+
Docker for reproducibility. It covers the **real-time proactive** demo (the Speak Head decides *when*
|
| 7 |
+
to respond), plus narration and reactive QA. See [ARCHITECTURE.md](ARCHITECTURE.md) for how ROMA works.
|
| 8 |
+
|
| 9 |
+
> Training and the full evaluation suite are **out of scope** for this image.
|
| 10 |
+
|
| 11 |
+
## Why a Turing-specific image?
|
| 12 |
+
|
| 13 |
+
The Quadro RTX 6000 is **Turing (sm_75)**, which changes three things vs. the repo's defaults:
|
| 14 |
+
|
| 15 |
+
| Repo default | Problem on Turing | This image |
|
| 16 |
+
|---|---|---|
|
| 17 |
+
| `attn_implementation="flash_attention_2"` | FlashAttention-2 needs Ampere (sm_80+) | defaults to **`sdpa`** (`ROMA_ATTN`) |
|
| 18 |
+
| `torch_dtype=torch.bfloat16` | bf16 not hardware-accelerated on Turing | defaults to **fp16** (`ROMA_DTYPE`) |
|
| 19 |
+
| `flash_attn==2.7.4.post1` in requirements | no sm_75 wheel; source build fails | **removed** from `requirements-rtx6000.txt` |
|
| 20 |
+
| single-GPU fp16 (~22 GB) | won't fit 24 GB + KV-cache | **sharded across all 4 GPUs** via `device_map="auto"` |
|
| 21 |
+
|
| 22 |
+
x86_64 means the original `+cu124` PyTorch wheels are valid, so this image stays close to the
|
| 23 |
+
upstream pins (unlike an ARM/GH200 build). We base on `nvidia/cuda:12.4.1-cudnn-runtime` and install
|
| 24 |
+
**official cu124 PyTorch wheels**, which include Turing kernels.
|
| 25 |
+
|
| 26 |
+
## Prerequisites
|
| 27 |
+
|
| 28 |
+
- NVIDIA driver (present: 570.195.03) + **NVIDIA Container Toolkit**.
|
| 29 |
+
Verify: `docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi` lists all 4 cards.
|
| 30 |
+
- Docker with Compose v2, ~40 GB free disk (image + checkpoint).
|
| 31 |
+
- Network access to `pypi.org`, `download.pytorch.org`, `github.com`, `huggingface.co`.
|
| 32 |
+
|
| 33 |
+
## 1. Build
|
| 34 |
+
|
| 35 |
+
```bash
|
| 36 |
+
git clone <your-repo-url> ROMA && cd ROMA
|
| 37 |
+
docker compose -f docker/docker-rtx6000/docker-compose.yml build
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
## 2. Start an interactive container (all 4 GPUs)
|
| 41 |
+
|
| 42 |
+
```bash
|
| 43 |
+
docker compose -f docker/docker-rtx6000/docker-compose.yml run --rm --service-ports roma bash
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
The checkpoint, HF cache and demo media are bind-mounted to the host (`./whole_model`, `./hf_cache`,
|
| 47 |
+
`./demo_media`) so they persist across runs.
|
| 48 |
+
|
| 49 |
+
## 3. Download the checkpoint (inside the container)
|
| 50 |
+
|
| 51 |
+
```bash
|
| 52 |
+
bash scripts/rtx6000/download_model.sh # -> whole_model/model (~16-22 GB)
|
| 53 |
+
```
|
| 54 |
+
|
| 55 |
+
(If the pull is rate-limited/gated, set `HF_TOKEN`.)
|
| 56 |
+
|
| 57 |
+
## 4. Run a real-time demo (inside the container)
|
| 58 |
+
|
| 59 |
+
```bash
|
| 60 |
+
bash scripts/rtx6000/run_demo.sh proactive # real-time proactive event alert (default)
|
| 61 |
+
# or
|
| 62 |
+
bash scripts/rtx6000/run_demo.sh narration # real-time streaming narration
|
| 63 |
+
bash scripts/rtx6000/run_demo.sh mme # reactive multimodal QA
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
Open **`http://<host>:7860`** and click **▶ Start Detection Stream**. ROMA streams its output live,
|
| 67 |
+
with the Speak Head triggering above its threshold.
|
| 68 |
+
|
| 69 |
+
### Using your own clips
|
| 70 |
+
|
| 71 |
+
```bash
|
| 72 |
+
ROMA_VIDEO=/app/demo_media/my_clip.mp4 \
|
| 73 |
+
ROMA_AUDIO=/app/demo_media/my_clip.wav \
|
| 74 |
+
bash scripts/rtx6000/run_demo.sh proactive
|
| 75 |
+
```
|
| 76 |
+
|
| 77 |
+
A bundled sample video: `gradio/aCkbw-aI4xU_cut80s.mp4` (the `narration` default).
|
| 78 |
+
|
| 79 |
+
## Smoke test (verify the environment)
|
| 80 |
+
|
| 81 |
+
Inside the container:
|
| 82 |
+
|
| 83 |
+
```bash
|
| 84 |
+
python -c "import torch; print(torch.__version__, torch.cuda.device_count(), torch.cuda.get_device_name(0), torch.cuda.get_device_capability(0))"
|
| 85 |
+
# expect: 2.6.0+cu124 4 'Quadro RTX 6000' (7, 5)
|
| 86 |
+
python -c "from transformers import Qwen2_5OmniModel; print('Qwen2_5OmniModel OK')"
|
| 87 |
+
```
|
| 88 |
+
|
| 89 |
+
While a demo runs, `nvidia-smi` should show the model **sharded across GPUs 0–3** (~5–6 GB each).
|
| 90 |
+
|
| 91 |
+
## Fallback matrix (env vars)
|
| 92 |
+
|
| 93 |
+
| Symptom | Try |
|
| 94 |
+
|---|---|
|
| 95 |
+
| `sdpa` rejected by the transformers fork | `ROMA_ATTN=eager bash scripts/rtx6000/run_demo.sh ...` |
|
| 96 |
+
| Gate probabilities print as `nan` (fp16 overflow) | `ROMA_DTYPE=bfloat16 ...` (bf16 runs in software on Turing — slower but safe) |
|
| 97 |
+
| `device_map="auto"` mis-places modules / cross-GPU error | run on one card with 8-bit: `CUDA_VISIBLE_DEVICES=0 ROMA_LOAD_8BIT=1 ...` |
|
| 98 |
+
| Want to free 3 GPUs for other work | `CUDA_VISIBLE_DEVICES=0 ROMA_LOAD_8BIT=1 ...` (fits ~10–12 GB on one card) |
|
| 99 |
+
| 8-bit load errors on the omni encoders | edit `llm_int8_skip_modules` in the demo loader, or set `ROMA_LOAD_8BIT=0` |
|
| 100 |
+
|
| 101 |
+
## Notes
|
| 102 |
+
|
| 103 |
+
- The demos only use `model.thinker`; the loader calls `disable_talker()` (best-effort) to free memory.
|
| 104 |
+
- `attn_implementation` and dtype are read from env at load time, so the same scripts also run with the
|
| 105 |
+
paper's original settings on an Ampere+ GPU: `ROMA_ATTN=flash_attention_2 ROMA_DTYPE=bfloat16`.
|
docker/docker-gh200/Dockerfile
DELETED
|
@@ -1,56 +0,0 @@
|
|
| 1 |
-
# ROMA inference image for NVIDIA GH200 (ARM64/aarch64 Grace + Hopper GPU, sm_90).
|
| 2 |
-
#
|
| 3 |
-
# We base on the NGC PyTorch container. NGC publishes a multi-arch manifest, so on a GH200
|
| 4 |
-
# host `docker build`/`pull` automatically selects the linux/arm64 (sbsa) variant, which already
|
| 5 |
-
# ships PyTorch, flash-attention and transformer-engine built for aarch64 + Hopper. We therefore
|
| 6 |
-
# do NOT reinstall torch / flash-attn / xformers / the nvidia-*-cu12 wheels (those upstream pins
|
| 7 |
-
# are x86_64-only and would break the ARM build) — see requirements-gh200.txt for the rationale.
|
| 8 |
-
#
|
| 9 |
-
# Pin notes: 24.12-py3 == PyTorch 2.6.0a0 + CUDA 12.6, matching the repo's intended torch 2.6.
|
| 10 |
-
# If the patched transformers fork ever needs a different torch minor, only this tag changes.
|
| 11 |
-
ARG BASE_IMAGE=nvcr.io/nvidia/pytorch:24.12-py3
|
| 12 |
-
FROM ${BASE_IMAGE}
|
| 13 |
-
|
| 14 |
-
# Hopper arch for any from-source CUDA build fallback; faster HF downloads of the ~16-22GB ckpt.
|
| 15 |
-
ENV TORCH_CUDA_ARCH_LIST=9.0
|
| 16 |
-
ENV HF_HUB_ENABLE_HF_TRANSFER=1
|
| 17 |
-
ENV PIP_INDEX=https://pypi.org/simple
|
| 18 |
-
# The gradio demos call demo.launch() without a server name; bind to all interfaces so the UI is
|
| 19 |
-
# reachable from the host. Demos read this env (added in the gradio edits).
|
| 20 |
-
ENV GRADIO_SERVER_NAME=0.0.0.0
|
| 21 |
-
|
| 22 |
-
ARG TRANSFORMERS_REF=roma_patch
|
| 23 |
-
|
| 24 |
-
WORKDIR /app
|
| 25 |
-
|
| 26 |
-
# 1) Install the filtered runtime deps. Intentionally keeps the NGC-provided framework + CUDA
|
| 27 |
-
# stack untouched (no torch/flash-attn/xformers/triton/nvidia-*-cu12 lines in this file).
|
| 28 |
-
COPY requirements-gh200.txt /app/requirements-gh200.txt
|
| 29 |
-
RUN python -m pip install --upgrade pip && \
|
| 30 |
-
python -m pip install --index-url "$PIP_INDEX" -r /app/requirements-gh200.txt
|
| 31 |
-
|
| 32 |
-
# 2) Install ROMA's custom transformers fork (Qwen2.5-Omni streaming patch). --no-deps so it
|
| 33 |
-
# cannot pull a conflicting torch over the NGC build; its runtime deps (tokenizers, safetensors,
|
| 34 |
-
# huggingface-hub) are already provided by requirements-gh200.txt.
|
| 35 |
-
RUN python -m pip install --no-deps --no-build-isolation \
|
| 36 |
-
"git+https://github.com/Eureka-Maggie/transformers.git@${TRANSFORMERS_REF}"
|
| 37 |
-
|
| 38 |
-
# 3) Copy the repo and register the llamafactory package in editable mode without re-resolving
|
| 39 |
-
# framework deps (already satisfied above).
|
| 40 |
-
COPY . /app
|
| 41 |
-
RUN python -m pip install --no-deps -e .
|
| 42 |
-
|
| 43 |
-
# 4) Build-time sanity check (non-fatal: GPU isn't visible during build, so don't assert cuda).
|
| 44 |
-
RUN python -c "import torch, transformers; print('torch', torch.__version__); print('transformers', transformers.__version__)" && \
|
| 45 |
-
(python -c "import flash_attn; print('flash_attn', flash_attn.__version__)" || echo 'WARN: flash_attn import failed at build time; will be verified at runtime')
|
| 46 |
-
|
| 47 |
-
# LLaMA Board / gradio UI and API ports.
|
| 48 |
-
ENV GRADIO_SERVER_PORT=7860
|
| 49 |
-
EXPOSE 7860
|
| 50 |
-
ENV API_PORT=8000
|
| 51 |
-
EXPOSE 8000
|
| 52 |
-
|
| 53 |
-
# Persist the downloaded checkpoint, HF cache and demo media across container runs.
|
| 54 |
-
VOLUME [ "/app/whole_model", "/root/.cache/huggingface", "/app/demo_media" ]
|
| 55 |
-
|
| 56 |
-
CMD ["bash"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docker/docker-rtx6000/Dockerfile
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ROMA inference image for Quadro RTX 6000 (Turing sm_75, x86_64, 24GB ×4 = 96GB).
|
| 2 |
+
#
|
| 3 |
+
# Base: CUDA 12.4 runtime on Ubuntu 22.04. CUDA 12.4 matches the repo's torch 2.6.0+cu124, and runs
|
| 4 |
+
# fine on the host's 570.x / CUDA-12.8 driver (drivers are backward compatible). We install the
|
| 5 |
+
# OFFICIAL PyTorch cu124 wheels (via download.pytorch.org), which include Turing (sm_75) kernels --
|
| 6 |
+
# NGC datacenter images may omit sm_75 and produce "no kernel image is available" at runtime, so we
|
| 7 |
+
# deliberately do NOT use an NGC base here.
|
| 8 |
+
#
|
| 9 |
+
# Turing notes (handled in the demo scripts, not here): FlashAttention-2 is unsupported on sm_75 so
|
| 10 |
+
# the demos default to attn_implementation=sdpa; bf16 is not accelerated so they default to fp16.
|
| 11 |
+
ARG BASE_IMAGE=nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04
|
| 12 |
+
FROM ${BASE_IMAGE}
|
| 13 |
+
|
| 14 |
+
ENV DEBIAN_FRONTEND=noninteractive
|
| 15 |
+
ENV PIP_INDEX=https://pypi.org/simple
|
| 16 |
+
ENV TORCH_INDEX=https://download.pytorch.org/whl/cu124
|
| 17 |
+
ENV HF_HUB_ENABLE_HF_TRANSFER=1
|
| 18 |
+
# The gradio demos call demo.launch() without a server name; bind to all interfaces so the UI is
|
| 19 |
+
# reachable from the host (the demos read this env, added in the gradio edits).
|
| 20 |
+
ENV GRADIO_SERVER_NAME=0.0.0.0
|
| 21 |
+
ENV PYTHONUNBUFFERED=1
|
| 22 |
+
|
| 23 |
+
ARG TRANSFORMERS_REF=roma_patch
|
| 24 |
+
|
| 25 |
+
# System deps: Python 3.10, ffmpeg (decord/av/moviepy), git (to pip-install the transformers fork).
|
| 26 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 27 |
+
python3.10 python3.10-dev python3-pip \
|
| 28 |
+
ffmpeg git ca-certificates && \
|
| 29 |
+
ln -sf /usr/bin/python3.10 /usr/bin/python && \
|
| 30 |
+
rm -rf /var/lib/apt/lists/*
|
| 31 |
+
|
| 32 |
+
WORKDIR /app
|
| 33 |
+
|
| 34 |
+
# Install the runtime deps. The +cu124 torch/vision/audio pins resolve from the PyTorch index; the
|
| 35 |
+
# transformers@roma_patch fork is fetched from git (already pinned in the requirements file).
|
| 36 |
+
COPY requirements-rtx6000.txt /app/requirements-rtx6000.txt
|
| 37 |
+
RUN python -m pip install --upgrade pip && \
|
| 38 |
+
python -m pip install \
|
| 39 |
+
--index-url "$PIP_INDEX" \
|
| 40 |
+
--extra-index-url "$TORCH_INDEX" \
|
| 41 |
+
-r /app/requirements-rtx6000.txt
|
| 42 |
+
|
| 43 |
+
# Register the llamafactory package editable from the local checkout (deps already satisfied above).
|
| 44 |
+
COPY . /app
|
| 45 |
+
RUN python -m pip install --no-deps -e .
|
| 46 |
+
|
| 47 |
+
# Build-time sanity import (GPU is not visible during build, so we don't assert cuda here).
|
| 48 |
+
RUN python -c "import torch, transformers, bitsandbytes; print('torch', torch.__version__, '| transformers', transformers.__version__)"
|
| 49 |
+
|
| 50 |
+
ENV GRADIO_SERVER_PORT=7860
|
| 51 |
+
EXPOSE 7860
|
| 52 |
+
ENV API_PORT=8000
|
| 53 |
+
EXPOSE 8000
|
| 54 |
+
|
| 55 |
+
# Persist the checkpoint, HF cache and demo media across container runs.
|
| 56 |
+
VOLUME [ "/app/whole_model", "/root/.cache/huggingface", "/app/demo_media" ]
|
| 57 |
+
|
| 58 |
+
CMD ["bash"]
|
docker/{docker-gh200 → docker-rtx6000}/docker-compose.yml
RENAMED
|
@@ -1,18 +1,19 @@
|
|
| 1 |
-
# ROMA inference on
|
| 2 |
-
# Usage (run from the repo root on the
|
| 3 |
-
# docker compose -f docker/docker-
|
| 4 |
-
# docker compose -f docker/docker-
|
| 5 |
services:
|
| 6 |
roma:
|
| 7 |
build:
|
| 8 |
-
dockerfile: ./docker/docker-
|
| 9 |
context: ../..
|
| 10 |
args:
|
| 11 |
-
BASE_IMAGE:
|
| 12 |
TRANSFORMERS_REF: roma_patch
|
| 13 |
PIP_INDEX: https://pypi.org/simple
|
| 14 |
-
|
| 15 |
-
|
|
|
|
| 16 |
volumes:
|
| 17 |
# ~16-22GB checkpoint, HF cache and demo media live on the host, not in the image.
|
| 18 |
- ../../whole_model:/app/whole_model
|
|
@@ -25,6 +26,11 @@ services:
|
|
| 25 |
environment:
|
| 26 |
- GRADIO_SERVER_NAME=0.0.0.0
|
| 27 |
- HF_HUB_ENABLE_HF_TRANSFER=1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
# - HF_TOKEN=${HF_TOKEN} # uncomment if the checkpoint pull is rate-limited/gated
|
| 29 |
ipc: host
|
| 30 |
shm_size: "16gb"
|
|
@@ -36,6 +42,6 @@ services:
|
|
| 36 |
reservations:
|
| 37 |
devices:
|
| 38 |
- driver: nvidia
|
| 39 |
-
count: all
|
| 40 |
capabilities: [gpu]
|
| 41 |
restart: unless-stopped
|
|
|
|
| 1 |
+
# ROMA inference on 4x Quadro RTX 6000 (Turing, x86_64).
|
| 2 |
+
# Usage (run from the repo root on the workstation):
|
| 3 |
+
# docker compose -f docker/docker-rtx6000/docker-compose.yml build
|
| 4 |
+
# docker compose -f docker/docker-rtx6000/docker-compose.yml run --rm --service-ports roma bash
|
| 5 |
services:
|
| 6 |
roma:
|
| 7 |
build:
|
| 8 |
+
dockerfile: ./docker/docker-rtx6000/Dockerfile
|
| 9 |
context: ../..
|
| 10 |
args:
|
| 11 |
+
BASE_IMAGE: nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04
|
| 12 |
TRANSFORMERS_REF: roma_patch
|
| 13 |
PIP_INDEX: https://pypi.org/simple
|
| 14 |
+
TORCH_INDEX: https://download.pytorch.org/whl/cu124
|
| 15 |
+
image: roma-rtx6000:latest
|
| 16 |
+
container_name: roma-rtx6000
|
| 17 |
volumes:
|
| 18 |
# ~16-22GB checkpoint, HF cache and demo media live on the host, not in the image.
|
| 19 |
- ../../whole_model:/app/whole_model
|
|
|
|
| 26 |
environment:
|
| 27 |
- GRADIO_SERVER_NAME=0.0.0.0
|
| 28 |
- HF_HUB_ENABLE_HF_TRANSFER=1
|
| 29 |
+
# fp16 sharded across all 4 GPUs (no quantization). See README-RTX6000.md for fallbacks.
|
| 30 |
+
- ROMA_DTYPE=float16
|
| 31 |
+
- ROMA_ATTN=sdpa
|
| 32 |
+
- ROMA_LOAD_8BIT=0
|
| 33 |
+
# NOTE: intentionally NOT setting CUDA_VISIBLE_DEVICES, so device_map="auto" shards across all 4 GPUs.
|
| 34 |
# - HF_TOKEN=${HF_TOKEN} # uncomment if the checkpoint pull is rate-limited/gated
|
| 35 |
ipc: host
|
| 36 |
shm_size: "16gb"
|
|
|
|
| 42 |
reservations:
|
| 43 |
devices:
|
| 44 |
- driver: nvidia
|
| 45 |
+
count: all # all 4 Quadro RTX 6000 cards
|
| 46 |
capabilities: [gpu]
|
| 47 |
restart: unless-stopped
|
gradio/mme.py
CHANGED
|
@@ -4,7 +4,7 @@ import os
|
|
| 4 |
from io import BytesIO
|
| 5 |
from urllib.request import urlopen
|
| 6 |
from qwen_vl_utils import process_vision_info
|
| 7 |
-
from transformers import Qwen2_5OmniProcessor, Qwen2_5OmniModel, AutoTokenizer, AutoProcessor, Qwen2_5OmniThinkerModel
|
| 8 |
from src.llamafactory.model.loader import patch_tokenizer, patch_processor
|
| 9 |
from src.llamafactory.data.template import get_template_and_fix_tokenizer
|
| 10 |
from argparse import Namespace, ArgumentParser
|
|
@@ -45,13 +45,24 @@ args = parser.parse_args()
|
|
| 45 |
#print(f"正在使用设备: {device}")
|
| 46 |
|
| 47 |
print(f"从 '{args.model_path}' 加载模型")
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
device_map=
|
| 52 |
-
|
| 53 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
# if not hasattr(model.thinker, "gate_head"):
|
| 56 |
# H = model.thinker.config.get_text_config().hidden_size
|
| 57 |
# device = next(model.parameters()).device
|
|
|
|
| 4 |
from io import BytesIO
|
| 5 |
from urllib.request import urlopen
|
| 6 |
from qwen_vl_utils import process_vision_info
|
| 7 |
+
from transformers import Qwen2_5OmniProcessor, Qwen2_5OmniModel, AutoTokenizer, AutoProcessor, Qwen2_5OmniThinkerModel, BitsAndBytesConfig
|
| 8 |
from src.llamafactory.model.loader import patch_tokenizer, patch_processor
|
| 9 |
from src.llamafactory.data.template import get_template_and_fix_tokenizer
|
| 10 |
from argparse import Namespace, ArgumentParser
|
|
|
|
| 45 |
#print(f"正在使用设备: {device}")
|
| 46 |
|
| 47 |
print(f"从 '{args.model_path}' 加载模型")
|
| 48 |
+
# Hardware-agnostic, env-driven loader. Defaults are Turing-safe (Quadro RTX 6000, sm_75):
|
| 49 |
+
# ROMA_DTYPE=float16 (bf16 is not accelerated on Turing)
|
| 50 |
+
# ROMA_ATTN=sdpa (FlashAttention-2 is unsupported on Turing; use eager if sdpa fails)
|
| 51 |
+
# ROMA_LOAD_8BIT=0 (fp16 sharded across all visible GPUs via device_map=auto; set 1 for 1-GPU)
|
| 52 |
+
_DTYPE = {"float16": torch.float16, "bfloat16": torch.bfloat16, "auto": "auto"}[os.environ.get("ROMA_DTYPE", "float16")]
|
| 53 |
+
_load_kwargs = dict(
|
| 54 |
+
torch_dtype=_DTYPE,
|
| 55 |
+
device_map="auto",
|
| 56 |
+
attn_implementation=os.environ.get("ROMA_ATTN", "sdpa"),
|
| 57 |
+
trust_remote_code=True,
|
| 58 |
)
|
| 59 |
+
if os.environ.get("ROMA_LOAD_8BIT", "0") == "1":
|
| 60 |
+
_load_kwargs["quantization_config"] = BitsAndBytesConfig(
|
| 61 |
+
load_in_8bit=True,
|
| 62 |
+
llm_int8_skip_modules=["talker", "token2wav", "visual", "audio_tower",
|
| 63 |
+
"gate_head", "gate_mixer", "gate_head_pro_fc1", "gate_head_pro_fc2"],
|
| 64 |
+
)
|
| 65 |
+
model = Qwen2_5OmniModel.from_pretrained(args.model_path, **_load_kwargs)
|
| 66 |
# if not hasattr(model.thinker, "gate_head"):
|
| 67 |
# H = model.thinker.config.get_text_config().hidden_size
|
| 68 |
# device = next(model.parameters()).device
|
gradio/mme_gradio.py
CHANGED
|
@@ -6,7 +6,7 @@ import json
|
|
| 6 |
import math
|
| 7 |
import soundfile as sf
|
| 8 |
from argparse import Namespace
|
| 9 |
-
from transformers import Qwen2_5OmniModel, AutoTokenizer, AutoProcessor
|
| 10 |
from transformers.cache_utils import DynamicCache
|
| 11 |
from src.llamafactory.model.loader import patch_processor
|
| 12 |
from src.llamafactory.data.template import get_template_and_fix_tokenizer
|
|
@@ -22,13 +22,29 @@ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
|
|
| 22 |
print(f"Loading model from {MODEL_PATH} on {DEVICE}...")
|
| 23 |
|
| 24 |
# ================= Model Loading =================
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
device_map="auto",
|
| 29 |
-
attn_implementation="
|
| 30 |
-
trust_remote_code=True
|
| 31 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
tokenizer = AutoTokenizer.from_pretrained(
|
| 34 |
MODEL_PATH,
|
|
|
|
| 6 |
import math
|
| 7 |
import soundfile as sf
|
| 8 |
from argparse import Namespace
|
| 9 |
+
from transformers import Qwen2_5OmniModel, AutoTokenizer, AutoProcessor, BitsAndBytesConfig
|
| 10 |
from transformers.cache_utils import DynamicCache
|
| 11 |
from src.llamafactory.model.loader import patch_processor
|
| 12 |
from src.llamafactory.data.template import get_template_and_fix_tokenizer
|
|
|
|
| 22 |
print(f"Loading model from {MODEL_PATH} on {DEVICE}...")
|
| 23 |
|
| 24 |
# ================= Model Loading =================
|
| 25 |
+
# Hardware-agnostic, env-driven loader. Defaults are Turing-safe (Quadro RTX 6000, sm_75):
|
| 26 |
+
# ROMA_DTYPE=float16 (bf16 is not accelerated on Turing)
|
| 27 |
+
# ROMA_ATTN=sdpa (FlashAttention-2 is unsupported on Turing; use eager if sdpa fails)
|
| 28 |
+
# ROMA_LOAD_8BIT=0 (fp16 sharded across all visible GPUs via device_map=auto; set 1 for 1-GPU)
|
| 29 |
+
_DTYPE = {"float16": torch.float16, "bfloat16": torch.bfloat16, "auto": "auto"}[os.environ.get("ROMA_DTYPE", "float16")]
|
| 30 |
+
_load_kwargs = dict(
|
| 31 |
+
torch_dtype=_DTYPE,
|
| 32 |
device_map="auto",
|
| 33 |
+
attn_implementation=os.environ.get("ROMA_ATTN", "sdpa"),
|
| 34 |
+
trust_remote_code=True,
|
| 35 |
)
|
| 36 |
+
if os.environ.get("ROMA_LOAD_8BIT", "0") == "1":
|
| 37 |
+
_load_kwargs["quantization_config"] = BitsAndBytesConfig(
|
| 38 |
+
load_in_8bit=True,
|
| 39 |
+
# keep encoders, the gate (Speak Head) and the talker in fp16 for quality/correctness
|
| 40 |
+
llm_int8_skip_modules=["talker", "token2wav", "visual", "audio_tower",
|
| 41 |
+
"gate_head", "gate_mixer", "gate_head_pro_fc1", "gate_head_pro_fc2"],
|
| 42 |
+
)
|
| 43 |
+
model = Qwen2_5OmniModel.from_pretrained(MODEL_PATH, **_load_kwargs)
|
| 44 |
+
try:
|
| 45 |
+
model.disable_talker() # demos only use model.thinker; frees memory. Best-effort (fork API may vary)
|
| 46 |
+
except Exception:
|
| 47 |
+
pass
|
| 48 |
|
| 49 |
tokenizer = AutoTokenizer.from_pretrained(
|
| 50 |
MODEL_PATH,
|
gradio/narration_gradio.py
CHANGED
|
@@ -1,13 +1,14 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import time
|
| 3 |
import os
|
| 4 |
-
|
|
|
|
| 5 |
import torch
|
| 6 |
import json
|
| 7 |
import math
|
| 8 |
import soundfile as sf
|
| 9 |
from argparse import Namespace
|
| 10 |
-
from transformers import Qwen2_5OmniModel, AutoTokenizer, AutoProcessor
|
| 11 |
from src.llamafactory.model.loader import patch_processor
|
| 12 |
from src.llamafactory.data.template import get_template_and_fix_tokenizer
|
| 13 |
|
|
@@ -22,13 +23,29 @@ THRESHOLD = 0.975
|
|
| 22 |
print(f"Loading model from {MODEL_PATH} on {DEVICE}...")
|
| 23 |
|
| 24 |
# ================= Model Loading =================
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
device_map="auto",
|
| 29 |
-
attn_implementation="
|
| 30 |
-
trust_remote_code=True
|
| 31 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
tokenizer = AutoTokenizer.from_pretrained(
|
| 34 |
MODEL_PATH,
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import time
|
| 3 |
import os
|
| 4 |
+
# Do not force a single GPU: leaving CUDA_VISIBLE_DEVICES unset lets device_map="auto" shard across
|
| 5 |
+
# all visible GPUs (needed to fit fp16 on the 4x Quadro RTX 6000). Restrict externally if desired.
|
| 6 |
import torch
|
| 7 |
import json
|
| 8 |
import math
|
| 9 |
import soundfile as sf
|
| 10 |
from argparse import Namespace
|
| 11 |
+
from transformers import Qwen2_5OmniModel, AutoTokenizer, AutoProcessor, BitsAndBytesConfig
|
| 12 |
from src.llamafactory.model.loader import patch_processor
|
| 13 |
from src.llamafactory.data.template import get_template_and_fix_tokenizer
|
| 14 |
|
|
|
|
| 23 |
print(f"Loading model from {MODEL_PATH} on {DEVICE}...")
|
| 24 |
|
| 25 |
# ================= Model Loading =================
|
| 26 |
+
# Hardware-agnostic, env-driven loader. Defaults are Turing-safe (Quadro RTX 6000, sm_75):
|
| 27 |
+
# ROMA_DTYPE=float16 (bf16 is not accelerated on Turing)
|
| 28 |
+
# ROMA_ATTN=sdpa (FlashAttention-2 is unsupported on Turing; use eager if sdpa fails)
|
| 29 |
+
# ROMA_LOAD_8BIT=0 (fp16 sharded across all visible GPUs via device_map=auto; set 1 for 1-GPU)
|
| 30 |
+
_DTYPE = {"float16": torch.float16, "bfloat16": torch.bfloat16, "auto": "auto"}[os.environ.get("ROMA_DTYPE", "float16")]
|
| 31 |
+
_load_kwargs = dict(
|
| 32 |
+
torch_dtype=_DTYPE,
|
| 33 |
device_map="auto",
|
| 34 |
+
attn_implementation=os.environ.get("ROMA_ATTN", "sdpa"),
|
| 35 |
+
trust_remote_code=True,
|
| 36 |
)
|
| 37 |
+
if os.environ.get("ROMA_LOAD_8BIT", "0") == "1":
|
| 38 |
+
_load_kwargs["quantization_config"] = BitsAndBytesConfig(
|
| 39 |
+
load_in_8bit=True,
|
| 40 |
+
# keep encoders, the gate (Speak Head) and the talker in fp16 for quality/correctness
|
| 41 |
+
llm_int8_skip_modules=["talker", "token2wav", "visual", "audio_tower",
|
| 42 |
+
"gate_head", "gate_mixer", "gate_head_pro_fc1", "gate_head_pro_fc2"],
|
| 43 |
+
)
|
| 44 |
+
model = Qwen2_5OmniModel.from_pretrained(MODEL_PATH, **_load_kwargs)
|
| 45 |
+
try:
|
| 46 |
+
model.disable_talker() # demos only use model.thinker; frees memory. Best-effort (fork API may vary)
|
| 47 |
+
except Exception:
|
| 48 |
+
pass
|
| 49 |
|
| 50 |
tokenizer = AutoTokenizer.from_pretrained(
|
| 51 |
MODEL_PATH,
|
gradio/proactive_gradio.py
CHANGED
|
@@ -6,7 +6,7 @@ import json
|
|
| 6 |
import math
|
| 7 |
import soundfile as sf
|
| 8 |
from argparse import Namespace
|
| 9 |
-
from transformers import Qwen2_5OmniModel, AutoTokenizer, AutoProcessor
|
| 10 |
from src.llamafactory.model.loader import patch_processor
|
| 11 |
from src.llamafactory.data.template import get_template_and_fix_tokenizer
|
| 12 |
|
|
@@ -22,13 +22,29 @@ THRESHOLD = 0.6
|
|
| 22 |
print(f"Loading model from {MODEL_PATH} on {DEVICE}...")
|
| 23 |
|
| 24 |
# ================= Model Loading =================
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
device_map="auto",
|
| 29 |
-
attn_implementation="
|
| 30 |
-
trust_remote_code=True
|
| 31 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
tokenizer = AutoTokenizer.from_pretrained(
|
| 34 |
MODEL_PATH,
|
|
|
|
| 6 |
import math
|
| 7 |
import soundfile as sf
|
| 8 |
from argparse import Namespace
|
| 9 |
+
from transformers import Qwen2_5OmniModel, AutoTokenizer, AutoProcessor, BitsAndBytesConfig
|
| 10 |
from src.llamafactory.model.loader import patch_processor
|
| 11 |
from src.llamafactory.data.template import get_template_and_fix_tokenizer
|
| 12 |
|
|
|
|
| 22 |
print(f"Loading model from {MODEL_PATH} on {DEVICE}...")
|
| 23 |
|
| 24 |
# ================= Model Loading =================
|
| 25 |
+
# Hardware-agnostic, env-driven loader. Defaults are Turing-safe (Quadro RTX 6000, sm_75):
|
| 26 |
+
# ROMA_DTYPE=float16 (bf16 is not accelerated on Turing)
|
| 27 |
+
# ROMA_ATTN=sdpa (FlashAttention-2 is unsupported on Turing; use eager if sdpa fails)
|
| 28 |
+
# ROMA_LOAD_8BIT=0 (fp16 sharded across all visible GPUs via device_map=auto; set 1 for 1-GPU)
|
| 29 |
+
_DTYPE = {"float16": torch.float16, "bfloat16": torch.bfloat16, "auto": "auto"}[os.environ.get("ROMA_DTYPE", "float16")]
|
| 30 |
+
_load_kwargs = dict(
|
| 31 |
+
torch_dtype=_DTYPE,
|
| 32 |
device_map="auto",
|
| 33 |
+
attn_implementation=os.environ.get("ROMA_ATTN", "sdpa"),
|
| 34 |
+
trust_remote_code=True,
|
| 35 |
)
|
| 36 |
+
if os.environ.get("ROMA_LOAD_8BIT", "0") == "1":
|
| 37 |
+
_load_kwargs["quantization_config"] = BitsAndBytesConfig(
|
| 38 |
+
load_in_8bit=True,
|
| 39 |
+
# keep encoders, the gate (Speak Head) and the talker in fp16 for quality/correctness
|
| 40 |
+
llm_int8_skip_modules=["talker", "token2wav", "visual", "audio_tower",
|
| 41 |
+
"gate_head", "gate_mixer", "gate_head_pro_fc1", "gate_head_pro_fc2"],
|
| 42 |
+
)
|
| 43 |
+
model = Qwen2_5OmniModel.from_pretrained(MODEL_PATH, **_load_kwargs)
|
| 44 |
+
try:
|
| 45 |
+
model.disable_talker() # demos only use model.thinker; frees memory. Best-effort (fork API may vary)
|
| 46 |
+
except Exception:
|
| 47 |
+
pass
|
| 48 |
|
| 49 |
tokenizer = AutoTokenizer.from_pretrained(
|
| 50 |
MODEL_PATH,
|
requirements-gh200.txt → requirements-rtx6000.txt
RENAMED
|
@@ -1,17 +1,15 @@
|
|
| 1 |
-
#
|
| 2 |
#
|
| 3 |
-
#
|
| 4 |
-
#
|
| 5 |
-
#
|
| 6 |
-
#
|
| 7 |
-
# -
|
| 8 |
-
#
|
| 9 |
-
# -
|
| 10 |
-
#
|
| 11 |
-
#
|
| 12 |
-
#
|
| 13 |
-
#
|
| 14 |
-
# Everything else keeps its exact upstream pin for reproducibility.
|
| 15 |
|
| 16 |
accelerate==1.0.1
|
| 17 |
aiofiles==23.2.1
|
|
@@ -28,6 +26,7 @@ attrs==25.3.0
|
|
| 28 |
audioread==3.0.1
|
| 29 |
av==14.0.1
|
| 30 |
bert-score==0.3.13
|
|
|
|
| 31 |
certifi==2025.4.26
|
| 32 |
cffi==1.17.1
|
| 33 |
charset-normalizer==3.4.2
|
|
@@ -111,7 +110,21 @@ ninja==1.11.1.4
|
|
| 111 |
nltk==3.9.1
|
| 112 |
numba==0.61.2
|
| 113 |
numpy==1.26.4
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
nvidia-ml-py==12.575.51
|
|
|
|
|
|
|
|
|
|
| 115 |
nvitop==1.5.1
|
| 116 |
omegaconf==2.3.0
|
| 117 |
openai==1.86.0
|
|
@@ -193,9 +206,14 @@ threadpoolctl==3.6.0
|
|
| 193 |
tiktoken==0.9.0
|
| 194 |
tokenizers==0.21.1
|
| 195 |
tomlkit==0.12.0
|
|
|
|
|
|
|
|
|
|
| 196 |
tornado==6.5.1
|
| 197 |
tqdm==4.65.2
|
| 198 |
traitlets==5.14.3
|
|
|
|
|
|
|
| 199 |
trl==0.9.6
|
| 200 |
typer==0.15.3
|
| 201 |
typing_extensions==4.13.2
|
|
|
|
| 1 |
+
# Requirements for the Quadro RTX 6000 (Turing sm_75, x86_64) Docker image.
|
| 2 |
#
|
| 3 |
+
# Derived from requirements.txt. Because this is x86_64, the original CUDA wheels are valid, so this
|
| 4 |
+
# stays close to the upstream pins. Differences:
|
| 5 |
+
# REMOVED flash_attn==2.7.4.post1 -> FlashAttention-2 has no Turing (sm_75) support and would
|
| 6 |
+
# trigger a failing source build; the demos use sdpa instead.
|
| 7 |
+
# REMOVED liger_kernel, deepspeed -> training-only; not used by the inference/streaming demos.
|
| 8 |
+
# REMOVED xformers -> not used by the demos; avoids an unnecessary heavy dep.
|
| 9 |
+
# REMOVED -e git+...ROMA... -> llamafactory is installed editable from the local checkout.
|
| 10 |
+
# ADDED bitsandbytes>=0.43.0 -> optional 8-bit fallback (ROMA_LOAD_8BIT=1) for few-GPU runs.
|
| 11 |
+
# Kept: official torch/vision/audio 2.6.0+cu124 (include sm_75 kernels), the nvidia-*-cu12 wheels
|
| 12 |
+
# (valid on x86), and the transformers@roma_patch fork.
|
|
|
|
|
|
|
| 13 |
|
| 14 |
accelerate==1.0.1
|
| 15 |
aiofiles==23.2.1
|
|
|
|
| 26 |
audioread==3.0.1
|
| 27 |
av==14.0.1
|
| 28 |
bert-score==0.3.13
|
| 29 |
+
bitsandbytes>=0.43.0
|
| 30 |
certifi==2025.4.26
|
| 31 |
cffi==1.17.1
|
| 32 |
charset-normalizer==3.4.2
|
|
|
|
| 110 |
nltk==3.9.1
|
| 111 |
numba==0.61.2
|
| 112 |
numpy==1.26.4
|
| 113 |
+
nvidia-cublas-cu12==12.4.5.8
|
| 114 |
+
nvidia-cuda-cupti-cu12==12.4.127
|
| 115 |
+
nvidia-cuda-nvrtc-cu12==12.4.127
|
| 116 |
+
nvidia-cuda-runtime-cu12==12.4.127
|
| 117 |
+
nvidia-cudnn-cu12==9.1.0.70
|
| 118 |
+
nvidia-cufft-cu12==11.2.1.3
|
| 119 |
+
nvidia-cufile-cu12==1.11.1.6
|
| 120 |
+
nvidia-curand-cu12==10.3.5.147
|
| 121 |
+
nvidia-cusolver-cu12==11.6.1.9
|
| 122 |
+
nvidia-cusparse-cu12==12.3.1.170
|
| 123 |
+
nvidia-cusparselt-cu12==0.6.2
|
| 124 |
nvidia-ml-py==12.575.51
|
| 125 |
+
nvidia-nccl-cu12==2.21.5
|
| 126 |
+
nvidia-nvjitlink-cu12==12.4.127
|
| 127 |
+
nvidia-nvtx-cu12==12.4.127
|
| 128 |
nvitop==1.5.1
|
| 129 |
omegaconf==2.3.0
|
| 130 |
openai==1.86.0
|
|
|
|
| 206 |
tiktoken==0.9.0
|
| 207 |
tokenizers==0.21.1
|
| 208 |
tomlkit==0.12.0
|
| 209 |
+
torch==2.6.0+cu124
|
| 210 |
+
torchaudio==2.6.0+cu124
|
| 211 |
+
torchvision==0.21.0+cu124
|
| 212 |
tornado==6.5.1
|
| 213 |
tqdm==4.65.2
|
| 214 |
traitlets==5.14.3
|
| 215 |
+
transformers @ git+https://github.com/Eureka-Maggie/transformers.git@roma_patch
|
| 216 |
+
triton==3.2.0
|
| 217 |
trl==0.9.6
|
| 218 |
typer==0.15.3
|
| 219 |
typing_extensions==4.13.2
|
scripts/{gh200 → rtx6000}/download_model.sh
RENAMED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
# Download the released ROMA checkpoint (EurekaTian/ROMA, ~16-22GB bf16 safetensors) into the
|
| 3 |
-
#
|
| 4 |
# Run this INSIDE the container (working dir /app). Re-runs resume/skip already-downloaded files.
|
| 5 |
set -euo pipefail
|
| 6 |
|
|
@@ -12,7 +12,6 @@ export HF_HUB_ENABLE_HF_TRANSFER="${HF_HUB_ENABLE_HF_TRANSFER:-1}"
|
|
| 12 |
echo "Downloading ${REPO_ID} -> ${TARGET_DIR}"
|
| 13 |
mkdir -p "${TARGET_DIR}"
|
| 14 |
|
| 15 |
-
# Pass --token only if HF_TOKEN is set (in case the repo is gated/rate-limited).
|
| 16 |
TOKEN_ARGS=()
|
| 17 |
if [[ -n "${HF_TOKEN:-}" ]]; then
|
| 18 |
TOKEN_ARGS=(--token "${HF_TOKEN}")
|
|
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
# Download the released ROMA checkpoint (EurekaTian/ROMA, ~16-22GB bf16 safetensors) into the
|
| 3 |
+
# location the demos expect by default: whole_model/model.
|
| 4 |
# Run this INSIDE the container (working dir /app). Re-runs resume/skip already-downloaded files.
|
| 5 |
set -euo pipefail
|
| 6 |
|
|
|
|
| 12 |
echo "Downloading ${REPO_ID} -> ${TARGET_DIR}"
|
| 13 |
mkdir -p "${TARGET_DIR}"
|
| 14 |
|
|
|
|
| 15 |
TOKEN_ARGS=()
|
| 16 |
if [[ -n "${HF_TOKEN:-}" ]]; then
|
| 17 |
TOKEN_ARGS=(--token "${HF_TOKEN}")
|
scripts/{gh200 → rtx6000}/run_demo.sh
RENAMED
|
@@ -1,27 +1,33 @@
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
-
# Launch a ROMA real-time demo. Run INSIDE the container (
|
| 3 |
#
|
| 4 |
# Usage:
|
| 5 |
-
# bash scripts/
|
| 6 |
#
|
| 7 |
-
#
|
| 8 |
-
# proactive - real-time proactive event alert (
|
| 9 |
# narration - real-time streaming narration (threshold 0.975)
|
| 10 |
# mme - reactive multimodal QA
|
| 11 |
#
|
| 12 |
-
#
|
| 13 |
-
#
|
| 14 |
-
#
|
| 15 |
-
#
|
| 16 |
-
# GRADIO_SERVER_PORT (default: 7860)
|
| 17 |
#
|
| 18 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
set -euo pipefail
|
| 20 |
|
| 21 |
-
#
|
| 22 |
cd "$(dirname "$0")/../.."
|
| 23 |
|
| 24 |
DEMO="${1:-proactive}"
|
|
|
|
|
|
|
|
|
|
| 25 |
export GRADIO_SERVER_NAME="${GRADIO_SERVER_NAME:-0.0.0.0}"
|
| 26 |
export GRADIO_SERVER_PORT="${GRADIO_SERVER_PORT:-7860}"
|
| 27 |
|
|
@@ -34,9 +40,9 @@ esac
|
|
| 34 |
|
| 35 |
MODEL_PATH="${ROMA_MODEL_PATH:-whole_model/model}"
|
| 36 |
if [[ ! -e "${MODEL_PATH}/config.json" ]]; then
|
| 37 |
-
echo "ERROR: no model at '${MODEL_PATH}'. Run scripts/
|
| 38 |
exit 1
|
| 39 |
fi
|
| 40 |
|
| 41 |
-
echo "Launching '${DEMO}' demo -> http://<host>:${GRADIO_SERVER_PORT}"
|
| 42 |
exec python "${SCRIPT}"
|
|
|
|
| 1 |
#!/usr/bin/env bash
|
| 2 |
+
# Launch a ROMA real-time demo on the 4x Quadro RTX 6000. Run INSIDE the container (workdir /app).
|
| 3 |
#
|
| 4 |
# Usage:
|
| 5 |
+
# bash scripts/rtx6000/run_demo.sh [proactive|narration|mme]
|
| 6 |
#
|
| 7 |
+
# Demos (default: proactive):
|
| 8 |
+
# proactive - real-time proactive event alert (Speak Head fires above threshold 0.6)
|
| 9 |
# narration - real-time streaming narration (threshold 0.975)
|
| 10 |
# mme - reactive multimodal QA
|
| 11 |
#
|
| 12 |
+
# Turing-safe defaults (override via env before calling):
|
| 13 |
+
# ROMA_DTYPE=float16 (set bfloat16 if fp16 produces NaN gate probs; slower on Turing)
|
| 14 |
+
# ROMA_ATTN=sdpa (set eager if the transformers fork rejects sdpa)
|
| 15 |
+
# ROMA_LOAD_8BIT=0 (fp16 sharded across all visible GPUs; see note below)
|
|
|
|
| 16 |
#
|
| 17 |
+
# GPUs: by default ALL visible GPUs are used (device_map="auto" shards the ~22GB fp16 model across
|
| 18 |
+
# the 4 cards). To restrict to fewer GPUs, export CUDA_VISIBLE_DEVICES and enable 8-bit, e.g.:
|
| 19 |
+
# CUDA_VISIBLE_DEVICES=0 ROMA_LOAD_8BIT=1 bash scripts/rtx6000/run_demo.sh proactive
|
| 20 |
+
#
|
| 21 |
+
# Then open http://<host>:${GRADIO_SERVER_PORT:-7860}
|
| 22 |
set -euo pipefail
|
| 23 |
|
| 24 |
+
# Run from the repo root so the demos' "from src.llamafactory ..." imports resolve.
|
| 25 |
cd "$(dirname "$0")/../.."
|
| 26 |
|
| 27 |
DEMO="${1:-proactive}"
|
| 28 |
+
export ROMA_DTYPE="${ROMA_DTYPE:-float16}"
|
| 29 |
+
export ROMA_ATTN="${ROMA_ATTN:-sdpa}"
|
| 30 |
+
export ROMA_LOAD_8BIT="${ROMA_LOAD_8BIT:-0}"
|
| 31 |
export GRADIO_SERVER_NAME="${GRADIO_SERVER_NAME:-0.0.0.0}"
|
| 32 |
export GRADIO_SERVER_PORT="${GRADIO_SERVER_PORT:-7860}"
|
| 33 |
|
|
|
|
| 40 |
|
| 41 |
MODEL_PATH="${ROMA_MODEL_PATH:-whole_model/model}"
|
| 42 |
if [[ ! -e "${MODEL_PATH}/config.json" ]]; then
|
| 43 |
+
echo "ERROR: no model at '${MODEL_PATH}'. Run scripts/rtx6000/download_model.sh first." >&2
|
| 44 |
exit 1
|
| 45 |
fi
|
| 46 |
|
| 47 |
+
echo "Launching '${DEMO}' demo (dtype=${ROMA_DTYPE} attn=${ROMA_ATTN} 8bit=${ROMA_LOAD_8BIT}) -> http://<host>:${GRADIO_SERVER_PORT}"
|
| 48 |
exec python "${SCRIPT}"
|