From CLIP to BLIP-2 — Q-Former as Modality Bridge
CLIP aligns images and text but cannot caption, answer questions, or hold a conversation. BLIP-2 (Salesforce, 2023) fixed that with a small trainable bridge: 32 learnable query vectors cross-attend over a frozen ViT's features, and the result slots into a frozen LLM's input stream. 188M parameters of bridge connected an 11B LLM to a ViT-g/14. Adapter-based VLMs through 2026, including MiniGPT-4 and InstructBLIP, descend from it, and LLaVA is a close cousin. This lesson reads the Q-Former's architecture, walks through its two-stage training, and builds a toy that projects visual tokens to an LLM's embedding dim.
Learning Objectives
- Explain why a trainable bottleneck between a frozen vision encoder and frozen LLM beats end-to-end finetuning in cost and stability.
- Implement a cross-attention block where a fixed set of learnable queries attend to external image features.
- Walk through BLIP-2's two-stage pretraining: representation (ITC + ITM + ITG) then generative (LM loss with frozen decoder).
- Compare Q-Former to the simpler MLP projector used in LLaVA and argue when each choice wins.
The Problem
You have a frozen ViT that produces 256 patch tokens of dim 1408 per image, and a frozen 7B LLM that expects token embeddings of dim 4096. The obvious bridge is a linear layer from 1408 to 4096. It works, but it feeds all 256 patch tokens into the LLM's context, which costs 256 extra tokens per image. Over a batch of 32 images that is 8192 tokens spent on the visual modality alone.
The BLIP-2 question: can you compress those 256 tokens into far fewer (say 32) and still give the LLM enough to caption, answer questions, and reason about the image? And can you train that bridge without touching either frozen backbone, so the training cost is just the bridge's parameters?
The answer is a Q-Former: 32 learnable "query" vectors that cross-attend to the ViT's patch tokens and produce a 32-token visual summary for the LLM. It has 188M parameters and is trained with contrastive, matching, and generative objectives before it ever meets the LLM.
The Concept
Learnable queries
The core trick: instead of letting the LLM's text tokens attend to image patches, introduce a new set of 32 learnable query vectors Q and let them attend to the patches. The queries are parameters of the model. They are learned during training, and the same 32 are used for every image.
After cross-attention, each query holds a compressed summary of the image. You can imagine one asking "what is the main object", another "what is the background", another "how many things are there". The queries do not literally specialize on semantic labels, though. They learn whatever encoding makes the downstream losses drop.
Architecture
The Q-Former is a small transformer (12 layers, ~100M params) with two paths:
- Query path: 32 query vectors flow through self-attention (among themselves), then cross-attention over the frozen ViT's patch tokens, then an FFN.
- Text path: a BERT-like text encoder that shares the self-attention and FFN weights with the query path. Cross-attention is disabled for the text path.
At training time both paths run. The queries and text interact through the shared self-attention, so the queries can condition on text for tasks that need it (ITM, ITG). At inference time for VLM handoff, only the queries flow through, yielding 32 visual tokens.
Two-stage training
BLIP-2 pretrains in two stages.
Stage 1 is representation learning, with no LLM. Three losses run together:
- ITC (image-text contrastive): CLIP-style contrastive loss between pooled query tokens and the text CLS token.
- ITM (image-text matching): a binary classifier that asks whether an image-text pair is a match, trained on hard-negative-mined pairs.
- ITG (image-grounded text generation): a causal LM head on the text, conditioned on the queries. It forces the queries to encode content the text can be generated from.
Only the Q-Former trains. The ViT is frozen, and no LLM is involved.
Stage 2 is generative learning. Attach a frozen LLM (OPT-2.7B or Flan-T5-XL, for example), project the 32 query outputs to the LLM's embedding dim with a small linear layer, and prepend them to the text prompt. Train only the linear projection and the Q-Former on LM loss over the concatenated prompt + image + caption sequence.
After stage 2, the Q-Former plus projection is the full visual adapter. At inference: image → ViT → Q-Former → linear projection → prepended to text → frozen LLM emits output.
Parameter economics
BLIP-2 with ViT-g/14 (1.1B, frozen) + OPT-6.7B (6.7B, frozen) + Q-Former (188M, trained) comes to 8B total with 188M trained. The Q-Former is about 2.4% of the stack. Training cost reflects that: days on a handful of A100s versus weeks for end-to-end.
On quality, BLIP-2 matches or beats Flamingo-80B on zero-shot VQA while being 50x smaller. The bridge works.
InstructBLIP and the instruction-aware Q-Former
InstructBLIP (2023) gives the Q-Former one more input: the instruction text itself. At cross-attention time the queries see both the image patches and the instruction, so they can specialize per instruction ("count the cars", "describe the mood") instead of learning one fixed summary. It showed benchmark gains on held-out tasks.
MiniGPT-4 and the projector-only approach
MiniGPT-4 kept the Q-Former but trained only the output linear projection and froze everything else. That is cheap, and the price is quality: the queries were BLIP-2's, not tuned for MiniGPT-4. Good for fast iteration, not the best architecture.
Why LLaVA went simpler
LLaVA (2023, Lesson 12.05) replaced the Q-Former with a plain 2-layer MLP that projects each ViT patch token into LLM space. For a 24x24 grid that is 576 tokens per image, all fed to the LLM. Compression is worse, but the LLM gets to attend over raw patches. At the time this was controversial. By late 2023 it was dominant, because visual instruction data (LLaVA-Instruct-150k) showed the MLP could be trained to preserve enough signal. The tradeoff is that LLaVA's context fills faster, but it scales naturally to multi-image and video.
By 2026 the field had split. The Q-Former survives where token budget matters (long video, many images), and the MLP projector dominates where raw quality per token is the priority.
Gated cross-attention: Flamingo, the ancestor
Flamingo (Lesson 12.04) predated BLIP-2 and used the same cross-attention idea, but at each frozen LLM layer rather than as a single bridge. BLIP-2 showed you can compress down to the input layer only and still get a working model. Gemini and Idefics combine both: interleaved input tokens plus optional gated cross-attention for in-context few-shot.
The 2026 descendants
- Q-Former: BLIP-2, InstructBLIP, MiniGPT-4, and most video-language models for token budget reasons.
- Perceiver resampler: Flamingo's variant (Lesson 12.04); the Idefics family, Eagle, OmniMAE.
- MLP projector: LLaVA, LLaVA-NeXT, LLaVA-OneVision, Cambrian-1.
- Attention pool: VILA, PaliGemma.
These four are all valid choices. What decides between them is whether you are constrained on token budget or on quality per token.
Use It
code/main.py builds a stdlib Q-Former-style cross-attention at toy scale:
- Simulate 64 image patch tokens (dim 16).
- Instantiate 8 query vectors (dim 16).
- Run scaled-dot-product cross-attention (Q from queries, K/V from patches).
- Project to a toy LLM dim (24) with a linear layer.
- Output 8 LLM-ready visual tokens.
The math is pure Python, nested loops over vectors. The sizes are scaled down from the 256 patches and 32 queries above, but the shapes and the mechanism are the same. Instead of the full weight matrix, the script prints a per-query summary: the entropy of the attention weights against the uniform baseline, and the top five patches each query pulled from. A second demo copies a few patch vectors in as the queries and checks that each query lands on its own patch.
Ship It
This lesson produces outputs/skill-modality-bridge-picker.md. Given a target VLM configuration (vision encoder token count, LLM context budget, deployment constraints, quality target), it recommends Q-Former vs MLP vs Perceiver resampler with a short justification and a parameter-count estimate for each bridge.
I'd run main.py and read the entropy lines before anything else. The first demo uses random, unscaled weights and nothing is trained, yet the attention comes out sharply peaked: in my run most queries put nearly all their weight on a single patch, and the mean entropy sits far below the uniform baseline. Low entropy by itself tells you nothing about learning. The model has to earn its attention pattern against a loss, and this toy has no loss.
The second demo is the one that shows the mechanism. Queries are copies of patches 5, 17, 33, 48, 60, 2, 11 and 27, with identity weights, and each query's top patch is its own source patch. That is the whole idea of cross-attention here: a query is a question, and the patches it matches best get pulled into its summary.
Keep the toy in proportion. It has no text path, no ITC/ITM/ITG, and no stage 2, so the "learnable" queries are just random vectors. The TAKEAWAYS printout at the end still says 32 queries and 256 patches, while the code runs 8 and 64. If you want to feel why the bridge matters, do exercise 5 and count tokens for a video.
Exercises
-
Implement the cross-attention block in PyTorch. Verify that with 32 queries and 256 keys/values, the attention-weight matrix is 32 x 256 and each row sums to 1 after softmax.
-
In BLIP-2 stage 1 the Q-Former runs three losses simultaneously: ITC, ITM, ITG. Write the forward signature for each in pseudo-code. Which one requires the text encoder path to be active?
-
Compare parameter counts: Q-Former (12 layers, 768 hidden) vs a 2-layer MLP projector (1408 → 4096, two layers). At what LLM scale does the 188M Q-Former cost pay back in training efficiency?
-
Read Section 3.2 of the BLIP-2 paper (arXiv:2301.12597) on how the Q-Former is initialized. Explain why initializing from BERT-base (not random) accelerates convergence.
-
For a 10-minute video at 1 FPS sampled to 60 frames, compute the per-frame token cost at (Q-Former → 32 tokens/frame) vs (MLP projector → 576 tokens/frame). Which fits into a 128k-token LLM context window?
Key Terms
| Term | What people say | What it actually means |
|---|---|---|
| Q-Former | "Querying transformer" | Small transformer with 32 learnable query vectors that cross-attend to frozen ViT features |
| Learnable queries | "Soft prompt for vision" | A fixed set of parameters that serve as the query side of cross-attention; learned per model, shared across all inputs |
| Cross-attention | "Q from here, K/V from there" | Attention where query, key, and value come from different sources; how the queries pull from ViT patches |
| ITC | "Image-text contrastive" | CLIP-style loss applied to Q-Former pooled queries vs text CLS |
| ITM | "Image-text matching" | Binary classifier on hard-negative-mined pairs; forces the queries to discriminate fine-grained mismatches |
| ITG | "Image-grounded text generation" | Causal LM loss where text is generated conditioned on queries; forces queries to encode text-decodable content |
| Two-stage pretraining | "Representation then generative" | Stage 1 trains Q-Former alone (ITC/ITM/ITG); Stage 2 attaches frozen LLM and trains only the projection + Q-Former |
| Frozen backbone | "Do not finetune" | The vision encoder and LLM weights are fixed; only the bridge trains |
| Projection head | "Linear to LLM dim" | Final linear layer mapping Q-Former output to the LLM's embedding dimension |
| Perceiver resampler | "Flamingo's version" | Similar learnable-query cross-attention, used by Flamingo at every layer rather than as a single bridge |
Further Reading
- Li et al.: BLIP-2 (arXiv:2301.12597): the core paper.
- Li et al.: BLIP (arXiv:2201.12086): the predecessor with the ITC/ITM/ITG trio.
- Li et al.: ALBEF (arXiv:2107.07651): "align before fuse": the conceptual ancestor of stage 1 training.
- Dai et al.: InstructBLIP (arXiv:2305.06500): instruction-aware Q-Former.
- Zhu et al.: MiniGPT-4 (arXiv:2304.10592): projector-only approach.
- Jaegle et al.: Perceiver IO (arXiv:2107.14795): general architecture for learnable-query cross-attention.
Code
- main.py (python, 179 lines)