Spaces:
Sleeping
Sleeping
Commit
·
1b3cdee
1
Parent(s):
49557ca
Fix supabase_client error
Browse files- supabase_client.py +30 -7
- tools.py +87 -27
supabase_client.py
CHANGED
@@ -6,6 +6,7 @@ import json
|
|
6 |
import logging
|
7 |
|
8 |
from utils.classes import Order
|
|
|
9 |
# Configurar logging
|
10 |
logging.basicConfig(level=logging.INFO)
|
11 |
logger = logging.getLogger(__name__)
|
@@ -26,13 +27,26 @@ class SupabaseOrderManager:
|
|
26 |
self.supabase_url = url or os.getenv("SUPABASE_URL")
|
27 |
self.supabase_key = key or os.getenv("SUPABASE_KEY")
|
28 |
|
|
|
29 |
if not self.supabase_url or not self.supabase_key:
|
30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
31 |
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
36 |
async def send_order(self, order: Order) -> Dict[str, Any]:
|
37 |
"""
|
38 |
Envía una orden a Supabase.
|
@@ -47,6 +61,8 @@ class SupabaseOrderManager:
|
|
47 |
# Convertir el objeto Order a un diccionario
|
48 |
order_dict = order.to_dict()
|
49 |
|
|
|
|
|
50 |
# 1. Insertar la orden principal
|
51 |
order_data = {
|
52 |
"order_id": order_dict["order_id"],
|
@@ -56,13 +72,15 @@ class SupabaseOrderManager:
|
|
56 |
}
|
57 |
|
58 |
# Realizar la inserción de la orden
|
|
|
59 |
order_response = self.supabase.table("orders").insert(order_data).execute()
|
60 |
|
61 |
if not order_response.data:
|
62 |
-
raise Exception("Error al insertar orden en Supabase")
|
63 |
|
64 |
# Obtener el ID de la orden insertada
|
65 |
db_order_id = order_response.data[0]["id"]
|
|
|
66 |
|
67 |
# 2. Insertar los elementos de la orden
|
68 |
items_to_insert = []
|
@@ -76,18 +94,23 @@ class SupabaseOrderManager:
|
|
76 |
|
77 |
# Realizar la inserción de los elementos
|
78 |
if items_to_insert:
|
|
|
79 |
items_response = self.supabase.table("order_items").insert(items_to_insert).execute()
|
80 |
|
81 |
if not items_response.data:
|
82 |
# Si falla la inserción de items, eliminamos la orden para mantener consistencia
|
|
|
83 |
self.supabase.table("orders").delete().eq("id", db_order_id).execute()
|
84 |
raise Exception("Error al insertar elementos de la orden en Supabase")
|
|
|
|
|
85 |
|
86 |
logger.info(f"Orden {order_dict['order_id']} enviada correctamente a Supabase")
|
87 |
return {
|
88 |
"success": True,
|
89 |
"order_id": order_dict["order_id"],
|
90 |
-
"database_id": db_order_id
|
|
|
91 |
}
|
92 |
|
93 |
except Exception as e:
|
|
|
6 |
import logging
|
7 |
|
8 |
from utils.classes import Order
|
9 |
+
|
10 |
# Configurar logging
|
11 |
logging.basicConfig(level=logging.INFO)
|
12 |
logger = logging.getLogger(__name__)
|
|
|
27 |
self.supabase_url = url or os.getenv("SUPABASE_URL")
|
28 |
self.supabase_key = key or os.getenv("SUPABASE_KEY")
|
29 |
|
30 |
+
# Validar que las credenciales existan
|
31 |
if not self.supabase_url or not self.supabase_key:
|
32 |
+
error_msg = (
|
33 |
+
"SUPABASE_URL y SUPABASE_KEY deben estar definidos como variables de entorno "
|
34 |
+
"o proporcionados como parámetros. "
|
35 |
+
f"URL encontrada: {'✓' if self.supabase_url else '✗'}, "
|
36 |
+
f"KEY encontrada: {'✓' if self.supabase_key else '✗'}"
|
37 |
+
)
|
38 |
+
logger.error(error_msg)
|
39 |
+
raise ValueError(error_msg)
|
40 |
|
41 |
+
try:
|
42 |
+
# Inicializar cliente
|
43 |
+
self.supabase = create_client(self.supabase_url, self.supabase_key)
|
44 |
+
logger.info("Cliente Supabase inicializado correctamente")
|
45 |
+
|
46 |
+
except Exception as e:
|
47 |
+
logger.error(f"Error al inicializar cliente Supabase: {e}")
|
48 |
+
raise
|
49 |
+
|
50 |
async def send_order(self, order: Order) -> Dict[str, Any]:
|
51 |
"""
|
52 |
Envía una orden a Supabase.
|
|
|
61 |
# Convertir el objeto Order a un diccionario
|
62 |
order_dict = order.to_dict()
|
63 |
|
64 |
+
logger.info(f"Iniciando envío de orden {order_dict['order_id']} a Supabase")
|
65 |
+
|
66 |
# 1. Insertar la orden principal
|
67 |
order_data = {
|
68 |
"order_id": order_dict["order_id"],
|
|
|
72 |
}
|
73 |
|
74 |
# Realizar la inserción de la orden
|
75 |
+
logger.debug(f"Insertando orden principal: {order_data}")
|
76 |
order_response = self.supabase.table("orders").insert(order_data).execute()
|
77 |
|
78 |
if not order_response.data:
|
79 |
+
raise Exception("Error al insertar orden en Supabase - respuesta vacía")
|
80 |
|
81 |
# Obtener el ID de la orden insertada
|
82 |
db_order_id = order_response.data[0]["id"]
|
83 |
+
logger.info(f"Orden insertada con ID de base de datos: {db_order_id}")
|
84 |
|
85 |
# 2. Insertar los elementos de la orden
|
86 |
items_to_insert = []
|
|
|
94 |
|
95 |
# Realizar la inserción de los elementos
|
96 |
if items_to_insert:
|
97 |
+
logger.debug(f"Insertando {len(items_to_insert)} elementos de la orden")
|
98 |
items_response = self.supabase.table("order_items").insert(items_to_insert).execute()
|
99 |
|
100 |
if not items_response.data:
|
101 |
# Si falla la inserción de items, eliminamos la orden para mantener consistencia
|
102 |
+
logger.error("Fallo al insertar elementos, eliminando orden para mantener consistencia")
|
103 |
self.supabase.table("orders").delete().eq("id", db_order_id).execute()
|
104 |
raise Exception("Error al insertar elementos de la orden en Supabase")
|
105 |
+
|
106 |
+
logger.info(f"Insertados {len(items_response.data)} elementos correctamente")
|
107 |
|
108 |
logger.info(f"Orden {order_dict['order_id']} enviada correctamente a Supabase")
|
109 |
return {
|
110 |
"success": True,
|
111 |
"order_id": order_dict["order_id"],
|
112 |
+
"database_id": db_order_id,
|
113 |
+
"items_count": len(items_to_insert)
|
114 |
}
|
115 |
|
116 |
except Exception as e:
|
tools.py
CHANGED
@@ -10,12 +10,35 @@ from utils.classes import Order
|
|
10 |
|
11 |
from supabase_client import SupabaseOrderManager
|
12 |
import asyncio
|
|
|
|
|
13 |
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
|
21 |
def create_menu_info_tool(retriever: VectorStoreRetriever) -> Tool:
|
@@ -52,19 +75,19 @@ def create_menu_info_tool(retriever: VectorStoreRetriever) -> Tool:
|
|
52 |
return "Lo siento, no tengo información sobre eso."
|
53 |
|
54 |
return Tool(
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
)
|
68 |
|
69 |
def create_send_to_kitchen_tool(llm: ChatOpenAI) -> Tool:
|
70 |
"""
|
@@ -167,6 +190,28 @@ def create_send_to_kitchen_tool(llm: ChatOpenAI) -> Tool:
|
|
167 |
log_info(f"Procesando resumen para enviar pedido a cocina...")
|
168 |
log_debug(f"Resumen recibido: {conversation_summary}")
|
169 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
# Extraer el pedido a partir del resumen
|
171 |
order = extract_order_from_summary(conversation_summary)
|
172 |
|
@@ -187,12 +232,11 @@ def create_send_to_kitchen_tool(llm: ChatOpenAI) -> Tool:
|
|
187 |
log_warn("No se identificaron artículos en el pedido")
|
188 |
return "No se pudo identificar ningún artículo en el pedido. ¿Podría repetir su pedido, por favor?"
|
189 |
|
190 |
-
#
|
191 |
order_dict = order.to_dict()
|
192 |
log_info(f"ENVIANDO PEDIDO A COCINA: {json.dumps(order_dict, indent=2, ensure_ascii=False)}")
|
193 |
|
194 |
-
#
|
195 |
-
# Por ejemplo, enviar a una API, base de datos, etc.
|
196 |
async def async_send_and_get_result(order):
|
197 |
return await supabase.send_order(order)
|
198 |
|
@@ -211,16 +255,32 @@ def create_send_to_kitchen_tool(llm: ChatOpenAI) -> Tool:
|
|
211 |
log_debug(traceback.format_exc())
|
212 |
return "Lo siento, hubo un problema al procesar su pedido. ¿Podría intentarlo de nuevo?"
|
213 |
|
214 |
-
#
|
215 |
-
|
216 |
-
|
217 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
Envía el pedido completo a la cocina. Usa esta herramienta SOLAMENTE cuando el cliente haya terminado de hacer su pedido
|
219 |
completo y esté listo para enviarlo.
|
220 |
|
221 |
Esta herramienta espera recibir un RESUMEN de la conversación que describe los elementos del pedido.
|
222 |
No envíes la conversación completa, solo un resumen claro de lo que el cliente ha pedido, la mesa,
|
223 |
y cualquier instrucción especial relevante.
|
224 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
225 |
func=send_to_kitchen,
|
226 |
-
)
|
|
|
10 |
|
11 |
from supabase_client import SupabaseOrderManager
|
12 |
import asyncio
|
13 |
+
import os
|
14 |
+
from dotenv import load_dotenv
|
15 |
|
16 |
+
# Cargar variables de entorno
|
17 |
+
load_dotenv()
|
18 |
+
|
19 |
+
# Intentar inicializar Supabase de forma segura
|
20 |
+
def init_supabase_client():
|
21 |
+
"""Inicializa el cliente de Supabase de forma segura."""
|
22 |
+
try:
|
23 |
+
# Verificar si las variables de entorno están disponibles
|
24 |
+
supabase_url = os.getenv("SUPABASE_URL")
|
25 |
+
supabase_key = os.getenv("SUPABASE_KEY")
|
26 |
+
|
27 |
+
if not supabase_url or not supabase_key:
|
28 |
+
log_warn("Variables de entorno de Supabase no encontradas. Funcionando sin base de datos.")
|
29 |
+
return None
|
30 |
+
|
31 |
+
supabase = SupabaseOrderManager()
|
32 |
+
log_info("Cliente de Supabase inicializado correctamente")
|
33 |
+
return supabase
|
34 |
+
|
35 |
+
except Exception as e:
|
36 |
+
log_error(f"Error al inicializar el cliente de Supabase: {e}")
|
37 |
+
log_warn("Continuando sin funcionalidad de base de datos")
|
38 |
+
return None
|
39 |
+
|
40 |
+
# Inicializar cliente
|
41 |
+
supabase = init_supabase_client()
|
42 |
|
43 |
|
44 |
def create_menu_info_tool(retriever: VectorStoreRetriever) -> Tool:
|
|
|
75 |
return "Lo siento, no tengo información sobre eso."
|
76 |
|
77 |
return Tool(
|
78 |
+
name="guest_info_tool",
|
79 |
+
description="""Herramienta para consultar información detallada del menú del restaurante.
|
80 |
+
Úsala cuando necesites:
|
81 |
+
- Buscar platos específicos y verificar su disponibilidad
|
82 |
+
- Consultar precios exactos de productos
|
83 |
+
- Obtener información sobre ingredientes, alérgenos o composición de platos
|
84 |
+
- Explorar secciones del menú (entrantes, principales, postres, bebidas, etc.)
|
85 |
+
- Verificar la existencia de productos antes de recomendarlos
|
86 |
+
- Responder preguntas específicas sobre la carta del restaurante
|
87 |
+
|
88 |
+
Esta herramienta accede al contenido completo del menú para proporcionar información precisa y actualizada.""",
|
89 |
+
func=extract_text,
|
90 |
+
)
|
91 |
|
92 |
def create_send_to_kitchen_tool(llm: ChatOpenAI) -> Tool:
|
93 |
"""
|
|
|
190 |
log_info(f"Procesando resumen para enviar pedido a cocina...")
|
191 |
log_debug(f"Resumen recibido: {conversation_summary}")
|
192 |
|
193 |
+
# Verificar si Supabase está disponible
|
194 |
+
if supabase is None:
|
195 |
+
log_warn("Supabase no está configurado. Simulando envío de pedido.")
|
196 |
+
|
197 |
+
# Extraer el pedido para mostrarlo en logs aunque no se envíe
|
198 |
+
order = extract_order_from_summary(conversation_summary)
|
199 |
+
|
200 |
+
# Verificar si hay un error en el procesamiento
|
201 |
+
if hasattr(order, 'error') and order.error:
|
202 |
+
return "Lo siento, ha ocurrido un problema al procesar su pedido. Por favor, inténtelo de nuevo."
|
203 |
+
|
204 |
+
# Verificar si hay elementos en el pedido
|
205 |
+
if not order.items:
|
206 |
+
return "No se pudo identificar ningún artículo en el pedido. ¿Podría repetir su pedido, por favor?"
|
207 |
+
|
208 |
+
# Simular el procesamiento del pedido
|
209 |
+
order_dict = order.to_dict()
|
210 |
+
log_info(f"PEDIDO PROCESADO (MODO SIMULACIÓN): {json.dumps(order_dict, indent=2, ensure_ascii=False)}")
|
211 |
+
|
212 |
+
# Devolver confirmación simulada
|
213 |
+
return f"Su pedido ha sido procesado correctamente. Mesa: {order.table_number}, Artículos: {len(order.items)} elemento(s). (Modo simulación - Supabase no configurado)"
|
214 |
+
|
215 |
# Extraer el pedido a partir del resumen
|
216 |
order = extract_order_from_summary(conversation_summary)
|
217 |
|
|
|
232 |
log_warn("No se identificaron artículos en el pedido")
|
233 |
return "No se pudo identificar ningún artículo en el pedido. ¿Podría repetir su pedido, por favor?"
|
234 |
|
235 |
+
# Enviar a la cocina usando Supabase
|
236 |
order_dict = order.to_dict()
|
237 |
log_info(f"ENVIANDO PEDIDO A COCINA: {json.dumps(order_dict, indent=2, ensure_ascii=False)}")
|
238 |
|
239 |
+
# Envío real con Supabase
|
|
|
240 |
async def async_send_and_get_result(order):
|
241 |
return await supabase.send_order(order)
|
242 |
|
|
|
255 |
log_debug(traceback.format_exc())
|
256 |
return "Lo siento, hubo un problema al procesar su pedido. ¿Podría intentarlo de nuevo?"
|
257 |
|
258 |
+
# Determinar la descripción basada en si Supabase está disponible
|
259 |
+
if supabase is None:
|
260 |
+
description = """
|
261 |
+
Procesa y confirma el pedido del cliente (MODO SIMULACIÓN - Sin base de datos).
|
262 |
+
|
263 |
+
Usa esta herramienta SOLAMENTE cuando el cliente haya terminado de hacer su pedido
|
264 |
+
completo y esté listo para confirmarlo.
|
265 |
+
|
266 |
+
NOTA: Supabase no está configurado, por lo que el pedido será procesado pero no se
|
267 |
+
enviará a una base de datos real.
|
268 |
+
|
269 |
+
Esta herramienta espera recibir un RESUMEN de la conversación que describe los elementos del pedido.
|
270 |
+
"""
|
271 |
+
else:
|
272 |
+
description = """
|
273 |
Envía el pedido completo a la cocina. Usa esta herramienta SOLAMENTE cuando el cliente haya terminado de hacer su pedido
|
274 |
completo y esté listo para enviarlo.
|
275 |
|
276 |
Esta herramienta espera recibir un RESUMEN de la conversación que describe los elementos del pedido.
|
277 |
No envíes la conversación completa, solo un resumen claro de lo que el cliente ha pedido, la mesa,
|
278 |
y cualquier instrucción especial relevante.
|
279 |
+
"""
|
280 |
+
|
281 |
+
# Retornar la herramienta configurada con la función send_to_kitchen
|
282 |
+
return Tool(
|
283 |
+
name="send_to_kitchen_tool",
|
284 |
+
description=description,
|
285 |
func=send_to_kitchen,
|
286 |
+
)
|