n4nAI

What is multimodal AI and how it processes multiple inputs

A technical definition of multimodal AI covering architecture patterns, cross-modal attention, training objectives, and practical deployment considerations for engineers.

n4n Team6 min read1,416 words

Audio narration

Coming soon — every post will get a voice note here.

Multimodal AI refers to models that jointly process and reason across two or more distinct data modalities — such as text, images, audio, video, or structured data — within a single unified architecture. Unlike ensemble approaches that stitch together separate single-modality models, true multimodal models learn shared representations that capture relationships between modalities, enabling capabilities like visual question answering, image captioning, and cross-modal retrieval. The defining characteristic is not merely accepting multiple inputs, but learning joint distributions that allow reasoning about one modality conditioned on another.

How multimodal architectures work

Most production multimodal systems follow one of three architectural patterns, each with distinct trade-offs for latency, quality, and training cost.

Early fusion with shared encoders

Early fusion projects all modalities into a common embedding space before any cross-modal interaction. Vision transformers (ViT) process image patches, while text uses a standard transformer tokenizer; both feed into a shared transformer backbone with modality-specific positional embeddings.

# Conceptual early-fusion forward pass
class EarlyFusionModel(nn.Module):
    def __init__(self, dim=768, depth=12, heads=12):
        super().__init__()
        self.image_encoder = ViT(patch_size=16, dim=dim)
        self.text_encoder = TextTransformer(vocab_size=32000, dim=dim)
        self.shared_backbone = Transformer(dim=dim, depth=depth, heads=heads)
        self.modality_emb = nn.Embedding(2, dim)  # 0=image, 1=text
    
    def forward(self, images, input_ids):
        img_tokens = self.image_encoder(images)          # [B, N_img, D]
        txt_tokens = self.text_encoder(input_ids)        # [B, N_txt, D]
        
        # Prepend modality embeddings
        img_tokens += self.modality_emb(torch.zeros_like(img_tokens[..., 0]).long())
        txt_tokens += self.modality_emb(torch.ones_like(txt_tokens[..., 0]).long())
        
        combined = torch.cat([img_tokens, txt_tokens], dim=1)
        return self.shared_backbone(combined)

This approach maximizes cross-modal interaction depth but requires massive co-training datasets. Models like Flamingo and GPT-4V use variants of this pattern.

Late fusion with frozen encoders

Late fusion keeps modality-specific encoders separate (often frozen from pretraining) and only learns a lightweight cross-attention or projection layer on top. CLIP exemplifies this: a ViT image encoder and a text transformer encode independently, then contrastive loss aligns their output embeddings.

# CLIP-style contrastive objective
def clip_loss(image_features, text_features, temperature=0.07):
    # Normalize
    image_features = F.normalize(image_features, dim=-1)
    text_features = F.normalize(text_features, dim=-1)
    
    # Cosine similarity as logits
    logits_per_image = image_features @ text_features.T / temperature
    logits_per_text = logits_per_image.T
    
    # Ground truth: diagonal elements are positive pairs
    labels = torch.arange(len(image_features), device=image_features.device)
    
    loss_i = F.cross_entropy(logits_per_image, labels)
    loss_t = F.cross_entropy(logits_per_text, labels)
    return (loss_i + loss_t) / 2

Late fusion is cheaper to train and adapts easily to new modalities, but limits the depth of cross-modal reasoning. It works well for retrieval and classification; less so for generative tasks requiring fine-grained interaction.

Mixture-of-experts with modality routing

MoE architectures route tokens to modality-specific expert layers within a shared transformer. Each layer contains experts specialized for vision, text, audio, etc., with a learned router directing tokens. This reduces active parameters per forward pass while maintaining modality-specific capacity.

# Simplified MoE routing for multimodal
class MultimodalMoELayer(nn.Module):
    def __init__(self, dim, num_experts=8, top_k=2):
        super().__init__()
        self.experts = nn.ModuleList([
            Expert(dim) for _ in range(num_experts)
        ])
        self.router = nn.Linear(dim, num_experts, bias=False)
        self.top_k = top_k
    
    def forward(self, x, modality_ids):
        # x: [B, T, D], modality_ids: [B, T] indicating modality per token
        router_logits = self.router(x)  # [B, T, E]
        
        # Bias router by modality (optional learned bias per modality)
        modality_bias = self.modality_bias(modality_ids)  # [B, T, E]
        router_logits = router_logits + modality_bias
        
        # Top-k routing
        weights, indices = router_logits.topk(self.top_k, dim=-1)
        weights = F.softmax(weights, dim=-1)
        
        # Dispatch to experts (simplified; real impl uses scatter/gather)
        out = torch.zeros_like(x)
        for k in range(self.top_k):
            expert_idx = indices[..., k]
            expert_weight = weights[..., k:k+1]
            for e in range(len(self.experts)):
                mask = (expert_idx == e)
                if mask.any():
                    out[mask] += expert_weight[mask] * self.experts[e](x[mask])
        return out

Models like Google’s PaLM-E and some internal n4n.ai routing layers use this pattern to serve heterogeneous workloads efficiently.

Training objectives that matter

The choice of training objective determines what the model can actually do at inference time.

Contrastive alignment (CLIP, ALIGN, SigLIP) pulls matching image-text pairs together in embedding space while pushing non-matching pairs apart. This yields strong zero-shot classification and retrieval but no generative capability.

Masked multimodal modeling (BEiT-3, M3AE, VideoMAE) extends BERT-style masking to multiple modalities simultaneously. Random patches of images and spans of text are masked; the model reconstructs both. This learns rich joint representations but requires careful masking ratios per modality.

Next-token prediction with interleaved data (Flamingo, GPT-4V, LLaVA) treats images as token sequences (via a vision encoder + projection) and trains autoregressively on interleaved image-text documents. This enables few-shot in-context learning and open-ended generation.

Captioning and VQA supervision adds task-specific heads on top of pretrained backbones. LLaVA fine-tunes a LLaMA backbone on GPT-4-generated instruction-following data with image context. This is the dominant recipe for open-source multimodal chat models.

Why multimodal matters for production systems

Reduced pipeline complexity

Traditional vision-language pipelines chain separate models: object detector → captioner → LLM. Each stage adds latency, error propagation, and operational overhead. A single multimodal model replaces the chain with one forward pass.

# Before: cascaded pipeline (3+ model calls, ~800ms)
def legacy_pipeline(image, question):
    boxes = detector(image)                    # 150ms
    crops = crop_and_resize(image, boxes)      # 50ms
    captions = captioner(crops)                # 200ms
    context = format_context(captions, boxes)  # 20ms
    answer = llm(context + question)           # 400ms
    return answer

# After: single multimodal forward pass (~200ms)
def multimodal_pipeline(image, question):
    return multimodal_model(image, question)   # 200ms

Cross-modal reasoning that cascades can’t capture

Cascaded pipelines lose information at each boundary. A detector might miss a subtle visual cue that the LLM would need; a captioner might omit spatial relationships critical to the question. Joint models preserve fine-grained alignment because gradients flow across modalities during training.

Consider this VQA example:

Image: A receipt with handwritten tip amount partially obscured by a coffee stain
Question: “What was the tip percentage?”

A detector+captions pipeline sees “receipt with stain.” A joint model attends directly to the pixel region near the tip line, reasoning about the obscured digits in context of the total and subtotal visible elsewhere.

Unified serving infrastructure

One model endpoint replaces multiple specialized services. This simplifies autoscaling, monitoring, and versioning. When you route requests through a gateway that handles 240+ models, multimodal endpoints consolidate what would otherwise be separate vision, audio, and text deployments.

Concrete example: Document understanding with layout

Document AI is a killer application for multimodal models. Invoices, contracts, and forms combine visual layout, tabular structure, and natural language — none of which a pure text or pure vision model handles well alone.

Architecture for document understanding

class DocumentMultimodalModel(nn.Module):
    def __init__(self, backbone_dim=1024):
        super().__init__()
        # Layout-aware visual encoder
        self.visual_encoder = LayoutXLMVisualBackbone()
        # Text encoder with 2D position embeddings (x, y, width, height)
        self.text_encoder = LayoutXLMTextEncoder()
        # Cross-modal fusion
        self.fusion = CrossModalTransformer(
            dim=backbone_dim, depth=6, heads=16
        )
        # Task heads
        self.token_classifier = nn.Linear(backbone_dim, num_entity_types)
        self.relation_head = RelationExtractionHead(backbone_dim)
    
    def forward(self, image, ocr_tokens, ocr_boxes):
        # Visual features with layout awareness
        visual_feats = self.visual_encoder(image, ocr_boxes)
        
        # Text features with 2D positional embeddings
        text_feats = self.text_encoder(ocr_tokens, ocr_boxes)
        
        # Cross-modal attention
        fused = self.fusion(visual_feats, text_feats)
        
        # Per-token entity classification (NER)
        entity_logits = self.token_classifier(fused.text_tokens)
        
        # Key-value relation extraction
        relations = self.relation_head(fused)
        
        return {
            "entities": entity_logits,
            "relations": relations,
            "fused_embeddings": fused
        }

Training data strategy

Synthetic data generation dominates here. Render templates (invoices, receipts, forms) with randomized content, fonts, layouts, and noise. Use the template metadata as ground truth for token-level labels and relations. Supplement with real documents annotated via active learning.

def generate_synthetic_invoice():
    template = random.choice(INVOICE_TEMPLATES)
    data = {
        "vendor": fake.company(),
        "invoice_number": fake.bothify("INV-####-???"),
        "date": fake.date_between("-2y", "today"),
        "line_items": [
            {
                "description": fake.catch_phrase(),
                "quantity": random.randint(1, 100),
                "unit_price": round(random.uniform(10, 5000), 2)
            }
            for _ in range(random.randint(1, 15))
        ],
        "tax_rate": random.choice([0.0, 0.05, 0.08, 0.1, 0.15, 0.2]),
    }
    # Render to image with random perturbations
    image = render_template(template, data, 
                           font_noise=True, 
                           stain_prob=0.1,
                           rotation=random.uniform(-2, 2))
    # Ground truth from template structure
    annotations = extract_annotations(template, data)
    return image, annotations

Inference considerations

Document models often process high-resolution inputs (1000+ tokens). Techniques that matter:

  • Hierarchical encoding: Encode pages independently, then cross-page attention only on pooled representations
  • Sparse attention: Restrict cross-modal attention to spatially nearby tokens (layout-aware windowing)
  • KV caching: Cache visual encoder outputs for multi-turn Q&A on the same document

Common misconceptions

“Multimodal just means multiple inputs”

A model that accepts an image and text but processes them through independent towers with only a final concatenation is not meaningfully multimodal. The hallmark is cross-modal attention or shared representation learning where gradients from one modality update parameters that affect the other. If you can ablate the vision encoder without retraining the text tower, you have an ensemble, not a multimodal model.

“Larger context windows solve multimodal reasoning”

Stuffing OCR text into a long-context LLM works for simple extraction but fails on spatial reasoning. Layout, visual hierarchy, and non-textual cues (checkboxes, signatures, stamps) are lost in pure text serialization. A 1M-token context window doesn’t recover the 2D spatial relationships that a vision encoder preserves natively.

“Open-source multimodal models match proprietary ones on all tasks”

Models like LLaVA-1.5, Qwen-VL, and Idefics2 are impressive on academic benchmarks (VQAv2, GQA, TextVQA). In production document understanding, they lag on:

  • Table structure recovery (merged cells, multi-header rows)
  • Handwritten text in noisy backgrounds
  • Multi-page document reasoning with cross-page references
  • Low-resource languages with non-Latin scripts

The gap narrows with domain-specific fine-tuning, but expect to invest in data curation.

“You need massive compute to train multimodal models”

Full pretraining from scratch does. But adapter-based fine-tuning (LoRA on the LLM backbone + trained projection layer) achieves strong results on domain tasks with 1-8 GPUs. The LLaVA recipe: freeze CLIP ViT-L/14 and LLaMA-7B, train only a 2-layer MLP projector on 558K image-text pairs, then LoRA-finetune on 150K instruction samples. Total cost: ~$500-2000 on current cloud pricing.

“Multimodal models hallucinate less than text-only LLMs”

They hallucinate differently. Visual grounding reduces certain factual hallucinations (the model “sees” the answer), but introduces new failure modes:

  • Visual hallucination: Describing objects not present, triggered by text prompt priors
  • OCR hallucination: Misreading text in images, especially stylized fonts or low contrast
  • Spatial hallucination: Incorrect left/right, above/below, or containment relationships

Mitigation requires visual grounding heads, uncertainty calibration, and retrieval-augmented approaches — not just larger models.

Deployment patterns worth knowing

Cascade with multimodal fallback

Route simple queries to fast unimodal models; escalate to multimodal only when needed.

async def route_request(request):
    # Fast path: text-only classification
    if request.type == "text_classification":
        return await text_classifier(request.text)
    
    # Medium path: image classification
    if request.type == "image_classification":
        return await image_classifier(request.image)
    
    # Slow path: true multimodal reasoning
    if request.requires_cross_modal_reasoning:
        return await multimodal_model(request.image, request.text)
    
    # Default fallback
    return await multimodal_model(request.image, request.text)

This pattern reduces average latency and GPU cost significantly when only a fraction of traffic needs joint reasoning.

Speculative decoding with multimodal draft

Use a small multimodal model (e.g., 1B params) as a draft for a large one (70B+). The draft proposes tokens conditioned on both modalities; the large model verifies in parallel. Works because visual context is fixed — the draft only needs to predict text tokens.

Quantization asymmetry

Quantize the LLM backbone aggressively (INT4/INT8) but keep the vision encoder and projection layer in FP16/BF16. Vision encoders are more sensitive to quantization; the projection layer amplifies errors. Asymmetric quantization recovers 95%+ quality at 40% memory reduction.

When to choose which approach

Requirement Recommended pattern
Zero-shot classification, retrieval CLIP-style late fusion (SigLIP, OpenCLIP)
Open-ended VQA, captioning, chat Early fusion autoregressive (LLaVA, Qwen-VL, Idefics2)
Document understanding, form extraction Layout-aware multimodal (LayoutXLM, Donut, custom)
Video understanding Video-specific encoders + temporal attention (VideoMAE, InternVideo)
Audio + text (ASR, TTS, QA) Whisper encoder + LLM with audio projector (SALMONN, Qwen-Audio)
Real-time, high-throughput serving Late fusion or MoE with modality routing
Domain-specific with limited data Adapter/LoRA fine-tune on frozen backbone

Closing thought

Multimodal AI is not a single model class — it’s a spectrum of architectural choices trading off cross-modal interaction depth, training cost, and inference efficiency. The right choice depends on whether your bottleneck is quality, latency, data availability, or serving cost. Start with the simplest architecture that meets your evaluation criteria (usually late fusion or adapter-tuned early fusion), measure on realistic production distributions, and escalate complexity only when the metrics demand it.

Tagsmultimodal-aiai-modelsdefinitions

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All multimodal ai models posts →