¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Ingeniería de contexto para agentes LLM

Después de esta lección: Puedo decidir qué entra en la ventana en cada paso, dar un presupuesto a cada parte y decir qué se descarta primero.

Lección de 60 min7 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

Elige lo que el modelo ve

La ingeniería de contexto consiste en decidir qué entra en la ventana del modelo en cada paso de una ejecución de agente. La ventana es finita, así que cada parte es una decisión.

Un agente que guarda todos los archivos y todos los resultados de herramientas llena la ventana en el sexto paso. Entonces las instrucciones importantes quedan enterradas bajo salidas que nadie necesita.

Al final de esta lección

Nota

Puedo decidir qué entra en la ventana en cada paso, dar un presupuesto a cada parte y decir qué se descarta primero.

Palabras clave

PalabraQué significa
Ventana de contextotodo lo que el modelo lee en una llamada
Presupuestoel máximo de tokens que cabe en una ventana
Fijadauna parte que nunca se descarta
Resultado de herramientalo que imprimió una herramienta, devuelto al modelo
Memorianotas que se guardan entre ejecuciones y se cargan al empezar
Orden de descartequé partes salen primero cuando la ventana está llena

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Una ventana se compone de partes

Cada llamada envía partes en un orden fijo. Las instrucciones dicen quién es el agente y qué puede hacer. La memoria guarda notas duraderas. Los archivos son aquello en lo que trabaja. Los resultados de herramientas son lo que imprimieron sus herramientas. El historial es la conversación hasta ahora.

Cómo se guarda la memoria es otro tema, el de construir agentes. Aquí la pregunta es solo cuánta cabe.

Qué descartar primero

Da un presupuesto a toda la ventana y descarta partes hasta que quepa. Descarta primero lo que cuesta menos reconstruir. Un resultado de herramienta antiguo se puede pedir de nuevo. Un archivo se puede volver a leer. La memoria es más lenta de rehacer.

No descartes nunca las instrucciones. Fija el archivo que se está editando. Deja de descartar en cuanto la ventana quepa, porque cada descarte de más pierde algo.

Orden de descarte de un agente de código

ParteSe descartaPor qué
Resultados de herramientasPrimero, los más antiguos antesLa herramienta puede ejecutarse otra vez
ArchivosDespués, salvo los fijadosEl archivo se puede volver a leer
MemoriaEn tercer lugarLas notas son más lentas de rehacer
HistorialAl finalContiene lo que pidió la persona
InstruccionesNuncaSin ellas el agente no tiene reglas

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un error frecuente

Advertencia

Mucha gente recorta por el principio y quita los mensajes más antiguos sea cual sea su contenido. Así se van primero las instrucciones. Descarta según lo que es una parte, no según su edad.

Escribe el ayudante del modelo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' '  return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el ayudante del modelo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    const d = await res.json();' '    return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    return { text: sample, inTokens: null, outTokens: null, recorded: true };' '  }' '}' 'module.exports = { ask };' >> model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el armador de ventana, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const BUDGET = 60;' '// Aquí un token es una palabra. Un tokenizador real cuenta de otra forma.' 'function size(text) { return text.split(\" \").length; }' 'const parts = [' '  { kind: \"instructions\", name: \"reglas\", text: \"Eres un asistente de código. Edita solo los archivos que se te muestran. Di qué has cambiado.\" },' '  { kind: \"memory\", name: \"notas\", text: \"El proyecto usa tabuladores. Las pruebas están en tests. Ejecútalas antes de cada commit.\" },' '  { kind: \"file\", name: \"app.py\", pinned: true, text: \"def total(items): return sum(items) # suma los precios de una cesta\" },' '];' > context1.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el armador de ventana, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'parts.push({ kind: \"tool_result\", name: \"prueba 1\", text: \"3 pasaron 1 falló test_total esperado 12 obtenido 10 en tests barra test_app\" });' 'parts.push({ kind: \"tool_result\", name: \"prueba 2\", text: \"4 pasaron 0 fallaron\" });' 'parts.push({ kind: \"file\", name: \"leeme\", text: \"Un pequeño script de tienda que calcula el precio de las cestas e imprime un recibo.\" });' 'const DROP = [\"tool_result\", \"file\", \"memory\"];' 'function total(list) {' '  let sum = 0;' '  for (const p of list) sum = sum + size(p.text);' '  return sum;' '}' >> context1.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el armador de ventana, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function assemble(all, budget) {' '  const kept = all.slice();' '  const dropped = [];' '  for (const kind of DROP) {' '    for (const p of all) {' '      if (total(kept) <= budget) break;' '      if (p.kind === kind && p.pinned === undefined) {' '        kept.splice(kept.indexOf(p), 1);' '        dropped.push(p.name);' '      }' '    }' '  }' '  return { kept: kept, dropped: dropped, used: total(kept) };' '}' >> context1.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el armador de ventana, parte 4

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const w = assemble(parts, BUDGET);' '  console.log(\"presupuesto \" + BUDGET + \", usado \" + w.used);' '  for (const p of parts) {' '    console.log((w.kept.includes(p) ? \"conservado \" : \"descartado \") + p.kind + \" \" + p.name + \" \" + size(p.text));' '  }' '  const body = w.kept.slice(1).map(function (p) { return p.name + \": \" + p.text; }).join(\" | \");' '  const question = body + \" | ¿Qué archivo editas primero? Una frase.\";' '  const messages = [{ role: \"system\", content: w.kept[0].text }, { role: \"user\", content: question }];' '  const reply = await ask(messages, \"Edito app.py primero, porque la prueba que falla es sobre total.\", 40);' '  console.log(\"modelo: \" + reply.text);' '}' 'main();' >> context1.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecuta y mira qué se descartó

Comando
docker exec -w /home/node/project agent node context1.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Las palabras hacen de tokens

Una ventana real se cuenta en tokens con el tokenizador del modelo. Aquí una palabra es un token, así que cada estudiante imprime los mismos tamaños. La idea es la misma: sumar las partes y comparar con un límite.

El Run hace una llamada corta con lo conservado. Sin modelo imprime una muestra grabada.

Una salida posible

LíneaQué muestra
presupuesto 60, usado 58Ahora la ventana cabe
conservado instructions reglas 17Las instrucciones nunca se descartan
descartado tool_result prueba 1 13El resultado más antiguo sale primero
descartado tool_result prueba 2 4El descarte para en cuanto cabe
conservado file leeme 16No se descartó ningún archivo, así que el leeme se queda
modelo: ...Una frase. Las palabras cambian en cada ejecución

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.