Task APIs: Escribir, Resumir y Corregir con Precisión

La Prompt API es extremadamente flexible: puedes hacer prácticamente cualquier tarea con el prompt correcto. Pero esa flexibilidad tiene un costo: modelos más grandes, mayor consumo de recursos, y la necesidad de gestionar tokens, contexto y prompts cuidadosamente.
Para tareas específicas y bien definidas, Chrome ofrece Task APIs: modelos afinados (fine-tuned) que sacrifican flexibilidad por eficiencia, precisión y simplicidad de uso.
¿Por qué Task APIs en lugar de Prompt API?
Las Task APIs están optimizadas para casos de uso concretos. La diferencia fundamental es que mientras la Prompt API es como una conversación abierta donde mantienes un historial completo, las Task APIs son llamadas stateless: ejecutas una operación, obtienes el resultado, y no hay contexto persistente.
| Aspecto | Prompt API | Task APIs |
|---|---|---|
| Tamaño del modelo | Modelo general completo | Versiones más ligeras/cuantizadas |
| Calidad | Depende del prompt engineering | Afinadas para la tarea específica |
| API | Requiere diseño de prompts | Parámetros declarativos simples |
| Gestión de estado | Conversaciones multi-turno (stateful) | Stateless (sin historial) |
| Memoria | Alta (mantiene contexto) | Baja (libera después de cada call) |
| Latencia | Variable según contexto | Predecible y optimizada |
| Uso típico | Chatbots, RAG, tareas complejas | Resumen, reescritura, corrección |
Regla de oro: Si existe una Task API para tu necesidad, úsala. Ahorrarás recursos, batería y complejidad.
Configuración del Entorno
Las Task APIs comparten los mismos requisitos de hardware y configuración que la Prompt API. Si ya configuraste tu entorno, estás listo. Si no:
- Chrome Canary o Dev (versión 137+)
- Flags necesarios en
chrome://flags:Enables optimization guide on device: Enabled BypassPerfRequirementPrompt API for Gemini Nano: Enabled
- Verificar componentes en
chrome://components: Actualizar "Optimization Guide On Device Model"
Patrón Común de Uso
Todas las Task APIs (Summarizer, Writer, Rewriter, Proofreader) siguen el mismo patrón de uso:
// 1. Verificar soporte del navegador
if (!('Summarizer' in self)) {
// API no soportada, usar fallback
return;
}
// 2. Verificar disponibilidad del modelo
const availability = await Summarizer.availability();
if (availability === 'unavailable') {
// Hardware insuficiente, usar cloud API
return;
}
// 3. Crear instancia con opciones
const summarizer = await Summarizer.create({
type: 'key-points',
length: 'medium',
});
// 4. Usar la API
const result = await summarizer.summarize(text);
// 5. Limpiar recursos
summarizer.destroy();
Los estados de disponibilidad son los mismos que en Prompt API:
unavailable: Hardware insuficientedownloadable: Requiere descarga (primera vez, requiere user activation)downloading: Descarga en progresoavailable: Listo para usar
Conceptos Compartidos
Como ya vimos en los artículos sobre Prompt API, estos conceptos aplican también a Task APIs:
- User Activation: La descarga del modelo requiere interacción del usuario (click, keydown)
- Download Monitoring: Usa el parámetro
monitorpara mostrar progreso - Streaming: Todas las APIs tienen versión
*Streaming()para resultados progresivos - Cleanup: Siempre llama a
destroy()para liberar recursos - Error Handling: Manejar
QuotaExceededErrorcuando el input excede límites
La única diferencia importante es que las Task APIs no mantienen historial entre llamadas, a diferencia de Prompt API donde cada prompt() acumula contexto.
1. Summarizer API: Extracción Inteligente de Insights
La Summarizer API está optimizada para extraer información relevante de textos largos. A diferencia de pedirle a Prompt API "resume este texto", aquí defines qué tipo de resumen quieres a través de parámetros declarativos.
Tipos de Resumen
const summarizer = await Summarizer.create({
type: 'key-points', // 'key-points' | 'tldr' | 'teaser' | 'headline'
format: 'markdown', // 'markdown' | 'plain-text'
length: 'medium', // 'short' | 'medium' | 'long'
sharedContext: '', // Contexto compartido para múltiples documentos
});
Cada type está diseñado para un caso de uso específico:
-
key-points: Lista de puntos clave. Ideal para artículos técnicos, documentación, o cuando necesitas escanear rápidamente el contenido. El modelo extrae las ideas principales en formato de lista. -
tldr: Resumen ultra-conciso de 1-2 oraciones. Perfecto para previews rápidos, notificaciones, o cuando el espacio es limitado (cards, tooltips). -
teaser: Introducción que incentiva a leer más. Diseñado para generar engagement, útil en feeds de contenido, newsletters, o sugerencias de artículos. -
headline: Título descriptivo del contenido. Usa esto para generar títulos automáticos de secciones, categorizar documentos, o crear índices.
Shared Context: El Contexto Sin Contaminar
El parámetro sharedContext es particularmente útil cuando resumes múltiples documentos relacionados. A diferencia de incluir contexto en cada texto, sharedContext se define una sola vez al crear la instancia y aplica a todas las llamadas posteriores sin contar contra el límite de tokens de cada documento.
const summarizer = await Summarizer.create({
type: 'tldr',
sharedContext:
'Estos son comentarios de usuarios sobre la nueva versión 2.0 de nuestra app',
});
// Procesar múltiples reviews sin repetir el contexto
for (const review of customerReviews) {
const summary = await summarizer.summarize(review);
console.log(summary);
}
Esto es especialmente poderoso cuando procesas lotes de documentos similares: reportes financieros, tickets de soporte, feedback de usuarios, etc.
Escalando Más Allá del Contexto: Summary of Summaries
El contexto de Gemini Nano (~4K tokens o ~3,000 palabras) puede ser insuficiente para documentos extensos. La técnica de "summary of summaries" divide el documento en chunks, resume cada parte, y luego resume los resúmenes.
Es importante dividir por límites semánticos (párrafos, secciones) en lugar de por caracteres, para mantener coherencia. El trade-off es claro: cada nivel de recursión distancia el resumen del contenido original, pero permite procesar documentos de cualquier tamaño.
async function summarizeLargeDocument(text) {
const summarizer = await Summarizer.create({
type: 'tldr',
format: 'plain-text',
length: 'long',
});
// Verificar si cabe en el contexto
const estimatedTokens = await summarizer.measureInputUsage(text);
if (estimatedTokens <= summarizer.inputQuota) {
return await summarizer.summarize(text);
}
// Dividir por párrafos (semántico)
const chunks = text.split(/\n\n+/).reduce((acc, paragraph) => {
const maxChunkSize = summarizer.inputQuota * 3; // ~3 chars por token
if (
acc.length === 0 ||
acc[acc.length - 1].length + paragraph.length > maxChunkSize
) {
acc.push(paragraph);
} else {
acc[acc.length - 1] += '\n\n' + paragraph;
}
return acc;
}, []);
// Resumir chunks y luego resumir los resúmenes
const summaries = await Promise.all(chunks.map(c => summarizer.summarize(c)));
return await summarizer.summarize(summaries.join('\n\n'));
}
2. Writer API: Generación de Contenido Asistida
Writer API genera contenido desde cero. La diferencia clave con Prompt API es que Writer está específicamente entrenada para creación de texto, no para conversación o razonamiento complejo.
Control de Tono y Formato
const writer = await Writer.create({
tone: 'neutral', // 'formal' | 'neutral' | 'casual'
format: 'markdown', // 'markdown' | 'plain-text'
length: 'medium', // 'short' | 'medium' | 'long'
sharedContext: 'Eres asistente de servicio al cliente de TechCorp',
});
const response = await writer.write(
'Generar respuesta sobre política de devoluciones',
{
context:
'El cliente compró hace 15 días. Política: 30 días para devoluciones.',
}
);
La combinación de sharedContext (definido en create()) y context (por llamada) te permite:
- sharedContext: Define el "rol" o contexto global que se mantiene para todas las generaciones
- context: Información específica de cada petición que cambia dinámicamente
Esto es más eficiente que repetir el contexto global en cada llamada, y te permite reutilizar la misma instancia de Writer para múltiples generaciones relacionadas.
Casos de Uso Típicos
- Respuestas predefinidas: Generar variaciones de respuestas comunes en sistemas de soporte
- Autocompletado inteligente: Sugerir continuaciones de texto basadas en contexto
- Plantillas dinámicas: Crear contenido personalizado (emails, notificaciones) sin templates rígidos
- Reformulación: Expresar la misma idea de diferentes maneras
3. Rewriter API: Transformación de Contenido
Rewriter API toma texto existente y lo transforma. Es el caso de uso más común en interfaces de usuario: el usuario escribe algo informal y quiere profesionalizarlo, o viceversa.
Parámetros de Transformación
const rewriter = await Rewriter.create({
tone: 'more-formal', // 'more-formal' | 'as-is' | 'more-casual'
format: 'markdown', // 'as-is' | 'markdown' | 'plain-text'
length: 'shorter', // 'shorter' | 'as-is' | 'longer'
});
Nota: Los valores de tone son direccionales (more-formal, more-casual) a diferencia de Writer que usa estados absolutos (formal, casual). Esto es porque Rewriter transforma texto existente, no genera desde cero.
Patrones de Uso
1. Botón "Mejorar" en formularios:
// Inicializar una vez
const rewriter = await Rewriter.create({
tone: 'more-formal',
length: 'as-is',
});
// Usar en múltiples campos
document.querySelector('#enhance-btn').addEventListener('click', async () => {
const textarea = document.querySelector('#message');
textarea.value = await rewriter.rewrite(textarea.value);
});
2. Condensar texto manteniendo información esencial:
const rewriter = await Rewriter.create({ tone: 'as-is', length: 'shorter' });
const concise = await rewriter.rewrite(verbosoText);
3. Convertir formato (plain text → markdown):
const rewriter = await Rewriter.create({ tone: 'as-is', format: 'markdown' });
La API es particularmente útil porque no requieres diseñar prompts específicos como "haz este texto más formal pero mantén la misma longitud". Los parámetros declarativos manejan esto automáticamente.
4. Proofreader API: Corrección Contextual
Proofreader API va más allá de un corrector ortográfico tradicional. Entiende gramática compleja, contexto, y puede explicar cada error detectado. Es la API más ligera de todas, optimizada para latencia mínima.
Estructura de Respuesta
const proofreader = await Proofreader.create({
includeCorrectionTypes: true, // Clasificar errores
includeCorrectionExplanations: true, // Generar explicaciones
expectedInputLanguages: ['en'],
correctionExplanationLanguage: 'es',
});
const result = await proofreader.proofread('I seen him yesterday at the store');
console.log(result.correctedInput);
// "I saw him yesterday at the store."
console.log(result.corrections);
// [{
// startIndex: 2,
// endIndex: 6,
// correction: 'saw',
// type: 'grammar',
// explanation: 'El verbo "see" en pasado simple es "saw", no "seen"...'
// }]
Tipos de Error Detectados
La API clasifica errores en categorías específicas, lo que te permite:
spelling: Errores ortográficos (typos, palabras mal escritas)grammar: Errores gramaticales (tiempo verbal, concordancia)punctuation: Puntuación incorrecta o faltantecapitalization: Uso incorrecto de mayúsculaspreposition: Preposiciones incorrectasmissing-words: Palabras omitidas que afectan comprensión
Esto permite implementar UX sofisticadas: mostrar diferentes íconos por tipo de error, filtrar errores por severidad, o aplicar correcciones selectivamente.
Ventajas vs Correctores Tradicionales
Los correctores ortográficos tradicionales funcionan con diccionarios y reglas. Proofreader API entiende contexto:
- Detecta errores que dependen del significado, no solo de la gramática formal
- Sugiere correcciones que mantienen la intención original
- Puede explicar POR QUÉ algo es incorrecto (valioso para aprendizaje)
La trade-off es latencia: un corrector basado en reglas es instantáneo, Proofreader API requiere inferencia del modelo (aunque está optimizada para ser la más rápida de las Task APIs).
Comparativa: ¿Cuándo Usar Qué?
| Tarea | Prompt API | Task API Recomendada | Razón |
|---|---|---|---|
| Chatbot conversacional | ✅ Sí | ❌ No | Requiere contexto multi-turno |
| Resumir artículo | ⚠️ Posible | ✅ Summarizer | Modelos más ligeros, tipos de resumen configurables |
| Generar respuesta predefinida | ⚠️ Posible | ✅ Writer | Optimizado para creación, no conversación |
| Cambiar tono de mensaje | ⚠️ Posible | ✅ Rewriter | Transformación específica, parámetros declarativos |
| Corregir gramática/ortografía | ⚠️ Posible | ✅ Proofreader | Más ligero, errores tipados, explicaciones |
| Extracción de datos (JSON) | ✅ Sí | ❌ No | Requiere JSON Schema (solo Prompt API) |
| RAG con múltiples pasos | ✅ Sí | ❌ No | Requiere contexto persistente |
Estrategias de Implementación
1. Progressive Enhancement
No asumas que todos tus usuarios tendrán Built-in AI disponible. Implementa detección y fallback:
async function enhanceText(text) {
if ('Rewriter' in self) {
try {
const availability = await Rewriter.availability();
if (availability !== 'unavailable') {
const rewriter = await Rewriter.create({ tone: 'more-formal' });
const result = await rewriter.rewrite(text);
rewriter.destroy();
return { result, source: 'local' };
}
} catch (error) {
console.warn('Local AI failed:', error);
}
}
// Fallback a Cloud API
return { result: await cloudEnhance(text), source: 'cloud' };
}
2. Lazy Loading con Cleanup Automático
Para funcionalidades secundarias, carga la API solo cuando el usuario la necesita:
class LazyRewriter {
constructor() {
this.instance = null;
this.lastUsed = Date.now();
}
async rewrite(text) {
if (!this.instance) {
this.instance = await Rewriter.create({ tone: 'more-formal' });
}
this.lastUsed = Date.now();
this.scheduleCleanup();
return await this.instance.rewrite(text);
}
scheduleCleanup() {
clearTimeout(this.timer);
this.timer = setTimeout(
() => {
if (Date.now() - this.lastUsed > 5 * 60 * 1000) {
// 5 min inactivo
this.instance?.destroy();
this.instance = null;
}
},
5 * 60 * 1000
);
}
}
3. Batch Processing con sharedContext
Cuando procesas múltiples documentos similares, aprovecha sharedContext para eficiencia:
const summarizer = await Summarizer.create({
type: 'tldr',
sharedContext: 'Feedback de usuarios sobre la versión beta',
});
// Procesar lote sin repetir contexto
const summaries = await Promise.all(
feedbackList.map(f => summarizer.summarize(f))
);
Consideraciones de Producción
Requisitos de Hardware
Las Task APIs comparten las mismas restricciones que Prompt API:
- Almacenamiento: Mínimo 22GB libres
- GPU: >4GB VRAM, o CPU con 16GB RAM + 4+ núcleos
- Sistema Operativo: Windows 10+, macOS 13+, Linux, ChromeOS
En producción, Chrome solo activará las APIs en hardware compatible. Por eso el fallback no es opcional, es crítico.
UX de Descarga
Si el modelo no está descargado, la primera llamada a create() requiere user activation (click del usuario). Implementa una UX clara:
const availability = await Rewriter.availability();
if (availability === 'downloadable') {
showDownloadButton('Habilitar mejora de texto (descarga única)', async () => {
await Rewriter.create({
monitor: m =>
m.addEventListener('downloadprogress', e =>
updateProgress(Math.round(e.loaded * 100))
),
});
});
}
Streaming para UX Responsive
Todas las APIs soportan streaming (summarizeStreaming(), writeStreaming(), rewriteStreaming()). Para operaciones que toman más de 1-2 segundos, streaming mejora significativamente la percepción de velocidad:
const stream = summarizer.summarizeStreaming(longDocument);
for await (const chunk of stream) {
outputElement.textContent += chunk; // Texto aparece progresivamente
}
Conclusión
Las Task APIs representan un balance ideal entre potencia y especialización:
- Summarizer: 4 tipos de resumen configurables (key-points, tldr, teaser, headline) con manejo de contexto compartido
- Writer: Generación de contenido con control fino de tono, formato y longitud
- Rewriter: Transformación de texto existente con parámetros direccionales
- Proofreader: Corrección con clasificación de errores y explicaciones pedagógicas
La diferencia fundamental con Prompt API es que estas APIs son stateless y están afinadas para tareas específicas. Esto se traduce en modelos más ligeros, mejor calidad en su dominio, y APIs más simples de usar.
Úsalas cuando la tarea encaje perfectamente en su especialización. Usa Prompt API cuando necesitas flexibilidad, contexto persistente, o capacidades que las Task APIs no ofrecen (JSON Schema, Tool Use, conversaciones multi-turno).
Con estas herramientas, puedes construir experiencias de escritura asistida, resumen inteligente y corrección automática completamente client-side, manteniendo privacidad total y disponibilidad offline.

