Here is the uncomfortable part. When an AI assistant answers a question and cites a source, no model read your page, not the way a person does, not top to bottom. Your page was pulled apart into passages, each converted into a list of numbers and stored in an index. The question became numbers too, and the system went looking for the closest match.
The unit that competed was never your page. It was a fragment of it, maybe three hundred words long, sitting alone in a database with no title, no navigation, and no memory of the paragraph above it. Teams still write for the page, measure at the page level, and audit at the page level, meanwhile the thing being judged is a passage they never saw in isolation.
This piece walks the whole pipeline, because the shape of the machine determines the shape of the content that wins inside it. Once you can see where passages get cut, where meaning leaks out, and where the ranking actually happens, a lot of vague advice about "writing for AI" collapses into something specific, the mechanical layer beneath how RAG actually works.
01Why does your page get cut up at all?
Feed it one tight paragraph about pricing tiers and the vector strongly encodes pricing tiers. Feed it your entire product page and the vector encodes something like "general B2B software marketing page", with the pricing detail smeared into near-invisibility. That is not a bug, it is the arithmetic of compression: specific numbers, named entities and precise claims lose signal strength relative to the dominant topic of the document. Chunking is the fix, split the document into smaller passages before encoding and each passage gets its own full budget.
Go too far the other way and you break the thing that made the text useful. Chop a document into hyper-granular fragments and you destroy the macro narrative, leaving isolated statements stripped of the detail that gave them meaning. Every retrieval system sits somewhere on this trade-off, and where it sits determines what it can find. Most production systems land between 200 and 800 tokens per chunk, roughly 150 to 600 words.
02What are the four ways your page gets cut?
| Strategy | How it cuts | What it buys | What it breaks |
|---|---|---|---|
| Fixed-size sliding window | Static token count with a fixed stride overlap. | Almost no compute cost; predictable memory. | Bisects named entities, formulas and logical propositions. |
| Sentence / paragraph | Punctuation and newline delimiters. | Preserves local syntax and clause structure. | Variable lengths create unstable embedding density. |
| Semantic distance | Cuts where cosine similarity drops between adjacent sentences. | Boundaries land on genuine topic shifts. | High ingestion latency, a forward pass per sentence. |
| Structural headers | Markdown headers and HTML DOM nodes. | Preserves the organisation you actually intended. | Collapses on inconsistent or malformed markup. |
You cannot control which algorithm indexes you, and different assistants use different ones. What you can control is making your content survive all four: real heading tags, semantically complete sections, and topic shifts that align with structural breaks give every parser the same answer, which is also why clean internal structure decides retrieval.
03What is context rupture, and why does good content fail?
Chunk A: "ACME Corporation expanded its robotics division in Q3."
Chunk B: "The division achieved a 14% revenue increase over the prior fiscal year."
Chunk B has the answer, the number, the growth rate. And it will not be retrieved. Nothing in it says ACME, robotics, or Q3. Embedded on its own, its vector is positioned entirely on its isolated text, so the query "ACME Corporation Q3 financial performance" lands somewhere else and Chunk B falls outside the nearest-neighbour radius. The fact exists, it is correctly indexed, and it cannot be found.
Now audit your own writing: pronouns carrying the subject across paragraphs, section three referring to "this approach" from section two, a case study where the client name appears once in the intro and never again, comparison tables where product names live in the header row and the rows say "it" and "the platform". All of that is fine for a human reader. All of it produces orphaned chunks, the same failure that makes AI misdescribe a brand it can't cleanly resolve.
04How do retrieval systems patch the problem?
Fix one: generative contextual augmentation
Before embedding a chunk, send it to a language model with the full parent document and ask for a short prefix explaining what the chunk is about, then glue that prefix on and index the combined text. A chunk reading "Operating margins expanded by 240 basis points" becomes "This chunk is from the Q2 2023 financial statement for ACME Corporation... Operating margins expanded by 240 basis points". The rewritten passage resolves the pronouns, names the entity, anchors the timeframe, and the explicit terms become searchable in the keyword index too. This is Anthropic's contextual retrieval.
<document>
{{WHOLE_DOCUMENT_TEXT}}
</document>
<chunk>
{{TARGET_CHUNK_TEXT}}
</chunk>
Please give a succinct context (50-100 tokens) to situate this
chunk within the overall document, to improve search retrieval.
Answer only with the contextual prefix and nothing else.The measured gains are not marginal. On standard evaluation sets, contextual prefixes on dense embeddings cut top-20 retrieval failure by 35% against a naive pipeline; pair them with contextual keyword search and failures drop 49%; add a reranking stage and the reduction reaches 67%. The whole funnel runs once per sub-query produced by query fan-out.
Read those numbers as a diagnosis, not a benchmark: two thirds of retrieval failures in a naive system are caused by problems that have nothing to do with content quality, context loss, vocabulary mismatch, and bad ranking. All three have content-side counterparts. And it is cheap: key-value prompt caching gives cache reads a ~90% token discount, so ingestion lands near $1 per million document tokens, which means you should assume the systems reading your content already do this and are already compensating for some of your ambiguity. Some, not all.
Fix two: late chunking
The more elegant approach reverses the order of operations. Traditional pipelines split first and encode second, so attention only ever sees one isolated chunk. Late chunking feeds the entire document through a long-context encoder in one pass, so every token vector already encodes global context, and only then applies chunk boundaries, pooling across the token slice. It preserves cross-chunk dependencies and document-level context without changing the vector's dimensions, and adds no query-time cost.
| Axis | Generative contextualisation | Late chunking |
|---|---|---|
| Depends on | An external LLM API or local generative model. | A long-context transformer embedder (8k+ tokens). |
| Ingestion speed | Slower, bound by token generation. | Fast, one encoder pass per document. |
| Effect on keyword search | Large, adds real searchable words to the sparse index. | None, the underlying text is untouched. |
| How context is stored | Explicitly, as text prepended to the passage. | Implicitly, inside the attention layers. |
| Operational complexity | Higher, needs caching, orchestration, retries. | Lower, needs slice-based pooling support. |
Late chunking recovers context that exists in your document. It cannot invent context that was never written down. If your page never states the entity, the timeframe, or the qualifier anywhere in the surrounding text, no amount of attention across the document will surface it. Explicit beats implicit, every time.
05What happens inside the vector space?
# What dense retrieval actually computes, stripped to essentials
import numpy as np
def cosine(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
query = embed("how long does onboarding take")
chunks = [embed(c) for c in page_chunks]
scores = [cosine(query, c) for c in chunks]
ranking = np.argsort(scores)[::-1]
# Only the top handful ever reach the model.
top_k = [page_chunks[i] for i in ranking[:5]]Two refinements matter for content. Matryoshka embeddings nest meaning hierarchically, coarse topic in the leading dimensions, fine detail later, which enables a cheap first pass on a 64-dimensional prefix before rescoring the shortlist on full vectors. The blunt consequence: the first filter your chunk faces is deliberately coarse, judging on broad topical signal alone, so passages whose topic is unmistakable in the opening lines pass it. And multi-vector models like ColBERT keep token-level vectors and score with MaxSim, which rewards passages containing the literal terminology of the question, not just its general vibe. The exact words still matter.
06What funnel does your chunk have to survive?
Dense vectors are excellent at intent and synonyms and weak at exact lookups (part numbers, SKUs, proper nouns), so BM25 keyword search runs alongside. BM25's term-frequency component saturates, so the tenth mention of a keyword adds almost nothing and dilutes your passage on the vector side, there is no version of this system where stuffing works. The two score scales are incompatible, so Reciprocal Rank Fusion throws away raw scores and operates on rank positions, commonly weighting dense 80% and keyword 20%. The passage that wins is rarely the best on either axis, it is the one that is good on both.
# Reciprocal Rank Fusion, the whole idea in a few lines
K = 60
def rrf(rankings, weights=None):
scores = {}
for i, ranked_ids in enumerate(rankings):
w = (weights or [1] * len(rankings))[i]
for rank, doc_id in enumerate(ranked_ids, start=1):
scores[doc_id] = scores.get(doc_id, 0) + w / (K + rank)
return sorted(scores, key=scores.get, reverse=True)
# Dense search carries more weight than keyword search
final = rrf([dense_results, bm25_results], weights=[0.8, 0.2])The reranker is where most outcomes are decided. Dense retrieval uses a bi-encoder that embeds query and passage separately (what makes pre-indexing possible); a cross-encoder runs both through one transformer together, letting every query word attend to every passage word. Far more accurate, far too expensive to run over the whole index, so it runs as a second pass over 100 to 150 candidates and narrows them to the 5 to 20 that build the final context.
07What are the three failure modes, and their fixes?
| Failure mode | What happens | Your content-side fix |
|---|---|---|
| Semantic fragmentation | Chunking split related facts across passages; no single vector matches. | Write sections that are semantically complete, every section names its own subject. |
| Lexical mismatch | Dense search misses exact constraints, part numbers, identifiers, versions. | Vocabulary discipline, use the literal category, competitor and version terms buyers type. |
| Ranking degradation | The right chunk is retrieved but sits too low to make the window. | Directness, answer the query head-on, early, in language that mirrors the question. |
Clever renaming of a known category is a lexical mismatch you are inflicting on yourself. And cross-encoders reward passages that answer the query head-on: a passage that opens with three sentences of throat-clearing loses to one that opens with the answer, the same shape as any high-citation page.
08How do you write content that survives the cut?
| Check | What good looks like | Failure it prevents |
|---|---|---|
| Section independence | Every H2 makes full sense read alone, with no prior paragraph. | Semantic fragmentation |
| Entity naming | The subject is named by name at least once inside every section. | Vector drift |
| Temporal anchors | Dates and periods stated explicitly, never "last year". | Vector drift |
| Answer position | The core claim appears in the first two sentences of the section. | Ranking degradation |
| Vocabulary match | Uses the literal category and product terms buyers type. | Lexical mismatch |
| Markup integrity | Real H2 and H3 tags in a clean, consistent hierarchy. | Bad boundary placement |
| Table framing | A summary line above each table; subjects repeated in row labels. | Structural fragmentation |
| Specificity | Concrete numbers and named entities, not general characterisation. | Compression loss |
Front-loading the answer helps at three separate stages at once, coarse first-pass filtering, cross-encoder scoring, and the moment a model decides which passage to quote, which is exactly what the answer-block optimizer checks. Naming the subject in every section directly reduces fragmentation, the highest-leverage change a content team can make, and it is the same explicitness that makes you resolvable as an entity.
None of this replaces authority. Retrieval mechanics determine whether your passage can be found; corroboration across independent sources, consistent entity naming, and genuine subject depth determine whether it gets trusted once it is. Mechanics get you into the candidate pool. Authority is what survives the reranker.
09How do you tell whether any of this is working?
| Metric | What it measures | What a low score is telling you |
|---|---|---|
| Context precision | Signal-to-noise and ranking quality. | Ranking is weak, relevant passages exist but sit too low. |
| Context recall | Completeness of retrieved information. | The candidate window is too narrow, or facts are fragmented. |
| Context entity recall | Coverage of named entities. | Vocabulary and entity-naming gaps between query and corpus. |
| Faithfulness | Whether generated claims are grounded in context. | The generator is hallucinating past what was retrieved. |
| Answer relevancy | Whether the output addresses the actual question. | Instruction-following failure downstream of retrieval. |
You will not run RAGAS on someone else's index, but a manual equivalent is genuinely useful: build 30 to 50 questions your buyers actually ask in their words; run each through the assistants that matter and record whether you appear and which passage got quoted; for the misses, read the passage on your site that should have answered it in isolation, with no title and no surrounding text. In most cases the reason is visible in ten seconds, the passage does not name its subject, does not state its qualifier, or buries the answer four sentences deep. Fix the passage, not the page, then re-run the same question set in four to six weeks. Different assistants weight these stages differently, which is part of why engines recommend different vendors.
Three browser-based tools built from this teardown: the Chunk Retrievability Analyzer to find your orphaned passages, the Retrieval-Readiness Checklist to score a page against the eight-point test, and the RRF Rank-Fusion Calculator to see how dense and keyword rankings merge. All free, all run in your browser.
10What's the takeaway?
That is not a hack, and it will not stop working when the architectures change. It is simply what it looks like to write for a reader who arrives in the middle, with no context, and only a few seconds of attention to spend, which, as it turns out, describes most human readers too.
Do AI search engines read my whole page?
No. Before an AI engine can cite you, your page is split into passages (typically 150-600 words, 200-800 tokens), each converted into a fixed-length vector and stored in an index. When someone asks a question, that question is vectorised too and the system retrieves the closest-matching passages, not pages. The unit that competes for a citation is a single chunk, scored alone with no title, no navigation and no memory of the paragraph above it, so writing and auditing at the page level misses where the contest actually happens.
Why does my best content sometimes get zero AI visibility?
Usually context rupture. Standard pipelines embed each chunk in isolation, so a passage that carries its meaning through pronouns or references to earlier paragraphs, "the division", "this approach", "last year", loses its subject when cut. Its vector lands away from the query's vector and it falls outside the nearest-neighbour search radius, so the fact is correctly indexed but cannot be found. The fix is to name the subject, state the timeframe, and repeat the qualifier inside every section.
What is contextual retrieval and late chunking?
Two engineering fixes for context rupture. Contextual retrieval (Anthropic) uses an LLM to write a short prefix naming a chunk's subject and timeframe before indexing it, cutting top-20 retrieval failures by 35%, rising to 67% when combined with keyword search and reranking. Late chunking (Jina AI) runs the whole document through a long-context encoder first so every token vector carries global context, then slices, preserving cross-chunk meaning at no query-time cost. Both recover context that was written down, neither can invent context you never stated.
How do I write content that gets retrieved and cited?
Write every H2 section so it makes sense read alone: name the subject by name at least once, state dates explicitly, put the core claim in the first two sentences, use the literal terms buyers type (category, competitor and version names), keep real H2/H3 markup, add a summary line above every table, and prefer concrete numbers over general characterisation. These reduce the three failure modes, semantic fragmentation, lexical mismatch and ranking degradation, without writing worse for humans.
The research and engineering sources this teardown draws on.
- Contextual Retrieval in AI Systems. Anthropic.
- jina-ai/late-chunking: code for explaining and evaluating late chunking. GitHub.
- Late Chunking in Long-Context Embedding Models. Jina AI.
- A Step-by-Step RAG Evaluation Process & Key Metrics Explained. Openxcell.
- RAG Evaluation Metrics: Best Practices. Patronus AI.
- Matryoshka Representation Learning (arXiv:2205.13147). arXiv.
- Late Chunking: Contextual Chunk Embeddings Using Long-Context Embedding Models (PDF). arXiv.
- Enhancing RAG with contextual retrieval. Claude Cookbook.
- Late Chunking: Contextual Chunk Embeddings (v3). arXiv.
- Late Chunking: Contextual Chunk Embeddings (v2). arXiv.
- Chunking Strategies for LLM Applications. Pinecone.
- Contextual Retrieval in Retrieval-Augmented Generation (RAG). Box Blog.
- Implementing Anthropic's Contextual Retrieval with Async Processing. Instructor.
- Late Chunking vs Contextual Retrieval: The Math Behind RAG's Context Problem. KX Systems on Medium.
- Introducing Contextual Retrieval by Anthropic. r/Rag, Reddit.
- Late Chunking in RAG: Improving Text Retrieval Performance. Bluetick Consultants.
- MIPIC: Matryoshka Representation Learning via Self-Distilled Intra-Relational and Progressive Information Chaining. arXiv.
- MaxSim Operator in Dense Retrieval. Emergent Mind.
- Late Chunking: Embedding First, Chunk Later. Stackademic.
- Ragas Evaluation: In-Depth Insights. PIXION Blog.
- RAG Evaluation Simplified, Part 2: Deep Dive into Recall & Precision. Medium.
- Context Recall. Ragas Documentation.
- Metrics. Ragas Documentation.
- Evaluating RAG Applications with RAGAs. Leonie Monigatti.
- Context Precision. Ragas Documentation.
- Contextual retrieval in Anthropic using Amazon Bedrock Knowledge Bases. AWS.
rawmktg. publishes data-driven teardowns and technical playbooks on GEO, retrieval mechanics and B2B AI-search visibility. Method: same data, same lens, every time. Contact: vinayak@rawmktg.com
Sources: Anthropic contextual retrieval, Jina AI late chunking, the Matryoshka Representation Learning and ColBERT papers, Pinecone chunking guidance, and the RAGAS evaluation framework, 2024-26. Code is illustrative; figures are drawn from the cited sources.