English · Español
Lab 01 — Agente tutor sobre 30 frases canónicas¶
Lee
theory/00-motivation.mdytheory/01-react-and-planning.md. No consultessolutions/.
Objetivo¶
Cablea Planner, ScratchpadMemory, LongTermMemory y las herramientas MCP de la Fase 31 en un GrammarTutorAgent. Ejecútalo sobre el conjunto canónico de prueba de 30 frases. Consigue ≥ 90 % de corrección. Captura la traza completa para un happy path, una ambigüedad y un rechazo fuera de alcance.
Setup¶
Archivos a crear / extender:
src/miniagent/agent.py—GrammarTutorAgentsrc/miniagent/types.py—CorrectionResult,Step,PlannerStatetests/test_agent_loop.py— el test de regresión de 30 frasesexperiments/<date>-phase-32-tutor-demo/— transcripciones + resumen
Tareas¶
Tarea 1 — ensambla el conjunto canónico de prueba¶
Crea experiments/<date>-phase-32-tutor-demo/test_sentences.json con 30 entradas:
- 10 correcciones happy-path (entrada clara, un solo error). Ejemplos:
"He goed to school" → "He went to school","I has a book" → "I have a book","She don't like it" → "She doesn't like it". - 5 frases ya correctas (no se necesita corrección). Ejemplos:
"I work every day". El agente debería devolvercorrected = None(ya que la original es correcta). - 5 frases ambiguas (múltiples correcciones válidas). Ejemplos:
"I will going to the store"— podría ser "I will go" o "I am going". Elige una corrección canónica. - 5 frases multi-error (≥ 2 errores). Ejemplo:
"He goed and she have went home". El agente debería arreglar un error y reportar el resto comoadditional_issues. - 5 frases fuera de alcance (usan pronombres plurales, verbos fuera de §A13 o tiempos fuera de §A13). Ejemplo:
"They are running."El agente debería devolvercorrected = None, in_scope = False, rationale = ["plural pronoun out of scope"].
Cada entrada:
{
"id": 1,
"original": "He goed to school.",
"expected": {
"corrected": "He went to school.",
"in_scope": true,
"rationale_keywords": ["irregular", "past", "went"],
"must_call_tools": ["lookup_irregular_verb", "conjugate"]
}
}
El campo must_call_tools es el camino dorado por el espacio de herramientas — útil para diagnosticar dónde se desvía el planificador del agente.
Tarea 2 — implementa GrammarTutorAgent¶
class GrammarTutorAgent:
def __init__(
self,
planner: Planner | MockPlanner,
tool_dispatcher: MCPClient,
long_term: LongTermMemory,
max_steps: int = 8,
):
...
def correct(self, sentence: str, learner_id: str = "borja") -> CorrectionResult:
scratchpad = ScratchpadMemory() # fresh per call
for step_index in range(self.max_steps):
state = PlannerState(
original=sentence,
scratchpad=scratchpad,
long_term_view=self.long_term.view_for(learner_id, sentence),
step_index=step_index,
)
step = self.planner.next_step(state)
if isinstance(step, FinalAnswer):
self._update_long_term(learner_id, sentence, step.answer)
return CorrectionResult(
original=sentence,
corrected=step.answer.corrected,
rationale=step.answer.rationale,
spanish_gloss=step.answer.spanish_gloss,
in_scope=step.answer.in_scope,
tool_trace=scratchpad.tool_calls(),
)
elif isinstance(step, ToolCall):
if self._is_duplicate_action(step, scratchpad):
return self._budget_exhausted_result(sentence, scratchpad, reason="loop")
result = run_under_sandbox(
self.tool_dispatcher.get_tool(step.tool),
step.args,
policy=SandboxPolicy.PERMISSIVE,
)
scratchpad.append(thought="", action=step, observation=result)
else:
raise TypeError(f"unexpected step type: {type(step)}")
return self._budget_exhausted_result(sentence, scratchpad, reason="budget")
Restricciones:
scratchpadse construye dentro decorrect(), no se almacena enself.long_termse comparte entre correcciones (es estado persistente).- Todas las herramientas se despachan vía el cliente MCP de la Fase 31 (sin imports directos).
- Detección de acción duplicada: si la misma
(tool, args)aparece dos veces seguidas, detente.
Tarea 3 — cablea primero contra MockPlanner¶
Antes de enchufar el planificador real (Mini-GPT no entrenado), ejecuta contra MockPlanner del Lab 00. El mock devuelve pasos prefabricados para las 30 frases. Esto verifica que el bucle funciona antes de introducir incertidumbre del modelo.
Ejecuta sobre las 30 frases:
agent = GrammarTutorAgent(planner=MockPlanner(scripts), ...)
results = [agent.correct(s["original"]) for s in test_sentences]
Esperado: ≥ 95 % de corrección contra MockPlanner (con scripts escritos correctamente, esto es cerca del 100 %). Cualquier fallo aquí es un bug del bucle del agente, no del planificador.
Tarea 4 — captura tres transcripciones¶
Para inclusión en PHASE_32_REPORT.md:
- Happy path —
"He goed to school"— traza completa. - Ambigüedad —
"I will going home"— traza completa, mostrando cómo el agente elige una corrección canónica. - Fuera de alcance —
"They went home"— traza completa, mostrando al agente reconociendo y reportando el fuera-de-alcance.
Para cada uno, guarda:
{
"sentence": "...",
"trace": [
{"step": 1, "action": {"tool": "...", "args": {...}}, "observation": "..."},
{"step": 2, "action": {"tool": "...", "args": {...}}, "observation": "..."},
{"step": 3, "action": "FINAL_ANSWER", "answer": {...}}
]
}
Tarea 5 — mide la corrección¶
Para el conjunto de prueba de 30 frases, reporta:
- Precisión (correctas ÷ total) por categoría (happy / ya-correcta / ambigua / multi-error / fuera-de-alcance).
- Pasos medios por corrección.
- Herramientas medias invocadas por corrección.
- Distribución de conteos de pasos (histograma, guardar como
experiments/<date>-phase-32-tutor-demo/steps_histogram.png).
Objetivo: ≥ 90 % de precisión global con MockPlanner. Con el planificador real (no entrenado), la precisión probablemente será ~aleatoria; esto se documenta como la brecha entre el "entrenado para corrección forward" de la Fase 17 y el "fine-tuned para seguimiento de instrucciones" de la Fase 28.
Tarea 6 — verificación de actualización de memoria a largo plazo¶
Tras ejecutar las 30 frases, inspecciona longterm.json. Los contadores de errores para verbos como go, have, do deberían tener ≥ 1 entrada. Las estadísticas de precisión por tiempo deberían estar pobladas.
Una segunda ejecución sobre las mismas 30 frases debería:
- Producir las mismas correcciones (determinista con semilla fija).
- Mostrar conteos de errores doblados en
longterm.json(ya que cada frase se corrigió dos veces). - Posiblemente mostrar racionales diferentes si el agente inyecta contexto long-term en el prompt.
Medidas a capturar¶
- Resultados del test de 30 frases (pasa/falla por frase).
- Tres transcripciones (happy / ambigüedad / fuera-de-alcance).
- Histograma de distribución de pasos.
longterm.jsontras una ejecución.- Diff entre
longterm.jsontras la ejecución 1 y la 2.
Aceptación¶
-
GrammarTutorAgent.correct()funciona sobre las 30 frases sin lanzar. - Precisión basada en MockPlanner ≥ 90 %.
- Tres transcripciones guardadas en el directorio del experimento.
- Histograma de pasos guardado.
-
longterm.jsonse actualiza correctamente entre ejecuciones. - El test
tests/test_agent_loop.pyestá en verde.
Trampas a esperar¶
- Fuga del scratchpad. Si
scratchpadse almacena enself, la segundacorrect()ve la traza de la primera. Testea esto explícitamente: llamacorrect("A")luegocorrect("B"); el scratchpad de la segunda llamada debería tener solo los pasos de B. - Actualización de long-term en fuera-de-alcance. ¿Deberíamos incrementar contadores de errores para frases fuera de alcance? Default: no (fuera-de-alcance no es un error de verbo, es un desajuste de corpus). Documenta la elección.
- Lagunas en el script del MockPlanner. Si scriptaste solo 25 de 30 frases, las 5 que faltan saltarán un
KeyError. O scripta las 30, o haz queMockPlannerlance un error claro de "scripted-but-not-found". - El agente llama a
final_answerinmediatamente. Un planificador con bugs podría emitirfinal_answercomo paso 1 sin invocar ninguna herramienta. El resultado no es fiable pero es estructuralmente válido. Captura esto en el test: asserta conteo de pasos ≥ 1 (al menos un tool call) antes de aceptar una respuesta, excepto para frases "ya correctas".
Siguiente: 02-sandbox-an-evil-tool.md