changh95's picture
Add files using upload-large-folder tool
1d30035 verified
Raw History Blame Contribute Delete
54.4 kB
# SPDX-FileCopyrightText: © 2026 Tenstorrent USA, Inc.
# SPDX-License-Identifier: Apache-2.0
"""Architectural constants of GR00T N1.5 / N1.6 / N1.7 as frozen dataclasses.
Every number here is copied from the research reports under ``docs/research/`` (the section is cited next to the
field or in the class docstring) or from the checkpoints' ``config.json``; nothing is derived from live model code.
Conventions follow ``01-architecture-synthesis.md``: batch 1, ``S`` = LLM sequence length, ``H`` = action horizon,
``V`` = cameras, ``n_img`` = images per sample.
Usage::
from models.experimental.gr00t.common.configs import get_config, GR00T_VERSIONS, snapshot_dir
cfg = get_config("n17")
cfg.dit.n_blocks # 32
cfg.canonical_layout.s_pad_llm # 512
snapshot_dir("n17") # ~/.cache/huggingface/hub/models--nvidia--GR00T-N1.7-3B/snapshots/2fc962b9...
"""
from __future__ import annotations
import os
from dataclasses import dataclass, field
from pathlib import Path
from typing import Dict, Mapping, Optional, Tuple
GR00T_VERSIONS: Tuple[str, ...] = ("n15", "n16", "n17")
# --------------------------------------------------------------------------------------------------------------------
# Checkpoint identity (weight-loader-spec.md header table + §1.1; 01-architecture-synthesis.md §1.9)
# --------------------------------------------------------------------------------------------------------------------
HF_REPOS: Mapping[str, str] = {
"n15": "nvidia/GR00T-N1.5-3B",
"n16": "nvidia/GR00T-N1.6-3B",
"n17": "nvidia/GR00T-N1.7-3B",
}
HF_SNAPSHOT_SHAS: Mapping[str, str] = {
"n15": "869830fc749c35f34771aa5209f923ac57e4564e",
"n16": "d0814e7ecb19202e7c8468b46098b0b7ef3a6d61",
"n17": "2fc962b973bccdd5d8ce4f67cc63b264d6886495",
}
def hf_hub_cache() -> Path:
"""Directory holding the ``models--*`` snapshot trees (``HF_HUB_CACHE`` > ``HF_HOME/hub`` > ``~/.cache/huggingface/hub``)."""
if "HF_HUB_CACHE" in os.environ:
return Path(os.environ["HF_HUB_CACHE"])
if "HF_HOME" in os.environ:
return Path(os.environ["HF_HOME"]) / "hub"
return Path.home() / ".cache" / "huggingface" / "hub"
def snapshot_dir(version: str, hub_cache: Optional[Path] = None) -> Path:
"""Resolve the local HF snapshot directory of ``version`` and verify that it exists (no fallback).
The pinned revision is the one every golden dump and every research report was produced from
(``weight-loader-spec.md`` header table; ``golden-tap-map-and-thresholds.md`` §1 provenance row).
"""
_check_version(version)
hub = Path(hub_cache) if hub_cache is not None else hf_hub_cache()
repo_dir = "models--" + HF_REPOS[version].replace("/", "--")
path = hub / repo_dir / "snapshots" / HF_SNAPSHOT_SHAS[version]
if not (path / "model.safetensors.index.json").is_file():
raise FileNotFoundError(
f"{version}: snapshot {HF_REPOS[version]}@{HF_SNAPSHOT_SHAS[version][:8]} not found at {path} "
"(expected model.safetensors.index.json)"
)
return path
def _check_version(version: str) -> None:
if version not in GR00T_VERSIONS:
raise KeyError(f"unknown GR00T version {version!r}; expected one of {GR00T_VERSIONS}")
# --------------------------------------------------------------------------------------------------------------------
# Component configs
# --------------------------------------------------------------------------------------------------------------------
@dataclass(frozen=True)
class CheckpointConfig:
"""Checkpoint facts (weight-loader-spec.md header table + §1.1; 01-architecture-synthesis.md §1.9)."""
hf_repo: str
hf_sha: str
n_shards: int
n_tensors: int # keys in model.safetensors.index.json
n_params: int
n_bytes: int # == metadata.total_size; all tensors bf16
shard_files: Tuple[str, ...]
# The unit (LLM layer / DiT block) whose tensors are split across two shards -> shards must be resolved per key
# (weight-loader-spec.md §1.1 consequence (b)).
straddling_prefix: str
# Canonical checkpoint key prefixes (weight-loader-spec.md §2 "strip prefix" column).
vision_prefix: str
projector_prefix: Optional[str]
llm_prefix: str # prefix of `embed_tokens.weight`, `layers.N.*`, `norm.weight`
lm_head_key: str
action_head_prefix: str = "action_head."
dit_prefix: str = "action_head.model."
vlln_prefix: str = "action_head.vlln."
vl_self_attention_prefix: Optional[str] = None
embodiment_prefixes: Tuple[str, ...] = (
"action_head.state_encoder.",
"action_head.action_encoder.",
"action_head.action_decoder.",
)
@dataclass(frozen=True)
class VisionConfig:
"""Vision encoder (01-architecture-synthesis.md §1.1; arch-n15 §2.1, arch-n16 §1/§4, arch-n17 §2.1-2.2)."""
family: str # "siglip_v1" | "siglip2_naflex" | "qwen3vl"
n_layers: int
hidden: int
n_heads: int
head_dim: int
mlp_dim: int
activation: str # "gelu_tanh" (gelu_pytorch_tanh) in all three towers
ln_eps: float
attention_bias: bool # q/k/v/out Linear carry biases in all three
qkv_fused_in_checkpoint: bool # N1.7 stores one `attn.qkv` Linear(1024->3072); SigLIP stores q/k/v separately
patch_size: int
temporal_patch: int # Conv3d temporal kernel (N1.7 = 2, still frame duplicated to t=2)
patch_in_features: int # 3*14*14 = 588 (SigLIP) / 3*2*16*16 = 1536 (Qwen3-VL)
patch_column_order: str # "(kh,kw,c)" for SigLIP (== pi0 unfold), "(c,t,ph,pw)" for Qwen3-VL (host-layout §1-3)
pos_table_rows: int # learned position table rows: 256 (16x16) / 256 / 2304 (48x48)
pos_grid: int # side of the learned grid
pos_interpolation: str # "none" | "bilinear_16_to_18" | "bilinear_4tap_per_grid"
image_size: Optional[int] # fixed square input side; None = dynamic (multiple of 32)
patches_per_image: Optional[int] # None = depends on grid
tokens_per_image: Optional[int] # LLM tokens per image after merge; None = depends on grid
merge_size: int # 1 (none) / 2 (2x2 pixel-unshuffle or merger)
frames_per_camera: int # 1 / 1 / 2 (history + current)
rope: str # "none" | "2d"
rope_theta: Optional[float]
rope_freqs_per_axis: Optional[int] # N1.7: 16 frequencies per (h, w) axis -> cos/sin [P, 64]
post_layernorm: bool # SigLIP `post_layernorm`; Qwen3-VL has the LN inside the merger
deepstack_layers: Tuple[int, ...] # blocks whose outputs feed the deepstack mergers (N1.7: 5, 11, 17)
full_attention_per_image: bool = True # N1.6 windows are disabled (critique C1, golden-tap-map §5)
head_dim_pad: int = 0 # ttnn SDPA head-dim padding (static-shape-plan §3.1): 72->96, 64 unchanged
patch_in_features_pad: int = 0 # 588 -> 608 tile padding (static-shape-plan §3.1)
dynamic_min_pixels: Optional[int] = None # N1.7 smart_resize: >= 65,536 px, factor 32
dynamic_factor: Optional[int] = None
executed_params: int = 0 # perf-model-v2 §2.2 (pooling head excluded)
executed_bytes_bf16: int = 0
@property
def attention_scale(self) -> float:
"""Softmax scale; must be passed explicitly when heads are padded (static-shape-plan D5)."""
return self.head_dim**-0.5
@dataclass(frozen=True)
class ProjectorConfig:
"""Vision -> LLM projector (01-architecture-synthesis.md §1.2; arch-n15 §2.2, arch-n16 §4, arch-n17 §2.2)."""
kind: str # "linear" | "unshuffle_ln_mlp" | "qwen3vl_merger"
in_dim: int # width entering the first Linear (1152 / 4608 / 4096)
hidden_dim: Optional[int] # None for the single Linear
out_dim: int # 2048 = LLM hidden
ln_dim: Optional[int] # LayerNorm width (None = no LN): N1.6 4608 (post-concat); N1.7 1024 (pre-concat)
ln_eps: Optional[float]
ln_position: Optional[str] # "post_concat" | "pre_concat"
activation: Optional[str] # "gelu_erf" (nn.GELU()) or None -- never tanh here (synthesis §3 N9)
merge_channel_order: Optional[str] # N1.6 "c*4+dy*2+dx" (F.pixel_unshuffle); N1.7 "(mh,mw,c)" row-major concat
image_token_id: int # slot id overwritten by the projector rows (151669 <IMG_CONTEXT> / 151655 <|image_pad|>)
splice: str # "overwrite" (N1.5/N1.6 indexed assignment) | "masked_scatter" (N1.7)
n_deepstack: int = 0 # N1.7: 3 extra mergers (post-concat LN(4096)) added to the residual after LLM layers 0..2
deepstack_ln_dim: Optional[int] = None
params: int = 0
params_deepstack_each: int = 0
@dataclass(frozen=True)
class LLMConfig:
"""Truncated Qwen3 decoder (01-architecture-synthesis.md §1.3; arch-n15 §2.4, arch-n16 §5, arch-n17 §1.4/§2.3)."""
family: str # "qwen3_1p7b" | "qwen3vl_2b_text"
n_layers_total: int # 28 in the source model
n_layers_executed: int # `select_layer`: 12 / 16 / 16
hidden: int
n_heads: int
n_kv_heads: int
head_dim: int
intermediate: int # SwiGLU width
rms_eps: float
qk_norm: bool # per-head RMSNorm(128) on q and k before RoPE
attention_bias: bool
rope_mode: str # "1d" | "mrope_interleaved"
rope_theta: float
mrope_section: Optional[Tuple[int, int, int]] # N1.7 (24, 20, 20): T owns 24 half-dims, H 20, W 20
rope_layout: str # "rotate_half" (HF) in all three
vocab: int # embed_tokens rows
tie_word_embeddings: bool
final_norm_applied: bool # backbone feature = post final RMSNorm (N1.5/N1.6) or raw layer-15 residual (N1.7)
deepstack_add_after_layers: Tuple[int, ...] # N1.7: (0, 1, 2)
causal: bool = True
massive_activation_channels: Tuple[int, ...] = () # residual channels reaching ~1e4 at token 0 (ref-env §5.4)
executed_layer_params: int = 0 # perf-model-v2 §2.2
executed_layer_bytes_bf16: int = 0
@dataclass(frozen=True)
class VLAdapterConfig:
"""`vlln` + optional 4-block VL self-attention (01-architecture-synthesis.md §1.4; arch-n15 §3.5, arch-n17 §3.2)."""
dim: int # 2048
vlln_eps: float # LayerNorm(2048, eps 1e-5, affine)
n_blocks: int # 4 / 0 / 4
n_heads: int
head_dim: int
ff_dim: int
ln_eps: float
activation: str # "gelu_tanh"
attention_bias: bool
masked: bool # reference applies no key mask at B=1
reference_dtype: str # "fp32" (N1.5 autocast promotes LN, residual fp32) | "bf16"
params: int = 0
@dataclass(frozen=True)
class DiTConfig:
"""AdaLN cross/self-interleaved DiT (01-architecture-synthesis.md §1.5; critique C6; weight-loader §4.6)."""
class_name: str # "cross_attention_dit.DiT" | "dit.AlternateVLDiT"
n_blocks: int
width: int
n_heads: int
head_dim: int
ff_dim: int
activation: str # "gelu_tanh"
attention_bias: bool
cross_attention_dim: int # 2048 (to_k/to_v: 2048 -> 1536)
cross_block_parity: str # "even" blocks cross-attend, odd self-attend (C S C S ...)
cross_key_set: str # "all" (N1.5, no mask) | "alternate_text_image" (idx%4==0 -> non-image, idx%4==2 -> image)
adaln_chunks: int # 2
adaln_order: Tuple[str, str] # ("scale", "shift") for norm1.linear -- attention branch only, ungated
adaln_ln_eps: float # 1e-5, non-affine
norm3_affine: bool # False: plain LN(1536, eps 1e-5) before the FF, no weights in any checkpoint (synthesis §3 N8)
norm3_eps: float
out_norm_eps: float # 1e-6, non-affine
proj_out_1_order: Tuple[str, str] # ("shift", "scale") -- opposite order to the blocks
out_dim: int # proj_out_2: 1536 -> 1024
timestep_embed_dim: int # Timesteps(256, flip_sin_to_cos=True, downscale_freq_shift=1)
timestep_flip_sin_to_cos: bool
timestep_downscale_freq_shift: int
timestep_max_period: float
timestep_mlp_hidden: int # Linear(256->1536) -> SiLU -> Linear(1536->1536); `temb` shared by all blocks
n_query_tokens: int # 49 = state 1 + future 32 + action 16 | 51 | 41
n_future_tokens: int # 32 (N1.5 learned FLARE tokens) | 0
head_dim_pad: int = 64 # 48 -> 64 at load (static-shape-plan D5)
m_pad: int = 64 # query rows padded to 64 (static-shape-plan D4)
params_blocks: int = 0
params_timestep_encoder: int = 0
params_proj_out: int = 0
@property
def attention_scale(self) -> float:
"""48**-0.5; must be passed explicitly after padding to 64 (ttnn-blocks-dit §3.1)."""
return self.head_dim**-0.5
@property
def cross_block_indices(self) -> Tuple[int, ...]:
return tuple(range(0, self.n_blocks, 2))
@property
def self_block_indices(self) -> Tuple[int, ...]:
return tuple(range(1, self.n_blocks, 2))
def cross_key_subset(self, block_idx: int) -> str:
"""Key set of cross block ``block_idx``: "all" | "text" (non-image) | "image" (arch-n16 §7.4, arch-n17 §3.3)."""
if block_idx % 2 != 0:
raise ValueError(f"block {block_idx} is a self-attention block")
if self.cross_key_set == "all":
return "all"
return "text" if block_idx % 4 == 0 else "image"
@property
def velocity_rows(self) -> slice:
"""Rows of the decoder output that form the velocity: the last H rows (synthesis §1.6 'action decoder')."""
return slice(self.n_query_tokens - (self.n_query_tokens - 1 - self.n_future_tokens), None)
@dataclass(frozen=True)
class EncoderConfig:
"""Embodiment-conditioned MLPs (01-architecture-synthesis.md §1.6; weight-loader-spec.md §4.7, arch-n1x §3.1)."""
max_num_embodiments: int # 32 -> W [32, in, out], b [32, out]; y = x @ W[e] + b[e] ([in,out], no transpose)
max_state_dim: int
max_action_dim: int
action_horizon: int
hidden_size: int # 1024 (state encoder hidden, decoder hidden, DiT output width)
input_embedding_dim: int # 1536 (DiT width)
state_encoder_dims: Tuple[int, int, int] # (max_state_dim, 1024, 1536); ReLU between
action_encoder_w1: Tuple[int, int] # (max_action_dim, 1536)
action_encoder_w2: Tuple[int, int] # (3072, 1536) on cat[a, tau]; swish after
action_encoder_w3: Tuple[int, int] # (1536, 1536)
tau_dim: int # 1536 sinusoid: half 768, freqs f_i = exp(-i ln(1e4)/768), enc = [sin(t f), cos(t f)] (arch-n15 §3.3)
tau_order: Tuple[str, str]
tau_max_period: float
action_decoder_dims: Tuple[int, int, int] # (1024, 1024, max_action_dim); ReLU between
position_embedding_rows: int # Embedding(1024, 1536); rows 0..H-1 added to the action tokens
state_dim_pad: int # tile-friendly padding of the state input (weight-loader §4.7): 64 / 128 / 160
action_dim_pad: int # 32 / 128 / 160
used_slot_bytes_bf16: int = 0 # perf-model-v2 §2.2
@dataclass(frozen=True)
class SamplerConfig:
"""4-step Euler flow matching (01-architecture-synthesis.md §1.6; arch-n16 §7.6; golden-tap-map §2.1)."""
num_inference_timesteps: int # 4
num_timestep_buckets: int # 1000
dt: float # 0.25
timestep_buckets: Tuple[int, ...] # int(k/4 * 1000) = 0, 250, 500, 750
noise_shape: Tuple[int, int, int] # [1, H, max_action_dim]; all dims noisy incl. pads
euler_dtype: str # "fp32_actions_bf16_velocity" (N1.5) | "bf16" (N1.6/N1.7)
noise_dtype: str # RNG dtype in the reference: "fp32" | "bf16"
velocity_rows_from_end: int # decoder rows -H:
def timestep_bucket(self, k: int) -> int:
"""Discretised timestep fed to the encoders: ``int(k / num_inference_timesteps * num_timestep_buckets)``."""
if not 0 <= k < self.num_inference_timesteps:
raise ValueError(f"step {k} out of range")
return int(k / self.num_inference_timesteps * self.num_timestep_buckets)
@dataclass(frozen=True)
class PreprocessingConfig:
"""Host-side image/state preprocessing constants (01-architecture-synthesis.md §1.7; host-pipeline-parity §4.2)."""
image_pipeline: str # short recipe name, see host-pipeline-parity §4.2
crop_fraction: float # 0.95 in all three
shortest_edge: int # 256 source frames
crop_size: int # int(256 * 0.95) = 243
resize_interpolation: str # "torchvision_bilinear_antialias" | "pil_bicubic" | "qwen2vl_bicubic_antialias"
output_size: Optional[int] # 224 / 252 / None (dynamic)
smart_resize_factor: Optional[int] # None / 28 / 32
smart_resize_min_pixels: Optional[int] # None / 4*28*28 / 65536
smart_resize_max_pixels: Optional[int]
normalize_offset: float # (u8 - 127.5) / 127.5 in fp32 (NOT ((x/255)-0.5)/0.5; differs by 5.9e-8)
normalize_scale: float
uint8_truncation_before_processor: bool # N1.5 casts (x*255).uint8 (truncation) before the Eagle tiler
frames_per_camera: int
image_order: str # N1.7 "frame-major": [cam1@t-15, cam2@t-15, cam1@t, cam2@t]
formalize_language: bool # lower-case + strip [^\w\s]
instruction_as_repr_list: bool # N1.5: the template sees repr([instruction]) -> tokens `['` (677) and `']` (660)
state_normalization: str # "sincos_or_minmax_per_config" | "minmax_clip_or_sincos_per_group" | "q01q99_clip"
action_decode: str # host-pipeline-parity §5 recipe name
host_cost_ms: float # host-pipeline-parity §6 (pinned cores)
@dataclass(frozen=True)
class PromptConfig:
"""Prompt template and token ids (01-architecture-synthesis.md §1.7; static-shape-plan §4.1; arch-n1x)."""
tokenizer: str # "qwen2_bpe_eagle2" | "qwen2_bpe_eagle3" | "qwen2_bpe_cosmos_reason2"
vocab_entries: int # tokenizer entries (151680 / 151680 / 151669); embed table rows are in LLMConfig.vocab
pad_id: int # <|endoftext|> 151643
eos_id: int # <|im_end|> 151645
im_start_id: int # 151644
im_end_id: int # 151645
newline_id: int # 198
image_token_id: int # <IMG_CONTEXT> 151669 | <|image_pad|> 151655
image_open_id: Optional[int] # <img> 151670 | <|vision_start|> 151652
image_close_id: Optional[int] # </img> 151671 | <|vision_end|> 151653
add_bos: bool # False in all three
layout: str # "images_then_text_with_generation_prompt" | "text_then_images" | "images_then_text_no_system"
system_prompt: bool
generation_prompt: bool
header_ids: Tuple[int, ...] # fixed leading tokens
per_image_prefix_ids: Tuple[int, ...] # tokens before the image run (k=1); `<image k>` digit varies with k
per_image_prefix_len: int # 6 (N1.5 `<image k><img>`), 6 (N1.6 `<image k>` 5 + `<img>`), 1 (N1.7 vision_start)
per_image_suffix_len: int # `</img>` 1 | `<|vision_end|>` 1
suffix_ids: Tuple[int, ...] # fixed trailing tokens
text_extra_ids: Tuple[int, ...] # N1.5 bracket tokens (677, 660) that wrap the instruction
fixed_tokens_formula: str # human-readable S formula
# N1.6 `<image k>` renders as 5 tokens `27 1805 220 <digit> 29`; N1.5 as `<image k><img>` = 6 tokens.
def seq_len(self, n_images: int, n_text: int, tokens_per_image: int) -> int:
"""``S`` for ``n_images`` images and ``n_text`` instruction BPE tokens (static-shape-plan §4.1)."""
per_image = self.per_image_prefix_len + tokens_per_image + self.per_image_suffix_len
return len(self.header_ids) + n_images * per_image + n_text + len(self.text_extra_ids) + len(self.suffix_ids)
@dataclass(frozen=True)
class LayoutConfig:
"""One static shape key (static-shape-plan.md §2, §4.2, §6): all device tensor shapes are fixed per layout."""
name: str
embodiment_tag: str
embodiment_id: int
n_cameras: int
n_images: int # cameras x frames
grid_thw: Optional[Tuple[int, int, int]] # N1.7 ViT grid per image (t, h, w) in patches; None for SigLIP
patches_per_image: int
patch_rows_pad: int # per image, multiple of 32 (324 -> 352)
tokens_per_image: int
s_golden: Optional[int] # observed S of the golden sample (None if no golden for this layout)
s_typical: str # observed / expected range as text
s_pad_llm: int # multiple of 128 (patched tt_transformers MLP or tt_dit encoder)
s_pad_llm_unpatched: int # multiple of 512 when >= 512 for the unpatched tt_transformers MLP
s_pad_vl: int # rows for vlln / VL-SA / cross K/V (== s_pad_llm in the first implementation)
l_max: int # text-token budget at s_pad_llm (incl. N1.5's 2 bracket tokens)
text_padding: str # "right" (N1.5/N1.7) | "text_slot" (N1.6: pads between text and images, explicit mask)
image_slots: Tuple[Tuple[int, int], ...] # fixed half-open slot ranges of the image tokens under the padding policy
non_image_slots: Optional[int] # count of non-image slots at s_pad_llm
dit_m_logical: int # 49 / 51 / 41
dit_m_pad: int # 64
cross_image_keys: Optional[Tuple[int, int]] # (real, padded) image keys for idx%4==2 blocks (None for N1.5)
cross_text_keys: Optional[Tuple[int, int]] # (real slots, padded) non-image keys for idx%4==0 blocks
cross_all_keys: Optional[Tuple[int, int]] # N1.5: (S, s_pad_vl) all tokens
state_shape: Tuple[int, int, int]
noise_shape: Tuple[int, int, int]
valid_slice: Tuple[int, int] # (horizon_valid, dims_valid) of the padded action tensors
action_groups: Tuple[str, ...]
rope_table: str # "constant_arange" | "per_call_rows" | "constant_mrope_per_layout"
notes: str = ""
@dataclass(frozen=True)
class GR00TConfig:
"""Everything the port needs to know about one GR00T version (01-architecture-synthesis.md §1)."""
version: str
display_name: str
checkpoint: CheckpointConfig
vision: VisionConfig
projector: ProjectorConfig
llm: LLMConfig
vl_adapter: VLAdapterConfig
dit: DiTConfig
encoders: EncoderConfig
sampler: SamplerConfig
preprocessing: PreprocessingConfig
prompt: PromptConfig
embodiment_ids: Mapping[str, int] # tag -> slot id (base checkpoint)
canonical_embodiment: str
layouts: Tuple[LayoutConfig, ...]
canonical_layout_name: str
backbone_feature_dim: int = 2048
reference_code: str = ""
golden_dir: str = "" # relative to the golden root
@property
def canonical_embodiment_id(self) -> int:
return self.embodiment_ids[self.canonical_embodiment]
@property
def canonical_layout(self) -> LayoutConfig:
return self.layout(self.canonical_layout_name)
def layout(self, name: str) -> LayoutConfig:
for lay in self.layouts:
if lay.name == name:
return lay
raise KeyError(f"{self.version}: unknown layout {name!r}; have {[l.name for l in self.layouts]}")
def embodiment_id(self, tag: str) -> int:
if tag not in self.embodiment_ids:
raise KeyError(f"{self.version}: unknown embodiment tag {tag!r}; have {sorted(self.embodiment_ids)}")
return self.embodiment_ids[tag]
# --------------------------------------------------------------------------------------------------------------------
# Shared constants
# --------------------------------------------------------------------------------------------------------------------
# Qwen2 BPE special ids shared by the three tokenizers (arch-n15 §4.2, arch-n16 §1, arch-n17 §1.3).
_PAD_ID = 151643
_IM_START = 151644
_IM_END = 151645
_NEWLINE = 198
# `<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\n` (arch-n15 §4.2 table, arch-n16 §4.2).
_SYSTEM_USER_HEADER: Tuple[int, ...] = (
151644,
8948,
198,
2610,
525,
264,
10950,
17847,
13,
151645,
198,
151644,
872,
198,
)
_SAMPLER_BUCKETS: Tuple[int, ...] = (0, 250, 500, 750)
_QWEN3_LLM_COMMON = dict(
n_layers_total=28,
hidden=2048,
n_heads=16,
n_kv_heads=8,
head_dim=128,
intermediate=6144,
rms_eps=1e-6,
qk_norm=True,
attention_bias=False,
rope_layout="rotate_half",
tie_word_embeddings=True,
)
_DIT_COMMON = dict(
width=1536,
n_heads=32,
head_dim=48,
ff_dim=6144,
activation="gelu_tanh",
attention_bias=True,
cross_attention_dim=2048,
cross_block_parity="even",
adaln_chunks=2,
adaln_order=("scale", "shift"),
adaln_ln_eps=1e-5,
norm3_affine=False,
norm3_eps=1e-5,
out_norm_eps=1e-6,
proj_out_1_order=("shift", "scale"),
out_dim=1024,
timestep_embed_dim=256,
timestep_flip_sin_to_cos=True,
timestep_downscale_freq_shift=1,
timestep_max_period=10000.0,
timestep_mlp_hidden=1536,
params_timestep_encoder=2_755_584,
params_proj_out=6_295_552,
)
_SIGLIP_COMMON = dict(
n_layers=27,
hidden=1152,
n_heads=16,
head_dim=72,
mlp_dim=4304,
activation="gelu_tanh",
ln_eps=1e-6,
attention_bias=True,
qkv_fused_in_checkpoint=False,
patch_size=14,
temporal_patch=1,
patch_in_features=588,
patch_column_order="(kh,kw,c)",
pos_table_rows=256,
pos_grid=16,
merge_size=1,
frames_per_camera=1,
rope="none",
rope_theta=None,
rope_freqs_per_axis=None,
post_layernorm=True,
deepstack_layers=(),
head_dim_pad=96,
patch_in_features_pad=608,
executed_params=412_442_352,
executed_bytes_bf16=824_884_704,
)
# --------------------------------------------------------------------------------------------------------------------
# N1.5
# --------------------------------------------------------------------------------------------------------------------
_N15_EMBODIMENTS: Dict[str, int] = { # arch-n15 §4.4 (gr00t/data/embodiment_tags.py:19-47)
"gr1": 24,
"oxe_droid": 17,
"agibot_genie1": 26,
"new_embodiment": 31,
}
_N15_GROUPS = ("left_arm", "right_arm", "left_hand", "right_hand")
N15_CONFIG = GR00TConfig(
version="n15",
display_name="GR00T-N1.5-3B",
reference_code="Isaac-GR00T-n1.5 (n1.5-release, 4af2b622)",
golden_dir="n15",
checkpoint=CheckpointConfig(
hf_repo=HF_REPOS["n15"],
hf_sha=HF_SNAPSHOT_SHAS["n15"],
n_shards=3,
n_tensors=899,
n_params=2_724_163_520,
n_bytes=5_448_327_040,
shard_files=tuple(f"model-0000{i}-of-00003.safetensors" for i in (1, 2, 3)),
straddling_prefix="backbone.eagle_model.language_model.model.layers.5.",
vision_prefix="backbone.eagle_model.vision_model.",
projector_prefix="backbone.eagle_model.mlp1.",
llm_prefix="backbone.eagle_model.language_model.model.",
lm_head_key="backbone.eagle_model.language_model.lm_head.weight",
vl_self_attention_prefix="action_head.vl_self_attention.",
),
vision=VisionConfig(
family="siglip_v1",
pos_interpolation="none",
image_size=224,
patches_per_image=256,
tokens_per_image=256,
**_SIGLIP_COMMON,
),
projector=ProjectorConfig(
kind="linear",
in_dim=1152,
hidden_dim=None,
out_dim=2048,
ln_dim=None,
ln_eps=None,
ln_position=None,
activation=None,
merge_channel_order=None,
image_token_id=151669,
splice="overwrite",
params=2_361_344,
),
llm=LLMConfig(
family="qwen3_1p7b",
n_layers_executed=12,
rope_mode="1d",
rope_theta=1e6,
mrope_section=None,
vocab=151_680,
final_norm_applied=True,
deepstack_add_after_layers=(),
massive_activation_channels=(1793, 1999),
executed_layer_params=604_032_000,
executed_layer_bytes_bf16=1_208_064_000,
**_QWEN3_LLM_COMMON,
),
vl_adapter=VLAdapterConfig(
dim=2048,
vlln_eps=1e-5,
n_blocks=4,
n_heads=32,
head_dim=64,
ff_dim=8192,
ln_eps=1e-5,
activation="gelu_tanh",
attention_bias=True,
masked=False,
reference_dtype="fp32",
params=201_433_088,
),
dit=DiTConfig(
class_name="cross_attention_dit.DiT",
n_blocks=16,
cross_key_set="all",
n_query_tokens=49,
n_future_tokens=32,
params_blocks=541_335_552,
**_DIT_COMMON,
),
encoders=EncoderConfig(
max_num_embodiments=32,
max_state_dim=64,
max_action_dim=32,
action_horizon=16,
hidden_size=1024,
input_embedding_dim=1536,
state_encoder_dims=(64, 1024, 1536),
action_encoder_w1=(32, 1536),
action_encoder_w2=(3072, 1536),
action_encoder_w3=(1536, 1536),
tau_dim=1536,
tau_order=("sin", "cos"),
tau_max_period=10000.0,
action_decoder_dims=(1024, 1024, 32),
position_embedding_rows=1024,
state_dim_pad=64,
action_dim_pad=32,
used_slot_bytes_bf16=19_700_000,
),
sampler=SamplerConfig(
num_inference_timesteps=4,
num_timestep_buckets=1000,
dt=0.25,
timestep_buckets=_SAMPLER_BUCKETS,
noise_shape=(1, 16, 32),
euler_dtype="fp32_actions_bf16_velocity",
noise_dtype="fp32",
velocity_rows_from_end=16,
),
preprocessing=PreprocessingConfig(
image_pipeline="x/255 -> CenterCrop(243) -> Resize(224, bilinear, antialias) -> (x*255).uint8 -> Eagle2.5 "
"tiler (1 tile @224, no thumbnail) -> (u8-127.5)/127.5",
crop_fraction=0.95,
shortest_edge=256,
crop_size=243,
resize_interpolation="torchvision_bilinear_antialias",
output_size=224,
smart_resize_factor=None,
smart_resize_min_pixels=None,
smart_resize_max_pixels=None,
normalize_offset=127.5,
normalize_scale=127.5,
uint8_truncation_before_processor=True,
frames_per_camera=1,
image_order="camera",
formalize_language=False,
instruction_as_repr_list=True,
state_normalization="sincos_or_minmax_per_config",
action_decode="minmax_no_clip_torch_fp32",
host_cost_ms=0.8,
),
prompt=PromptConfig(
tokenizer="qwen2_bpe_eagle2",
vocab_entries=151_680,
pad_id=_PAD_ID,
eos_id=_IM_END,
im_start_id=_IM_START,
im_end_id=_IM_END,
newline_id=_NEWLINE,
image_token_id=151669,
image_open_id=151670,
image_close_id=151671,
add_bos=False,
layout="images_then_text_with_generation_prompt",
system_prompt=True,
generation_prompt=True,
header_ids=_SYSTEM_USER_HEADER,
per_image_prefix_ids=(27, 1805, 220, 16, 29, 151670), # `<image 1><img>` (arch-n15 §4.2)
per_image_prefix_len=6,
per_image_suffix_len=1,
suffix_ids=(151645, 198, 151644, 77091, 198), # `<|im_end|>\n<|im_start|>assistant\n`
text_extra_ids=(677, 660), # `['` and `']` of repr([instruction]) (critique C4)
fixed_tokens_formula="S = 14 + 263*V + 2 + n_text + 5",
),
embodiment_ids=_N15_EMBODIMENTS,
canonical_embodiment="gr1",
canonical_layout_name="gr1",
layouts=(
LayoutConfig(
name="gr1",
embodiment_tag="gr1",
embodiment_id=24,
n_cameras=1,
n_images=1,
grid_thw=None,
patches_per_image=256,
patch_rows_pad=256,
tokens_per_image=256,
s_golden=296,
s_typical="296-297",
s_pad_llm=384,
s_pad_llm_unpatched=384,
s_pad_vl=384,
l_max=102,
text_padding="right",
image_slots=((20, 276),),
non_image_slots=None,
dit_m_logical=49,
dit_m_pad=64,
cross_image_keys=None,
cross_text_keys=None,
cross_all_keys=(296, 384),
state_shape=(1, 1, 64),
noise_shape=(1, 16, 32),
valid_slice=(16, 26),
action_groups=_N15_GROUPS,
rope_table="constant_arange",
notes="S_pad_vl 320 (10 tiles) is the tighter alternative (static-shape-plan §4.2/§5).",
),
LayoutConfig(
name="v3",
embodiment_tag="oxe_droid",
embodiment_id=17,
n_cameras=3,
n_images=3,
grid_thw=None,
patches_per_image=256,
patch_rows_pad=256,
tokens_per_image=256,
s_golden=None,
s_typical="813-817",
s_pad_llm=896,
s_pad_llm_unpatched=1024,
s_pad_vl=896,
l_max=88,
text_padding="right",
image_slots=((20, 276), (283, 539), (546, 802)),
non_image_slots=None,
dit_m_logical=49,
dit_m_pad=64,
cross_image_keys=None,
cross_text_keys=None,
cross_all_keys=(816, 896),
state_shape=(1, 1, 64),
noise_shape=(1, 16, 32),
valid_slice=(16, 26),
action_groups=_N15_GROUPS,
rope_table="constant_arange",
notes="DROID (id 17) / AgiBot (id 26), no golden; S_pad_vl 832 alternative.",
),
),
)
# --------------------------------------------------------------------------------------------------------------------
# N1.6
# --------------------------------------------------------------------------------------------------------------------
_N16_EMBODIMENTS: Dict[str, int] = { # arch-n16 §3.4 (processing_gr00t_n1d6.py:33-45 merged with embodiment_id.json)
"gr1": 20,
"robocasa_panda_omron": 13,
"behavior_r1_pro": 24,
"unitree_g1": 8,
"oxe_google": 0,
"oxe_widowx": 1,
"libero_panda": 2,
"oxe_droid": 16,
"new_embodiment": 10,
}
_N16_GROUPS = ("left_arm", "right_arm", "left_hand", "right_hand", "waist")
N16_CONFIG = GR00TConfig(
version="n16",
display_name="GR00T-N1.6-3B",
reference_code="Isaac-GR00T-n1.6 (n1.6.1-release, 5dc80c4a)",
golden_dir="n16",
checkpoint=CheckpointConfig(
hf_repo=HF_REPOS["n16"],
hf_sha=HF_SNAPSHOT_SHAS["n16"],
n_shards=2,
n_tensors=1106,
n_params=3_286_608_832,
n_bytes=6_573_217_664,
shard_files=("model-00001-of-00002.safetensors", "model-00002-of-00002.safetensors"),
straddling_prefix="action_head.model.transformer_blocks.18.",
vision_prefix="backbone.model.vision_model.",
projector_prefix="backbone.model.mlp1.",
llm_prefix="backbone.model.language_model.model.",
lm_head_key="backbone.model.language_model.lm_head.weight",
vl_self_attention_prefix=None,
),
vision=VisionConfig(
family="siglip2_naflex",
pos_interpolation="bilinear_16_to_18",
image_size=252,
patches_per_image=324,
tokens_per_image=81,
**{**_SIGLIP_COMMON, "merge_size": 2},
),
projector=ProjectorConfig(
kind="unshuffle_ln_mlp",
in_dim=4608,
hidden_dim=2048,
out_dim=2048,
ln_dim=4608,
ln_eps=1e-5,
ln_position="post_concat",
activation="gelu_erf",
merge_channel_order="c*4+dy*2+dx",
image_token_id=151669,
splice="overwrite",
params=13_644_800,
),
llm=LLMConfig(
family="qwen3_1p7b",
n_layers_executed=16,
rope_mode="1d",
rope_theta=1e6,
mrope_section=None,
vocab=151_680,
final_norm_applied=True,
deepstack_add_after_layers=(),
massive_activation_channels=(),
executed_layer_params=805_376_000,
executed_layer_bytes_bf16=1_610_752_000,
**_QWEN3_LLM_COMMON,
),
vl_adapter=VLAdapterConfig(
dim=2048,
vlln_eps=1e-5,
n_blocks=0,
n_heads=32,
head_dim=64,
ff_dim=8192,
ln_eps=1e-5,
activation="gelu_tanh",
attention_bias=True,
masked=False,
reference_dtype="bf16",
params=0,
),
dit=DiTConfig(
class_name="dit.AlternateVLDiT",
n_blocks=32,
cross_key_set="alternate_text_image",
n_query_tokens=51,
n_future_tokens=0,
params_blocks=1_082_671_104,
**_DIT_COMMON,
),
encoders=EncoderConfig(
max_num_embodiments=32,
max_state_dim=128,
max_action_dim=128,
action_horizon=50,
hidden_size=1024,
input_embedding_dim=1536,
state_encoder_dims=(128, 1024, 1536),
action_encoder_w1=(128, 1536),
action_encoder_w2=(3072, 1536),
action_encoder_w3=(1536, 1536),
tau_dim=1536,
tau_order=("sin", "cos"),
tau_max_period=10000.0,
action_decoder_dims=(1024, 1024, 128),
position_embedding_rows=1024,
state_dim_pad=128,
action_dim_pad=128,
used_slot_bytes_bf16=20_300_000,
),
sampler=SamplerConfig(
num_inference_timesteps=4,
num_timestep_buckets=1000,
dt=0.25,
timestep_buckets=_SAMPLER_BUCKETS,
noise_shape=(1, 50, 128),
euler_dtype="bf16",
noise_dtype="bf16",
velocity_rows_from_end=50,
),
preprocessing=PreprocessingConfig(
image_pipeline="LetterBoxPad -> SmallestMaxSize(256, INTER_AREA) -> FractionalCenterCrop(0.95) -> "
"SmallestMaxSize(256, INTER_AREA) -> smart_resize(factor 28) -> PIL BICUBIC 252x252 -> (u8-127.5)/127.5",
crop_fraction=0.95,
shortest_edge=256,
crop_size=243,
resize_interpolation="pil_bicubic",
output_size=252,
smart_resize_factor=28,
smart_resize_min_pixels=4 * 28 * 28,
smart_resize_max_pixels=4096 * 28 * 28,
normalize_offset=127.5,
normalize_scale=127.5,
uint8_truncation_before_processor=False,
frames_per_camera=1,
image_order="camera",
formalize_language=True,
instruction_as_repr_list=False,
state_normalization="minmax_clip_or_sincos_per_group",
action_decode="clip_relative_minmax_per_step_plus_last_state_waist_absolute",
host_cost_ms=2.0,
),
prompt=PromptConfig(
tokenizer="qwen2_bpe_eagle3",
vocab_entries=151_680,
pad_id=_PAD_ID,
eos_id=_IM_END,
im_start_id=_IM_START,
im_end_id=_IM_END,
newline_id=_NEWLINE,
image_token_id=151669,
image_open_id=151670,
image_close_id=151671,
add_bos=False,
layout="text_then_images",
system_prompt=True,
generation_prompt=False,
header_ids=_SYSTEM_USER_HEADER,
per_image_prefix_ids=(27, 1805, 220, 16, 29, 151670), # `<image 1>` (5) + `<img>` (arch-n16 §4.2)
per_image_prefix_len=6,
per_image_suffix_len=1,
suffix_ids=(151645, 198), # `<|im_end|>\n`
text_extra_ids=(),
fixed_tokens_formula="S = 16 + 88*V + n_text",
),
embodiment_ids=_N16_EMBODIMENTS,
canonical_embodiment="gr1",
canonical_layout_name="gr1",
layouts=(
LayoutConfig(
name="gr1",
embodiment_tag="gr1",
embodiment_id=20,
n_cameras=1,
n_images=1,
grid_thw=None,
patches_per_image=324,
patch_rows_pad=352,
tokens_per_image=81,
s_golden=116,
s_typical="116-117",
s_pad_llm=128,
s_pad_llm_unpatched=128,
s_pad_vl=128,
l_max=24,
text_padding="text_slot",
image_slots=((44, 125),),
non_image_slots=47,
dit_m_logical=51,
dit_m_pad=64,
cross_image_keys=(81, 96),
cross_text_keys=(47, 64),
cross_all_keys=None,
state_shape=(1, 1, 128),
noise_shape=(1, 50, 128),
valid_slice=(16, 29),
action_groups=_N16_GROUPS,
rope_table="per_call_rows",
notes="With L_max=24: `<image 1><img>` [38,44), IMG [44,125), `</img>` 125, `<|im_end|>\\n` 126-127.",
),
LayoutConfig(
name="gr1_long_text",
embodiment_tag="gr1",
embodiment_id=20,
n_cameras=1,
n_images=1,
grid_thw=None,
patches_per_image=324,
patch_rows_pad=352,
tokens_per_image=81,
s_golden=None,
s_typical="up to 232",
s_pad_llm=256,
s_pad_llm_unpatched=256,
s_pad_vl=256,
l_max=152,
text_padding="text_slot",
image_slots=((172, 253),),
non_image_slots=175,
dit_m_logical=51,
dit_m_pad=64,
cross_image_keys=(81, 96),
cross_text_keys=(175, 192),
cross_all_keys=None,
state_shape=(1, 1, 128),
noise_shape=(1, 50, 128),
valid_slice=(16, 29),
action_groups=_N16_GROUPS,
rope_table="per_call_rows",
),
LayoutConfig(
name="v3",
embodiment_tag="robocasa_panda_omron",
embodiment_id=13,
n_cameras=3,
n_images=3,
grid_thw=None,
patches_per_image=324,
patch_rows_pad=352,
tokens_per_image=81,
s_golden=None,
s_typical="291",
s_pad_llm=384,
s_pad_llm_unpatched=384,
s_pad_vl=384,
l_max=104,
text_padding="text_slot",
image_slots=((124, 205), (212, 293), (300, 381)),
non_image_slots=141,
dit_m_logical=51,
dit_m_pad=64,
cross_image_keys=(243, 256),
cross_text_keys=(141, 160),
cross_all_keys=None,
state_shape=(1, 1, 128),
noise_shape=(1, 50, 128),
valid_slice=(16, 29),
action_groups=_N16_GROUPS,
rope_table="per_call_rows",
notes="robocasa_panda_omron (13) / behavior_r1_pro (24); no golden.",
),
),
)
# --------------------------------------------------------------------------------------------------------------------
# N1.7
# --------------------------------------------------------------------------------------------------------------------
_N17_EMBODIMENTS: Dict[str, int] = { # arch-n17 §4.3/§4.4 (processing_gr00t_n1d7.py:69-118 + embodiment_id.json)
"oxe_droid_relative_eef_relative_joint": 24,
"real_g1_relative_eef_relative_joints": 25,
"real_r1_pro_sharpa_relative_eef": 26,
"real_r1_pro_sharpa_relative_eef_human": 26,
"real_r1_pro_sharpa_relative_eef_maxinsights": 26,
"real_r1_pro_sharpa_relative_eef_mecka": 26,
"xdof_relative_eef_relative_joint": 27,
"xdof_relative_eef_relative_joint_subtask": 27,
"new_embodiment": 10,
}
_N17_DROID_GROUPS = ("eef_9d", "gripper_position", "joint_position")
_N17_G1_GROUPS = (
"left_wrist_eef_9d",
"right_wrist_eef_9d",
"left_hand",
"right_hand",
"left_arm",
"right_arm",
"waist",
"base_height_command",
"navigate_command",
)
N17_CONFIG = GR00TConfig(
version="n17",
display_name="GR00T-N1.7-3B",
reference_code="Isaac-GR00T (main, 51d4c89f)",
golden_dir="n17",
checkpoint=CheckpointConfig(
hf_repo=HF_REPOS["n17"],
hf_sha=HF_SNAPSHOT_SHAS["n17"],
n_shards=2,
n_tensors=1031,
n_params=3_455_180_928,
n_bytes=6_910_361_856,
shard_files=("model-00001-of-00002.safetensors", "model-00002-of-00002.safetensors"),
straddling_prefix="action_head.model.transformer_blocks.19.",
vision_prefix="backbone.model.model.visual.",
projector_prefix=None, # the merger lives inside `visual.` (weight-loader §2.3 rule 3)
llm_prefix="backbone.model.model.language_model.",
lm_head_key="backbone.model.lm_head.weight",
vl_self_attention_prefix="action_head.vl_self_attention.",
),
vision=VisionConfig(
family="qwen3vl",
n_layers=24,
hidden=1024,
n_heads=16,
head_dim=64,
mlp_dim=4096,
activation="gelu_tanh",
ln_eps=1e-6,
attention_bias=True,
qkv_fused_in_checkpoint=True,
patch_size=16,
temporal_patch=2,
patch_in_features=1536,
patch_column_order="(c,t,ph,pw)",
pos_table_rows=2304,
pos_grid=48,
pos_interpolation="bilinear_4tap_per_grid",
image_size=None,
patches_per_image=None,
tokens_per_image=None,
merge_size=2,
frames_per_camera=2,
rope="2d",
rope_theta=1e4,
rope_freqs_per_axis=16,
post_layernorm=False,
deepstack_layers=(5, 11, 17),
head_dim_pad=64,
patch_in_features_pad=1536,
dynamic_min_pixels=65_536,
dynamic_factor=32,
executed_params=406_957_056,
executed_bytes_bf16=813_914_112,
),
projector=ProjectorConfig(
kind="qwen3vl_merger",
in_dim=4096,
hidden_dim=4096,
out_dim=2048,
ln_dim=1024,
ln_eps=1e-6,
ln_position="pre_concat",
activation="gelu_erf",
merge_channel_order="(mh,mw,c)",
image_token_id=151655,
splice="masked_scatter",
n_deepstack=3,
deepstack_ln_dim=4096,
params=25_174_016,
params_deepstack_each=25_180_160,
),
llm=LLMConfig(
family="qwen3vl_2b_text",
n_layers_executed=16,
rope_mode="mrope_interleaved",
rope_theta=5e6,
mrope_section=(24, 20, 20),
vocab=151_936,
final_norm_applied=False,
deepstack_add_after_layers=(0, 1, 2),
massive_activation_channels=(1793,),
executed_layer_params=805_376_000,
executed_layer_bytes_bf16=1_610_752_000,
**_QWEN3_LLM_COMMON,
),
vl_adapter=VLAdapterConfig(
dim=2048,
vlln_eps=1e-5,
n_blocks=4,
n_heads=32,
head_dim=64,
ff_dim=8192,
ln_eps=1e-5,
activation="gelu_tanh",
attention_bias=True,
masked=False,
reference_dtype="bf16",
params=201_433_088,
),
dit=DiTConfig(
class_name="dit.AlternateVLDiT",
n_blocks=32,
cross_key_set="alternate_text_image",
n_query_tokens=41,
n_future_tokens=0,
params_blocks=1_082_671_104,
**_DIT_COMMON,
),
encoders=EncoderConfig(
max_num_embodiments=32,
max_state_dim=132,
max_action_dim=132,
action_horizon=40,
hidden_size=1024,
input_embedding_dim=1536,
state_encoder_dims=(132, 1024, 1536),
action_encoder_w1=(132, 1536),
action_encoder_w2=(3072, 1536),
action_encoder_w3=(1536, 1536),
tau_dim=1536,
tau_order=("sin", "cos"),
tau_max_period=10000.0,
action_decoder_dims=(1024, 1024, 132),
position_embedding_rows=1024,
state_dim_pad=160,
action_dim_pad=160,
used_slot_bytes_bf16=20_400_000,
),
sampler=SamplerConfig(
num_inference_timesteps=4,
num_timestep_buckets=1000,
dt=0.25,
timestep_buckets=_SAMPLER_BUCKETS,
noise_shape=(1, 40, 132),
euler_dtype="bf16",
noise_dtype="bf16",
velocity_rows_from_end=40,
),
preprocessing=PreprocessingConfig(
image_pipeline="SmallestMaxSize(256, INTER_AREA) -> FractionalCenterCrop(0.95) -> SmallestMaxSize(256) -> "
"Qwen2VLImageProcessor: smart_resize(factor 32, min 65536 px) bicubic+antialias -> (u8-127.5)/127.5 -> "
"T=2 duplicate -> patchify (c,t,ph,pw) -> [n_patches, 1536]",
crop_fraction=0.95,
shortest_edge=256,
crop_size=243,
resize_interpolation="qwen2vl_bicubic_antialias",
output_size=None,
smart_resize_factor=32,
smart_resize_min_pixels=65_536,
smart_resize_max_pixels=16_777_216,
normalize_offset=127.5,
normalize_scale=127.5,
uint8_truncation_before_processor=False,
frames_per_camera=2,
image_order="frame_major",
formalize_language=True,
instruction_as_repr_list=False,
state_normalization="q01q99_clip",
action_decode="clip_relative_minmax_per_step_rot6d_se3_compose_plus_last_state_absolute_q01q99",
host_cost_ms=10.0,
),
prompt=PromptConfig(
tokenizer="qwen2_bpe_cosmos_reason2",
vocab_entries=151_669,
pad_id=_PAD_ID,
eos_id=_IM_END,
im_start_id=_IM_START,
im_end_id=_IM_END,
newline_id=_NEWLINE,
image_token_id=151655,
image_open_id=151652,
image_close_id=151653,
add_bos=False,
layout="images_then_text_no_system",
system_prompt=False,
generation_prompt=False,
header_ids=(151644, 872, 198), # `<|im_start|>user\n` (arch-n17 §1.3)
per_image_prefix_ids=(151652,), # `<|vision_start|>`
per_image_prefix_len=1,
per_image_suffix_len=1,
suffix_ids=(151645, 198), # `<|im_end|>\n`
text_extra_ids=(),
fixed_tokens_formula="S = 5 + n_img*(T_img + 2) + n_text",
),
embodiment_ids=_N17_EMBODIMENTS,
canonical_embodiment="oxe_droid_relative_eef_relative_joint",
canonical_layout_name="droid",
layouts=(
LayoutConfig(
name="droid",
embodiment_tag="oxe_droid_relative_eef_relative_joint",
embodiment_id=24,
n_cameras=2,
n_images=4,
grid_thw=(1, 16, 28),
patches_per_image=448,
patch_rows_pad=448,
tokens_per_image=112,
s_golden=469,
s_typical="469-473",
s_pad_llm=512,
s_pad_llm_unpatched=512,
s_pad_vl=512,
l_max=51,
text_padding="right",
image_slots=((4, 116), (118, 230), (232, 344), (346, 458)),
non_image_slots=64,
dit_m_logical=41,
dit_m_pad=64,
cross_image_keys=(448, 448),
cross_text_keys=(64, 64),
cross_all_keys=None,
state_shape=(1, 1, 132),
noise_shape=(1, 40, 132),
valid_slice=(40, 17),
action_groups=_N17_DROID_GROUPS,
rope_table="constant_mrope_per_layout",
notes="320x180 -> 455x256 -> 448x256 (16:9); mRoPE slot j >= 459 -> position j - 392; S_pad_vl 480 alt.",
),
LayoutConfig(
name="g1_4x3",
embodiment_tag="real_g1_relative_eef_relative_joints",
embodiment_id=25,
n_cameras=1,
n_images=2,
grid_thw=(1, 16, 22),
patches_per_image=352,
patch_rows_pad=352,
tokens_per_image=88,
s_golden=None,
s_typical="~196",
s_pad_llm=256,
s_pad_llm_unpatched=256,
s_pad_vl=256,
l_max=71,
text_padding="right",
image_slots=((4, 92), (94, 182)),
non_image_slots=80,
dit_m_logical=41,
dit_m_pad=64,
cross_image_keys=(176, 192),
cross_text_keys=(80, 96),
cross_all_keys=None,
state_shape=(1, 1, 132),
noise_shape=(1, 40, 132),
valid_slice=(40, 53),
action_groups=_N17_G1_GROUPS,
rope_table="constant_mrope_per_layout",
notes="4:3 aspect assumed from key names (UNVERIFIED, synthesis §6 #11); the only G1 golden is 16:9 synthetic.",
),
LayoutConfig(
name="g1_synthetic_16x9",
embodiment_tag="real_g1_relative_eef_relative_joints",
embodiment_id=25,
n_cameras=1,
n_images=2,
grid_thw=(1, 16, 28),
patches_per_image=448,
patch_rows_pad=448,
tokens_per_image=112,
s_golden=243,
s_typical="243",
s_pad_llm=256,
s_pad_llm_unpatched=256,
s_pad_vl=256,
l_max=23,
text_padding="right",
image_slots=((4, 116), (118, 230)),
non_image_slots=32,
dit_m_logical=41,
dit_m_pad=64,
cross_image_keys=(224, 224),
cross_text_keys=(32, 32),
cross_all_keys=None,
state_shape=(1, 1, 132),
noise_shape=(1, 40, 132),
valid_slice=(40, 53),
action_groups=_N17_G1_GROUPS,
rope_table="constant_mrope_per_layout",
notes="golden/n17/g1_synthetic_*: DROID frames with the G1 embodiment id (golden-tap-map §8 item 6).",
),
LayoutConfig(
name="cam3_4x3",
embodiment_tag="xdof_relative_eef_relative_joint",
embodiment_id=27,
n_cameras=3,
n_images=6,
grid_thw=(1, 16, 22),
patches_per_image=352,
patch_rows_pad=352,
tokens_per_image=88,
s_golden=None,
s_typical="~556",
s_pad_llm=640,
s_pad_llm_unpatched=1024,
s_pad_vl=640,
l_max=95,
text_padding="right",
image_slots=((4, 92), (94, 182), (184, 272), (274, 362), (364, 452), (454, 542)),
non_image_slots=112,
dit_m_logical=41,
dit_m_pad=64,
cross_image_keys=(528, 544),
cross_text_keys=(112, 128),
cross_all_keys=None,
state_shape=(1, 1, 132),
noise_shape=(1, 40, 132),
valid_slice=(40, 14),
action_groups=(),
rope_table="constant_mrope_per_layout",
notes="XDOF (27) / R1-Pro Sharpa (26); valid dims 14 (XDOF) or 62 (R1-Pro); no golden.",
),
),
)
_CONFIGS: Mapping[str, GR00TConfig] = {"n15": N15_CONFIG, "n16": N16_CONFIG, "n17": N17_CONFIG}
def get_config(version: str) -> GR00TConfig:
"""Return the frozen config of ``version`` ('n15' | 'n16' | 'n17')."""
_check_version(version)
return _CONFIGS[version]
def all_configs() -> Tuple[GR00TConfig, ...]:
return tuple(_CONFIGS[v] for v in GR00T_VERSIONS)
# Tile facts shared by every static-shape decision (static-shape-plan.md §1).
TILE = 32
LLM_SEQ_PAD_MULTIPLE = 128
LLM_SEQ_PAD_MULTIPLE_UNPATCHED_MLP = 512
DIT_QUERY_ROWS_PAD = 64
DIT_HEAD_DIM_PAD = 64
SIGLIP_HEAD_DIM_PAD = 96
# Blackhole p150a as measured (00-device-facts.md).
DEVICE_COMPUTE_GRID = (11, 10)
DEVICE_L1_BYTES_PER_CORE = 1536 * 1024
DEVICE_DRAM_CHANNELS = 8