Context window : De 2K à 2M tokens - l'évolution de la mémoire des LLMs
Imaginez discuter avec quelqu’un qui ne se souvient que des 10 dernières secondes de conversation. Frustrant, n’est-ce pas ?
C’est exactement le défi des premiers LLMs : GPT-2 (2019) ne “voyait” que ~1 000 tokens (750 mots), soit 1-2 pages de texte. Impossible d’analyser un document long, de maintenir une conversation étendue, ou de comprendre un contexte riche.
Aujourd’hui, Gemini 1.5 traite jusqu’à 2 millions de tokens : l’équivalent de 4 romans ou 8 heures de vidéo. Cette évolution révolutionne les cas d’usage.

Pourquoi c’est crucial
Impact direct sur les capacités :
- Documents longs : Analyser rapport de 200 pages sans découper
- Conversations : Historique complet de session multi-tours
- Code : Comprendre codebase entière (10K+ lignes)
- Multi-sources : Combiner plusieurs documents simultanément
- Cohérence : Réponses contextuellement riches
Exemple concret :
Avec 4K context :
Prompt : Lis ce PDF de 50 pages et résume-le
Résultat : ❌ "Le document est trop long, veuillez le découper"
Avec 200K context :
Prompt : Lis ce PDF de 50 pages et résume-le
Résultat : ✅ "Voici le résumé en 5 points clés : 1) ..."
Comprendre les tokens et la mémoire
Rappel : Qu’est-ce qu’un token ?
Un token est l’unité de traitement d’un LLM. Pas exactement un mot, mais un fragment de texte.
En français :
- 1 token ≈ 0.75 mot en moyenne
- “Bonjour le monde” = 3-4 tokens
- “L’intelligence artificielle” = 3-5 tokens
Calcul pratique :
100 tokens ≈ 75 mots ≈ 3-4 phrases
1 000 tokens ≈ 750 mots ≈ 1 page A4
4 000 tokens ≈ 3 000 mots ≈ 5-6 pages
100 000 tokens ≈ 75 000 mots ≈ 150 pages = petit roman
En savoir plus sur les tokens →
Context window = Mémoire de travail
Le context window fonctionne comme la mémoire RAM d’un ordinateur :
Mémoire RAM (ordinateur) :
- Stocke programmes/données actifs
- Limite : 8GB, 16GB, 32GB…
- Si dépassé : Swap sur disque (lent)
Context window (LLM) :
- Stocke prompt + historique + génération en cours
- Limite : 4K, 128K, 2M tokens…
- Si dépassé : ❌ Erreur ou troncature
# Exemple : Calculer tokens
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-3.1-8B")
text = """
Ceci est un exemple de texte assez long pour illustrer
le comptage de tokens. Plus le texte est long, plus
il consomme de tokens dans la fenêtre de contexte.
"""
tokens = tokenizer.encode(text)
print(f"Nombre de tokens : {len(tokens)}")
# Output : Nombre de tokens : 45
# Vérifier si ça rentre dans le context
max_context = 8192 # Llama 3.1 : 8K context
if len(tokens) < max_context:
print("✅ Rentre dans le context")
else:
print("❌ Trop long, sera tronqué")
Composition du context
Context window = Input + Output :
[System prompt] + [User messages] + [Assistant responses] + [New generation]
100 tokens 500 tokens 300 tokens ? tokens
|_______________________________________________________________________|
Total : < Max context window
Exemple avec 4K context :
- System prompt : 100 tokens
- Historique conversation : 2 000 tokens
- Nouveau message user : 500 tokens
- Reste pour génération : 4 096 - 2 600 = 1 496 tokens (~1 100 mots)
Si la réponse nécessite plus, elle sera tronquée.
L’évolution des context windows
Timeline historique
Évolution spectaculaire en 5 ans :
| Année | Modèle | Context | Capacité |
|---|---|---|---|
| 2019 | GPT-2 | 1K | ~750 mots (1 page) |
| 2020 | GPT-3 | 2K-4K | ~3 000 mots (5 pages) |
| 2021 | GPT-3 Davinci | 4K | ~3 000 mots |
| 2022 | GPT-3.5 | 4K | Standard |
| 2022 | GPT-3.5-16K | 16K | ~12 000 mots (25 pages) |
| 2023 | GPT-4 | 8K | Standard |
| 2023 | GPT-4-32K | 32K | ~24 000 mots (50 pages) |
| 2023 | Claude 2 | 100K | ~75 000 mots (150 pages) |
| 2023 | GPT-4 Turbo | 128K | ~96 000 mots (200 pages) |
| 2024 | Claude 3 | 200K | ~150 000 mots (300 pages) |
| 2024 | Gemini 1.5 Pro | 1M-2M | ~1,5M mots (3 000 pages = 4 romans) |
Croissance exponentielle : x1000 en 5 ans (1K → 1M).
Modèles actuels (2025)
Production-ready :
| Modèle | Context | Prix input | Use case optimal |
|---|---|---|---|
| GPT-4o | 128K | $2.50/M | Général, multimodal |
| GPT-4 Turbo | 128K | $10/M | Qualité maximale |
| Claude 3.5 Sonnet | 200K | $3/M | Documents techniques |
| Claude 3 Opus | 200K | $15/M | Analyse approfondie |
| Gemini 1.5 Pro | 2M | $1.25/M | Contexte massif |
| Gemini 1.5 Flash | 1M | $0.075/M | Rapide, économique |
| Mistral Large | 128K | Variable | Sliding window |
| Llama 3.1 (local) | 128K | Gratuit | Self-hosted |
Pourquoi c’est important ?
Analyser documents longs
Cas d’usage : Résumer un livre entier, analyser rapport annuel, comprendre spécification technique.
Sans long context (4K) :
# Devoir découper le document
chunks = split_document(book, chunk_size=3000) # Perte de contexte global
summaries = [summarize(chunk) for chunk in chunks]
final_summary = summarize(summaries) # Approximation
Avec long context (200K+) :
# Traiter d'un coup
full_text = read_book() # 100K tokens
summary = llm.complete(f"Résume ce livre :\n\n{full_text}")
# ✅ Comprend l'œuvre dans sa globalité
Exemple concret :
from anthropic import Anthropic
client = Anthropic(api_key="your-api-key")
# Charger livre complet (ex: 150K tokens)
with open("Les_Miserables.txt") as f:
book_content = f.read()
message = client.messages.create(
model="claude-3-5-sonnet-20241022", # 200K context
max_tokens=2000,
messages=[{
"role": "user",
"content": f"""Analyse ce roman complet :
{book_content}
Réponds :
1. Thèmes principaux
2. Évolution des personnages
3. Symbolisme récurrent
4. Structure narrative
5. Conclusion de l'auteur"""
}]
)
print(message.content[0].text)
Conversations étendues
Chat avec historique complet :
# Conversation de 50 tours (10K tokens d'historique)
conversation_history = [
{"role": "user", "content": "Parle-moi de la Révolution française"},
{"role": "assistant", "content": "La Révolution française (1789-1799)..."},
# ... 48 tours supplémentaires ...
{"role": "user", "content": "Reviens sur ce que tu as dit au début sur les causes économiques"}
]
# Avec 4K context : ❌ Historique tronqué, perd le début
# Avec 128K context : ✅ Se souvient de tout
Avantage : Cohérence totale, peut référencer n’importe quel élément passé.
Analyse de code
Comprendre codebase entière :
import os
from pathlib import Path
def load_codebase(root_dir, extensions=[".py", ".js", ".ts"]):
"""Charger tous les fichiers de code"""
files_content = []
for path in Path(root_dir).rglob("*"):
if path.suffix in extensions:
with open(path) as f:
files_content.append(f"# File: {path}\n{f.read()}\n\n")
return "".join(files_content)
# Charger projet complet
codebase = load_codebase("./my_project") # Ex: 80K tokens
# Analyse avec Gemini 1.5 (1M context)
import google.generativeai as genai
genai.configure(api_key="your-api-key")
model = genai.GenerativeModel("gemini-1.5-pro")
response = model.generate_content(f"""Analyse ce codebase :
{codebase}
Tâches :
1. Architecture générale
2. Identifier patterns et anti-patterns
3. Dépendances entre modules
4. Suggestions d'amélioration
5. Bugs potentiels""")
print(response.text)
Résultat : Comprend la structure globale, pas juste des fichiers isolés.
Multi-documents
Combiner plusieurs sources :
# Charger 5 articles scientifiques (total 120K tokens)
papers = [
load_pdf("paper1.pdf"), # 25K tokens
load_pdf("paper2.pdf"), # 30K tokens
load_pdf("paper3.pdf"), # 28K tokens
load_pdf("paper4.pdf"), # 20K tokens
load_pdf("paper5.pdf") # 17K tokens
]
combined = "\n\n---\n\n".join([f"Paper {i+1}:\n{p}" for i, p in enumerate(papers)])
# Analyse comparative
prompt = f"""Voici 5 papers sur l'attention dans les Transformers :
{combined}
Compare leurs approches :
1. Points communs
2. Différences méthodologiques
3. Résultats contradictoires
4. Synthèse des meilleures pratiques"""
response = client.chat.completions.create(
model="gpt-4-turbo", # 128K context
messages=[{"role": "user", "content": prompt}]
)
Impossible avec 4K context : Devrait résumer chaque paper séparément, perdre nuances.
Traduction cohérente
Documents longs avec terminologie spécifique :
# Traduire livre technique (100 pages, 75K tokens)
book_en = load_document("technical_manual_EN.pdf")
translation = client.messages.create(
model="claude-3-opus-20240229", # 200K context
messages=[{
"role": "user",
"content": f"""Traduis ce manuel technique en français :
{book_en}
Consignes :
- Cohérence terminologique (glossaire unifié)
- Préserver numérotation et structure
- Adapter idiomes culturellement"""
}],
max_tokens=100000
)
# ✅ Terminologie cohérente sur tout le document
# ❌ Avec petit context : Termes techniques traduits différemment selon les chunks
Les défis techniques du long context
Attention quadratique : O(n²)
Le problème fondamental :
Le mécanisme d’attention (cœur des Transformers) a une complexité quadratique : chaque token doit “regarder” tous les autres tokens.
Calcul :
Coût attention = n × n = n²
Où n = nombre de tokens
Impact pratique :
| Context | Opérations attention | Temps relatif | Mémoire |
|---|---|---|---|
| 1K | 1M | 1x | 1x |
| 4K | 16M | 16x | 16x |
| 16K | 256M | 256x | 256x |
| 128K | 16.4B | 16 384x | 16 384x |
| 1M | 1T | 1 000 000x | 1 000 000x |
Conséquence : Sans optimisations, 1M context serait 1 million de fois plus lent que 1K.
# Pseudo-code attention naïve
def attention(Q, K, V):
# Q, K, V : (batch, seq_len, dim)
scores = Q @ K.T # (seq_len × seq_len) ← QUADRATIQUE
# Ex: 100K tokens → 10 milliards d'opérations
weights = softmax(scores)
output = weights @ V
return output
Mémoire GPU explosive
Besoin mémoire :
Mémoire attention ≈ batch_size × num_heads × seq_len² × 2 bytes (FP16)
Exemple : GPT-4 (hypothétique 128K context)
Mémoire = 1 × 96 × (128K)² × 2 bytes
= 1 × 96 × 16.4B × 2
= 3.1 TB (!!)
Impossible sur GPU (A100 = 80 GB VRAM).
Solution : Techniques avancées (Flash Attention, gradient checkpointing).
Lost in the middle
Phénomène observé : Les LLMs ont tendance à mieux “voir” le début et la fin du context, mais oublient le milieu.
Étude (Liu et al., 2023) :
Placer information clé à différentes positions dans 32K context :
Position 0-10% (début) : 95% recall
Position 40-60% (milieu) : 65% recall ← PROBLÈME
Position 90-100% (fin) : 90% recall
Impact : Si l’info critique est noyée au milieu d’un long document, le modèle peut la manquer.
# Illustration du problème
long_context = f"""
{'Texte de remplissage ' * 5000} # 10K tokens de bruit
INFORMATION CRUCIALE : Le code secret est XYZ-789.
{'Texte de remplissage ' * 5000} # 10K tokens de bruit
Question : Quel est le code secret ?
"""
# Résultat fréquent : "Je ne trouve pas cette information"
# Même si elle est techniquement dans le context !
Mitigation :
- Placer infos importantes en début/fin
- Utiliser RAG pour sélectionner chunks pertinents
- Modèles récents (Gemini 1.5) améliorent ce problème
Coûts proportionnels
Prix API augmente avec context utilisé :
# Comparaison coûts (GPT-4 Turbo : $10/M tokens input)
# Requête 1K tokens
cost_1k = 1000 / 1_000_000 * 10 = $0.01
# Requête 100K tokens
cost_100k = 100000 / 1_000_000 * 10 = $1.00 # 100x plus cher
# Requête 1M tokens (Gemini : $1.25/M)
cost_1m = 1000000 / 1_000_000 * 1.25 = $1.25
À grande échelle :
- 1 000 requêtes/jour de 100K tokens = $1 000/jour = $30K/mois
- Optimiser context = économies massives
Techniques d’optimisation
Flash Attention
Innovation majeure (Dao et al., 2022) qui réduit mémoire de O(n²) à O(n).
Principe :
- Calculer attention par blocs (tiles)
- Ne jamais matérialiser la matrice complète en mémoire
- Utiliser SRAM rapide au lieu de HBM lente
Gains :
- ✅ Mémoire : 10-20x réduction
- ✅ Vitesse : 2-4x plus rapide
- ✅ Context : Permet 128K+ sur GPU standard
# Flash Attention intégré nativement dans transformers récents
from transformers import AutoModelForCausalLM
import torch
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-3.1-8B",
torch_dtype=torch.bfloat16,
attn_implementation="flash_attention_2", # ← Flash Attention
device_map="auto"
)
# Context 128K possible sur RTX 4090 grâce à Flash Attention
Flash Attention 2 (2023) : Encore plus optimisé, standard actuel.
Sparse Attention
Idée : Chaque token ne regarde pas tous les autres, seulement un sous-ensemble.
Patterns :
- Local : Regarder seulement fenêtre proche (ex: ±512 tokens)
- Stride : Regarder tous les N tokens (ex: 1, 5, 10, 15…)
- Global : Certains tokens “hub” regardent tout
# Exemple : Longformer (local + global attention)
from transformers import LongformerModel
model = LongformerModel.from_pretrained("allenai/longformer-base-4096")
# Context 4K avec coût linéaire O(n) au lieu de O(n²)
Limite : Peut perdre dépendances long-range importantes.
Ring Attention
Technique pour distribuer long context sur plusieurs GPUs.
Principe :
- Découper séquence en segments
- Chaque GPU traite un segment
- Communication en “ring” entre GPUs
- Agréger résultats
Résultat : Context quasi-illimité (plusieurs millions de tokens).
# Pseudo-code Ring Attention
def ring_attention(tokens, num_gpus=8):
# Découper séquence
segments = split(tokens, num_gpus)
# Distribuer sur GPUs
for gpu_id in range(num_gpus):
gpu_outputs[gpu_id] = process_segment(
segments[gpu_id],
previous_gpu_context=gpu_outputs[gpu_id - 1]
)
# Agréger
return concatenate(gpu_outputs)
Usage : Recherche (ex: analyser dataset entier en un pass).
Sliding Window (Mistral)
Approche de Mistral : Attention locale glissante.
Fonctionnement :
- Chaque couche regarde seulement fenêtre de 4K tokens
- Mais empilage de couches → portée effective 128K+
- Coût computationnel fixe (linéaire)
Couche 1 : Regarde [token-2K, token+2K]
Couche 2 : Regarde [token-2K, token+2K] des embeddings de couche 1
...
Couche 32 : Portée effective ~100K tokens
Avantage : Vitesse constante quelle que soit longueur context.
# Mistral Large avec 128K context
from mistralai.client import MistralClient
client = MistralClient(api_key="your-api-key")
# Traite 128K tokens avec coût linéaire
response = client.chat(
model="mistral-large-latest",
messages=[{"role": "user", "content": very_long_document}]
)
RoPE Scaling
RoPE (Rotary Position Embedding) : Encodage positionnel des Transformers modernes.
Problème : Entraîné sur 4K, performance dégrade au-delà.
Solution : Scaling :
# Étendre RoPE sans réentraînement
rope_scaling = {
"type": "linear", # ou "dynamic"
"factor": 8.0 # 4K × 8 = 32K context
}
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b",
rope_scaling=rope_scaling, # ← Étend context
torch_dtype=torch.bfloat16
)
# Context effectif : 32K au lieu de 4K
Types :
- Linear : Simple multiplication
- Dynamic : Adaptatif selon longueur réelle
- YaRN : Yet another RoPE extensioN (state-of-art)
Modèles à long contexte en détail
Gemini 1.5 Pro (2M tokens)
Champion absolu du long context.
Capacités :
- 2 millions de tokens = 1,5M mots = 3 000 pages
- Multimodal : Texte + Image + Audio + Vidéo
- Analyse 11h d’audio ou 1h de vidéo en une fois
Cas d’usage uniques :
import google.generativeai as genai
genai.configure(api_key="your-api-key")
# Analyser film complet (1h30 = ~500K tokens audio/video)
video_file = genai.upload_file("movie.mp4")
model = genai.GenerativeModel("gemini-1.5-pro")
response = model.generate_content([
video_file,
"""Analyse ce film :
1. Résumé par acte
2. Évolution des personnages
3. Symbolisme visuel
4. Thèmes principaux
5. Critique constructive
Inclus timestamps pour moments clés."""
])
print(response.text)
Prix : $1.25/M tokens (très compétitif pour 2M context).
Claude 3 (200K tokens)
Points forts :
- Précision : Moins de “lost in the middle” que concurrents
- Documents techniques : Excellent sur code, research papers
- Cohérence : Qualité constante même avec context plein
Benchmark “Needle in a Haystack” :
Test : Cacher information dans 200K tokens, demander de la retrouver
Claude 3 Opus : 95% recall à n'importe quelle position
GPT-4 Turbo : 87% recall (baisse au milieu)
Gemini 1.5 : 92% recall
Exemple usage :
from anthropic import Anthropic
client = Anthropic(api_key="your-api-key")
# 10 articles scientifiques (total 180K tokens)
papers = load_multiple_pdfs(["paper1.pdf", ..., "paper10.pdf"])
message = client.messages.create(
model="claude-3-opus-20240229",
max_tokens=4000,
messages=[{
"role": "user",
"content": f"""Voici 10 papers sur l'IA en médecine :
{papers}
Méta-analyse :
1. Consensus scientifique
2. Méthodologies dominantes
3. Lacunes de recherche
4. Recommandations futures
5. Tableau comparatif résultats"""
}]
)
GPT-4 Turbo (128K tokens)
Standard industrie pour long context.
Caractéristiques :
- 128K tokens = ~96 000 mots = 200 pages
- Multimodal (texte + image)
- Fonction calling avec long context
Usage :
from openai import OpenAI
client = OpenAI(api_key="your-api-key")
# Analyse codebase (100K tokens)
codebase = load_all_code_files("./project")
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[
{
"role": "system",
"content": "Tu es un expert en revue de code et architecture logicielle."
},
{
"role": "user",
"content": f"""Voici le codebase complet :
{codebase}
Audit complet :
1. Vulnérabilités de sécurité
2. Performance bottlenecks
3. Code smells et refactoring
4. Architecture suggestions
5. Priorité des améliorations"""
}
],
max_tokens=3000
)
print(response.choices[0].message.content)
Quand utiliser long context vs RAG ?
Trade-offs :
| Critère | Long Context | RAG |
|---|---|---|
| Coût | $$$ Proportionnel à taille | $ Fixe (seulement chunks pertinents) |
| Latence | Élevée (traiter tout) | Faible (seulement pertinent) |
| Précision | Contexte global complet | Peut manquer éléments |
| Cohérence | Maximale | Dépend de retrieval |
| Scalabilité | Limitée (max 2M tokens) | Illimitée (millions de docs) |
Utiliser long context quand :
✅ Cohérence globale critique
- Exemple : Analyser roman (comprendre arc narratif complet)
✅ Documents < 200K tokens
- Exemple : Contrat 50 pages, rapport annuel
✅ Relations complexes entre parties
- Exemple : Codebase où tout est interconnecté
✅ Budget flexible
- Coût API acceptable
Utiliser RAG quand :
✅ Base de connaissance massive
- Exemple : 10 000 documents d’entreprise
✅ Coût prioritaire
- Exemple : Application grand public
✅ Mises à jour fréquentes
- Exemple : Documentation produit changeante
✅ Latence critique
- Exemple : Chatbot temps réel
Hybride (meilleur des deux) :
# Approche combinée : RAG + Long Context
def hybrid_qa(question, knowledge_base):
# 1. RAG : Retriever top 10 documents pertinents
relevant_docs = retrieve_top_k(question, knowledge_base, k=10)
# Total : ~80K tokens
# 2. Long Context : Analyser tous ces docs ensemble
combined = "\n\n---\n\n".join(relevant_docs)
response = client.chat.completions.create(
model="gpt-4-turbo", # 128K context
messages=[{
"role": "user",
"content": f"""Contexte (10 documents les plus pertinents) :
{combined}
Question : {question}
Réponds en citant tes sources (numéro du document)."""
}]
)
return response.choices[0].message.content
# Avantages :
# - Coût réduit (seulement 10 docs au lieu de 10K)
# - Contexte riche (10 docs entiers, pas juste chunks)
# - Cohérence (LLM voit relations entre les 10 docs)
L’avenir du context
Context illimité ?
Théoriquement possible avec architectures alternatives :
- Linformer : Attention linéaire O(n)
- Performer : Kernel approximation
- Mamba : State Space Models (pas d’attention)
Défis :
- Coût computationnel reste élevé
- “Lost in the middle” s’aggrave
- Valeur marginale décroissante (au-delà de 1M, gains limités)
Mémoire externe
Concept : Context infini via mémoire externe (comme RAG intégré).
Modèle ↔ [Context Window 128K] ↔ [Mémoire externe 10M tokens]
↓
Retrieval automatique
Avantages :
- Pas de limite pratique
- Coût constant
- Accès sélectif
Recherche : MemGPT, RecurrentGPT.
Compression intelligente
Idée : Compresser context automatiquement.
# Exemple : LongLLMLingua
from llmlingua import PromptCompressor
compressor = PromptCompressor()
# Document 50K tokens
long_doc = load_document("report.pdf") # 50K tokens
# Compresser à 10K tokens (5x)
compressed = compressor.compress_prompt(
long_doc,
target_token=10000,
condition_in_question="Résume les points clés"
)
# Utiliser compressed au lieu de long_doc
# ✅ Coût divisé par 5
# ✅ Latence divisée par 5
# ⚠️ Perte d'information minime (~2%)
Context adaptatif
Future : Modèles ajustant dynamiquement leur context.
- Tâche simple → 4K tokens suffisent
- Tâche complexe → Étendre à 128K automatiquement
- Pay for what you use
Conclusion
Le context window est passé de 1K à 2M tokens en 5 ans : une évolution x2000 qui a transformé les capacités des LLMs.
Points clés :
- Évolution : GPT-2 (1K) → Gemini 1.5 (2M) en 5 ans
- Impact : Analyser livres entiers, codebases complètes, conversations longues
- Défis : Coût O(n²), mémoire, lost in the middle, prix
- Solutions : Flash Attention, RAG, sliding window, RoPE scaling
- Leaders : Gemini 1.5 (2M), Claude 3 (200K), GPT-4 Turbo (128K)
- Trade-off : Long context vs RAG selon cas d’usage
- Futur : Context illimité, compression, mémoire externe
Recommandations :
- <10K tokens : Modèle standard (GPT-4o, Claude Sonnet)
- 10-100K tokens : GPT-4 Turbo, Claude 3, Llama 3.1
- 100K-500K tokens : Claude 3 Opus (précision), Gemini 1.5 Flash (coût)
- 500K-2M tokens : Gemini 1.5 Pro (seule option)
- >2M tokens : RAG obligatoire
Le long context n’est pas toujours la réponse : RAG reste souvent plus efficient. Mais quand la cohérence globale est critique, le long context est irremplaçable.
L’avenir tend vers des systèmes hybrides combinant le meilleur des deux mondes : retrieval intelligent + analyse en long context.
Ressources
Articles liés :
Papers :
- Flash Attention - Dao et al. (2022)
- Lost in the Middle - Liu et al. (2023)
- RoPE Scaling - Press et al. (2022)
- Gemini 1.5 Technical Report - Google (2024)
Outils :
- LongLLMLingua - Compression context
- LangChain - RAG frameworks
- LlamaIndex - Context management
Benchmarks :
- Needle in a Haystack Test
- RULER (Long Context Evaluation)
- LongBench