In the previous lesson, each document page was turned into one vector and stored in a search index. That works, it is cheap, and for most pages it is enough.
This lesson is about the cases where it is not enough — and about the technique, late interaction, that fixes them.
Picture a single page from an annual report. It contains a heading, two paragraphs, a bar chart with quarterly figures, and a small table of regional totals in the corner.
Now that whole page gets compressed into one vector — say 768 numbers that represent "what this page is about."
Those 768 numbers have to describe everything on the page at once. Inevitably they end up describing the page's main themes: revenue, quarterly performance, this company, this year. The small table in the corner contributes almost nothing to the result, because it is a tiny part of a busy page.
So when a user asks:
What was the regional total for the South in Q3?
the page that genuinely holds the answer does not stand out. Its one vector says "this page is about quarterly revenue," which is true of forty other pages in the report. The evidence is on the page; the summary of the page lost it.
Late interaction takes a different approach. Instead of one vector per page, it keeps many — roughly one for each small patch of the page image. The corner table gets its own vectors, and they are not averaged away into the page's general theme.
The query is broken up in the same way: one vector per query token rather than one for the whole question.
Matching then happens between those small pieces, at search time.
The name describes when the query and the document are allowed to interact.
| Approach | When query and page meet | Consequence |
|---|---|---|
| Early interaction | The model reads query and page together before scoring | Very accurate, far too slow to run over a million pages |
| No interaction (single vector) | Never — each side is summarised alone, then two vectors are compared | Very fast, loses local detail |
| Late interaction | Each side is encoded alone, then the pieces are matched at search time | Keeps detail, still fast enough to index |
Late interaction is the middle path. The encoders still run separately, so you can index every page in advance — but the detailed comparison is postponed until you know the query, instead of being thrown away during indexing.
A text query also becomes multiple vectors—roughly one per query token.
Each query token can then match the page region that best fits it.
Query:
Q3 revenue growth
Different parts may match different page regions:
Q3 → the Q3 label below a barrevenue → the chart titlegrowth → the comparison between Q2 and Q3A single page vector must blend all page content together. Local patch vectors let these query parts find separate evidence.
Let:
qᵢ = one query-token vector. The small i identifies the query token.dⱼ = one page-patch vector. The small j identifies the page patch.For every query token:
Page score
= best patch score for query token 1
+ best patch score for query token 2
+ ...
+ best patch score for the final query token
The compact mathematical form is:
Score(Q, D) = Σᵢ maxⱼ(qᵢ · dⱼ)
Q = all query-token vectorsD = all page-patch vectors· = dot product, a similarity scoremaxⱼ = keep the highest-scoring page patch for this query tokenΣᵢ = add the best scores from all query tokensThe query has two tokens: Q3 and revenue.
Best patch score for "Q3" = 0.82
Best patch score for "revenue" = 0.74
Page score = 0.82 + 0.74 = 1.56
The page with the larger final score is ranked higher.
Conceptual code:
def late_interaction_score(query_vectors, page_vectors):
total = 0
for query_token in query_vectors:
patch_scores = query_token @ page_vectors.T
total += patch_scores.max()
return total
This explains the name: the encoders work separately first; detailed query-page interaction happens later.
ColBERT popularised late interaction for text retrieval. ColPali applies the idea to complete document-page images.
The published ColPali design:
(query, page image) pairs.No OCR is required for its core retrieval representation. OCR may still help with exact text lookup, display, filtering, or verification in a production system.
Suppose a batch contains correct query-page pairs.
This teaches the model what a page that actually answers a question looks like—not merely which pages share similar words.
The lecture notes report that query-time matching can remain fast with suitable indexing, while offline indexing is simpler than several traditional pipelines. Actual latency depends on hardware, page resolution, index design, and corpus size.
One page represented by hundreds of patch vectors needs much more storage than one page represented by one vector.
| Representation | Detail | Index size | Search cost |
|---|---|---|---|
| One vector per page | Lower | Smaller | Lower |
| Many patch vectors per page | Higher | Larger | Higher |
This is the main trade-off: local detail versus storage and compute.
ViDoRe evaluates visual document retrieval across domains, languages, layouts, and visual styles. It contains visually rich PDF pages and asks systems to rank the page that answers each query.
The main metric highlighted in the lecture is nDCG@5:
Reported comparisons in the ColPali work show the direction:
Treat paper results as benchmark evidence, not a guarantee for every private document collection.
ColPali searches complete page images with late interaction, matching each query token to its best page patch for more detail at a higher storage cost.