Contenido del curso
Fundamentos de la API de OpenAI
Control de Respuestas
Desarrollo de 'PlatziVision'
Fine-Tuning
OpenAI Batch
OpenAI Assistants
Proyecto Final y Cierre del Curso
Generación de imágenes con function calling en GPT
Resumen
Integrar la generación de imágenes en un chatbot con GPT requiere convertir tu lógica en una función declarada, manejar streaming y notificar a la interfaz cada paso. Aquí verás cómo implementar function calling con DALL·E dentro de un endpoint que itera sobre múltiples llamadas, todo aplicado al proyecto Plativisión.
Cómo se declara una función para que GPT la use correctamente
Lo primero es transformar el código de generación de imágenes en una función reutilizable llamada generate_image, ubicada antes de la función de chat dentro de chat.py. Esa función recibe un prompt y una calidad por defecto en estándar.
Para que el modelo GPT sepa cuándo invocarla, necesitas una declaración formal en el arreglo de tools. Esa declaración incluye nombre, descripción y parámetros tipados, y se pasa dentro de la llamada a create.
¿Qué es una declaración de función en GPT? Es un objeto que le dice al modelo el nombre de la función, para qué sirve y qué parámetros recibe. Sin esa declaración, GPT no puede decidir cuándo llamarla.
Qué parámetros debe incluir la declaración
La estructura de la declaración debe contener un objeto parameters con type: object y un bloque properties que defina cada argumento. En este caso:
prompt: tipo string, descripción "instrucción o prompt que generará la imagen".quality: tipo string, descripción "calidad de la imagen, puede ser HD o estándar".- Nombre de la función:
generate_image.
La descripción de la función guía al asistente: cuando el usuario pida generar una imagen, debe llamar a generate_image [02:15].
Por qué necesitas un bucle para iterar sobre las respuestas del asistente
En implementaciones anteriores con funciones como consultar el clima, bastaba con dos respuestas: una donde el modelo anunciaba la función y otra donde procesaba el resultado. Aquí cambia el escenario.
Como el endpoint puede invocar generate_image varias veces dentro de un mismo mensaje, hay que iterar. Si solo ejecutas la función una vez, la conversación se queda estancada y el usuario nunca recibe la respuesta final en lenguaje natural.
La solución es envolver toda la lógica de respuesta en un bucle controlado por la variable response. Mientras response is None, la conversación continúa; cuando ya no hay más llamadas a herramientas, rompes el bucle [04:30].
Cómo manejar el streaming de argumentos
GPT no devuelve los argumentos completos de golpe. Los entrega en chunks, así que debes acumularlos.
- Detectar si el chunk contiene
tool_calls. - Guardar el
tool_call_idpara no confundir llamadas múltiples. - Acumular los argumentos en una variable
accumulated_argschunk por chunk. - Cuando detectes el cierre de llaves
}, parsear el JSON y ejecutar la función dentro de un bloque try/except.
Este patrón evita errores cuando el modelo aún no ha terminado de emitir el JSON completo.
Cómo notificar a la interfaz que se está generando una imagen
Generar una imagen toma segundos, y sin retroalimentación visual el usuario puede creer que el sistema falló. Por eso, justo antes de llamar a generate_image, emites un evento al frontend con yield.
El formato sigue el patrón de Server-Sent Events: cada mensaje empieza con data: seguido del JSON, por ejemplo {"status": "generating_image"}. Importante: cada yield debe terminar con saltos de línea, porque sin ellos el streaming se confunde y el frontend no recibe la señal a tiempo [09:45].
¿Por qué fallan los eventos en streaming? Casi siempre por falta de saltos de línea al final del mensaje. El protocolo SSE requiere
\n\npara delimitar eventos.
Cómo agregar la llamada y el resultado al historial de mensajes
Una vez ejecutada la función, debes actualizar el historial con dos entradas nuevas:
- Un mensaje con
role: assistant,content: nully el bloquetool_callsque incluye elid, eltype: functiony los argumentos usados. - Un mensaje con
role: tool, el mismotool_call_idy elcontentcon la URL de la imagen generada.
Especificar type: function parece redundante hoy, pero OpenAI planea añadir más tipos de herramientas, así que la convención protege tu código a futuro.
Cómo cerrar el ciclo y devolver la respuesta final al usuario
Después de añadir la URL al historial, vuelves a poner response = None y dejas que el bucle haga otra iteración. En esa nueva iteración, el asistente recibe la URL como contexto y genera el texto natural: "Aquí tienes la imagen de un hermoso atardecer".
Cuando el modelo ya no llama a más herramientas y solo emite texto, rompes el bucle con break. Ese es el punto exacto en el que la tarea del usuario se considera completada.
En la prueba final con Plativisión, al pedir "genera una imagen de un atardecer", la terminal muestra los argumentos acumulándose en tiempo real, luego el log "iniciando la llamada a la función", después "imagen generada correctamente" y finalmente la URL aparece renderizada en la interfaz junto al texto del asistente.
Comparte las imágenes que generes en Plativisión dentro de la sección de aportes y cuéntame qué prompts te dieron los mejores resultados.