Skip to content

Crear una API de Generación de Imágenes DALL-E con Laravel: Guía Paso a Paso

En esta guía, recorreremos el proceso de creación de un endpoint de API de Laravel que genera imágenes DALL-E y las almacena en el sistema de archivos local. Esta funcionalidad puede ser útil para aplicaciones que requieren imágenes generadas por IA bajo demanda, como herramientas de creación de contenido o chatbots.

Introducción

DALL-E es un modelo de IA desarrollado por OpenAI que puede crear imágenes únicas a partir de descripciones de texto. Integrar esta capacidad en una aplicación Laravel abre posibilidades para contenido visual dinámico impulsado por IA.

Problema

Muchos desarrolladores encuentran desafiante incorporar capacidades de generación de imágenes de IA en sus aplicaciones Laravel. El proceso implica no solo generar las imágenes, sino también almacenarlas eficientemente, proporcionar acceso a ellas y manejar posibles errores. Este artículo tiene como objetivo simplificar este proceso proporcionando una guía completa.

Solución

Desglosemos la solución en los siguientes pasos:

Paso 1: Configurar la API de OpenAI

Antes de comenzar, necesita obtener una clave de API de la API de OpenAI. Visite el sitio web de OpenAI, cree una cuenta y genere una clave de API.

Una vez que tenga su clave de API, agréguela a su configuración de entorno de Laravel:

OPENAI_API_KEY=su_clave_api_aquí

Paso 2: Crear la Clase Auxiliar OpenAIProvider

Cree un nuevo archivo llamado app/AI/Providers/OpenAIProvider.php y agregue el siguiente código:

php
<?php

namespace App\AI\Providers;

use App\Exceptions\Errors;
use OpenAI;
use Exception;

class OpenAIProvider
{
    const array MODEL_RETRY_TIMES = [3000, 7000, 10000];

    private static function getApiKey(): string
    {
        return config('openai.api_key');
    }

    private static function getClient(): OpenAI\Client
    {
        return OpenAI::client(self::getApiKey());
    }

    public static function images(
        string $prompt,
        int $n = 1,
        string $model = 'dall-e-3',
        string $quality = 'hd',
        string $size = '1792x1024',
        string $style = 'natural',
        string $response_format = 'url',
        ?string $user = null
    ): ?array {
        $urls = [];
        $parameters = [
            'prompt' => $prompt,
            'model' => $model,
            'n' => $n,
            'quality' => $quality,
            'size' => $size,
            'style' => $style,
            'response_format' => $response_format,
        ];

        if ($user !== null) {
            $parameters['user'] = $user;
        }

        try {
            $response = retry(
                times: self::MODEL_RETRY_TIMES,
                callback: function () use ($parameters) {
                    return self::getClient()->images()->create($parameters);
                },
            );

            foreach ($response->data as $data) {
                $urls[] = $data->url;
            }
        } catch (Exception $e) {
            Errors::captureException($e);
        }

        return $urls;
    }
}

Esta clase maneja la interacción con la API de OpenAI, incluyendo reintentar la solicitud si es necesario y capturar cualquier excepción que ocurra.

Paso 3: Implementar el Manejo de Errores

Cree un nuevo archivo llamado app/Exceptions/Errors.php y agregue el siguiente código:

php
<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Support\Facades\Log;

use function Sentry\captureException;

class Errors
{
    public static function captureException(Exception $e): void
    {
        captureException($e);

        if (config('app.env') === 'local') {
            Log::error($e);
        }
    }
}

Esta clase captura excepciones y las registra usando seguimiento de errores de Sentry, con registro local adicional para entornos de desarrollo.

Paso 4: Configurar el Controlador

Cree un nuevo controlador llamado app/Http/Controllers/ChatbotController.php y agregue el siguiente código:

php
<?php

namespace App\Http\Controllers;

use App\AI\Providers\OpenAIProvider;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;

class ChatbotController extends Controller
{
    public function v1Dalle(Request $request): JsonResponse
    {
        $v = $request->validate([
            'prompt' => 'required|string',
        ]);

        $chatbot_api_key = config('integrations.chatbot_api_key');
        $incoming_api_key = $request->headers->get('X-Api-Key');

        if ($chatbot_api_key !== $incoming_api_key) {
            return response()->json([
                'error' => 'Unauthorized',
            ], 401);
        }

        $prompt = $v['prompt'];
        $app_url = config('app.url');
        $public_url = null;

        $images = OpenAIProvider::images(
            prompt: $prompt,
        );

        foreach ($images as $image) {
            $image_contents = Http::get($image)->body();

            $filename = 'dalle3/'.uniqid().'.png';
            $public_filename = 'public/'.$filename;

            Storage::put($public_filename, $image_contents);

            $public_url = $app_url.Storage::url($public_filename);
        }

        return response()->json([
            'url' => $public_url,
        ]);
    }
}

Este controlador maneja la solicitud entrante, valida la clave de API, genera la imagen usando OpenAIProvider, la guarda en el sistema de archivos local usando Laravel Storage, y devuelve la URL pública de la imagen guardada.

Paso 5: Configurar la Ruta

Agregue la siguiente ruta a su archivo routes/api.php:

php
Route::post('/v1/dalle', [ChatbotController::class, 'v1Dalle']);

Paso 6: Configurar la Clave de API

Agregue lo siguiente a su archivo .env:

CHATBOT_API_KEY=su_clave_api_chatbot_aquí

Luego, en config/integrations.php (cree este archivo si no existe), agregue:

php
<?php

return [
    'chatbot_api_key' => env('CHATBOT_API_KEY'),
];

Paso 7: Actualizar la Configuración Local

Para asegurarse de que las nuevas variables de entorno se carguen en la aplicación, ejecute el comando php artisan optimize:clear. Esto ejecutará un par de acciones, una de ellas es asegurar que las nuevas variables de entorno estén en caché.

Paso 8: Probar el Endpoint

Puede probar el endpoint usando una herramienta como Postman o curl. Envíe una solicitud POST a /api/v1/dalle con los siguientes encabezados y cuerpo:

Encabezados:

X-Api-Key: su_clave_api_chatbot_aquí
Content-Type: application/json

Cuerpo:

json
{
  "prompt": "Un paisaje urbano futurista con autos voladores"
}

La respuesta debe contener una URL a la imagen generada.

Consideraciones de Seguridad

Al implementar esta API, es crucial seguir las mejores prácticas de seguridad de API:

  1. Siempre use HTTPS para las solicitudes de API para proteger las claves de API y otros datos sensibles.
  2. Almacene las claves de API de forma segura en variables de entorno, nunca en el control de versiones.
  3. Implemente limitación de tasa en Laravel en su endpoint para prevenir abusos.

Consideraciones de Rendimiento

Para garantizar un rendimiento óptimo de su API de generación de imágenes DALL-E:

  1. Considere implementar el almacenamiento en caché para imágenes solicitadas con frecuencia para reducir las llamadas a la API y las operaciones de almacenamiento.
  2. Use colas de Laravel para tareas de generación de imágenes si espera un tráfico alto para evitar bloquear el hilo principal.

Limitaciones de Este Enfoque

Aunque la solución presentada en esta guía proporciona una API funcional de generación de imágenes DALL-E, es importante ser consciente de sus limitaciones:

  1. Clave de API Fija Única: El ejemplo utiliza una única variable de entorno fija (CHATBOT_API_KEY) para autenticar las solicitudes. Este enfoque carece de flexibilidad y puede no ser adecuado para sistemas multiusuario o aplicaciones que requieren diferentes niveles de acceso.

  2. Almacenamiento de Archivos Local: Las imágenes se almacenan en el sistema de archivos local, lo que puede no ser escalable o adecuado para sistemas distribuidos. En un entorno de producción, es posible que deba considerar el uso de soluciones de almacenamiento en la nube como AWS S3 o Google Cloud Storage.

  3. Manejo de Errores: Aunque se implementa un manejo básico de errores, no cubre todos los casos posibles ni proporciona mensajes de error detallados al cliente.

  4. Parámetros de Imagen Fijos: Los parámetros de DALL-E (como tamaño y calidad) están codificados en este ejemplo, siéntase libre de agregar parámetros adicionales en la solicitud según sea necesario.

  5. Validación Limitada del Prompt: El ejemplo solo verifica si el prompt es una cadena no vacía, sin moderación de contenido ni restricciones de longitud.

  6. Sin Seguimiento de Uso: El ejemplo no realiza un seguimiento del uso de la API, lo que podría ser importante para fines de facturación o monitoreo.

Conclusión

Siguiendo estos pasos, hemos creado con éxito un endpoint de API que genera imágenes DALL-E y las almacena en el sistema de archivos local usando Laravel.

Este endpoint se puede integrar fácilmente en aplicaciones Laravel existentes, permitiendo la generación y almacenamiento bajo demanda de imágenes de IA.

Recuerde manejar los errores con gracia, implementar medidas de seguridad adecuadas y considerar optimizaciones de rendimiento a medida que su aplicación escala.