Diao, Wang, Wu, Liu et al. (S-Lab NTU + SenseTime), 2026

NEO-ov: Pixels to Words
Without an Encoder

A single decoder-only transformer that learns to see — no CLIP, no SigLIP, no projector. One backbone unifies single images, multi-image, video, and 3D spatial reasoning by sending raw patches and words into the SAME stream.

Prerequisites: Transformers & attention + VLM intuition + RoPE basics
10
Chapters
6
Simulations

Chapter 0: The Problem

Almost every vision-language model you have heard of — LLaVA, Qwen-VL, InternVL — is built the same way. Take a pretrained image encoder (CLIP or SigLIP). Run the image through it. Take the resulting feature vectors, push them through a small "projector" MLP, and paste them in front of a language model as if they were word embeddings. Three modules, stitched together, trained in stages.

It works astonishingly well. So why would anyone tear it apart?

The core tension: A vision encoder like SigLIP was trained to do one thing — match an image to a caption. To do that, it learns to throw away everything that doesn't help captioning: exact textures, fine geometry, pixel-level position. By the time those features reach the language model, the picture has already been semantically filtered. The LLM never sees the raw pixels — it sees a summary written by a module optimized for a different goal.

Three concrete cracks in the modular design

The paper lays out three failure axes. Each is worth feeling viscerally before we reach for a solution.

A worked example of "semantic filtering"

Say you ask "Is the second word on the sign slightly higher than the first?" A SigLIP encoder compresses a 384×384 image into ~729 tokens optimized for caption matching. The vertical pixel offset between two words — a handful of pixels — contributes almost nothing to a caption-matching loss, so it gets averaged away. The LLM literally cannot recover information the encoder already discarded.

This is why modular VLMs are strong on "what is in the image?" and weak on "where exactly, and how does it relate spatially?". Fine-grained perception and spatial intelligence are precisely the casualties of the encode-then-project pipeline.

The bet of this paper: what if the language model saw the pixels directly, from layer one, and learned vision from scratch alongside language — so that nothing is filtered before reasoning begins?
Why do modular VLMs struggle with fine-grained spatial perception?

Chapter 1: The Key Insight

NEO-ov ("ov" = one-vision) deletes the vision encoder entirely. There is no CLIP, no SigLIP, no projector. An image becomes tokens through a tiny convolutional patch embedder — about as heavy as a word-embedding table — and those visual tokens are interleaved with text tokens and fed into one decoder-only transformer.

The insight: A monolithic backbone where pixels and words share the same layers from the start lets vision capability emerge natively inside the language model. Cross-image comparison and temporal reasoning refine jointly from shallow to deep layers — instead of operating on features that were already compressed by an external module.

What "native" actually buys you

This is the lineage of Fuyu and EVE — "encoder-free" VLMs — and of NEO, the authors' prior work. NEO-ov's specific contribution is extending native modeling from mostly single-image settings to a true one-vision model: single image, multiple images, and video all handled by the same primitives, with strong 3D spatial intelligence as a bonus.

Three native primitives carry the whole design

1. Patch Embedding
Two conv layers turn raw pixels into tokens — no pretrained encoder. Any resolution in.
2. Native-RoPE
Position encoding with separate Temporal / Height / Width indices and frequencies. One scheme for text, images, and frames.
3. Native Mixed Attention
Bidirectional inside each image/frame, causal across units. Dense 2D vision meets autoregressive language in one mask.
↓ all inside one decoder-only backbone

What changes from a normal LLM?

AspectStandard text LLMNEO-ov
Input embeddingsWord embedding layer onlyWord embedding (WEL) + Patch embedding (PEL)
Position1D RoPE (one index per token)Native-RoPE: 3 indices [t, h, w] per token
Attention maskFully causalMixed: bidirectional within a visual unit, causal across units
Attention headsSingle head dimensionHead dim split into decoupled T, H, W components
Backbone initFrom scratch or pretrainedPre-Buffer + post-LLM init from NEO & Qwen3

Everything else — the transformer blocks, the next-token objective — is unchanged. That minimalism is the point: vision is added by changing how tokens are made, positioned, and masked, not by bolting on a second network.

What does NEO-ov replace the vision encoder with?

Chapter 2: Modular Background

Before we build the native version, let's trace the data flow of the thing we're replacing so the differences are concrete.

The modular pipeline, step by step

For an image I ∈ R^{H×W×3} and instruction text, the LLaVA-style pipeline does:

  1. Encode: SigLIP ViT ingests I resized to a fixed grid (e.g. 384×384), outputs R^{729×1152} patch features. These are tuned for image-text contrastive matching.
  2. Project: An MLP maps 1152 → d_LLM (e.g. 3584), giving R^{729×3584} — now "pretend word embeddings".
  3. Concatenate: Stick those 729 visual tokens in front of the tokenized text.
  4. Decode: A causal LLM autoregressively answers.
Where the information dies: step 1. The SigLIP loss never asked the encoder to preserve exact pixel positions, fine texture, or sub-patch geometry — only enough to match a caption. Steps 2-4 cannot resurrect what step 1 threw away. The LLM reasons over a summary, not the scene.

Why this also hurts video and KV caching

The vision encoder sits outside the autoregressive decoder. In a decoder-only LLM, each new token reuses the cached keys/values of all previous tokens — that's the KV cache, the reason generation is fast. But the encoder is a separate forward pass per image; there is no incremental cache across frames of a streaming video. Every new frame re-pays the full encoder cost. For a 128-frame clip that is murderous.

A native model folds the "encoder" into the decoder itself. Visual tokens become first-class citizens of the same KV cache as text — so the cache mechanism works across frames automatically.

The encoder-free lineage

ModelYearKey idea
Fuyu2023Feed image patches straight into a decoder-only transformer; no encoder
EVE / EVEv22024Learn vision from scratch; distill from a visual encoder to stabilize
NEO2025Shared pixel-word representation; Pre-Buffer + native RoPE; closes gap to modular
NEO-ov2026Unify single-image, multi-image, video & spatial intelligence natively
Why can't a modular VLM reuse a KV cache across video frames?

Chapter 3: Patch Embedding

If there's no SigLIP, how does an image become tokens? With two convolutions and a GELU — that's it. Let's trace the exact shapes.

xv = Conv2( GELU( Conv1(I) ) + PE )

Reading symbol by symbol:

The headline number: one visual token represents a 32×32 pixel region. A 1024×1024 image → 32×32 = 1024 visual tokens. A 256×256 image → 8×8 = 64 tokens. The token count scales with the image — no fixed 729-token budget. Big images keep their detail; small images stay cheap.

Worked example: how many tokens?

Take a 640×480 photo. Downsample by 32: width → ⌊640/32⌋ = 20 tokens wide, height → ⌊480/32⌋ = 15 tokens tall. Total = 20×15 = 300 visual tokens, arranged as a 20×15 grid. Those tokens get wrapped with the special markers <img></img> and concatenated with the text tokens.

Patchify an Image — Drag the Resolution

Why this beats a frozen encoder for fine detail

A patch token here is a learned linear-ish map of raw pixels in its 32×32 region. The gradient that shapes it flows all the way from the answer loss — so the embedder learns to keep exactly the pixel structure the task needs (text edges for OCR, geometry for spatial questions), not what a caption-matching loss wanted. Nothing is pre-filtered.

# Native patch embedding: pixels -> tokens, no pretrained encoder
import torch.nn as nn

class PatchEmbed(nn.Module):
    def __init__(self, d=2048):
        super().__init__()
        self.conv1 = nn.Conv2d(3, d, kernel_size=16, stride=16)  # 16x16 patches
        self.conv2 = nn.Conv2d(d, d, kernel_size=2, stride=2)   # aggregate 2x2 -> 32x32 region/token
        self.act   = nn.GELU()

    def forward(self, img, pe):           # img: [B,3,H,W]   pe: 2D RoPE grid
        x = self.act(self.conv1(img)) + pe  # [B,d,H/16,W/16]
        x = self.conv2(x)                   # [B,d,H/32,W/32]
        return x.flatten(2).transpose(1,2)  # [B, (H/32)*(W/32), d] visual tokens
How many visual tokens does a 512×512 image produce?

Chapter 4: Native-RoPE

Now the deepest idea. A text LLM gives each token one position index, 0,1,2,…, and rotates the query/key by that index (RoPE). But a visual token isn't on a line — it lives at a (row, col) inside a frame, at some point in time. One index can't express that. So Native-RoPE gives every token three indices.

idxi = [ ti, hi, wi ]
The clean rule: A text token sets h = w = 0 and only uses t — so text behaves exactly like a normal LLM. A visual token shares one t with all patches in its image (they're "simultaneous"), and uses h, w to say where in the grid it sits. Spatial indices reset per image; the temporal index runs continuously across the whole sequence.

How three indices enter attention

The head dimension is split into a T part, an H part, and a W part. Each query and key carries three sub-vectors, each rotated by its own index:

qi = [ qTi ; qHi ; qWi ]    kj = [ kTj ; kHj ; kWj ]

The attention score is then the sum of three dot products — one per axis:

sij = ⟨qTi, kTj⟩ + ⟨qHi, kHj⟩ + ⟨qWi, kWj

So one attention head simultaneously measures "how close in time / sequence", "how close in row", and "how close in column". The T branch inherits the LLM's language and cross-frame reasoning; the H and W branches are new capacity added for 2D structure. The original LLM head dimension is preserved as the T component — that's why language ability isn't damaged.

Different frequencies for different axes

RoPE rotates faster or slower depending on a base frequency θ. NEO-ov picks deliberately different bases:

AxisBase θIndex rangeWhy
T (temporal)1,000,0000 … ~n·104-6Long sequences (128-frame video, 36K tokens) need very slow rotation to stay distinguishable
H / W (spatial)10,0000 … ~n·102Spatial grids are small (tens of patches); a tighter range gives sharper position resolution
Why the huge T base? A larger θ makes the lowest-frequency dimensions rotate very slowly, so even tokens thousands of positions apart still have distinguishable angles. That's exactly what you need to address every patch across a 128-frame video without two distant frames colliding to the same phase.
Native-RoPE Index Assignment — Watch [t,h,w] Flow
Each cell shows its [t,h,w]. Notice: text tokens have h=w=0; all patches of one image share a t; t never resets, h/w reset per image.
For a text token in NEO-ov, what are its h and w RoPE indices?

Chapter 5: Native Mixed Attention ★ SHOWCASE

Here is the heart of the model — and the place where "vision" and "language" reconcile. A language model is causal: token i can only see tokens ≤ i (you can't read the future). But an image is not a sequence — every patch should see every other patch in the same frame (2D structure is bidirectional). NEO-ov satisfies both at once with one mask.

The mask, in one line

Let ui be the visual unit index of token i: ui = 0 means a text token; ui > 0 means token i belongs to image/frame number ui. Then token i may attend to token j iff:

Mij = 1  ⇔  ( j ≤ i )  ∨  ( ui = uj > 0 )

Read it as an OR of two permissions:

The payoff: inside an image, attention is dense and bidirectional — rich 2D structure is modeled directly from patch tokens at the earliest layers. Across images / frames / text, attention stays causal — so cross-frame reasoning and language generation behave like a normal autoregressive model. One mask, both behaviors.

Build it and break it

The simulator below lays out a real sequence: text · Img1 (3×3 patches) · text · Img2 (2×2) · text. Click any token to see exactly which tokens it can attend to under the NEO-ov mask. Toggle the bidirectional rule off to watch it collapse to a plain causal LLM — and see the within-image links vanish.

Native Mixed Attention Mask — Click a Token
Click any token to highlight what it attends to.
What you should observe: with the rule ON, click a patch inside Img1 — it lights up all of Img1 (forward and backward) plus everything before Img1. Turn the rule OFF and the same patch can only see earlier tokens — the future patches in its own image go dark. That lost bidirectional structure is exactly what gives native VLMs their fine-grained 2D perception.

The data-flow consequence

In a modular VLM, "image understanding" is finished before the LLM starts — the encoder already produced fixed features. In NEO-ov, because patches attend bidirectionally inside the backbone, image understanding co-evolves with reasoning: shallow layers resolve local geometry, deep layers fuse it with the question and with other frames. Cross-frame comparison is refined layer by layer rather than computed once by a frozen module.

# Native mixed attention mask: bidirectional within a visual unit, causal across units
import torch

def native_mask(unit):           # unit: [N] long; 0 = text, >0 = which image/frame
    N = unit.shape[0]
    i = torch.arange(N)[:, None]
    j = torch.arange(N)[None, :]
    causal   = j <= i                                # look back at everything before
    same_img = (unit[:, None] == unit[None, :]) & (unit[:, None] > 0)
    return causal | same_img                          # [N,N] boolean: True = may attend
Under NEO-ov's mask, when can two tokens attend to each other regardless of order?

Chapter 6: Unified Serialization

We have a way to embed images (Ch 3), position them (Ch 4), and mask them (Ch 5). The last piece: how do you lay out a conversation that may mix text, several images, and a video into one flat token sequence the backbone can read?

One image

Insert one visual segment at the <img> slot, wrapped in markers, surrounded by text. That segment becomes visual unit 1; the patches inside it share one t index and attend bidirectionally.

Multiple images

Each <img> in the prompt becomes an independent visual unit, in textual order:

Xmulti = [ xt1, <img> xv1 </img>, …, xtm, <img> xvm </img>, q ]

Crucially, each image is encoded at arbitrary resolution, so image 1 might be 256 tokens and image 2 might be 1024 — the budget adapts per image. That's exactly what fine-grained comparison ("which photo is sharper here?") needs: details aren't squashed to a common token count.

Video = ordered frames with timestamps

A video is not compressed into one global embedding. Instead, f frames are sampled, each serialized as its own image unit, each tagged with its timestamp:

Xvideo = [ pglobal, [τ1]: <img> xv1 </img>, …, [τf]: <img> xvf </img>, q ]
The unification: video and multi-image are the same mechanism. A video is just a sequence of image units carrying timestamps; the temporal index t (Ch 4) supplies frame order; the mixed mask (Ch 5) makes within-frame attention bidirectional and cross-frame attention causal. No separate video encoder, no separate code path.
Serialize a Sequence — Switch Input Type
How does NEO-ov represent a video?

Chapter 7: The Training Recipe

You can't just throw random pixels and words at a transformer and hope vision emerges. NEO-ov uses a three-stage curriculum that protects the pretrained language ability while growing visual capacity. The frozen/trained pattern is the whole story.

Three-Stage Training — What's Frozen vs Trained

Stage 1 — Pre-Training (align without forgetting)

Train on ~20M image-text caption pairs. Only the patch embedding layers, the Pre-Buffer layers, and the new QK parameters (the H/W head components from Ch 4) are unfrozen. The main LLM stays frozen. Why? Because the pretrained Qwen3 language priors are precious — if you trained everything on noisy captions, you'd wreck them. Freezing the LLM forces visual tokens to align into the existing language space rather than dragging it around.

Stage 2 — Mid-Training (scale spatiotemporal reasoning)

Now all layers are unfrozen and trained on ~60M samples spanning single-image, multi-image, and video, with resolutions from 256² up to 4096² and videos up to 128 frames. The context window is grown from 16K to 36K tokens. This is where the model learns to handle high-resolution detail and long temporal context — the LLM is now mature enough that joint optimization won't destroy it.

Stage 3 — Supervised Fine-Tuning (polish)

~6M high-quality instruction samples (~4M single-image, ~1M multi-image, ~1M video) covering VQA, OCR, fine-grained perception, temporal reasoning, math, dialogue. Whole model end-to-end under next-token prediction. This sharpens instruction following and fine-grained perception.

 Stage 1: Pre-TrainStage 2: Mid-TrainStage 3: SFT
Data~20M caption pairs~60M (img/multi/video)~6M high-quality
Resolution256²–1024²256²–4096²256²–4096²
What trainsPEL + Pre-Buffer + new QKAll layersAll layers
LLM backboneFrozen 🧊Trained 🔥Trained 🔥
Peak LR2×10-45×10-55×10-5
Concept + realization: The freeze schedule is the alignment strategy. Stage 1 = "learn to speak the LLM's language with your eyes, but don't touch its grammar." Stage 2 = "now you both grow together." Stage 3 = "act polite." Skip Stage 1's freeze and you get catastrophic forgetting of language; skip Stage 2's unfreeze and vision stays shallow.

Implementation footprint

Backbones: Qwen3-1.7B and Qwen3-8B. Pre-Buffer: 12 layers (2B model) / 6 layers (9B model). Native-RoPE bases fixed at θT=106, θHW=104. AdamW, cosine decay, warmup ratio 0.01, trained on sixteen 8×80GB-GPU nodes.

Why is the LLM backbone frozen during Stage 1 pre-training?

Chapter 8: Experiments

The claim to test: a fully encoder-free model can match or beat encoder-based competitors of the same LLM scale — and especially shine on fine-grained perception and spatial intelligence. The toggle below compares NEO-ov against its closest baselines on real benchmarks from the paper.

NEO-ov vs Baselines — Pick a Domain

Image understanding (8B class)

Against prior native VLMs, NEO-ov sets a new frontier. On MMMU it jumps to 68.1 (vs NEO's 54.6, SAIL's mid-50s). On OCRBench it reaches 81.6, on DocVQA 91.9, on ChartQA 86.2 — territory that used to belong only to encoder-based models. The gains are biggest on reasoning- and hallucination-sensitive tasks (MMMU, HallusionBench), confirming that native end-to-end modeling unlocks strong visual reasoning.

The honest caveat the paper states: OCR-intensive tasks remain the hardest gap to modular systems. Reading dense text is exactly where a vision encoder's pretrained text-detection prior helps most — and where learning from scratch costs the most. NEO-ov narrows but does not fully close this gap.

Video understanding

At 8B, NEO-ov leads native VLMs on every video benchmark reported — VideoMME 62.8, MVBench 70.7, MLVU 69.3, LongVideoBench 67.4, VideoMMMU 51.6 — far above Fuyu/EVE/ELVA. The unified frame-as-image-unit serialization (Ch 6) plus the temporal RoPE index (Ch 4) is doing real work: no separate video encoder, yet competitive video reasoning.

Spatial intelligence — the standout

This is where "native" pays off most. On Mindcube, NEO-ov (8B) scores 90.0 — beating even spatial-specialist models like Sensenova-SI (85.7) and GeoThinker (83.0), and crushing general models InternVL3.5 (40.4) and Qwen3-VL (29.6). On VSI-Bench it reaches 64.8 vs InternVL3.5's 56.3. Because patches enter the backbone un-filtered and attend bidirectionally, the model retains the pixel-level geometry that modular pipelines discard — exactly the information spatial reasoning needs.

Reading the data flow behind the win

Why does an encoder-free model win on spatial tasks specifically? Trace it: a spatial question ("is object A left of and behind object B?") depends on precise relative position. A frozen SigLIP encoder already pooled that away into caption-level semantics. NEO-ov's patch tokens still carry their (h, w) via Native-RoPE and their cross-frame order via t — so the geometry survives all the way into the reasoning layers. The architecture preserves the very signal the task needs.

On which capability does NEO-ov most dramatically outperform — even beating specialist models?

Chapter 9: Connections & Cheat Sheet

NEO-ov sits at the intersection of three threads: encoder-free VLMs (Fuyu → EVE → NEO), multi-axis positional encoding (RoPE → M-RoPE → Native-RoPE), and unified video-language modeling.

2023
Fuyu — patches straight into a decoder; first practical encoder-free VLM
2024
EVE / EVEv2 — learn vision from scratch with distillation to stabilize
2025
NEO — shared pixel-word representation + Pre-Buffer + native RoPE
2026
NEO-ov — one native backbone for image, multi-image, video & spatial intelligence

The cheat sheet — every key equation

IdeaEquationWhat each symbol means
Patch embedxv = Conv2(GELU(Conv1(I)) + PE)I = raw image; stride 16×2 → 32; one token per 32×32 region
3-axis indexidxi = [ti, hi, wi]t = temporal/order; h,w = spatial; text sets h=w=0
Split query/keyqi = [qT; qH; qW]head dim split; T inherits LLM, H/W are new spatial capacity
Attention scoresij = ⟨qT,kT⟩ + ⟨qH,kH⟩ + ⟨qW,kWsum of per-axis similarities
Mixed maskMij=1 ⇔ (j≤i) ∨ (ui=uj>0)u = visual unit; causal across units, bidirectional within
Video serializeXvideo=[pglobal, [τk]:<img>xvk</img>, …]τ = timestamp text; frame = image unit

When to reach for native vs modular

NeedNative (NEO-ov)Modular (LLaVA-style)
Fine spatial / geometryStrong — pixels un-filteredWeak — encoder discards geometry
Dense OCRImproving, still a gapStrong — text-detection prior
Long/streaming videoKV cache works across framesRe-run encoder per frame (expensive)
Fast to build todayCostly from-scratch vision trainingReuse off-the-shelf encoders
The lasting lesson: the vision encoder was never free. Its convenience came at the cost of pre-deciding what the language model is allowed to see. Removing it is expensive to train, but it hands the LLM the raw signal — and on the tasks that need that signal most (spatial reasoning), native wins decisively.
"Take the red pill, NEO-ov."
— from the paper's own teaser figure