English · Español
Lab 01 — Escribe scripts/gen_corpus.py¶
Objetivo: implementa el generador de corpus. Enumera las 20 × 6 × 3 = 360 celdas de formas correctas con pares en español, más emite mis-conjugaciones de la taxonomía cerrada. La salida es
data/raw/all_rows.jsonl+ un manifest parcial.Tiempo estimado: 4–6 horas.
Prerrequisito: lab 00 commiteado (
data/corpus_spec.md).
Lo que produces¶
scripts/gen_corpus.py— punto de entrada. Lee la tabla de verbos desdesrc/minicorpus/verb_table.py. Emitedata/raw/all_rows.jsonl.src/minicorpus/__init__.py— re-exports.src/minicorpus/verb_table.py— la tabla de 20 verbos como estructuras de datos Python (sin lógica).src/minicorpus/conjugate.py— funciones puras:conjugate_english(verb, tense, person, table) -> stry el equivalente en español.src/minicorpus/mis_conjugate.py— dada una forma correcta, produce una forma mis-conjugada para un tipo dado.tests/test_conjugate.py— tests unitarios sobre un puñado de tuplas (verbo, tiempo, persona).
El generador no es un script monolítico — es un paquete pequeño. El script orquesta; el paquete conjuga.
TODOs¶
Bloque A — src/minicorpus/verb_table.py¶
- Define
VERB_TABLE: dict[str, VerbEntry]con una entrada por cada uno de los 20 verbos. -
VerbEntryes un frozen dataclass con:english_lemma,spanish_lemma,english_regularity,spanish_regularity,english_past,english_participle,spanish_irregular_forms: dict[(tense, person), str](sparse — solo rellena celdas irregulares; las celdas regulares se computan desde el lema). - Para cada uno de los 8 irregulares en inglés, puebla
english_pastyenglish_participle. - Para cada forma irregular en español, puebla
spanish_irregular_forms. - Añade
SPANISH_PRONOUNS: dict[person, str]mapeando1sg → "yo",2sg → "tú",3sg → "él". - Añade
ENGLISH_PRONOUNS: dict[person, str]mapeando1sg → "I",2sg → "you",3sg → "he".
Bloque B — src/minicorpus/conjugate.py¶
-
conjugate_english(verb_lemma: str, tense: str, person: str, table=VERB_TABLE) -> str. Función pura. Busca la entrada, computa la forma superficial según las reglas endata/corpus_spec.md. - Maneja las 6 formas superficiales de tiempo:
infinitive:to <lemma>(o solo<lemma>— escoge la convención de la spec; documenta).present_simple:<pronoun> <lemma>para1sg/2sg;<pronoun> <lemma+s>para3sg. Maneja-espara verbos que terminan en-sh,-ch,-s,-x,-o(watch → watches,study → studiesvía-y → -ies).past_simple: regulares obtienen<lemma+ed>(con-y → -iedparastudy); irregulares usanentry.english_past. El past debetiene variantes por persona (was/were/was).past_participle: regulares igual que past simple; irregulares usanentry.english_participle. Desnudo (sin pronombre).future_will:<pronoun> will <lemma>.future_going_to:<pronoun> <to-be-conjugated-for-person> going to <lemma>. P. ej.,I am going to work,you are going to work,he is going to work.-
conjugate_spanish(verb_lemma: str, tense: str, person: str, table=VERB_TABLE) -> str. Misma idea para español. Maneja patrones regulares-ar/-er/-ir; busca irregulares desdeentry.spanish_irregular_forms. - Caso especial
like → gustarcon sintaxis invertida: en lugar de<yo/tú/él> <gustar-conjugation>, emite<me/te/le> <gusta>(3sg siempre) — documenta esta excepción en la función.
Bloque C — src/minicorpus/mis_conjugate.py¶
- Para cada tipo de mis-conjugación, define una función
apply_<type>(correct_form, verb_entry, tense, person) -> Optional[str]. - Cada función:
- Retorna
Nonesi el tipo no aplica a esta celda (p. ej.,missing_third_person_sretornaNonepara celdas no-3sg, no-present-simple). - De lo contrario, retorna la forma desviante.
- Las 6 funciones de mis-conjugación:
apply_missing_third_person_s(form, entry, tense, person)— quita la-sde 3sg present-simple.he works → he work.apply_overregularization_past(form, entry, tense, person)— para verbos irregulares enpast_simpleopast_participle, genera la forma "qué pasaría si fuera regular".he went → he goed.eaten → eated.apply_wrong_aux_will_with_to(form, entry, tense, person)— parafuture_will, insertatotraswill.he will work → he will to work.apply_wrong_aux_going_to_missing_ing(form, entry, tense, person)— parafuture_going_to, cambiagoingporgo.I am going to work → I am go to work.apply_subject_verb_disagreement(form, entry, tense, person)— forma auxiliar incorrecta. Parayou have worked, cambia ayou has worked. Para(you, be, past_simple)you were → you was.-
apply_bare_participle_missing_aux(form, entry, tense, person)— parapast_participle, prepende un pronombre incorrecto + sin aux.gone → he gone(la forma "correcta" esperada seríahe has gone). -
Helper
eligible_mis_conjugations(entry, tense, person) -> list[str]retorna los nombres de tipos que podrían aplicar a esta celda.
Bloque D — scripts/gen_corpus.py¶
- CLI:
argparsecon--seed(default 42),--output(defaultdata/raw/). - Llama
seed_everything(args.seed). - Enumera las 20 verbos × 6 formas superficiales de tiempo × 3 personas = 360 celdas.
- Para cada celda, emite una fila correct con
text,spanish, todos los campos del esquema,label="correct",mis_conjugation_type=null,correct_form=null. - Dentro de cada celda, consulta
eligible_mis_conjugations; si no está vacío, selecciona aleatoriamente 0–2 (condicionado por un coin flip basado en RNG) y emite cada una como una filamis_conjugatedconcorrect_formpoblado. - Asigna
idsecuencial (con zero-padding a 4 dígitos). - Computa
fingerprint = sha256(NFC(text))por fila. - Verifica que la fila pase el JSONSchema antes de escribir (verificación ligera en-proceso; el validador completo es lab 02).
- Escribe a
data/raw/all_rows.jsonl. - Emite un manifest parcial (
data/raw/MANIFEST_partial.json) con seed, sellos de versión y conteo total de filas.
Bloque E — tests/test_conjugate.py¶
- Un test por cada una de las 6 formas superficiales de tiempo × 1 verbo regular × 3 personas.
- Un test por cada una de las 6 formas superficiales de tiempo × 1 verbo irregular (
go) × 3 personas. - Test de caso especial:
(like, present_simple, 1sg)retornaI like(inglés) yme gusta(español). - Test de caso especial:
(be, past_simple, 1sg)retornaI was;(be, past_simple, 2sg)retornayou were. - Test de caso especial:
(study, present_simple, 3sg)retornahe studies. - Test de caso especial:
(watch, present_simple, 3sg)retornahe watches. - Tests de mis-conjugación: al menos uno por cada uno de los 6 tipos, asegurando que la forma desviante sea lo que la spec dice.
-
mypy --strict src/minicorpus/limpio. -
rufflimpio.
Bloque F — print de cordura¶
- En la parte inferior del script (o en un notebook separado en
experiments/12-corpus-generation/), imprime: - Total de filas generadas.
- Cobertura por celda (esperar 1 correcta + 0–2 mis-conjugadas por celda).
- Muestrea 10 filas aleatorias para revisión humana.
- Total de filas mis-conjugadas por tipo.
Restricciones¶
- Python puro. No se necesita
numpy(el corpus es texto estructurado, no numérico). mypy --strictlimpio.rufflimpio.banditlimpio.- Determinismo asegurado vía la fixture de semilla en
tests/conftest.py. - Sin lógica de conjugación impulsada por regex. Usa operaciones de string explícitas + lookups de tabla. Los regex para morfología son difíciles de depurar.
- NFC normaliza cada campo
textyspanishemitido. Usaunicodedata.normalize('NFC', s).
Condiciones de parada¶
Hecho cuando:
- Los cinco archivos Python commiteados bajo
src/minicorpus/yscripts/. - Todos los tests pasan;
pytest -q tests/test_conjugate.pyestá verde. mypy --strict src/minicorpus/limpio.python scripts/gen_corpus.py --seed 42producedata/raw/all_rows.jsonlcon al menos 460 filas (360 correctas + ~100–200 mis-conjugadas).- El print de cordura de muestra se ve correcto a ojos de Borja — sin español raro, sin typos en inglés.
Escollos¶
study → studiesvsstudy → studys. La regla-y → -iespara verbos terminados en consonante +ynecesita manejo explícito.watch → watches,finish → finishes. Verbos terminados en-ch,-sh,-s,-x,-zañaden-es, no-s.bees únicamente irregular en present simple.I am,you are,he is. No intentes derivarlos de una regla.- Cambios de stem en español.
querer → quiero(e → ie),empezar → empiezo. Enumera, no derives por regla. - Inversión de sintaxis
like → gustar. El sujeto entero se convierte en objeto indirecto. Mejor caso-especiallikeenconjugate_spanish. - Mis-conjugación que es realmente correcta.
apply_missing_third_person_s("I work", entry, "present_simple", "1sg")debería retornarNone— no hay-sque quitar paraI work. Fácil olvidar el check de elegibilidad. - Bytes vs codepoints en NFC. Siempre llama a
unicodedata.normalize('NFC', s)sobre strings de Python (no bytes). No mezcles niveles. - Capitalización de
I. El pronombreIen inglés es mayúscula; todo lo demás en el corpus es minúscula. No pongas en minúscula el string completo al final.
Pista de último recurso¶
Si llevas 5 horas y la lógica de conjugación es un desastre: simplifica enumerando más y computando menos. La tabla de verbos puede tener todas las 360 formas hardcodeadas si escribir la regla es demasiado doloroso. El tradeoff reglas-vs-lookup favorece a lookup para nuestra escala.
Cuándo consultar solutions/¶
Tras que todos los tests pasen. Solución: solutions/01-implement-generator-ref.md (apertura de fase). La referencia contiene la tabla de verbos completa, las funciones de conjugación y los handlers de mis-conjugación.
Siguiente lab: lab/02-validate-and-split.md.