Update app.py
Browse files
app.py
CHANGED
|
@@ -83,6 +83,7 @@ class HyperrealisticPromptGenerator:
|
|
| 83 |
def _choose_random(self, options: List[str]) -> str:
|
| 84 |
return random.choice(options)
|
| 85 |
|
|
|
|
| 86 |
def generate_single_prompt(self, role: Optional[str] = None) -> str:
|
| 87 |
selected_role = role if role else self._choose_random(self.ROLES)
|
| 88 |
age = self._choose_random(self.AGES)
|
|
@@ -92,17 +93,21 @@ class HyperrealisticPromptGenerator:
|
|
| 92 |
pose = self._choose_random(self.POSES)
|
| 93 |
setting = self._choose_random(self.SETTINGS)
|
| 94 |
atmosphere = self._choose_random(self.ATMOSPHERES)
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
return prompt
|
| 107 |
|
| 108 |
def generate_prompt_automatic(self):
|
|
@@ -113,6 +118,7 @@ class HyperrealisticPromptGenerator:
|
|
| 113 |
gen = HyperrealisticPromptGenerator()
|
| 114 |
|
| 115 |
# Configuración API SambaNova
|
|
|
|
| 116 |
API_KEY = os.getenv("SAMBANOVA_API_KEY")
|
| 117 |
API_URL = "https://api.sambanova.ai/v1/chat/completions"
|
| 118 |
headers = {
|
|
@@ -122,6 +128,9 @@ headers = {
|
|
| 122 |
|
| 123 |
def analizar_imagen_y_generar_prompt(image_url_or_base64):
|
| 124 |
# Se envía la imagen para obtener una descripción en inglés
|
|
|
|
|
|
|
|
|
|
| 125 |
messages = [
|
| 126 |
{"role": "system", "content": "You are an assistant that describes images in detailed English."},
|
| 127 |
{"role": "user", "content": [
|
|
@@ -139,24 +148,47 @@ def analizar_imagen_y_generar_prompt(image_url_or_base64):
|
|
| 139 |
response.raise_for_status()
|
| 140 |
resp_json = response.json()
|
| 141 |
text_resp = resp_json["choices"][0]["message"]["content"]
|
| 142 |
-
|
|
|
|
|
|
|
|
|
|
| 143 |
return prompt
|
| 144 |
except Exception as e:
|
| 145 |
return f"Error al analizar imagen y generar prompt: {e}"
|
| 146 |
|
| 147 |
def chat_sambanova(user_message, image_input, auto_mode, chat_history):
|
| 148 |
updated_history = chat_history.copy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
|
| 150 |
if auto_mode and image_input:
|
| 151 |
# Modo automático: analizar imagen y generar prompt automáticamente
|
| 152 |
prompt = analizar_imagen_y_generar_prompt(image_input)
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
|
| 157 |
# Modo chat manual: enviar mensaje a SambaNova API
|
| 158 |
messages = [{"role": "system", "content": "Eres un asistente útil"}]
|
| 159 |
for user_msg, ai_msg in updated_history:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
messages.append({"role": "user", "content": [{"type": "text", "text": user_msg}]})
|
| 161 |
messages.append({"role": "assistant", "content": ai_msg})
|
| 162 |
|
|
@@ -176,6 +208,7 @@ def chat_sambanova(user_message, image_input, auto_mode, chat_history):
|
|
| 176 |
response.raise_for_status()
|
| 177 |
|
| 178 |
collected_text = ""
|
|
|
|
| 179 |
updated_history.append((user_message, ""))
|
| 180 |
|
| 181 |
for line in response.iter_lines(decode_unicode=True):
|
|
@@ -191,34 +224,53 @@ def chat_sambanova(user_message, image_input, auto_mode, chat_history):
|
|
| 191 |
|
| 192 |
collected_text += text_fragment
|
| 193 |
|
|
|
|
| 194 |
if updated_history:
|
| 195 |
updated_history[-1] = (updated_history[-1][0], collected_text)
|
| 196 |
|
|
|
|
| 197 |
yield "", updated_history
|
| 198 |
except json.JSONDecodeError:
|
| 199 |
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
except requests.exceptions.RequestException as err:
|
| 201 |
-
error_msg = f"Error: {err}"
|
|
|
|
| 202 |
if not updated_history or updated_history[-1][0] != user_message:
|
| 203 |
updated_history.append((user_message, error_msg))
|
| 204 |
else:
|
| 205 |
updated_history[-1] = (updated_history[-1][0], error_msg)
|
| 206 |
yield "", updated_history
|
| 207 |
-
|
| 208 |
def generar_prompt_interno():
|
|
|
|
| 209 |
return gen.generate_prompt_automatic()
|
| 210 |
|
| 211 |
with gr.Blocks() as demo:
|
|
|
|
|
|
|
| 212 |
chat_history = gr.State([])
|
| 213 |
-
chatbot = gr.Chatbot(label="Chatbot IA")
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
|
|
|
|
| 220 |
btn_send.click(chat_sambanova, inputs=[msg, img_input, auto_mode, chat_history], outputs=[msg, chatbot, chat_history])
|
| 221 |
msg.submit(chat_sambanova, inputs=[msg, img_input, auto_mode, chat_history], outputs=[msg, chatbot, chat_history])
|
| 222 |
|
| 223 |
-
|
| 224 |
-
|
|
|
|
|
|
|
|
|
| 83 |
def _choose_random(self, options: List[str]) -> str:
|
| 84 |
return random.choice(options)
|
| 85 |
|
| 86 |
+
# --- CORRECCIÓN DE SYNTAX ERROR AQUÍ ---
|
| 87 |
def generate_single_prompt(self, role: Optional[str] = None) -> str:
|
| 88 |
selected_role = role if role else self._choose_random(self.ROLES)
|
| 89 |
age = self._choose_random(self.AGES)
|
|
|
|
| 93 |
pose = self._choose_random(self.POSES)
|
| 94 |
setting = self._choose_random(self.SETTINGS)
|
| 95 |
atmosphere = self._choose_random(self.ATMOSPHERES)
|
| 96 |
+
|
| 97 |
+
# Uso de triple comilla f-string para construir el prompt multilínea
|
| 98 |
+
prompt = f"""```
|
| 99 |
+
Role: {selected_role}
|
| 100 |
+
Age: {age}
|
| 101 |
+
Hair: {hair_style} in {hair_color}
|
| 102 |
+
Eyes: {eye_color} with expressive, captivating gaze
|
| 103 |
+
Pose: {pose}
|
| 104 |
+
Environment: {setting}
|
| 105 |
+
Atmosphere: {atmosphere}
|
| 106 |
+
Outfit: {self.CONDITION_FIXED}
|
| 107 |
+
|
| 108 |
+
Technical specs:
|
| 109 |
+
{self.TECHNICAL_DETAILS}
|
| 110 |
+
```"""
|
| 111 |
return prompt
|
| 112 |
|
| 113 |
def generate_prompt_automatic(self):
|
|
|
|
| 118 |
gen = HyperrealisticPromptGenerator()
|
| 119 |
|
| 120 |
# Configuración API SambaNova
|
| 121 |
+
# Asegúrate de que SAMBANOVA_API_KEY esté disponible en tu entorno
|
| 122 |
API_KEY = os.getenv("SAMBANOVA_API_KEY")
|
| 123 |
API_URL = "https://api.sambanova.ai/v1/chat/completions"
|
| 124 |
headers = {
|
|
|
|
| 128 |
|
| 129 |
def analizar_imagen_y_generar_prompt(image_url_or_base64):
|
| 130 |
# Se envía la imagen para obtener una descripción en inglés
|
| 131 |
+
if not API_KEY:
|
| 132 |
+
return "Error: La variable de entorno SAMBANOVA_API_KEY no está configurada."
|
| 133 |
+
|
| 134 |
messages = [
|
| 135 |
{"role": "system", "content": "You are an assistant that describes images in detailed English."},
|
| 136 |
{"role": "user", "content": [
|
|
|
|
| 148 |
response.raise_for_status()
|
| 149 |
resp_json = response.json()
|
| 150 |
text_resp = resp_json["choices"][0]["message"]["content"]
|
| 151 |
+
|
| 152 |
+
# --- CORRECCIÓN DE SYNTAX ERROR AQUÍ ---
|
| 153 |
+
# Envuelve la respuesta en un bloque de código markdown
|
| 154 |
+
prompt = f"```\n{text_resp}\n```"
|
| 155 |
return prompt
|
| 156 |
except Exception as e:
|
| 157 |
return f"Error al analizar imagen y generar prompt: {e}"
|
| 158 |
|
| 159 |
def chat_sambanova(user_message, image_input, auto_mode, chat_history):
|
| 160 |
updated_history = chat_history.copy()
|
| 161 |
+
|
| 162 |
+
if not API_KEY:
|
| 163 |
+
error_msg = "Error: La variable de entorno SAMBANOVA_API_KEY no está configurada."
|
| 164 |
+
updated_history.append((user_message if user_message else "Intento de interacción", error_msg))
|
| 165 |
+
yield "", updated_history
|
| 166 |
+
return
|
| 167 |
|
| 168 |
if auto_mode and image_input:
|
| 169 |
# Modo automático: analizar imagen y generar prompt automáticamente
|
| 170 |
prompt = analizar_imagen_y_generar_prompt(image_input)
|
| 171 |
+
|
| 172 |
+
# El prompt se inyecta como un mensaje de la IA
|
| 173 |
+
ai_msg = f"IA - Prompt automático generado:\n{prompt}"
|
| 174 |
+
|
| 175 |
+
# Si el usuario envió un mensaje, lo mantenemos. Si no, usamos una etiqueta.
|
| 176 |
+
user_display = user_message if user_message else "Análisis de imagen automático"
|
| 177 |
+
updated_history.append((user_display, ai_msg))
|
| 178 |
+
|
| 179 |
+
# Se vacía el mensaje de entrada y se actualiza el chat
|
| 180 |
+
yield "", updated_history
|
| 181 |
+
return
|
| 182 |
|
| 183 |
# Modo chat manual: enviar mensaje a SambaNova API
|
| 184 |
messages = [{"role": "system", "content": "Eres un asistente útil"}]
|
| 185 |
for user_msg, ai_msg in updated_history:
|
| 186 |
+
# Si el mensaje es una tupla, asumimos que el primer elemento es el texto.
|
| 187 |
+
if isinstance(user_msg, str) and user_msg.startswith("IA - Prompt automático generado"):
|
| 188 |
+
# Ignorar los prompts generados internamente para el contexto del modelo
|
| 189 |
+
continue
|
| 190 |
+
|
| 191 |
+
# El historial de Gradio almacena las interacciones, pero el modelo necesita los roles 'user' y 'assistant'
|
| 192 |
messages.append({"role": "user", "content": [{"type": "text", "text": user_msg}]})
|
| 193 |
messages.append({"role": "assistant", "content": ai_msg})
|
| 194 |
|
|
|
|
| 208 |
response.raise_for_status()
|
| 209 |
|
| 210 |
collected_text = ""
|
| 211 |
+
# Agregar el mensaje del usuario con una respuesta vacía inicialmente
|
| 212 |
updated_history.append((user_message, ""))
|
| 213 |
|
| 214 |
for line in response.iter_lines(decode_unicode=True):
|
|
|
|
| 224 |
|
| 225 |
collected_text += text_fragment
|
| 226 |
|
| 227 |
+
# Actualizar la respuesta en el último elemento del historial
|
| 228 |
if updated_history:
|
| 229 |
updated_history[-1] = (updated_history[-1][0], collected_text)
|
| 230 |
|
| 231 |
+
# Usar yield para la respuesta en tiempo real
|
| 232 |
yield "", updated_history
|
| 233 |
except json.JSONDecodeError:
|
| 234 |
continue
|
| 235 |
+
|
| 236 |
+
# Asegurarse de que el último yield se complete
|
| 237 |
+
yield "", updated_history
|
| 238 |
+
|
| 239 |
except requests.exceptions.RequestException as err:
|
| 240 |
+
error_msg = f"Error de conexión con SambaNova: {err}"
|
| 241 |
+
# Asegurarse de que el error se muestre como respuesta
|
| 242 |
if not updated_history or updated_history[-1][0] != user_message:
|
| 243 |
updated_history.append((user_message, error_msg))
|
| 244 |
else:
|
| 245 |
updated_history[-1] = (updated_history[-1][0], error_msg)
|
| 246 |
yield "", updated_history
|
| 247 |
+
|
| 248 |
def generar_prompt_interno():
|
| 249 |
+
# Esta función simplemente llama a generate_prompt_automatic y devuelve el valor
|
| 250 |
return gen.generate_prompt_automatic()
|
| 251 |
|
| 252 |
with gr.Blocks() as demo:
|
| 253 |
+
gr.Markdown("# Hyperrealistic Prompt Generator & Chatbot")
|
| 254 |
+
|
| 255 |
chat_history = gr.State([])
|
| 256 |
+
chatbot = gr.Chatbot(label="Chatbot IA (SambaNova - Llama-4 Maverick)")
|
| 257 |
+
|
| 258 |
+
with gr.Row():
|
| 259 |
+
msg = gr.Textbox(label="Escribe tu mensaje", scale=4)
|
| 260 |
+
img_input = gr.Textbox(label="Imagen base64 o URL (opcional)", placeholder="Pega aquí la imagen o URL", scale=2)
|
| 261 |
+
|
| 262 |
+
with gr.Row():
|
| 263 |
+
auto_mode = gr.Checkbox(label="Modo automático (generar prompt auto desde imagen)", value=False)
|
| 264 |
+
btn_send = gr.Button("Enviar mensaje", variant="primary")
|
| 265 |
+
# --- CORRECCIÓN DE LA FUNCIÓN INCOMPLETA AQUÍ ---
|
| 266 |
+
# El botón de prompt interno ahora pone el prompt generado en el cuadro de texto 'msg'
|
| 267 |
+
btn_gen_prompt = gr.Button("Generar prompt automático interno (al cuadro de texto)", variant="secondary")
|
| 268 |
|
| 269 |
+
# Eventos
|
| 270 |
btn_send.click(chat_sambanova, inputs=[msg, img_input, auto_mode, chat_history], outputs=[msg, chatbot, chat_history])
|
| 271 |
msg.submit(chat_sambanova, inputs=[msg, img_input, auto_mode, chat_history], outputs=[msg, chatbot, chat_history])
|
| 272 |
|
| 273 |
+
# El botón genera el prompt y lo coloca en el cuadro de texto 'msg'
|
| 274 |
+
btn_gen_prompt.click(generar_prompt_interno, inputs=[], outputs=[msg])
|
| 275 |
+
|
| 276 |
+
# demo.launch() # Descomenta para ejecutar la aplicación localmente
|