Danielbrdz commited on
Commit
a599d3b
·
verified ·
1 Parent(s): 500b4f9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -79
app.py CHANGED
@@ -3,90 +3,76 @@ import os
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:
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
- # 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:
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
- # --- 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?"],
 
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?"],