¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Enviar imágenes y documentos a un modelo

Después de esta lección: Puedo explicar qué cambia cuando la entrada es una imagen o un documento.

Lección de 65 min7 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

Qué cambia cuando la entrada no es texto

Una entrada multimodal es una petición que lleva imágenes o documentos además de palabras. El modelo los lee, pero tu servicio ahora transporta archivos grandes, comprueba su tipo y paga por imagen o por página. Importa porque una petición de unos cientos de bytes puede pasar a pesar varios megabytes.

Un usuario fotografía un ticket de compra y sube un contrato de diez páginas. Una sola petición tiene ahora tres partes y tres maneras de ser rechazada.

Al final de esta lección

Nota

Puedo explicar qué cambia cuando la entrada es una imagen o un documento.

Palabras clave

PalabraQué significaEjemplo
Parteun trozo de la petición: texto, imagen o documento
Tipo de mediola etiqueta del formato de un archivoimage/png
Tamaño de la cargalos bytes que lleva una petición
Límite de páginasel máximo de páginas de un documento
Precio unitarioel coste de una imagen o una página

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

El laboratorio solo admite texto

Advertencia

El punto de acceso al modelo del laboratorio acepta texto. Un Run no puede enviarle una imagen ni un documento. Esta lección parte de una forma de petición grabada, inventada para la lección, y la comprueba con código.

Una petición es una lista de partes

Una entrada de texto es una sola cadena. Una entrada multimodal es una lista de partes, cada una con un tipo y sus datos. Los datos de un archivo viajan como bytes, a menudo codificados como texto, lo que los hace un tercio más grandes.

Debajo hay una forma grabada, inventada para esta lección. Cada proveedor real tiene sus propios nombres de campo: lee siempre su documentación.

Una forma de petición grabada

Código: node
{ "messages": [{ "role": "user", "content": [
    { "type": "text", "text": "¿Qué hay en este ticket de compra?" },
    { "type": "image", "media": "image/png", "data": "<base64, 412000 bytes>" },
    { "type": "document", "media": "application/pdf", "data": "<base64, 880000 bytes>" }
] }] }

Comprueba cada parte antes de enviar

Comprueba cada parte con una regla que fijes tú: el tipo de medio, el tamaño en bytes y el número de páginas. Comprueba también los totales: cuántas imágenes, cuántos bytes en conjunto.

Rechaza pronto, con un motivo claro. Una petición que falla en el proveedor ya te ha costado la subida y quizá dinero.

Ejemplo resuelto: límites y un precio

ParteQué esComprobaciónCoste en unidades
1texto, 1800 caracteressin límite aquí2
2imagen, png, 412000 bytespermitida, bajo 5 MB4
3imagen, gif, 90000 bytesgif no está en la lista4
4documento, 24 páginassupera el límite de 20 páginas48

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

El coste es por imagen y por página

El texto se paga por token. Una imagen o una página suele pagarse con una cantidad fija o con un número de tokens que depende de su tamaño. Suma las partes antes de la llamada, para que una regla de presupuesto pueda rechazar una petición cara.

Siempre que puedas, envía menos: reduce el tamaño de la imagen o envía solo las páginas que importan.

Un error frecuente

Advertencia

Mucha gente se fía del nombre o de la extensión del archivo. Un nombre puede decir png en un archivo que no lo es. Comprueba el tipo a partir de los bytes, en el servidor, y mantén también los límites de tamaño. La extensión es una pista, no un hecho.

Escribe el ayudante del modelo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 200 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    return (await res.json()).choices[0].message.content;' > model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el ayudante del modelo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    const list = [].concat(sample);' '    const turn = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' '    return list[Math.min(turn, list.length - 1)];' '  }' '}' 'module.exports = { ask };' >> model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el comprobador, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' '// Una petición grabada e inventada: cada proveedor tiene su propia forma.' 'const request = { parts: [' '  { type: \"texto\", chars: 1800 },' '  { type: \"imagen\", kind: \"png\", bytes: 412000 },' '  { type: \"imagen\", kind: \"gif\", bytes: 90000 },' '  { type: \"documento\", pages: 24, bytes: 880000 },' '] };' 'const LIMITS = { images: 3, imageBytes: 5000000, pages: 20, kinds: [\"png\", \"jpeg\"] };' 'const PRICE = { image: 4, page: 2, thousandChars: 1 }; // unidades inventadas' > shapes.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el comprobador, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function check(req) {' '  const problems = [];' '  let images = 0;' '  let cost = 0;' '  req.parts.forEach(function (p, i) {' '    const n = i + 1;' '    if (p.type === \"texto\") cost += Math.ceil(p.chars / 1000) * PRICE.thousandChars;' '    if (p.type === \"imagen\") {' '      images++;' '      cost += PRICE.image;' '      if (LIMITS.kinds.indexOf(p.kind) < 0) problems.push(\"parte \" + n + \": formato \" + p.kind + \" no permitido\");' '      if (p.bytes > LIMITS.imageBytes) problems.push(\"parte \" + n + \": imagen demasiado grande\");' '    }' >> shapes.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el comprobador, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' '    if (p.type === \"documento\") {' '      cost += p.pages * PRICE.page;' '      if (p.pages > LIMITS.pages) problems.push(\"parte \" + n + \": demasiadas páginas\");' '    }' '  });' '  if (images > LIMITS.images) problems.push(\"demasiadas imágenes\");' '  return { problems: problems, cost: cost };' '}' >> shapes.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el comprobador, parte 4

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const result = check(request);' 'result.problems.forEach(function (p) { console.log(\"Problema:\", p); });' 'console.log(\"Coste:\", result.cost, \"unidades (un precio inventado)\");' 'async function main() {' '  const text = \"Texto del ticket: pan 2,10, leche 1,05, total 3,15. ¿Cuál es el total?\";' '  const sample = \"El total es 3,15.\";' '  console.log(\"Solo texto, llamada real:\", await ask([{ role: \"user\", content: text }], sample, 30));' '}' 'main();' >> shapes.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Comprueba la petición grabada

Comando
docker exec -w /home/node/project agent node shapes.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Una salida posible

LíneaQué muestra
Problema: parte 3: formato gif no permitidoEl tipo de medio no está en la lista
Problema: parte 4: demasiadas páginas24 páginas superan el límite de 20
Coste: 58 unidadesTexto 2, dos imágenes 8 y un documento 48
Solo texto, llamada realUna respuesta corta a una pregunta de texto, o una Muestra grabada con su etiqueta

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.