pgx
PGX — Lightweight Postgres for AI agents. Written in Rust. Thousands of isolated databases in one runtime. 🐘
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Starter kit oficial del reto MLOps Pulso TransMi. Incluye un cliente Python, ejemplos reproducibles y una plantilla de GitHub Actions para construir un pipeline que descargue datos, entrene, monitoree y posteriormente envíe predicciones. Disponible públicamente: la API de lectura está en https://pulso-transmi.72-60-245-2.sslip.io y su documentación interactiva en /docs.檢視完整 README ↗
Starter kit oficial del reto MLOps Pulso TransMi. Incluye un cliente Python, ejemplos reproducibles y una plantilla de GitHub Actions para construir un pipeline que descargue datos, entrene, monitoree y posteriormente envíe predicciones.
Disponible públicamente: la API de lectura está en
https://pulso-transmi.72-60-245-2.sslip.ioy su documentación interactiva en/docs.
Se pronostica demanda sintética cada 15 minutos para 12 estaciones reales de TransMilenio. El sistema liberará observaciones con el tiempo y cambiará algunos patrones durante la competencia. Un modelo entrenado una sola vez puede perder desempeño: el objetivo es operar un pipeline capaz de medir, decidir y reentrenar.
estaciones provienen de datos oficiales de TransMilenio.
Requiere Python 3.11 o superior.
git clone https://github.com/uexternadojz/pulso-transmi-sdk.git
cd pulso-transmi-sdk
python -m venv .venv
source .venv/bin/activate
python -m pip install -e '.[ml]'
cp .env.example .env
python examples/01_download.py
python examples/02_naive_baseline.py
En Windows PowerShell, la activación es .venv\Scripts\Activate.ps1.
from pulso_transmi import PulsoTransmiClient
client = PulsoTransmiClient()
print(client.meta())
stations = client.stations()
observations = client.observations_dataframe(station_id="07107")
context = client.context_dataframe()
print(stations.head())
print(observations.tail())
El SDK recorre automáticamente todas las páginas. Si prefieres controlar cada
página, usa client.observations_page(...) y conserva next_cursor exactamente
como lo entrega la API.
| Recurso | Tamaño |
|---|---|
| Estaciones | 12 |
| Frecuencia | 15 minutos |
| Historia | 45 días |
| Periodos por estación | 4.320 |
| Observaciones | 51.840 |
Para evaluación local, usa una división temporal: por ejemplo, primeros 38 días para entrenamiento y últimos 7 para validación. Una partición aleatoria mezcla futuro y pasado y genera métricas engañosas.
0.2.0| Método | Ruta | Uso |
|---|---|---|
GET | /health | Estado básico |
GET | /v1/meta | Versión, rango, hashes y enlaces |
GET | /v1/stations | Catálogo geográfico |
GET | /v1/observations | Demanda paginada |
GET | /v1/context | Clima y eventos |
GET | /v1/downloads/{filename} | Descarga completa |
Swagger está disponible en /docs. Consulta docs/api.md para
filtros, paginación y errores.
mi-pulso-transmi/
├── src/
│ ├── ingest.py
│ ├── features.py
│ ├── train.py
│ ├── predict.py
│ └── monitor.py
├── tests/
├── artifacts/
├── requirements.txt o pyproject.toml
└── .github/workflows/pipeline.yml
El repositorio de cada equipo debe dejar trazabilidad de:
templates/pipeline.yml es una plantilla manual. Cópiala
a .github/workflows/pipeline.yml dentro del repositorio de tu equipo. Cuando se
habilite la competencia, agrega el API key como secret y luego activa el horario
indicado por el profesor.
Nunca escribas API keys, contraseñas de Supabase ni tokens dentro del código.
Supabase es opcional para persistir ejecuciones, métricas, predicciones y estado del modelo. Vercel es opcional y corresponde al bono de visualización. Ninguna de las dos plataformas reemplaza el repositorio ni GitHub Actions.
Consulta docs/student-project.md para el flujo completo y los entregables.
La referencia actual es:
WAPE = sum(abs(real - predicción)) / sum(real)
Accuracy = 100 × max(0, 1 - WAPE)
La métrica se calcula por estación y luego se promedia. El contrato definitivo de submissions y leaderboard se publicará antes de iniciar la ventana competitiva.
python -m pip install -e '.[dev,ml]'
pytest -q
Después de descargar los datos, instala la dependencia de gráficos y ejecuta:
python -m pip install -e '.[eda]'
python eda/01_eda_inicial.py
El script escribe en eda_outputs/ un resumen de calidad por columna, un
resumen estadístico por estación, las correlaciones ordenadas con demand y
gráficos sobre composición, ubicación geográfica, evolución temporal,
distribución, perfil horario y promedios por hora y día de la semana.
Para comparar los baselines estacionales con un modelo global de gradient boosting, ejecuta:
python examples/03_gradient_boosting.py
El experimento usa backtesting rolling sobre tres folds semanales, retardos de
demanda, ventanas históricas, calendario, estación, clima pronosticado y
eventos. Evalúa modelos directos para 15, 30, 45 y 60 minutos; las variables
meteorológicas observadas no se usan porque no estarían disponibles al predecir
el futuro. Guarda el detalle por horizonte, modelo, fold y estación en
reports/ml_validation_metrics.csv.
La validación simula además el desfase entre la última observación disponible y
el data_cutoff del ciclo (actualmente 133 intervalos de 15 minutos). Así, las
features de demanda no consultan datos que aún no existirían al inferir. El
paquete selecciona modelos y pesos por horizonte frente al baseline semanal. En
la validación con ese desfase, el WAPE fue aproximadamente 13.89%, 13.76%,
13.96% y 14.11% para 15, 30, 45 y 60 minutos, respectivamente. Son métricas
offline de validación temporal; el puntaje de competencia solo se confirma con
una submission aceptada y evaluada por la plataforma.
Todas las evaluaciones se registran en MLflow: parámetros, WAPE por estación,
accuracy promedio, fold, horizonte, cobertura de las 12 estaciones, reporte CSV
y modelo serializado. MLflow usa por defecto mlflow.db y mlruns/ localmente.
Para abrir la interfaz:
mlflow ui --backend-store-uri sqlite:///mlflow.db
Después visita http://127.0.0.1:5000. Las corridas se agrupan en el experimento
pulso-transmi-forecasting. mlruns/ y mlflow.db son artefactos locales y no
deben subirse al repositorio.
Para empaquetar los mejores modelos validados, ejecuta:
PYTHONPATH=src python examples/04_package_best_model.py
El paquete se genera en artifacts/pulso_transmi_best_models.zip e incluye un
modelo por horizonte, la configuración del ensemble, el WAPE de las 12
estaciones y un manifiesto SHA-256.
El entrenamiento y el empaquetado se apoyan en data/snapshot.json. Si el hash
del snapshot no coincide con los datos cargados, el proceso se detiene, de modo
que las métricas siempre pertenecen al mismo estado del dataset.
examples/03_gradient_boosting.py acepta una ventana de validación anclada y la
puntuación del campeón:
PYTHONPATH=src python examples/03_gradient_boosting.py \
--validation-anchor 2026-09-01T00:00:00+00:00 \
--score-champion artifacts/previous_model \
--champion-version <model_version_del_campeon>
Con --validation-anchor las folds se repiten idénticas en cada corrida, y con
--score-champion el modelo activo se puntúa sobre esas mismas folds.
examples/04_package_best_model.py guarda esa evidencia en
promotion_inputs.json (métricas de candidato y campeón con la misma ventana,
los mismos horizontes y el mismo hueco de historia) y la incluye en el ZIP, en el
manifiesto y en los artefactos de MLflow.
scripts/promote_model.py solo promueve cuando la comparación es emparejada:
--allow-unpaired es una salida de emergencia para paquetes antiguos y deja
constancia escrita en artifacts/model_promotion.json.
La compuerta y la lectura de la evidencia empaquetada están cubiertas por
python -m pytest tests/test_model_gate.py tests/test_promote_pairing.py.
El contrato vigente de submissions está disponible en /docs y en
/openapi.json. El ciclo activo se consulta en
/v1/forecast-cycles/current; sus targets definen exactamente las estaciones y
fechas que deben enviarse.
export PULSO_API_KEY='TU_API_KEY'
PYTHONPATH=src python scripts/submit_prediction.py \
--template /tmp/submission.json
# Completa predictions[].value con las predicciones del modelo
PYTHONPATH=src python scripts/submit_prediction.py \
--payload /tmp/submission.json
El script valida cycle_id, data_cutoff, cobertura de estaciones, cantidad de
predicciones y rangos antes de enviar a POST /v1/submissions. Usa una clave de
idempotencia automáticamente. La API puede pedir 12 predicciones para un ciclo
de 15 minutos; siempre debe obedecerse la respuesta del ciclo actual.
El workflow .github/workflows/forecast_cycle.yml consulta ciclos con dos
horarios escalonados (cada 2–3 minutos nominalmente). Descarga los datos al inicio
de cada ejecución e intenta enviar solo cuando la API tiene un ciclo abierto. El
resumen de Actions muestra el cycle_id, el número de predicciones y si la API
confirmó la entrega. Requiere el secreto PULSO_API_KEY.
El pipeline separa cuatro tareas programadas: .github/workflows/data_collector.yml
guarda observaciones cada 30 minutos; forecast_cycle.yml consulta ciclos cada
2–3 minutos e intenta enviar las predicciones; wape_drift.yml compara cada media
hora el WAPE por estación de dos ventanas consecutivas de siete días, usando solo
predicciones oficiales con resultado real disponible; y retrain_on_drift.yml
reentrena ante alertas pendientes y conserva la accuracy de validación temporal
como criterio de promoción. El drift usa por defecto un umbral relativo de -5%:
activa cuando el WAPE reciente es al menos el 95% de la referencia. Exige al menos
120 pares y 10 estaciones en cada ventana.
Aplica las migraciones de supabase/migrations/ y configura SUPABASE_SERVICE_ROLE_KEY
como secreto en GitHub Actions. Sin ese secreto no se pueden persistir los datos,
las predicciones ni las alertas WAPE. La tabla de predicciones empieza a llenarse
cuando se confirma una submission oficial; el monitor necesita dos ventanas con
resultados maduros (hasta 14 días) antes de poder detectar deterioro. Ajusta
WAPE_DRIFT_THRESHOLD si necesitas otro umbral relativo.
El dashboard del bono está en dashboard/. Aplica también la migración
20260923100000_add_dashboard_rpc.sql; publica dashboard/ como sitio estático
en Vercel y configura el directorio raíz del proyecto como dashboard. En
dashboard/config.js agrega la URL del proyecto Supabase y su clave publicable
(anon). La página solo consulta la RPC agregada forecast_dashboard; nunca uses
SUPABASE_SERVICE_ROLE_KEY ni una clave sb_secret_ en el navegador. El panel
muestra accuracy acumulada y rolling de 24 horas, tendencia diaria, distribución
del error, mapa esquemático por estación, alertas de WAPE drift, última ejecución
y modelo activo. La posición del leaderboard queda como no disponible mientras
la API de la competencia no publique standings.
La migración crea las tablas en supabase/migrations/. Para cargar el corte
actual de la API en datasets, stations, context y observations, usa una
service_role key únicamente como variable local y ejecuta:
export SUPABASE_URL=https://TU_PROJECT_REF.supabase.co
export SUPABASE_SERVICE_ROLE_KEY='TU_SERVICE_ROLE_KEY'
PYTHONPATH=src python scripts/ingest_api_to_supabase.py
El script usa upsert por lotes y puede repetirse sin duplicar datos. Nunca
subas la service_role key al repositorio ni la uses en el navegador.
Este repositorio es público para estudiantes. No debe contener ground truth futuro, semillas, configuración privada del escenario ni parámetros de drift.