Skip to content
bits
Retrieval without tears · Lesson 5 of 9

Contextual retrieval

Tutor:

Remember the lonely chunk from lesson 2: “Claims must be filed within 30 days of noticing the fault.” It's the right answer to “how long do I have to claim on my e-bike battery?”, but it never mentions batteries, warranties or e-bikes. Both search methods struggle to find it.

Contextual retrieval is Anthropic's fix, and it's simple. Before you index a chunk, ask Claude to write a sentence or two that places the chunk in its document. Glue that context to the front of the chunk, then embed it and add it to the keyword index as usual.

Plain chunk vs Contextual chunkillustrative: made-up numbers that show the idea, not output from a real modelcompare
Plain chunk

Claims must be filed within 30 days of noticing the fault, with the order number and a photo of the battery label.

Contextual chunk

From Orbit Bikes' 2026 warranty guide, in the section on e-bike battery warranty claims. Claims must be filed within 30 days of noticing the fault, with the order number and a photo of the battery label.

Tutor:

Now “battery”, “warranty” and “e-bike” are all in the chunk, for both embeddings and keywords to find.

Tutor:

Does it help? In Anthropic's tests (published September 2024, across code, fiction and papers), the share of questions where the right chunk missed the top 20 fell from 5.7% to 3.7% with contextual embeddings, and to 2.9% with contextual embeddings plus contextual BM25. That's about half the misses gone. A reranker cut it further, to 1.9%; that's next lesson. Those numbers came from Anthropic's data and models of the time, so measure on yours (lesson 8 shows how).

It costs one Claude call per chunk, once, at index time. Prompt caching keeps that cheap: the whole document goes first and is cached, so each chunk's call re-reads it from the cache at a tenth of the input price. (Caching only kicks in above a minimum length, 512 tokens on Haiku 5.5.)

import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
// Write a short context for one chunk, using the whole document.
// Call it for every chunk of a document, one after another: the first
// call writes the document to the cache, the rest read it.
export async function contextualize(doc: string, chunk: string) {
const res = await client.messages.create({
model: "claude-haiku-5-5",
max_tokens: 200,
messages: [{
role: "user",
content: [
{ type: "text", text: `<document>\n${doc}\n</document>`, cache_control: { type: "ephemeral" } },
{ type: "text", text: `Here is one chunk of that document:\n<chunk>\n${chunk}\n</chunk>\nIn one or two sentences, say where this chunk sits in the document and what it's about, so a search can find it. Reply with only those sentences.` },
],
}],
});
const block = res.content.find((b) => b.type === "text");
const context = block?.type === "text" ? block.text.trim() : "";
return `${context}\n\n${chunk}`; // embed and keyword-index this
}
TypeScriptUTF-8● lines 15–16: document first, cached
Tutor:

Keep the original chunk too. When you hand results to Claude later, you can show the context and the chunk separately so it knows which is which.

quick check+10 neurons
Tutor:

Anthropic also tried adding one generic summary of the whole document to every chunk. Why would that help less than a context written for each chunk?

    Type your answer or tap an option · Enter checks

    Tutor:

    Your turn. The document and the lonely chunk are in the box. Write the instruction that makes Claude produce the context: say what it's for (search), keep it short, and ask for only the context, with no preamble. Run it a few times and check that the batteries and warranty make it in.

    Your turn

    Run your prompt and the replies land here.

      • Includes the document and chunk, not yet
      • Asks for context, not yet
      • Says it's for search, not yet
      • Keeps it short, not yet
      • Asks for only the context, not yet
      • Ran at 1.0, not yet
      run at
      ~0 tokens

      Turn on JavaScript to run prompts.