Skip to content

English · Español

Lab 02 — CLI de conjugación estructurada end-to-end

Objetivo: cablear máscara + modelo + sampler en scripts/conjugate_structured.py; producir el artefacto contractual para las herramientas de la Fase 31 y el agente tutor de gramática de la Fase 32.

Tiempo estimado: 2–3 horas (asume que el lab 01 está terminado).

Prerrequisito: lab 01 (máscara JSON Schema). Punto de control de MiniGPT de la Fase 18.


Lo que produces

  • scripts/conjugate_structured.py — CLI: python scripts/conjugate_structured.py "He ate pizza yesterday" → JSON de conjugación en stdout.
  • experiments/30-end-to-end/ con:
  • sample_sentences/ — cinco frases en inglés (una por cubo de tense: contexto infinitive, present_simple, past_simple, past_participle, simple_future).
  • outputs/ — salidas CLI capturadas para cada una.
  • README.md — para cada frase, la entrada, la salida, tu comentario de un párrafo sobre si el modelo acertó semánticamente.

TODOs

Bloque A — forma de la CLI

  • scripts/conjugate_structured.py toma un único argumento posicional de frase O stdin si no hay arg.
  • Carga el punto de control de MiniGPT desde models/minigpt-phase-18.npz (o donde la Fase 18 lo guarde).
  • Construye JSONSchemaMask(tokenizer, conjugation_schema) una vez.
  • Construye un prompt:
    Identify the main verb conjugation in this English sentence.
    Return JSON with keys: verb (lemma), tense, person.
    
    Sentence: <sentence>
    
    Conjugation:
    
  • Llama a generate(prompt, mask=mask, max_new_tokens=64).
  • Imprime la salida. Compatible con pipe: sin prosa extra, solo el JSON.

Bloque B — terminar al estar listo

  • Cuando mask.is_done() sea True, detén la generación inmediatamente (no esperes a max_new_tokens). Esto acorta significativamente el tiempo medio de decode.
  • Test: una salida de {"verb":"eat","tense":"past_simple","person":"3sg"} NO debería tener tokens al final.

Bloque C — validar y reportar

  • Tras la generación, ejecuta json.loads y jsonschema.validate (lib OK aquí, a posteriori). Si cualquiera falla, imprime la salida malformada en stderr con un error claro y sal con código no-cero. (Esto nunca debería pasar en la práctica; la red de seguridad captura bugs de la máscara.)

Bloque D — frases de muestra

Elige cinco frases en inglés que cubran el espacio de tense de §A13. Conjunto recomendado:

  1. Contexto infinitive. "I want to work tomorrow." — verbo principal want, present_simple, 1sg. (El infinitive work también está presente; el lab especifica "main verb" — documenta la regla de desambiguación en el README.)
  2. Present simple, 3sg. "She plays the piano every Sunday." — verbo play, present_simple, 3sg.
  3. Past simple, regular. "They listened to the radio."they es plural; los plurales de §A13 están aplazados, así que esto está fuera de alcance. Sáltalo y usa: "He listened to the radio." — verbo listen, past_simple, 3sg.
  4. Past simple, irregular. "She wrote a long letter." — verbo write, past_simple, 3sg.
  5. Simple future. "I will study tomorrow." — verbo study, simple_future, 1sg.

Ejecuta cada una por conjugate_structured.py. Guarda las salidas. Comenta en el README si el contenido coincide con la expectativa. (Recuerda: la Fase 30 garantiza el parseo, NO la corrección. Si el modelo emite tense: "present_simple" para "She wrote a long letter", la máscara hizo su trabajo; el modelo está poco entrenado.)

Bloque E — smoke test de pipeline

En tests/test_conjugate_cli.py:

  • test_conjugate_cli_returns_valid_json — ejecuta la CLI sobre una frase fija, asserta que la salida parsee y valide.
  • test_conjugate_cli_verb_in_scope — asserta que el campo verb sea uno de los 20 enums.
  • test_conjugate_cli_tense_in_scope — asserta que el campo tense sea uno de los 5 enums.
  • test_conjugate_cli_person_in_scope — asserta que el campo person sea uno de los 3 enums.
  • test_conjugate_cli_exits_zero_on_valid — código de salida es 0 en éxito.
  • test_conjugate_cli_exits_nonzero_on_no_input — stdin vacío → salida no-cero + error útil.

Restricciones

  • Sin retries. Si la generación falla (error de parseo), la CLI sale con código no-cero. El contrato de la Fase 30 es que esto nunca pasa.
  • Sin prosa en la salida. La CLI saca solo el JSON. Sin cabecera, sin logging en stdout (el logging va a stderr).
  • Sin import de transformers. Usa el MiniGPT hecho a mano.
  • Flag de semilla determinista. --seed N para reproducibilidad. Semilla por defecto = 0 para los smoke tests.

Condiciones de parada

Terminado cuando:

  1. La CLI corre sobre las cinco frases de muestra y produce JSON parseable y válido por esquema.
  2. Los tests del Bloque E pasan.
  3. El README documenta qué frase acertó semánticamente el modelo y cuál falló. (Esto son datos para el ajuste fino (fine-tuning) de la Fase 28 más adelante, no un fallo de la Fase 30.)

Trampas

  • MiniGPT está poco entrenado. El modelo de la Fase 18 puede producir salida semánticamente incorrecta pero parseable. Eso está bien para el DoD de la Fase 30. No te distraigas intentando mejorar la calidad de contenido aquí.
  • Truncamiento de contexto. Si la frase + prompt es mayor que la ventana de contexto del modelo, truncarás. Recorta duro a los últimos N tokens que quepan; documenta en el README.
  • EOS en mitad de un string. El modelo puede querer emitir EOS pronto. Tu máscara debería prohibir EOS hasta que se alcance el estado DONE del esquema. Testea esto.
  • Espacios en blanco al final en la salida CLI. Strip antes de imprimir — los pipes downstream son sensibles.
  • Desambiguar "main verb". "I want to work tomorrow" contiene dos verbos; el esquema pide uno. El prompt debe instruir al modelo a elegir el verbo finito (el que lleva el tense). Documenta la regla.

Cuándo consultar solutions/

Después de que la CLI funcione end-to-end. El interés de la solución está principalmente en cómo se estructura el prompt (una forma menor del arte que no cambia la corrección pero afecta al KL por paso).


Siguiente lab: lab/03-mask-overhead.md.