feat: Implement new sales data analysis agents and utilities
- Added Router_de_agentes.py to manage agent interactions for sales data analysis. - Created Analizador_de_datos_de_ventas.yaml for generating structured text reports from sales data. - Developed Generador_sql_ventas.yaml for generating SQL queries to analyze sales data. - Established Router_de_agente.yaml as a routing mechanism for agent requests. - Compiled centros_disponibles.md listing available sales centers. - Introduced primera_ejecucion_de_un_agente.py as an example for executing agents. - Added ver_los_prompts_de_un_agente.py to inspect prompts sent to OpenAI. - Included service account key for BigQuery access in rag-datasets-reader-sa-key.json. - Defined schema for sales data in Objeto_ventas.json. - Implemented utility functions for querying BigQuery in conseguir_datos_bq.py. - Created data transformation utilities in transformar_datos.py for handling decimal and date formats.
This commit is contained in:
@@ -0,0 +1,378 @@
|
||||
# Constantes ##########################################################################
|
||||
|
||||
PROMPT = "Dame los datos de ventas de los ultimos 3 meses del centro de Alcobendas"
|
||||
|
||||
|
||||
# Librerias de Agno ################################################################
|
||||
|
||||
from agno.agent import Agent
|
||||
from agno.models.openai import OpenAIChat
|
||||
|
||||
# Prefect imports ##################################################################
|
||||
|
||||
from prefect import task, flow
|
||||
from prefect.logging import get_run_logger
|
||||
from prefect.filesystems import LocalFileSystem
|
||||
|
||||
local_file_system_block = LocalFileSystem.load("localfile")
|
||||
|
||||
# Cargar variables de entorno ######################################################
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
|
||||
# Imports adicionales #########################################################
|
||||
|
||||
import traceback
|
||||
from uuid import uuid4
|
||||
|
||||
# Importaciones de Archivos #########################################################
|
||||
|
||||
from jinja2 import Template
|
||||
import yaml
|
||||
import json
|
||||
|
||||
|
||||
# Utils ###################################################################################
|
||||
|
||||
from utils.conseguir_datos_bq import consultar_bigquery_paginado
|
||||
from utils.transformar_datos import limpiar_datos_para_json
|
||||
|
||||
|
||||
|
||||
|
||||
#######################################################
|
||||
# Agentes ##########################################
|
||||
|
||||
|
||||
with open("agents/Generador_sql_ventas.yaml", "r", encoding="utf-8") as f:
|
||||
experto_sql_ventas = yaml.safe_load(f)
|
||||
|
||||
with open("agents/Analizador_de_datos_de_ventas.yaml", "r", encoding="utf-8") as f:
|
||||
analizador_de_datos_de_ventas = yaml.safe_load(f)
|
||||
|
||||
|
||||
|
||||
|
||||
#########################################################
|
||||
# Datos extras ##########################
|
||||
|
||||
with open("schemas_bbdd/Objeto_ventas.json", "r", encoding="utf-8") as f:
|
||||
schema_json_ventas = json.load(f)
|
||||
|
||||
with open("detalles_para_agentes/centros_disponibles.md", "r", encoding="utf-8") as f:
|
||||
detalles_centros = f.read()
|
||||
|
||||
#############################################################
|
||||
# Datos añadidos a los agentes ##########################
|
||||
|
||||
schema_str_ventas = json.dumps(schema_json_ventas, indent=2, ensure_ascii=False)
|
||||
contexto_ventas = {
|
||||
"esquema_ventas": schema_str_ventas,
|
||||
"centros_disponibles": detalles_centros
|
||||
}
|
||||
|
||||
contexto_ventas_analizador = {
|
||||
"centros_disponibles": detalles_centros
|
||||
}
|
||||
|
||||
# Datos para Generador de SQL
|
||||
|
||||
template_ventas = Template(experto_sql_ventas["system_message"])
|
||||
rendered_yaml_ventas_sql = template_ventas.render(esquema_ventas=contexto_ventas)
|
||||
experto_sql_ventas["system_message"] = rendered_yaml_ventas_sql
|
||||
|
||||
|
||||
# Datos para Analizador de datos de ventas
|
||||
|
||||
template_ventas_analizador = Template(analizador_de_datos_de_ventas["system_message"])
|
||||
rendered_yaml_ventas_analisis = template_ventas_analizador.render(esquema_ventas=contexto_ventas_analizador)
|
||||
analizador_de_datos_de_ventas["system_message"] = rendered_yaml_ventas_analisis
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
###############################################################
|
||||
# Tareas ##########################################################
|
||||
|
||||
|
||||
|
||||
# Generar SQL ventas ######################################
|
||||
|
||||
@task(name="Convierte_prompt_a_sql", log_prints=True)
|
||||
def Convierte_prompt_a_sql(prompt_de_usuario: str):
|
||||
prefect_logger = get_run_logger()
|
||||
|
||||
prefect_logger.debug("Creando el agente con OpenAI")
|
||||
|
||||
agente = Agent(
|
||||
model=OpenAIChat(id="gpt-4o-mini", api_key=openai_api_key),
|
||||
name=experto_sql_ventas["name"],
|
||||
description=experto_sql_ventas["description"],
|
||||
system_message=experto_sql_ventas["system_message"],
|
||||
debug_mode=True,
|
||||
)
|
||||
|
||||
prefect_logger.debug("Agente creado correctamente")
|
||||
prefect_logger.debug("Enviando el prompt al agente")
|
||||
|
||||
try:
|
||||
resultado = agente.run(f"devuelve el sql para el siguiente requerimiento: {prompt_de_usuario}")
|
||||
prefect_logger.debug("Prompt enviado correctamente")
|
||||
|
||||
# Imprime la respuesta del agente en el log Prefect
|
||||
prefect_logger.info("=== RESPUESTA DEL AGENTE ===")
|
||||
prefect_logger.info(str(resultado.content.strip())) # imprime texto generado
|
||||
prefect_logger.info("============================")
|
||||
|
||||
# Si debug_mode está activado, puedes imprimir los logs internos del agente
|
||||
if hasattr(agente, "messages"):
|
||||
prefect_logger.debug("=== LOG INTERNO DEL AGENTE ===")
|
||||
for msg in agente.messages:
|
||||
prefect_logger.debug(f"{msg.role}: {msg.content}")
|
||||
prefect_logger.debug("===============================")
|
||||
|
||||
prefect_logger.debug("Ejecución completada correctamente ✅")
|
||||
return resultado.content.strip()
|
||||
|
||||
except Exception as e:
|
||||
prefect_logger.error("Error al enviar el prompt al agente")
|
||||
traceback_str = traceback.format_exc()
|
||||
prefect_logger.error(f"Traceback: {traceback_str}")
|
||||
raise e
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Conseguir datos de ventas a partir del SQL generado ##############################
|
||||
|
||||
@task(name="Consigue_datos_ventas", log_prints=True)
|
||||
def Consigue_datos_ventas(sql_generado_por_agente: str, num_pagina_deseada: int = 1):
|
||||
prefect_logger = get_run_logger()
|
||||
prefect_logger.info("Iniciando consulta de datos de ventas en BigQuery...")
|
||||
|
||||
try:
|
||||
paginas = consultar_bigquery_paginado(sql_generado_por_agente)
|
||||
|
||||
total_paginas = 0
|
||||
resultados_finales = []
|
||||
|
||||
for pagina in paginas:
|
||||
total_paginas += 1
|
||||
if total_paginas == num_pagina_deseada:
|
||||
prefect_logger.info(f"✅ Página {num_pagina_deseada} obtenida con {len(pagina)} filas")
|
||||
resultados_finales = pagina
|
||||
|
||||
if not resultados_finales:
|
||||
prefect_logger.warning(f"⚠️ No se encontró la página {num_pagina_deseada}. Total de páginas disponibles: {total_paginas}")
|
||||
return {
|
||||
"pagina": num_pagina_deseada,
|
||||
"total_paginas": total_paginas,
|
||||
"datos": [],
|
||||
"mensaje": f"No se encontró la página {num_pagina_deseada}"
|
||||
}
|
||||
|
||||
# Mostrar ejemplo en logs
|
||||
ejemplo = resultados_finales[:5]
|
||||
# prefect_logger.info("Ejemplo de datos obtenidos:")
|
||||
# for fila in ejemplo:
|
||||
# prefect_logger.info(str(fila))
|
||||
|
||||
prefect_logger.info(
|
||||
f"Consulta completada ✅ Página devuelta: {num_pagina_deseada} / {total_paginas} "
|
||||
f"con {len(resultados_finales)} filas"
|
||||
)
|
||||
|
||||
datos_ventas = {
|
||||
"pagina": num_pagina_deseada,
|
||||
"total_paginas": total_paginas,
|
||||
"filas_en_pagina": len(resultados_finales),
|
||||
"datos": resultados_finales,
|
||||
"ejemplo": ejemplo,
|
||||
"descripcion": (
|
||||
f"Página {num_pagina_deseada} de {total_paginas}. "
|
||||
f"Contiene {len(resultados_finales)} filas. "
|
||||
"Los datos son los resultados de la consulta SQL proporcionada."
|
||||
)
|
||||
}
|
||||
|
||||
prefect_logger.info(datos_ventas)
|
||||
|
||||
# 📦 Devolver información accesible al agente
|
||||
return datos_ventas
|
||||
|
||||
except Exception as e:
|
||||
prefect_logger.error("❌ Error durante la consulta en BigQuery")
|
||||
traceback_str = traceback.format_exc()
|
||||
prefect_logger.error(f"Traceback: {traceback_str}")
|
||||
raise e
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Analizador de resultados ##########################################################
|
||||
@task(name="Analizador_de_resultados", log_prints=True)
|
||||
def Analizador_de_resultados(datos_ventas: dict, prompt_de_usuario: str):
|
||||
prefect_logger = get_run_logger()
|
||||
prefect_logger.info("Iniciando análisis de resultados de ventas...")
|
||||
|
||||
try:
|
||||
agente = Agent(
|
||||
model=OpenAIChat(id="gpt-4o-mini", api_key=openai_api_key),
|
||||
name=analizador_de_datos_de_ventas["name"],
|
||||
description=analizador_de_datos_de_ventas["description"],
|
||||
system_message=analizador_de_datos_de_ventas["system_message"],
|
||||
debug_mode=True,
|
||||
)
|
||||
|
||||
prefect_logger.info("Agente Analizador_de_datos creado correctamente ✅")
|
||||
|
||||
pagina_actual = datos_ventas.get("pagina", 1)
|
||||
total_paginas = datos_ventas.get("total_paginas", 1)
|
||||
filas_en_pagina = datos_ventas.get("filas_en_pagina", 0)
|
||||
|
||||
# 🔧 Limpieza de Decimals antes del dump
|
||||
datos_limpiados = limpiar_datos_para_json(datos_ventas.get("datos", []))
|
||||
datos_json = json.dumps(datos_limpiados, indent=2, ensure_ascii=False)
|
||||
|
||||
prompt_agente = f"""
|
||||
Analiza los siguientes datos de ventas y responde al requerimiento del usuario.
|
||||
|
||||
🧠 Prompt del usuario:
|
||||
{prompt_de_usuario}
|
||||
|
||||
📄 Información de la página actual:
|
||||
- Página actual: {pagina_actual} / {total_paginas}
|
||||
- Filas en esta página: {filas_en_pagina}
|
||||
|
||||
📊 Datos de esta página:
|
||||
{datos_json}
|
||||
|
||||
"""
|
||||
|
||||
resultado = agente.run(prompt_agente)
|
||||
|
||||
prefect_logger.info("✅ Análisis completado correctamente")
|
||||
prefect_logger.info("=== RESULTADO DEL ANÁLISIS ===")
|
||||
prefect_logger.info(resultado.content.strip())
|
||||
prefect_logger.info("===============================")
|
||||
|
||||
return {
|
||||
"prompt_usuario": prompt_de_usuario,
|
||||
"pagina_analizada": pagina_actual,
|
||||
"total_paginas": total_paginas,
|
||||
"filas_analizadas": filas_en_pagina,
|
||||
"analisis": resultado.content.strip(),
|
||||
"datos_analizados": datos_limpiados,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
prefect_logger.error("❌ Error durante el análisis de resultados")
|
||||
traceback_str = traceback.format_exc()
|
||||
prefect_logger.error(f"Traceback: {traceback_str}")
|
||||
raise e
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# FLUJO PRINCIPAL ##########################################################
|
||||
|
||||
@flow(name="Agente_ventas", result_storage=local_file_system_block, log_prints=True) # type: ignore
|
||||
def Agente_ventas(PROMPT, num_pagina: int = 1):
|
||||
prefect_logger = get_run_logger()
|
||||
prefect_logger.info("🚀 Iniciando flujo Agente_ventas...")
|
||||
|
||||
# 🧠 1. Generar SQL a partir del prompt
|
||||
resultado_analisis = Convierte_prompt_a_sql.submit(PROMPT).result()
|
||||
|
||||
# 🧮 2. Intentar obtener los datos (máximo 3 intentos)
|
||||
for intento in range(3):
|
||||
try:
|
||||
datos_ventas = Consigue_datos_ventas.submit(
|
||||
resultado_analisis, num_pagina_deseada=num_pagina
|
||||
).result()
|
||||
break # ✅ Si la consulta fue exitosa, salir del bucle
|
||||
|
||||
except Exception as e:
|
||||
# 🧰 En caso de error, regenerar el SQL con información del fallo
|
||||
resultado_analisis = Convierte_prompt_a_sql.submit(f"""
|
||||
El SQL generado previamente daba error. El SQL era: {resultado_analisis}.
|
||||
El error fue: {str(e)}.
|
||||
Corrige el SQL para que no dé error y vuelve a generarlo.
|
||||
El prompt del usuario era: {PROMPT}
|
||||
""").result()
|
||||
|
||||
if intento == 2:
|
||||
raise e # ❌ Si falla 3 veces, detener el flujo
|
||||
|
||||
# 🧾 3. Logs de diagnóstico
|
||||
print("=== SQL GENERADO ===")
|
||||
print(resultado_analisis)
|
||||
print("====================")
|
||||
print("=== DATOS DE VENTAS OBTENIDOS ===")
|
||||
print(datos_ventas)
|
||||
print("==================================")
|
||||
|
||||
# 📊 4. Analizar los resultados con el agente analista
|
||||
prefect_logger.info(f"🔎 Analizando los resultados de la página {num_pagina}...")
|
||||
|
||||
analisis = Analizador_de_resultados.submit(
|
||||
datos_ventas, PROMPT
|
||||
).result()
|
||||
|
||||
# 🧠 5. Mostrar el análisis final
|
||||
print(f"=== ANÁLISIS DE PÁGINA {num_pagina} ===")
|
||||
print(analisis["analisis"])
|
||||
print("===================================")
|
||||
|
||||
# ✅ 6. Devolver resultados combinados
|
||||
return {
|
||||
"sql_generado": resultado_analisis,
|
||||
"analisis": analisis,
|
||||
}
|
||||
|
||||
|
||||
# Ejecución directa del flujo
|
||||
if __name__ == "__main__":
|
||||
# num_pagina=1 → analiza solo una página
|
||||
Agente_ventas(PROMPT, num_pagina=1)
|
||||
@@ -0,0 +1,44 @@
|
||||
# Constantes ##########################################################################
|
||||
|
||||
PROMPT = "Dame la venta total del centro de velez malaga de marzo de 2023 desglosado por factura"
|
||||
|
||||
|
||||
# Librerias de Agno ################################################################
|
||||
|
||||
from agno.agent import Agent
|
||||
from agno.models.openai import OpenAIChat
|
||||
|
||||
# Prefect imports ##################################################################
|
||||
|
||||
from prefect import task, flow
|
||||
from prefect.logging import get_run_logger
|
||||
from prefect.filesystems import LocalFileSystem
|
||||
|
||||
local_file_system_block = LocalFileSystem.load("localfile")
|
||||
|
||||
# Cargar variables de entorno ######################################################
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
|
||||
# Imports adicionales #########################################################
|
||||
|
||||
import traceback
|
||||
from uuid import uuid4
|
||||
|
||||
# Importaciones de Archivos #########################################################
|
||||
|
||||
from jinja2 import Template
|
||||
import yaml
|
||||
import json
|
||||
|
||||
|
||||
# Utils ###################################################################################
|
||||
|
||||
from utils.conseguir_datos_bq import consultar_bigquery_paginado
|
||||
from utils.transformar_datos import convertir_decimales
|
||||
@@ -0,0 +1,32 @@
|
||||
name: Analizador de datos de ventas
|
||||
description: Agente que analiza los datos recibidos y genera un informe en texto claro y estructurado, sin generar código ni SQL.
|
||||
system_message: >
|
||||
Eres un analista de datos de ventas con más de 200 años de experiencia combinada en análisis, interpretación y comunicación de información comercial.
|
||||
Tu objetivo es examinar los datos proporcionados y redactar un informe narrativo que describa los patrones, tendencias y observaciones más relevantes.
|
||||
|
||||
➤ **Tu estilo**
|
||||
- Redactas informes claros, concisos y bien estructurados.
|
||||
- Usas un tono profesional y analítico, pero fácil de entender.
|
||||
- No generas ni mencionas código, consultas SQL, funciones, ni instrucciones técnicas.
|
||||
- No inventas datos ni haces suposiciones fuera del conjunto recibido.
|
||||
|
||||
➤ **Tu enfoque**
|
||||
- Observa distribuciones, totales, promedios, máximos/mínimos, y comparaciones si son posibles con los datos entregados.
|
||||
- Resume las diferencias entre centros, periodos o categorías si los datos lo permiten.
|
||||
- Si detectas valores anómalos o inconsistencias, menciónalos brevemente.
|
||||
- Evita hacer recomendaciones o predicciones: tu labor es descriptiva, no prescriptiva.
|
||||
|
||||
➤ **Información de contexto**
|
||||
Los centros disponibles para las ventas son:
|
||||
{{centros_disponibles}}
|
||||
(columna: "Centros___Centro_NavId__name")
|
||||
|
||||
➤ **Tu salida esperada**
|
||||
Genera **únicamente** un informe de texto (sin tablas ni gráficos), que:
|
||||
- Resuma los hallazgos principales.
|
||||
- Destaque las observaciones relevantes.
|
||||
- Organice la información en secciones o párrafos temáticos.
|
||||
- Sea comprensible para directivos o analistas sin conocimiento técnico.
|
||||
|
||||
⚠️ **No generes SQL, código, fórmulas ni pseudocódigo.**
|
||||
⚠️ **Usa únicamente la información presente en los datos recibidos.**
|
||||
@@ -0,0 +1,25 @@
|
||||
name: Consultor SQL de Ventas
|
||||
description: Agente que solamente tiene que generar una consulta SQL para analizar datos de ventas
|
||||
system_message: >
|
||||
Eres un consultor SQL con 200 años de experiencia en análisis de datos de ventas.
|
||||
Te especializas en extraer, transformar y cargar datos para generar informes
|
||||
que ayuden a mejorar las estrategias de ventas
|
||||
Agrupas efectivamente los datos y generas informes claros y concisos.
|
||||
Recupera y analiza el dataset de ventas almacenado en la base de datos como autingo-159109.rag_datasets.Objeto_Ventas.
|
||||
No hagas Joins, consigue todos los datos desdes la tabla "autingo-159109.rag_datasets.Objeto_Ventas"
|
||||
No des explicaciones ni pasos intermedios, solo la consulta SQL.
|
||||
|
||||
Los centros disponibles para las ventas son:
|
||||
{{centros_disponibles}}
|
||||
en la columna "Centros___Centro_NavId__name"
|
||||
|
||||
Si no se te especifica que uses un centro de Cristales o Glass no lo uses.
|
||||
Utiliza su centro principal sin Cristales o Glass.
|
||||
|
||||
Utiliza SQL para BigQuery para extraer la información relevante y generar un informe inicial de los datos.
|
||||
Utiliza este esquema para recuperar los datos de la tabla "autingo-159109.rag_datasets.Objeto_Ventas"
|
||||
|
||||
COLUMNAS:
|
||||
{{esquema_ventas}}
|
||||
|
||||
La salida esperada es una consulta SQL generada entre ```sql SELECT ... ``` sin mas explicaciones.
|
||||
@@ -0,0 +1,154 @@
|
||||
Avda. Toreros
|
||||
Fuengirola
|
||||
Alcala Henares CRISTALES
|
||||
San Fernando CRISTALES
|
||||
Leganes CRISTALES
|
||||
Alcobendas CRISTALES
|
||||
Las Rozas
|
||||
Alfafar
|
||||
Huelva
|
||||
MT Maria Auxiliadora CRISTALES
|
||||
Almeria
|
||||
Gta. Cadiz
|
||||
MT Cornella
|
||||
Pinto
|
||||
Parla
|
||||
Vaguada
|
||||
Islazul
|
||||
MT Vigo
|
||||
MT Pintor Sorolla - Colon
|
||||
MT Alexandre Rosello
|
||||
MT Diagonal
|
||||
Santa Engracia CRISTALES
|
||||
MT San Jose de Valderas CRISTALES
|
||||
Goya GLASS
|
||||
MT Avenida de Francia CRISTALES
|
||||
Vallecas
|
||||
MT Puerto Venecia
|
||||
MT Bahia de Santander
|
||||
MT Sanchinarro
|
||||
Cornella
|
||||
Vallecas CRISTALES
|
||||
Elche
|
||||
Villalba
|
||||
MT Avenida de España
|
||||
MT Gran Via
|
||||
Cordoba
|
||||
MT Princesa
|
||||
Majadahonda
|
||||
Store
|
||||
La Red
|
||||
Finestrat
|
||||
MT Castellana
|
||||
MT Nuevo Centro
|
||||
MT El Corte Ingles Cartagena
|
||||
MT Goya
|
||||
Aurgi Asociados
|
||||
Xativa
|
||||
Cornella 2
|
||||
Villalba CRISTALES
|
||||
Torrevieja
|
||||
Zaragoza
|
||||
La Maquinista
|
||||
MT Monasterio
|
||||
Puerto de Santa Maria
|
||||
MT San Juan de Aznalfarache
|
||||
MT Malaga
|
||||
MT Pozuelo
|
||||
MT Monasterio CRISTALES
|
||||
MT Girocentre
|
||||
Santa Engracia
|
||||
MT Nervion
|
||||
Linares
|
||||
Badajoz
|
||||
San Sebastian CRISTALES
|
||||
MT Gijon
|
||||
MT Avenida de la Libertad
|
||||
MT Talavera de la Reina
|
||||
Rivas
|
||||
Pola de Siero
|
||||
Mostoles
|
||||
MT Gran Casa
|
||||
MT Compostela CRISTALES
|
||||
Serrano
|
||||
MT Ramon y Cajal
|
||||
San Sebastian
|
||||
Goya
|
||||
MT Ronda de Cordoba
|
||||
Granada
|
||||
MT Paseo de Morella
|
||||
MT Ctra de Madrid-Irun km. 236 CRISTALES
|
||||
Hospitalet
|
||||
Alcorcon
|
||||
MT Costa de Marbella
|
||||
Puerto de Santa Maria CRISTALES
|
||||
MT Conquistadores
|
||||
Malaga
|
||||
Olias del Rey
|
||||
MT Ctra de Madrid-Irun km. 236
|
||||
Alcobendas
|
||||
MT Bahia de Cadiz
|
||||
MT Jerez
|
||||
Leganes
|
||||
SP EL ESCORIAL
|
||||
MT Avenida de Francia
|
||||
Mataro
|
||||
Torremolinos
|
||||
Gava
|
||||
MT Costa Mijas
|
||||
MT Compostela
|
||||
MT El Bercial
|
||||
MT Mendez Alvaro
|
||||
Vall D'Uixo
|
||||
Villanueva de la Serena
|
||||
Zaragoza CRISTALES
|
||||
MT Bahia de Malaga
|
||||
MT Ciudad de Elche
|
||||
AUR ALICANTE AV. NOVELDA
|
||||
MT Xanadu
|
||||
MT Web
|
||||
Les Franqueses
|
||||
Chamartin
|
||||
MT Alcala de Henares
|
||||
Aluche
|
||||
MT Cornella CRISTALES
|
||||
Las Rozas CRISTALES
|
||||
Sant Celoni
|
||||
MT Ramon y Cajal CRISTALES
|
||||
MT San Jose de Valderas
|
||||
San Fernando
|
||||
Tucan
|
||||
MT Campo de las Naciones
|
||||
Aurgi Web
|
||||
Barbera
|
||||
San Juan CRISTALES
|
||||
MT Pozuelo CRISTALES
|
||||
MT Siete Palmas
|
||||
Sabadell
|
||||
Roquetas
|
||||
Sant Adria
|
||||
MT Jaen
|
||||
Alcala Henares
|
||||
MT El Bercial CRISTALES
|
||||
Denia
|
||||
Unidad Movil Madrid Glass
|
||||
Aurgi Asociados Gruas
|
||||
Velez Malaga
|
||||
Jerez
|
||||
Arganda
|
||||
Emilio Muñoz
|
||||
MT Alicante
|
||||
Granollers
|
||||
Sant Boi
|
||||
MT Bahia de Algeciras
|
||||
Oficinas Centrales
|
||||
MT Maria Auxiliadora
|
||||
Barbera CRISTALES
|
||||
MT Tres de Mayo
|
||||
Autingo
|
||||
Sant Cugat
|
||||
SP JAVEA
|
||||
Store CRISTALES
|
||||
San Juan
|
||||
Marques Vadillo
|
||||
Valdemoro
|
||||
@@ -19,12 +19,13 @@ load_dotenv()
|
||||
openai_api_key = os.getenv("OPENAI_API_KEY")
|
||||
|
||||
|
||||
prefect_logger = get_run_logger()
|
||||
|
||||
# Definir tareas ###############################################
|
||||
|
||||
@task(name="Inicializar agente financiero", log_prints=True)
|
||||
def inicializar_agente_financiero():
|
||||
prefect_logger = get_run_logger()
|
||||
|
||||
|
||||
prefect_logger.debug(f"Inicializando el agente financiero")
|
||||
# Aquí se podría agregar la lógica para inicializar el agente
|
||||
return "Agente financiero inicializado"
|
||||
@@ -32,9 +33,9 @@ def inicializar_agente_financiero():
|
||||
|
||||
@task(name="Analizar datos financieros", log_prints=True)
|
||||
def analizar_datos_financieros(datos: str):
|
||||
|
||||
prefect_logger = get_run_logger()
|
||||
|
||||
|
||||
prefect_logger.debug(f"Creando el agente con OpenAI")
|
||||
|
||||
prefect_logger.debug(f"analizando los datos: {datos}")
|
||||
@@ -121,7 +121,7 @@ def averiguar_el_prompt_que_seenvia_a_openai(prompt_de_usuario: str):
|
||||
|
||||
# Definir el flujo principal #########################################
|
||||
|
||||
@flow(name="Flujo financiero", result_storage=local_file_system_block, log_prints=True) # type: ignore
|
||||
@flow(name="Averiguar_prompt_enviado", result_storage=local_file_system_block, log_prints=True) # type: ignore
|
||||
def flujo_principal():
|
||||
|
||||
resultado_analisis = averiguar_el_prompt_que_seenvia_a_openai.submit(PROMPT).result()
|
||||
@@ -1,64 +0,0 @@
|
||||
version: '3.9'
|
||||
services:
|
||||
otel-collector:
|
||||
image: otel/opentelemetry-collector-contrib:0.136.0
|
||||
container_name: otel-collector
|
||||
command:
|
||||
- --config=/etc/otel/config.yaml
|
||||
volumes:
|
||||
- ./otel-config.yaml:/etc/otel/config.yaml
|
||||
ports:
|
||||
- 4317:4317
|
||||
- 4318:4318
|
||||
depends_on:
|
||||
- victoria
|
||||
- tempo
|
||||
victoria:
|
||||
image: victoriametrics/victoria-metrics:latest
|
||||
container_name: victoria
|
||||
ports:
|
||||
- 8428:8428
|
||||
volumes:
|
||||
- ./victoria-data:/victoria-metrics-data
|
||||
command:
|
||||
- --storageDataPath=/victoria-metrics-data
|
||||
- --retentionPeriod=3
|
||||
tempo:
|
||||
image: grafana/tempo:latest
|
||||
container_name: tempo
|
||||
ports:
|
||||
- 3200:3200
|
||||
volumes:
|
||||
- ./tempo-data:/var/tempo
|
||||
command:
|
||||
- -config.file=/etc/tempo.yaml
|
||||
configs:
|
||||
- source: tempo_config
|
||||
target: /etc/tempo.yaml
|
||||
grafana-srv:
|
||||
image: grafana/grafana-oss:latest
|
||||
container_name: grafana-srv
|
||||
ports:
|
||||
- 33000:3000
|
||||
environment:
|
||||
GF_SECURITY_ADMIN_USER: admin
|
||||
GF_SECURITY_ADMIN_PASSWORD: admin123
|
||||
GF_USERS_ALLOW_SIGN_UP: 'false'
|
||||
depends_on:
|
||||
- victoria
|
||||
- tempo
|
||||
volumes:
|
||||
- grafana_data:/var/lib/grafana
|
||||
- ./provisioning/datasources:/etc/grafana/provisioning/datasources
|
||||
- ./provisioning/dashboards:/etc/grafana/provisioning/dashboards
|
||||
- ./grafana-dashboards:/var/lib/grafana/dashboards
|
||||
configs:
|
||||
tempo_config:
|
||||
content: "\nserver:\n http_listen_port: 3200\n\ndistributor:\n receivers:\n\
|
||||
otlp:\n protocols:\n grpc:\n endpoint: \"0.0.0.0:4317\"\n http:\n\
|
||||
\ endpoint: \"0.0.0.0:4318\"\n\ningester:\n trace_idle_period: 10s\n \
|
||||
\ max_block_bytes: 1000000\n max_block_duration: 5m\n\ncompactor:\n compaction:\n\
|
||||
block_retention: 24h\n\nstorage:\n trace:\nwal:\n path: /var/tempo/wal\nlocal:\n\
|
||||
\ path: /var/tempo/blocks\n"
|
||||
volumes:
|
||||
grafana_data: {}
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"id": null,
|
||||
"uid": "overview",
|
||||
"title": "\ud83d\udcca System Overview",
|
||||
"timezone": "browser",
|
||||
"panels": [
|
||||
{
|
||||
"type": "graph",
|
||||
"title": "CPU Usage",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "process_cpu_seconds_total",
|
||||
"legendFormat": "{{instance}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "table",
|
||||
"title": "Logs (simulados)",
|
||||
"targets": [
|
||||
{
|
||||
"expr": "up"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schemaVersion": 36,
|
||||
"version": 1
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc: {}
|
||||
http: {}
|
||||
processors:
|
||||
batch: {}
|
||||
exporters:
|
||||
prometheusremotewrite:
|
||||
endpoint: http://victoria:8428/api/v1/write
|
||||
otlp/tempo:
|
||||
endpoint: http://tempo:4317
|
||||
tls:
|
||||
insecure: true
|
||||
debug:
|
||||
verbosity: normal
|
||||
service:
|
||||
pipelines:
|
||||
metrics:
|
||||
receivers:
|
||||
- otlp
|
||||
processors:
|
||||
- batch
|
||||
exporters:
|
||||
- prometheusremotewrite
|
||||
- debug
|
||||
traces:
|
||||
receivers:
|
||||
- otlp
|
||||
processors:
|
||||
- batch
|
||||
exporters:
|
||||
- otlp/tempo
|
||||
- debug
|
||||
logs:
|
||||
receivers:
|
||||
- otlp
|
||||
processors:
|
||||
- batch
|
||||
exporters:
|
||||
- prometheusremotewrite
|
||||
- debug
|
||||
@@ -1,10 +0,0 @@
|
||||
apiVersion: 1
|
||||
providers:
|
||||
- name: default
|
||||
orgId: 1
|
||||
folder: ''
|
||||
type: file
|
||||
disableDeletion: false
|
||||
updateIntervalSeconds: 10
|
||||
options:
|
||||
path: /var/lib/grafana/dashboards
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: 1
|
||||
datasources:
|
||||
- name: VictoriaMetrics
|
||||
type: prometheus
|
||||
access: proxy
|
||||
url: http://victoria:8428
|
||||
isDefault: true
|
||||
- name: Tempo
|
||||
type: tempo
|
||||
access: proxy
|
||||
url: http://tempo:3200
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
田Jpu6�
|
||||
@@ -1 +0,0 @@
|
||||
[]
|
||||
@@ -1 +0,0 @@
|
||||
[]
|
||||
@@ -1 +0,0 @@
|
||||
[]
|
||||
Binary file not shown.
@@ -6,6 +6,7 @@ readme = "README.md"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"agno>=2.1.1",
|
||||
"google-cloud-bigquery>=3.38.0",
|
||||
"icecream>=2.1.8",
|
||||
"marimo>=0.16.5",
|
||||
"openai>=2.1.0",
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"type": "service_account",
|
||||
"project_id": "autingo-159109",
|
||||
"private_key_id": "c43c626d47606344cd3a255d62df1be77019cc54",
|
||||
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQD0yeIqsGZ/RYHO\nqIZ67AN1Jd+c2rKzAOp1G/9XKuNfQV4XChkq2pVCMG78WbgUWSMlJY2OLsVdEvrS\n4W8MM9ZiXkJ0Ox3O5Y6/1w+omLBaqG/JuJU/euRvUZUIjLc36fpY0nzZu42CK7oK\nhUepE31WYf5i+MbhR5LpaOaJQQjfOhRZAd01iUCiKFGPVfI24dk0qYZnBQKVSSmH\nQD8zjNVHPo0LmXWOwOj2t4VrBq9WjrepJftzKumyieLJrMua76pMc+dmStyWb4yK\nTrk2yjXsN9QQRN3SLG+k0hedPdCa5ca+Wi0OCGBb1akaFjgAKw/ygiRtUDDUfmjv\nH/Q7wR/VAgMBAAECggEAOU8TfWGPmY/dEFQpqdkcBR7xD3CvIhPekDzWBqMSmOA9\npkC1vC/w/k5HCZr6qv7kaMO2NJm0GLKDGQBwxmdTc3O0dLBLbf8V8Mlpj9Pxg8QH\n6e7mODauCPbNYLNLCNLlSsq6sqIDgvx4QZLLAGVA9IqcKzEppJ/kX/Nwd6VLbbEe\nzm+P9RJRPGNBjpUKvkI1KLVRADLAuFQN44S9IzHItEYEi7C8Qe6EdPl5scXJn3hq\noPW7YoGgaaj7G81yXovQUK4tTSxduCsO4HhiYAF3CfYsoZ+sXQ/MpNQWZK5Yiic3\n+z6MsNSE0SYeOX9E008/PPzKwR2ehgmO2U6Lhl5AAQKBgQD8zSXbx7dEhRXI6+uV\nT+Fiuke3FGBUu6zGbMn75KGFnHaOMVfARaJnmla8EJ01ZkGMRis4f53elywUSQyJ\nBa7xCP7/FshuM9J+5vfvGM7NRc6kcUUaJSlg52/DNgeZy2cijBy0iaPy7+uyRRcO\nWhyaj3h+bv11US0dyt7TB3jf1QKBgQD34sgICtQcdkt51l+iHmAhiW2U6s8kuFDa\n9TX8bp4YaPoC65IkfutI3saLcJpqLgBb67j/HxCb6gkFr+OeQQIGN+X7J4rTUdhB\nLEWAnjMV3ow23q8tO5xN+jnLV0UCiF8EZLg7EIzLQ0MozjB9gndp8xxoEKDqWEG5\nagP9p4dAAQKBgELiF+EU7sTfHQtid5qyXqQbOrwSVQY1/RkmUS4mqCFMawVlwpyp\nD7WvXME2+BDXtAHj0q2I/gCVKGFZjkp2SXmV8rkUkwStC0Tt4KzOeHBQxsI1AZ5Q\nNKlhse0Iz2v+J5Q5U6LkQ48TsN0icF4osyalTLDOtpoiVvhp4xgcAvvdAoGAOBXL\nhGZOz5HESfDC+n886NmbPZJTA8/gG2pXqKGui39U8cwy6Kb+vSIKcgosJdH6qtGO\nrcpti5lMKUk+itPSjW2gT08HDgD6mORXZV5l2JDd0JxZrjZKiyoOYX+BUa1hMjFH\nrbV05Zh2XYkpV3xpYENtLe51OhB17mmaNY3uAAECgYBydII40sWjpvybaRc40UXH\nWLKCDPfeeSyJqrybU80nbOKI6WfmO9sBtVS/qf+4z8aDHenOhmcpXPIFhEe34ARw\nanWSjSBLI1sdn88KwtLSd2dCytN+0VnJ1RNpzHPwDK4J5wZaIJV0AYvryfWazqn4\nazDWb8s8eRHw+9nAS2TALg==\n-----END PRIVATE KEY-----\n",
|
||||
"client_email": "rag-datasets-reader-sa@autingo-159109.iam.gserviceaccount.com",
|
||||
"client_id": "111296269982496507213",
|
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||
"token_uri": "https://oauth2.googleapis.com/token",
|
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/rag-datasets-reader-sa%40autingo-159109.iam.gserviceaccount.com",
|
||||
"universe_domain": "googleapis.com"
|
||||
}
|
||||
@@ -0,0 +1,359 @@
|
||||
[
|
||||
{
|
||||
"name": "Fecha",
|
||||
"mode": "NULLABLE",
|
||||
"type": "DATETIME",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "numeroDocumento",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "NumeroLineas",
|
||||
"mode": "NULLABLE",
|
||||
"type": "INTEGER",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "idCentro",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "idProducto",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "cantidad",
|
||||
"mode": "NULLABLE",
|
||||
"type": "BIGNUMERIC",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "precioUnitario",
|
||||
"mode": "NULLABLE",
|
||||
"type": "BIGNUMERIC",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Base_imponible_linea",
|
||||
"mode": "NULLABLE",
|
||||
"type": "BIGNUMERIC",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Tipo_de_documento",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "semana",
|
||||
"mode": "NULLABLE",
|
||||
"type": "INTEGER",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "ano",
|
||||
"mode": "NULLABLE",
|
||||
"type": "INTEGER",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "ano_mas_uno",
|
||||
"mode": "NULLABLE",
|
||||
"type": "INTEGER",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Fecha_mas_un_ano",
|
||||
"mode": "NULLABLE",
|
||||
"type": "DATETIME",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__nav_id",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__id_centro",
|
||||
"mode": "NULLABLE",
|
||||
"type": "INTEGER",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__name",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__Companies__name",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__Zones__name",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__Cluster_centros",
|
||||
"mode": "NULLABLE",
|
||||
"type": "INTEGER",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__Jefes_de_centro_y_Rmos___co_51ce9994",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__Jefes_de_centro_y_Rmos___co_c6afb8e8",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__Jefes_de_centro_y_Rmos___co_a5423963",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__Provincias_comunidades_y_su_b8d2c2a0",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__Provincias_comunidades_y_su_cb74d1a1",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Centros___Centro_NavId__Provincias_comunidades_y_su_9fd8d3fc",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__id",
|
||||
"mode": "NULLABLE",
|
||||
"type": "INTEGER",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__nav_id",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__description",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__is_tecdoc",
|
||||
"mode": "NULLABLE",
|
||||
"type": "BOOLEAN",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Status_de_producto",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Is_Encargo",
|
||||
"mode": "NULLABLE",
|
||||
"type": "BOOLEAN",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__is_service",
|
||||
"mode": "NULLABLE",
|
||||
"type": "BOOLEAN",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__is_tpv",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Tipo___Navision",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Product_Groups__description",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Product_Categories__description",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo1",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo2",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo3",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo5",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo4",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo6",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo7",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo8",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo9",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idAtributo10",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idCategoria",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Producto___Nav__idGrupo",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Categoria_16_07_cgq___t_cb30d712",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Categoria_16_07_cgq___t_d83f396f",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"name": "Productos___Producto_NavId__Categoria_16_07_cgq___t_5e9550ff",
|
||||
"mode": "NULLABLE",
|
||||
"type": "STRING",
|
||||
"description": "",
|
||||
"fields": []
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,68 @@
|
||||
from google.cloud import bigquery
|
||||
from typing import Generator, List, Dict
|
||||
import os
|
||||
|
||||
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "rag-datasets-reader-sa-key.json"
|
||||
|
||||
|
||||
def consultar_bigquery_paginado(
|
||||
sql_query: str,
|
||||
page_size: int = 1000,
|
||||
project_id: str | None = None
|
||||
) -> Generator[List[Dict], None, None]:
|
||||
"""
|
||||
Ejecuta una consulta SQL de BigQuery y devuelve los resultados paginados.
|
||||
Limpia el texto SQL automáticamente antes de ejecutarlo.
|
||||
|
||||
Args:
|
||||
sql_query (str): Texto SQL (puede incluir espacios o punto y coma al final).
|
||||
page_size (int): Número de filas por página.
|
||||
project_id (str | None): ID del proyecto GCP (opcional si está configurado el entorno).
|
||||
|
||||
Yields:
|
||||
list[dict]: Página de resultados (cada fila convertida a dict).
|
||||
"""
|
||||
# 🧹 Limpieza del texto SQL
|
||||
cleaned_query = (
|
||||
sql_query.strip() # elimina espacios y saltos al inicio y fin
|
||||
.removeprefix("```sql").removeprefix("```").removesuffix("```") # limpia delimitadores markdown si los hay
|
||||
.strip() # vuelve a limpiar por si quedaron espacios
|
||||
)
|
||||
|
||||
# Quita el punto y coma final si lo tiene
|
||||
if cleaned_query.endswith(";"):
|
||||
cleaned_query = cleaned_query[:-1].strip()
|
||||
|
||||
# Inicializa el cliente
|
||||
client = bigquery.Client(project=project_id)
|
||||
|
||||
# Ejecuta la consulta
|
||||
query_job = client.query(cleaned_query)
|
||||
|
||||
# Devuelve resultados paginados
|
||||
iterator = query_job.result(page_size=page_size)
|
||||
for page in iterator.pages:
|
||||
yield [dict(row) for row in page]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
resultado = consultar_bigquery_paginado("""```sql
|
||||
SELECT
|
||||
Productos___Producto_NavId__description AS producto,
|
||||
Centros___Centro_NavId__name AS region,
|
||||
SUM(cantidad) AS total_vendido,
|
||||
SUM(cantidad * precioUnitario) AS ingreso_total
|
||||
FROM
|
||||
`autingo-159109.rag_datasets.Objeto_Ventas`
|
||||
WHERE
|
||||
Fecha >= DATE_SUB(CURRENT_DATE(), INTERVAL 3 MONTH)
|
||||
GROUP BY
|
||||
producto, region
|
||||
ORDER BY
|
||||
total_vendido DESC;
|
||||
```""")
|
||||
|
||||
for pagina in resultado:
|
||||
for fila in pagina:
|
||||
print(fila)
|
||||
print("----- Fin de página -----")
|
||||
@@ -0,0 +1,32 @@
|
||||
from decimal import Decimal
|
||||
from datetime import datetime, date, time
|
||||
|
||||
def convertir_decimales(obj):
|
||||
if isinstance(obj, list):
|
||||
return [convertir_decimales(x) for x in obj]
|
||||
elif isinstance(obj, dict):
|
||||
return {k: convertir_decimales(v) for k, v in obj.items()}
|
||||
elif isinstance(obj, Decimal):
|
||||
return float(obj)
|
||||
else:
|
||||
return obj
|
||||
|
||||
|
||||
def convertir_fechas(obj):
|
||||
"""
|
||||
Convierte objetos datetime, date y time a su representación ISO 8601.
|
||||
"""
|
||||
if isinstance(obj, list):
|
||||
return [convertir_fechas(x) for x in obj]
|
||||
elif isinstance(obj, dict):
|
||||
return {k: convertir_fechas(v) for k, v in obj.items()}
|
||||
elif isinstance(obj, (datetime, date, time)):
|
||||
return obj.isoformat()
|
||||
else:
|
||||
return obj
|
||||
|
||||
|
||||
def limpiar_datos_para_json(data):
|
||||
data = convertir_decimales(data)
|
||||
data = convertir_fechas(data)
|
||||
return data
|
||||
@@ -280,6 +280,7 @@ version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "agno" },
|
||||
{ name = "google-cloud-bigquery" },
|
||||
{ name = "icecream" },
|
||||
{ name = "marimo" },
|
||||
{ name = "openai" },
|
||||
@@ -292,6 +293,7 @@ dependencies = [
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "agno", specifier = ">=2.1.1" },
|
||||
{ name = "google-cloud-bigquery", specifier = ">=3.38.0" },
|
||||
{ name = "icecream", specifier = ">=2.1.8" },
|
||||
{ name = "marimo", specifier = ">=0.16.5" },
|
||||
{ name = "openai", specifier = ">=2.1.0" },
|
||||
@@ -519,6 +521,112 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/01/61/d4b89fec821f72385526e1b9d9a3a0385dda4a72b206d28049e2c7cd39b8/gitpython-3.1.45-py3-none-any.whl", hash = "sha256:8908cb2e02fb3b93b7eb0f2827125cb699869470432cc885f019b8fd0fccff77", size = 208168, upload-time = "2025-07-24T03:45:52.517Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "google-api-core"
|
||||
version = "2.25.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "google-auth" },
|
||||
{ name = "googleapis-common-protos" },
|
||||
{ name = "proto-plus" },
|
||||
{ name = "protobuf" },
|
||||
{ name = "requests" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/09/cd/63f1557235c2440fe0577acdbc32577c5c002684c58c7f4d770a92366a24/google_api_core-2.25.2.tar.gz", hash = "sha256:1c63aa6af0d0d5e37966f157a77f9396d820fba59f9e43e9415bc3dc5baff300", size = 166266, upload-time = "2025-10-03T00:07:34.778Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/d8/894716a5423933f5c8d2d5f04b16f052a515f78e815dab0c2c6f1fd105dc/google_api_core-2.25.2-py3-none-any.whl", hash = "sha256:e9a8f62d363dc8424a8497f4c2a47d6bcda6c16514c935629c257ab5d10210e7", size = 162489, upload-time = "2025-10-03T00:07:32.924Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
grpc = [
|
||||
{ name = "grpcio" },
|
||||
{ name = "grpcio-status" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "google-auth"
|
||||
version = "2.41.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cachetools" },
|
||||
{ name = "pyasn1-modules" },
|
||||
{ name = "rsa" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/af/5129ce5b2f9688d2fa49b463e544972a7c82b0fdb50980dafee92e121d9f/google_auth-2.41.1.tar.gz", hash = "sha256:b76b7b1f9e61f0cb7e88870d14f6a94aeef248959ef6992670efee37709cbfd2", size = 292284, upload-time = "2025-09-30T22:51:26.363Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/be/a4/7319a2a8add4cc352be9e3efeff5e2aacee917c85ca2fa1647e29089983c/google_auth-2.41.1-py2.py3-none-any.whl", hash = "sha256:754843be95575b9a19c604a848a41be03f7f2afd8c019f716dc1f51ee41c639d", size = 221302, upload-time = "2025-09-30T22:51:24.212Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "google-cloud-bigquery"
|
||||
version = "3.38.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "google-api-core", extra = ["grpc"] },
|
||||
{ name = "google-auth" },
|
||||
{ name = "google-cloud-core" },
|
||||
{ name = "google-resumable-media" },
|
||||
{ name = "packaging" },
|
||||
{ name = "python-dateutil" },
|
||||
{ name = "requests" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/07/b2/a17e40afcf9487e3d17db5e36728ffe75c8d5671c46f419d7b6528a5728a/google_cloud_bigquery-3.38.0.tar.gz", hash = "sha256:8afcb7116f5eac849097a344eb8bfda78b7cfaae128e60e019193dd483873520", size = 503666, upload-time = "2025-09-17T20:33:33.47Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/39/3c/c8cada9ec282b29232ed9aed5a0b5cca6cf5367cb2ffa8ad0d2583d743f1/google_cloud_bigquery-3.38.0-py3-none-any.whl", hash = "sha256:e06e93ff7b245b239945ef59cb59616057598d369edac457ebf292bd61984da6", size = 259257, upload-time = "2025-09-17T20:33:31.404Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "google-cloud-core"
|
||||
version = "2.4.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "google-api-core" },
|
||||
{ name = "google-auth" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d6/b8/2b53838d2acd6ec6168fd284a990c76695e84c65deee79c9f3a4276f6b4f/google_cloud_core-2.4.3.tar.gz", hash = "sha256:1fab62d7102844b278fe6dead3af32408b1df3eb06f5c7e8634cbd40edc4da53", size = 35861, upload-time = "2025-03-10T21:05:38.948Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/40/86/bda7241a8da2d28a754aad2ba0f6776e35b67e37c36ae0c45d49370f1014/google_cloud_core-2.4.3-py2.py3-none-any.whl", hash = "sha256:5130f9f4c14b4fafdff75c79448f9495cfade0d8775facf1b09c3bf67e027f6e", size = 29348, upload-time = "2025-03-10T21:05:37.785Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "google-crc32c"
|
||||
version = "1.7.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/19/ae/87802e6d9f9d69adfaedfcfd599266bf386a54d0be058b532d04c794f76d/google_crc32c-1.7.1.tar.gz", hash = "sha256:2bff2305f98846f3e825dbeec9ee406f89da7962accdb29356e4eadc251bd472", size = 14495, upload-time = "2025-03-26T14:29:13.32Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/72/b8d785e9184ba6297a8620c8a37cf6e39b81a8ca01bb0796d7cbb28b3386/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:df8b38bdaf1629d62d51be8bdd04888f37c451564c2042d36e5812da9eff3c35", size = 30467, upload-time = "2025-03-26T14:36:06.909Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/25/5f18076968212067c4e8ea95bf3b69669f9fc698476e5f5eb97d5b37999f/google_crc32c-1.7.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:e42e20a83a29aa2709a0cf271c7f8aefaa23b7ab52e53b322585297bb94d4638", size = 30309, upload-time = "2025-03-26T15:06:15.318Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/83/9228fe65bf70e93e419f38bdf6c5ca5083fc6d32886ee79b450ceefd1dbd/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:905a385140bf492ac300026717af339790921f411c0dfd9aa5a9e69a08ed32eb", size = 33133, upload-time = "2025-03-26T14:41:34.388Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/ca/1ea2fd13ff9f8955b85e7956872fdb7050c4ace8a2306a6d177edb9cf7fe/google_crc32c-1.7.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b211ddaf20f7ebeec5c333448582c224a7c90a9d98826fbab82c0ddc11348e6", size = 32773, upload-time = "2025-03-26T14:41:35.19Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/89/32/a22a281806e3ef21b72db16f948cad22ec68e4bdd384139291e00ff82fe2/google_crc32c-1.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:0f99eaa09a9a7e642a61e06742856eec8b19fc0037832e03f941fe7cf0c8e4db", size = 33475, upload-time = "2025-03-26T14:29:11.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/c5/002975aff514e57fc084ba155697a049b3f9b52225ec3bc0f542871dd524/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32d1da0d74ec5634a05f53ef7df18fc646666a25efaaca9fc7dcfd4caf1d98c3", size = 33243, upload-time = "2025-03-26T14:41:35.975Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/cb/c585282a03a0cea70fcaa1bf55d5d702d0f2351094d663ec3be1c6c67c52/google_crc32c-1.7.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e10554d4abc5238823112c2ad7e4560f96c7bf3820b202660373d769d9e6e4c9", size = 32870, upload-time = "2025-03-26T14:41:37.08Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "google-resumable-media"
|
||||
version = "2.7.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "google-crc32c" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/58/5a/0efdc02665dca14e0837b62c8a1a93132c264bd02054a15abb2218afe0ae/google_resumable_media-2.7.2.tar.gz", hash = "sha256:5280aed4629f2b60b847b0d42f9857fd4935c11af266744df33d8074cae92fe0", size = 2163099, upload-time = "2024-08-07T22:20:38.555Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/82/35/b8d3baf8c46695858cb9d8835a53baa1eeb9906ddaf2f728a5f5b640fd1e/google_resumable_media-2.7.2-py2.py3-none-any.whl", hash = "sha256:3ce7551e9fe6d99e9a126101d2536612bb73486721951e9562fee0f90c6ababa", size = 81251, upload-time = "2024-08-07T22:20:36.409Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "googleapis-common-protos"
|
||||
version = "1.70.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "protobuf" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/39/24/33db22342cf4a2ea27c9955e6713140fedd51e8b141b5ce5260897020f1a/googleapis_common_protos-1.70.0.tar.gz", hash = "sha256:0e1b44e0ea153e6594f9f394fef15193a68aaaea2d843f83e2742717ca753257", size = 145903, upload-time = "2025-04-14T10:17:02.924Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/86/f1/62a193f0227cf15a920390abe675f386dec35f7ae3ffe6da582d3ade42c7/googleapis_common_protos-1.70.0-py3-none-any.whl", hash = "sha256:b8bfcca8c25a2bb253e0e0b0adaf8c00773e5e6af6fd92397576680b807e0fd8", size = 294530, upload-time = "2025-04-14T10:17:01.271Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "graphviz"
|
||||
version = "0.21"
|
||||
@@ -564,6 +672,51 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/b1/9ff6578d789a89812ff21e4e0f80ffae20a65d5dd84e7a17873fe3b365be/griffe-1.14.0-py3-none-any.whl", hash = "sha256:0e9d52832cccf0f7188cfe585ba962d2674b241c01916d780925df34873bceb0", size = 144439, upload-time = "2025-09-05T15:02:27.511Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grpcio"
|
||||
version = "1.75.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9d/f7/8963848164c7604efb3a3e6ee457fdb3a469653e19002bd24742473254f8/grpcio-1.75.1.tar.gz", hash = "sha256:3e81d89ece99b9ace23a6916880baca613c03a799925afb2857887efa8b1b3d2", size = 12731327, upload-time = "2025-09-26T09:03:36.887Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/46/74/bac4ab9f7722164afdf263ae31ba97b8174c667153510322a5eba4194c32/grpcio-1.75.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:3bed22e750d91d53d9e31e0af35a7b0b51367e974e14a4ff229db5b207647884", size = 5672779, upload-time = "2025-09-26T09:02:19.11Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/52/d0483cfa667cddaa294e3ab88fd2c2a6e9dc1a1928c0e5911e2e54bd5b50/grpcio-1.75.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:5b8f381eadcd6ecaa143a21e9e80a26424c76a0a9b3d546febe6648f3a36a5ac", size = 11470623, upload-time = "2025-09-26T09:02:22.117Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/e4/d1954dce2972e32384db6a30273275e8c8ea5a44b80347f9055589333b3f/grpcio-1.75.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5bf4001d3293e3414d0cf99ff9b1139106e57c3a66dfff0c5f60b2a6286ec133", size = 6248838, upload-time = "2025-09-26T09:02:26.426Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/43/073363bf63826ba8077c335d797a8d026f129dc0912b69c42feaf8f0cd26/grpcio-1.75.1-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:9f82ff474103e26351dacfe8d50214e7c9322960d8d07ba7fa1d05ff981c8b2d", size = 6922663, upload-time = "2025-09-26T09:02:28.724Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/6f/076ac0df6c359117676cacfa8a377e2abcecec6a6599a15a672d331f6680/grpcio-1.75.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0ee119f4f88d9f75414217823d21d75bfe0e6ed40135b0cbbfc6376bc9f7757d", size = 6436149, upload-time = "2025-09-26T09:02:30.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/27/1d08824f1d573fcb1fa35ede40d6020e68a04391709939e1c6f4193b445f/grpcio-1.75.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:664eecc3abe6d916fa6cf8dd6b778e62fb264a70f3430a3180995bf2da935446", size = 7067989, upload-time = "2025-09-26T09:02:33.233Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/98/98594cf97b8713feb06a8cb04eeef60b4757e3e2fb91aa0d9161da769843/grpcio-1.75.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c32193fa08b2fbebf08fe08e84f8a0aad32d87c3ad42999c65e9449871b1c66e", size = 8010717, upload-time = "2025-09-26T09:02:36.011Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/7e/bb80b1bba03c12158f9254762cdf5cced4a9bc2e8ed51ed335915a5a06ef/grpcio-1.75.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5cebe13088b9254f6e615bcf1da9131d46cfa4e88039454aca9cb65f639bd3bc", size = 7463822, upload-time = "2025-09-26T09:02:38.26Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/1c/1ea57fdc06927eb5640f6750c697f596f26183573069189eeaf6ef86ba2d/grpcio-1.75.1-cp313-cp313-win32.whl", hash = "sha256:4b4c678e7ed50f8ae8b8dbad15a865ee73ce12668b6aaf411bf3258b5bc3f970", size = 3938490, upload-time = "2025-09-26T09:02:40.268Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/24/fbb8ff1ccadfbf78ad2401c41aceaf02b0d782c084530d8871ddd69a2d49/grpcio-1.75.1-cp313-cp313-win_amd64.whl", hash = "sha256:5573f51e3f296a1bcf71e7a690c092845fb223072120f4bdb7a5b48e111def66", size = 4642538, upload-time = "2025-09-26T09:02:42.519Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/1b/9a0a5cecd24302b9fdbcd55d15ed6267e5f3d5b898ff9ac8cbe17ee76129/grpcio-1.75.1-cp314-cp314-linux_armv7l.whl", hash = "sha256:c05da79068dd96723793bffc8d0e64c45f316248417515f28d22204d9dae51c7", size = 5673319, upload-time = "2025-09-26T09:02:44.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/ec/9d6959429a83fbf5df8549c591a8a52bb313976f6646b79852c4884e3225/grpcio-1.75.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:06373a94fd16ec287116a825161dca179a0402d0c60674ceeec8c9fba344fe66", size = 11480347, upload-time = "2025-09-26T09:02:47.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/7a/26da709e42c4565c3d7bf999a9569da96243ce34a8271a968dee810a7cf1/grpcio-1.75.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4484f4b7287bdaa7a5b3980f3c7224c3c622669405d20f69549f5fb956ad0421", size = 6254706, upload-time = "2025-09-26T09:02:50.4Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/08/dcb26a319d3725f199c97e671d904d84ee5680de57d74c566a991cfab632/grpcio-1.75.1-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2720c239c1180eee69f7883c1d4c83fc1a495a2535b5fa322887c70bf02b16e8", size = 6922501, upload-time = "2025-09-26T09:02:52.711Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/66/044d412c98408a5e23cb348845979a2d17a2e2b6c3c34c1ec91b920f49d0/grpcio-1.75.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:07a554fa31c668cf0e7a188678ceeca3cb8fead29bbe455352e712ec33ca701c", size = 6437492, upload-time = "2025-09-26T09:02:55.542Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/9d/5e3e362815152aa1afd8b26ea613effa005962f9da0eec6e0e4527e7a7d1/grpcio-1.75.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:3e71a2105210366bfc398eef7f57a664df99194f3520edb88b9c3a7e46ee0d64", size = 7081061, upload-time = "2025-09-26T09:02:58.261Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/1a/46615682a19e100f46e31ddba9ebc297c5a5ab9ddb47b35443ffadb8776c/grpcio-1.75.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:8679aa8a5b67976776d3c6b0521e99d1c34db8a312a12bcfd78a7085cb9b604e", size = 8010849, upload-time = "2025-09-26T09:03:00.548Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/8e/3204b94ac30b0f675ab1c06540ab5578660dc8b690db71854d3116f20d00/grpcio-1.75.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:aad1c774f4ebf0696a7f148a56d39a3432550612597331792528895258966dc0", size = 7464478, upload-time = "2025-09-26T09:03:03.096Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/97/2d90652b213863b2cf466d9c1260ca7e7b67a16780431b3eb1d0420e3d5b/grpcio-1.75.1-cp314-cp314-win32.whl", hash = "sha256:62ce42d9994446b307649cb2a23335fa8e927f7ab2cbf5fcb844d6acb4d85f9c", size = 4012672, upload-time = "2025-09-26T09:03:05.477Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/df/e2e6e9fc1c985cd1a59e6996a05647c720fe8a03b92f5ec2d60d366c531e/grpcio-1.75.1-cp314-cp314-win_amd64.whl", hash = "sha256:f86e92275710bea3000cb79feca1762dc0ad3b27830dd1a74e82ab321d4ee464", size = 4772475, upload-time = "2025-09-26T09:03:07.661Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "grpcio-status"
|
||||
version = "1.75.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "googleapis-common-protos" },
|
||||
{ name = "grpcio" },
|
||||
{ name = "protobuf" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/74/5b/1ce0e3eedcdc08b4739b3da5836f31142ec8bee1a9ae0ad8dc0dc39a14bf/grpcio_status-1.75.1.tar.gz", hash = "sha256:8162afa21833a2085c91089cc395ad880fac1378a1d60233d976649ed724cbf8", size = 13671, upload-time = "2025-09-26T09:13:16.412Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/ad/6f414bb0b36eee20d93af6907256f208ffcda992ae6d3d7b6a778afe31e6/grpcio_status-1.75.1-py3-none-any.whl", hash = "sha256:f681b301be26dcf7abf5c765d4a22e4098765e1a65cbdfa3efca384edf8e4e3c", size = 14428, upload-time = "2025-09-26T09:12:55.516Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.16.0"
|
||||
@@ -1282,6 +1435,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/db/14bafcb4af2139e046d03fd00dea7873e48eafe18b7d2797e73d6681f210/prometheus_client-0.23.1-py3-none-any.whl", hash = "sha256:dd1913e6e76b59cfe44e7a4b83e01afc9873c1bdfd2ed8739f1e76aeca115f99", size = 61145, upload-time = "2025-09-18T20:47:23.875Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proto-plus"
|
||||
version = "1.26.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "protobuf" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f4/ac/87285f15f7cce6d4a008f33f1757fb5a13611ea8914eb58c3d0d26243468/proto_plus-1.26.1.tar.gz", hash = "sha256:21a515a4c4c0088a773899e23c7bbade3d18f9c66c73edd4c7ee3816bc96a012", size = 56142, upload-time = "2025-03-10T15:54:38.843Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/6d/280c4c2ce28b1593a19ad5239c8b826871fc6ec275c21afc8e1820108039/proto_plus-1.26.1-py3-none-any.whl", hash = "sha256:13285478c2dcf2abb829db158e1047e2f1e8d63a077d94263c2b88b043c75a66", size = 50163, upload-time = "2025-03-10T15:54:37.335Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "protobuf"
|
||||
version = "6.32.1"
|
||||
@@ -1321,6 +1486,27 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/49/a6cfc94a9c483b1fa401fbcb23aca7892f60c7269c5ffa2ac408364f80dc/psycopg2-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:91fd603a2155da8d0cfcdbf8ab24a2d54bca72795b90d2a3ed2b6da8d979dee2", size = 2569060, upload-time = "2025-01-04T20:09:15.28Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyasn1"
|
||||
version = "0.6.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyasn1-modules"
|
||||
version = "0.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pyasn1" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e9/e6/78ebbb10a8c8e4b61a59249394a4a594c1a7af95593dc933a349c8d00964/pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6", size = 307892, upload-time = "2025-03-28T02:41:22.17Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/47/8d/d529b5d697919ba8c11ad626e835d4039be708a35b0d22de83a269a6682c/pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a", size = 181259, upload-time = "2025-03-28T02:41:19.028Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.23"
|
||||
@@ -1736,6 +1922,18 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/32/7d/97119da51cb1dd3f2f3c0805f155a3aa4a95fa44fe7d78ae15e69edf4f34/rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772", size = 230097, upload-time = "2025-08-27T12:15:03.961Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "4.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pyasn1" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/da/8a/22b7beea3ee0d44b1916c0c1cb0ee3af23b700b6da9f04991899d0c555d4/rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75", size = 29034, upload-time = "2025-04-16T09:51:18.218Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/64/8d/0133e4eb4beed9e425d9a98ed6e081a55d195481b7632472be1af08d2f6b/rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762", size = 34696, upload-time = "2025-04-16T09:51:17.142Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruamel-yaml"
|
||||
version = "0.18.15"
|
||||
|
||||
Reference in New Issue
Block a user