Cosmos and Omnimodal World Foundation Models › Physical AI Data and Tokenization

Michael BrenndoerferJuly 23, 202619 min read
World Models HandbookAll chapters
Part 9 of 12Foundation and World-Action Models
Chapter 53Cosmos and Omnimodal World Foundation Models › Physical AI Data and Tokenization
Reading section 2 of 8 · Physical AI Data and Tokenization · 19 minSection 2 of 8 · 19 min

Book contents

Section 2 of 8 · 19 min read

Cosmos and Omnimodal World Foundation Models › Physical AI Data and TokenizationOne section · Sections in this chapter2 / 8 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

The training corpus and video tokenizer both shape what a world foundation model can learn from observations. They are not the only determinants: architecture, objective, conditioning data, and post-training matter too. A curation pass that discards fast-motion clips may conceal a temporal codec's weakness on fast events; aggressive temporal compression can discard task-relevant information even in a high-frame-rate corpus. Evaluate data slices and reconstructions together.

What makes physical AI data different

"Physical AI" is a term for systems whose intelligence is expressed through bodies in the world: vehicles, manipulators, legged robots, drones, and warehouse robots. Their data can differ from typical web video in the prevalence of ego-motion and contact, the availability of action annotations and synchronized sensors, and the continuity of trajectories. Those differences affect data collection and the tests a world model needs.

  • An agentic viewpoint. Many cameras move with a vehicle or robot, so ego-motion can account for substantial pixel change; independently moving objects and lighting matter too. Video-only prediction can learn correlations along recorded trajectories without identifying how futures change under alternative actions. That distinction matters when a model is used for planning.
  • Physically plausible dynamics. Objects often persist across frames, occlusions may persist or resolve, and camera trajectories should remain coherent with the scene; abrupt physical motion can still be real. For a continuous physical rollout, cuts, edits, and cross-fades are discontinuities rather than environmental dynamics. Because edited web video often contains them, a corpus assembled without care can encourage the model to reproduce discontinuities.
  • Action relevance. Near-misses, contact, occlusion boundaries, and degraded visibility can be consequential yet underrepresented in collections dominated by routine operation. If they are scarce in the target corpus, targeted collection or candidate generation may help. Measure coverage and choose sampling weights for the evaluation task rather than treating every recorded second as equally informative.
  • Multimodal alignment. Some physical-AI datasets include depth, LiDAR, radar, IMU, odometry, or joint readings alongside video. Available sensors vary by platform; paired signals need appropriate spatial calibration and temporal synchronization. A one-frame offset can corrupt a supervised relationship without necessarily causing visible hallucination in every output.
  • Condition diversity. Time of day, weather, sensor degradation, lens dirt, and seasonality change observations; some also change physics. Wet pavement, for example, changes tire–road friction and braking behavior. Appearance conditioning alone cannot stand in for dynamics coverage, so test both.
Real2Sim2Real

A pipeline that reconstructs real sensor data into a simulator representation (real2sim), varies controllable factors, then generates more realistic observations (sim2real). A conditional world model may help the second hop, but generation cost and label adherence have to be measured; simulator labels do not remain valid automatically.

The curation pipeline

Large raw video collections usually need curation before training. The original Cosmos report documents stages that affect the data distribution; the order and retention rules should be chosen for the intended task and measured rather than copied wholesale.

  1. Session and shot splitting. The original Cosmos pipeline extracts clips of about 2 to 60 seconds and detects shot boundaries using frame changes. A hard edit between unrelated views is not an ordinary physical transition; training across it can confuse temporal prediction. Overly short clips may omit the event evolution needed for a task.
  2. Quality filtering. Screen clips that are blurry, over- or under-exposed, mostly static, dominated by lens occlusion, or dominated by text overlays and picture-in-picture. Retention criteria depend on the target task: static or degraded clips can be useful for some evaluations. Burned-in captions and watermarks can be copied into generated outputs, so measure their prevalence rather than assuming a particular amplification factor.
  3. Captioning. Use a vision-language model to annotate clips or clip segments, ideally with temporal grounding. The original Cosmos report describes a caption per 256 frames, not necessarily one exhaustive description of every full clip. Captions support text conditioning and retrieval; their coverage and errors affect which scenarios users can request reliably.
  4. Deduplication. Check near-duplicates within the corpus and between training and evaluation sets. Leakage can inflate a reported generalization score; the score alone cannot reveal which examples leaked.
  5. Diversity adjustment, shuffling, and sharding. Balance the mixture across domains, sensor types, and environments. Then write it into shards that can be streamed by a distributed loader without random seeks into object storage. Mixture balance is a modelling decision in disguise: the relative weight of highway, urban, and rural footage helps shape which environments the model handles well.

The original Cosmos report describes a 20-million-hour raw collection curated into about 100 million clips. Its documented stages include shot splitting, filtering, annotation, deduplication, and sharding. The counts belong to that release; a new corpus needs its own retention criteria, labeling plan, and evaluation split.

Data coverage and architecture both constrain physical-AI world models. Large collections of synchronized, action-labeled interaction video are difficult to curate, especially for rare events. Real recordings, structured simulators, and neural generators can complement one another, but each brings distinct limitations in coverage, fidelity, or label validity.

Tokenization: from pixels to tokens

Here a video tokenizer acts as a learned compression codec. Its encoder maps a clip x∈RT×H×W×Cx \in \mathbb{R}^{T \times H \times W \times C} into latents

z=E(x),z∈R⌈T/ct⌉×⌈H/ch⌉×⌈W/cw⌉×dz = E(x), \qquad z \in \mathbb{R}^{\lceil T/c_t\rceil \times \lceil H/c_h\rceil \times \lceil W/c_w\rceil \times d}

and a decoder maps them back, x^=D(z)\hat{x} = D(z). This shape assumes suitable padding and integer downsampling factors; learned codecs need not correspond to independent, nonoverlapping blocks. The factors are often written ct×ch×cwc_t \times c_h \times c_w. The nominal token count is

L  =  ⌈Tct⌉⌈Hch⌉⌈Wcw⌉.L \;=\; \left\lceil \frac{T}{c_t} \right\rceil \left\lceil \frac{H}{c_h} \right\rceil \left\lceil \frac{W}{c_w} \right\rceil .

This LL counts latent-grid cells under the stated shape assumption, not necessarily transformer tokens: a generator may patchify the latent grid and add condition tokens. More cells generally increase compute, but the relationship depends on attention pattern, implementation, precision, hardware, and serving. Dense attention has a quadratic arithmetic term in sequence length; memory-optimized exact attention need not materialize a quadratic attention matrix. Neither a fixed horizon nor a frame rate follows from the codec factor alone.

The choice of what to compress is not symmetric either. Aggressive temporal compression can lose fast events, but a learned temporal codec may integrate information across all frames in its receptive field; it is not necessarily simple frame decimation. Whether a lane crossing survives must be tested on reconstructed clips. Aggressive spatial compression can lose brake lights, fingers, distant pedestrians, or lane boundaries. As with state abstractions in Part III, the relevant question is downstream sufficiency, not average fidelity alone.

Continuous versus discrete tokens

Continuous and discrete latents are two common design choices. They affect the generator objective and interface but do not uniquely determine the generator family.

Continuous tokenizers produce floating-point latents, sometimes with KL or perceptual regularization. They pair naturally with latent diffusion and flow models. A 16-dimensional latent stored in bf16 occupies 256 storage bits per token before any entropy coding; that is not a measured rate–distortion result. The PCA toy below uses float64 in memory unless explicitly cast. Continuous latents do not preclude likelihood modeling or reuse of all sequence-model tooling, but they do not provide a native categorical next-token objective.

Discrete tokenizers map latents to integer indices in a vocabulary of size KK. A fixed-width representation needs ⌈log⁡2K⌉\lceil \log_2 K \rceil bits per index; entropy coding can yield a different average rate. A learned VQ-VAE codebook is one way to construct such indices, but the original Cosmos tokenizer uses finite scalar quantization (FSQ): six scalar coordinates with (8,8,8,5,5,5)(8,8,8,5,5,5) levels respectively define a 64,000-entry implicit vocabulary, not a learned VQ codebook. Discrete indices support categorical autoregression, subject to the model's training and interface. Temperature, top-kk/nucleus sampling, and KV caching may be used when the decoder supports them; text–video interleaving and speculative decoding require compatible designs. Quantization error and autoregressive drift still matter. Learned-codebook collapse and EMA updates are VQ-specific concerns, not requirements of Cosmos's FSQ tokenizer.

The original Cosmos platform reported continuous and discrete video tokenizers and causal variants. A causal tokenizer avoids dependence on future frames and is suited to streaming. A non-causal tokenizer can still be used online with a buffering window and corresponding delay; it is not categorically unusable. Rate–distortion, latency, and model compatibility all matter to the choice.

What to measure

A tokenizer is often evaluated on reconstruction, but reconstruction alone is not a sufficient selection target for a policy-facing world model. Average pixel fidelity says little about whether the compressed representation still supports the decisions you intend to make. The useful panel of measurements looks like this.

  • Distortion: PSNR and SSIM for pixel/structural fidelity, LPIPS for learned perceptual similarity, and FVD for distribution-level video comparison rather than a per-frame reconstruction score. Each can miss a small safety-critical object, so slice by task-relevant events.
  • Rate: measure actual compressed bits per second including codebook or entropy-coder overhead where relevant, then relate that to latent token count and model compute. A bf16 storage estimate is not a fair bitrate comparison to entropy-coded discrete tokens.
  • Downstream utility: does a policy trained or evaluated on reconstructed observations behave the same as on originals? A tokenizer can score well on average reconstruction while losing a small decision-relevant detail. For a policy-facing use case, this check should carry substantial weight, despite the extra work of running the downstream task.
  • Compression-shape sensitivity: measure distortion separately on fast-motion and fine-detail slices. Average PSNR can hide small-object failures. Slicing by motion magnitude and object size takes additional annotation or detection effort but makes the operating envelope clearer.

Worked example: tokenizing a 10-second clip

The arithmetic is simple enough to do on paper, and doing it once makes every infrastructure discussion in this chapter concrete.

Take a 10-second clip at 30 frames per second and 1280×720 resolution. That is T=300T = 300 frames. With an 8x16x16 tokenizer, the temporal axis becomes ⌈300/8⌉=38\lceil 300/8 \rceil = 38 groups, the height becomes 4545, and the width becomes 8080. The nominal token count is 38×45×80=136,80038 \times 45 \times 80 = 136{,}800, before text or other modalities. With 8x8x8, it quadruples to 547,200547{,}200. Compare these counts with the actual context and attention scheme of the model being evaluated rather than an unspecified language-model context window.

These latent-grid counts illustrate a resource pressure, not the input length of a particular Cosmos transformer. Patchification, attention layout, and conditioning change the actual token sequence. Full attention has quadratic arithmetic in sequence length, although exact memory-efficient implementations can avoid a quadratic attention-matrix allocation. Diffusion or flow inference performs a model evaluation per sampler step, but step counts vary by release and distillation; Predict2.5, for example, reports a four-step distilled variant. A hypothetical 30 GPU-seconds for ten generated video seconds is a throughput example, not a measured wall-clock latency or Cosmos benchmark.

Let us build a miniature version of this pipeline. We will synthesize a tiny driving clip with a synchronized depth map and a semantic segmentation map, exactly the kind of multimodal bundle that physical AI corpora contain. We will use a fixed random seed so the example is deterministic and reproducible. Then we will run a deliberately naive tokenizer over it.

In[3]:
Code
import numpy as np
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA


def make_scene(n_frames=24, height=32, width=32, speed=0.55, seed=0):
    """Render a tiny schematic driving clip plus aligned depth and segmentation."""
    r = np.random.default_rng(seed)
    frames = np.zeros((n_frames, height, width, 3))
    depth = np.zeros((n_frames, height, width))
    seg = np.zeros((n_frames, height, width), dtype=np.int64)
    horizon = height // 2
    for t in range(n_frames):
        frames[t, :horizon] = (0.62, 0.72, 0.88)  # sky
        frames[t, horizon:] = (0.24, 0.24, 0.27)  # road surface
        seg[t, horizon:] = 1  # class 1: road
        depth[t, :horizon] = 1.00
        depth[t, horizon:] = 0.50
        offset = int(round(speed * t)) % 8  # lane marker pattern scrolls up
        for row in range(horizon, height):
            if (row + offset) % 8 < 3:
                col = width // 2
                frames[t, row, col - 1 : col + 2] = (0.90, 0.90, 0.85)
                seg[t, row, col - 1 : col + 2] = 2
                depth[t, row, col - 1 : col + 2] = 0.45
        row_c = int(horizon + 14 - 4.0 * speed * t)  # car moves toward horizon
        if horizon < row_c < height - 2:
            frames[t, row_c - 2 : row_c + 2, 12:20] = (0.85, 0.20, 0.15)
            seg[t, row_c - 2 : row_c + 2, 12:20] = 3
            depth[t, row_c - 2 : row_c + 2, 12:20] = 0.18
        frames[t] = np.clip(
            frames[t] + r.normal(0, 0.012, frames[t].shape), 0, 1
        )
    return frames, depth, seg

We generate one clip to fit the codec and a second, slightly slower clip with different noise to evaluate it. This is a held-out synthetic clip, not a separate driving session or a test of deployment generalization. The car's fixed drawn width and depth values are schematic, not a physically consistent receding vehicle.

Out[4]:
Console
train clip : (24, 32, 32, 3)   depth (24, 32, 32)   seg (24, 32, 32)
eval clip  : (24, 32, 32, 3)  (different speed, different noise)
raw scalar values in one clip: 73,728
segmentation classes present : [0, 1, 2, 3]
depth proxy range            : 0.18 to 1.00 (unitless)

Next we implement a toy patchification step: chop the clip into non-overlapping tubes and flatten each tube into a vector. Production learned tokenizers need not operate on independent, non-overlapping raw-pixel blocks. The layout is still useful for understanding the token-count arithmetic.

In[5]:
Code
def patchify(video, ct=4, ch=8, cw=8):
    """Non-overlapping tubes in time-row-column order; axes must divide evenly."""
    T, H, W, C = video.shape
    if T % ct or H % ch or W % cw:
        raise ValueError("T, H, and W must be divisible by ct, ch, and cw")
    x = video.reshape(T // ct, ct, H // ch, ch, W // cw, cw, C)
    x = x.transpose(0, 2, 4, 1, 3, 5, 6)
    return x.reshape(-1, ct * ch * cw * C)


def unpatchify(tokens, shape, ct=4, ch=8, cw=8):
    """Inverse of patchify for a compatible shape and complete token set."""
    T, H, W, C = shape
    if T % ct or H % ch or W % cw:
        raise ValueError("T, H, and W must be divisible by ct, ch, and cw")
    x = tokens.reshape(T // ct, H // ch, W // cw, ct, ch, cw, C)
    x = x.transpose(0, 3, 1, 4, 2, 5, 6)
    return x.reshape(T, H, W, C)

Patchification alone compresses nothing: 96 tokens of 768 values each retain the original 73,728 scalar values. (24 frames divided by ct=4 gives 6 time groups, 32/8=4 rows, and 32/8=4 columns.) Compression comes from the bottleneck. PCA and kk-means provide a small, runnable stand-in for a learned encoder and vector-quantized codebook; their measured tradeoff in this synthetic example should not be assumed to match a production codec.

In[6]:
Code
patches = patchify(train_frames, 4, 8, 8)
mean_patch = patches.mean(axis=0, keepdims=True)

pca = PCA(n_components=16, random_state=0).fit(patches - mean_patch)
train_latents = pca.transform(patches - mean_patch)

km = KMeans(n_clusters=64, n_init=4, random_state=0).fit(train_latents)
codebook = km.cluster_centers_

We can compare nominal storage bits after specifying a precision. The NumPy arrays in this experiment are float64 in memory; the following accounting instead assumes an eight-bit RGB source, 16-bit stored continuous latents, and ideal fixed-width code indices. It omits codebook storage, metadata, and entropy coding, so these are not measured compressed file sizes.

Out[7]:
Console
patches per clip        : (96, 768)
continuous latent dim   : 16  (24,576 bits, 24.0x compression)
discrete codebook size  : 64  (576 bits, 1024x compression)
Under these storage assumptions, discrete indices use fewer bits. Next: reconstruction.

We encode the held-out clip and reconstruct it both ways to answer that question.

In[8]:
Code
def psnr(reference, estimate, peak=1.0):
    mse = np.mean((reference - estimate) ** 2)
    return np.inf if mse == 0 else 10 * np.log10(peak**2 / mse)


eval_patches = patchify(eval_frames, 4, 8, 8)
eval_latents = pca.transform(eval_patches - mean_patch)
eval_codes = km.predict(eval_latents)

recon_continuous = unpatchify(
    pca.inverse_transform(eval_latents) + mean_patch, eval_frames.shape, 4, 8, 8
)
recon_discrete = unpatchify(
    pca.inverse_transform(codebook[eval_codes]) + mean_patch,
    eval_frames.shape,
    4,
    8,
    8,
)

psnr_continuous = psnr(eval_frames, recon_continuous)
psnr_discrete = psnr(eval_frames, recon_discrete)
Out[9]:
Console
held-out PSNR, continuous tokens : 25.98 dB
held-out PSNR, discrete tokens   : 24.34 dB
quantisation penalty             : 1.64 dB

A single operating point says little. What matters is the whole rate-distortion curve,
because that curve is what a designer trades against the generative model's cost.

Codebook usage is another diagnostic. If most entries are never selected, the nominal vocabulary overstates effective capacity; an autoregressive model can still predict the used indices, but some representational capacity is wasted. Here we have only 96 training tokens for 64 codes, so usage counts are noisy and should not be mistaken for a production collapse test.

Out[10]:
Console
codebook size                    : 64
codes never selected in training : 0
codes never selected on held-out : 22
top code share of training tokens: 6%
Out[11]:
Visualization
Sorted usage curves of codebook entries for training and held-out clips.
Training and held-out token counts by codebook entry, sorted by training usage. All 64 codes appear among just 96 training tokens, while some receive no held-out assignments. With so few tokens, this is a small-sample coverage observation, not evidence of production codebook collapse or robust generalization.

The rate-distortion sweep below changes PCA latent dimension and discrete codebook size. On the continuous curve, adding dimensions spends more bits and improves held-out PSNR; reading from left to right on its compression-ratio axis reverses that direction. The discrete points occupy much higher compression ratios, so this toy does not compare the two tokenizers at equal rate. It shows how to measure a tradeoff, not which tokenizer family wins. A curve that flattens as rate increases suggests checking encoder capacity and evaluation slices before buying more bits.

In[12]:
Code
sweep = []
for n_dims in (4, 8, 16, 32, 64):
    sub_pca = PCA(n_components=n_dims, random_state=0).fit(patches - mean_patch)
    lat_tr = sub_pca.transform(patches - mean_patch)
    lat_ev = sub_pca.transform(eval_patches - mean_patch)
    recon = unpatchify(
        sub_pca.inverse_transform(lat_ev) + mean_patch,
        eval_frames.shape,
        4,
        8,
        8,
    )
    cont_ratio = (eval_frames.size * 8) / (eval_patches.shape[0] * n_dims * 16)
    sweep.append(
        ("continuous", n_dims, 0, cont_ratio, psnr(eval_frames, recon))
    )
    for n_codes in (16, 32, 64):
        sub_km = KMeans(n_clusters=n_codes, n_init=4, random_state=0).fit(
            lat_tr
        )
        codes = sub_km.predict(lat_ev)
        recon_q = unpatchify(
            sub_pca.inverse_transform(sub_km.cluster_centers_[codes])
            + mean_patch,
            eval_frames.shape,
            4,
            8,
            8,
        )
        disc_ratio = (eval_frames.size * 8) / (
            eval_patches.shape[0] * np.ceil(np.log2(n_codes))
        )
        sweep.append(
            (
                "discrete",
                n_dims,
                n_codes,
                disc_ratio,
                psnr(eval_frames, recon_q),
            )
        )

cont_curve = sorted(
    (r, p) for kind, _, _, r, p in sweep if kind == "continuous"
)
disc_curve = sorted((r, p) for kind, _, _, r, p in sweep if kind == "discrete")
Out[13]:
Visualization
Line of continuous-token PSNR and scatter of discrete-token PSNR, showing continuous PSNR falling as the compression ratio rises.
Held-out PSNR against nominal compression ratio for a PCA-and-k-means toy tokenizer. Continuous reconstruction improves as PCA dimension and bit rate increase, appearing as a decline from left to right because the horizontal axis is compression ratio. The discrete points share three nominal bit rates, with five PCA dimensions overlapping horizontally at each rate; this plot does not establish which family reconstructs better at equal rate.

A frame comparison can reveal spatial structure hidden by average reconstruction metrics. A tokenizer can score reasonably on whole-frame PSNR while losing a small decision-relevant object. Below we inspect one held-out frame and its reconstruction from discrete codes.

In[14]:
Code
frame_index = 4  # the car is visible in this held-out frame
original_frame = eval_frames[frame_index]
reconstructed_frame = np.clip(recon_discrete[frame_index], 0, 1)

In this selected frame, the red car is visible in the original but largely lost in the discrete reconstruction. The nominal code index budget saves bits at this toy operating point, yet average PSNR alone does not tell us whether a small object remains usable for a decision. An object-specific reconstruction slice and a downstream task test would make that failure measurable.

Out[15]:
Visualization
Small synthetic driving frame showing sky, road, lane marker and a red lead vehicle.
Held-out toy frame 4. The original shows the red car and lane markings; unitless depth and segmentation arrays are aligned side channels but are not displayed here.
Toy discrete reconstruction of the same frame; the red car is barely distinguishable.
The same frame reconstructed from the toy k-means code indices. The red car is largely lost despite the scene's coarse road and sky structure remaining visible. This is an example of an object-specific failure hidden by a whole-clip average.