Cursus
Retrieval-augmented generation (RAG) helpt AI-modellen extra kennis uit externe bronnen te gebruiken. Toch verliezen deze systemen vaak belangrijke context, wat kan leiden tot minder nauwkeurige resultaten.
Anthropic heeft contextuele retrieval ontwikkeld: een eenvoudige maar effectieve manier om informatieopvraging te verbeteren. Door voor elk fragment de juiste context te behouden, nemen retrievalfouten met wel 67% af, wat leidt tot veel betere prestaties in vervolgtaken.
In dit artikel leg ik uit wat contextuele retrieval is en hoe je het in je applicaties kunt gebruiken.
Wat is contextuele retrieval?
Hoewel traditionele RAG-systemen effectief zijn, hebben ze een groot nadeel: ze splitsen documenten vaak in kleine fragmenten om het ophalen te vergemakkelijken, maar daardoor kan belangrijke context verdwijnen.
Zo kan een fragment bijvoorbeeld zeggen “Meer dan 3,85 miljoen inwoners maken het de meest bevolkte stad van de Europese Unie” zonder te vermelden over welke stad of welk land het gaat. Dit gebrek aan context kan leiden tot onvolledige of irrelevante resultaten, zeker wanneer specifieke details nodig zijn.

Bron: Introducing Contextual Retrieval
Contextuele retrieval lost dit op door vóór het embedden een korte, contexts-specifieke uitleg bij elk fragment te genereren en toe te voegen. In het bovenstaande voorbeeld wordt het fragment als volgt omgevormd:
contextualized_chunk = """Berlin is the capital and largest city of Germany, known for being the EU's most populous city within its limits.
Its more than 3.85 million inhabitants make it the European Union's most populous city, as measured by population within city limits.
"""

Bron: Introducing Contextual Retrieval
Over het geheel genomen laten interne tests van Anthropic in verschillende domeinen, waaronder codebases, wetenschappelijke artikelen en fictie, zien dat contextuele retrieval retrievalfouten met 49% vermindert wanneer het wordt gebruikt met contextuele embeddingmodellen en Contextual BM25.

Bron: Introducing Contextual Retrieval
Implementatie van contextuele retrieval
Ik leg nu stap voor stap uit hoe je contextuele retrieval implementeert. We gebruiken het volgende voorbeelddocument als leidraad:
# Input text for the knowledge base
input_text = """Berlin is the capital and largest city of Germany, both by area and by population.
Its more than 3.85 million inhabitants make it the European Union's most populous city, as measured by population within city limits.
The city is also one of the states of Germany and is the third smallest state in the country in terms of area.
Paris is the capital and most populous city of France.
It is situated along the Seine River in the north-central part of the country.
The city has a population of over 2.1 million residents within its administrative limits, making it one of Europe's major population centers."""
Stap 1: Verdeel het document in fragmenten
De eerste stap is het voorbeelddocument op te delen in kleinere, zelfstandige fragmenten. In dit geval splitsen we het op in losse zinnen.
# Splitting the input text into smaller chunks
test_chunks = [
'Berlin is the capital and largest city of Germany, both by area and by population.',
"\\n\\nIts more than 3.85 million inhabitants make it the European Union's most populous city, as measured by population within city limits.",
'\\n\\nThe city is also one of the states of Germany and is the third smallest state in the country in terms of area.',
'\\n\\n# Paris is the capital and most populous city of France.',
'\\n\\n# It is situated along the Seine River in the north-central part of the country.',
"\\n\\n# The city has a population of over 2.1 million residents within its administrative limits, making it one of Europe's major population centers."
]
Stap 2: Definieer de prompttemplate
Vervolgens zetten we de prompt op die ons model gebruikt om context voor elk fragment te genereren. Anthropic heeft hiervoor een handige template gedeeld. De prompt neemt twee inputs: het volledige document en het specifieke tekstfragment dat we willen situeren.
from langchain.prompts import ChatPromptTemplate, PromptTemplate, HumanMessagePromptTemplate
# Define the prompt for generating contextual information
anthropic_contextual_retrieval_system_prompt = """<document>
{WHOLE_DOCUMENT}
</document>
Here is the chunk we want to situate within the whole document
<chunk>
{CHUNK_CONTENT}
</chunk>
Please give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk. Answer only with the succinct context and nothing else."""
# Create a PromptTemplate for WHOLE_DOCUMENT and CHUNK_CONTENT
anthropic_prompt_template = PromptTemplate(
input_variables=['WHOLE_DOCUMENT', 'CHUNK_CONTENT'],
template=anthropic_contextual_retrieval_system_prompt
)
# Wrap the prompt in a HumanMessagePromptTemplate
human_message_prompt = HumanMessagePromptTemplate(prompt=anthropic_prompt_template)
# Create the final ChatPromptTemplate
anthropic_contextual_retrieval_final_prompt = ChatPromptTemplate(
input_variables=['WHOLE_DOCUMENT', 'CHUNK_CONTENT'],
messages=[human_message_prompt]
)
Stap 3: Initialiseer je favoriete taalmodel
Hier kun je elk gewenst LLM kiezen om context voor elk fragment te genereren. In ons voorbeeld gebruiken we OpenAI’s GPT-4o-model.
import os
from langchain_openai import ChatOpenAI
# Load environment variables
os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_API_KEY"
# Initialize the model instance
llm_model_instance = ChatOpenAI(
model="gpt-4o",
)
Stap 4: Alles samenbrengen
We koppelen de prompttemplate aan het taalmodel om een LLM-keten te maken die klaar is om de eerder gemaakte fragmenten te verwerken.
from langchain.output_parsers import StrOutputParser
# Chain the prompt with the model instance
contextual_chunk_creation = anthropic_contextual_retrieval_final_prompt | llm_model_instance | StrOutputParser()
Stap 5: Verwerk elk fragment
We lopen nu door onze fragmenten heen, genereren de contextuele informatie voor elk fragment en printen de resultaten met de contextual_chunk_creation-LLM-keten.
# Process each chunk and generate contextual information
for test_chunk in test_chunks:
res = contextual_chunk_creation.invoke({
"WHOLE_DOCUMENT": input_text,
"CHUNK_CONTENT": test_chunk
})
print(res)
print('-----')
The document compares Berlin and Paris, highlighting Berlin as Germany's capital and largest city by area and population, and noting its significance within the European Union.
-----
Berlin is the capital and largest city of Germany, known for being the EU's most populous city within its limits.
-----
Berlin is the capital and largest city of Germany, both by area and by population.
-----
Paris, the capital of France, is a major population center in Europe with over 2.1 million residents.
-----
Paris is the capital and most populous city of France.
-----
Paris is the capital and most populous city of France, with a population of over 2.1 million residents within its administrative limits.
-----
Verbetering met reranking
Hoewel contextuele retrieval de nauwkeurigheid verbetert, kun je nog een stap verder gaan met reranking. Deze filtertechniek zorgt ervoor dat alleen de meest relevante fragmenten naar het model gaan, wat de antwoordkwaliteit verbetert en kosten en verwerkingstijd verlaagt.
Reranking werkt door de in de eerste stap opgehaalde fragmenten te scoren en alleen de beste te behouden. In onze tests verlaagde reranking de retrievalfouten van 5,7% naar slechts 1,9%, een verbetering van 67% ten opzichte van traditionele methoden.

Bron: Introducing Contextual Retrieval
Aanvullende overwegingen
Uit onderzoek van Anthropic blijkt dat niet elke situatie de complexiteit van contextuele retrieval vereist. Voor kleinere kennisbanken onder 200.000 tokens (ongeveer 500 pagina’s) kan het beter zijn om de volledige kennisbank direct in de prompt van het model op te nemen, zodat een retrievalsysteem helemaal niet nodig is.
Ze raden ook aan gebruik te maken van prompt caching, een functie die is geïntroduceerd voor Claude. Door veelgebruikte prompts tussen API-calls in de cache te bewaren, kunnen ontwikkelaars de kosten tot wel 90% verlagen en de responstijden meer dan verdubbelen. Dit prompt-caching-kookboek biedt stapsgewijze instructies voor de implementatie.
Conclusie
De contextuele retrieval van Anthropic is een eenvoudige maar effectieve methode om retrievalsystemen te verbeteren. Het combineren van contextuele embeddings, BM25 en reranking verhoogt de nauwkeurigheid van deze systemen aanzienlijk.
Wil je meer leren over verschillende retrievaltechnieken? Dan raad ik de volgende blogs aan:
Ryan is lead data scientist en gespecialiseerd in het bouwen van AI-toepassingen met LLM’s. Hij is promovendus in Natural Language Processing en Knowledge Graphs aan Imperial College London, waar hij ook zijn master in Computer Science heeft behaald. Buiten data science om schrijft hij een wekelijkse Substack-nieuwsbrief, The Limitless Playbook, waarin hij één toepasbaar idee van ’s werelds beste denkers deelt en af en toe schrijft over kernconcepten in AI.

