Inteligencia Artificial 9 min de lectura 1917 palabras

Doce años de recetas y una despensa que nadie podía consultar

EN
Doce años de recetas y una despensa que nadie podía consultar

Migue es Miguel Ángel López Pascual, cocinero sevillano y buen amigo. Desde 2014 publica recetas de cocina tradicional andaluza en lachozademigue.com: solomillo al whisky, espinacas con garbanzos, salmorejo, croquetas. Doce años después son 1.388 entradas escritas a mano, una por una, a razón de dos por semana.

El problema no era el contenido. El contenido es excelente y es suyo. El problema era que ese archivo se había vuelto imposible de consultar: una plantilla por defecto de WordPress, Live Composer montando la portada, 91 categorías con la jerarquía rota y 775 etiquetas. Si querías encontrar qué hacer con unas ñoras que te sobraban, no había manera.

Me ofrecí a echarle una mano y aproveché para probar dos cosas que tenía ganas de mezclar: Claude Code para el rediseño y LM Studio en local para el trabajo pesado sobre el contenido. Esto es lo que salió.

Lo primero fue mirar, no diseñar

Antes de tocar una línea de CSS hice un recuento completo de las 1.388 entradas por la API REST. Los números cambiaron el diseño entero:

DatoConsecuencia
Párrafos planos, sin H2/H3 ni listasEl diseño se juega todo en la tipografía del cuerpo
Solo 13 imágenes destacadas de 1.388Prohibido depender de la foto en los listados
91 categorías y 775 etiquetas, jerarquía rotaLa navegación no puede ser un menú de categorías
Doce años de archivo, ~2 entradas/semanaEs un recetario consultable, no un blog cronológico

Ese segundo dato es el que manda. Trece fotos destacadas para 1.388 recetas significa que cualquier diseño de food blog moderno —rejilla de tarjetas con foto grande, hero fotográfico, todo eso— era sencillamente imposible. No hay material.

Así que el concepto fue el contrario: el cuaderno de cocina. Papel hueso, tinta, tipografía con carácter, y una regla que ordena todo lo demás: la ausencia de foto no es un hueco, es el diseño. Las tarjetas sin imagen conviven con las que la tienen y pesan visualmente lo mismo.

Es la misma lección que me llevé rediseñando este blog hace unos días: el diseño sale del contenido que hay, no del que te gustaría tener.

De párrafos sueltos a recetas de verdad

Una receta en el WordPress de Migue era esto: un párrafo de introducción, un párrafo con todos los ingredientes en texto corrido (500 gr de boquerones, 200 ml de vinagre…) y varios párrafos de elaboración sin numerar. Para un lector, perfecto. Para un buscador o para cualquier cosa que quiera entender la receta, opaco: sin Recipe, sin recipeIngredient, sin nada.

Migrar 1.388 entradas a bloques estructurados con schema Recipe es el clásico trabajo que da pánico, porque un error masivo te destroza doce años de contenido ajeno. Así que el proceso se montó con tres reglas:

  1. Nunca se escribe sin informe previo. El informe analiza y propone; no toca la base de datos.
  2. El aplicador hace simulacro por defecto. Solo escribe si le pasas explícitamente en-serio.
  3. Copia de cada entrada antes de tocarla. Todo reversible, receta a receta.

Con eso, la migración se hizo en tandas de 50, revisando el CSV de cada tanda antes de aplicarla. El informe clasificaba cada entrada en propuesta, revisar, sin_reconocer o no_es_receta, y las de estado revisar traían el motivo concreto: «Muy pocos ingredientes (2)», «Un ingrediente es sospechosamente largo».

Acabaron migradas 1.358. Las cuatro que el parser no reconoció se hicieron a mano, que es exactamente lo que debe pasar: la máquina se ocupa del 99,7 % y tú del resto.

El experimento: extraer ingredientes con un modelo local

Aquí viene la parte que quería probar de verdad.

La idea era poder navegar el recetario por ingredientes: entrar en /ingrediente/comino/ y ver las recetas que lo llevan. En WordPress eso es una taxonomía propia — un vocabulario con URL, archivo y contador, igual que las categorías pero con palabras mías.

El problema es poblarla. Hay que leer 1.388 listas de ingredientes escritas a mano durante doce años y sacar de cada línea el ingrediente limpio: de 2 dientes de ajo sale ajo, de 500 gr de tomate maduro sale tomate. Eso son 11.111 líneas.

Podría haberlo hecho con expresiones regulares, y de hecho el extractor de cantidades y unidades acierta el 99,8 % sin IA ninguna. Pero normalizar el resto —decidir que pimienta molida, pimientas negras y pimienta negra molida son la misma cosa— es donde un LLM se gana el sueldo.

Lo monté con LM Studio en local, sin nube. Y antes de lanzarlo contra 1.388 recetas, comparé modelos sobre las mismas cinco recetas.

Para extraer, el modelo pequeño vale

Comparando qwen3-4b con llama-3.2-3b, los dos aciertan prácticamente lo mismo. Las diferencias son de matiz:

Recetaqwen3-4bllama-3.2-3b
Manitas con garbanzosmanita, laurel, clavomanita de cerdo, hoja de laurel, clavo de olor
Arroz con bogavantebrandybrandi
Coliflor rebozadahuevohuevos

Ninguno se inventa ingredientes. Ninguno se deja los importantes. Las diferencias son de forma —singular contra plural, una errata ortográfica— y eso lo arregla la normalización posterior, no un modelo más grande.

Extraer datos de un texto que ya los contiene es una tarea fácil, y ahí un modelo de 3 o 4B en tu portátil es suficiente. Tres horas de LLM local, 18 tandas de 100 recetas, sin un solo fallo del proceso.

Para escribir, no

Cuando pasé a la siguiente fase —escribir un texto breve explicando cada ingrediente, imitando el estilo de Migue— el mismo modelo se cayó con estrépito:

«El bogavante es una planta de la familia de las rubiáceas»

«Las ñoras son plantas perennes de hoja ancha»

Falso y creíble a la vez, que es la peor combinación posible. Probé con Haiku y mejoró en los hechos difíciles —bogavante como crustáceo, ñora como pimiento seco— pero fallaba la redacción: «se deseca y salazón», «el tocino se pueden conservar», y situaba el bacalao «en Castilla».

En un texto de 60 palabras que va firmado por un cocinero sevillano, esos fallos se ven a un kilómetro. Los textos acabaron escritos con Sonnet, y las reglas del prompt salieron directamente de esas dos pruebas fallidas: prohibir atribuir un ingrediente a una región, exigir concordancia gramatical, y omitir un dato antes que inventarlo.

La lección es más útil que cualquier ranking de modelos: la talla del modelo la decide la tarea, no el proyecto. En el mismo trabajo conviven un 4B local haciendo extracción durante tres horas y un modelo grande escribiendo 50 textos breves. Usar el grande para todo habría sido tirar dinero; usar el pequeño para todo habría publicado que el bogavante es una planta.

La curva que dice cuándo has terminado

Esto no lo esperaba y es mi hallazgo favorito. Anotando cuántos términos nuevos aparecían en cada tanda de 100 recetas:

111 → 81 → 49 → 44 → 38 → 41 → 32 → 43 → 23 → 33
 → 21 → 26 → 24 → 18 → 26 → 18 → 26 → 1

De 111 términos nuevos por cada 100 recetas, a uno. El vocabulario de Migue es finito y se agota. Doce años de cocina tradicional andaluza caben en unos 900 ingredientes, y a partir de la receta 1.200 ya casi no aparece nada que no hayas visto.

Esa curva es una señal de parada objetiva. Sabes que has terminado no porque se acaben las recetas, sino porque el vocabulario ha convergido.

El reparto también fue revelador: 34 términos cubren la mitad del recetario (sal, aceite de oliva, ajo, cebolla…), y 437 términos aparecen en una sola receta. Esa cola larga no es ruido: burrata, cochinillo, queso gamoneu, sesos de ternera. Un ingrediente con una sola receta detrás es justo lo que hoy nadie encuentra.

La sal no es un ingrediente útil

Al terminar, la sal aparecía en 1.073 recetas: el 79 % del recetario. Como filtro de navegación no distingue nada — pinchar en «Sal» te devuelve casi todo el sitio.

Se borró el término. Con matices: se conservan flor de sal, sal gorda y sal marina, que sí dicen algo del plato, y el texto de las recetas no se toca — la sal sigue en la lista de ingredientes de cada una, porque es lo que escribió Migue. Lo que desaparece es el término de la taxonomía.

Es un buen recordatorio de que un dato correcto puede ser inútil. La sal estaba bien extraída; simplemente no servía para navegar.

Los fallos que parecían del modelo

Tres cosas que aprendí a base de perder tiempo:

Las líneas van separadas, no aplanadas. Pasar la receta como texto corrido hacía perder ingredientes de forma determinista. El mismo modelo, con las líneas separadas, no fallaba.

Las erratas del modelo hay que absorberlas, no evitarlas. El modelo escribía ingrediento por ingrediente y champinón por champiñón. En lugar de pelear con el prompt, el código lee los campos por prefijo y fusiona por slug quedándose con la grafía que lleva más tildes. Más barato y más robusto.

Casi todo lo que parecía fallo del modelo era del código de alrededor: el parser, el recuento, o una lista de referencia que yo había escrito de memoria y estaba mal. Ante un resultado raro, mirar primero la respuesta en crudo del modelo. Casi siempre estaba bien.

Un efecto secundario: el censo destapó recetas rotas

Al extraer los ingredientes aparecieron líneas que no eran ingredientes:

mantequilla 500 gr de fiambre surtido pollo
hr de patatas
mg de nata
gaseosa tambien nos servira agua con gas o sifon

No era ruido del extractor: eran recetas que se estaban mostrando mal en la web desde la migración, que había unido en una sola línea lo que el texto plano no separaba bien. Entre 40 y 80 casos.

Me gusta esto porque es un patrón que se repite: procesar sistemáticamente un archivo viejo te encuentra problemas que llevaban años ahí. La taxonomía era la excusa; arreglar esas recetas es una mejora por sí sola.

Dónde está ahora

Recetas con schema Recipe1.358
Ingredientes en la taxonomía749
Recetas enlazadas1.360 (100 %)
Media de ingredientes por receta7,9
Plugins activos2 (eran 5, con Live Composer y una caché de un hosting que ya no usa)

La web tiene ahora un índice de ingredientes navegable, cada receta enlaza los suyos, y las 91 categorías se limpiaron hasta 89 con jerarquía coherente y redirecciones 301 para no romper las URLs viejas.

Quedan cosas. Unas 36 recetas tienen la lista de ingredientes mal formada y hay que repasarlas a mano. Los textos de los ingredientes van por el 62 %. Y hay errores sueltos en la taxonomía, que Migue irá corrigiendo — porque lo relevante del sitio no es el theme ni la taxonomía, son las recetas, y esas las ha cocinado y escrito él durante doce años.

Lo que me llevo

La parte de IA fue la fácil. Extraer ingredientes con un modelo local funcionó a la primera y costó tres horas de portátil. Lo que decidió el resultado fue el diccionario: agrupar variantes, decidir que champiñones portobello cuelga de champiñón, mirar la cola larga a ojo para separar los ingredientes legítimos del ruido. Ahí no hay modelo que valga, hay criterio.

Y el criterio venía de conocer el contenido. Saber que la sal no sirve como filtro, que las fichas que Migue escribió a mano son mejores que cualquier texto generado y había que recuperarlas, que las trece fotos destacadas condicionaban el diseño entero. Nada de eso sale de un prompt: sale de sentarse a mirar qué hay antes de empezar a construir.

El código fue rápido. Lo demás, no.