← back
00 · opening
Last updated July 23, 2026

The transformer only ever sees lists of numbers.

You already know how a language model handles text. It splits the text into tokens, turns each token into a vector, lets attention mix the vectors, and predicts the next token. A multimodal model does the same thing to a photo, a voice note or a PDF. The transformer in the middle stays the same. The new work is turning each new kind of input into vectors.

· four senses, one language · TEXT · IMAGE AUDIO · PDF any input VECTORS one shared space 1 TRANSFORMER same attention

scroll

01 · the one thing to carry over

A language model already turns words into numbers.

When you type a sentence into an LLM, the first thing it does is throw the letters away. Each token is looked up in a table and replaced by a list of numbers, a vector of a few thousand values. From then on, the model only works with vectors.

Attention does not know it is working on English. It takes a list of vectors, lets each one look at the others, and mixes them. The final vector is turned into a probability for each token in the vocabulary, and one token is sampled from those probabilities. The model appends that token and runs again.

So the model's real input is a sequence of vectors. Text is one convenient way to make them. Remember this, because it is how images, audio and documents get in too.

the pivot If the transformer takes in vectors and does not care where they came from, then any input you can turn into a sequence of vectors can be fed to it. A multimodal model keeps the same transformer. What it adds are new doors: new ways to turn a picture or a sound into vectors.
02 · the unifying idea

Each kind of input has its own door into one shared space.

Picture a single, shared vector space. It is a huge coordinate system where every input becomes a point. A point can stand for the word "dog," the sound of a bark, or a photo of a spaniel. If they mean the same thing, they sit near each other. The transformer works inside this space and reasons over whatever points it is handed.

Each modality gets its own encoder. An encoder is a piece of network with one job: take raw input (pixels, audio samples, a rendered page) and turn it into points in the shared space. It is that input's door into the space. For text the encoder is simple, a lookup table. Images and audio need real neural networks. Once an input is through its door, it is a list of vectors like the words are, and attention mixes them all together in one sequence.

many encoders in, one transformer
TEXT IMAGE AUDIO PDF lookup table vision encoder audio encoder render + vision SHARED VECTOR SPACE TRANSFORMERattention · same as ever next token
Change the kind of input on the left and you change the encoder. The shared space and the transformer stay the same.
in essence · the transformer never asks where a vector came from
# one model, many inputs. the encoder is the only modality-specific part.
def forward(inputs):                 # inputs: text, an image, some audio, a page...
    seq = []
    for x in inputs:
        enc = ENCODERS[x.modality]      # pick the door for this modality
        seq += enc(x)                   # -> vectors in ONE shared space
    return transformer(seq)            # same attention, same next-token loop
# pixels instead of words changes ENCODERS, not the transformer.
03 · the vectors, concretely

A word, a patch and a sound all become 4,096 numbers.

"Turned into a vector" is hard to picture until you see it done once. So here is one worked example for each door, with real shapes. The vectors below are 4,096 numbers wide. That is the embedding dimension of a Llama-3-8B-class model. Bigger models use wider vectors, but the steps are the same.

text · a lookup

"dog"

input
The token "dog", which the tokenizer maps to one integer, say id 5679.
what happens
Row 5,679 is copied out of a learned table of shape [128,256 × 4,096]. No math at all.
output
4,096 floats.
image · a matmul

one 16×16 patch

input
16 × 16 pixels × 3 colors = 768 raw numbers, the patch's RGB values scaled to about ±1.
what happens
One learned matrix of shape [4,096 × 768] multiplies the pixel list. That is a single matrix multiply, or matmul.
output
4,096 floats.
audio · a small net

~20 ms of sound

input
A slice of the spectrogram, a picture of the sound: 80 mel energies (loudness in 80 pitch bands) per 10 ms frame, plus its neighbors.
what happens
A few convolution layers and encoder layers process it. Then a connector maps the result to the LLM's width.
output
4,096 floats, one vector per ~20 ms.
in essence · three doors, one identical output
# the same LLM width (4,096 floats), reached three ways
"dog"                             # text: a table lookup, no computation
  → id 5679 → E[5679]
  → [ 0.013, -0.208,  0.091, ...,  0.044]

patch(row 3, col 7)               # image: one matrix multiply
  → 768 pixel values → W @ px
  → [-0.171,  0.062, -0.055, ...,  0.238]

frame @ t=1.20s                   # audio: conv + attention, then a connector
  → 80 mel energies → encode
  → [ 0.087, -0.114,  0.302, ..., -0.201]
# three origins, one shape. downstream, nothing can tell them apart.
The float values are invented for illustration. The shapes and the mechanics are the real ones.
the point An embedding is a fixed-length list of floats. A door does its job if it puts those floats in the right neighborhood, near other inputs that mean the same thing. Text gets its list from a lookup, a patch from a matmul, a sound from a small network. Either way, the transformer receives lists that look the same.
04 · images, part one

Cut the image into squares and treat each square as a word.

A sentence is already a sequence, so splitting it into tokens is natural. An image is a grid of a million pixels, with no obvious "first" or "next." The Vision Transformer solved this with a very simple idea. Chop the image into a grid of small squares and call each square a token. A patch of, say, 16×16 pixels becomes one item in a sequence, the same way a word does.

Each patch is flattened into one long line of numbers and passed through one small linear layer, the patch embedding, which turns its raw pixels into a vector in the shared space. Then a positional embedding is added so the model knows where the patch sat in the grid. Now the picture is a sequence of vectors, and it can go into the same transformer the words use.

a picture becomes a sequence
one image · 16 patches 16 vectors · one per patch
the patch's journey · tap a station or press play
01 / the image
A grid of pixels.
Start with a raw photo: a grid of red, green and blue values, with no order the model can read yet.
05 · order & position

Attention has no idea what came first.

Why did that stepper need an "add position" station at all? Look at what attention computes. Each token makes three small vectors from its embedding: a query, a key and a value. The score between two tokens is the dot product of one token's query with the other's key. A softmax turns the scores into weights that add up to 1, and the output is a weighted average of the values. Each of these operations treats the tokens as a set, with no order. No index, no "previous" and no "next" appear anywhere in the formula.

in essence · attention is a weighted average over a set
# attention, for one token A among {A, B, C}
w = softmax([q_A·k_A, q_A·k_B, q_A·k_C])   # who should A look at?
out_A = w[0]*v_A + w[1]*v_B + w[2]*v_C      # a weighted average. that is all.
# hand it B and C in swapped order: the same numbers come out.
# without position, "dog bites man" and "man bites dog" are one bag of words.

So order has to be put in as data. Before attention runs, a position vector is added to each token's embedding. Now position is part of every query and key, so the dot product between two tokens changes with how far apart they sit.

What does that position vector look like? The original 2017 transformer used sine waves. Each dimension goes up and down at its own frequency. Fast ones change at every position. Slow ones drift across thousands of positions, like the second, minute and hour hands of a clock. A Vision Transformer instead keeps a plain learned table: one vector per grid slot, random at the start and shaped by training. And most modern LLMs use RoPE, which rotates the query and key vectors by an angle proportional to position instead of adding anything. All three do the same job: they make the same token look different at different positions.

the sinusoidal position table · one column per position
Read the highlighted column from top to bottom. That list of values is the vector added to the token at slot 9. Fast rows change at every step; slow rows change gradually across dozens of steps. Each column is one position, written in sine waves.
the point The transformer has no built-in sense of order. Order gets in the same way meaning does, as numbers added into the vectors. That is why the same trick works for every modality: a 1D position for words, a 2D grid position for image patches, a timestamp for audio frames.
06 · images, part two

Getting image vectors into the language model's space.

Patchifying gives you image vectors, but they start out in the vision encoder's own space, which is different from the language model's. Two steps connect them.

First, alignment. A model called CLIP is trained on hundreds of millions of image-caption pairs to place a photo and its description at the same spot. After training, the text "a photo of a dog" and an actual dog photo land near each other. So the image vectors now carry meaning in a form that lines up with text.

Second, the bridge. Most vision-language models keep a frozen CLIP-style encoder (its weights are not trained any further) and add a tiny connector, often a two-layer network, that maps image vectors into the LLM's token space. This is the recipe behind LLaVA and most open vision models. A photo goes in as a few hundred visual tokens, placed in the prompt right next to the words.

in essence · one training example from each stage, verbatim
# a CLIP alignment pair (one of ~400,000,000)
{ "image": beach_dog_0412.jpg,      # just pixels, nothing labeled inside
  "text":  "a golden retriever running on a beach" }
# batched 32,768 at a time: pull each true pair together,
# push the 32,767 mismatches apart. that is the whole recipe.

# a LLaVA connector-tuning example (one of ~600,000)
{ "image": "coco/000000215677.jpg",
  "conversations": [
    { "from": "human", "value": "<image>\nWhat is unusual about this image?" },
    { "from": "gpt",   "value": "The man is ironing clothes on a board
                              attached to the roof of a moving taxi." } ] }
# at train time the <image> slot is replaced by ~576 vectors from the
# frozen vision encoder. only the tiny connector learns to make them legible.

Those few hundred tokens are why images cost what they do. Providers cut a picture into tiles and charge per tile. It works like text pricing: more visual detail means more tokens, and more tokens means more compute.

in essence · why one photo costs a paragraph's worth of tokens
# how many tokens is an image? (OpenAI high-detail accounting, 2026)
def image_tokens(w, h, tile=512):
    w, h = fit_inside(w, h, box=2048)      # shrink to fit a 2048 box
    w, h = scale_short_side(w, h, to=768)   # then short side -> 768px
    tiles = ceil(w/tile) * ceil(h/tile)     # count the 512px tiles
    return 85 + 170 * tiles                # base + per-tile
image_tokens(1024, 1024)                  # -> ~765 tokens for one picture
# Claude and Gemini use different formulas, same idea: detail = tokens.
the takeaway: A vision-language model is usually three parts: a vision encoder that patchifies, a connector that aligns, and the same LLM you already know. Only the middle piece is new, and it is often the smallest part of the system.
07 · audio

Sound becomes a picture first.

Raw audio is hard to model directly. One second of sound is tens of thousands of samples, far too many for attention to handle. So almost every audio model first converts the waveform into a spectrogram, a picture with time across the bottom and pitch up the side. Then it handles that picture almost the same way as an image.

This is what Whisper does. It turns the waveform into a log-mel spectrogram. Then a few convolution layers and a transformer encoder turn that into a sequence of vectors, one per short slice of time. From there, it works like every other input. Those vectors can feed a decoder that writes text, or be projected into an LLM so it can "hear" your voice note.

Generating audio needs the reverse. A neural codec compresses sound into a stream of discrete audio tokens using residual vector quantization. The model predicts those tokens like any other sequence, and the codec's decoder turns them back into a waveform. So to understand audio, a model uses the spectrogram door. To produce audio, it uses the codec door.

a waveform becomes a picture of sound
waveform · ~16,000 samples/sec spectrogram · time × frequency
in essence · 30 seconds of speech, by the numbers
# whisper-large's front door, concretely
samples = 30 * 16_000            # 480,000 amplitude values
mel     = log_mel(samples)        # (80, 3000) · 80 pitches x 10 ms frames
h       = conv_stem(mel)          # (1500, 1280) · stride-2 conv halves time
vectors = encoder(h)              # 1,500 vectors · one per 20 ms of sound
# 480,000 samples in, 1,500 vectors out: a 320x squeeze.
# your voice costs ~50 vectors per second, the price of dense prose.
the sound's journey · tap a station or press play
01 / the waveform
A long list of samples.
Raw sound is a list of amplitudes, measured tens of thousands of times a second. That is far too long for attention to handle directly.
08 · documents & PDFs

A model often reads a PDF as a picture of each page.

This one surprises people. A modern model usually does not parse a PDF's internal file structure at all. There are two doors, and the more interesting one is also the simpler one.

door one · read the text

OCR to tokens

how
OCR reads the characters off the page, and they go in as ordinary text tokens.
good at
Clean, text-heavy pages. Fast, cheap, reliable.
loses
A bar chart becomes a few stray numbers. A table with merged cells comes out scrambled. A diagram disappears.
door two · look at the page

Render as an image

how
Turn each page into a picture at ~200 DPI, then run it through the same image pipeline from sections 04 and 06.
good at
Layout, tables, charts, stamps, handwriting, anything where position on the page carries meaning.
costs
More tokens and more compute than plain text. Dense pages get expensive.

Look at what the second door means. To read your PDF, the model takes a screenshot of each page and cuts it into patches like any other image. Nothing tells it this is a "document." It sees a picture that happens to be full of words and lines, and reads it with the same vision machinery it uses for a photo of a beach.

mid-2026 · the scoreboard

So which models read documents best right now? The surprise of the past year is that the generalists won. On public OCR leaderboards in early 2026, the top of the table is held by general-purpose models, not document specialists. Gemini 3, Claude Opus 4.6 and GPT-5.2 are ordinary frontier multimodal models that read pages through the render-and-look door. They beat dedicated OCR pipelines on messy scans, receipts and handwriting, with roughly 3-4× fewer character errors on noisy pages.

Recent research turns the cost argument around. DeepSeek-OCR showed that reading a page as an image can be the cheap option. One vision token can carry roughly ten text tokens' worth of content at ~97% fidelity. So a dense page fits in a few hundred vision tokens, where a raw text dump of the same page needs thousands. Its January 2026 successor reads a complex page in 256 to 1,120 vision tokens. The image door was first chosen because it keeps the page faithful. Now it is also becoming a way to compress text.

whowhat it iswhy it matters
Gemini 3 · Flash / Progeneralist frontier VLMtops the OCR Arena leaderboard, early 2026
Claude Opus 4.6 · GPT-5.2generalist frontier VLMsbeat dedicated OCR systems on real documents
DeepSeek-OCR-23B document specialist~10× optical compression; a page in a few hundred vision tokens
dots.ocr · Qwen3-VLsmall open modelsnear-free parsing, 100+ languages

One caveat: VLM readers run 5-10× slower than classic OCR engines. What happens when they misread is covered next.

the accuracy question

If a page becomes patch vectors, there is a fair worry. Patchifying is lossy compression, so some detail is thrown away. And a next-token predictor never says "unreadable." Show it a smudged 7 and it will output the most plausible digit, with full confidence. Nothing in the mechanism guarantees that a number comes through correctly. So where does the accuracy come from? It comes from four places.

01 · spend enough tokens
The more pixels each character gets, the more accurate the reading. Pages are rendered at ~150-200 DPI and large pages are split into tiles, so more detail costs more tokens. DeepSeek-OCR measured the tradeoff: ~97% decoding accuracy under 10× compression, falling to ~60% near 20×. Use too few tokens and digits get misread.
02 · train on transcription
In training, models see millions of pairs of a page image and its exact text. They are scored by character error rate on document benchmarks. Reading characters out of patches is a skill the model learns, and one we can measure.
03 · open both doors at once
Production pipelines feed in the rendered page and the PDF's extracted text layer together. The text tokens carry the exact characters, the patch vectors carry the layout, and attention connects the two. This is how Claude's PDF mode reads documents.
04 · re-read, then verify
The patch vectors stay in the context, so when you ask about one table cell, the model can look back at that exact region. When mistakes are costly (invoices, contracts), pipelines cross-check against a classic OCR pass or require citations that point to a spot on the page.
in essence · how a careful pipeline reads a PDF
# both doors at once, then verify (Claude-style ingestion)
for page in pdf:
    seq += vision_tokens(render(page, dpi=200))   # layout, charts, stamps
    seq += text_tokens(extract_text(page))        # the exact characters
answer = llm(seq + question)
# digits anchor to the text stream, positions to the pixels.
# high stakes? cross-check with classic OCR, or require a
# page + bounding-box citation before trusting a number.
the short answer Accuracy has to be paid for. You pay with enough tokens for the resolution, transcription practice during training, a text layer that pins down the exact characters, and a second pass when a wrong digit costs money. The embedding lets the model understand the page. The checks are what let you trust it.
the takeaway: There is no special machinery for PDFs. A model reads a page either as text (the OCR door) or as an image (the render door). In 2026, frontier models more and more often use the image door, because a page's layout is information, and the only way to keep it is to look at the page.
09 · fusion

Three ways to feed a new modality to the LLM.

Once you can turn an image or a sound into vectors, one question is left: how do those vectors get into the language model? The field has tried three answers. In order, they go from attaching vision to an existing model to building it in from the start.

2022 · bolt it on

Cross-attention

idea
Keep the LLM frozen. Add new cross-attention layers that let the text look at a few image vectors.
bridge
A resampler compresses an image down to ~64 vectors.
seen in
Flamingo, early vision add-ons.
2023 · slot it in

Projection

idea
Project image vectors into the token space and concatenate them with the prompt, so everything is one flat sequence.
bridge
A small MLP connector. Hundreds of visual tokens.
seen in
LLaVA, most open VLMs.
2024+ · build it in

Native early-fusion

idea
No bridge. Every modality is turned into tokens from one shared vocabulary, starting in pretraining.
bridge
None. Trained on mixed streams from scratch.
seen in
Chameleon, GPT-4o, Gemini.
the arc Read those left to right and you see the history. First, image vectors were attached to a frozen language model through extra layers. Then images were fed in alongside the words, in one sequence. Now one model is trained on text, images and audio together from the start. With each step, the modalities share more of the same space.
10 · training

How the shared space is learned.

A shared vector space has to be learned. Something has to train the model so that a dog photo and the word "dog" land in the same place. There are three techniques, matching the three fusion styles.

Contrastive alignment comes first. Show the model a batch of image-caption pairs. Train it to pull each true pair closer together and push every mismatched pair apart. Do this across hundreds of millions of pairs and the image encoder and the text encoder end up placing matching things in the same spots. That is CLIP, and it is the reason any of this works.

Connector tuning comes next. Freeze the vision encoder and the LLM, and train only the small connector between them on image-and-caption data. Then do a light round of instruction tuning. This is cheap and fast, and it is enough to let a text model see images. Native pretraining is the expensive option. Mix every modality into one token stream and train the whole model on next-token prediction over all of it, from the first step.

in essence · the loss that builds the shared space
# CLIP: pull matching image+text together, push mismatches apart.
img = image_encoder(images)               # N images   -> N vectors
txt = text_encoder(captions)              # N captions -> N vectors
scores = img @ txt.T                       # N x N grid of similarities
loss = cross_entropy(scores, diagonal)    # the diagonal is the true pairing
# minimize this and "a dog" lands exactly where a dog photo lands.

The full pipeline, pretraining then post-training, is covered step by step in the LLM training explainer. For a multimodal model, the only difference is that the training data now includes pictures and sound as well as words.

11 · the other direction

Turning vectors back into pictures and sound.

Everything so far was about input: turning images and sound into vectors. Output goes the other way, from vectors to pixels or sound. There are two main ways to make an image, and they mirror the fusion choices above.

the transformer's native trick

Autoregressive tokens

idea
Predict image tokens one at a time, the same way as words. Then a codebook decoder turns the grid of token indices into pixels.
wins
One model and one loop for both text and images. It extends naturally to any-to-any.
seen in
Chameleon, GPT-4o image generation.
the image specialist's trick

Diffusion

idea
Start from random noise and denoise it over many steps toward an image that matches the prompt, working in a continuous latent space.
wins
Higher fidelity and more detail. Usually a separate specialist model.
seen in
Most standalone image and video generators.

Audio output works the same way, with an audio codec in place of the image codebook. The model predicts discrete audio tokens, and the neural codec's decoder rebuilds the waveform. Put input and output together and you get an any-to-any model: one network that can read a screenshot, hear a question, and answer in speech or with a new picture. Google's Gemini Omni, announced in May 2026, goes furthest. It is a single backbone that takes any mix of text, image, audio and video and can generate video as output.

the symmetry Input and output mirror each other. An encoder maps an image or a sound into the shared space. A decoder maps a point in that space back out to pixels or sound. Understanding and generation are the same path, traveled in opposite directions.
12 · why it works

Attention cannot tell where a vector came from.

Why does all of this work? Look at what attention does. It takes a set of vectors and computes weighted averages of them, based only on how they point relative to each other. No tag says where a vector came from, and attention never looks for one. To the attention math, a vector from the word "cat" and a vector from a 16×16 patch of fur are the same kind of thing: a point in the space.

In these models, meaning is geometric. A vector's meaning comes from where it sits and what it sits near. So suppose your encoder does its job and places the sound of a dog barking near the word "dog" and near a photo of a dog. Then reasoning about the sound and reasoning about the sentence are the same computation. The transformer does not translate between modalities. Once every input is a point in one space, there is nothing to translate.

That is why the gap between modalities is a problem of encoding, not reasoning. Adding a new sense to a model (touch, smell, a stream of sensor data) has never required a smarter transformer. It requires a good encoder that maps the new signal into the shared space. The transformer's reasoning already works on any input placed in that space.

the crux The hard, mysterious part of a multimodal model is the next-token engine, and you already know how that part works. The new work is all at the edges: the encoders that decide where each kind of input lands in the shared space. If they place things well, the transformer can reason about the new input without any changes.
13 · closing

The same LLM, with more ways in.

A multimodal model is the same LLM you already understand, with more doors. The transformer still never sees a word, a pixel or a sound wave. It sees vectors, mixes them with attention, and predicts the next one.

Everything on this page came from one idea: turn each modality into a sequence of vectors in one shared space. Cut an image into patches, turn a sound into a spectrogram, take a screenshot of a page. Align them with contrastive training. Then connect them with a small connector, or train everything together from scratch. Run the process backwards through a decoder and the model can produce pictures and sound too. Understand the encoders, and the rest is the LLM you already know.

The interactive diagrams are simplified sketches meant to build intuition, not to show exact tensor shapes. Patch counts, token costs and codebook sizes are typical figures from the cited papers and provider docs. They vary by model and configuration.

built to learn, one vector at a time
← back to heqinghuang.com reasoning models llm training