Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
59e9a85
Add fake demo runtime vertical slice
jarcherNV Aug 9, 2026
42c7859
Fix demo session invariant cleanup
jarcherNV Aug 9, 2026
539911e
Finalize direct demo driver invariant failures
jarcherNV Aug 9, 2026
d06df9f
Add RuntimeHost worker boundary
jarcherNV Aug 9, 2026
d661edb
Apply Phase 3 test import formatting
jarcherNV Aug 9, 2026
dbf33a9
runtime: extract demo run mode session helpers
jarcherNV Aug 9, 2026
6f83fdf
runtime: finalize session edges when invariant cleanup dispatch fails
jarcherNV Aug 9, 2026
631963b
runtime: guard cleanup error recording during teardown
jarcherNV Aug 9, 2026
dbfd430
runtime: add realtime timing contracts
jarcherNV Aug 9, 2026
d1cb914
runtime: add realtime session driver
jarcherNV Aug 9, 2026
3b08bd3
runtime: clarify unavailable host cleanup
jarcherNV Aug 9, 2026
b856f48
runtime: harden batch cleanup finalization
jarcherNV Aug 9, 2026
4a3b807
runtime: split demo step requirements from input windows
jarcherNV Aug 9, 2026
19a4449
runtime: add MP4 and null demo output sinks
jarcherNV Aug 9, 2026
9d3afd9
runtime: add demo capability validation
jarcherNV Aug 9, 2026
b16920e
runtime: avoid serving dependency in demo timing
jarcherNV Aug 9, 2026
a9d3860
runtime: split demo warmup setup
jarcherNV Aug 9, 2026
c8314f9
runtime: guard run cleanup telemetry failures
jarcherNV Aug 9, 2026
7f36767
Phase 10: unify demo metrics and error policies
jarcherNV Aug 9, 2026
5abea73
Phase 11: extract legacy runner onto shared batch path
jarcherNV Aug 9, 2026
386e9b0
Phase 11.5: adopt shared replay output sinks
jarcherNV Aug 9, 2026
42eeaaf
Phase 12: decompose shared WebRTC session edges
jarcherNV Aug 9, 2026
75a2a7d
runtime: fix WebRTC service import ordering
jarcherNV Aug 9, 2026
60bef84
runtime: harden realtime WebRTC service contracts
jarcherNV Aug 9, 2026
6ca870c
runtime: route WebRTC sessions through realtime driver
jarcherNV Aug 9, 2026
b137f75
runtime: shield async invariant cleanup
jarcherNV Aug 9, 2026
f021b99
runtime: attempt provider cleanup after session timeout
jarcherNV Aug 9, 2026
eb57155
Reshape OmniDreams replay runtime toward shared contract
jarcherNV Aug 9, 2026
03de4c5
Wire OmniDreams precomputed HDMaps through provider
jarcherNV Aug 9, 2026
3affc4f
Fix provider cleanup after session close timeout
jarcherNV Aug 9, 2026
19a5727
Add OmniDreams replay null output mode
jarcherNV Aug 9, 2026
62c3b79
Shield pre-edge provider cleanup from cancellation
jarcherNV Aug 9, 2026
f988ce4
Preserve worker affinity for cleanup timeouts
jarcherNV Aug 9, 2026
c3609f7
Mark cleanup dispatch failures unhealthy
jarcherNV Aug 9, 2026
e976b44
Document worker-affine cleanup timeout tradeoff
jarcherNV Aug 9, 2026
d7b39fd
Phase 14: add OmniDreams Ludus replay provider
jarcherNV Aug 10, 2026
26735b5
Add OmniDreams Ludus keyboard trace
jarcherNV Aug 10, 2026
758eabe
Mark runtime host unhealthy on cleanup close failures
jarcherNV Aug 10, 2026
84b1a6c
Quarantine runtime host on cleanup failures
jarcherNV Aug 10, 2026
26e4510
Document runtime cleanup quarantine rationale
jarcherNV Aug 10, 2026
1acd7d5
Collapse OmniDreams WebRTC onto shared runtime session
jarcherNV Aug 10, 2026
53c1b9d
Fix OmniDreams WebRTC shared runtime warmup
jarcherNV Aug 10, 2026
8c68f20
Keep OmniDreams WebRTC encoders across warmup
jarcherNV Aug 10, 2026
a2ae69b
Cap OmniDreams WebRTC video display size
jarcherNV Aug 10, 2026
16cd15d
Load OmniDreams WebRTC video sizing stylesheet reliably
jarcherNV Aug 10, 2026
ea817a4
Close async demo provider on pre-driver cancellation
jarcherNV Aug 10, 2026
18e4d36
Route OmniDreams WebRTC through shared realtime driver
jarcherNV Aug 10, 2026
24c6e07
ci: add OmniDreams demo runtime GPU workflow
jarcherNV Aug 10, 2026
1a91935
ci: shorten OmniDreams demo runtime artifacts
jarcherNV Aug 10, 2026
441e1bb
omnidreams: clean up shared demo runtime layout
jarcherNV Aug 10, 2026
1c12ecf
docs: record validated OmniDreams demo commands
jarcherNV Aug 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
328 changes: 328 additions & 0 deletions .github/workflows/omnidreams-demo-runtime.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
name: OmniDreams Demo Runtime

on:
push:
branches:
- main
- "pull-request/[0-9]+"
paths:
- ".github/workflows/omnidreams-demo-runtime.yml"
- "pyproject.toml"
- "uv.lock"
- "flashdreams/pyproject.toml"
- "flashdreams/flashdreams/core/**"
- "flashdreams/flashdreams/infra/**"
- "flashdreams/flashdreams/runtime/**"
- "flashdreams/flashdreams/serving/**"
- "flashdreams/flashdreams/recipes/taehv/**"
- "flashdreams/flashdreams/recipes/wan/**"
- "integrations/omnidreams/**"
- "integrations/lingbot/**"
workflow_dispatch:

permissions:
contents: read

jobs:
demo-runtime:
name: null, precomputed MP4, and Ludus MP4
runs-on: linux-amd64-gpu-rtxpro6000-latest-2
timeout-minutes: 180
defaults:
run:
shell: bash
container:
image: nvidia/cuda:13.2.1-cudnn-devel-ubuntu24.04
options: --gpus all
env:
UV_PROJECT_ENVIRONMENT: /tmp/flashdreams-venv
UV_LINK_MODE: copy
UV_PYTHON: "3.10"
MAX_JOBS: 8
ARTIFACT_DIR: artifacts/omnidreams_demo_runtime
NULL_BLOCKS: "10"
PRECOMPUTED_BLOCKS: "75"
LUDUS_BLOCKS: "76"
FPS: "30"
EXAMPLE_DATA_UUID: 239560dc-33d1-11ef-9720-00044bcbccac
LUDUS_SCENE_UUID: 0d404ff7-2b66-498c-b047-1ed8cded60d4
LUDUS_TRACE: integrations/omnidreams/omnidreams/demo/traces/ludus_forward_sweep_60s.json
EXPECTED_WIDTH: "1280"
EXPECTED_HEIGHT: "704"
MIN_DURATION_SECONDS: "18"
MAX_DURATION_SECONDS: "22"
steps:
- name: Detect GPU architecture
id: gpu-arch
run: |
nvidia-smi
compute_cap=$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader 2>/dev/null | head -1 | tr -d '[:space:]')
arch=$(echo "${compute_cap}" | tr -d '.')
echo "arch=${arch}" >> "$GITHUB_OUTPUT"
echo "Detected GPU compute capability: ${compute_cap} -> sm_${arch}"

- name: Checkout
uses: actions/checkout@v4

- name: Install system dependencies
run: |
apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends \
python3 python3-dev python3-venv \
ffmpeg \
gcc g++ ninja-build \
libnccl-dev \
curl git ca-certificates jq unzip
rm -rf /var/lib/apt/lists/*

- name: Setup proxy cache
uses: nv-gha-runners/setup-proxy-cache@main

- name: Setup uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
cache-suffix: "omnidreams-demo-runtime-sm${{ steps.gpu-arch.outputs.arch }}"
prune-cache: false

- name: Install dependencies
env:
NVTE_CUDA_ARCHS: ${{ steps.gpu-arch.outputs.arch }}
run: |
uv venv --clear
uv sync --locked --extra dev

- name: Verify GPU availability
run: nvidia-smi

- name: Run OmniDreams demo modes
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
run: |
set -uo pipefail

log_dir="${ARTIFACT_DIR}/logs"
output_dir="${ARTIFACT_DIR}/outputs"
summary="${ARTIFACT_DIR}/summary.md"
status_file="${ARTIFACT_DIR}/command-status.env"
mkdir -p "${log_dir}" "${output_dir}"
: > "${status_file}"

odemo() {
uv run --no-sync --package flashdreams-omnidreams omnidreams-demo "$@"
}

run_demo() {
local name="$1"
shift
local log="${log_dir}/${name}.log"

{
printf '$'
printf ' %q' "$@"
printf '\n\n'
"$@"
} 2>&1 | tee "${log}"

local rc="${PIPESTATUS[0]}"
echo "${name}=${rc}" >> "${status_file}"
echo "${name} exit code: ${rc}" | tee -a "${summary}"
return 0
}

{
echo "# OmniDreams Demo Runtime CI"
echo
echo "| Mode | Expected blocks | Output |"
echo "| --- | ---: | --- |"
echo "| null | ${NULL_BLOCKS} | none |"
echo "| precomputed MP4 | ${PRECOMPUTED_BLOCKS} | omnidreams-demo-precomputed-20s.mp4 |"
echo "| Ludus MP4 | ${LUDUS_BLOCKS} | omnidreams-demo-ludus-20s.mp4 |"
echo
echo "## Command Status"
} > "${summary}"

run_demo null \
odemo replay \
--output-mode null \
--device cuda:0 \
--total-blocks "${NULL_BLOCKS}"

run_demo precomputed-mp4 \
odemo replay \
--device cuda:0 \
--example-data \
--example-data-uuid "${EXAMPLE_DATA_UUID}" \
--total-blocks "${PRECOMPUTED_BLOCKS}" \
--fps "${FPS}" \
--output "${output_dir}/omnidreams-demo-precomputed-20s.mp4"

run_demo ludus-mp4 \
odemo replay \
--conditioning-mode ludus-scene-driving \
--keyboard-trace "${LUDUS_TRACE}" \
--device cuda:0 \
--scene-uuid "${LUDUS_SCENE_UUID}" \
--seed 42 \
--total-blocks "${LUDUS_BLOCKS}" \
--output "${output_dir}/omnidreams-demo-ludus-20s.mp4"

- name: Validate OmniDreams demo artifacts
run: |
set -euo pipefail

log_dir="${ARTIFACT_DIR}/logs"
output_dir="${ARTIFACT_DIR}/outputs"
probe_dir="${ARTIFACT_DIR}/ffprobe"
summary="${ARTIFACT_DIR}/summary.md"
status_file="${ARTIFACT_DIR}/command-status.env"
mkdir -p "${probe_dir}"

status_of() {
awk -F= -v name="$1" '$1 == name { print $2 }' "${status_file}"
}

assert_exit_zero() {
local name="$1"
local rc
rc="$(status_of "${name}")"
if [ "${rc}" != "0" ]; then
echo "${name} command failed with exit code ${rc}" >&2
exit 1
fi
}

assert_clean_log() {
local log="$1"
if grep -En "ERROR|Traceback|Exception|status=failed|Run failed|failed run" "${log}"; then
echo "failure marker found in ${log}" >&2
exit 1
fi
}

assert_log_contains() {
local log="$1"
local pattern="$2"
local label="$3"
if ! grep -Eq "${pattern}" "${log}"; then
echo "expected ${label} in ${log}" >&2
exit 1
fi
}

validate_mp4() {
local mode="$1"
local mp4="$2"
local metadata="${probe_dir}/${mode}.json"

if [ ! -s "${mp4}" ]; then
echo "expected non-empty MP4 at ${mp4}" >&2
exit 1
fi

ffprobe \
-v error \
-select_streams v:0 \
-show_entries stream=width,height,r_frame_rate,avg_frame_rate,nb_frames,duration:format=duration \
-of json \
"${mp4}" > "${metadata}"

local stream_count width height duration
stream_count="$(jq '.streams | length' "${metadata}")"
width="$(jq -r '.streams[0].width // ""' "${metadata}")"
height="$(jq -r '.streams[0].height // ""' "${metadata}")"
duration="$(jq -r '.streams[0].duration // .format.duration // "0"' "${metadata}")"

if [ "${stream_count}" -lt 1 ]; then
echo "ffprobe found no video stream in ${mp4}" >&2
exit 1
fi

if [ "${width}" != "${EXPECTED_WIDTH}" ] || [ "${height}" != "${EXPECTED_HEIGHT}" ]; then
echo "unexpected ${mode} resolution ${width}x${height}; expected ${EXPECTED_WIDTH}x${EXPECTED_HEIGHT}" >&2
exit 1
fi

awk \
-v duration="${duration}" \
-v min_duration="${MIN_DURATION_SECONDS}" \
-v max_duration="${MAX_DURATION_SECONDS}" \
'BEGIN {
if ((duration + 0) < min_duration || (duration + 0) > max_duration) {
exit 1
}
}' || {
echo "unexpected ${mode} duration ${duration}s; expected ${MIN_DURATION_SECONDS}-${MAX_DURATION_SECONDS}s" >&2
exit 1
}
}

null_log="${log_dir}/null.log"
precomputed_log="${log_dir}/precomputed-mp4.log"
ludus_log="${log_dir}/ludus-mp4.log"

assert_exit_zero null
assert_exit_zero precomputed-mp4
assert_exit_zero ludus-mp4

assert_clean_log "${null_log}"
assert_clean_log "${precomputed_log}"
assert_clean_log "${ludus_log}"

assert_log_contains "${null_log}" "AR 9 encode" "null final AR block"
assert_log_contains "${null_log}" "OmniDreams demo replay step 9 frames=" "null final replay step"
assert_log_contains "${null_log}" "Loaded OmniDreams demo HDMaps shape=.*views=1" "null precomputed HDMaps"

assert_log_contains "${precomputed_log}" "AR 74 encode" "precomputed final AR block"
assert_log_contains "${precomputed_log}" "OmniDreams demo replay step 74 frames=" "precomputed final replay step"
assert_log_contains "${precomputed_log}" "Loaded OmniDreams demo HDMaps shape=.*views=1" "precomputed HDMaps"

assert_log_contains "${ludus_log}" "AR 75 encode" "Ludus final AR block"
assert_log_contains "${ludus_log}" "OmniDreams demo replay step 75 frames=" "Ludus final replay step"
assert_log_contains "${ludus_log}" "ludus_backend=cuda" "Ludus CUDA backend"
assert_log_contains "${ludus_log}" "trace_events=[1-9][0-9]*" "nonzero Ludus trace events"

validate_mp4 precomputed-mp4 "${output_dir}/omnidreams-demo-precomputed-20s.mp4"
validate_mp4 ludus-mp4 "${output_dir}/omnidreams-demo-ludus-20s.mp4"

{
echo
echo "## Validation"
echo
echo "- All commands exited zero."
echo "- Logs contained expected final AR blocks and provider markers."
echo "- MP4 outputs were non-empty and passed ffprobe stream checks."
} >> "${summary}"

- name: Trim uv cache for upload
if: always()
run: |
cache_dir="${UV_CACHE_DIR:-/github/home/.cache/uv}"
echo "=== Cache size before trim ==="
du -sh "${cache_dir}" || true
du -sh "${cache_dir}"/*/ 2>/dev/null || true

rm -rf "${cache_dir}/wheels-v6"
rm -rf "${cache_dir}/archive-v0"

find "${cache_dir}/git-v0/checkouts" \
\( -name "build" -o -name "*.egg-info" -o -name "__pycache__" \) \
-type d -exec rm -rf {} + 2>/dev/null || true

rm -rf "${cache_dir}/sdists-v9/editable"

echo ""
echo "=== Cache size after trim ==="
du -sh "${cache_dir}" || true
du -sh "${cache_dir}"/*/ 2>/dev/null || true
echo ""
echo "=== Cached built wheels (sdists-v9) ==="
find "${cache_dir}/sdists-v9" -name "*.whl" -exec ls -lh {} \; 2>/dev/null || true

- name: Upload demo runtime artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: omnidreams-demo-runtime
path: ${{ env.ARTIFACT_DIR }}
if-no-files-found: ignore
14 changes: 12 additions & 2 deletions flashdreams/flashdreams/runtime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,20 @@
from flashdreams.runtime.metrics import (
InMemoryMetricsRecorder,
MetricsRecorder,
MetricsSnapshot,
NullMetricsRecorder,
RuntimeMetricSample,
)
from flashdreams.runtime.output import NullOutputTarget, OutputArtifact, OutputTarget
from flashdreams.runtime.runner import run_inference_session
from flashdreams.runtime.types import StepRequest, StepResult
from flashdreams.runtime.types import (
StepRequest,
StepRequirements,
StepResult,
step_requirements_from_request,
)
from flashdreams.runtime.video_output import Mp4VideoOutputTarget
from flashdreams.runtime.worker import ThreadAffineRuntimeWorker
from flashdreams.runtime.worker import ModelExecutionWorker, ThreadAffineRuntimeWorker

__all__ = [
"CanonicalInputs",
Expand Down Expand Up @@ -90,7 +96,9 @@
"KeyboardToDriverCommand",
"MappingCompatibility",
"MetricsRecorder",
"MetricsSnapshot",
"ModelAdapter",
"ModelExecutionWorker",
"Mp4VideoOutputTarget",
"NullMetricsRecorder",
"NullOutputTarget",
Expand All @@ -100,10 +108,12 @@
"RuntimeMetricSample",
"ScriptedModality",
"StepRequest",
"StepRequirements",
"StepResult",
"TimeWindow",
"ThreadAffineRuntimeWorker",
"run_inference_session",
"step_requirements_from_request",
"undeclared_inference_inputs",
"UserInputCapability",
"UserInputEvent",
Expand Down
8 changes: 8 additions & 0 deletions flashdreams/flashdreams/runtime/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ class InferenceConfig:
cache_policy: str | None = None
"""Optional cache policy selector; ``None`` leaves the choice to the adapter."""

seed: int | None = None
"""Optional seed used when resolving deterministic demo/runtime behavior."""

runtime_options: Mapping[str, Any] = field(default_factory=dict)
"""Adapter/backend-specific runtime options."""

Expand All @@ -70,6 +73,11 @@ class InferenceConfig:
def __post_init__(self) -> None:
if not self.model_id.strip():
raise ValueError("InferenceConfig.model_id must be non-empty.")
if self.seed is not None:
if isinstance(self.seed, bool) or not isinstance(self.seed, int):
raise TypeError("InferenceConfig.seed must be an integer.")
if self.seed < 0:
raise ValueError("InferenceConfig.seed must be >= 0.")
object.__setattr__(
self, "runtime_options", freeze_mapping(self.runtime_options)
)
Expand Down
Loading
Loading