Blog.

Prompt API: Características Avanzadas

Prompt API: Características Avanzadas
10 min read

En la primera parte exploramos los fundamentos de la Prompt API. Ahora vamos a profundizar en características avanzadas que te permiten construir aplicaciones de IA más sofisticadas.

Entre algunas de las caracteristicas avanzadas veremos como trabajar con una salida estructurada con JSON Schema, como utilizar una entrada multimodal (imágenes y audio) y la posibilidad de usar Tool Use para invocar funciones.

Salida Estructurada con JSON Schema

Uno de los problemas más frustrantes con LLMs es parsear sus respuestas. La Prompt API resuelve esto con responseConstraint.

El Problema

Sin responseConstraint, el modelo devuelve texto libre que requiere parsing frágil con regex o prompt engineering complejo.

// Sin restricciones - output impredecible
const result = await session.prompt(
  'Dame 3 hashtags para: "Lanzamiento de API de IA"'
);
console.log(result);
// "Claro! Aquí tienes algunos hashtags relevantes:
// 1. #InteligenciaArtificial
// 2. #APIDesarrollo
// 3. #InnovaciónTech
// Espero que te sean útiles!"

// 😩 Necesitas regex frágiles o prompt engineering

La Solución

Con responseConstraint definimos un JSON Schema que fuerza al modelo a devolver datos estructurados y parseables directamente.

const schema = {
  type: 'object',
  properties: {
    hashtags: {
      type: 'array',
      items: {
        type: 'string',
        pattern: '^#[^\\s#]+$',
      },
      minItems: 3,
      maxItems: 3,
    },
  },
  required: ['hashtags'],
  additionalProperties: false,
};

const result = await session.prompt(
  'Genera hashtags para: "Lanzamiento de API de IA local"',
  { responseConstraint: schema }
);

const data = JSON.parse(result);
console.log(data);
// { "hashtags": ["#IALocal", "#APIWeb", "#Privacidad"] }

Casos de Uso

1. Extracción de Información

Podemos extraer datos específicos de texto no estructurado garantizando que el output tenga los campos que necesitamos.

const contactSchema = {
  type: 'object',
  properties: {
    nombre: { type: 'string' },
    email: { type: 'string', format: 'email' },
    telefono: { type: 'string', pattern: '^\\+?[0-9\\s-]+$' },
  },
  required: ['nombre'],
};

const result = await session.prompt(
  `Extrae los datos: "Soy María González. Email: [email protected]"`,
  { responseConstraint: contactSchema }
);

2. Clasificación Multi-clase

Definir un schema con enum garantiza que el modelo solo devuelva valores permitidos, ideal para clasificación.

const classificationSchema = {
  type: 'object',
  properties: {
    sentiment: {
      type: 'string',
      enum: ['positive', 'negative', 'neutral'],
    },
    confidence: { type: 'number', minimum: 0, maximum: 1 },
  },
  required: ['sentiment', 'confidence'],
};

Entrada Multimodal: Imágenes y Audio

La Prompt API puede procesar imágenes y audio directamente (actualmente en Origin Trial).

Configurando Sesiones Multimodales

Para usar imágenes o audio, debes declarar los tipos de entrada esperados al crear la sesión con expectedInputs.

const session = await LanguageModel.create({
  expectedInputs: [
    { type: 'text', languages: ['en', 'es'] },
    { type: 'image' },
  ],
});

Trabajando con Imágenes

Puedes enviar archivos de imagen (Blob/File) directamente como parte del array de contenido en el prompt.

// Desde un input file
const file = document.querySelector('#imageInput').files[0];

const session = await LanguageModel.create({
  expectedInputs: [{ type: 'text' }, { type: 'image' }],
});

const result = await session.prompt([
  { role: 'user', content: 'Describe esta imagen en detalle' },
  { role: 'user', content: file },
]);

Ejemplo: Generación de Alt Text

Combinar entrada de imagen con JSON Schema permite generar alt text accesible en formato estructurado.

const imageSchema = {
  type: 'object',
  properties: {
    altText: { type: 'string' },
    detailedDescription: { type: 'string' },
  },
  required: ['altText'],
};

const result = await session.prompt(
  [
    { role: 'user', content: 'Genera texto alternativo' },
    { role: 'user', content: imageBlob },
  ],
  { responseConstraint: imageSchema }
);

Trabajando con Audio

Similar a imágenes, puedes enviar archivos de audio especificando el tipo audio en expectedInputs.

const session = await LanguageModel.create({
  expectedInputs: [
    { type: 'text', languages: ['es'] },
    { type: 'audio', languages: ['es'] },
  ],
});

const transcription = await session.prompt([
  { role: 'user', content: 'Transcribe este audio' },
  { role: 'user', content: audioBlob },
]);

Transcripción con Análisis

Puedes combinar transcripción de audio con análisis de sentimiento en una sola llamada usando JSON Schema.

const analysisSchema = {
  type: 'object',
  properties: {
    transcription: { type: 'string' },
    sentiment: { type: 'string', enum: ['positive', 'negative', 'neutral'] },
    keywords: { type: 'array', items: { type: 'string' } },
  },
  required: ['transcription', 'sentiment'],
};

const result = await session.prompt(
  [
    { role: 'user', content: 'Transcribe y analiza este audio' },
    { role: 'user', content: audioBlob },
  ],
  { responseConstraint: analysisSchema }
);

Consideraciones de Seguridad: CORS

Al trabajar con recursos externos, debes manejar SecurityError que ocurre cuando falta configuración CORS.

try {
  const externalImage = await fetch('https://other-domain.com/image.jpg');
  const blob = await externalImage.blob();
  await session.prompt([
    { role: 'user', content: 'Describe esta imagen' },
    { role: 'user', content: blob },
  ]);
} catch (error) {
  if (error.name === 'SecurityError') {
    console.error('Imagen cross-origin sin CORS headers');
  }
}

Tool Use (Function Calling)

Tool Use permite que el modelo invoque funciones de JavaScript autónomamente.

Definiendo Tools

Un tool es un objeto con name, description, inputSchema (JSON Schema) y una función execute que el modelo puede invocar.

const calculatorTool = {
  name: 'calculate',
  description: 'Realiza operaciones matemáticas precisas.',
  inputSchema: {
    type: 'object',
    properties: {
      operation: {
        type: 'string',
        enum: ['add', 'subtract', 'multiply', 'divide'],
      },
      a: { type: 'number' },
      b: { type: 'number' },
    },
    required: ['operation', 'a', 'b'],
  },
  execute: async ({ operation, a, b }) => {
    switch (operation) {
      case 'add':
        return a + b;
      case 'subtract':
        return a - b;
      case 'multiply':
        return a * b;
      case 'divide':
        return b !== 0 ? a / b : 'Error: División por cero';
    }
  },
};

const session = await LanguageModel.create({
  tools: [calculatorTool],
});

const result = await session.prompt('¿Cuánto es 15437 multiplicado por 8923?');
// El modelo invoca calculate({ operation: 'multiply', a: 15437, b: 8923 })

Ejemplo Real: Consulta de Base de Datos o API

Podemos crear tools que consulten bases de datos o APIs, permitiendo al modelo acceder a información dinámica.

const databaseTool = {
  name: 'queryDatabase',
  description:
    'Consulta productos. Usa cuando el usuario pregunte precios o stock.',
  inputSchema: {
    type: 'object',
    properties: {
      productName: { type: 'string' },
      field: { type: 'string', enum: ['price', 'stock', 'all'] },
    },
    required: ['productName'],
  },
  execute: async ({ productName, field = 'all' }) => {
    const db = {
      laptop: { price: 1299.99, stock: 15 },
      mouse: { price: 29.99, stock: 150 },
    };
    // esto es un mock para mostrar la idea, en este punto se llamaria a la API
    const product = db[productName.toLowerCase()];
    return product
      ? field === 'all'
        ? product
        : { [field]: product[field] }
      : { error: 'No encontrado' };
  },
};

Múltiples Tools Concurrentes

El modelo puede invocar varios tools en paralelo cuando necesita combinar información de múltiples fuentes y de forma concurrente.

const weatherTool = {
  name: 'getWeather',
  description: 'Obtiene clima de una ciudad',
  inputSchema: {
    type: 'object',
    properties: {
      city: { type: 'string' },
    },
    required: ['city'],
  },
  execute: async ({ city }) => {
    const weather = {
      Madrid: { temp: 22, condition: 'soleado' },
      Barcelona: { temp: 24, condition: 'nublado' },
    };
    return weather[city] || { error: 'Ciudad no encontrada' };
  },
};

const timeTool = {
  name: 'getCurrentTime',
  description: 'Obtiene la hora actual',
  inputSchema: {
    type: 'object',
    properties: {},
  },
  execute: async () => {
    return new Date().toLocaleTimeString('es-AR');
  },
};

const session = await LanguageModel.create({
  tools: [weatherTool, timeTool],
});

// El modelo invoca múltiples tools en paralelo
const result = await session.prompt(
  '¿Qué clima hay en Madrid y Barcelona y que hora es?'
);

Nota sobre Ejecución Paralela

Cuando el modelo decide que necesita invocar múltiples tools para responder a una pregunta, los ejecuta en paralelo de manera similar a Promise.all(). Esto significa que:

  • El mismo tool puede ser invocado múltiples veces simultáneamente con diferentes parámetros
  • El modelo espera a que todas las invocaciones completen antes de continuar
  • Las funciones execute deben ser thread-safe si acceden a recursos compartidos
// El modelo puede hacer esto internamente:
const result = await session.prompt('¿Clima en Madrid, Barcelona y Sevilla?');
// Internamente ejecuta algo equivalente a:
// await Promise.all([
//   weatherTool.execute({ city: 'Madrid' }),
//   weatherTool.execute({ city: 'Barcelona' }),
//   weatherTool.execute({ city: 'Sevilla' })
// ])

Seguridad: Validación de Tools

Es crítico validar permisos y sanitizar inputs en tools que modifican datos, ya que el modelo puede ser manipulado por prompt injection.

const databaseWriteTool = {
  name: 'saveUserData',
  description: 'Guarda datos (solo admins)',
  inputSchema: {
    type: 'object',
    properties: {
      userId: { type: 'string' },
      data: { type: 'object' },
    },
  },
  execute: async ({ userId, data }, context) => {
    // ✅ CRÍTICO: Validar permisos
    if (!context.user.isAdmin) {
      return { error: 'Permisos insuficientes' };
    }

    // ✅ CRÍTICO: Validar y sanitizar inputs
    if (!isValidUserId(userId)) {
      return { error: 'User ID inválido' };
    }

    const allowedFields = ['name', 'email', 'phone'];
    const sanitizedData = {};
    for (const field of allowedFields) {
      if (data[field]) {
        sanitizedData[field] = sanitizeInput(data[field]);
      }
    }

    await database.update(userId, sanitizedData);
    return { success: true };
  },
};

Prefix Guidance

Prefix guidance fuerza al modelo a comenzar su respuesta con un formato específico, útil para garantizar salidas en formato código o JSON.

const session = await LanguageModel.create({
  initialPrompts: [
    {
      role: 'user',
      content: 'Genera configuración package.json para React con TypeScript',
    },
    {
      role: 'assistant',
      content: '```json\n',
      prefix: true,
    },
  ],
});

const result = await session.prompt('¿Dependencias esenciales?');
// El modelo DEBE continuar desde ```json\n

Combinar con JSON Schema

Combinar prefix con JSON Schema asegura tanto el formato inicial como la estructura del contenido.

const result = await session.prompt(
  [
    { role: 'user', content: 'Extrae datos: "Soy Juan, [email protected]"' },
    { role: 'assistant', content: '{\n  "', prefix: true },
  ],
  {
    responseConstraint: {
      type: 'object',
      properties: {
        nombre: { type: 'string' },
        email: { type: 'string', format: 'email' },
      },
    },
  }
);

Conclusión

Las características avanzadas de la Prompt API la convierten en una herramienta extremadamente versátil:

Capacidades Clave:

  • JSON Schema: Respuestas predecibles y parseables
  • Multimodal: Procesa imágenes y audio directamente
  • Tool Use: Invoca funciones JavaScript autónomamente
  • Prefix Guidance: Fuerza formatos específicos

Casos de Uso Avanzados:

  • RAG (Retrieval-Augmented Generation) con búsqueda semántica
  • Asistentes de accesibilidad con generación de alt text
  • Transcripción y análisis de audio
  • Workflows multi-step coordinados por el modelo
  • Clasificación y extracción con salida estructurada

Con estas herramientas, puedes construir experiencias de IA sofisticadas completamente en el cliente, manteniendo privacidad total, latencia baja y disponibilidad offline.

Para un ejemplo completo funcional, consulta la demo HTML incluida con este artículo.

Comments

Share your thoughts and join the discussion


Related Posts

Prompt API: Fundamentos

Prompt API: Fundamentos

13 min read

Descubre los fundamentos de la Prompt API: sesiones, streaming, gestión de tokens, y control de parámetros del modelo para construir aplicaciones de IA en el navegador.