Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -3,76 +3,78 @@ import os
|
|
3 |
import json
|
4 |
import requests
|
5 |
from datetime import datetime
|
6 |
-
|
7 |
-
# --- Importar la librería de Supabase ---
|
8 |
from supabase import create_client, Client
|
9 |
-
# --- FIN de las importaciones de Supabase ---
|
10 |
|
|
|
|
|
11 |
GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
|
12 |
GROQ_API_URL = "https://api.groq.com/openai/v1/chat/completions"
|
|
|
|
|
13 |
SYSTEM_MESSAGE = os.environ.get("System_Prompt")
|
14 |
-
MODEL_NAME = "
|
15 |
MAX_TOKENS = 4096
|
16 |
TEMPERATURE = 0.7
|
17 |
TOP_P = 0.95
|
18 |
|
19 |
-
# ---
|
20 |
-
# Es CRÍTICO que estas variables de entorno se configuren en tu Hugging Face Space
|
21 |
-
# Ve a Settings -> Repository secrets y añade SUPABASE_URL y SUPABASE_KEY
|
22 |
SUPABASE_URL = os.environ.get("SUPABASE_URL")
|
23 |
SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
|
|
|
24 |
|
25 |
-
|
|
|
26 |
if SUPABASE_URL and SUPABASE_KEY:
|
27 |
-
|
28 |
-
supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
|
29 |
-
print("Supabase cliente inicializado correctamente.")
|
30 |
-
except Exception as e:
|
31 |
-
print(f"Error al inicializar Supabase cliente: {e}")
|
32 |
else:
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
def
|
|
|
|
|
|
|
|
|
38 |
if not supabase:
|
39 |
-
|
40 |
-
return
|
41 |
|
42 |
try:
|
43 |
-
#
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
# Realiza la inserción en Supabase
|
57 |
-
# .insert() devuelve una tupla, el primer elemento es el resultado y el segundo es el count de registros afectados
|
58 |
-
response = supabase.table('conversations').insert(data_to_insert).execute()
|
59 |
-
|
60 |
-
# Supabase devuelve el resultado de la inserción en el atributo 'data' del objeto response.
|
61 |
-
# Verifica si la inserción fue exitosa
|
62 |
-
if response.data:
|
63 |
-
print(f"Conversación guardada en Supabase. ID de sesión: {response.data[0].get('id')}")
|
64 |
else:
|
65 |
-
|
66 |
|
67 |
except Exception as e:
|
68 |
-
print(f"
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
|
|
|
76 |
messages = [{"role": "system", "content": SYSTEM_MESSAGE}]
|
77 |
for user_msg, assistant_msg in history:
|
78 |
if user_msg:
|
@@ -94,13 +96,16 @@ def respond(message, history: list[tuple[str, str]]):
|
|
94 |
"stream": True
|
95 |
}
|
96 |
|
97 |
-
|
98 |
-
|
99 |
-
headers=headers,
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
|
|
103 |
|
|
|
104 |
accumulated_response = ""
|
105 |
for line in response.iter_lines():
|
106 |
if line:
|
@@ -119,15 +124,27 @@ def respond(message, history: list[tuple[str, str]]):
|
|
119 |
yield accumulated_response
|
120 |
except json.JSONDecodeError:
|
121 |
continue
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
125 |
else:
|
126 |
-
|
127 |
-
|
|
|
|
|
|
|
|
|
128 |
|
129 |
demo = gr.ChatInterface(
|
130 |
respond,
|
|
|
|
|
|
|
131 |
examples=[["¡Bienvenido a Tu Aliado Momentum!"],
|
132 |
["¿En qué consiste el programa y para quién es?"],
|
133 |
["¿Qué beneficios obtengo y con qué empresas me conecto?"],
|
|
|
3 |
import json
|
4 |
import requests
|
5 |
from datetime import datetime
|
6 |
+
import uuid # Necesario para generar IDs únicos para cada conversación
|
|
|
7 |
from supabase import create_client, Client
|
|
|
8 |
|
9 |
+
# --- CONFIGURACIÓN ---
|
10 |
+
# Clave de la API de Groq
|
11 |
GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
|
12 |
GROQ_API_URL = "https://api.groq.com/openai/v1/chat/completions"
|
13 |
+
|
14 |
+
# Configuración del modelo y el sistema
|
15 |
SYSTEM_MESSAGE = os.environ.get("System_Prompt")
|
16 |
+
MODEL_NAME = "llama3-70b-8192" # Modelo actualizado y recomendado
|
17 |
MAX_TOKENS = 4096
|
18 |
TEMPERATURE = 0.7
|
19 |
TOP_P = 0.95
|
20 |
|
21 |
+
# --- NUEVA CONFIGURACIÓN DE SUPERBASE ---
|
|
|
|
|
22 |
SUPABASE_URL = os.environ.get("SUPABASE_URL")
|
23 |
SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
|
24 |
+
TABLE_NAME = "conversations" # Asegúrate que este sea el nombre de tu tabla
|
25 |
|
26 |
+
# Inicializar el cliente de Supabase
|
27 |
+
# Se verifica que las credenciales existan antes de crear el cliente
|
28 |
if SUPABASE_URL and SUPABASE_KEY:
|
29 |
+
supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
|
|
|
|
|
|
|
|
|
30 |
else:
|
31 |
+
supabase = None
|
32 |
+
print("Advertencia: Las credenciales de Supabase no están configuradas. El historial de chat no se guardará.")
|
33 |
+
|
34 |
+
# --- FUNCIÓN DE PERSISTENCIA MODIFICADA PARA SUPABASE ---
|
35 |
+
def persist_conversation(conversation_id: uuid.UUID, user_id: str, messages_data: list):
|
36 |
+
"""
|
37 |
+
Guarda o actualiza una conversación completa en la tabla de Supabase.
|
38 |
+
Usa 'upsert' para insertar si es nueva o actualizar si ya existe.
|
39 |
+
"""
|
40 |
if not supabase:
|
41 |
+
return # No hacer nada si el cliente no se inicializó
|
|
|
42 |
|
43 |
try:
|
44 |
+
# El método 'upsert' es ideal: inserta una nueva fila si el 'id' no existe,
|
45 |
+
# o la actualiza si ya existe. Esto es perfecto para guardar el estado de
|
46 |
+
# una conversación en curso.
|
47 |
+
response = supabase.table(TABLE_NAME).upsert({
|
48 |
+
"id": str(conversation_id),
|
49 |
+
"timestamp": datetime.now().isoformat(), # Usamos formato ISO 8601 que Supabase entiende
|
50 |
+
"user_id": str(user_id), # Basado en tu columna 'user_id'
|
51 |
+
"messages": messages_data # Guardamos la lista de mensajes como JSONB
|
52 |
+
}).execute()
|
53 |
+
|
54 |
+
# Opcional: Verificar si hubo un error en la respuesta de Supabase
|
55 |
+
if hasattr(response, 'error') and response.error:
|
56 |
+
print(f"Error al guardar en Supabase: {response.error}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
else:
|
58 |
+
print(f"Conversación {conversation_id} guardada/actualizada en Supabase.")
|
59 |
|
60 |
except Exception as e:
|
61 |
+
print(f"Ocurrió una excepción al intentar guardar en Supabase: {e}")
|
62 |
+
|
63 |
+
# --- FUNCIÓN PRINCIPAL DEL CHATBOT (MODIFICADA) ---
|
64 |
+
def respond(message: str, history: list[tuple[str, str]], conversation_id: uuid.UUID):
|
65 |
+
"""
|
66 |
+
Función principal que procesa la entrada del usuario, llama a la API de Groq y guarda la conversación.
|
67 |
+
"""
|
68 |
+
# Si 'conversation_id' es None, significa que es el primer mensaje de una nueva conversación.
|
69 |
+
if conversation_id is None:
|
70 |
+
conversation_id = uuid.uuid4()
|
71 |
+
# Para la columna 'user_id', podemos usar el mismo ID de la conversación
|
72 |
+
# si no tienes un sistema de usuarios más complejo.
|
73 |
+
user_id = conversation_id
|
74 |
+
else:
|
75 |
+
user_id = conversation_id # Mantener el mismo user_id
|
76 |
|
77 |
+
# Construir el payload para la API de Groq
|
78 |
messages = [{"role": "system", "content": SYSTEM_MESSAGE}]
|
79 |
for user_msg, assistant_msg in history:
|
80 |
if user_msg:
|
|
|
96 |
"stream": True
|
97 |
}
|
98 |
|
99 |
+
# Llamada a la API de Groq
|
100 |
+
try:
|
101 |
+
response = requests.post(GROQ_API_URL, headers=headers, json=payload, stream=True, timeout=10)
|
102 |
+
response.raise_for_status() # Lanza un error si la respuesta es 4xx o 5xx
|
103 |
+
except requests.exceptions.RequestException as e:
|
104 |
+
print(f"Error en la petición a la API de Groq: {e}")
|
105 |
+
yield "Lo siento, no pude conectarme con el servicio en este momento. Inténtalo de nuevo más tarde."
|
106 |
+
return
|
107 |
|
108 |
+
# Procesar la respuesta en streaming
|
109 |
accumulated_response = ""
|
110 |
for line in response.iter_lines():
|
111 |
if line:
|
|
|
124 |
yield accumulated_response
|
125 |
except json.JSONDecodeError:
|
126 |
continue
|
127 |
+
|
128 |
+
# Después de obtener la respuesta completa, la guardamos en Supabase
|
129 |
+
if accumulated_response:
|
130 |
+
# Formateamos el historial completo para la columna 'messages' (JSONB)
|
131 |
+
# Esto es mucho más útil que un archivo de texto plano.
|
132 |
+
full_history_for_db = messages + [{"role": "assistant", "content": accumulated_response}]
|
133 |
+
|
134 |
+
persist_conversation(conversation_id, user_id, full_history_for_db)
|
135 |
else:
|
136 |
+
yield "Lo siento, ocurrió un error al procesar tu solicitud."
|
137 |
+
|
138 |
+
# --- INTERFAZ DE GRADIO (MODIFICADA) ---
|
139 |
+
# Usamos gr.State para mantener el ID de la conversación a través de múltiples turnos
|
140 |
+
# en la misma sesión del navegador.
|
141 |
+
conversation_id_state = gr.State(value=None)
|
142 |
|
143 |
demo = gr.ChatInterface(
|
144 |
respond,
|
145 |
+
additional_inputs=[conversation_id_state], # Pasamos el estado como una entrada adicional
|
146 |
+
title="Tu Aliado Momentum",
|
147 |
+
description="Chatea conmigo para saber más sobre el programa Momentum.",
|
148 |
examples=[["¡Bienvenido a Tu Aliado Momentum!"],
|
149 |
["¿En qué consiste el programa y para quién es?"],
|
150 |
["¿Qué beneficios obtengo y con qué empresas me conecto?"],
|