Phase 11 - Lesson 05
Ingeniería de Contexto: Ventanas, Presupuestos, Memoria y Recuperación
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
La ingeniería de prompts es un subconjunto. La ingeniería de contexto es todo el juego. Un prompt es una cadena de texto que escribes. El contexto es todo lo que entra en la ventana del modelo: instrucciones del sistema, documentos recuperados, definiciones de herramientas, historial de conversación, ejemplos few-shot y el prompt mismo. Los mejores ingenieros de IA en 2026 son ingenieros de contexto. Ellos deciden qué entra, qué se queda fuera y en qué orden.
Tipo: Build Lenguajes: Python Prerrequisitos: Phase 10 (LLMs from Scratch), Phase 11 Lección 01-02 Tiempo: ~90 minutos Relacionado: Phase 11 · 15 (Prompt Caching) — el diseño amigable con el caché es una extensión de la ingeniería de contexto. Phase 5 · 28 (Long-Context Evaluation) para cómo medir lost-in-the-middle con NIAH/RULER.
Objetivos de Aprendizaje
- Calcular presupuestos de tokens en todos los componentes de la ventana de contexto (prompt del sistema, herramientas, historial, documentos recuperados, margen de generación)
- Implementar estrategias de gestión de ventanas de contexto: truncamiento, resumen y ventana deslizante para el historial de conversación
- Priorizar y ordenar los componentes de contexto para maximizar la atención del modelo en la información más relevante
- Construir un ensamblador de contexto que asigne tokens dinámicamente según el tipo de consulta y el espacio disponible en la ventana
El Problema
Claude Opus 4.7 tiene una ventana de tokens de 200K (1M en beta). GPT-5 tiene 400K. Gemini 3 Pro tiene 2M. Llama 4 promete 10M. Estos números parecen enormes hasta que los llenas.
Aquí hay un desglose real para un asistente de programación. Prompt del sistema: 500 tokens. Definiciones de herramientas para 50 herramientas: 8,000 tokens. Documentación recuperada: 4,000 tokens. Historial de conversación (10 turnos): 6,000 tokens. Consulta actual del usuario: 200 tokens. Presupuesto de generación (salida máxima): 4,000 tokens. Total: 22,700 tokens. Eso es solo el 18% de una ventana de 128K.
Pero la atención no escala linealmente con la longitud del contexto. Un modelo con 128K tokens de contexto paga un costo de atención cuadrático (O(n^2) en transformers estándar, aunque la mayoría de los modelos de producción utilizan variantes de atención eficientes). Más importante aún, la precisión de recuperación se degrada. La prueba "Needle in a Haystack" (Aguja en un Pajar) muestra que los modelos tienen dificultades para encontrar información colocada en medio de contextos largos. La investigación de Liu et al. (2023) demostró que los LLMs recuperan información al principio y al final de contextos largos con una precisión casi perfecta, pero la precisión cae entre un 10% y un 20% para la información colocada en el medio (posiciones 40-70% del contexto). Este efecto "lost-in-the-middle" (perdido en el medio) varía según el modelo, pero afecta a todas las arquitecturas actuales.
La lección práctica: tener 200K tokens disponibles no significa que usar 200K tokens sea efectivo. Un contexto de 10K tokens cuidadosamente seleccionado a menudo supera a un contexto acumulado de 100K tokens. La ingeniería de contexto es la disciplina de maximizar la relación señal-ruido dentro de la ventana de contexto.
Cada token que colocas en la ventana desplaza a un token que podría contener información más relevante. Cada definición de herramienta irrelevante, cada turno de conversación obsoleto, cada fragmento de texto recuperado que no responde a la pregunta -- cada uno de ellos hace que el modelo sea ligeramente peor en la tarea.
El Concepto
La Ventana de Contexto es un Recurso Escaso
Piensa en la ventana de contexto como RAM, no como disco. Es rápida y accesible directamente, pero limitada. No puedes meter todo. Debes elegir.
graph TD
subgraph Window["Ventana de Contexto (128K tokens)"]
direction TB
S["Prompt del Sistema\n~500 tokens"] --> T["Definiciones de Herramientas\n~2K-8K tokens"]
T --> R["Contexto Recuperado\n~2K-10K tokens"]
R --> H["Historial de Conversación\n~2K-20K tokens"]
H --> F["Ejemplos Few-shot\n~1K-3K tokens"]
F --> Q["Consulta del Usuario\n~100-500 tokens"]
Q --> G["Presupuesto de Generación\n~2K-8K tokens"]
end
style S fill:#1a1a2e,stroke:#e94560,color:#fff
style T fill:#1a1a2e,stroke:#0f3460,color:#fff
style R fill:#1a1a2e,stroke:#ffa500,color:#fff
style H fill:#1a1a2e,stroke:#51cf66,color:#fff
style F fill:#1a1a2e,stroke:#9b59b6,color:#fff
style Q fill:#1a1a2e,stroke:#e94560,color:#fff
style G fill:#1a1a2e,stroke:#0f3460,color:#fff
Cada componente compite por espacio. Agregar más definiciones de herramientas significa menos espacio para el historial de conversación. Agregar más contexto recuperado significa menos espacio para ejemplos few-shot. La ingeniería de contexto es el arte de asignar este presupuesto para maximizar el rendimiento de la tarea.
Lost-in-the-Middle
El hallazgo empírico más importante en la ingeniería de contexto. Los modelos atienden mejor a la información al principio y al final del contexto. La información en el medio recibe puntuaciones de atención más bajas y es más probable que sea ignorada.
Liu et al. (2023) probaron esto sistemáticamente. Colocaron un documento relevante entre 20 documentos irrelevantes en varias posiciones y midieron la precisión de las respuestas. Cuando el documento relevante estaba al principio o al final, la precisión era del 85-90%. Cuando estaba en el medio (posición 10 de 20), la precisión cayó al 60-70%.
Esto tiene implicaciones directas en la ingeniería:
- Coloca la información más importante primero (prompt del sistema, instrucciones críticas)
- Coloca la consulta actual y el contexto más relevante al final (el sesgo de recencia ayuda)
- Trata el medio del contexto como la zona de menor prioridad
- Si debes incluir información en el medio, duplica el punto clave al final
graph LR
subgraph Attention["Distribución de Atención en el Contexto"]
direction LR
P1["Posición 0-20%\nALTA atención\n(prompt del sistema)"]
P2["Posición 20-40%\nMODERADA"]
P3["Posición 40-70%\nBAJA atención\n(lost in middle)"]
P4["Posición 70-90%\nMODERADA"]
P5["Posición 90-100%\nALTA atención\n(consulta actual)"]
end
style P1 fill:#51cf66,color:#000
style P2 fill:#ffa500,color:#000
style P3 fill:#ff6b6b,color:#fff
style P4 fill:#ffa500,color:#000
style P5 fill:#51cf66,color:#000
Componentes del Contexto
Prompt del sistema: define el personaje, restricciones y reglas de comportamiento. Va primero y permanece constante a lo largo de los turnos. Claude Code utiliza aproximadamente 6,000 tokens para su prompt del sistema, incluyendo definiciones de herramientas e instrucciones de comportamiento. Manténlo conciso. Cada palabra en el prompt del sistema se repite en cada llamada a la API.
Definiciones de herramientas: cada herramienta agrega 50-200 tokens (nombre, descripción, esquema de parámetros). 50 herramientas a 150 tokens cada una son 7,500 tokens antes de que ocurra cualquier conversación. La selección dinámica de herramientas -- incluyendo solo las herramientas relevantes para la consulta actual -- puede reducir esto entre un 60% y un 80%.
Contexto recuperado: documentos de una base de datos vectorial, resultados de búsqueda, contenido de archivos. La calidad de la recuperación determina directamente la calidad de la respuesta. Una mala recuperación es peor que ninguna recuperación -- llena la ventana con ruido y desvía activamente al modelo.
Historial de conversación: cada mensaje anterior del usuario y respuesta del asistente. Crece linealmente con la longitud de la conversación. Una conversación de 50 turnos a 200 tokens por turno son 10,000 tokens de historial. La mayor parte es irrelevante para la consulta actual.
Ejemplos few-shot: pares de entrada/salida que demuestran el comportamiento deseado. Dos o tres ejemplos bien seleccionados a menudo mejoran la calidad de la salida más que miles de tokens de instrucciones. Pero cuestan espacio.
Presupuesto de generación: los tokens reservados para la respuesta del modelo. Si llenas la ventana a su capacidad máxima, el modelo no tendrá espacio para responder. Reserva al menos 2,000-4,000 tokens para la generación.
Estrategias de Compresión de Contexto
Resumen del historial: en lugar de mantener todos los turnos anteriores de forma literal, resume la conversación periódicamente. "Discutimos X, decidimos Y y el usuario quiere Z" en 100 tokens reemplaza 10 turnos que tomaron 2,000 tokens. Ejecuta el resumen cuando el historial supere un umbral (por ejemplo, 5,000 tokens).
Filtrado de relevancia: califica cada documento recuperado según la consulta actual y descarta los documentos por debajo de un umbral. Si recuperaste 10 fragmentos pero solo 3 son relevantes, descarta los otros 7. Es mejor tener 3 fragmentos muy relevantes que 10 mediocres.
Poda de herramientas: clasifica la intención de la consulta del usuario e incluye solo las herramientas relevantes para esa intención. Una pregunta de código no necesita herramientas de calendario. Una pregunta de programación de citas no necesita herramientas del sistema de archivos. Esto puede reducir las definiciones de herramientas de 8,000 tokens a 1,000.
Resumen recursivo: para documentos muy largos, resume por etapas. Primero resume cada sección, luego resume los resúmenes. Un documento de 50 páginas se convierte en un compendio de 500 tokens que captura los puntos clave.
Sistemas de Memoria
La ingeniería de contexto abarca tres horizontes temporales.
Memoria a corto plazo: la conversación actual. Almacenada directamente en la ventana de contexto. Crece con cada turno. Gestionada por resumen y truncamiento.
Memoria a largo plazo: hechos y preferencias que persisten entre conversaciones. "El usuario prefiere TypeScript." "El proyecto usa PostgreSQL." Almacenada en una base de datos, recuperada al inicio de la sesión. Claude Code almacena esto en archivos CLAUDE.md. ChatGPT lo almacena en su función de memoria.
Memoria episódica: interacciones pasadas específicas que podrían ser relevantes. "El martes pasado, depuramos un problema similar en el módulo de autenticación." Almacenada como embeddings, recuperada cuando la conversación actual coincide con un episodio pasado.
graph TD
subgraph Memory["Arquitectura de Memoria"]
direction TB
STM["Memoria a Corto Plazo\n(conversación actual)\nDirecto en la ventana de contexto"]
LTM["Memoria a Largo Plazo\n(hechos, preferencias)\nBD -> recuperado al inicio de la sesión"]
EM["Memoria Episódica\n(interacciones pasadas)\nEmbeddings -> recuperado por similitud"]
end
Q["Consulta Actual"] --> STM
Q --> LTM
Q --> EM
STM --> CW["Ventana de Contexto"]
LTM --> CW
EM --> CW
style STM fill:#1a1a2e,stroke:#51cf66,color:#fff
style LTM fill:#1a1a2e,stroke:#0f3460,color:#fff
style EM fill:#1a1a2e,stroke:#e94560,color:#fff
style CW fill:#1a1a2e,stroke:#ffa500,color:#fff
Ensamblado Dinámico de Contexto
La idea clave: diferentes consultas necesitan diferentes contextos. Un prompt del sistema estático + herramientas estáticas + historial estático es un desperdicio. Los mejores sistemas ensamblan dinámicamente el contexto por consulta.
- Clasificar la intención de la consulta
- Seleccionar herramientas relevantes (no todas las herramientas)
- Recuperar documentos relevantes (no un conjunto fijo)
- Incluir turnos de historial relevantes (no todo el historial)
- Agregar ejemplos few-shot que coincidan con el tipo de tarea
- Ordenar todo por importancia: lo crítico primero, lo importante al final, lo opcional en el medio
Esto es lo que separa a una buena aplicación de IA de una excelente. El modelo es el mismo. El contexto es el diferenciador.
Constrúyelo
Paso 1: Contador de Tokens
No puedes presupuestar lo que no puedes medir. Construye un contador de tokens simple (una aproximación usando división por espacios en blanco, ya que el conteo exacto depende del tokenizador).
import json
import numpy as np
from collections import OrderedDict
def count_tokens(text):
if not text:
return 0
return int(len(text.split()) * 1.3)
def count_tokens_json(obj):
return count_tokens(json.dumps(obj))
Paso 2: Gestor de Presupuesto de Contexto
La abstracción principal. Un gestor de presupuesto rastrea cuántos tokens usa cada componente y aplica límites.
class ContextBudget:
def __init__(self, max_tokens=128000, generation_reserve=4000):
self.max_tokens = max_tokens
self.generation_reserve = generation_reserve
self.available = max_tokens - generation_reserve
self.allocations = OrderedDict()
def allocate(self, component, content, max_tokens=None):
tokens = count_tokens(content)
if max_tokens and tokens > max_tokens:
words = content.split()
target_words = int(max_tokens / 1.3)
content = " ".join(words[:target_words])
tokens = count_tokens(content)
used = sum(self.allocations.values())
if used + tokens > self.available:
allowed = self.available - used
if allowed <= 0:
return None, 0
words = content.split()
target_words = int(allowed / 1.3)
content = " ".join(words[:target_words])
tokens = count_tokens(content)
self.allocations[component] = tokens
return content, tokens
def remaining(self):
used = sum(self.allocations.values())
return self.available - used
def utilization(self):
used = sum(self.allocations.values())
return used / self.max_tokens
def report(self):
total_used = sum(self.allocations.values())
lines = []
lines.append(f"Context Budget Report ({self.max_tokens:,} token window)")
lines.append("-" * 50)
for component, tokens in self.allocations.items():
pct = tokens / self.max_tokens * 100
bar = "#" * int(pct / 2)
lines.append(f" {component:<25} {tokens:>6} tokens ({pct:>5.1f}%) {bar}")
lines.append("-" * 50)
lines.append(f" {'Used':<25} {total_used:>6} tokens ({total_used/self.max_tokens*100:.1f}%)")
lines.append(f" {'Generation reserve':<25} {self.generation_reserve:>6} tokens")
lines.append(f" {'Remaining':<25} {self.remaining():>6} tokens")
return "\n".join(lines)
Paso 3: Reordenamiento Lost-in-the-Middle
Implementa la estrategia de reordenamiento: los elementos más importantes van al principio y al final, los menos importantes van al medio.
def reorder_lost_in_middle(items, scores):
paired = sorted(zip(scores, items), reverse=True)
sorted_items = [item for _, item in paired]
if len(sorted_items) <= 2:
return sorted_items
first_half = sorted_items[::2]
second_half = sorted_items[1::2]
second_half.reverse()
return first_half + second_half
def score_relevance(query, documents):
query_words = set(query.lower().split())
scores = []
for doc in documents:
doc_words = set(doc.lower().split())
if not query_words:
scores.append(0.0)
continue
overlap = len(query_words & doc_words) / len(query_words)
scores.append(round(overlap, 3))
return scores
Paso 4: Compresor del Historial de Conversación
Resume los turnos antiguos de conversación para recuperar el presupuesto de tokens.
class ConversationManager:
def __init__(self, max_history_tokens=5000):
self.turns = []
self.summaries = []
self.max_history_tokens = max_history_tokens
def add_turn(self, role, content):
self.turns.append({"role": role, "content": content})
self._compress_if_needed()
def _compress_if_needed(self):
total = sum(count_tokens(t["content"]) for t in self.turns)
if total <= self.max_history_tokens:
return
while total > self.max_history_tokens and len(self.turns) > 4:
old_turns = self.turns[:2]
summary = self._summarize_turns(old_turns)
self.summaries.append(summary)
self.turns = self.turns[2:]
total = sum(count_tokens(t["content"]) for t in self.turns)
def _summarize_turns(self, turns):
parts = []
for t in turns:
content = t["content"]
if len(content) > 100:
content = content[:100] + "..."
parts.append(f"{t['role']}: {content}")
return "Previous: " + " | ".join(parts)
def get_context(self):
parts = []
if self.summaries:
parts.append("[Conversation Summary]")
for s in self.summaries:
parts.append(s)
parts.append("[Recent Conversation]")
for t in self.turns:
parts.append(f"{t['role']}: {t['content']}")
return "\n".join(parts)
def token_count(self):
return count_tokens(self.get_context())
Paso 5: Selector Dinámico de Herramientas
Solo incluye las herramientas relevantes para la consulta actual. Clasifica la intención y luego filtra.
TOOL_REGISTRY = {
"read_file": {
"description": "Read contents of a file",
"tokens": 120,
"categories": ["code", "files"],
},
"write_file": {
"description": "Write content to a file",
"tokens": 150,
"categories": ["code", "files"],
},
"search_code": {
"description": "Search for patterns in codebase",
"tokens": 130,
"categories": ["code"],
},
"run_command": {
"description": "Execute a shell command",
"tokens": 140,
"categories": ["code", "system"],
},
"create_calendar_event": {
"description": "Create a new calendar event",
"tokens": 180,
"categories": ["calendar"],
},
"list_emails": {
"description": "List recent emails",
"tokens": 160,
"categories": ["email"],
},
"send_email": {
"description": "Send an email message",
"tokens": 200,
"categories": ["email"],
},
"web_search": {
"description": "Search the web for information",
"tokens": 140,
"categories": ["research"],
},
"query_database": {
"description": "Run a SQL query on the database",
"tokens": 170,
"categories": ["code", "data"],
},
"generate_chart": {
"description": "Generate a chart from data",
"tokens": 190,
"categories": ["data", "visualization"],
},
}
def classify_intent(query):
query_lower = query.lower()
intent_keywords = {
"code": ["code", "function", "bug", "error", "file", "implement", "refactor", "debug", "test"],
"calendar": ["meeting", "schedule", "calendar", "appointment", "event"],
"email": ["email", "mail", "send", "inbox", "message"],
"research": ["search", "find", "what is", "how does", "explain", "look up"],
"data": ["data", "query", "database", "chart", "graph", "analytics", "sql"],
}
scores = {}
for intent, keywords in intent_keywords.items():
score = sum(1 for kw in keywords if kw in query_lower)
if score > 0:
scores[intent] = score
if not scores:
return ["code"]
max_score = max(scores.values())
return [intent for intent, score in scores.items() if score >= max_score * 0.5]
def select_tools(query, token_budget=2000):
intents = classify_intent(query)
relevant = {}
total_tokens = 0
for name, tool in TOOL_REGISTRY.items():
if any(cat in intents for cat in tool["categories"]):
if total_tokens + tool["tokens"] <= token_budget:
relevant[name] = tool
total_tokens += tool["tokens"]
return relevant, total_tokens
Paso 6: Pipeline Completo de Ensamblado de Contexto
Conecta todo. Dada una consulta, ensambla dinámicamente el contexto óptimo.
class ContextEngine:
def __init__(self, max_tokens=128000, generation_reserve=4000):
self.budget = ContextBudget(max_tokens, generation_reserve)
self.conversation = ConversationManager(max_history_tokens=5000)
self.system_prompt = (
"You are a helpful AI assistant. You have access to tools for "
"code editing, file management, web search, and data analysis. "
"Use the appropriate tools for each task. Be concise and accurate."
)
self.knowledge_base = [
"Python 3.12 introduced type parameter syntax for generic classes using bracket notation.",
"The project uses PostgreSQL 16 with pgvector for embedding storage.",
"Authentication is handled by Supabase Auth with JWT tokens.",
"The frontend is built with Next.js 15 using the App Router.",
"API rate limits are set to 100 requests per minute per user.",
"The deployment pipeline uses GitHub Actions with Docker multi-stage builds.",
"Test coverage must be above 80% for all new modules.",
"The codebase follows the repository pattern for data access.",
]
def assemble(self, query):
self.budget = ContextBudget(self.budget.max_tokens, self.budget.generation_reserve)
system_content, _ = self.budget.allocate("system_prompt", self.system_prompt, max_tokens=1000)
tools, tool_tokens = select_tools(query, token_budget=2000)
tool_text = json.dumps(list(tools.keys()))
tool_content, _ = self.budget.allocate("tools", tool_text, max_tokens=2000)
relevance = score_relevance(query, self.knowledge_base)
threshold = 0.1
relevant_docs = [
doc for doc, score in zip(self.knowledge_base, relevance)
if score >= threshold
]
if relevant_docs:
doc_scores = [s for s in relevance if s >= threshold]
reordered = reorder_lost_in_middle(relevant_docs, doc_scores)
doc_text = "\n".join(reordered)
doc_content, _ = self.budget.allocate("retrieved_context", doc_text, max_tokens=3000)
history_text = self.conversation.get_context()
if history_text.strip():
history_content, _ = self.budget.allocate("conversation_history", history_text, max_tokens=5000)
query_content, _ = self.budget.allocate("user_query", query, max_tokens=500)
return self.budget
def chat(self, query):
self.conversation.add_turn("user", query)
budget = self.assemble(query)
response = f"[Response to: {query[:50]}...]"
self.conversation.add_turn("assistant", response)
return budget
def run_demo():
print("=" * 60)
print(" Context Engineering Pipeline Demo")
print("=" * 60)
engine = ContextEngine(max_tokens=128000, generation_reserve=4000)
print("\n--- Query 1: Code task ---")
budget = engine.chat("Fix the bug in the authentication module where JWT tokens expire too early")
print(budget.report())
print("\n--- Query 2: Research task ---")
budget = engine.chat("What is the best approach for implementing vector search in PostgreSQL?")
print(budget.report())
print("\n--- Query 3: After conversation history builds up ---")
for i in range(8):
engine.conversation.add_turn("user", f"Follow-up question number {i+1} about the implementation details of the system")
engine.conversation.add_turn("assistant", f"Here is the response to follow-up {i+1} with technical details about the architecture")
budget = engine.chat("Now implement the changes we discussed")
print(budget.report())
print("\n--- Tool Selection Examples ---")
test_queries = [
"Fix the bug in auth.py",
"Schedule a meeting with the team for Tuesday",
"Show me the database query performance stats",
"Search for best practices on error handling",
]
for q in test_queries:
tools, tokens = select_tools(q)
intents = classify_intent(q)
print(f"\n Query: {q}")
print(f" Intents: {intents}")
print(f" Tools: {list(tools.keys())} ({tokens} tokens)")
print("\n--- Lost-in-the-Middle Reordering ---")
docs = ["Doc A (most relevant)", "Doc B (somewhat relevant)", "Doc C (least relevant)",
"Doc D (relevant)", "Doc E (moderately relevant)"]
scores = [0.95, 0.60, 0.20, 0.80, 0.50]
reordered = reorder_lost_in_middle(docs, scores)
print(f" Original order: {docs}")
print(f" Scores: {scores}")
print(f" Reordered: {reordered}")
print(f" (Most relevant at start and end, least relevant in middle)")
Úselo
La Estrategia de Contexto de Claude Code
Claude Code gestiona el contexto con un enfoque en capas. El prompt del sistema incluye reglas de comportamiento y definiciones de herramientas (~6K tokens). Cuando abres un archivo, su contenido se inyecta como contexto. Cuando buscas, se agregan los resultados. Los turnos de conversación antiguos se resumen. CLAUDE.md proporciona memoria a largo plazo que persiste entre sesiones.
La decisión clave de ingeniería: Claude Code no vuelca todo tu código fuente en el contexto. Recupera archivos relevantes bajo demanda. Esto es ingeniería de contexto en la práctica.
Carga Dinámica de Contexto de Cursor
Cursor indexa todo tu código fuente en embeddings. Cuando escribes una consulta, recupera los archivos y bloques de código más relevantes mediante similitud vectorial. Solo esas partes entran en la ventana de contexto. Un código fuente de 500K líneas se comprime en los 5-10 bloques de código más relevantes.
Este es el patrón: incorporar todo (embed), recuperar bajo demanda, incluir solo lo que importa.
Memoria de ChatGPT
ChatGPT almacena preferencias y hechos del usuario como memoria a largo plazo. Al inicio de cada conversación, se recuperan las memorias relevantes y se incluyen en el prompt del sistema. "El usuario prefiere Python" cuesta 5 tokens pero ahorra cientos de tokens de instrucciones repetidas en todas las conversaciones.
RAG como Ingeniería de Contexto
La Generación Aumentada por Recuperación (RAG) es la ingeniería de contexto formalizada. En el caso de enfilar el conocimiento en los pesos del modelo (entrenamiento) o en el prompt del sistema (contexto estático), recuperas documentos relevantes al momento de la consulta y los inyectas en la ventana de contexto. Todo el pipeline de RAG -- fragmentación (chunking), incrustación (embedding), recuperación, reclasificación (reranking) -- existe para resolver un problema: colocar la información correcta en la ventana de contexto.
Envíalo
Esta lección produce outputs/prompt-context-optimizer.md -- un prompt reutilizable que audita una estrategia de ensamblado de contexto y recomienda optimizaciones. Aliméntalo con tu prompt del sistema, número de herramientas, longitud promedio del historial y estrategia de recuperación, e identificará el desperdicio de tokens y sugerirá mejoras.
También produce outputs/skill-context-engineering.md -- un marco de decisión para diseñar pipelines de ensamblado de contexto según el tipo de tarea, el tamaño de la ventana de contexto y el presupuesto de latencia.
Ejercicios
Agrega un "detector de desperdicio de tokens" a la clase ContextBudget. Debe marcar los componentes que usan más del 30% del presupuesto y sugerir estrategias de compresión específicas para cada tipo de componente (resumir el historial, podar herramientas, reclasificar documentos).
Implementa la deduplicación semántica para el contexto recuperado. Si dos documentos recuperados son más del 80% similares (por superposición de palabras o similitud de coseno de sus embeddings), conserva solo el de mayor puntuación. Mide cuánto presupuesto de tokens recupera esto.
Construye una herramienta de "reproducción de contexto". Dada una transcripción de conversación, reprodúcela a través de ContextEngine y visualiza cómo cambia la asignación de presupuesto turno por turno. Grafica el uso de tokens por componente a lo largo del tiempo. Identifica el turno en el que el contexto comienza a comprimirse.
Implementa un selector de herramientas basado en prioridades. En lugar de una inclusión/exclusión binaria, asigna a cada herramienta una puntuación de relevancia para la consulta actual. Incluye herramientas en orden descendente de relevancia hasta que se agote el presupuesto de herramientas. Compara el rendimiento de la tarea con 5, 10, 20 y 50 herramientas incluidas.
Construye un compresor de contexto multiestrategia. Implementa tres estrategias de compresión (truncamiento, resumen, extracción de oraciones clave) y evalúalas en un conjunto de 20 documentos. Mide el equilibrio (tradeoff) entre la tasa de compresión y la retención de información (¿la versión comprimida todavía contiene la respuesta a la consulta?).
Términos Clave
| Término | Lo que la gente dice | Lo que realmente significa |
|---|---|---|
| Ventana de contexto | "Cuánto puede leer el modelo" | El número máximo de tokens (entrada + salida) que el modelo procesa en una sola pasada hacia adelante (forward pass) -- 400K para GPT-5, 200K (1M beta) para Claude Opus 4.7, 2M para Gemini 3 Pro |
| Ingeniería de contexto | "Ingeniería de prompts avanzada" | La disciplina de decidir qué entra en la ventana de contexto, en qué orden y con qué prioridad -- abarca la recuperación, compresión, selección de herramientas y gestión de la memoria |
| Lost-in-the-middle | "Los modelos olvidan cosas en el medio" | Hallazgo empírico de que los LLMs atienden mejor al principio y al final del contexto, con una caída del 10-20% en la precisión para la información colocada en el medio |
| Presupuesto de tokens | "Cuántos tokens te quedan" | Una asignación explícita de la capacidad de la ventana de contexto entre los componentes (prompt del sistema, herramientas, historial, recuperación, generación) con límites por componente |
| Contexto dinámico | "Cargar cosas sobre la marcha" | Ensamblar la ventana de contexto de manera diferente para cada consulta según la clasificación de la intención, la selección de herramientas relevantes y los resultados de la recuperación |
| Resumen del historial | "Comprimir la conversación" | Reemplazar los turnos de conversación antiguos y literales con un resumen conciso, reduciendo el costo de tokens mientras se conserva la información clave |
| Poda de herramientas | "Solo incluir herramientas relevantes" | Clasificar la intención de la consulta e incluir solo definiciones de herramientas que coincidan, reduciendo el costo de tokens de herramientas entre un 60% y un 80% |
| Memoria a largo plazo | "Recordar a través de sesiones" | Hechos y preferencias almacenados en una base de datos y recuperados al inicio de la sesión -- CLAUDE.md, ChatGPT Memory y sistemas similares |
| Memoria episódica | "Recordar eventos pasados específicos" | Interacciones pasadas almacenadas como embeddings y recuperadas cuando la consulta actual es similar a una conversación pasada |
| Presupuesto de generación | "Espacio para la respuesta" | Tokens reservados para la salida del modelo -- si el contexto llena la ventana por completo, el modelo no tiene espacio para responder |
Lectura Adicional
- Liu et al., 2023 -- "Lost in the Middle: How Language Models Use Long Contexts" -- el estudio definitivo sobre la atención dependiente de la posición, que muestra que los modelos tienen dificultades con la información en el medio de contextos largos
- Anthropic's Contextual Retrieval blog post -- cómo Anthropic aborda la recuperación de fragmentos conscientes del contexto, reduciendo los fallos de recuperación en un 49%
- Simon Willison's "Context Engineering" -- la publicación de blog que dio nombre a la disciplina y la distinguió de la ingeniería de prompts
- LangChain documentation on RAG -- implementación práctica de la generación aumentada por recuperación como un patrón de ingeniería de contexto
- Greg Kamradt's Needle in a Haystack test -- el benchmark que reveló fallas de recuperación dependientes de la posición en todos los modelos principales
- Pope et al., "Efficiently Scaling Transformer Inference" (2022) -- por qué la longitud del contexto impulsa la memoria y la latencia, y cómo KV cache, MQA y GQA cambian el cálculo del presupuesto.
- Agrawal et al., "SARATHI: Efficient LLM Inference by Piggybacking Decodes with Chunked Prefills" (2023) -- las dos fases de inferencia que hacen que los prompts largos sean costosos en TTFT pero baratos en TPOT; la realidad detrás de las ventajas y desventajas de la compactación de contexto.
- Ainslie et al., "GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints" (EMNLP 2023) -- el artículo sobre atención de consulta agrupada que redujo la memoria KV en 8 veces en decodificadores de producción sin pérdida de calidad.