Alexei Rojas Quiroga
← Todos los proyectos

Proyecto personal

Apagones Habana

Mapa de apagones de La Habana casi en tiempo real, hecho desde un canal de Telegram

Estado
En vivo
Rol
En solitario: arquitectura, pipeline de datos, integración LLM, frontend, bot, despliegue y operación
Sitio en vivo GitHub

Arquitectura

  • Disparado por un guardián externo cada 30 min
  • Serverless en Cloudflare + GitHub Actions
  • Reglas primero, LLM después
  • Las pruebas bloquean cada publicación
  • Supabase PostgreSQL

gha corre las pruebas, el ingestor trae las publicaciones nuevas, las reglas y los jobs LLM las convierten en eventos y enriquecimiento, y los builders publican datos estáticos frescos en Pages.

Arquitectura · 10 nodos · 1 flujos
LO QUE CONSTRUÍTelegramFuente de apagonesCanal oficial y grupode discusiónPython · Telet…Ingesta de mensajesDescarga incremental deposts y comentariosPython · regexExtracción deapagonesReglas por bloque,circuito y zonaPython scriptsJobs deenriquecimiento LLMPartes, comentarios,notas de voz,embeddingsPython scriptsGenerador de datosestáticosestado.json, circuitos,analítica, SEOCloudflare Pag…Sitio y API en eledgeSitio estático yendpoints /apiMapLibre · JSMapa de apagonesMapa, circuitos,analítica, preguntasfrecuentesSupabase · Pos…Almacén de mensajesy eventosmensajes, eventos,comentarios_llm,reportes, vectoresNaN · NIM · Wo…Proveedores LLMNaN Builders, NVIDIANIM, Workers AIGitHub ActionsEjecutor delpipelinePruebas, ingesta,build, deploy1234567891011
  • Servicio / cómputo
  • Almacén de datos
  • IA
  • Cliente
  • Sistema externo
  • Síncrono
  • Asíncrono / bucle
Desplázate hacia los lados para ver todo el diagrama

Cómo fluye, paso a paso

Haz clic en un paso para saltar a él. Haz clic en un componente para ver detalles.

Qué hace

Un mapa público y un bot de Telegram que indican a los habaneros qué bloques y circuitos tienen corriente. Ingiere el canal de Telegram de la empresa eléctrica y su grupo de comentarios, extrae eventos de apagón con reglas más enriquecimiento con LLM, y publica un sitio estático accesible desde Cuba con analítica, páginas por circuito y un asistente conversacional.

El problema

La información de apagones en La Habana está dispersa en publicaciones y comentarios de texto libre en un canal de Telegram. Los vecinos no tienen una vista estructurada y consultable del estado actual, las horas sin corriente por circuito ni el histórico.

Qué construí

  • Pipeline completo desde publicaciones crudas de Telegram hasta un sitio estático publicado, ejecutado por GitHub Actions y desplegado en Cloudflare Pages sin servidor encendido.
  • Un Worker guardián independiente detecta datos publicados viejos, cancela corridas zombi de CI, relanza la ingesta y abre un issue de alerta tras un atasco real de 18 horas.
  • Cliente LLM multi-proveedor con orden de preferencia, respaldo y control de cuota diaria por proveedor; el LLM enriquece texto libre pero nunca reemplaza las reglas deterministas.
  • El asistente de Telegram usa tool-calling sobre datos precalculados y un RAG con pgvector de respaldo, de modo que cada cifra sale de herramientas deterministas y no de aritmética del modelo.
  • Suite de regresión extensa (unas 37 módulos de prueba) que bloquea cada publicación: si una prueba falla, no se despliega en lugar de publicar un estado erróneo.
  • Reportes vecinales con privacidad: las IP se hashean con sal, se limitan por IP y la ubicación se acota a La Habana.

Decisiones clave y por qué

01

Cloudflare como hosting en vez de Vercel/AWS

Cloudflare normalmente es accesible desde IPs cubanas, y los usuarios están en Cuba. Los tiles y datos se sirven desde el mismo origen para no depender de terceros bloqueados.

02

Ingesta por pull con cron de CI, no una conexión persistente

Telethon trae los mensajes desde el último id guardado en cada corrida, evitando un servidor pago siempre encendido. Hace falta una cuenta de usuario MTProto porque un bot no puede leer el canal.

03

Un Worker de Cloudflare como único disparador y guardián

El scheduler de GitHub llegaba tarde de media y los disparos solapados se cancelaban entre sí. Un componente fuera de GitHub dispara workflow_dispatch y vigila la frescura, así un atasco de GitHub no puede ocultarse.

04

Reglas primero, LLM como enriquecimiento best-effort

Los partes oficiales son muy regulares, así que las reglas regex resuelven la mayoría de forma barata y predecible. Los pasos LLM no bloquean y el estado envejece a desconocido sin noticias, evitando respuestas erróneas con falsa confianza.

05

Embeddings en pgvector de Supabase en vez de un JSON estático

El índice vectorial era demasiado grande para servirlo como archivo estático. Mantenerlo en la base evita que los vectores salgan del servidor; el worker envía la consulta y recibe solo los k fragmentos más relevantes, con embeddings Matryoshka de 1024 dimensiones para respetar los límites de ivfflat.

Stack tecnológico

Lenguajes
Python 3.12JavaScript
Frontend
Leaflet + GeoJSON
Nube
Cloudflare PagesCloudflare Workers
Datos
Supabase (PostgreSQL)pgvector
Mensajería
Telethon (MTProto)Telegram Bot API
IA
NaN Builders / NVIDIA NIM / Cloudflare Workers AIWhisper transcription
DevOps
GitHub Actions
Pruebas
unittest regression suite