Skip to content

Commit 9fcbba2

Browse files
authored
Merge pull request #14 from deepinfra/johan/cosmos3-framework-worker
feat: Cosmos3 videogen worker on public cosmos-framework (overlay)
2 parents 082829b + 78aa7cf commit 9fcbba2

5 files changed

Lines changed: 930 additions & 0 deletions

File tree

‎examples/cosmos3/Dockerfile‎

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# DeepInfra Cosmos3 Dynamo videogen worker image.
2+
#
3+
# Overlay build: clones NVIDIA/cosmos-framework at a pinned ref, applies the
4+
# reviewed patches from ./patches, then follows upstream's own Dockerfile steps
5+
# (same base image, uv-managed env) and bakes in the DeepInfra worker.
6+
# There is no DeepInfra copy of the framework repo — this directory plus the
7+
# pin below is the complete, reviewable definition of the image.
8+
#
9+
# Build (from this directory; token file must hold an HF token whose account
10+
# has accepted the nvidia/Cosmos-Guardrail1 auto-gate — the secret mount keeps
11+
# it out of image layers and history):
12+
# docker build --secret id=hf_token,src=/path/to/token-file \
13+
# -t localhost:30500/cosmos3-worker:v1 .
14+
15+
ARG CUDA_VERSION=13.0.2
16+
ARG BASE_IMAGE=nvidia/cuda:${CUDA_VERSION}-cudnn-devel-ubuntu24.04
17+
FROM ${BASE_IMAGE}
18+
19+
ENV DEBIAN_FRONTEND=noninteractive
20+
21+
RUN --mount=type=cache,target=/var/cache/apt \
22+
--mount=type=cache,target=/var/lib/apt \
23+
apt-get update && \
24+
apt-get install -y --no-install-recommends \
25+
curl \
26+
ffmpeg \
27+
git \
28+
git-lfs \
29+
tree \
30+
wget
31+
32+
COPY --from=ghcr.io/astral-sh/uv:0.10.8 /uv /uvx /usr/local/bin/
33+
ENV UV_LINK_MODE=copy
34+
ENV UV_PYTHON_CACHE_DIR=/root/.cache/uv/python
35+
ENV PATH="/root/.local/bin:$PATH"
36+
37+
# Upstream pin. Bumping this ref is THE upstream-update mechanism; if a patch
38+
# in ./patches stops applying, the build fails loudly and the patch must be
39+
# rebased (or dropped because upstream absorbed the fix).
40+
ARG COSMOS_FRAMEWORK_REPO=https://github.com/NVIDIA/cosmos-framework.git
41+
ARG COSMOS_FRAMEWORK_REF=463ac142b47c637098a7e86d0631252f82b65418
42+
43+
WORKDIR /workspace
44+
RUN git clone --filter=blob:none ${COSMOS_FRAMEWORK_REPO} /workspace && \
45+
git -C /workspace checkout ${COSMOS_FRAMEWORK_REF}
46+
47+
# Upstream build steps (mirrors NVIDIA/cosmos-framework Dockerfile @ the pin,
48+
# minus bind-mounts: the sources are already in the layer from the clone).
49+
# NOTE: patches are applied LAST (near the entrypoint), not here. cosmos_framework
50+
# is installed editable (`uv pip install -e`), so patching /workspace afterward is
51+
# picked up live at runtime — and keeping the patch layer last means editing a
52+
# patch rebuilds in seconds instead of re-running the ~11GB gated HF prefetch.
53+
RUN --mount=type=cache,target=/root/.cache/uv uv python install
54+
RUN echo "$CUDA_VERSION" | sed -E 's/^([0-9]+)\.([0-9]+).*/cu\1\2/' > /root/.cuda-name
55+
RUN --mount=type=cache,target=/root/.cache/uv \
56+
uv sync --locked --no-install-project --no-editable --all-extras --group=$(cat /root/.cuda-name)
57+
ENV PATH="/workspace/.venv/bin:$PATH"
58+
59+
# Triton bundled ptxas doesn't support latest GPU architectures
60+
ENV TRITON_PTXAS_PATH="/usr/local/cuda/bin/ptxas"
61+
62+
# Serving deps. fastapi/uvicorn for standalone mode; ai-dynamo + uvloop for
63+
# production Dynamo mode. ai-dynamo provides the DistributedRuntime, frontend
64+
# binary, and endpoint registration used by the videogen worker pattern.
65+
RUN --mount=type=cache,target=/root/.cache/uv \
66+
uv pip install fastapi uvicorn ai-dynamo==1.1.1 uvloop
67+
68+
# Pre-install the HF CLI tool so that `uvx hf@1.13.0` reuses this
69+
# installation instead of creating an ephemeral env missing `click`.
70+
RUN --mount=type=cache,target=/root/.cache/uv \
71+
uv tool install hf@1.13.0 --with click
72+
73+
RUN --mount=type=cache,target=/root/.cache/uv \
74+
uv pip install --no-deps -e /workspace
75+
76+
# Pre-fetch HuggingFace dependencies needed by cosmos_framework at model init
77+
# time: Qwen tokenizer configs (*.json, *.txt — few MB), Wan VAE checkpoints,
78+
# and the full Cosmos-Guardrail1 snapshot (the one gated repo — auto-approve
79+
# gate; the token account must have accepted it). The token comes in via a
80+
# BuildKit secret mount so it never persists in a layer or in image history.
81+
# This eliminates any runtime dependency on HuggingFace availability.
82+
# Revisions MUST match the pins in
83+
# cosmos_framework/inference/common/checkpoints.py and
84+
# cosmos_framework/auxiliary/guardrail/common/core.py at the ref above — the
85+
# runtime looks up these exact revisions; a mismatch silently falls back to a
86+
# live (unauthenticated, rate-limited) HF fetch at every pod boot.
87+
RUN --mount=type=secret,id=hf_token \
88+
export HF_TOKEN=$(cat /run/secrets/hf_token 2>/dev/null || true) && \
89+
uvx hf@1.13.0 download --format=json \
90+
Qwen/Qwen3-0.6B \
91+
--repo-type model \
92+
--revision c1899de289a04d12100db370d81485cdf75e47ca \
93+
--include '*.json' --include '*.txt' && \
94+
uvx hf@1.13.0 download --format=json \
95+
Qwen/Qwen3-VL-2B-Instruct \
96+
--repo-type model \
97+
--revision 89644892e4d85e24eaac8bacfd4f463576704203 \
98+
--include '*.json' --include '*.txt' && \
99+
uvx hf@1.13.0 download --format=json \
100+
Qwen/Qwen3-VL-8B-Instruct \
101+
--repo-type model \
102+
--revision 0c351dd01ed87e9c1b53cbc748cba10e6187ff3b \
103+
--include '*.json' --include '*.txt' && \
104+
uvx hf@1.13.0 download --format=json \
105+
Qwen/Qwen3-VL-32B-Instruct \
106+
--repo-type model \
107+
--revision 0cfaf48183f594c314753d30a4c4974bc75f3ccb \
108+
--include '*.json' --include '*.txt' && \
109+
uvx hf@1.13.0 download --format=json \
110+
Wan-AI/Wan2.1-T2V-14B \
111+
--repo-type model \
112+
--revision a064a6c71f5be440641209c07bf2a5ce7a2ff5e4 \
113+
Wan2.1_VAE.pth && \
114+
uvx hf@1.13.0 download --format=json \
115+
Wan-AI/Wan2.2-TI2V-5B \
116+
--repo-type model \
117+
--revision 921dbaf3f1674a56f47e83fb80a34bac8a8f203e \
118+
Wan2.2_VAE.pth && \
119+
uvx hf@1.13.0 download --format=json \
120+
nvidia/Cosmos-Guardrail1 \
121+
--repo-type model \
122+
--revision d6d4bfa899a71454a700907664f3e88f503950cf
123+
124+
# DeepInfra runtime settings.
125+
# - LD_LIBRARY_PATH is cleared so the venv/CUDA libs resolve without host leakage.
126+
# - torch.compile (inductor) and triton write kernel caches to a persistent
127+
# mountable location instead of an ephemeral home dir.
128+
ENV LD_LIBRARY_PATH=""
129+
ENV TORCHINDUCTOR_CACHE_DIR="/cache/torchinductor"
130+
ENV TRITON_CACHE_DIR="/cache/triton"
131+
RUN mkdir -p /cache/torchinductor /cache/triton
132+
133+
# DeepInfra patches to upstream code (reviewed in deepinfra/dynamo). Applied
134+
# last so a patch edit doesn't invalidate the expensive prefetch layer above;
135+
# the editable install makes them live at runtime. Fails loudly if a patch no
136+
# longer applies against COSMOS_FRAMEWORK_REF (the signal to rebase or drop it).
137+
COPY patches /workspace/deepinfra-patches
138+
RUN git -C /workspace apply --verbose deepinfra-patches/*.patch
139+
140+
# DeepInfra Dynamo videogen worker. Runtime args
141+
# (--served-model-name, --model, --num-gpus, ...) are appended to this command.
142+
# worker.py self-relaunches under torchrun when --num-gpus > 1.
143+
COPY worker.py /workspace/worker.py
144+
ENTRYPOINT ["python3", "worker.py"]

‎examples/cosmos3/README.md‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Cosmos3 Dynamo videogen worker (public cosmos-framework)
2+
3+
DeepInfra serving overlay for `nvidia/Cosmos3-Nano` and `nvidia/Cosmos3-Super`
4+
on NVIDIA's **public** [cosmos-framework](https://github.com/NVIDIA/cosmos-framework),
5+
replacing the retired private EA fork (`deepinfra/cosmos3`, archived — see
6+
provenance below).
7+
8+
## What lives here
9+
10+
- `worker.py` — the Dynamo videogen worker: registers with the Dynamo frontend
11+
(`ModelType.Videos`), translates deepapi requests to
12+
`cosmos_framework.inference` calls, multi-GPU via torchrun with a gloo
13+
control-plane group (idle NCCL-watchdog fix). `--standalone` runs a plain
14+
FastAPI server for testing without any Dynamo infra.
15+
- `Dockerfile` — overlay build: clones cosmos-framework at the pinned
16+
`COSMOS_FRAMEWORK_REF`, applies `patches/`, runs upstream's own build steps,
17+
bakes worker + HF prefetch (incl. gated `nvidia/Cosmos-Guardrail1`; the build
18+
`HF_TOKEN` account must have accepted that repo's auto-approve gate).
19+
- `patches/` — the complete set of in-tree changes to upstream:
20+
- `0001-cap-encoder-threads.patch` — cap libx264 `-threads` (default 32,
21+
`DI_VIDEO_ENCODE_THREADS` to override) so mp4 encode doesn't grab every
22+
core on shared multi-GPU nodes.
23+
24+
## Updating upstream
25+
26+
Bump `COSMOS_FRAMEWORK_REF` in the Dockerfile and rebuild. If a patch fails to
27+
apply, the build fails: rebase the patch, or delete it if upstream absorbed
28+
the fix.
29+
30+
## Provenance
31+
32+
The EA-era history (19 PRs) lives in the archived private repo
33+
`deepinfra/cosmos3`. Sixteen of those PRs were shims to load the public
34+
diffusers weights on the private EA code — all obsolete: the public framework
35+
loads the public checkpoints natively, ships the audio (AVAE) tokenizer,
36+
fixes the discarded-parallelism-config bug (`inference/model.py`, fixed
37+
upstream), and enables guardrails by default. What survives is `worker.py`
38+
(EA PRs #1/#18), the encoder-thread cap (EA PR #19, now `patches/0001`), and
39+
the Dockerfile's prefetch/bake strategy.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
diff --git a/cosmos_framework/utils/easy_io/handlers/imageio_video_handler.py b/cosmos_framework/utils/easy_io/handlers/imageio_video_handler.py
2+
index fdc944f..359d016 100644
3+
--- a/cosmos_framework/utils/easy_io/handlers/imageio_video_handler.py
4+
+++ b/cosmos_framework/utils/easy_io/handlers/imageio_video_handler.py
5+
@@ -1,6 +1,7 @@
6+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
7+
# SPDX-License-Identifier: OpenMDW-1.1
8+
9+
+import os
10+
from typing import IO, Any, Dict, Tuple
11+
12+
import imageio
13+
@@ -171,6 +172,17 @@ class ImageioVideoHandler(BaseFileHandler):
14+
}
15+
# Update with any other kwargs
16+
mimsave_kwargs.update(kwargs)
17+
+
18+
+ # deepinfra: cap CPU encoder threads (covers the crf and qscale branches
19+
+ # above, plus any caller-supplied ffmpeg_params). With no -threads, x264
20+
+ # auto-detects every core and oversubscribes on shared multi-GPU nodes
21+
+ # (8 GPUs / 224 cores), contending with neighbouring pods so encode
22+
+ # latency drifts with node load. Override via DI_VIDEO_ENCODE_THREADS.
23+
+ _params = list(mimsave_kwargs.get("ffmpeg_params") or [])
24+
+ if "-threads" not in _params:
25+
+ _params += ["-threads", os.getenv("DI_VIDEO_ENCODE_THREADS", "32")]
26+
+ mimsave_kwargs["ffmpeg_params"] = _params
27+
+
28+
log.debug(f"mimsave_kwargs: {mimsave_kwargs}")
29+
30+
imageio.mimsave(file, obj, format, **mimsave_kwargs)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
diff --git a/cosmos_framework/auxiliary/guardrail/common/presets.py b/cosmos_framework/auxiliary/guardrail/common/presets.py
2+
index 8536685..932daa5 100644
3+
--- a/cosmos_framework/auxiliary/guardrail/common/presets.py
4+
+++ b/cosmos_framework/auxiliary/guardrail/common/presets.py
5+
@@ -21,13 +21,22 @@ def create_text_guardrail_runner(offload_model_to_cpu: bool = False) -> Guardrai
6+
7+
8+
def create_video_guardrail_runner(offload_model_to_cpu: bool = False) -> GuardrailRunner:
9+
- """Create the video guardrail runner."""
10+
+ """Create the video guardrail runner.
11+
+
12+
+ deepinfra: the RetinaFace face-blur postprocessor is intentionally removed.
13+
+ It unconditionally pixelates every detected face in every output frame,
14+
+ which breaks the product (people are a core use case) and is a privacy/
15+
+ anti-deepfake measure, not a content-safety control. The content-safety
16+
+ value lives in the text-prompt guardrail (Blocklist + Qwen3Guard), which is
17+
+ unchanged. Upstream's VideoContentSafetyFilter is already disabled by NVIDIA
18+
+ (false positives), so the video runner is now a no-op passthrough.
19+
+ """
20+
return GuardrailRunner(
21+
safety_models=[
22+
# VideoContentSafetyFilter(offload_model_to_cpu=offload_model_to_cpu)
23+
# Too many false positives, add back when fixed
24+
],
25+
- postprocessors=[RetinaFaceFilter(offload_model_to_cpu=offload_model_to_cpu)],
26+
+ postprocessors=[],
27+
)
28+
29+

0 commit comments

Comments
 (0)