🎨 Generación de Imágenes con IA
Crea imágenes únicas usando los modelos de IA disponibles a través de la plataforma Atenea:
Flujo de Trabajo
Obtener Servicios Disponibles
Consulta qué modelos de IA están disponibles actualmente
GET /api/atenea/ai/services
Generar Imagen
Usa uno de los servicios disponibles para generar tu imagen
POST /api/atenea/ai/generate
Verificar Estado (Opcional)
Para procesos asíncronos, consulta el estado del job
GET /api/atenea/ai/job/{jobId}
1. Obtener Servicios Disponibles
Antes de generar imágenes, consulta qué servicios de IA están disponibles:
curl -X GET https://limbo.lefebvre.es/api/atenea/ai/services \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
Respuesta de ejemplo:
{
"success": true,
"data": [
"dall-e-2",
"dall-e-3",
"freepik-classic",
"freepik-mystic"
],
"message": "Available AI services",
"httpCode": 200
}
2. Generar Imagen con IA
Usa uno de los servicios disponibles para generar tu imagen:
curl -X POST https://limbo.lefebvre.es/api/atenea/ai/generate \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{
"service": "dall-e-3",
"prompt": "A modern office workspace with plants and natural lighting, minimalist style",
"size": "1024x1024",
"quality": "hd",
"n": 1
}'
// Usando las APIs del componente Limbo
import { getAiServices, generateAiImage } from './services/aiApi.js';
class LimboAIService {
constructor(apiKey, prod = false) {
this.apiKey = apiKey;
this.prod = prod;
}
async getAvailableServices() {
try {
const response = await getAiServices(this.apiKey, this.prod);
return response.data; // Array de servicios disponibles
} catch (error) {
console.error('Error obteniendo servicios IA:', error);
throw error;
}
}
async generateImage(options) {
const {
service = 'dall-e-3',
prompt,
size = '1024x1024',
quality = 'standard',
n = 1
} = options;
try {
const response = await generateAiImage(this.apiKey, {
service,
prompt,
size,
quality,
n
}, this.prod);
return response;
} catch (error) {
console.error('Error generando imagen:', error);
throw error;
}
}
}
// Uso
const aiService = new LimboAIService('your-api-key', false);
// 1. Obtener servicios disponibles
const availableServices = await aiService.getAvailableServices();
console.log('Servicios disponibles:', availableServices);
// 2. Generar imagen
const result = await aiService.generateImage({
service: availableServices[0], // Usar primer servicio disponible
prompt: 'Modern office workspace with plants',
quality: 'hd'
});
console.log('Imagen generada:', result.data.images);
prompt,
model,
size,
style,
quality,
negative_prompt: negativePrompt,
num_images: numImages
})
});
if (!response.ok) {
throw new Error(`AI generation failed: ${response.statusText}`);
}
const result = await response.json();
return result;
} catch (error) {
console.error('AI generation error:', error);
throw error;
}
}
async enhanceImage(assetId, options = {}) {
const {
enhancement = 'upscale',
factor = 2,
style = 'auto'
} = options;
try {
const response = await fetch(`${this.apiUrl}/ai/enhance`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${await this.authService.getValidToken()}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
asset_id: assetId,
enhancement,
factor,
style
})
});
if (!response.ok) {
throw new Error(`AI enhancement failed: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('AI enhancement error:', error);
throw error;
}
}
async analyzeImage(assetId) {
try {
const response = await fetch(`${this.apiUrl}/ai/analyze`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${await this.authService.getValidToken()}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
asset_id: assetId
})
});
if (!response.ok) {
throw new Error(`AI analysis failed: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('AI analysis error:', error);
throw error;
}
}
async generateTags(assetId, options = {}) {
const { language = 'es', maxTags = 10 } = options;
try {
const response = await fetch(`${this.apiUrl}/ai/tag`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${await this.authService.getValidToken()}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
asset_id: assetId,
language,
max_tags: maxTags
})
});
if (!response.ok) {
throw new Error(`AI tagging failed: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('AI tagging error:', error);
throw error;
}
}
}
// Uso
const aiService = new LimboAIService(authService, 'https://limbo.lefebvre.es');
// Generar imagen
const generateButton = document.getElementById('generate-btn');
generateButton.addEventListener('click', async () => {
const prompt = document.getElementById('prompt').value;
try {
showLoading('Generando imagen...');
const result = await aiService.generateImage({
prompt: prompt,
model: 'dall-e-3',
quality: 'hd'
});
displayGeneratedImages(result.data.images);
hideLoading();
} catch (error) {
showError('Error generando imagen: ' + error.message);
hideLoading();
}
});
// Análisis automático al subir imagen
async function onImageUpload(assetId) {
try {
// Analizar imagen
const analysis = await aiService.analyzeImage(assetId);
displayAnalysis(analysis.data);
// Generar tags automáticamente
const tags = await aiService.generateTags(assetId);
suggestTags(tags.data.tags);
} catch (error) {
console.error('Auto-analysis failed:', error);
}
}
httpClient = $httpClient;
$this->authService = $authService;
$this->apiUrl = $apiUrl;
}
public function generateImage(array $options): array
{
$token = $this->authService->getValidToken();
$defaultOptions = [
'model' => 'dall-e-3',
'size' => '1024x1024',
'style' => 'natural',
'quality' => 'standard',
'num_images' => 1
];
$params = array_merge($defaultOptions, $options);
$response = $this->httpClient->request('POST', $this->apiUrl . '/ai/generate', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json'
],
'json' => $params
]);
if ($response->getStatusCode() !== 200) {
throw new \Exception('AI generation failed: ' . $response->getContent(false));
}
return $response->toArray();
}
public function enhanceImage(string $assetId, array $options = []): array
{
$token = $this->authService->getValidToken();
$defaultOptions = [
'enhancement' => 'upscale',
'factor' => 2,
'style' => 'auto'
];
$params = array_merge($defaultOptions, $options, ['asset_id' => $assetId]);
$response = $this->httpClient->request('POST', $this->apiUrl . '/ai/enhance', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json'
],
'json' => $params
]);
if ($response->getStatusCode() !== 200) {
throw new \Exception('AI enhancement failed: ' . $response->getContent(false));
}
return $response->toArray();
}
public function analyzeImage(string $assetId): array
{
$token = $this->authService->getValidToken();
$response = $this->httpClient->request('POST', $this->apiUrl . '/ai/analyze', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json'
],
'json' => ['asset_id' => $assetId]
]);
if ($response->getStatusCode() !== 200) {
throw new \Exception('AI analysis failed: ' . $response->getContent(false));
}
return $response->toArray();
}
public function generateTags(string $assetId, array $options = []): array
{
$token = $this->authService->getValidToken();
$defaultOptions = [
'language' => 'es',
'max_tags' => 10
];
$params = array_merge($defaultOptions, $options, ['asset_id' => $assetId]);
$response = $this->httpClient->request('POST', $this->apiUrl . '/ai/tag', [
'headers' => [
'Authorization' => 'Bearer ' . $token,
'Content-Type' => 'application/json'
],
'json' => $params
]);
if ($response->getStatusCode() !== 200) {
throw new \Exception('AI tagging failed: ' . $response->getContent(false));
}
return $response->toArray();
}
public function batchProcessImages(array $assetIds, array $operations = []): array
{
$results = [];
foreach ($assetIds as $assetId) {
try {
$assetResults = ['asset_id' => $assetId];
if (in_array('analyze', $operations)) {
$assetResults['analysis'] = $this->analyzeImage($assetId);
}
if (in_array('tags', $operations)) {
$assetResults['tags'] = $this->generateTags($assetId);
}
if (in_array('enhance', $operations)) {
$assetResults['enhanced'] = $this->enhanceImage($assetId);
}
$results[] = $assetResults;
} catch (\Exception $e) {
$results[] = [
'asset_id' => $assetId,
'error' => $e->getMessage()
];
}
}
return $results;
}
}
// Uso en controlador
class AIController extends AbstractController
{
public function __construct(private LimboAIService $aiService)
{
}
#[Route('/admin/ai/generate', methods: ['POST'])]
public function generateImage(Request $request): JsonResponse
{
$data = json_decode($request->getContent(), true);
try {
$result = $this->aiService->generateImage([
'prompt' => $data['prompt'],
'model' => $data['model'] ?? 'dall-e-3',
'quality' => $data['quality'] ?? 'standard'
]);
return $this->json(['success' => true, 'data' => $result]);
} catch (\Exception $e) {
return $this->json(['success' => false, 'error' => $e->getMessage()], 400);
}
}
}
Respuesta de Generación
{
"success": true,
"data": {
"generation_id": "gen_abc123def456",
"model": "dall-e-3",
"prompt": "A modern office workspace with plants and natural lighting",
"images": [
{
"id": "img_789xyz123",
"url": "https://limbo.lefebvre.es/assets/generated/img_789xyz123/view",
"thumbnail_url": "https://limbo.lefebvre.es/assets/generated/img_789xyz123/thumbnail",
"size": "1024x1024",
"format": "png",
"estimated_cost": 0.04,
"generation_time": 8.2,
"metadata": {
"style": "natural",
"quality": "hd",
"safety_rating": "safe",
"content_tags": ["office", "workspace", "plants", "modern", "professional"]
}
}
],
"usage": {
"tokens_used": 156,
"estimated_cost": 0.04,
"generation_time_seconds": 8.2
},
"created_at": "2024-01-15T14:35:18Z"
}
}
📷 Banco de Imágenes Stock
Acceso a imágenes de stock a través de los proveedores integrados en la plataforma Atenea:
Flujo de Trabajo
Obtener Servicios de Stock
Consulta qué proveedores de stock están disponibles
GET /api/atenea/stock/services
Buscar Imágenes
Busca imágenes usando criterios específicos
POST /api/atenea/stock/search
Descargar Imagen
Descarga la imagen seleccionada para tu proyecto
POST /api/atenea/stock/download