Workers AI te da acceso a modelos de ML corriendo en la infraestructura de GPU de Cloudflare, invocables como un binding de Worker. Sin hosting de modelos, sin facturas de GPU, sin infraestructura que administrar. La promesa es atractiva. Esto es lo que se ve en producción.
Qué Estoy Usando
Dos modelos:
@cf/facebook/bart-large-cnn— resume el contenido del post en un abstract de 2-3 oraciones@cf/meta/m2m100-1.2b— traduce posts en inglés al español cuando no existe una traducción humana
Ambos son del tier gratuito. Ambos tienen límites. Ambos requieren una estrategia de caché para ser usables.
BART: El Problema de Latencia en la Primera Visita
BART tarda aproximadamente 1-2 segundos en resumir un post de 500 palabras. En un Worker, esa latencia bloquea la respuesta completa.
La primera vez que alguien visita un post, el Worker obtiene el contenido desde KV, ejecuta BART, renderiza la página con el resumen, y cachea el resultado de vuelta a KV. Las visitas posteriores leen desde KV sin ningún costo de IA.
javascriptaiSummary = await env.POSTS_KV.get(`summary:${slug}`, "text");
if (!aiSummary) {
const r = await env.AI.run("@cf/facebook/bart-large-cnn", {
input_text: content.slice(0, 2000),
max_length: 100,
});
const summary = r.summary || r.text || "";
if (summary) {
aiSummary = summary;
ctx.waitUntil(env.POSTS_KV.put(`summary:${slug}`, summary));
}
}
El await antes de AI.run es intencional — el primer visitante ve el resumen en la misma carga de página, no en un recargo. La escritura en KV usa ctx.waitUntil porque ya tenemos el valor y no necesitamos bloquear en la escritura.
El content.slice(0, 2000) trunca la entrada. BART tiene un límite de tokens, y enviar un post de 3000 palabras completo causa errores. 2000 caracteres cubre la mayor parte de una introducción y primera sección — suficiente para un resumen útil.
M2M100: Bueno con Texto Corto, Poco Fiable con Texto Largo
El modelo de traducción es m2m100-1.2b, un modelo multilingüe de 1.2 mil millones de parámetros. Maneja bien los posts cortos a medianos. Para posts más largos (1500+ palabras), la calidad de salida se degrada — las oraciones empiezan a desviarse, los términos técnicos se maltraducen.
La mitigación: truncar a 5000 caracteres y presentar el resultado como "traducción IA" en lugar de una traducción humana. Los usuarios saben que obtienen una aproximación.
javascriptconst result = await env.AI.run("@cf/meta/m2m100-1.2b", {
text: content.slice(0, 5000),
source_lang: "en",
target_lang: "es",
});
Si existe una traducción humana (una clave post:<slug>-es en KV), tiene prioridad. La traducción IA es un fallback para posts donde aún no he escrito la versión en español.
Los Límites de Rate Son Reales
El tier gratuito tiene límites por modelo. Los he alcanzado durante pruebas al disparar generación de IA en múltiples posts rápidamente. En producción con tráfico orgánico, un post por sesión, y caché en KV, no he alcanzado los límites.
El try/catch alrededor de todas las llamadas a IA no es opcional:
javascripttry {
const r = await env.AI.run(...);
// usar resultado
} catch(e) {
// fallar silenciosamente — la página igual carga sin resumen
}
Un error de rate limit de Workers AI lanza una excepción. Sin el catch, haría que la petición completa de la página devolviera un 500. Con él, la página carga normalmente y el bloque de resumen muestra un placeholder "generando...".
La Estrategia de Caché
Ambos modelos usan el mismo patrón: verificar KV primero, generar en miss, escribir de vuelta a KV.
Las lecturas de KV toman ~5ms. Los runs de IA toman 500ms-2000ms. La proporción significa que después de la primera generación, el costo es despreciable.
Para los resúmenes de BART, la clave de caché es summary:<slug>. Para las traducciones, es post:<slug>-es-ai (separada de las traducciones humanas en post:<slug>-es).
No hay TTL en el caché. Un resumen generado una vez es válido indefinidamente — el contenido del post no cambia. Si edito un post y quiero un resumen nuevo, borro la clave de KV manualmente.
Qué Haría Diferente
Pre-generar resúmenes al publicar. Ahora mismo el primer visitante paga la latencia de 1-2s. El script de publicación podría ejecutar BART para cada post y sembrar el caché de KV durante CI. El primer visitante vería un resumen cacheado como todos los demás.
Streaming para traducciones. El endpoint de traducción actualmente bloquea hasta que la traducción completa esté lista. Para posts largos, son 3-5 segundos. Una respuesta en streaming que envía chunks traducidos conforme llegan se sentiría mucho más rápida.
Ambas son mejoras que no he hecho aún porque el comportamiento actual es aceptable. La latencia de primera visita para los resúmenes es invisible para la mayoría de usuarios — están leyendo el contenido del post mientras BART trabaja.