Instructions to use xfcghj/AR with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use xfcghj/AR with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("xfcghj/AR", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
Download models/auto.py from xfcghj/AR: direct link, hf CLI and curl.
- Browser
- Download file 21.1 kB
-
https://huggingface.co/xfcghj/AR/resolve/main/models/auto.py
- Command line
-
hf download hf://xfcghj/AR/models/auto.py
-
curl -L -o auto.py https://huggingface.co/xfcghj/AR/resolve/main/models/auto.py
21.1 kB
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| def _init_linear_identity(linear): | |
| if linear.weight.shape[0] != linear.weight.shape[1]: | |
| raise ValueError( | |
| "Identity initialization requires a square Linear layer. " | |
| f"Got weight shape {tuple(linear.weight.shape)}." | |
| ) | |
| nn.init.eye_(linear.weight) | |
| if linear.bias is not None: | |
| nn.init.constant_(linear.bias, 0) | |
| def _zero_linear(linear): | |
| nn.init.constant_(linear.weight, 0) | |
| if linear.bias is not None: | |
| nn.init.constant_(linear.bias, 0) | |
| def _zero_last_linear(module): | |
| for layer in reversed(module): | |
| if isinstance(layer, nn.Linear): | |
| _zero_linear(layer) | |
| return | |
| raise ValueError("Expected at least one Linear layer.") | |
| def _init_layer_norm_identity(norm): | |
| nn.init.constant_(norm.weight, 1) | |
| nn.init.constant_(norm.bias, 0) | |
| class RotaryEmbedding(nn.Module): | |
| """Rotary positional embedding for temporal self-attention.""" | |
| def __init__(self, dim, max_seq_len=2048): | |
| super().__init__() | |
| if dim % 2 != 0: | |
| raise ValueError(f"RoPE head dim must be even, got {dim}.") | |
| self.dim = dim | |
| self.max_seq_len = max_seq_len | |
| inv_freq = 1.0 / (10000 ** (torch.arange(0, dim, 2).float() / dim)) | |
| self.register_buffer("inv_freq", inv_freq, persistent=True) | |
| self._set_cos_sin_cache(max_seq_len, device=torch.device("cpu")) | |
| def _set_cos_sin_cache(self, seq_len, device): | |
| self.max_seq_len = seq_len | |
| t = torch.arange(seq_len, device=device, dtype=torch.float32) | |
| freqs = torch.einsum("i,j->ij", t, self.inv_freq.to(device)) | |
| emb = torch.cat((freqs, freqs), dim=-1) | |
| self.register_buffer("cos_cached", emb.cos()[None, None, :, :], persistent=False) | |
| self.register_buffer("sin_cached", emb.sin()[None, None, :, :], persistent=False) | |
| def _rotate_half(x): | |
| x1 = x[..., : x.shape[-1] // 2] | |
| x2 = x[..., x.shape[-1] // 2 :] | |
| return torch.cat((-x2, x1), dim=-1) | |
| def forward(self, x, seq_len): | |
| if seq_len > self.max_seq_len or self.cos_cached.device != x.device: | |
| self._set_cos_sin_cache(seq_len=max(seq_len, self.max_seq_len), device=x.device) | |
| cos = self.cos_cached[..., :seq_len, :].to(dtype=x.dtype) | |
| sin = self.sin_cached[..., :seq_len, :].to(dtype=x.dtype) | |
| return (x * cos) + (self._rotate_half(x) * sin) | |
| class TransformerLayer(nn.Module): | |
| """Pre-LN temporal self-attention layer.""" | |
| def __init__(self, token_dim, num_heads, dim_feedforward, dropout): | |
| super().__init__() | |
| if token_dim % num_heads != 0: | |
| raise ValueError(f"token_dim={token_dim} must be divisible by num_heads={num_heads}.") | |
| self.num_heads = num_heads | |
| self.head_dim = token_dim // num_heads | |
| self.dropout = dropout | |
| self.qkv = nn.Linear(token_dim, token_dim * 3) | |
| self.out_proj = nn.Linear(token_dim, token_dim) | |
| self.norm1 = nn.LayerNorm(token_dim) | |
| self.norm2 = nn.LayerNorm(token_dim) | |
| self.ffn = nn.Sequential( | |
| nn.Linear(token_dim, dim_feedforward), | |
| nn.GELU(), | |
| nn.Dropout(dropout), | |
| nn.Linear(dim_feedforward, token_dim), | |
| nn.Dropout(dropout), | |
| ) | |
| self._init_identity_weights() | |
| def _init_identity_weights(self): | |
| _zero_linear(self.out_proj) | |
| _zero_last_linear(self.ffn) | |
| _init_layer_norm_identity(self.norm1) | |
| _init_layer_norm_identity(self.norm2) | |
| def forward(self, x, rope=None, mask=None): | |
| residual = x | |
| x = self.norm1(x) | |
| batch_size, seq_len, token_dim = x.shape | |
| q, k, v = self.qkv(x).chunk(3, dim=-1) | |
| q = q.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2).contiguous() | |
| k = k.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2).contiguous() | |
| v = v.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2).contiguous() | |
| if rope is not None: | |
| q = rope(q, seq_len=seq_len) | |
| k = rope(k, seq_len=seq_len) | |
| x = F.scaled_dot_product_attention( | |
| q, | |
| k, | |
| v, | |
| attn_mask=mask, | |
| dropout_p=self.dropout if self.training else 0.0, | |
| ) | |
| x = x.transpose(1, 2).reshape(batch_size, seq_len, token_dim).contiguous() | |
| x = residual + self.out_proj(x) | |
| x = x + self.ffn(self.norm2(x)) | |
| return x | |
| class TemporalTrajectoryPredictor(nn.Module): | |
| """ | |
| Temporal predictor without text cross-attention. | |
| Input: history_frames, shape (B, T, N, D), representing frames 0..T-1. | |
| Output: predictions, shape (B, T, N, D), representing next frames 1..T. | |
| Each output step only attends to current and previous input steps through a causal mask. | |
| """ | |
| def __init__( | |
| self, | |
| num_tokens=512, | |
| token_dim=768, | |
| max_seq_len=64, | |
| num_blocks=1, | |
| num_heads=8, | |
| dim_feedforward=2048, | |
| dropout=0.05, | |
| ): | |
| super().__init__() | |
| if token_dim % num_heads != 0: | |
| raise ValueError(f"token_dim={token_dim} must be divisible by num_heads={num_heads}.") | |
| self.num_tokens = num_tokens | |
| self.token_dim = token_dim | |
| self.max_seq_len = max_seq_len | |
| self.num_heads = num_heads | |
| self.head_dim = token_dim // num_heads | |
| self.rope = RotaryEmbedding(self.head_dim, max_seq_len) | |
| self.layers = nn.ModuleList( | |
| [ | |
| TransformerLayer(token_dim, num_heads, dim_feedforward, dropout) | |
| for _ in range(num_blocks) | |
| ] | |
| ) | |
| self.output_projection = nn.Linear(token_dim, token_dim) | |
| self._init_weights() | |
| def _init_weights(self): | |
| _init_linear_identity(self.output_projection) | |
| def _normalize_temporal_mask(mask, seq_len, device): | |
| if mask is None: | |
| return torch.ones((seq_len, seq_len), device=device, dtype=torch.bool).tril().unsqueeze(0).unsqueeze(1) | |
| if mask.dtype != torch.bool: | |
| return (mask < 0) if mask.dtype.is_floating_point else mask.bool() | |
| return mask | |
| def forward(self, history_frames, mask=None, predict_next_only=False): | |
| target_dtype = self.output_projection.weight.dtype | |
| history_frames = history_frames.to(dtype=target_dtype) | |
| batch_size, seq_len, num_tokens, token_dim = history_frames.shape | |
| if token_dim != self.token_dim: | |
| raise ValueError(f"Expected token_dim={self.token_dim}, got {token_dim}.") | |
| x = history_frames.transpose(1, 2).reshape(batch_size * num_tokens, seq_len, token_dim).contiguous() | |
| mask = self._normalize_temporal_mask(mask, seq_len, x.device) | |
| for layer in self.layers: | |
| x = layer(x, rope=self.rope, mask=mask) | |
| if predict_next_only: | |
| x = self.output_projection(x[:, -1:, :]) | |
| return x.reshape(batch_size, num_tokens, 1, token_dim).transpose(1, 2).contiguous() | |
| x = self.output_projection(x) | |
| return x.reshape(batch_size, num_tokens, seq_len, token_dim).transpose(1, 2).contiguous() | |
| class SpatialGraphRefiner(nn.Module): | |
| """Spatial graph refiner without text cross-attention.""" | |
| def __init__( | |
| self, | |
| num_tokens=512, | |
| token_dim=768, | |
| max_graph_dist=10, | |
| num_blocks=3, | |
| num_heads=8, | |
| dim_feedforward=2048, | |
| dropout=0.05, | |
| ): | |
| super().__init__() | |
| if token_dim % num_heads != 0: | |
| raise ValueError(f"token_dim={token_dim} must be divisible by num_heads={num_heads}.") | |
| self.num_tokens = num_tokens | |
| self.token_dim = token_dim | |
| self.max_graph_dist = max_graph_dist | |
| self.num_heads = num_heads | |
| self.head_dim = token_dim // num_heads | |
| self.dropout = dropout | |
| distances = torch.arange(max_graph_dist + 1, dtype=torch.float32) | |
| scales = torch.linspace(0.1, 1.0, num_heads) | |
| self.register_buffer("graph_bias_table", -1.0 * (distances.unsqueeze(1) * scales.unsqueeze(0))) | |
| self.blocks = nn.ModuleList( | |
| [ | |
| nn.ModuleDict( | |
| { | |
| "qkv1": nn.Linear(token_dim, token_dim * 3), | |
| "out1": nn.Linear(token_dim, token_dim), | |
| "ln1": nn.LayerNorm(token_dim), | |
| "qkv2": nn.Linear(token_dim, token_dim * 3), | |
| "out2": nn.Linear(token_dim, token_dim), | |
| "ln2": nn.LayerNorm(token_dim), | |
| "ffn": nn.Sequential( | |
| nn.Linear(token_dim, dim_feedforward), | |
| nn.GELU(), | |
| nn.Dropout(dropout), | |
| nn.Linear(dim_feedforward, token_dim), | |
| nn.Dropout(dropout), | |
| ), | |
| "ln3": nn.LayerNorm(token_dim), | |
| } | |
| ) | |
| for _ in range(num_blocks) | |
| ] | |
| ) | |
| self._init_identity_weights() | |
| def _init_identity_weights(self): | |
| for block in self.blocks: | |
| _zero_linear(block["out1"]) | |
| _zero_linear(block["out2"]) | |
| _zero_last_linear(block["ffn"]) | |
| _init_layer_norm_identity(block["ln1"]) | |
| _init_layer_norm_identity(block["ln2"]) | |
| _init_layer_norm_identity(block["ln3"]) | |
| def _compute_graph_bias(self, shortest_path_matrix, batch_size, seq_len): | |
| num_tokens = shortest_path_matrix.shape[-1] | |
| dist_clipped = torch.clamp(shortest_path_matrix, 0, self.max_graph_dist).long() | |
| bias = F.embedding(dist_clipped, self.graph_bias_table.to(shortest_path_matrix.device)) | |
| if bias.shape[0] == 1 and batch_size > 1: | |
| bias = bias.expand(batch_size, -1, -1, -1) | |
| elif bias.shape[0] != batch_size: | |
| raise ValueError( | |
| "shortest_path_matrix must have batch size 1 or B. " | |
| f"Got {bias.shape[0]} while input batch size is {batch_size}." | |
| ) | |
| return ( | |
| bias.unsqueeze(1) | |
| .expand(-1, seq_len, -1, -1, -1) | |
| .permute(0, 1, 4, 2, 3) | |
| .reshape(batch_size * seq_len, self.num_heads, num_tokens, num_tokens) | |
| ) | |
| def _spatial_attention(self, x, qkv, out, graph_attn_bias): | |
| batch_time, num_tokens, token_dim = x.shape | |
| q, k, v = qkv(x).chunk(3, dim=-1) | |
| q = q.view(batch_time, num_tokens, self.num_heads, self.head_dim).transpose(1, 2).contiguous() | |
| k = k.view(batch_time, num_tokens, self.num_heads, self.head_dim).transpose(1, 2).contiguous() | |
| v = v.view(batch_time, num_tokens, self.num_heads, self.head_dim).transpose(1, 2).contiguous() | |
| attn = F.scaled_dot_product_attention( | |
| q, | |
| k, | |
| v, | |
| attn_mask=graph_attn_bias, | |
| dropout_p=self.dropout if self.training else 0.0, | |
| ) | |
| return out(attn.transpose(1, 2).reshape(batch_time, num_tokens, token_dim)) | |
| def forward(self, next_frame_init, shortest_path_matrix): | |
| target_dtype = self.blocks[0]["qkv1"].weight.dtype | |
| next_frame_init = next_frame_init.to(dtype=target_dtype) | |
| if shortest_path_matrix.dim() == 2: | |
| shortest_path_matrix = shortest_path_matrix.unsqueeze(0) | |
| batch_size, seq_len, num_tokens, token_dim = next_frame_init.shape | |
| if token_dim != self.token_dim: | |
| raise ValueError(f"Expected token_dim={self.token_dim}, got {token_dim}.") | |
| if shortest_path_matrix.shape[-2:] != (num_tokens, num_tokens): | |
| raise ValueError( | |
| "shortest_path_matrix must have shape (B, N, N) or (1, N, N). " | |
| f"Got {tuple(shortest_path_matrix.shape)} for N={num_tokens}." | |
| ) | |
| graph_attn_bias = self._compute_graph_bias(shortest_path_matrix, batch_size, seq_len).to(dtype=target_dtype) | |
| x = next_frame_init.reshape(batch_size * seq_len, num_tokens, token_dim) | |
| for block in self.blocks: | |
| x = x + self._spatial_attention(block["ln1"](x), block["qkv1"], block["out1"], graph_attn_bias) | |
| x = x + self._spatial_attention(block["ln2"](x), block["qkv2"], block["out2"], graph_attn_bias) | |
| x = x + block["ffn"](block["ln3"](x)) | |
| return x.reshape(batch_size, seq_len, num_tokens, token_dim) | |
| class TextConditionedCrossAttentionGate(nn.Module): | |
| """ | |
| Independent text-conditioning module. | |
| It applies two text cross-attention layers, then uses text embeddings to produce | |
| a per-output-dimension gate over the refined features. | |
| """ | |
| def __init__( | |
| self, | |
| token_dim=768, | |
| text_dim=1024, | |
| num_heads=8, | |
| dim_feedforward=2048, | |
| dropout=0.05, | |
| gate_hidden_dim=None, | |
| gate_residual=True, | |
| ): | |
| super().__init__() | |
| if token_dim % num_heads != 0: | |
| raise ValueError(f"token_dim={token_dim} must be divisible by num_heads={num_heads}.") | |
| self.token_dim = token_dim | |
| self.text_dim = text_dim | |
| self.num_heads = num_heads | |
| self.head_dim = token_dim // num_heads | |
| self.dropout = dropout | |
| self.gate_residual = gate_residual | |
| self.cross_attn_1 = self._make_cross_attention_block(token_dim, text_dim, dim_feedforward, dropout) | |
| self.cross_attn_2 = self._make_cross_attention_block(token_dim, text_dim, dim_feedforward, dropout) | |
| hidden_dim = gate_hidden_dim or token_dim | |
| self.gate_norm = nn.LayerNorm(text_dim) | |
| self.gate_mlp = nn.Sequential( | |
| nn.Linear(text_dim, hidden_dim), | |
| nn.GELU(), | |
| nn.Linear(hidden_dim, token_dim), | |
| ) | |
| self.gate_scale = nn.Parameter(torch.zeros(1)) | |
| self._init_identity_weights() | |
| def _init_identity_weights(self): | |
| for block in (self.cross_attn_1, self.cross_attn_2): | |
| _zero_linear(block["out"]) | |
| _zero_last_linear(block["ffn"]) | |
| _init_layer_norm_identity(block["ln1"]) | |
| _init_layer_norm_identity(block["ln2"]) | |
| _init_layer_norm_identity(self.gate_norm) | |
| _zero_last_linear(self.gate_mlp) | |
| def _make_cross_attention_block(token_dim, text_dim, dim_feedforward, dropout): | |
| return nn.ModuleDict( | |
| { | |
| "q": nn.Linear(token_dim, token_dim), | |
| "kv": nn.Linear(text_dim, token_dim * 2), | |
| "out": nn.Linear(token_dim, token_dim), | |
| "ln1": nn.LayerNorm(token_dim), | |
| "ln2": nn.LayerNorm(token_dim), | |
| "ffn": nn.Sequential( | |
| nn.Linear(token_dim, dim_feedforward), | |
| nn.GELU(), | |
| nn.Dropout(dropout), | |
| nn.Linear(dim_feedforward, token_dim), | |
| nn.Dropout(dropout), | |
| ), | |
| } | |
| ) | |
| def _expand_text_for_tokens(text_embed, num_tokens): | |
| batch_size, text_len, text_dim = text_embed.shape | |
| return ( | |
| text_embed.unsqueeze(1) | |
| .expand(batch_size, num_tokens, text_len, text_dim) | |
| .reshape(batch_size * num_tokens, text_len, text_dim) | |
| .contiguous() | |
| ) | |
| def _cross_attention(self, x, text_embed, block): | |
| residual = x | |
| x_norm = block["ln1"](x) | |
| batch_tokens, seq_len, token_dim = x_norm.shape | |
| q = block["q"](x_norm).view(batch_tokens, seq_len, self.num_heads, self.head_dim).transpose(1, 2).contiguous() | |
| k, v = block["kv"](text_embed).chunk(2, dim=-1) | |
| k = k.view(batch_tokens, -1, self.num_heads, self.head_dim).transpose(1, 2).contiguous() | |
| v = v.view(batch_tokens, -1, self.num_heads, self.head_dim).transpose(1, 2).contiguous() | |
| x = F.scaled_dot_product_attention( | |
| q, | |
| k, | |
| v, | |
| attn_mask=None, | |
| dropout_p=self.dropout if self.training else 0.0, | |
| ) | |
| x = x.transpose(1, 2).reshape(batch_tokens, seq_len, token_dim).contiguous() | |
| x = residual + block["out"](x) | |
| x = x + block["ffn"](block["ln2"](x)) | |
| return x | |
| def forward(self, features, text_embed): | |
| target_dtype = self.gate_mlp[0].weight.dtype | |
| features = features.to(dtype=target_dtype) | |
| if text_embed.dim() == 2: | |
| text_embed = text_embed.unsqueeze(1) | |
| text_embed = text_embed.to(dtype=target_dtype) | |
| batch_size, seq_len, num_tokens, token_dim = features.shape | |
| if token_dim != self.token_dim: | |
| raise ValueError(f"Expected token_dim={self.token_dim}, got {token_dim}.") | |
| if text_embed.shape[0] != batch_size: | |
| raise ValueError(f"text_embed batch size must be B={batch_size}, got {text_embed.shape[0]}.") | |
| x = features.transpose(1, 2).reshape(batch_size * num_tokens, seq_len, token_dim).contiguous() | |
| text_for_tokens = self._expand_text_for_tokens(text_embed, num_tokens) | |
| x = self._cross_attention(x, text_for_tokens, self.cross_attn_1) | |
| x = self._cross_attention(x, text_for_tokens, self.cross_attn_2) | |
| x = x.reshape(batch_size, num_tokens, seq_len, token_dim).transpose(1, 2).contiguous() | |
| pooled_text = text_embed.mean(dim=1) | |
| gate = torch.sigmoid(self.gate_mlp(self.gate_norm(pooled_text))).view(batch_size, 1, 1, token_dim) | |
| if self.gate_residual: | |
| return features + self.gate_scale * gate * x | |
| return gate * x | |
| class TrajectorySpatialTextRefinementBlock(nn.Module): | |
| """One group: TemporalTrajectoryPredictor -> SpatialGraphRefiner -> TextConditionedCrossAttentionGate.""" | |
| def __init__(self, temporal_kwargs=None, spatial_kwargs=None, text_kwargs=None): | |
| super().__init__() | |
| temporal_kwargs = temporal_kwargs or {} | |
| spatial_kwargs = spatial_kwargs or {} | |
| text_kwargs = text_kwargs or {} | |
| self.temporal_predictor = TemporalTrajectoryPredictor(**temporal_kwargs) | |
| self.spatial_refiner = SpatialGraphRefiner(**spatial_kwargs) | |
| self.text_refiner = TextConditionedCrossAttentionGate(**text_kwargs) | |
| def forward(self, x, text_embed, shortest_path_matrix, mask=None): | |
| x = self.temporal_predictor(x, mask=mask, predict_next_only=False) | |
| x = self.spatial_refiner(x, shortest_path_matrix=shortest_path_matrix) | |
| x = self.text_refiner(x, text_embed=text_embed) | |
| return x | |
| class StackedTrajectorySpatialTextRefiner(nn.Module): | |
| """ | |
| Composite autoregressive model. | |
| It stacks N groups. Each group contains: | |
| TemporalTrajectoryPredictor + SpatialGraphRefiner + TextConditionedCrossAttentionGate. | |
| Args: | |
| num_groups: number of repeated groups. | |
| temporal_kwargs: either one dict shared by all groups, or a list of dicts. | |
| spatial_kwargs: either one dict shared by all groups, or a list of dicts. | |
| text_kwargs: either one dict shared by all groups, or a list of dicts. | |
| Forward: | |
| history_frames: (B, T, N, D), frames 0..T-1. | |
| text_embed: (B, L_text, text_dim). | |
| shortest_path_matrix: (B, N, N) or (1, N, N). | |
| return: (B, T, N, D), refined predictions for frames 1..T. | |
| """ | |
| def __init__(self, num_groups=1, temporal_kwargs=None, spatial_kwargs=None, text_kwargs=None): | |
| super().__init__() | |
| if num_groups < 1: | |
| raise ValueError(f"num_groups must be >= 1, got {num_groups}.") | |
| temporal_kwargs = self._expand_kwargs(temporal_kwargs, num_groups, "temporal_kwargs") | |
| spatial_kwargs = self._expand_kwargs(spatial_kwargs, num_groups, "spatial_kwargs") | |
| text_kwargs = self._expand_kwargs(text_kwargs, num_groups, "text_kwargs") | |
| self.blocks = nn.ModuleList( | |
| [ | |
| TrajectorySpatialTextRefinementBlock( | |
| temporal_kwargs=temporal_kwargs[i], | |
| spatial_kwargs=spatial_kwargs[i], | |
| text_kwargs=text_kwargs[i], | |
| ) | |
| for i in range(num_groups) | |
| ] | |
| ) | |
| def _expand_kwargs(kwargs, num_groups, name): | |
| if kwargs is None: | |
| return [{} for _ in range(num_groups)] | |
| if isinstance(kwargs, dict): | |
| return [dict(kwargs) for _ in range(num_groups)] | |
| if isinstance(kwargs, (list, tuple)): | |
| if len(kwargs) != num_groups: | |
| raise ValueError(f"{name} length must equal num_groups={num_groups}, got {len(kwargs)}.") | |
| return [dict(item) for item in kwargs] | |
| raise TypeError(f"{name} must be None, a dict, or a list/tuple of dicts.") | |
| def forward(self, history_frames, text_embed, shortest_path_matrix, mask=None): | |
| x = history_frames | |
| for block in self.blocks: | |
| x = block(x, text_embed=text_embed, shortest_path_matrix=shortest_path_matrix, mask=mask) | |
| return x | |