GoGma commited on
Commit
ee198b7
·
verified ·
1 Parent(s): 1e71fec

Fix image generation: Switch from OpenRouter to HuggingFace Inference API

Browse files
Files changed (1) hide show
  1. generation.py +46 -51
generation.py CHANGED
@@ -1,9 +1,10 @@
1
  import os
2
  import requests
3
  import random
4
- import re
5
  from datetime import datetime
6
  from typing import Optional
 
7
 
8
  # Configuración de carpetas
9
  OUTPUT_DIR = "generated_images"
@@ -12,94 +13,88 @@ os.makedirs(OUTPUT_DIR, exist_ok=True)
12
  def generate_image_from_prompt(
13
  prompt: str,
14
  negative_prompt: str = "",
15
- model_name: str = "ignored", # Este argumento lo ignoramos para usar los hardcodeados seguros
16
  seed: Optional[int] = None,
17
  ) -> tuple[Optional[str], str]:
18
 
19
  # 1. VALIDACIÓN DE CREDENCIALES
20
- api_key = os.getenv("OPENROUTER_API_KEY")
 
21
  if not api_key:
22
- return None, "❌ Error Crítico: No existe OPENROUTER_API_KEY en Secrets."
23
 
24
- api_key = api_key.strip() # Limpieza de seguridad
25
 
26
  # 2. DEFINICIÓN DE MODELOS (Principal y Respaldo)
27
- # El ID correcto verificado es con '-1-'
28
- primary_model = "black-forest-labs/flux-1-schnell"
29
- backup_model = "stabilityai/stable-diffusion-xl-base-1.0"
30
-
31
  models_to_try = [primary_model, backup_model]
32
-
33
  last_error = ""
34
 
35
  # 3. BUCLE DE INTENTOS
36
  for model in models_to_try:
37
  try:
38
  print(f"🔄 Intentando generar con modelo: {model}...")
 
 
 
39
 
40
  headers = {
41
  "Authorization": f"Bearer {api_key}",
42
- "Content-Type": "application/json",
43
- "HTTP-Referer": "https://huggingface.co",
44
- "X-Title": "Sofia AI Studio",
45
  }
46
-
 
47
  payload = {
48
- "model": model,
49
- "messages": [
50
- {"role": "user", "content": prompt}
51
- ]
52
  }
53
-
 
 
 
 
54
  response = requests.post(
55
- url="https://openrouter.ai/api/v1/chat/completions",
56
  headers=headers,
57
  json=payload,
58
- timeout=45 # Timeout para evitar bloqueos eternos
59
  )
60
 
61
- # Si hay error 400/500, pasamos al siguiente modelo
62
  if response.status_code != 200:
63
  error_detail = response.text
64
  print(f"⚠️ Fallo con {model}: {error_detail}")
65
  last_error = f"Error {response.status_code} en {model}: {error_detail}"
66
- continue # Salta al siguiente modelo del bucle
67
 
68
  # Si es 200 OK, procesamos la imagen
69
- data = response.json()
 
70
 
71
- # OpenRouter devuelve la imagen dentro del contenido del mensaje (Markdown o URL directa)
72
- if "choices" in data and len(data["choices"]) > 0:
73
- content = data['choices'][0]['message']['content']
 
 
 
 
 
 
 
 
74
 
75
- # Buscamos la URL con regex (formatos markdown ![img](url) o url directa)
76
- url_match = re.search(r'\((https://.*?)\)', content)
77
- if not url_match:
78
- url_match = re.search(r'(https://[^\s]+\.(png|jpg|jpeg|webp))', content)
79
 
80
- if url_match:
81
- image_url = url_match.group(1)
82
-
83
- # Descargamos la imagen
84
- img_data = requests.get(image_url).content
85
-
86
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
87
- if seed is None: seed = random.randint(0, 9999)
88
- filename = f"sofia_{timestamp}_{seed}.png"
89
- file_path = os.path.join(OUTPUT_DIR, filename)
90
-
91
- with open(file_path, 'wb') as f:
92
- f.write(img_data)
93
-
94
- return file_path, f"✅ ÉXITO: Imagen creada con {model}"
95
- else:
96
- last_error = f"La API respondió texto pero no vi imagen: {content[:50]}..."
97
- else:
98
- last_error = f"Respuesta vacía o formato desconocido: {data}"
99
 
100
  except Exception as e:
101
  last_error = f"Excepción técnica con {model}: {str(e)}"
102
  continue
103
 
104
  # Si llega aquí, fallaron todos los modelos
105
- return None, f"❌ ERROR FATAL: Fallaron todos los intentos.\nÚltimo error: {last_error}"
 
1
  import os
2
  import requests
3
  import random
4
+ import io
5
  from datetime import datetime
6
  from typing import Optional
7
+ from PIL import Image
8
 
9
  # Configuración de carpetas
10
  OUTPUT_DIR = "generated_images"
 
13
  def generate_image_from_prompt(
14
  prompt: str,
15
  negative_prompt: str = "",
16
+ model_name: str = "ignored", # Este argumento lo ignoramos
17
  seed: Optional[int] = None,
18
  ) -> tuple[Optional[str], str]:
19
 
20
  # 1. VALIDACIÓN DE CREDENCIALES
21
+ # Usamos HF_TOKEN que ya está en el environment de HuggingFace Spaces
22
+ api_key = os.getenv("HF_TOKEN")
23
  if not api_key:
24
+ return None, "❌ Error Crítico: No existe HF_TOKEN en el entorno."
25
 
26
+ api_key = api_key.strip() # Limpieza de seguridad
27
 
28
  # 2. DEFINICIÓN DE MODELOS (Principal y Respaldo)
29
+ # Usando modelos que funcionan con HuggingFace Inference API
30
+ primary_model = "black-forest-labs/FLUX.1-schnell"
31
+ backup_model = "stabilityai/stable-diffusion-2-1"
32
+
33
  models_to_try = [primary_model, backup_model]
34
+
35
  last_error = ""
36
 
37
  # 3. BUCLE DE INTENTOS
38
  for model in models_to_try:
39
  try:
40
  print(f"🔄 Intentando generar con modelo: {model}...")
41
+
42
+ # URL de HuggingFace Inference API
43
+ api_url = f"https://api-inference.huggingface.co/models/{model}"
44
 
45
  headers = {
46
  "Authorization": f"Bearer {api_key}",
47
+ "Content-Type": "application/json"
 
 
48
  }
49
+
50
+ # Payload para generación de imágenes
51
  payload = {
52
+ "inputs": prompt,
 
 
 
53
  }
54
+
55
+ # Añadir negative_prompt si existe
56
+ if negative_prompt:
57
+ payload["negative_prompt"] = negative_prompt
58
+
59
  response = requests.post(
60
+ api_url,
61
  headers=headers,
62
  json=payload,
63
+ timeout=60 # Timeout más largo para generación de imágenes
64
  )
65
 
66
+ # Si hay error, pasamos al siguiente modelo
67
  if response.status_code != 200:
68
  error_detail = response.text
69
  print(f"⚠️ Fallo con {model}: {error_detail}")
70
  last_error = f"Error {response.status_code} en {model}: {error_detail}"
71
+ continue # Salta al siguiente modelo
72
 
73
  # Si es 200 OK, procesamos la imagen
74
+ # HuggingFace Inference API devuelve la imagen directamente como bytes
75
+ image_bytes = response.content
76
 
77
+ # Verificar que recibimos una imagen válida
78
+ try:
79
+ image = Image.open(io.BytesIO(image_bytes))
80
+
81
+ # Guardar la imagen
82
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
83
+ if seed is None: seed = random.randint(0, 999)
84
+ filename = f"sofia_{timestamp}_{seed}.png"
85
+ file_path = os.path.join(OUTPUT_DIR, filename)
86
+
87
+ image.save(file_path)
88
 
89
+ return file_path, f"✅ ÉXITO: Imagen creada con {model}"
 
 
 
90
 
91
+ except Exception as img_error:
92
+ last_error = f"Error al procesar imagen de {model}: {str(img_error)}"
93
+ continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  except Exception as e:
96
  last_error = f"Excepción técnica con {model}: {str(e)}"
97
  continue
98
 
99
  # Si llega aquí, fallaron todos los modelos
100
+ return None, f"❌ ERROR FATAL: Fallaron todos los intentos.\nÚltimo error: {last_error}" return None, f"❌ ERROR FATAL: Fallaron todos los intentos.\nÚltimo error: {last_error}"