appinitdev commited on
Commit
1ab77c9
·
verified ·
1 Parent(s): 53c43ed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -50
app.py CHANGED
@@ -1,81 +1,56 @@
1
  import os
2
- import base64
3
  import traceback
4
- import requests
5
  import gradio as gr
6
-
7
- # URL del modelo en el ecosistema Serverless de Hugging Face
8
- API_URL = "https://api-inference.huggingface.co/models/joyfox/Qwen-Image-Edit-Cosplay"
9
 
10
  def fusionar_cosplay_bridge(imagen_real, imagen_ref):
11
- # 🌟 CRÍTICO: Leemos el Secret dentro de la función para asegurar que
12
- # esté disponible en el hilo de ejecución activo.
13
  hf_token = os.getenv("HF_TOKEN")
14
-
15
  if not hf_token:
16
  print("[-] ERROR: El HF_TOKEN no está configurado en los Secrets del Space.")
17
  raise gr.Error("Falta el token HF_TOKEN en el servidor.")
18
 
19
  try:
20
- print("[+] Petición recibida. Validando cadenas de entrada...")
 
 
 
 
21
 
22
- # Sanitizamos los Strings Base64 agregando el prefijo Data URI requerido por Qwen
23
  data_uri_real = imagen_real if imagen_real.startswith("data:") else f"data:image/jpeg;base64,{imagen_real}"
24
  data_uri_ref = imagen_ref if imagen_ref.startswith("data:") else f"data:image/jpeg;base64,{imagen_ref}"
25
 
26
- # Prompt optimizado puramente en caracteres originales para evitar problemas de codificación UTF-8
27
- prompt_texto = "把图2中动漫人物中的发型,服饰和装扮道具迁移到图1 de 真实人物,图1真实人物保持高度人脸一致性"
28
-
29
- json_payload = {
30
- "inputs": {
31
- "text": prompt_texto,
32
- "images": [data_uri_real, data_uri_ref]
33
- },
34
- "parameters": {
35
- "max_new_tokens": 512
36
- }
37
- }
38
 
39
- headers = {
40
- "Authorization": f"Bearer {hf_token}",
41
- "Content-Type": "application/json"
42
- }
43
 
44
- print("[+] Enviando payload a la API de Inferencia...")
45
- respuesta = requests.post(API_URL, headers=headers, json=json_payload, timeout=110)
46
- print(f"[+] Respuesta del modelo recibida con código: {respuesta.status_code}")
 
 
 
 
47
 
48
- if respuesta.status_code == 200:
49
- content_type = respuesta.headers.get("content-type", "").lower()
50
- if "application/json" in content_type:
51
- return respuesta.json()
52
- else:
53
- # Si la API retorna los bytes crudos de la imagen, la convertimos a Data URI estándar
54
- imagen_procesada_base64 = base64.b64encode(respuesta.content).decode("utf-8")
55
- return {"data": [f"data:image/jpeg;base64,{imagen_procesada_base64}"]}
56
- else:
57
- print(f"[-] Error de Hugging Face API: {respuesta.text}")
58
- raise gr.Error(f"HF API Error: {respuesta.status_code}")
59
 
60
  except Exception as e:
61
  print("\n================= CRASH EN EL PUENTE =================")
62
  traceback.print_exc()
63
  print("=====================================================\n")
64
- raise gr.Error(f"Crash interno: {str(e)}")
65
 
66
- # Usamos la clase Interface nativa. Al asignarle api_name="predict",
67
- # Gradio mapea automáticamente un endpoint POST HTTP puro en la ruta /api/predict
68
  demo = gr.Interface(
69
  fn=fusionar_cosplay_bridge,
70
- inputs=[
71
- gr.Textbox(label="Imagen Real Base64"),
72
- gr.Textbox(label="Imagen Referencia Base64")
73
- ],
74
- outputs=gr.JSON(label="Resultado JSON"),
75
  api_name="predict"
76
  )
77
 
78
- # 🌟 Deshabilitamos el Server-Side Rendering (SSR) experimental de Gradio 6
79
- # para que no interfiera con llamadas de red crudas hechas desde Ktor (Android).
80
  if __name__ == "__main__":
81
  demo.launch(ssr_mode=False)
 
1
  import os
 
2
  import traceback
 
3
  import gradio as gr
4
+ from gradio_client import Client
 
 
5
 
6
  def fusionar_cosplay_bridge(imagen_real, imagen_ref):
7
+ # 1. Validamos dinámicamente que el token exista en los Secrets
 
8
  hf_token = os.getenv("HF_TOKEN")
 
9
  if not hf_token:
10
  print("[-] ERROR: El HF_TOKEN no está configurado en los Secrets del Space.")
11
  raise gr.Error("Falta el token HF_TOKEN en el servidor.")
12
 
13
  try:
14
+ print("[+] Petición recibida desde Android. Inicializando cliente nativo del clúster...")
15
+
16
+ # 2. Inicializamos el cliente oficial de Hugging Face.
17
+ # Al apuntar al identificador del modelo, el clúster resuelve la red de forma interna sin pasar por DNS externos.
18
+ hf_client = Client("joyfox/Qwen-Image-Edit-Cosplay", hf_token=hf_token)
19
 
20
+ # Aseguramos el prefijo Data URI limpio
21
  data_uri_real = imagen_real if imagen_real.startswith("data:") else f"data:image/jpeg;base64,{imagen_real}"
22
  data_uri_ref = imagen_ref if imagen_ref.startswith("data:") else f"data:image/jpeg;base64,{imagen_ref}"
23
 
24
+ prompt_texto = "把图2中动漫人物中的发型,服饰和装扮道具迁移到图1的真实人物,图1真实人物保持高度人脸一致性"
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ print("[+] Enviando parámetros al pipeline de Qwen...")
 
 
 
27
 
28
+ # Ejecutamos la predicción usando el contrato de parámetros exacto del modelo
29
+ resultado = hf_client.predict(
30
+ parameter_0=data_uri_real,
31
+ parameter_1=data_uri_ref,
32
+ parameter_2=prompt_texto,
33
+ api_name="/predict"
34
+ )
35
 
36
+ print("[+] Fusión completada con éxito.")
37
+ # El cliente nativo devuelve la estructura limpia o la URL local del archivo procesado
38
+ return {"data": resultado}
 
 
 
 
 
 
 
 
39
 
40
  except Exception as e:
41
  print("\n================= CRASH EN EL PUENTE =================")
42
  traceback.print_exc()
43
  print("=====================================================\n")
44
+ raise gr.Error(f"Crash interno en el cliente del modelo: {str(e)}")
45
 
46
+ # 3. Mapeamos la interfaz limpia para Android
 
47
  demo = gr.Interface(
48
  fn=fusionar_cosplay_bridge,
49
+ inputs=[gr.Textbox(label="Real"), gr.Textbox(label="Ref")],
50
+ outputs=gr.JSON(label="Resultado"),
 
 
 
51
  api_name="predict"
52
  )
53
 
54
+ # Apagamos el SSR para que mantenga comunicación directa con Ktor sin middlewares intermedios
 
55
  if __name__ == "__main__":
56
  demo.launch(ssr_mode=False)