Implementa un agente financiero que consulta información sobre la inflación en Argentina utilizando OpenAI y herramientas de Wikipedia y Yahoo Finance. Se define un flujo de trabajo en Prefect para gestionar la ejecución y el registro de mensajes enviados al modelo.
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"version": "1",
|
||||
"metadata": {
|
||||
"marimo_version": "0.16.5"
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"id": "MJUe",
|
||||
"code_hash": "bf4c2ec3da54726b1dcf7bbacfb8a9fc",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/html": "<span class=\"markdown prose dark:prose-invert\"><h1 id=\"opentelemetry-grafana-stack-con-dashboards-preconfigurados\">\ud83d\udd2d OpenTelemetry + Grafana Stack con dashboards preconfigurados \ud83d\ude80</h1></span>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "Hbol",
|
||||
"code_hash": "1d0db38904205bec4d6f6f6a1f6cec3e",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "vblA",
|
||||
"code_hash": "9d8691f09dd3c2a110820415983b143e",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "bkHC",
|
||||
"code_hash": "95bf1fb529e82c3fbd4731c219f2b0b4",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "lEQa",
|
||||
"code_hash": "4d9a7cdeb028ab0e0df782ba3a18ec56",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "PKri",
|
||||
"code_hash": "42e8a076992b5694ca5db7e1da939de4",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": [
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": "time=\"2025-10-05T18:15:27+02:00\" level=warning msg=\"/home/lucas/DataProyects/mis_agentes/conseguir_datos_con_agentes/observability_stack/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion\"\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": "time=\"2025-10-05T18:15:27+02:00\" level=warning msg=\"/home/lucas/DataProyects/mis_agentes/conseguir_datos_con_agentes/observability_stack/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion\"\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Network observability_stack_default Creating\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Network observability_stack_default Created\n Container tempo Creating\n Container victoria Creating\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Container victoria Created\n Container tempo Created\n Container otel-collector Creating\n Container grafana-srv Creating\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Container otel-collector Created\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Container grafana-srv Created\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Container victoria Starting\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Container tempo Starting\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Container victoria Started\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Container tempo Started\n Container otel-collector Starting\n Container grafana-srv Starting\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stdout",
|
||||
"text": "\u2705 Sistema de observabilidad inicializado con dashboards preconfigurados\nGrafana: http://localhost:33000 (user: admin, pass: admin123)\nCollector OTLP HTTP: http://localhost:4318\nCollector OTLP gRPC: localhost:4317\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": " Container otel-collector Started\n Container grafana-srv Started\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,102 @@
|
||||
import marimo
|
||||
|
||||
__generated_with = "0.14.17"
|
||||
app = marimo.App(width="medium")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""# Grafana: Inicialización automática 🚀""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import os
|
||||
import yaml
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
# ==== Parámetros ====
|
||||
PUERTO_GRAFANA = 33000 # puerto host -> 3000 del contenedor
|
||||
SERVICIO = "grafana_srv"
|
||||
ADMIN_USER = "admin"
|
||||
ADMIN_PASSWORD = "admin123"
|
||||
RUTA_PROYECTO = Path(".").resolve()
|
||||
|
||||
return (
|
||||
ADMIN_PASSWORD,
|
||||
ADMIN_USER,
|
||||
Path,
|
||||
PUERTO_GRAFANA,
|
||||
RUTA_PROYECTO,
|
||||
SERVICIO,
|
||||
subprocess,
|
||||
yaml,
|
||||
)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(Path, yaml):
|
||||
def crear_docker_compose(ruta: Path, servicio: str, puerto_host: int, admin_user: str, admin_password: str):
|
||||
compose = {
|
||||
"version": "3.8",
|
||||
"services": {
|
||||
servicio: {
|
||||
"image": "grafana/grafana:latest",
|
||||
"container_name": servicio,
|
||||
"restart": "always",
|
||||
"ports": [f"{puerto_host}:3000"],
|
||||
"environment": {
|
||||
"GF_SECURITY_ADMIN_USER": admin_user,
|
||||
"GF_SECURITY_ADMIN_PASSWORD": admin_password,
|
||||
"GF_USERS_ALLOW_SIGN_UP": "false",
|
||||
"GF_INSTALL_PLUGINS": "grafana-piechart-panel,grafana-worldmap-panel",
|
||||
},
|
||||
"volumes": [
|
||||
"grafana_data:/var/lib/grafana",
|
||||
],
|
||||
}
|
||||
},
|
||||
"volumes": {"grafana_data": {}}
|
||||
}
|
||||
|
||||
(ruta / "docker-compose.yml").write_text(yaml.dump(compose, sort_keys=False), encoding="utf-8")
|
||||
|
||||
return (crear_docker_compose,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(Path, subprocess):
|
||||
def construir_y_levantar(ruta: Path):
|
||||
def _run(cmd):
|
||||
subprocess.run(cmd, cwd=ruta, check=True)
|
||||
|
||||
try:
|
||||
_run(["docker", "compose", "build"])
|
||||
_run(["docker", "compose", "up", "-d"])
|
||||
except Exception:
|
||||
_run(["docker-compose", "build"])
|
||||
_run(["docker-compose", "up", "-d"])
|
||||
|
||||
return (construir_y_levantar,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(ADMIN_PASSWORD, ADMIN_USER, PUERTO_GRAFANA, RUTA_PROYECTO, SERVICIO, construir_y_levantar, crear_docker_compose):
|
||||
if __name__ == "__main__":
|
||||
RUTA_PROYECTO.mkdir(parents=True, exist_ok=True)
|
||||
crear_docker_compose(RUTA_PROYECTO, SERVICIO, PUERTO_GRAFANA, ADMIN_USER, ADMIN_PASSWORD)
|
||||
construir_y_levantar(RUTA_PROYECTO)
|
||||
print(f"✅ Grafana inicializado en http://localhost:{PUERTO_GRAFANA} (usuario: {ADMIN_USER}, contraseña: {ADMIN_PASSWORD})")
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
@@ -0,0 +1,262 @@
|
||||
import marimo
|
||||
|
||||
__generated_with = "0.16.5"
|
||||
app = marimo.App(width="columns")
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import marimo as mo
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""# 🐘 Postgres: DDBB con extensiones avanzadas (pgvector, PostGIS, TimescaleDB, etc.)""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import os
|
||||
import textwrap
|
||||
import yaml
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
# ==== Parámetros ====
|
||||
PUERTO_POSTGRES = 55432
|
||||
SERVICIO = "postgres_ext"
|
||||
PASSWORD = "mipassword"
|
||||
USER = "postgres"
|
||||
DBNAME = "basededatos"
|
||||
|
||||
# ==== Extensiones que quieres habilitar ====
|
||||
EXTENSIONES = [
|
||||
# Builtins
|
||||
"hstore", "citext", "uuid-ossp", "pg_trgm",
|
||||
"fuzzystrmatch", "tablefunc", "unaccent", "ltree",
|
||||
# Ecosistema extendido
|
||||
"postgis", "pgvector", "timescaledb",
|
||||
]
|
||||
|
||||
RUTA_PROYECTO = Path(".").resolve()
|
||||
return (
|
||||
DBNAME,
|
||||
EXTENSIONES,
|
||||
PASSWORD,
|
||||
PUERTO_POSTGRES,
|
||||
Path,
|
||||
RUTA_PROYECTO,
|
||||
SERVICIO,
|
||||
USER,
|
||||
subprocess,
|
||||
yaml,
|
||||
)
|
||||
|
||||
|
||||
@app.function
|
||||
def pkgs_para_extensiones(exts, pg_major=15):
|
||||
"""
|
||||
Devuelve (pkgs_apt, builtins, needs_timescale_repo)
|
||||
builtins = extensiones que no requieren apt
|
||||
pkgs_apt = paquetes apt necesarios para extensiones adicionales
|
||||
needs_timescale_repo = True si hay que añadir el repo de TimescaleDB
|
||||
"""
|
||||
builtins = []
|
||||
pkgs_apt = []
|
||||
needs_timescale_repo = False
|
||||
|
||||
for e in exts:
|
||||
e_low = e.lower()
|
||||
|
||||
if e_low in {
|
||||
"hstore", "citext", "uuid-ossp", "pg_trgm",
|
||||
"fuzzystrmatch", "tablefunc", "unaccent", "ltree"
|
||||
}:
|
||||
builtins.append(e_low)
|
||||
|
||||
elif e_low == "postgis":
|
||||
pkgs_apt += [
|
||||
f"postgresql-{pg_major}-postgis-3",
|
||||
f"postgresql-{pg_major}-postgis-3-scripts",
|
||||
"gdal-bin",
|
||||
"proj-bin",
|
||||
]
|
||||
|
||||
elif e_low == "pgvector":
|
||||
pkgs_apt += [f"postgresql-{pg_major}-pgvector"]
|
||||
|
||||
elif e_low == "timescaledb":
|
||||
needs_timescale_repo = True
|
||||
pkgs_apt += [f"timescaledb-2-postgresql-{pg_major}"]
|
||||
|
||||
else:
|
||||
raise ValueError(f"Extensión no soportada: {e}")
|
||||
|
||||
pkgs_apt = sorted(set(pkgs_apt))
|
||||
return pkgs_apt, builtins, needs_timescale_repo
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(DBNAME, Path, USER):
|
||||
from textwrap import dedent
|
||||
from textwrap import indent
|
||||
from textwrap import dedent
|
||||
|
||||
def generar_dockerfile(ruta: Path, exts, pg_major=15):
|
||||
ruta.mkdir(parents=True, exist_ok=True)
|
||||
pkgs_apt, builtins, needs_timescale_repo = pkgs_para_extensiones(exts, pg_major)
|
||||
|
||||
base_image = f"postgres:{pg_major}"
|
||||
|
||||
apt_lines = [
|
||||
"RUN apt-get update && \\",
|
||||
" apt-get install -y wget gnupg && \\",
|
||||
]
|
||||
|
||||
if needs_timescale_repo:
|
||||
apt_lines += [
|
||||
" wget -qO- https://packagecloud.io/timescale/timescaledb/gpgkey | gpg --dearmor -o /usr/share/keyrings/timescaledb.gpg && \\",
|
||||
' echo \"deb [signed-by=/usr/share/keyrings/timescaledb.gpg] https://packagecloud.io/timescale/timescaledb/debian bookworm main\" > /etc/apt/sources.list.d/timescaledb.list && \\',
|
||||
" apt-get update && \\",
|
||||
]
|
||||
|
||||
if pkgs_apt:
|
||||
apt_lines.append(" DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \\")
|
||||
for pkg in pkgs_apt:
|
||||
apt_lines.append(f" {pkg} \\")
|
||||
apt_lines.append(" && rm -rf /var/lib/apt/lists/*")
|
||||
|
||||
apt_block = "\n".join(apt_lines)
|
||||
|
||||
# Si usa Timescale, añadimos pre-carga
|
||||
preload_block = ""
|
||||
if "timescaledb" in [e.lower() for e in exts]:
|
||||
preload_block = (
|
||||
"\n# Preload TimescaleDB\n"
|
||||
"RUN echo \"shared_preload_libraries = 'timescaledb'\" >> /usr/share/postgresql/postgresql.conf.sample\n"
|
||||
)
|
||||
|
||||
dockerfile = f"""
|
||||
FROM {base_image}
|
||||
|
||||
# Variables de entorno
|
||||
ENV POSTGRES_USER={USER} \\
|
||||
POSTGRES_DB={DBNAME}
|
||||
|
||||
{apt_block}
|
||||
|
||||
{preload_block}
|
||||
|
||||
# Copiamos scripts de inicialización
|
||||
COPY docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/
|
||||
"""
|
||||
|
||||
(ruta / "Dockerfile").write_text(dedent(dockerfile).strip() + "\n", encoding="utf-8")
|
||||
|
||||
return (generar_dockerfile,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(Path):
|
||||
def generar_init_sql(ruta: Path, exts):
|
||||
init_dir = ruta / "docker-entrypoint-initdb.d"
|
||||
init_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
lines = ["-- Habilitar extensiones solicitadas"]
|
||||
for e in exts:
|
||||
e_low = e.lower()
|
||||
ext_name = {
|
||||
"pgvector": "vector",
|
||||
"postgis": "postgis",
|
||||
"hstore": "hstore",
|
||||
"citext": "citext",
|
||||
"uuid-ossp": "\"uuid-ossp\"",
|
||||
"pg_trgm": "pg_trgm",
|
||||
"fuzzystrmatch": "fuzzystrmatch",
|
||||
"tablefunc": "tablefunc",
|
||||
"unaccent": "unaccent",
|
||||
"ltree": "ltree",
|
||||
"timescaledb": "timescaledb",
|
||||
}.get(e_low, e_low)
|
||||
lines.append(f"CREATE EXTENSION IF NOT EXISTS {ext_name};")
|
||||
|
||||
sql = "\n".join(lines) + "\n"
|
||||
(init_dir / "10-extensions.sql").write_text(sql, encoding="utf-8")
|
||||
|
||||
return (generar_init_sql,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(DBNAME, Path, USER, yaml):
|
||||
def crear_docker_compose(ruta: Path, servicio: str, puerto_host: int, password: str):
|
||||
compose = {
|
||||
"services": {
|
||||
servicio: {
|
||||
"build": {"context": "."},
|
||||
"restart": "always",
|
||||
"ports": [f"{puerto_host}:5432"],
|
||||
"environment": {
|
||||
"POSTGRES_PASSWORD": password,
|
||||
"POSTGRES_USER": USER,
|
||||
"POSTGRES_DB": DBNAME,
|
||||
},
|
||||
"healthcheck": {
|
||||
"test": ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"],
|
||||
"interval": "10s",
|
||||
"timeout": "5s",
|
||||
"retries": 5,
|
||||
},
|
||||
"volumes": ["postgres_data:/var/lib/postgresql/data"],
|
||||
}
|
||||
},
|
||||
"volumes": {"postgres_data": {}},
|
||||
}
|
||||
|
||||
(ruta / "docker-compose.yml").write_text(yaml.dump(compose, sort_keys=False), encoding="utf-8")
|
||||
|
||||
return (crear_docker_compose,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(Path, subprocess):
|
||||
def construir_y_levantar(ruta: Path):
|
||||
def _run(cmd):
|
||||
subprocess.run(cmd, cwd=ruta, check=True)
|
||||
|
||||
try:
|
||||
_run(["docker", "compose", "build"])
|
||||
_run(["docker", "compose", "up", "-d"])
|
||||
except Exception:
|
||||
_run(["docker-compose", "build"])
|
||||
_run(["docker-compose", "up", "-d"])
|
||||
|
||||
return (construir_y_levantar,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(
|
||||
EXTENSIONES,
|
||||
PASSWORD,
|
||||
PUERTO_POSTGRES,
|
||||
RUTA_PROYECTO,
|
||||
SERVICIO,
|
||||
construir_y_levantar,
|
||||
crear_docker_compose,
|
||||
generar_dockerfile,
|
||||
generar_init_sql,
|
||||
):
|
||||
if __name__ == "__main__":
|
||||
RUTA_PROYECTO.mkdir(parents=True, exist_ok=True)
|
||||
generar_dockerfile(RUTA_PROYECTO, EXTENSIONES)
|
||||
generar_init_sql(RUTA_PROYECTO, EXTENSIONES)
|
||||
crear_docker_compose(RUTA_PROYECTO, SERVICIO, PUERTO_POSTGRES, PASSWORD)
|
||||
construir_y_levantar(RUTA_PROYECTO)
|
||||
print(f"✅ Postgres inicializado en http://localhost:{PUERTO_POSTGRES}")
|
||||
print("📦 Extensiones instaladas:", ", ".join(EXTENSIONES))
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
Reference in New Issue
Block a user