La función de IA de nutri. convierte una descripción de alimento o una foto de etiqueta en una estimación nutricional estructurada por 100 g, mediante una cadena de respaldo de modelos: gemini-3.8-flash → 3.7 → 3.6 → 3.5 → gemini-2.5-flash → qwen3.6-27b en Groq → mistral-small-latest. Antes de este harness, cambiar un prompt, esquema o modelo era un acto de fe: la salida parecía correcta. Este caso explica la evaluación que sustituyó esa impresión por una compuerta de regresión medida y los problemas que reveló.
La referencia exige disciplina
El conjunto de referencia tiene siete casos. Cada valor esperado viene de USDA FoodData Central —SR Legacy o Foundation— y el fdcId se registra en el archivo del caso. Nunca sale de la memoria de un modelo, precisamente la contaminación que una evaluación debe detectar. Los casos de etiquetas incluyen una transcripción manual completa del empaque. Las fotos permanecen solo en el equipo local —el repositorio es público, las fotos de cocina no— y el runner omite limpiamente un caso si falta su foto, de modo que un clon del repositorio también puede ejecutarse.
Transcribir no es estimar
Una función de puntuación aplica dos regímenes de tolerancia. Leer una etiqueta impresa es transcripción: máximo de 2% o 0.5 unidades. Estimar un alimento crudo es inferencia: ±30% para macronutrientes y ±40% para micronutrientes. Siete campos obligatorios —los cuatro macronutrientes más sodio, potasio y magnesio— deben regresar como números en cada ejecución, se cumpla o no la tolerancia. Y si un caso semilla falla frente a FDC, no se «arregla» ampliando su tolerancia: la falla informa sobre calidad del modelo, se documenta y la línea base captura el estado real.
Contar alucinaciones en lugar de nombrarlas
En la transcripción completa de una etiqueta, cualquier micronutriente que el modelo devuelve sin estar declarado en el empaque es una fabricación. El detalle es que cuáles micronutrientes inventa cambia entre ejecuciones: la identidad es ruido; el conteo es la señal relativamente más estable. Por eso la compuerta registra el número de campos extra y falla si crece más de 1.5× + 3 frente a la línea base.
El determinismo se construye
La cascada de producción mejora disponibilidad, pero contamina una evaluación: un 503 hace responder a otro modelo y la siguiente ejecución marca como regresión una diferencia entre gemini-2.5 y gemini-3.5. El runner fija un solo modelo con temperatura 0, reintenta errores transitorios 5xx y nunca reintenta un 429: la cuota no es una falla transitoria. Incluso así puede fluctuar un campo cercano al límite de tolerancia. La política permite una repetición deliberada; si el fallo persiste, se considera real.
Una línea base por modelo y lo que reveló
La línea base predeterminada gobierna el modelo principal. Otra línea base versionada por separado cubre el último recurso de la cadena, mistral-small-latest, que resultó débil y poco reproducible incluso a temperatura 0: inventa gran parte de los micronutrientes de una etiqueta, lee la columna «por porción» ignorando los valores declarados y devolvió 47 y luego 37 kcal para la misma foto en ejecuciones consecutivas. La respuesta honesta fue reducir esa línea base a una prueba básica de funcionamiento —¿vive la ruta Mistral?, ¿sigue funcionando la traducción de esquema Gemini→Mistral?— en lugar de usarla como compuerta bloqueante. Una evaluación cuyas falsas alarmas se terminan ignorando es peor que no tenerla.
Las líneas base registradas concretan la diferencia. Campos cuenta valores esperados que regresaron dentro de tolerancia. Inventados cuenta micronutrientes devueltos fuera de los declarados en el empaque —solo tiene sentido en casos de etiqueta; la compuerta sigue el crecimiento frente a la línea base, no exige cero—:
| Caso | Modalidad | gemini-3.6-flash campos · inventados |
gemini-3.5-flash campos · inventados |
mistral-small-latest campos · inventados |
|---|---|---|---|---|
| gomitas-magnesio | etiqueta | 7/8 · 0 | 8/8 · 4 | 2/8 · 104 |
| huevo-gallinita | etiqueta | 12/12 · 0 | 12/12 · 70 | 6/12 · 100 |
| leche-deslactosada | etiqueta | 15/15 · 2 | 15/15 · 3 | 10/15 · 97 |
| miel-aguacate | etiqueta | 12/12 · 19 | 12/12 · 8 | 10/12 · 90 |
| huevo-crudo | estimación | 8/8 · — | 8/8 · — | 8/8 · — |
| manzana-fuji | estimación | 8/8 · — | 8/8 · — | 7/8 · — |
| tortilla-maiz | estimación | 8/8 · — | 8/8 · — | 0/8 (falló la verificación de modalidad) · — |
Los modelos Gemini Flash devuelven prácticamente todos los campos esperados dentro de tolerancia; el modelo de último recurso fabrica la mayoría de los micronutrientes en cada etiqueta. Esa tabla justifica relegarlo a una prueba básica de funcionamiento.
Actualización: la evaluación fue útil el día del lanzamiento
Google publicó Gemini 3.6 Flash el 21 de julio de 2026. A la mañana siguiente, ponerlo al principio de la cadena requirió una ejecución fijada —siete solicitudes— contra su propia línea base recién creada. Las cifras permitieron decidir: los micronutrientes inventados en los casos de etiqueta bajaron de 85 con 3.5-flash a 21, y el peor caso —huevo-gallinita, 70 inventados— llegó a cero. La ejecución también reveló concesiones que una revisión por impresión habría pasado por alto: un caso, miel-aguacate, empeoró de 8 a 19 fabricaciones, y 3.6 omite un campo obligatorio pero exento —potasio en una etiqueta que no lo declara— en vez de devolver null. El balance fue favorable y el cambio se entregó en la misma sesión, con las regresiones registradas en la línea base versionada. El día que sale un modelo nuevo, «¿conviene cambiar?» puede resolverse con una medición de quince minutos en vez de un debate.
Actualización: incorporación de un cuarto proveedor en una tarde
El 22 de julio de 2026, la cadena ganó otro eslabón del nivel gratuito: qwen3.6-27b en Groq, entre los modelos Gemini y Mistral. La evaluación decidió qué modelo usar, y la documentación habría inducido a error dos veces. Llama 4 Scout, recomendado para visión en guías de 2026 sobre Groq, ya no estaba en el catálogo de la API en vivo —404—; el único modelo con visión servido allí era qwen3.6-27b. Su primera ejecución real falló en todos los casos con json_validate_failed: consumía el presupuesto de salida en razonamiento oculto y devolvía JSON vacío. Se resolvió fijando reasoning_effort: "none", apropiado además para transcripción determinista.
El harness aprendió algo nuevo: dos errores 429 no significan lo mismo. En Gemini indican cuota diaria; reintentar solo consume solicitudes en una ventana sin salida, así que el runner los trata como fatales. En Groq indican una ventana de tokens por minuto —8 mil TPM medidos en los encabezados de respuesta— y se pueden reintentar treinta segundos después. Mismo código de estado, manejo opuesto según el proveedor.
La nueva línea base en los mismos siete casos: 59 de 72 campos y exactamente un micronutriente inventado entre las cuatro etiquetas, el menor número de fabricaciones de toda la cadena, incluso por debajo de gemini-3.6-flash. Su debilidad es la contraria a la de Mistral: no inventa, pero omite estimaciones obligatorias de potasio y magnesio cuando una etiqueta no los declara. Como cuarto recurso, llamado solo si fallan tres modelos Gemini, esa concesión —omisiones reconocibles en lugar de invenciones seguras de sí mismas— quedó documentada en una línea base, no en una corazonada.
Actualización: cuando dispara la compuerta, arbitrar con una A/B
Más tarde, el mismo 22 de julio, un cambio de tres líneas para mejorar precisión —temperatura 0 en producción como en la evaluación, MEDIA_RESOLUTION_HIGH de Gemini para leer mejor etiquetas y fotos comprimidas a 2048 px en vez de 1024— activó la compuerta de alucinaciones: miel-aguacate pasó de 19 a 66 micronutrientes inventados. El cambio parecía culpable. Una prueba A/B controlada sobre ese caso exacto —misma foto y prompt, con y sin el nuevo ajuste de resolución— devolvió cero fabricaciones en ambas condiciones. La compuerta había detectado variabilidad del modelo, no un efecto del cambio. Incluso con temperatura 0, la salida de visión no es totalmente determinista; el conteo de invenciones puede oscilar de 0 a 66 en un caso. Esto matiza la lección anterior: el conteo es más estable que la identidad, pero también varía. La política de arbitraje quedó así: si la compuerta se activa ante un cambio que difícilmente podría causarlo, una A/B de una sola variable sobre el caso fallido cuesta dos solicitudes y da información; repetir ciegamente los siete casos consume cuota sin aclarar la causa.
Actualización: la cascada creció a siete, la línea base no
Para finales de agosto, el inicio de la cadena había cambiado dos veces: gemini-3.8-flash y gemini-3.7-flash quedaron por encima de 3.6, y qwen3.6-27b de Groq se ubicó antes de Mistral como quinto proveedor. Siete eslabones en total. Estado honesto de la compuerta: solo los modelos con línea base capturada están gobernados por ella. Promover otro modelo mejora disponibilidad de inmediato, pero no incorpora cobertura de evaluación hasta ejecutar su línea base; el nivel gratuito permite 20 solicitudes al día por modelo. Esa brecha queda registrada: la corrección del respaldo es estructural —cualquier error pasa al siguiente eslabón—, mientras que la afirmación de exactitud solo alcanza hasta la última línea base capturada. Nombrar cuál de las dos se tiene diferencia una práctica de evaluación de un mero panel.
El costo forma parte de la especificación
El nivel gratuito permite 20 solicitudes diarias por modelo y una ejecución cuesta siete. Esto definió la herramienta: la evaluación se usa deliberadamente antes y después de un cambio, nunca como paso de CI —por cuota y variabilidad—. La lógica de puntuación es pura, no usa red y sí se prueba en CI con cada push.
La lección de producto: «¿cómo evaluarías esta función?» deja de ser abstracto cuando hay que decidir qué cuenta como referencia, por qué transcripción y estimación requieren tolerancias distintas, cómo controlar alucinaciones que no se repiten igual y cuándo una evaluación debe degradarse honestamente a prueba básica de funcionamiento. El harness está en el repositorio público github.com/vryahn/nutri, en evals/.