Skip to content
Back to skills

Tiadar Diffusion Autoregressive Hybrid

ASecurity

Combine diffusion-based parallel drafting with autoregressive sampling in a single forward pass using structured attention masks—achieving 5x+ token throughput while maintaining autoregressive-level output quality through hybrid generation.

  • 6 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 9, 2026
businesspythongit

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add ADu2021/skillXiv --skill tiadar-diffusion-autoregressive-hybrid --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Tiadar Diffusion Autoregressive Hybrid?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Tiadar Diffusion Autoregressive Hybrid
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adu2021-tiadar-diffusion-autoregressive-hybrid/badge)](https://www.skillsdirectory.com/skills/adu2021-tiadar-diffusion-autoregressive-hybrid)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: tiadar-diffusion-autoregressive-hybrid
title: "TiDAR: Think in Diffusion, Talk in Autoregression"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: "https://arxiv.org/abs/2511.08923"
keywords: [Hybrid Architecture, Diffusion Models, Autoregressive Language, Parallel Generation, Token Throughput]
description: "Combine diffusion-based parallel drafting with autoregressive sampling in a single forward pass using structured attention masks—achieving 5x+ token throughput while maintaining autoregressive-level output quality through hybrid generation."
---

# Hybrid Diffusion-Autoregressive Generation for High-Throughput Language Models

Autoregressive language models are high-quality but slow (one token per forward pass). Diffusion models generate tokens in parallel but with lower quality. TiDAR merges both paradigms: diffusion generates candidate tokens in parallel (drafting phase), then autoregression selects final outputs sequentially (refinement phase)—all in a single forward pass using structured attention.

The approach achieves 4.71x to 5.91x tokens per second compared to pure autoregression while maintaining comparable quality, solving a fundamental speed-quality tradeoff.

## Core Concept

TiDAR operates in two phases within one neural forward pass:

1. **Thinking (Diffusion)** - Parallel iterative refinement generates k candidate tokens for each position
2. **Talking (Autoregression)** - Sequential sampling selects final tokens using context and diffusion candidates

Structured attention masks enable this hybrid within a single transformer: diffusion layers have all-to-all connectivity (parallel thinking), while autoregressive layers have causal masks (sequential talking). The architecture transitions smoothly between thinking and talking phases.

## Architecture Overview

- **Diffusion Thinking Layers**: Parallel token generation with iterative refinement
- **Structured Attention Masks**: All-to-all for diffusion; causal for autoregression
- **Candidate Representation**: Stores k candidate tokens per position for AR selection
- **Autoregressive Refinement**: Sequential sampling from diffusion candidates
- **Hybrid Router**: Decides when to transition from diffusion to autoregressive phase
- **Efficient Masking**: Single forward pass enables gradient flow through both paradigms

## Implementation Steps

**Step 1: Diffusion-Based Candidate Generation**

Generate multiple token candidates per position through iterative diffusion.

```python
import torch
import torch.nn as nn
import torch.nn.functional as F

class DiffusionTokenGenerator(nn.Module):
    """
    Generates token candidates through diffusion-style iterative refinement.
    """

    def __init__(self, vocab_size: int, embed_dim: int, num_candidates: int = 8,
                 num_diffusion_steps: int = 4):
        """
        Args:
            vocab_size: Size of vocabulary
            embed_dim: Embedding dimension
            num_candidates: Number of candidate tokens per position
            num_diffusion_steps: Refinement iterations
        """
        super().__init__()
        self.vocab_size = vocab_size
        self.embed_dim = embed_dim
        self.num_candidates = num_candidates
        self.num_diffusion_steps = num_diffusion_steps

        # Learnable noise scheduler
        self.noise_schedule = nn.Parameter(
            torch.linspace(1.0, 0.0, num_diffusion_steps)
        )

        # Refinement layers
        self.refinement_layers = nn.ModuleList([
            nn.Linear(embed_dim, embed_dim) for _ in range(num_diffusion_steps)
        ])

    def generate_candidates(self, hidden_states: torch.Tensor) -> torch.Tensor:
        """
        Generate candidate tokens through diffusion.

        Args:
            hidden_states: Model hidden states [batch_size, seq_len, embed_dim]

        Returns:
            candidates: Candidate logits [batch_size, seq_len, num_candidates, vocab_size]
        """
        batch_size, seq_len, embed_dim = hidden_states.shape
        device = hidden_states.device

        # Initialize candidates with noise
        # Start from uniform random; refine toward true distribution
        candidates = torch.randn(
            batch_size, seq_len, self.num_candidates, embed_dim,
            device=device
        )

        # Iterative refinement (diffusion steps)
        for step in range(self.num_diffusion_steps):
            noise_level = self.noise_schedule[step]

            # Refine candidates with context
            # Attend to hidden states to bias candidates toward relevant tokens
            refined = candidates + hidden_states.unsqueeze(2)  # Add context bias
            refined = self.refinement_layers[step](refined)

            # Gradually remove noise
            candidates = refined * (1 - noise_level) + \
                        torch.randn_like(refined) * noise_level

        # Project to logits
        # Map embedding space to vocabulary
        logits = torch.matmul(
            candidates,
            torch.randn(embed_dim, self.vocab_size, device=device)
        )

        return logits
```

**Step 2: Structured Attention Masks**

Create attention patterns enabling diffusion (all-to-all) and autoregression (causal) in one forward pass.

```python
def create_hybrid_attention_mask(batch_size: int, seq_len: int, num_candidates: int,
                                 diffusion_layers: int, ar_layers: int,
                                 device: torch.device) -> Dict[str, torch.Tensor]:
    """
    Create structured attention masks for hybrid architecture.

    Args:
        batch_size: Batch size
        seq_len: Sequence length
        num_candidates: Number of candidates per position
        diffusion_layers: Number of diffusion (all-to-all) layers
        ar_layers: Number of autoregressive (causal) layers
        device: torch device

    Returns:
        masks: {diffusion_mask, ar_mask, candidate_mask}
    """
    # Diffusion mask: all-to-all connectivity (thinking phase)
    # Every position can attend to every other position
    diffusion_mask = torch.ones(
        batch_size, seq_len, seq_len,
        device=device, dtype=torch.bool
    )

    # Autoregressive mask: causal (talking phase)
    # Each position attends to itself and previous positions only
    ar_mask = torch.tril(
        torch.ones(seq_len, seq_len, device=device, dtype=torch.bool)
    ).unsqueeze(0).expand(batch_size, -1, -1)

    # Candidate mask: connections between AR positions and diffusion candidates
    # AR layer can attend to all candidate positions from previous step
    candidate_mask = torch.ones(
        batch_size, seq_len, num_candidates, seq_len,
        device=device, dtype=torch.bool
    )

    return {
        'diffusion_mask': diffusion_mask,
        'ar_mask': ar_mask,
        'candidate_mask': candidate_mask
    }

class HybridAttentionLayer(nn.Module):
    """
    Single attention layer supporting both diffusion and AR patterns.
    """

    def __init__(self, embed_dim: int, num_heads: int = 8):
        super().__init__()
        self.embed_dim = embed_dim
        self.num_heads = num_heads
        self.head_dim = embed_dim // num_heads

        self.query = nn.Linear(embed_dim, embed_dim)
        self.key = nn.Linear(embed_dim, embed_dim)
        self.value = nn.Linear(embed_dim, embed_dim)
        self.output = nn.Linear(embed_dim, embed_dim)

    def forward(self, hidden_states: torch.Tensor, attention_mask: torch.Tensor,
                phase: str = 'diffusion') -> torch.Tensor:
        """
        Apply hybrid attention.

        Args:
            hidden_states: [batch, seq_len, embed_dim]
            attention_mask: Attention mask (diffusion or AR)
            phase: 'diffusion' or 'autoregressive'

        Returns:
            output: Attended states [batch, seq_len, embed_dim]
        """
        batch_size, seq_len, embed_dim = hidden_states.shape

        # Compute Q, K, V
        Q = self.query(hidden_states)
        K = self.key(hidden_states)
        V = self.value(hidden_states)

        # Reshape for multi-head attention
        Q = Q.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
        K = K.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
        V = V.view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)

        # Scaled dot-product attention
        scores = torch.matmul(Q, K.transpose(-2, -1)) / (self.head_dim ** 0.5)

        # Apply mask
        if attention_mask is not None:
            # Mask shape: [batch, 1, seq_len, seq_len]
            scores = scores.masked_fill(~attention_mask.unsqueeze(1), float('-inf'))

        # Softmax and dropout
        attn_weights = F.softmax(scores, dim=-1)
        attn_output = torch.matmul(attn_weights, V)

        # Reshape back
        attn_output = attn_output.transpose(1, 2).contiguous()
        attn_output = attn_output.view(batch_size, seq_len, embed_dim)

        # Output projection
        output = self.output(attn_output)

        return output
```

**Step 3: Autoregressive Refinement from Candidates**

Select final tokens from diffusion candidates using autoregressive sampling.

```python
class AutoregressiveRefinement(nn.Module):
    """
    Refines diffusion candidates through autoregressive sampling.
    """

    def __init__(self, vocab_size: int, embed_dim: int):
        super().__init__()
        self.vocab_size = vocab_size
        self.embed_dim = embed_dim

        # Selection network: learns to pick best candidate
        self.selector = nn.Sequential(
            nn.Linear(embed_dim + vocab_size, embed_dim),
            nn.ReLU(),
            nn.Linear(embed_dim, 1)
        )

    def select_tokens(self, candidates_logits: torch.Tensor,
                     context_hidden: torch.Tensor) -> torch.Tensor:
        """
        Select best candidate tokens given context.

        Args:
            candidates_logits: [batch, seq_len, num_candidates, vocab_size]
            context_hidden: [batch, seq_len, embed_dim]

        Returns:
            selected_tokens: [batch, seq_len, vocab_size]
        """
        batch_size, seq_len, num_candidates, vocab_size = candidates_logits.shape

        # Compute candidate probabilities
        candidate_probs = F.softmax(candidates_logits, dim=-1)

        # Score each candidate position
        scores = []
        for c in range(num_candidates):
            # Get probabilities for this candidate set
            cand_probs = candidate_probs[:, :, c, :]

            # Combine with context
            combined = torch.cat([
                context_hidden,
                cand_probs
            ], dim=-1)

            # Compute selection score
            score = self.selector(combined).squeeze(-1)
            scores.append(score)

        scores = torch.stack(scores, dim=-1)  # [batch, seq_len, num_candidates]

        # Select highest-scoring candidate per position
        selected_idx = torch.argmax(scores, dim=-1)  # [batch, seq_len]

        # Gather selected logits
        selected_logits = torch.gather(
            candidates_logits,
            2,
            selected_idx.unsqueeze(-1).unsqueeze(-1).expand(-1, -1, 1, vocab_size)
        ).squeeze(2)

        return selected_logits
```

**Step 4: Unified Forward Pass**

Combine diffusion thinking and AR talking into single forward pass.

```python
class TiDARModel(nn.Module):
    """
    Unified model combining diffusion thinking with autoregressive talking.
    """

    def __init__(self, vocab_size: int, embed_dim: int, num_candidates: int = 8,
                 num_diffusion_layers: int = 6, num_ar_layers: int = 6):
        super().__init__()
        self.vocab_size = vocab_size
        self.embed_dim = embed_dim
        self.num_candidates = num_candidates

        # Embedding layer
        self.embedding = nn.Embedding(vocab_size, embed_dim)

        # Diffusion thinking layers
        self.diffusion_layers = nn.ModuleList([
            HybridAttentionLayer(embed_dim) for _ in range(num_diffusion_layers)
        ])
        self.diffusion_generator = DiffusionTokenGenerator(
            vocab_size, embed_dim, num_candidates
        )

        # Autoregressive talking layers
        self.ar_layers = nn.ModuleList([
            HybridAttentionLayer(embed_dim) for _ in range(num_ar_layers)
        ])
        self.ar_refinement = AutoregressiveRefinement(vocab_size, embed_dim)

        # Output projection
        self.to_logits = nn.Linear(embed_dim, vocab_size)

    def forward(self, input_ids: torch.Tensor) -> torch.Tensor:
        """
        Generate tokens through hybrid diffusion-autoregressive process.

        Args:
            input_ids: [batch_size, seq_len]

        Returns:
            logits: [batch_size, seq_len, vocab_size]
        """
        batch_size, seq_len = input_ids.shape
        device = input_ids.device

        # Embed input
        hidden = self.embedding(input_ids)

        # PHASE 1: Diffusion thinking (all-to-all connectivity)
        diffusion_mask = torch.ones(seq_len, seq_len, device=device, dtype=torch.bool)

        for layer in self.diffusion_layers:
            hidden = layer(hidden, diffusion_mask, phase='diffusion')
            hidden = F.relu(hidden)

        # Generate candidate tokens
        candidates_logits = self.diffusion_generator.generate_candidates(hidden)

        # PHASE 2: Autoregressive talking (causal mask)
        ar_mask = torch.tril(torch.ones(seq_len, seq_len, device=device, dtype=torch.bool))

        for layer in self.ar_layers:
            hidden = layer(hidden, ar_mask, phase='autoregressive')
            hidden = F.relu(hidden)

        # Refine candidates through AR
        final_logits = self.ar_refinement.select_tokens(candidates_logits, hidden)

        return final_logits

    def generate(self, input_ids: torch.Tensor, max_new_tokens: int = 100) -> torch.Tensor:
        """
        Generate text token-by-token using hybrid approach.

        Args:
            input_ids: [batch_size, seq_len]
            max_new_tokens: Maximum tokens to generate

        Returns:
            output_ids: [batch_size, seq_len + max_new_tokens]
        """
        for _ in range(max_new_tokens):
            # Forward pass through hybrid model
            logits = self.forward(input_ids)

            # Sample next token from last position
            next_logits = logits[:, -1, :]
            next_token = torch.argmax(next_logits, dim=-1, keepdim=True)

            # Append to sequence
            input_ids = torch.cat([input_ids, next_token], dim=1)

        return input_ids
```

## Practical Guidance

**When to Use TiDAR:**
- High-throughput inference scenarios (5x+ speedup valuable)
- Scenarios tolerating slight quality reduction for speed
- Long-context generation (diffusion thinking handles global context)

**When NOT to Use:**
- Tasks requiring maximum output quality (pure AR still slightly better)
- Real-time low-latency requirements (diffusion layers add latency)
- Fine-grained token-level control (hybrid approach less interpretable)

**Hyperparameters and Configuration:**
- Number of candidates: 4-8 (tradeoff between diversity and memory)
- Diffusion steps: 2-4 (more steps = better candidates but slower)
- Diffusion vs AR layer ratio: Equal works well (6D+6AR); adjust if needed
- Temperature for candidate selection: 1.0 (deterministic); increase for diversity

**Pitfalls to Avoid:**
1. **Candidate redundancy** - If candidates are too similar, AR selection provides no benefit; increase diffusion steps
2. **Attention mask errors** - Mask shapes must align with attention dimensions; test carefully
3. **Gradient flow issues** - Ensure gradients flow through diffusion candidates into refinement
4. **Memory overhead** - num_candidates increases memory; monitor for OOM

---

Reference: https://arxiv.org/abs/2511.08923

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.