Phase 04 - Lesson 25

Modelos de Visão-Linguagem — O Padrão ViT-MLP-LLM

Um codificador de visão converte uma imagem em tokens. Um projetor MLP mapeia esses tokens para o espaço de embeddings do LLM. Um modelo de linguagem faz o resto. Esse padrão — ViT-MLP-LLM — é todo VLM de produção em 2026.

Tipo: Aprender + Usar Linguagens: Python Pré-requisitos: Fase 4 Lição 14 (ViT), Fase 4 Lição 18 (CLIP), Fase 7 Lição 02 (Self-Attention) Tempo: ~75 minutos

Objetivos de Aprendizagem

  • Enunciar a arquitetura ViT-MLP-LLM e explicar o que cada um dos três componentes contribui
  • Comparar Qwen3-VL, InternVL3.5, LLaVA-Next e GLM-4.6V em contagem de parâmetros, comprimento de contexto e desempenho em benchmarks
  • Explicar o DeepStack: por que características multi-nível do ViT melhoram o alinhamento visão-linguagem mais do que uma única característica da última camada
  • Medir alucinação de VLM em produção com a Cross-Modal Error Rate (CMER) e agir sobre o sinal

O Problema

O CLIP (Fase 4 Lição 18) lhe dá um espaço de embeddings compartilhado para imagens e texto, o que é suficiente para classificação zero-shot e recuperação. Ele não consegue responder "quantos carros vermelhos há nesta imagem?" porque o CLIP não gera texto — ele apenas pontua similaridades.

Modelos de Visão-Linguagem (VLMs) — Qwen3-VL, InternVL3.5, LLaVA-Next, GLM-4.6V — acoplam um codificador de imagem da família CLIP a um modelo de linguagem completo. O modelo vê uma imagem mais uma pergunta e gera uma resposta. Em 2026 os VLMs open-source rivalizam ou superam o GPT-5 e o Gemini-2.5-Pro em benchmarks multimodais (MMMU, MMBench, DocVQA, ChartQA, MathVista, OSWorld).

O trio de peças (ViT, projetor, LLM) é o padrão. As diferenças entre modelos estão em qual ViT, qual projetor, qual LLM, os dados de treinamento e a receita de alinhamento. Uma vez que você entende o padrão, trocar qualquer componente é mecânico.

O Conceito

A arquitetura ViT-MLP-LLM

flowchart LR
    IMG["Imagem<br/>(H x W x 3)"] --> ViT["Codificador de visão<br/>(ViT, CLIP-L,<br/>SigLIP, DINOv3)"]
    ViT --> FEATS["Tokens de imagem<br/>(N, d_vit)"]
    FEATS --> PROJ["Projetor<br/>(MLP de 2-4 camadas<br/>ou Q-former)"]
    PROJ --> VTOK["Tokens de imagem<br/>no espaco do LLM<br/>(N, d_llm)"]
    TXT["Prompt de texto"] --> TOK["Tokenizador do LLM"]
    TOK --> TTOK["Tokens de texto<br/>(M, d_llm)"]
    VTOK --> CONCAT["Intercalar<br/>ou concatenar"]
    TTOK --> CONCAT
    CONCAT --> LLM["LLM decoder<br/>(Qwen3, LLaMA, etc.)"]
    LLM --> OUT["Resposta em texto"]

    style ViT fill:#dbeafe,stroke:#2563eb
    style PROJ fill:#fef3c7,stroke:#d97706
    style LLM fill:#dcfce7,stroke:#16a34a
  1. Codificador de visão — um ViT pré-treinado (CLIP-L/14, SigLIP, DINOv3 ou uma variante ajustada). Produz tokens de patch.
  2. Projetor — um pequeno módulo (MLP de 2-4 camadas, ou um Q-former) que mapeia tokens de visão para a dimensão de embedding do LLM. É aqui que ocorre a maior parte do fine-tuning.
  3. LLM — um modelo de linguagem decoder-only (Qwen3, Llama, Mistral, GLM, InternLM). Lê os tokens de visão + texto em sequência e gera texto.

Todas as três peças são, em princípio, treináveis. Na prática, o codificador de visão e o LLM ficam em sua maioria congelados enquanto o projetor é treinado — alguns bilhões de parâmetros de sinal por um custo baixo.

DeepStack

A projeção convencional usa apenas a última camada do ViT. O DeepStack (Qwen3-VL) amostra características de múltiplas profundidades do ViT e as empilha. Camadas mais profundas carregam semântica de alto nível; camadas mais rasas carregam informação espacial e de textura de granularidade fina. Alimentar ambas no LLM fecha a lacuna entre "o que a imagem contém" (semântica) e "onde exatamente" (ancoragem espacial).

Três estágios de treinamento

VLMs modernos treinam em estágios:

  1. Alinhamento — congele o ViT e o LLM. Treine apenas o projetor em pares imagem-legenda. Ensina o projetor a mapear o espaço de visão para o espaço de linguagem.
  2. Pré-treinamento — descongele tudo. Treine em dados imagem-texto intercalados em larga escala (mais de 500M de pares). Constrói o conhecimento visual do modelo.
  3. Instruction tuning — faça fine-tune em triplas curadas de (imagem, pergunta, resposta). Ensina comportamento conversacional e formatos de tarefa. É isso que transforma um "LM com consciência visual" em um assistente utilizável.

A maioria dos fine-tunes com LoRA mira o estágio 3 com um pequeno conjunto de dados rotulado.

Comparação da família de modelos (início de 2026)

Modelo Params Codificador de visão LLM Contexto Pontos fortes
Qwen3-VL-235B-A22B (MoE) 235B (22B ativos) ViT custom + DeepStack Qwen3 256K SOTA geral, agente de GUI
Qwen3-VL-30B-A3B (MoE) 30B (3B ativos) ViT custom + DeepStack Qwen3 256K Alternativa MoE menor
Qwen3-VL-8B (dense) 8B ViT custom Qwen3 128K Padrão dense de produção
InternVL3.5-38B 38B InternViT-6B Qwen3 + GPT-OSS 128K Forte em MMBench / MMVet
InternVL3.5-241B-A28B 241B (28B ativos) InternViT-6B Qwen3 128K Competitivo com GPT-4o
LLaVA-Next 72B 72B SigLIP Llama-3 32K Aberto, fácil de fazer fine-tune
GLM-4.6V ~70B custom GLM 64K Open-source, OCR forte
MiniCPM-V-2.6 8B SigLIP MiniCPM 32K Amigável para edge

Agentes visuais

O Qwen3-VL-235B alcança desempenho global de topo no OSWorld — um benchmark para agentes visuais que operam GUIs (desktop, mobile, web). O modelo vê uma captura de tela, entende a UI e emite ações (clicar, digitar, rolar). Combinado com ferramentas, ele fecha o ciclo em tarefas comuns de desktop. É isso que a maioria dos demos de "AI PC" de 2026 roda por baixo dos panos.

Capacidades agênticas + variantes de RoPE

VLMs precisam saber quando um quadro está em um vídeo. O Qwen3-VL evoluiu do T-RoPE (temporal rotary position embeddings) para o alinhamento temporal baseado em texto — tokens de texto de timestamp explícitos intercalados com quadros de vídeo. O modelo vê "<timestamp 00:32> quadro, prompt" e consegue raciocinar sobre relações temporais.

O problema de alinhamento

12% dos pares imagem-texto em um dataset coletado da web contêm descrições não totalmente ancoradas na imagem. Um VLM treinado nisso silenciosamente aprende a alucinar — fabricar objetos, ler números incorretamente, inventar relações. Em produção, este é o modo de falha dominante.

A Skywork.ai introduziu a Cross-Modal Error Rate (CMER) para rastreá-lo:

CMER = fracao de saidas onde a confianca do texto e alta mas a similaridade imagem-texto (via um verificador da familia CLIP) e baixa

Uma CMER alta significa que o modelo está afirmando com confiança coisas não ancoradas na imagem. Monitorar a CMER e tratá-la como um KPI de produção reduziu a taxa de alucinação em ~35% na implantação deles. O truque não é "consertar o modelo", mas "rotear saídas de CMER alta para revisão humana."

Fine-tuning com LoRA / QLoRA

O fine-tuning completo de um VLM de 70B está fora do alcance da maioria das equipes. LoRA (rank 16-64) nas camadas de atenção + projetor, ou QLoRA com pesos base de 4 bits, cabe em um único A100 / H100. Custo: 5.000-50.000 exemplos,

00-$5.000 em computação, 2-10 horas de treinamento.

O raciocínio espacial ainda é fraco

Os VLMs atuais pontuam 50-60% em benchmarks de raciocínio espacial (acima-abaixo, esquerda-direita, contagem, distância). Se seu caso de uso depende de "qual objeto está em cima de qual", valide intensamente — o desempenho de VLM genérico está abaixo do humano. Alternativas melhores que VLMs para tarefas puramente espaciais: um estimador especializado de keypoint / pose, um modelo de profundidade, ou um modelo de detecção com geometria de bounding box pós-processada.

Construa

Passo 1: O projetor

A parte que você treinará com mais frequência. MLP de 2-4 camadas com GELU.

import torch
import torch.nn as nn


class Projector(nn.Module):
    def __init__(self, vit_dim=768, llm_dim=4096, hidden=4096):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(vit_dim, hidden),
            nn.GELU(),
            nn.Linear(hidden, llm_dim),
        )

    def forward(self, x):
        return self.net(x)

A entrada é um tensor de tokens (N_patches, d_vit). A saída é (N_patches, d_llm). O LLM trata cada linha de saída apenas como mais um token.

Passo 2: Montar o ViT-MLP-LLM de ponta a ponta

Esqueleto do forward pass para um VLM mínimo. Código real usa transformers; este é o layout conceitual.

class MinimalVLM(nn.Module):
    def __init__(self, vit, projector, llm, image_token_id):
        super().__init__()
        self.vit = vit
        self.projector = projector
        self.llm = llm
        self.image_token_id = image_token_id  # placeholder token in text prompt

    def forward(self, image, input_ids, attention_mask):
        # 1. vision features
        vision_tokens = self.vit(image)                     # (B, N_patches, d_vit)
        vision_embeds = self.projector(vision_tokens)       # (B, N_patches, d_llm)

        # 2. text embeddings
        text_embeds = self.llm.get_input_embeddings()(input_ids)  # (B, M, d_llm)

        # 3. replace image placeholder tokens with vision embeds
        merged = self._merge(text_embeds, vision_embeds, input_ids)

        # 4. run LLM
        return self.llm(inputs_embeds=merged, attention_mask=attention_mask)

    def _merge(self, text_embeds, vision_embeds, input_ids):
        out = text_embeds.clone()
        expected = vision_embeds.size(1)
        for b in range(input_ids.size(0)):
            positions = (input_ids[b] == self.image_token_id).nonzero(as_tuple=True)[0]
            if len(positions) != expected:
                raise ValueError(
                    f"batch item {b} has {len(positions)} image tokens but vision_embeds has {expected} patches."
                    " Every sample in the batch must be pre-padded to the same number of image placeholder tokens.")
            out[b, positions] = vision_embeds[b]
        return out

O token placeholder <image> no texto é substituído por embeddings reais de imagem — mesmo padrão que LLaVA, Qwen-VL e InternVL usam.

Passo 3: Cálculo da CMER

Uma verificação leve em tempo de execução.

import torch.nn.functional as F


def cross_modal_error_rate(image_emb, text_emb, text_confidence, sim_threshold=0.25, conf_threshold=0.8):
    """
    image_emb, text_emb: embeddings of image and generated text (normalised internally)
    text_confidence:     mean per-token probability in [0, 1]
    Returns:             fraction of high-confidence outputs with low image-text alignment
    """
    image_emb = F.normalize(image_emb, dim=-1)
    text_emb = F.normalize(text_emb, dim=-1)
    sim = (image_emb * text_emb).sum(dim=-1)        # cosine similarity
    high_conf_low_sim = (text_confidence > conf_threshold) & (sim < sim_threshold)
    return high_conf_low_sim.float().mean().item()

Trate a CMER como um KPI de produção. Monitore-a por endpoint, por tipo de prompt, por cliente. Uma CMER crescente indica que o modelo está começando a alucinar em alguma distribuição de entrada.

Passo 4: Classificador VLM de brinquedo (executável)

Demonstra que o projetor treina. "Características de ViT" falsas entram; um pequeno token estilo LLM prevê uma classe.

class ToyVLM(nn.Module):
    def __init__(self, vit_dim=32, llm_dim=64, num_classes=5):
        super().__init__()
        self.projector = Projector(vit_dim, llm_dim, hidden=64)
        self.head = nn.Linear(llm_dim, num_classes)

    def forward(self, vision_tokens):
        projected = self.projector(vision_tokens)
        pooled = projected.mean(dim=1)
        return self.head(pooled)

É possível ajustar isso em pares sintéticos (característica, classe) em menos de 200 passos — o suficiente para mostrar que o padrão do projetor funciona.

Use

Três maneiras pelas quais equipes de produção usam VLMs em 2026:

  • API hospedada — OpenAI Vision, Anthropic Claude Vision, Google Gemini Vision. Zero infraestrutura, risco de fornecedor.
  • Self-host open-source — Qwen3-VL ou InternVL3.5 via transformers e vllm. Controle total, maior esforço inicial.
  • Fine-tune no domínio — carregue Qwen2.5-VL-7B ou LLaVA-1.6-7B, faça LoRA em 5k-50k exemplos custom, sirva com vllm ou TGI.
from transformers import AutoProcessor, AutoModelForVision2Seq
import torch
from PIL import Image

model_id = "Qwen/Qwen3-VL-8B-Instruct"
processor = AutoProcessor.from_pretrained(model_id)
model = AutoModelForVision2Seq.from_pretrained(model_id, torch_dtype=torch.bfloat16, device_map="auto")

messages = [{
    "role": "user",
    "content": [
        {"type": "image", "image": Image.open("plot.png")},
        {"type": "text", "text": "What does this chart show?"},
    ],
}]
inputs = processor.apply_chat_template(messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt").to("cuda")
generated = model.generate(**inputs, max_new_tokens=256)
answer = processor.decode(generated[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True)

O apply_chat_template esconde a tokenização do placeholder <image>; o modelo lida com o merge internamente.

Entregue

Esta lição produz:

  • outputs/prompt-vlm-selector.md — escolhe Qwen3-VL / InternVL3.5 / LLaVA-Next / API dadas acurácia, latência, comprimento de contexto e orçamento.
  • outputs/skill-cmer-monitor.md — emite o código para instrumentar um endpoint de VLM de produção com cross-modal error rate, dashboards por endpoint e limiares de alerta.

Exercícios

  1. (Fácil) Rode três prompts ("o que é isto?", "conte os objetos", "descreva a cena") através de qualquer VLM aberto em cinco imagens. Pontue cada resposta como correta / parcialmente correta / alucinada à mão. Calcule uma taxa de primeira passagem semelhante à CMER.
  2. (Médio) Faça fine-tune do Qwen2.5-VL-3B ou LLaVA-1.6-7B com LoRA (rank 16) em 500 imagens de um domínio-alvo com legendas. Compare a acurácia estilo MMBench zero-shot vs. com fine-tune.
  3. (Difícil) Substitua o codificador de imagem do VLM por DINOv3 em vez de seu SigLIP/CLIP padrão. Re-treine apenas o projetor (LLM congelado + DINOv3 congelado). Meça se as tarefas de predição densa (contagem, raciocínio espacial) melhoram.

Termos-Chave

Termo O que as pessoas dizem O que realmente significa
ViT-MLP-LLM "O padrão VLM" Codificador de visão + projetor + modelo de linguagem; todo VLM de 2026
Projetor "A ponte" MLP de 2-4 camadas (ou Q-former) que mapeia tokens de visão para o espaço de embedding do LLM
DeepStack "O truque de características do Qwen3-VL" Características multi-nível do ViT empilhadas em vez de apenas a última camada
Token de imagem "Placeholder " Token especial no fluxo de texto substituído por embeddings de visão projetados
CMER "KPI de alucinação" Cross-Modal Error Rate; alta quando a confiança do texto é alta mas a similaridade imagem-texto é baixa
Agente visual "VLM que clica" VLM operando GUIs (OSWorld, mobile, web) com chamadas de ferramenta
Q-former "Ponte de tokens de contagem fixa" Projetor estilo BLIP-2 que produz um número fixo de tokens de consulta visual
Alinhamento / pré-treinamento / instruction tuning "Três estágios" Pipeline padrão de treinamento de VLM

Leitura Adicional

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).