forked from innovacion/playground
155 lines
4.4 KiB
TypeScript
155 lines
4.4 KiB
TypeScript
import { NextRequest, NextResponse } from 'next/server';
|
|
import { type ImageGenerationConfig, getSafetySettings } from '@/lib/google-ai';
|
|
import { vertexAI } from '@/lib/google-ai-server';
|
|
|
|
export const runtime = 'nodejs';
|
|
export const maxDuration = 60;
|
|
|
|
export async function POST(req: NextRequest) {
|
|
try {
|
|
const body: ImageGenerationConfig = await req.json();
|
|
|
|
const {
|
|
model,
|
|
prompt,
|
|
aspectRatio = '1:1',
|
|
numberOfImages = 1,
|
|
negativePrompt,
|
|
temperature = 1,
|
|
safetyFilterLevel = 'block_some',
|
|
referenceImages,
|
|
} = body;
|
|
|
|
if (!prompt || !model) {
|
|
return NextResponse.json(
|
|
{ error: 'Prompt y modelo son requeridos' },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
|
|
// Obtener el modelo generativo de Vertex AI
|
|
const generativeModel = vertexAI.getGenerativeModel({
|
|
model: model,
|
|
safetySettings: getSafetySettings(safetyFilterLevel) as any,
|
|
generationConfig: {
|
|
temperature: temperature,
|
|
maxOutputTokens: 8192,
|
|
},
|
|
});
|
|
|
|
// Construir el prompt completo
|
|
let fullPrompt = prompt;
|
|
if (negativePrompt) {
|
|
fullPrompt += `\n\nNo incluir: ${negativePrompt}`;
|
|
}
|
|
|
|
// Agregar instrucciones de aspect ratio si no es 1:1
|
|
if (aspectRatio !== '1:1') {
|
|
fullPrompt += `\n\nGenera la imagen en formato ${aspectRatio}.`;
|
|
}
|
|
|
|
// Construir parts con imágenes de referencia si existen
|
|
const parts: any[] = [];
|
|
|
|
// Agregar imágenes de referencia primero
|
|
if (referenceImages && referenceImages.length > 0) {
|
|
for (const refImg of referenceImages) {
|
|
parts.push({
|
|
inlineData: {
|
|
data: refImg.data,
|
|
mimeType: refImg.mimeType,
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
// Agregar el prompt de texto
|
|
parts.push({ text: fullPrompt });
|
|
|
|
// Generar contenido
|
|
const result = await generativeModel.generateContent({
|
|
contents: [
|
|
{
|
|
role: 'user',
|
|
parts: parts,
|
|
},
|
|
],
|
|
});
|
|
|
|
const response = result.response;
|
|
|
|
// Extraer imágenes de la respuesta
|
|
const images: string[] = [];
|
|
|
|
if (response.candidates && response.candidates.length > 0) {
|
|
for (const candidate of response.candidates) {
|
|
if (candidate.content?.parts) {
|
|
for (const part of candidate.content.parts) {
|
|
// Verificar si la parte contiene datos inline (imagen)
|
|
if ('inlineData' in part && part.inlineData) {
|
|
const imageData = part.inlineData.data;
|
|
if (imageData) {
|
|
images.push(imageData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Si no hay imágenes, intentar generar más información de debug
|
|
if (images.length === 0) {
|
|
console.error('No se encontraron imágenes en la respuesta');
|
|
|
|
return NextResponse.json(
|
|
{
|
|
error: 'El modelo no generó imágenes',
|
|
details: 'El modelo respondió pero no incluyó datos de imagen',
|
|
response: response,
|
|
suggestion: 'Prueba con un prompt más descriptivo o cambia el modelo',
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
|
|
return NextResponse.json({
|
|
images: images,
|
|
model: model,
|
|
prompt: prompt,
|
|
aspectRatio: aspectRatio,
|
|
count: images.length,
|
|
});
|
|
|
|
} catch (error: any) {
|
|
console.error('Error generando imagen:', error);
|
|
|
|
// Manejar errores específicos de la API
|
|
let errorMessage = 'Error generando imagen';
|
|
let errorDetails = error.message;
|
|
|
|
if (error.message?.includes('credentials') || error.message?.includes('authentication')) {
|
|
errorMessage = 'Error de autenticación';
|
|
errorDetails = 'Verifica las credenciales del Service Account';
|
|
} else if (error.message?.includes('quota')) {
|
|
errorMessage = 'Límite de cuota excedido';
|
|
errorDetails = 'Has alcanzado el límite de uso de la API';
|
|
} else if (error.message?.includes('safety')) {
|
|
errorMessage = 'Contenido bloqueado por seguridad';
|
|
errorDetails = 'El prompt fue bloqueado por políticas de seguridad';
|
|
} else if (error.message?.includes('permission')) {
|
|
errorMessage = 'Error de permisos';
|
|
errorDetails = 'El Service Account no tiene permisos para Vertex AI';
|
|
}
|
|
|
|
return NextResponse.json(
|
|
{
|
|
error: errorMessage,
|
|
details: errorDetails,
|
|
stack: process.env.NODE_ENV === 'development' ? error.stack : undefined,
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|