Cosmos
Diffusers
Safetensors
cosmos3_omni
nvidia
cosmos3
omnimodel

Model Card: Add SGLang Instruction

#5
Files changed (1) hide show
  1. README.md +119 -0
README.md CHANGED
@@ -108,6 +108,7 @@ Our AI models are designed and/or optimized to run on NVIDIA GPU-accelerated sys
108
 
109
  - [PyTorch](https://pytorch.org/)
110
  - [vLLM-Omni](https://github.com/vllm-project/vllm-omni)
 
111
 
112
  **Supported Hardware Microarchitecture Compatibility:**
113
 
@@ -523,6 +524,124 @@ With the daytime sample, the output looks like this, tiled as a surround view wi
523
 
524
  <video src="https://huggingface.co/nvidia/Cosmos3-Nano-Sim-Auto/resolve/main/images/cosmos3-nano-sim-auto-quickstart.mp4" controls autoplay loop muted playsinline width="100%"></video>
525
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
526
  ## Ethical Considerations
527
 
528
  NVIDIA believes Trustworthy AI is a shared responsibility and we have established policies and practices to enable development for a wide array of AI applications. Developers should work with their internal model team to ensure this model meets requirements for the relevant industry and use case and addresses unforeseen product misuse.
 
108
 
109
  - [PyTorch](https://pytorch.org/)
110
  - [vLLM-Omni](https://github.com/vllm-project/vllm-omni)
111
+ - [SGLang](https://github.com/sgl-project/sglang)
112
 
113
  **Supported Hardware Microarchitecture Compatibility:**
114
 
 
524
 
525
  <video src="https://huggingface.co/nvidia/Cosmos3-Nano-Sim-Auto/resolve/main/images/cosmos3-nano-sim-auto-quickstart.mp4" controls autoplay loop muted playsinline width="100%"></video>
526
 
527
+ ### Quick Start with SGLang
528
+
529
+ [SGLang](https://github.com/sgl-project/sglang) serves the same model through its OpenAI-compatible Videos API and produces the same camera-major video as the example above. Two things differ: the server reads every input from a path it can open instead of accepting uploads, so the sample is downloaded into a directory that is mounted into the container, and generation runs as an asynchronous job that the client polls. For joint camera and LiDAR generation with SGLang, see the [SGLang notebook](https://github.com/NVIDIA/cosmos-framework/blob/main/.agents/skills/cookbooks/cosmos3/simulation/auto/run_sim-auto_with_sglang.ipynb).
530
+
531
+ #### 1. Start the server
532
+
533
+ On the same kind of host, with the published [`lmsysorg/sglang:dev`](https://hub.docker.com/r/lmsysorg/sglang/tags) image, which includes the Cosmos3 pipelines from [sgl-project/sglang#39475](https://github.com/sgl-project/sglang/pull/39475):
534
+
535
+ ```bash
536
+ export SAMPLE_DIR="$PWD/cosmos3-daytime-sample" # Receives the inputs; the server reads them from this path.
537
+ export SGLANG_HF_CACHE="${SGLANG_HF_CACHE:-$HOME/.cache/sglang-huggingface}" # The container runs as root.
538
+ mkdir -p "$SAMPLE_DIR" "$SGLANG_HF_CACHE"
539
+ chmod 777 "$SGLANG_HF_CACHE"
540
+ docker pull lmsysorg/sglang:dev
541
+ docker run --init --runtime nvidia --gpus all --ipc=host \
542
+ -v "$SGLANG_HF_CACHE:/root/.cache/huggingface" \
543
+ -v "$SAMPLE_DIR:$SAMPLE_DIR" \
544
+ --env "HF_TOKEN=$HF_TOKEN" \
545
+ -p 127.0.0.1:30000:30000 \
546
+ lmsysorg/sglang:dev \
547
+ sglang serve \
548
+ --model-path nvidia/Cosmos3-Nano-Sim-Auto \
549
+ --host 0.0.0.0 --port 30000
550
+ ```
551
+
552
+ The container publishes the server on `127.0.0.1:30000` of the host and mounts `SAMPLE_DIR` at the same path, so the paths in the request below are valid inside it. The `dev` tag moves with SGLang's main branch, so pull it before each start. The first start downloads the checkpoint; the HTTP port opens after the weights are loaded and the warmup request finishes. This pipeline runs no text or video guardrails. With N GPUs (2, 4, or 8), add `--num-gpus N --ulysses-degree N --sp-degree N` to `sglang serve` to split every chunk across them with Ulysses sequence parallelism.
553
+
554
+ #### 2. Generate the camera videos
555
+
556
+ Run this in the same shell, so `SAMPLE_DIR` is set:
557
+
558
+ ```bash
559
+ pip install requests huggingface_hub
560
+ ```
561
+
562
+ ```python
563
+ import json
564
+ import os
565
+ import time
566
+ from pathlib import Path
567
+
568
+ import requests
569
+ from huggingface_hub import snapshot_download
570
+
571
+ MODEL = "nvidia/Cosmos3-Nano-Sim-Auto"
572
+ SAMPLE_REPO = "nvidia/Cosmos3-Nano-Transfer-Auto" # Publishes the shared daytime sample.
573
+ SERVER = "http://127.0.0.1:30000"
574
+ SAMPLE_DIR = Path(os.environ["SAMPLE_DIR"]).resolve() # Mounted into the server container at this path.
575
+ # The sample's seven cameras, in the checkpoint's camera order.
576
+ CAMERAS = [
577
+ "camera_front_wide_120fov",
578
+ "camera_cross_right_120fov",
579
+ "camera_rear_right_70fov",
580
+ "camera_rear_tele_30fov",
581
+ "camera_rear_left_70fov",
582
+ "camera_cross_left_120fov",
583
+ "camera_front_tele_30fov",
584
+ ]
585
+ NUM_FRAMES = 297 # Must be 4k + 1.
586
+
587
+ # Download the sample's WSM controls, RGB videos, and captions (about 70 MB) into SAMPLE_DIR.
588
+ scene = Path(snapshot_download(SAMPLE_REPO, local_dir=SAMPLE_DIR, allow_patterns=[
589
+ "assets/sample_data/daytime_scene/wsm/*.mp4",
590
+ "assets/sample_data/daytime_scene/rgb/*.mp4",
591
+ "assets/sample_data/daytime_scene/captions/*.json",
592
+ ])) / "assets/sample_data/daytime_scene"
593
+
594
+ def caption(camera):
595
+ data = json.loads((scene / "captions" / f"{camera}.json").read_text())
596
+ return data["caption_structured"]["chunk_0_300"]["caption"]
597
+
598
+ # One view per camera: its caption and the server-visible paths of its WSM control and RGB video.
599
+ views = [
600
+ {
601
+ "camera_key": camera,
602
+ "prompt": caption(camera),
603
+ "control_path": str(scene / "wsm" / f"{camera}.mp4"),
604
+ "vision_path": str(scene / "rgb" / f"{camera}.mp4"),
605
+ }
606
+ for camera in CAMERAS
607
+ ]
608
+
609
+ form = {
610
+ "model": MODEL,
611
+ "prompt": views[0]["prompt"], # Required by the API; generation uses each view's prompt.
612
+ "size": "832x480",
613
+ "num_frames": str(NUM_FRAMES),
614
+ "fps": "30",
615
+ "guidance_scale": "1", # Fixed by the distilled checkpoint,
616
+ "num_inference_steps": "4", # as is its four-step sampler.
617
+ "seed": "0",
618
+ "extra_params": json.dumps({
619
+ "wsm": {},
620
+ "multiview": {"views": views, "condition_video_as_image": True, "num_frames": NUM_FRAMES},
621
+ "resolution": "480",
622
+ "aspect_ratio": "16,9",
623
+ }),
624
+ }
625
+
626
+ # Submit the job, poll it, and download the video. Nothing is uploaded: the form carries text fields only.
627
+ response = requests.post(f"{SERVER}/v1/videos", files=[(key, (None, value)) for key, value in form.items()], timeout=60)
628
+ response.raise_for_status()
629
+ job = response.json()
630
+ deadline = time.monotonic() + 3600
631
+ while job["status"] not in ("completed", "failed", "cancelled"):
632
+ if time.monotonic() > deadline:
633
+ raise TimeoutError(f"Job {job['id']} did not finish in time: {job}")
634
+ time.sleep(10)
635
+ job = requests.get(f"{SERVER}/v1/videos/{job['id']}", timeout=60).json()
636
+ if job["status"] != "completed":
637
+ raise RuntimeError(json.dumps(job, indent=2))
638
+ video = requests.get(f"{SERVER}/v1/videos/{job['id']}/content", timeout=600)
639
+ video.raise_for_status()
640
+ Path("sim_auto.mp4").write_bytes(video.content)
641
+ ```
642
+
643
+ The server uses only the first frame of each RGB video, and trims each 300-frame control to `num_frames` and resizes it to 832 × 480. Split the camera-major output as in step 3 above.
644
+
645
  ## Ethical Considerations
646
 
647
  NVIDIA believes Trustworthy AI is a shared responsibility and we have established policies and practices to enable development for a wide array of AI applications. Developers should work with their internal model team to ensure this model meets requirements for the relevant industry and use case and addresses unforeseen product misuse.