Skip to content

English · Español

Lab 00 — Curar la KB de 50 chunks de reglas de gramática

Una base de conocimiento de 50 chunks, escritos a mano, que cubren los 20 verbos × 5 tiempos × 3 personas en inglés y español. Cada chunk tiene un chunk_id, un cuerpo de 1-3 frases, etiquetas (tense, person, verb, regularity, language) y citas a referencias. Esta es la materia prima del retriever.

Objetivo

Construir data/kb/grammar-rules/: una base de conocimiento JSONL curada de ~50 chunks que cubre el alcance gramatical §A13, con metadatos estructurados para filtrado y evaluación. La KB debe ser autocontenida — toda consulta del eval set debe poder responderse con estos chunks.

Setup

  • Trabajo puramente de datos. Sin PyTorch, sin modelos.
  • La rejilla §A13: 20 verbos (12 regulares + 8 irregulares) × 5 tiempos × 3 personas × 2 idiomas.
  • El corpus de la Fase 12 ya existe (las frases de ejemplo); este lab produce las reglas.

El esquema de chunk

data/kb/grammar-rules/chunks.jsonl — una línea por chunk:

{
  "chunk_id": "en-pres-3sg-regular-s-rule-001",
  "language": "en",
  "topic": "tense_rule",
  "tense": "present_simple",
  "person": "3sg",
  "regularity": "regular",
  "verbs": ["work", "play", "walk", "talk", "listen",
            "watch", "study", "finish", "start", "look",
            "want", "like"],
  "title": "Present simple, 3rd-person singular: add -s",
  "body": "In English present simple, the 3rd-person singular form of a regular verb adds -s to the base form. For example: 'She works at the office.' / 'He walks home.' Verbs ending in -y after a consonant change y → ies (study → studies); verbs ending in -sh, -ch, -ss, -x, -o add -es (watch → watches, finish → finishes).",
  "examples": [
    {"en": "She works at the office.", "es": "Ella trabaja en la oficina."},
    {"en": "He studies every day.", "es": "Él estudia todos los días."}
  ],
  "source": "hand",
  "references": ["Murphy 2019 §3", "RAE Diccionario panhispánico §5"]
}

Campos requeridos:

  • chunk_id — único, estable, con prefijo descriptivo (ver convención de nombres más abajo).
  • languageen | es | bilingual.
  • topictense_rule | irregular_form | auxiliary | agreement | time_marker | spanish_equivalent.
  • tense — uno de los 5 tiempos, o null para chunks transversales.
  • person1sg | 2sg | 3sg | null para reglas que cruzan personas.
  • regularityregular | irregular | both.
  • verbs — lista de los verbos a los que se aplica este chunk (subconjunto de los 20).
  • title — resumen de una línea, ≤ 80 caracteres.
  • body — 1-3 frases, ≤ 600 caracteres. Autocontenido — legible sin contexto.

Campos opcionales (recomendados):

  • examples — lista de frases de ejemplo pareadas EN/ES.
  • sourcehand | derived.
  • references — lista de referencias a libros de gramática / diccionarios para trazabilidad.

Convención de nombres para chunk_id

Patrón: <lang>-<tense>-<person>-<regularity>-<topic>-<NNN>.

Ejemplos: - en-pres-3sg-regular-s-rule-001 - en-past-all-irregular-go-001 - es-pres-3sg-regular-er-conj-001 - bilingual-past-1sg-pair-001

Separado por guiones, minúsculas. El prefijo permite filtrar chunks con grep durante depuración.

Objetivos de cobertura

Categoría Chunks mínimos
Reglas de tiempo en inglés (5 tiempos × 3 personas × 2 regularidades) ≥ 20
Formas irregulares (8 verbos × 3-4 formas cada uno) ≥ 12
Equivalentes en español (reglas de traducción por tiempo) ≥ 10
Pares bilingües / contrastivos ≥ 5
Marcadores temporales (yesterday → pasado, tomorrow → futuro, etc.) ≥ 3
Total ≥ 50

Tareas

Parte A — Escribir la matriz de cobertura

Haz una hoja de cálculo (o simplemente una tabla markdown) con filas = celdas (tense, person, regularity, language). Marca cada celda al escribir un chunk para ella. Apunta a ~50 chunks en total; una cobertura más profunda en celdas comunes (present-simple-3sg-regular tiene muchas reglas relacionadas) está bien.

Parte B — Escribir 50+ chunks

Para cada chunk:

  1. Un título que diga cuál es la regla en 80 caracteres o menos.
  2. Cuerpo de 1-3 frases que enseñen la regla a un estudiante que no la conoce. Incluye la regla, un ejemplo y el caso límite si aplica.
  3. Al menos 1-2 ejemplos en la lista examples.
  4. Metadatos completos (no te saltes el campo regularity ni cuando sea "n/a" — usa both).

Guía de estilo:

  • Evita la jerga: "3rd-person singular" no "3PS"; "past simple" no "preterite-mode".
  • Una regla por chunk. Si la regla tiene excepciones, esas van en chunks separados con sus propios ids y un cross-link claro en references.
  • Los chunks bilingües pareados (donde la regla compara explícitamente EN y ES) viven con language: bilingual.

Parte C — Construir el loader

src/minirag/chunk.py:

from dataclasses import dataclass, field
from pathlib import Path
import json

ALLOWED_TENSES = {"infinitive", "present_simple", "past_simple",
                  "past_participle", "future", None}
ALLOWED_PERSONS = {"1sg", "2sg", "3sg", None}
ALLOWED_REGULARITY = {"regular", "irregular", "both"}
ALLOWED_LANGUAGES = {"en", "es", "bilingual"}
ALLOWED_TOPICS = {"tense_rule", "irregular_form", "auxiliary",
                  "agreement", "time_marker", "spanish_equivalent"}

@dataclass(frozen=True)
class Chunk:
    chunk_id: str
    language: str
    topic: str
    tense: str | None
    person: str | None
    regularity: str
    verbs: tuple[str, ...]
    title: str
    body: str
    examples: tuple[dict, ...] = field(default_factory=tuple)
    source: str = "hand"
    references: tuple[str, ...] = field(default_factory=tuple)

def load_chunks(path: Path) -> list[Chunk]: ...

def validate_chunks(chunks: list[Chunk]) -> list[str]:
    """Returns list of errors; [] = pass."""
    ...
  • load_chunks parsea JSONL → dataclasses Chunk.
  • validate_chunks verifica:
  • corrección del esquema, campos requeridos presentes.
  • unicidad de chunk_id.
  • valores de campos dentro de los conjuntos permitidos.
  • verbs ⊂ la lista de 20 verbos §A13.
  • body es 1-3 frases (cuenta . ? !, espera ≤ 3).
  • title ≤ 80 caracteres; body ≤ 600 caracteres.
  • se cumplen los mínimos de la matriz de cobertura.

Parte D — Tests en tests/minirag/test_chunk.py

  1. test_load_clean_kb — parsea el fichero semilla, cuenta ≥ 50.
  2. test_validate_clean_kbvalidate_chunks devuelve [].
  3. test_rejects_unknown_tense — un chunk con tense="conditional" se rechaza.
  4. test_rejects_unknown_verb — un chunk con verbs=["run"] (no en §A13) se rechaza.
  5. test_coverage_minima — una KB recortada sin los chunks en español se rechaza con un error de cobertura.
  6. test_chunk_id_unique — id duplicado rechazado.

Entregables

  • data/kb/grammar-rules/chunks.jsonl — ≥ 50 chunks.
  • data/kb/grammar-rules/COVERAGE.md — la matriz de cobertura (qué celdas están pobladas).
  • src/minirag/chunk.py — esquema + loader.
  • tests/minirag/test_chunk.py — seis tests pasando.
  • data/kb/grammar-rules/manifest.json — versión, recuento, semilla.

Aceptación

  • pytest tests/minirag/test_chunk.py -v pasa los seis.
  • La KB tiene ≥ 50 chunks que cubren la matriz según la tabla anterior.
  • Ningún chunk tiene body > 600 caracteres o title > 80 caracteres.
  • COVERAGE.md muestra qué celdas están pobladas y cuántos chunks por celda.

Trampas

  • Chunks que se parafrasean entre sí. Dos chunks que dicen "add -s for 3sg" con ejemplos distintos está bien; dos chunks que dicen exactamente lo mismo con otras palabras hinchan la KB sin añadir señal. Apunta a reglas distintas por chunk.
  • Chunks demasiado largos. Un chunk de 3 párrafos no recupera bien — los embedders trabajan mejor sobre unidades cohesionadas de 1-3 frases. Pártelo si superas el tope de 600 caracteres.
  • Olvidar null para reglas transversales. Una regla como "the past-participle form is used after have" aplica a todas las personas. No elijas una — usa person: null.
  • Fuga de la curación a mano en el eval. El eval set del Lab 01 no debería poder derivarse literalmente de un solo chunk. La KB es la respuesta; las consultas deben parafrasear la respuesta. Si una consulta es literalmente el título de un chunk, no está testando retrieval — está testando coincidencia de cadena.
  • Saltarse el español. La mitad del alcance §A13 es español. Una KB solo en EN hace triviales los labs siguientes.

Stretch

  • Añade 10 chunks adversariales: reglas casi correctas pero con un error sutil o una convención obsoleta. Márcalos source: adversarial. Se usan en el eval de faithfulness del Lab 03 (un reader fiel no cita un chunk adversarial como autoridad).
  • Traduce cada chunk en inglés a español (language: es) preservando los ejemplos. Duplica la KB y ejercita el retrieval bilingüe.

Siguiente lab: lab/01-bi-encoder-baseline.md.