What we learn along the way

Notes on engineering, research and building a company.

← All articles

Text as pictures: what a page costs

Apple's LensVLM reads a document as compressed page images and expands only the pages it needs. We ran it on a Mac and measured what a page costs in context.

Chapters

When a report is too long for a model's context window, a common answer is to split it into chunks and retrieve the passages that look relevant. That saves space, but the model can only work with the passages it receives. A detail left outside the selection is a detail it cannot use.

Apple's LensVLM explores another approach. It scans the whole document as tiny page images, decides which pages are worth reading, and asks for their full text.1 Think of spreading pages across a desk before picking one up to read. The overview stays in sight, and the original words remain within reach.

We wanted to see what that exchange buys on a Mac: how much context the pictures save, what happens when a page comes back as text, and whether the model finds the evidence it needs. We followed one document through the complete loop.

What the model does

LensVLM is a 9B vision-language model Apple published on 21 September 2026. The language tower is Qwen3.5-9B and the vision encoder comes from the Qwen3-VL family. Render a document to page images, and the model receives one image per page. It scans them, reasons about what it can see, and calls a read_page tool to get the text of a page it wants to examine properly.2

Apple ships three compression presets: 5x, 10x and 15x. Each fixes the page width and font size, with a target text capacity per page. The renderer, the system prompt and the tool loop are in the same public repository as the model.3

The model weights are licensed for research only. The Apple Machine Learning Research Model License excludes commercial exploitation, product development and use in commercial products or services. The code has a separate Apple Sample Code License. Our interest here is in examining the mechanism; adopting the model in a product would require different permission.4

Running it on a Mac

Apple's reference demonstration uses vLLM. We adapted its loop to mlx-vlm on an Apple M4 with 24 GB of unified memory, keeping the upstream renderer, system prompt, tool parsing and answer extraction.5 The 4-bit conversion of the weights is about 8 GB on disk and loaded in roughly three seconds in our runs.6

We used the example Apple ships with the repository: 32 033 characters, or 5 136 words, assembled for a question about the actress who played Corliss Archer in Kiss and Tell and the government position she later held. The reference answer, often called the gold answer, is "Chief of Protocol". The example also records a 15-page rendering at 10x, which our renderer reproduced.7 This document fits as text too; it lets us inspect the mechanism without making context capacity the limiting factor.

Apple's published evaluation uses vLLM on a node with eight B200 GPUs. Our measurements below describe the quantised MLX conversion on one consumer Mac.

What a page costs

Text occupies a model's context as tokens, usually words or pieces of words. Images become visual tokens that occupy context too. We counted both with the model's processor, after it had applied the chat template and expanded each image into the tokens the model receives.

The table separates the document from the conversation around it. "Document only" subtracts an identical short prompt from each representation. "First turn" includes Apple's tool instructions and the actual question. "Second turn" also includes the model's first response and the page text it requested.

RepresentationDocument onlyFirst turnSecond turn
Plain text7 9328 123n/a
5x page images1 4161 6072 298
10x page images7389291 784
15x page images5307211 354

All counts are tokens. Turn counts describe the input to each generation, not cumulative work or peak memory use. The plain-text prompt was counted but not run through the model.

Two charts. The left one shows the document alone with one identical wrapper: 7 932 tokens as plain text, 1 416 as 5x page images, 738 at 10x and 530 at 15x. The right one shows the prompts the harness sent, in two bars per preset: 1 607 and 2 298 at 5x, 929 and 1 784 at 10x, 721 and 1 354 at 15x.

Left: the document alone, with the same wrapper for text and images. Right: the prompts the harness sent, on the first turn and on the second turn after the model expanded one page. Counts come from the model's processor applied to the harness's own message lists.8

At 10x, the document takes 738 tokens as pictures, compared with 7 932 as text: about one tenth of the space. The full second-turn prompt grows to 1 784 tokens once the conversation and the requested page are included. That is still about 4.6 times smaller than the 8 123-token plain-text prompt, but it is a different comparison from the pictures alone.8

Those 738 tokens comprise 708 image tokens and 30 delimiters marking the 15 images. The average is 47.2 image tokens per page. Apple documents 48 for a full-sized 10x page; our shorter final page brings the average down. The same distinction applies at the other presets: our averages are 68.8 and 23.2, against Apple's 72 and 24 for full-sized pages.1

Two panels showing the same text. The left panel is the text rendered at 700 pixels wide, readable. The right panel is the same text as the model receives it at the 10x preset, 192 by 252 pixels, displayed 2.25 times larger.

The same text at two resolutions. At 10x a page is 192 pixels wide with a 6 pixel font; the right panel is enlarged for this article and the model sees the smaller version.

One detail to watch before assuming a compression preset is a page budget: the page count is not monotonic. This document needs 20 pages at 5x, 15 at 10x and 21 at 15x, because a preset changes how much text fits on a page at the same time as it changes the resolution. The 10x preset needed the fewest pages here, while 15x spent the fewest tokens. Neither is a rule, so measure the document you have.

Does it still answer?

We ran the full loop at all three presets: scan the compressed pages, call read_page when the model asks, and let it answer.9 The tool response contains the real page text, so the model works with the source document wherever it points.

PresetPages scannedPage expandedPage text returnedFirst turnSecond turnAnswer contains gold
5x20131 687 chars21.4 s23.6 syes
10x15102 192 chars17.0 s18.7 sno
15x21141 576 chars14.1 s8.4 syes

All three runs opened the relevant page and finished in two turns. They received between 1 576 and 2 192 characters as expanded text, out of 32 033 in the document, alongside the images of every page. Turn durations are wall clock on our machine, with the model already loaded and greedy decoding, and include image processing.10

At 10x the model chose page 10, matching Apple's published example. That page identifies Shirley Temple and lists several government roles: United States ambassador to Ghana, ambassador to Czechoslovakia, and Chief of Protocol of the United States. Our 10x run answered with the ambassadorships, the 5x run with "Chief of Protocol of the United States", and the 15x run with both.

The question asks for a government position without specifying which one. The 10x answer is supported by the page even though it does not contain the gold string. Finding the evidence and matching a reference answer are separate checks. Here, the latter is a literal string check, not a judgment that the other answer is false.

One document and one question cannot establish answer quality. They do show the interaction working: scan the images, select a page, read its source text, then answer, without building a retrieval index or loading the entire document as text.

Fewer tokens is not a shorter wait

A smaller context is not the same as a faster answer, and this is the tradeoff worth understanding before adopting the pattern. Apple's efficiency appendix measures it: with the typical single expansion, LensVLM needs two sequential inference turns totalling about 17 seconds against about 8 seconds for the single-turn text baseline, roughly twice the latency at batch size one with 256 generated tokens on B200 hardware.11

Two things cause that. Each expansion forces a generate-then-prefill round trip that cannot be parallelised, and every rendered page has to pass through the vision encoder before the language model sees anything, work that a text-only baseline skips entirely. What the approach buys instead is memory and coverage: in the same appendix, 20 pages at 15x cost the reader 2 288 tokens after all expansions against 10 686 for the text baseline, a 78.6 percent reduction in peak key-value cache, and 84.2 percent at 100 pages.

Our Mac runs took 22.5 to 45 seconds across the two turns. We did not time a full-text baseline on the Mac, so these runs do not establish a local speedup or slowdown. The measured saving is in prompt size; Apple's separate experiment shows why that need not translate into a shorter wait.

What carries over

The compression is a dial set before the run. Page geometry determines the initial visual-token budget. Choosing a preset does not require knowing the question, though the final conversation grows according to which pages the model opens. Count both when sizing a context window.

The original text remains available. There is no embedding index to build for this loop. The model sees every page in compressed form and can request the words behind a promising image. Apple's analysis reports that, as compression rises, the model relies more on expanded text and less on its own reading of the small images.1

The trained reader matters as much as the small pictures. Apple's rendering study compared three page geometries at roughly matched compression. The untrained baseline's accuracy varied by 18 percentage points; variants trained for those configurations differed by only half a point. The vision encoder stayed frozen during training. Shrinking pages alone does not give an arbitrary vision-language model the same behaviour.1

What we did not measure

We did not reproduce Apple's benchmark table. Their results cover seven text QA benchmarks judged by a 397B model; ours covers one document on one machine, and the two should not be compared.

We used one 4-bit conversion. Its per-layer bit allocation was transferred from another model rather than measured on this one, and its documented visual checks use simple shapes. Our runs exercise compressed document pages, but do not measure how much quality the conversion preserves. We also did not separate the effects of quantisation and the different runtime; that would require comparison with the bfloat16 weights and the reference path.

We have not tested Swedish documents, which matters more to us than it will to most readers. The published text evaluations are English, and the compressed page is a picture of whatever text you render into it, including diacritics at five pixels of height.

Conclusion

The question we started with was whether a smaller view could keep the evidence within reach. On this example, it did: at 10x, fifteen page images took 738 tokens, and the model requested the page containing the answer. Its second-turn prompt, including that text and the conversation, used 1 784 tokens against 8 123 for the plain-text alternative.

That gives us a concrete pattern to investigate when a document strains the context budget: keep an overview of every page, then spend more context on the evidence that needs it. Testing it on real work means measuring answer quality, the full conversation and the wait, alongside a retrieval or full-text baseline. Our single example cannot choose between those approaches, and LensVLM's research-only licence remains a separate constraint.

What stays with us is the division of attention. A small view can help locate the right page; the original words are still there when it is time to read.

Footnotes

  1. Xie, Friedman, Yu, Pan, Fifty, Kim, Du, Gan, Rathod and Dhingra, LensVLM: Selective Context Expansion for Compressed Visual Representation of Text, arXiv 2605.07019, submitted 7 May 2026. The abstract reports accuracy comparable to the full-text upper bound at 4.3x effective compression and results above retrieval-based, text-compression and visual-compression baselines up to 10.1x on seven text QA benchmarks. Both figures are compression levels, not accuracy multiples. ↩ ↩2 ↩3 ↩4

  2. Apple, apple/LensVLM-9B model card, published 21 September 2026. The card documents the read_page tool, the 5x, 10x and 15x compression options and the model's base architecture. ↩

  3. Apple, apple-aiml-research/ml-lensvlm at commit 10709a7. The compression presets live in lensvlm/rendering_config.py, the tool-calling system prompt in lensvlm/prompts.py, and the multi-turn loop in lensvlm/evaluate.py. The demonstration scripts import vLLM. ↩

  4. Apple Machine Learning Research Model License, consulted 24 September 2026. The grant is limited to research purposes and is revocable. The repository code is released under the Apple Sample Code License. ↩

  5. Device record, pins and setup commands: README.txt in the evidence bundle. The machine is an Apple M4 with 24 GB of unified memory running macOS 26.6.2, with Python 3.12, mlx-vlm 0.7.2 and mlx 0.32.2. ↩

  6. mlx-community/LensVLM-9B-OptiQ-4bit, revision 9e3d1de1d65ed7a301cdeed4b58e70a461a02463. Published 24 September 2026, about 7.1 GB for the language tower and 0.9 GB for the vision tower in a sidecar file. The card states that the per-layer bit allocation was transferred from the Qwen3.5-9B conversion rather than measured on this model. ↩

  7. Precisit, renderer check. The bundled example records 15 pages at 10x; our run produced the same count. Full pages are 192 by 252 pixels, with a shorter final page at 192 by 198. The file records the page counts and sizes for all three presets. ↩

  8. Precisit, measured token cost. Document-only counts subtract the same 27-token wrapper from each representation. Turn counts use Apple's system prompt and the actual question, with the recorded first response and tool response added on turn two. The counter uses the harness's message-building helpers and the model's processor. These are input lengths before generation, not a measurement of peak key-value cache allocation. ↩ ↩2

  9. Precisit, evidence bundle (ZIP), containing the portable MLX harness, two measurement scripts, raw run logs and every JSON file cited here. The harness adapts the reference loop to mlx-vlm generation and imports Apple's renderer, prompts, tool parsing and answer extraction. ↩

  10. Precisit, run receipts and the same table as CSV. Greedy generation used a 1 024-token cap per turn and no custom stop sequence; every recorded turn ended below the cap, the largest at 188 tokens. Apple's demonstration stops at the closing tool-call tag; our harness relies on the model's end-of-turn token. Model loading is outside the recorded durations. The archive includes the raw logs and a portable copy of the harness, with its subsequent setup changes documented. ↩

  11. The same paper, efficiency analysis and limitations. Its latency comparison uses a single expansion, batch size one, 256 generated tokens and B200 hardware; its token counts are peak key-value cache occupancy at the final turn, measured through vLLM with tensor parallelism 8 on 20 and 100 input images. ↩

Keep readingMeet your one-pass AI opponentM5 Pro vs M4 Pro: the training side of a Mac mini upgrade ← All articles