Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -3,90 +3,76 @@ import os
|
|
3 |
import json
|
4 |
import requests
|
5 |
from datetime import datetime
|
6 |
-
import uuid #
|
7 |
-
from supabase import create_client, Client
|
8 |
|
9 |
-
# ---
|
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
|
15 |
SYSTEM_MESSAGE = os.environ.get("System_Prompt")
|
16 |
-
MODEL_NAME = "
|
17 |
MAX_TOKENS = 4096
|
18 |
TEMPERATURE = 0.7
|
19 |
TOP_P = 0.95
|
20 |
|
21 |
-
# ---
|
|
|
22 |
SUPABASE_URL = os.environ.get("SUPABASE_URL")
|
23 |
SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
|
24 |
-
|
25 |
-
|
26 |
-
|
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
|
38 |
-
|
39 |
"""
|
40 |
-
|
41 |
-
|
|
|
|
|
42 |
|
43 |
try:
|
44 |
-
#
|
45 |
-
|
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 |
-
|
61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
-
#
|
64 |
-
|
65 |
-
|
66 |
-
|
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 |
-
|
|
|
|
|
|
|
|
|
78 |
messages = [{"role": "system", "content": SYSTEM_MESSAGE}]
|
|
|
79 |
for user_msg, assistant_msg in history:
|
80 |
if user_msg:
|
81 |
messages.append({"role": "user", "content": user_msg})
|
82 |
if assistant_msg:
|
83 |
messages.append({"role": "assistant", "content": assistant_msg})
|
|
|
84 |
messages.append({"role": "user", "content": message})
|
85 |
|
86 |
headers = {
|
87 |
"Content-Type": "application/json",
|
88 |
"Authorization": f"Bearer {GROQ_API_KEY}"
|
89 |
}
|
|
|
90 |
payload = {
|
91 |
"model": MODEL_NAME,
|
92 |
"messages": messages,
|
@@ -96,24 +82,23 @@ def respond(message: str, history: list[tuple[str, str]], conversation_id: uuid.
|
|
96 |
"stream": True
|
97 |
}
|
98 |
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
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:
|
112 |
line_text = line.decode('utf-8')
|
113 |
if line_text.startswith("data: "):
|
114 |
data_str = line_text[6:]
|
|
|
115 |
if data_str == "[DONE]":
|
116 |
break
|
|
|
117 |
try:
|
118 |
data = json.loads(data_str)
|
119 |
if 'choices' in data and len(data['choices']) > 0:
|
@@ -123,28 +108,21 @@ def respond(message: str, history: list[tuple[str, str]], conversation_id: uuid.
|
|
123 |
accumulated_response += token
|
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 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
|
|
|
|
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="
|
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?"],
|
|
|
3 |
import json
|
4 |
import requests
|
5 |
from datetime import datetime
|
6 |
+
import uuid # NUEVO: Para generar IDs únicos si se necesita en el futuro
|
7 |
+
from supabase import create_client, Client # NUEVO: Importamos el cliente de Supabase
|
8 |
|
9 |
+
# --- Credenciales de Groq (sin cambios) ---
|
|
|
10 |
GROQ_API_KEY = os.environ.get("GROQ_API_KEY")
|
11 |
GROQ_API_URL = "https://api.groq.com/openai/v1/chat/completions"
|
12 |
|
13 |
+
# --- Configuración del Modelo (sin cambios) ---
|
14 |
SYSTEM_MESSAGE = os.environ.get("System_Prompt")
|
15 |
+
MODEL_NAME = "meta-llama/llama-4-maverick-17b-128e-instruct"
|
16 |
MAX_TOKENS = 4096
|
17 |
TEMPERATURE = 0.7
|
18 |
TOP_P = 0.95
|
19 |
|
20 |
+
# --- NUEVO: Credenciales de Supabase ---
|
21 |
+
# Asegúrate de haber configurado estas variables de entorno en tu Space de Hugging Face
|
22 |
SUPABASE_URL = os.environ.get("SUPABASE_URL")
|
23 |
SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
|
24 |
+
|
25 |
+
# --- CAMBIADO: La función persist_data ahora usa Supabase ---
|
26 |
+
def persist_data(session_data, user_identifier=None):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
"""
|
28 |
+
Guarda el historial de la conversación en una tabla de Supabase.
|
29 |
+
Cada llamada inserta una nueva fila con el estado completo de la conversación.
|
30 |
"""
|
31 |
+
# Verifica que las credenciales de Supabase estén configuradas
|
32 |
+
if not SUPABASE_URL or not SUPABASE_KEY:
|
33 |
+
print("Advertencia: Las credenciales de Supabase (URL y KEY) no están configuradas. No se guardará la conversación.")
|
34 |
+
return
|
35 |
|
36 |
try:
|
37 |
+
# Inicializa el cliente de Supabase
|
38 |
+
supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
|
40 |
+
# Prepara los datos para insertar. Esto debe coincidir con tus columnas.
|
41 |
+
# La columna 'id' (uuid) y 'timestamp' (timestamptz) se pueden generar automáticamente
|
42 |
+
# por Supabase si las configuras con un valor por defecto (gen_random_uuid() y now()).
|
43 |
+
# Aquí enviamos el timestamp explícitamente.
|
44 |
+
data_to_insert = {
|
45 |
+
"timestamp": datetime.now().isoformat(),
|
46 |
+
"user_id": user_identifier, # Puedes dejarlo como None si no manejas usuarios
|
47 |
+
"messages": json.dumps(session_data) # Convertimos la lista de tuplas a un string JSON
|
48 |
+
}
|
49 |
|
50 |
+
# Inserta los datos en tu tabla. ¡CAMBIA 'conversations' POR EL NOMBRE REAL DE TU TABLA!
|
51 |
+
table_name = "conversations" # <--- ¡IMPORTANTE! Usa el nombre de tu tabla
|
52 |
+
response = supabase.table(table_name).insert(data_to_insert).execute()
|
53 |
+
|
54 |
+
print(f"Conversación guardada en Supabase exitosamente. Respuesta: {response.data}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
+
except Exception as e:
|
57 |
+
print(f"Error al guardar datos en Supabase: {e}")
|
58 |
+
|
59 |
+
# --- La función respond permanece casi igual ---
|
60 |
+
def respond(message, history: list[tuple[str, str]]):
|
61 |
messages = [{"role": "system", "content": SYSTEM_MESSAGE}]
|
62 |
+
|
63 |
for user_msg, assistant_msg in history:
|
64 |
if user_msg:
|
65 |
messages.append({"role": "user", "content": user_msg})
|
66 |
if assistant_msg:
|
67 |
messages.append({"role": "assistant", "content": assistant_msg})
|
68 |
+
|
69 |
messages.append({"role": "user", "content": message})
|
70 |
|
71 |
headers = {
|
72 |
"Content-Type": "application/json",
|
73 |
"Authorization": f"Bearer {GROQ_API_KEY}"
|
74 |
}
|
75 |
+
|
76 |
payload = {
|
77 |
"model": MODEL_NAME,
|
78 |
"messages": messages,
|
|
|
82 |
"stream": True
|
83 |
}
|
84 |
|
85 |
+
response = requests.post(
|
86 |
+
GROQ_API_URL,
|
87 |
+
headers=headers,
|
88 |
+
json=payload,
|
89 |
+
stream=True
|
90 |
+
)
|
|
|
|
|
91 |
|
|
|
92 |
accumulated_response = ""
|
93 |
for line in response.iter_lines():
|
94 |
if line:
|
95 |
line_text = line.decode('utf-8')
|
96 |
if line_text.startswith("data: "):
|
97 |
data_str = line_text[6:]
|
98 |
+
|
99 |
if data_str == "[DONE]":
|
100 |
break
|
101 |
+
|
102 |
try:
|
103 |
data = json.loads(data_str)
|
104 |
if 'choices' in data and len(data['choices']) > 0:
|
|
|
108 |
accumulated_response += token
|
109 |
yield accumulated_response
|
110 |
except json.JSONDecodeError:
|
111 |
+
print(f"Error decodificando JSON: {data_str}")
|
112 |
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
|
114 |
+
if not accumulated_response:
|
115 |
+
yield "Lo siento, ocurrió un error al procesar tu solicitud."
|
116 |
+
else:
|
117 |
+
# Al final de una respuesta exitosa, guarda la conversación completa
|
118 |
+
current_session = history + [(message, accumulated_response)]
|
119 |
+
persist_data(current_session) # Llamamos a la nueva función
|
120 |
|
121 |
+
# --- Interfaz de Gradio (sin cambios) ---
|
122 |
demo = gr.ChatInterface(
|
123 |
respond,
|
|
|
124 |
title="Tu Aliado Momentum",
|
125 |
+
description="Chatbot para resolver tus dudas sobre el programa Momentum.",
|
126 |
examples=[["¡Bienvenido a Tu Aliado Momentum!"],
|
127 |
["¿En qué consiste el programa y para quién es?"],
|
128 |
["¿Qué beneficios obtengo y con qué empresas me conecto?"],
|