Phase 11 - Lesson 05
Engenharia de Contexto: Janelas, Orçamentos, Memória e Recuperação
This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.
A engenharia de prompts é um subconjunto. A engenharia de contexto é o jogo completo. Um prompt é uma string que você digita. O contexto é tudo o que entra na janela do modelo: instruções do sistema, documentos recuperados, definições de ferramentas, histórico de conversação, exemplos few-shot e o próprio prompt. Os melhores engenheiros de IA em 2026 são engenheiros de contexto. Eles decidem o que entra, o que fica de fora e em qual ordem.
Tipo: Build Linguagens: Python Pré-requisitos: Phase 10 (LLMs from Scratch), Phase 11 Lição 01-02 Tempo: ~90 minutos Relacionado: Phase 11 · 15 (Prompt Caching) — o layout amigável ao cache é uma extensão da engenharia de contexto. Phase 5 · 28 (Long-Context Evaluation) para saber como medir lost-in-the-middle com NIAH/RULER.
Objetivos de Aprendizado
- Calcular orçamentos de tokens em todos os componentes da janela de contexto (prompt do sistema, ferramentas, histórico, documentos recuperados, margem de geração)
- Implementar estratégias de gerenciamento de janela de contexto: truncamento, sumarização e janela deslizante para o histórico de conversação
- Priorizar e ordenar componentes de contexto para maximizar a atenção do modelo nas informações mais relevantes
- Construir um montador de contexto que aloca tokens dinamicamente com base no tipo de consulta e no espaço disponível na janela
O Problema
O Claude Opus 4.7 tem uma janela de contexto de 200K tokens (1M em beta). O GPT-5 tem 400K. O Gemini 3 Pro tem 2M. O Llama 4 promete 10M. Esses números parecem enormes até que você os preencha.
Aqui está um detalhamento real para um assistente de código. Prompt do sistema: 500 tokens. Definições de ferramentas para 50 ferramentas: 8.000 tokens. Documentação recuperada: 4.000 tokens. Histórico de conversação (10 rodadas): 6.000 tokens. Consulta atual do usuário: 200 tokens. Orçamento de geração (saída máxima): 4.000 tokens. Total: 22.700 tokens. Isso representa apenas 18% de uma janela de 128K.
Mas a atenção não escala linearmente com o tamanho do contexto. Um modelo com 128K tokens de contexto paga um custo de atenção quadrático (O(n^2) em transformers padrão, embora a maioria dos modelos de produção utilize variantes eficientes de atenção). Mais importante ainda, a precisão de recuperação se degrada. O teste "Needle in a Haystack" (Agulha no Palheiro) mostra que os modelos têm dificuldade para encontrar informações colocadas no meio de contextos longos. Pesquisas de Liu et al. (2023) mostraram que os LLMs recuperam informações no início e no fim de contextos longos com precisão quase perfeita, mas a precisão cai de 10% a 20% para informações localizadas no meio (posições de 40% a 70% do contexto). Esse efeito "lost-in-the-middle" (perdido no meio) varia de acordo com o modelo, mas afeta todas as arquiteturas atuais.
A lição prática: ter 200K tokens disponíveis não significa que usar 200K tokens seja eficaz. Um contexto de 10K tokens cuidadosamente selecionado geralmente supera o desempenho de um contexto descartado de 100K tokens. A engenharia de contexto é a disciplina de maximizar a relação sinal-ruído dentro da janela de contexto.
Cada palavra que você coloca na janela desloca um token que poderia carregar informações mais relevantes. Cada definição de ferramenta irrelevante, cada rodada de conversação desatualizada, cada fragmento de texto recuperado que não responde à pergunta — cada um deles torna o modelo ligeiramente pior na tarefa.
O Conceito
A Janela de Contexto é um Recurso Escasso
Pense na janela de contexto como memória RAM, não como disco rígido. Ela é rápida e diretamente acessível, mas limitada. Você não pode colocar tudo nela. Você precisa escolher.
graph TD
subgraph Window["Janela de Contexto (128K tokens)"]
direction TB
S["Prompt do Sistema\n~500 tokens"] --> T["Definições de Ferramentas\n~2K-8K tokens"]
T --> R["Contexto Recuperado\n~2K-10K tokens"]
R --> H["Histórico de Conversação\n~2K-20K tokens"]
H --> F["Exemplos Few-shot\n~1K-3K tokens"]
F --> Q["Consulta do Usuário\n~100-500 tokens"]
Q --> G["Orçamento de Geração\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 compete por espaço. Adicionar mais definições de ferramentas significa menos espaço para o histórico de conversação. Adicionar mais contexto recuperado significa menos espaço para exemplos few-shot. A engenharia de contexto é a arte de alocar esse orçamento para maximizar o desempenho da tarefa.
Lost-in-the-Middle
A descoberta empírica mais importante na engenharia de contexto. Os modelos prestam mais atenção às informações no início e no final do contexto. As informações no meio recebem pontuações de atenção mais baixas e têm maior probabilidade de serem ignoradas.
Liu et al. (2023) testaram isso sistematicamente. Eles colocaram um documento relevante entre 20 documentos irrelevantes em várias posições e mediram a precisão das respostas. Quando o documento relevante estava no início ou no fim, a precisão era de 85-90%. Quando estava no meio (posição 10 de 20), a precisão caiu para 60-70%.
Isso tem implicações diretas na engenharia:
- Coloque as informações mais importantes no início (prompt do sistema, instruções críticas)
- Coloque a consulta atual e o contexto mais relevante por último (o viés de recência ajuda)
- Trate o meio do contexto como a zona de menor prioridade
- Se você precisar incluir informações no meio, duplique o ponto principal no final
graph LR
subgraph Attention["Distribuição de Atenção no Contexto"]
direction LR
P1["Posição 0-20%\nALTA atenção\n(prompt do sistema)"]
P2["Posição 20-40%\nMODERADA"]
P3["Posição 40-70%\nBAIXA atenção\n(lost in middle)"]
P4["Posição 70-90%\nMODERADA"]
P5["Posição 90-100%\nALTA atenção\n(consulta atual)"]
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 do Contexto
Prompt do sistema: define a persona, restrições e regras de comportamento. Ele vai primeiro e permanece constante ao longo das rodadas. O Claude Code usa aproximadamente 6.000 tokens em seu prompt do sistema, incluindo definições de ferramentas e instruções comportamentais. Mantenha-o enxuto. Cada palavra no prompt do sistema é repetida a cada chamada de API.
Definições de ferramentas: cada ferramenta adiciona 50-200 tokens (nome, descrição, esquema de parâmetros). 50 ferramentas a 150 tokens cada totalizam 7.500 tokens antes de qualquer conversa acontecer. A seleção dinâmica de ferramentas — incluindo apenas ferramentas relevantes para a consulta atual — pode reduzir isso em 60-80%.
Contexto recuperado: documentos de um banco de dados vetorial, resultados de busca, conteúdo de arquivos. A qualidade da recuperação determina diretamente a qualidade da resposta. Uma recuperação ruim é pior do que nenhuma recuperação — ela preenche a janela com ruído e induz o modelo ao erro.
Histórico de conversação: cada mensagem anterior do usuário e resposta do assistente. Cresce linearmente com a extensão da conversa. Uma conversa de 50 rodadas a 200 tokens por rodada representa 10.000 tokens de histórico. A maior parte disso é irrelevante para a consulta atual.
Exemplos few-shot: pares de entrada/saída que demonstram o comportamento desejado. Dois a três exemplos bem escolhidos costumam melhorar a qualidade da saída mais do que milhares de tokens de instruções. Mas eles custam espaço.
Orçamento de geração: os tokens reservados para a resposta do modelo. Se você preencher a janela até a capacidade máxima, o modelo não terá espaço para responder. Reserve pelo menos 2.000-4.000 tokens para a geração.
Estratégias de Compressão de Contexto
Sumarização de histórico: em vez de manter todas as rodadas anteriores textualmente, resuma a conversa periodicamente. "Discutimos X, decidimos Y e o usuário quer Z" em 100 tokens substitui 10 rodadas que consumiriam 2.000 tokens. Execute a sumarização quando o histórico exceder um limite (por exemplo, 5.000 tokens).
Filtragem por relevância: pontue cada documento recuperado em relação à consulta atual e descarte os documentos abaixo de um limite. Se você recuperou 10 fragmentos, mas apenas 3 são relevantes, descarte os outros 7. É melhor ter 3 fragmentos altamente relevantes do que 10 medíocres.
Poda de ferramentas: classifique a intenção da consulta do usuário e inclua apenas as ferramentas relevantes para essa intenção. Uma pergunta sobre código não precisa de ferramentas de calendário. Uma pergunta sobre agendamento não precisa de ferramentas de sistema de arquivos. Isso pode reduzir as definições de ferramentas de 8.000 tokens para 1.000.
Sumarização recursiva: para documentos muito longos, resuma em etapas. Primeiro resuma cada seção e, em seguida, resuma os resumos. Um documento de 50 páginas se torna um resumo de 500 tokens que captura os pontos principais.
Sistemas de Memória
A engenharia de contexto abrange três horizontes temporais.
Memória de curto prazo: a conversa atual. Armazenada diretamente na janela de contexto. Cresce a cada rodada. Gerenciada por sumarização e truncamento.
Memória de longo prazo: fatos e preferências que persistem entre conversas. "O usuário prefere TypeScript." "O projeto usa PostgreSQL." Armazenada em um banco de dados, recuperada no início da sessão. O Claude Code armazena isso em arquivos CLAUDE.md. O ChatGPT armazena isso em seu recurso de memória.
Memória episódica: interações passadas específicas que podem ser relevantes. "Na terça-feira passada, depuramos um problema semelhante no módulo de autenticação." Armazenada como embeddings, recuperada quando a conversa atual corresponde a um episódio anterior.
graph TD
subgraph Memory["Arquitetura de Memória"]
direction TB
STM["Memória de Curto Prazo\n(conversa atual)\nDireto na janela de contexto"]
LTM["Memória de Longo Prazo\n(fatos, preferências)\nBD -> recuperado no início da sessão"]
EM["Memória Episódica\n(interações passadas)\nEmbeddings -> recuperado por similaridade"]
end
Q["Consulta Atual"] --> STM
Q --> LTM
Q --> EM
STM --> CW["Janela 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
Montagem Dinâmica de Contexto
A principal percepção: consultas diferentes precisam de contextos diferentes. Um prompt de sistema estático + ferramentas estáticas + histórico estático é um desperdício. Os melhores sistemas montam o contexto dinamicamente para cada consulta.
- Classificar a intenção da consulta
- Selecionar ferramentas relevantes (não todas as ferramentas)
- Recuperar documentos relevantes (não um conjunto fixo)
- Incluir rodadas de histórico relevantes (não todo o histórico)
- Adicionar exemplos few-shot que correspondam ao tipo de tarefa
- Ordenar tudo por importância: o que é crítico primeiro, o que é importante por último, o que é opcional no meio
Isso é o que separa uma boa aplicação de IA de uma excelente. O modelo é o mesmo. O contexto é o diferencial.
Construa
Passo 1: Contador de Tokens
Você não pode gerenciar um orçamento do que não pode medir. Construa um contador de tokens simples (uma aproximação usando divisão por espaços em branco, já que a contagem exata depende do 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))
Passo 2: Gerenciador de Orçamento de Contexto
A abstração principal. Um gerenciador de orçamento rastreia quantos tokens cada componente usa e impõe limites.
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)
Passo 3: Reordenação Lost-in-the-Middle
Implemente a estratégia de reordenação: os itens mais importantes vão para o início e para o fim, os menos importantes vão para o meio.
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
Passo 4: Compressor de Histórico de Conversação
Resuma rodadas antigas de conversação para recuperar o orçamento 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())
Passo 5: Seletor Dinâmico de Ferramentas
Inclua apenas as ferramentas relevantes para a consulta atual. Classifique a intenção e, em seguida, filtre.
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
Passo 6: Pipeline Completo de Montagem de Contexto
Conecte tudo. Dada uma consulta, monte dinamicamente o contexto ideal.
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)")
Use
A Estratégia de Contexto do Claude Code
O Claude Code gerencia o contexto com uma abordagem em camadas. O prompt do sistema inclui regras comportamentais e definições de ferramentas (~6K tokens). Quando você abre um arquivo, seu conteúdo é injetado como contexto. Quando você pesquisa, os resultados são adicionados. Rodadas antigas de conversação são sumarizadas. O arquivo CLAUDE.md fornece memória de longo prazo que persiste entre as sessões.
A principal decisão de engenharia: o Claude Code não joga todo o seu código-fonte no contexto. Ele recupera arquivos relevantes sob demanda. Isso é engenharia de contexto na prática.
Carregamento Dinâmico de Contexto do Cursor
O Cursor indexa todo o seu código-fonte em embeddings. Quando você digita uma consulta, ele recupera os arquivos e blocos de código mais relevantes usando similaridade vetorial. Apenas esses pedaços entram na janela de contexto. Um código-base de 500 mil linhas é compactado nos 5 a 10 blocos de código mais relevantes.
Este é o padrão: incorporar tudo (embed), recuperar sob demanda, incluir apenas o que importa.
Memória do ChatGPT
O ChatGPT armazena preferências e fatos do usuário como memória de longo prazo. A cada início de conversa, as memórias relevantes são recuperadas e incluídas no prompt do sistema. "O usuário prefere Python" custa 5 tokens, mas economiza centenas de tokens de instruções repetidas ao longo das conversas.
RAG como Engenharia de Contexto
A Geração Aumentada de Recuperação (RAG) é a engenharia de contexto formalizada. Em vez de enfiar o conhecimento nos pesos do modelo (treinamento) ou no prompt do sistema (contexto estático), você recupera documentos relevantes no momento da consulta e os injeta na janela de contexto. Todo o pipeline de RAG — fragmentação (chunking), incorporação (embedding), recuperação e reclassificação (reranking) — existe para resolver um único problema: colocar a informação correta na janela de contexto.
Envie
Esta lição produz outputs/prompt-context-optimizer.md — um prompt reutilizável que audita uma estratégia de montagem de contexto e recomenda otimizações. Forneça a ele seu prompt de sistema, quantidade de ferramentas, tamanho médio do histórico e estratégia de recuperação, e ele identificará o desperdício de tokens e sugerirá melhorias.
Também produz outputs/skill-context-engineering.md — uma estrutura de decisão para projetar pipelines de montagem de contexto com base no tipo de tarefa, tamanho da janela de contexto e orçamento de latência.
Exercícios
Adicione um "detector de desperdício de tokens" à classe ContextBudget. Ele deve sinalizar componentes que usam mais de 30% do orçamento e sugerir estratégias de compressão específicas para cada tipo de componente (sumarizar histórico, podar ferramentas, reclassificar documentos).
Implemente a deduplicação semântica para o contexto recuperado. Se dois documentos recuperados forem mais de 80% semelhantes (por sobreposição de palavras ou similaridade de cosseno de seus embeddings), mantenha apenas aquele com maior pontuação. Meça quanto do orçamento de tokens isso recupera.
Construa uma ferramenta de "reprodução de contexto". Dada uma transcrição de conversa, reproduza-a por meio do ContextEngine e visualize como a alocação de orçamento muda rodada a rodada. Trace o uso de tokens por componente ao longo do tempo. Identifique a rodada na qual o contexto começa a ser compactado.
Implemente um seletor de ferramentas baseado em prioridade. Em vez de inclusão/exclusão binária, atribua a cada ferramenta uma pontuação de relevância para a consulta atual. Inclua ferramentas em ordem decrescente de relevância até que o orçamento de ferramentas seja esgotado. Compare o desempenho da tarefa com 5, 10, 20 e 50 ferramentas incluídas.
Construa um compressor de contexto multiestratégia. Implemente três estratégias de compressão (truncamento, sumarização, extração de frases-chave) e avalie-as em um conjunto de 20 documentos. Meça a relação de compromisso (tradeoff) entre a taxa de compressão e a retenção de informações (a versão compactada ainda contém a resposta para a consulta?).
Termos-Chave
| Termo | O que as pessoas dizem | O que realmente significa |
|---|---|---|
| Janela de contexto | "O quanto o modelo consegue ler" | O número máximo de tokens (entrada + saída) que o modelo processa em uma única passagem direta (forward pass) — 400K para GPT-5, 200K (1M beta) para Claude Opus 4.7, 2M para Gemini 3 Pro |
| Engenharia de contexto | "Engenharia de prompts avançada" | A disciplina de decidir o que entra na janela de contexto, em qual ordem e com qual prioridade — engloba recuperação, compressão, seleção de ferramentas e gerenciamento de memória |
| Lost-in-the-middle | "Os modelos esquecem coisas no meio" | Descoberta empírica de que os LLMs prestam mais atenção ao início e ao fim do contexto, com uma queda de 10-20% na precisão para informações colocadas no meio |
| Orçamento de tokens | "Quantos tokens restam" | Uma alocação explícita da capacidade da janela de contexto entre os componentes (prompt do sistema, ferramentas, histórico, recuperação, geração) com limites por componente |
| Contexto dinâmico | "Carregar coisas dinamicamente" | Montar a janela de contexto de forma diferente para cada consulta com base na classificação de intenção, seleção de ferramentas relevantes e resultados de recuperação |
| Sumarização de histórico | "Compactar a conversa" | Substituir rodadas antigas e literais da conversa por um resumo conciso, reduzindo o custo de tokens e preservando as informações principais |
| Poda de ferramentas | "Incluir apenas ferramentas relevantes" | Classificar a intenção da consulta e incluir apenas definições de ferramentas correspondentes, reduzindo o custo de tokens de ferramentas em 60-80% |
| Memória de longo prazo | "Lembrar entre sessões" | Fatos e preferências armazenados em um banco de dados e recuperados no início da sessão — CLAUDE.md, ChatGPT Memory e sistemas semelhantes |
| Memória episódica | "Lembrar de eventos passados específicos" | Interações passadas armazenadas como embeddings e recuperadas quando a consulta atual é semelhante a uma conversa anterior |
| Orçamento de geração | "Espaço para a resposta" | Tokens reservados para a saída do modelo — se o contexto preencher a janela completamente, o modelo não terá espaço para responder |
Leitura Adicional
- Liu et al., 2023 -- "Lost in the Middle: How Language Models Use Long Contexts" — o estudo definitivo sobre atenção dependente da posição, mostrando que os modelos têm dificuldades com informações localizadas no meio de contextos longos
- Anthropic's Contextual Retrieval blog post — como a Anthropic aborda a recuperação de fragmentos com percepção de contexto (context-aware chunk retrieval), reduzindo falhas de recuperação em 49%
- Simon Willison's "Context Engineering" — a postagem de blog que deu nome à disciplina e a diferenciou da engenharia de prompts
- LangChain documentation on RAG — implementação prática de geração aumentada de recuperação (RAG) como um padrão de engenharia de contexto
- Greg Kamradt's Needle in a Haystack test — o benchmark que revelou falhas de recuperação dependentes de posição em todos os principais modelos
- Pope et al., "Efficiently Scaling Transformer Inference" (2022) — por que o tamanho do contexto afeta a memória e a latência, e como KV cache, MQA e GQA alteram o cálculo do orçamento.
- Agrawal et al., "SARATHI: Efficient LLM Inference by Piggybacking Decodes with Chunked Prefills" (2023) — as duas fases de inferência que tornam prompts longos caros no TTFT (time-to-first-token), mas baratos no TPOT (time-per-output-token); a realidade por trás dos tradeoffs de compactação de contexto.
- Ainslie et al., "GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints" (EMNLP 2023) — o artigo sobre atenção de consulta agrupada (GQA) que reduziu a memória do KV cache em 8 vezes nos decodificadores de produção, sem perda de qualidade.