📄 Análisis técnico completo · Mayo 2026

ECCO — Estación de Captura
y Conocimiento Oficial

Análisis integral del sistema: módulos implementados, mejoras, tareas pendientes, potencial y comparativa con PLAUD Note.

Concejo de Medellín Versión 1.0.0 Python 3.11 · Streamlit · SQLite · Ollama Hardware: GTX 1660 6GB · i7-8700K · 16GB DDR4 Preparado por PINGS DSinf / Antigravity

📊 Resumen Ejecutivo

11
Páginas Streamlit
funcionales
12
Tablas SQLite
+ FTS5 virtual
7
Módulos src/
implementados
35+
Librerías Python
integradas

Sistema operativo

La aplicación arranca correctamente en C:\ECCO con todas las páginas funcionales. El bug crítico SQL (1AND) fue corregido en esta sesión. La BD SQLite está inicializada con 21 concejales y 10 temas predefinidos.

⚠️

Pipeline de IA parcialmente habilitado

La transcripción (Whisper), el análisis LLM (Ollama) y la búsqueda vectorial (ChromaDB) están implementados en código, pero requieren configuración adicional: token HuggingFace para diarización y resolución del conflicto PyTorch 2.3.1 / pysentimiento.

🔄 Flujo de Procesamiento

Cada sesión plenaria atraviesa las siguientes etapas. Verde = completamente implementado · Amarillo = implementado, requiere configuración · Rojo = pendiente de completar.

🎙️
Captura Audio
sounddevice
WASAPI / mic
🔊
Limpieza
DeepFilterNet
normalizer
📝
Transcripción
faster-whisper
large-v3 / int8
👥
Diarización
pyannote 3.1
⚠️ token HF
🤖
Análisis LLM
Ollama
qwen2.5:7b
🔍
Indexación
ChromaDB
FTS5 SQLite
📄
Acta Formal
python-docx
reportlab PDF

🧩 Módulos Implementados y su Utilidad

🎙️ src/audio/

Captura de audio en vivo desde micrófono o bucle WASAPI (Windows), con control en tiempo real (pausa/reanuda/detiene). Incluye normalización de amplitud y reducción de ruido con DeepFilterNet.

  • recorder.py — grabación en hilo separado
  • denoiser.py — filtrado DeepFilterNet
  • normalizer.py — ajuste de nivel dB
  • importer.py — importación de archivo existente

📝 src/transcription/

Pipeline orquestado que toma el audio limpio y produce intervenciones estructuradas: Whisper transcribe, pyannote identifica quién habla, el aligner fusiona ambos resultados y el result_builder genera el JSON final.

  • whisper_engine.py — ASR en GPU int8
  • diarizer.py — identificación de hablantes
  • aligner.py — alineación transcripción+hablante
  • pipeline.py — orquestador asíncrono con progreso

🤖 src/intelligence/

Interfaz con Ollama para análisis profundo: genera resúmenes ejecutivos, extrae temas de agenda, detecta votaciones automáticamente, analiza sentimiento de intervenciones y redacta el borrador del acta.

  • ollama_client.py — HTTP client (chat + embed)
  • summarizer.py — resumen corto y detallado
  • topic_extractor.py — extracción de temas
  • voting_detector.py — detección automática de votos
  • sentiment_analyzer.py — sentimiento en español
  • acta_generator.py — borrador formal del acta

🔍 src/search/

Motor de búsqueda híbrido que combina SQLite FTS5 (palabras clave exactas) con ChromaDB (búsqueda semántica por embeddings). Re-rankea resultados (40% FTS + 60% vectorial) y soporta RAG para responder preguntas sobre legislación.

  • hybrid_search.py — búsqueda combinada
  • fts_engine.py — full-text SQLite
  • vector_store.py — ChromaDB
  • rag_engine.py — pregunta → respuesta con contexto
  • embedder.py — indexación vía nomic-embed-text

📄 src/documents/

Genera documentos formales del Concejo: actas en Word (con estilos Medellín) y PDF, exportaciones de transcripción en TXT/CSV/JSON, e importación de legislación existente con OCR (pytesseract).

  • acta_docx.py — Word con estilos institucionales
  • acta_pdf.py — PDF con reportlab
  • exporter.py — TXT, CSV, JSON
  • ocr_importer.py — extracción de texto de PDFs escaneados

🗄️ src/database/

Capa de persistencia completa: conexión SQLite thread-safe con WAL mode, 12 tablas relacionales, 2 tablas FTS5 virtuales, triggers automáticos y 11 repositorios (uno por entidad de negocio).

  • connection.py — singleton thread-safe, 64MB cache
  • schema.py — DDL completo v1 + seed de temas
  • migrations.py — versionado del schema
  • repositories/ — concejales, sesiones, intervenciones, votaciones, actas, temas, legislación, asistencia, fotos, analítica

⚙️ src/utils/

Utilidades transversales del sistema: detector automático de hardware (GPU/CPU/VRAM), cargador de configuración YAML, logger estructurado rotativo y funciones de tiempo.

  • hardware_detector.py — detecta GPU, ajusta parámetros automáticamente
  • config_loader.py — acceso seguro a config.yaml
  • logger.py — loguru, rotación diaria, archivo de errores
  • time_utils.py — helpers de fecha/hora

📱 pages/ (Interfaz de usuario)

11 páginas Streamlit que cubren todo el ciclo de vida de una sesión plenaria: desde la captura hasta la firma del acta, pasando por búsqueda, estadísticas, gestión de concejales, votaciones y fotos.

  • 02 — Nueva Sesión (grabación en vivo / importar audio)
  • 03 — Sesiones (listado con filtros de estado y tipo)
  • 04 — Transcripción (visor sincronizado con audio)
  • 05 — Actas (generador Word/PDF con preview)
  • 06 — Búsqueda (semántica + FTS5 con filtros)
  • 07 — Concejales (perfiles, estadísticas, CRUD)
  • 08 — Votaciones (registro y detalle por concejal) ✨nuevo
  • 09 — Fotos (galería con carga manual) ✨nuevo
  • 10 — Base Legal (importación PDFs + RAG)
  • 11 — Estadísticas (Plotly: participación, asistencia, temas)

🔧 Mejoras Realizadas en Esta Sesión

  • 🐛

    Bug crítico SQL corregido — unrecognized token: "1AND"

    En analytics_repo.py línea 44, el f-string {'AND ...} producía WHERE 1=1AND. Corregido a {' AND ...'}. Afectaba el Dashboard principal y la página de Estadísticas. Ambas ahora cargan sin errores.

  • Página 08 — Votaciones creada

    Nueva página con KPIs (total, aprobadas, rechazadas, empates), listado de votaciones por sesión con badges visuales de resultado, y expander que muestra el voto individual de cada concejal.

  • Página 09 — Galería fotográfica creada

    Nueva página con explorador de sesiones, grid configurable de 2 a 5 columnas, carga manual de imágenes desde el navegador, timestamps del audio y mensaje amigable cuando no hay fotos.

  • assets/styles.css creado

    CSS global extraído del inline de app.py, ampliado con colores PINGS (#0D2E6E, #1565C0, #42A5F5), 10 badges de estado de sesión, cards de concejal, sidebar con marca y botones primarios personalizados.

  • CLAUDE.md creado en la raíz

    Documentación estructurada del codebase para Claude Code: arquitectura, comandos frecuentes, convenciones de código, notas de hardware, estado de todas las páginas.

  • config.yaml optimizado para GTX 1660

    batch_size_whisper: 8→6 (reduce picos VRAM), cpu_threads: 8→12 (aprovecha todos los hilos del i7-8700K), context_length: 16384→8192 (previene OOM del LLM), timeout_segundos: 300→600 (para sesiones largas en CPU).

  • 🐛

    migrations.py — error en BD nueva corregido

    Al inicializar por primera vez, el código consultaba schema_version antes de que existiera. Corregido con try/except que asume versión 0 si la tabla no existe.

  • 🐛

    scripts/03_inicializar_bd.py — tres errores corregidos

    UTF-8 en Windows (sys.stdout.reconfigure), import alias correcto (get_models as get_modelos_disponibles), nombre de función correcto del hardware detector (detect() → dataclass, no diccionario).

  • Páginas 07 y 10 creadas (sesión anterior)

    07_Concejales.py: grid de 21 perfiles con Ver/Editar. 10_Base_Legal.py: importación de PDFs legislativos con búsqueda RAG en 3 pestañas.

  • Sincronización C:\ECCOe:\PINGS_DSinf\Antigravity\ECCO

    Las dos rutas son directorios separados (no junction). Se sincronizan los 7 archivos modificados/creados a C:\ECCO sin tocar el venv ni la base de datos.

📋 Tareas Pendientes

Tarea Categoría Prioridad Estado Notas
Token HuggingFace para pyannote Configuración 🔴 Crítica Pendiente Sin él la diarización falla. Registrar en huggingface.co, aceptar términos de pyannote/speaker-diarization-3.1 y pegar el token en config.yaml → modelos.pyannote.auth_token.
Resolver conflicto PyTorch / pysentimiento Dependencias 🔴 Crítica Bloqueado pysentimiento requiere torch ≥ 2.4; el proyecto instala torch 2.3.1+cu121 para CUDA 12.1. Solución: instalar pysentimiento sin dependencias (--no-deps) o actualizar a torch 2.4+cu121 si es compatible con faster-whisper.
Verificar 2 concejales placeholder Datos 🟡 Alta Pendiente El seed tiene 19 reales + 2 marcados "Concejal por verificar". Consultar concejomedellin.gov.co y actualizar scripts/02_seed_concejales.py.
Fotos de perfil de concejales Datos 🟡 Alta Pendiente Colocar imágenes en data/fotos/{id_concejal}.jpg. La página 07 ya tiene la lógica de visualización.
Escudo de Medellín local Offline 🟡 Alta Pendiente app.py carga el escudo desde Wikipedia (requiere internet). Para modo 100% offline, descargar el SVG y reemplazar la URL por assets/escudo_medellin.svg.
Probar pipeline completo con audio real Validación 🟡 Alta Pendiente Existe el archivo Sesión Plenaria.MP3 (77 MB) en C:\ECCO. Importarlo como sesión de prueba y ejecutar el pipeline completo.
Configurar secretario(a) general en config.yaml Configuración 🟠 Media Pendiente actas.secretario_general está vacío. Completar con el nombre oficial para que aparezca en las actas generadas.
Tests automatizados Calidad 🟠 Media Pendiente pytest ya está en requirements.txt. Falta crear tests/ con pruebas unitarias para los repositorios y el motor de búsqueda.
Backup automático de la BD Operación 🟠 Media Parcial Config indica backup cada 24h pero el scheduler no está activo. Implementar tarea en background (threading.Timer) o usar Windows Task Scheduler.
Cifrado de la base de datos Seguridad 🟢 Baja Pendiente config.yaml → base_datos.encryption: false. SQLite no cifra nativamente. Evaluar SQLCipher o cifrado a nivel de carpeta (BitLocker en Windows).
Captura fotográfica automática Funcionalidad 🟢 Baja Parcial Config habilitada (captura_auto: true, cada 22 min, resolución 1280×720). Falta integrar cv2.VideoCapture en el pipeline y conectar con fotos_repo.
Análisis de coaliciones (alineación de votaciones) Analítica 🟢 Baja Parcial votaciones_repo.alineacion_votaciones() ya existe. Falta crear la visualización (heatmap de concejales × concejales) en la página de Estadísticas o Votaciones.
Exportar a PDF la página de Estadísticas Funcionalidad 🟢 Baja Pendiente Streamlit no tiene impresión directa de gráficas Plotly. Implementar con plotly.io.write_image + reportlab.

📦 Programas e Instalaciones Pendientes

🔑 HuggingFace CLI

Necesario para descargar pyannote/speaker-diarization-3.1.

pip install huggingface_hub
huggingface-cli login

Luego aceptar los términos de uso del modelo en huggingface.co/pyannote/speaker-diarization-3.1

🔦 Tesseract OCR

Para importar legislación desde PDFs escaneados. La librería Python pytesseract ya está en requirements.txt pero el ejecutable Tesseract debe instalarse por separado.

winget install UB-Mannheim.TesseractOCR
# O descargar desde: github.com/UB-Mannheim/tesseract/wiki

🎬 FFmpeg

Requerido por pydub y potencialmente por faster-whisper para conversión de formatos de audio (MP3 → WAV).

winget install Gyan.FFmpeg
# Verificar:
ffmpeg -version

🤖 Modelos Ollama

Dos modelos necesarios: el LLM para análisis y el modelo de embeddings para búsqueda semántica.

ollama pull qwen2.5:7b
ollama pull nomic-embed-text
# Verificar:
ollama list

🔥 PyTorch CUDA

Debe instalarse con el índice especial de CUDA. Leer el comentario en requirements.txt:

pip install torch==2.3.1+cu121 \
  torchaudio==2.3.1+cu121 \
  --index-url \
  https://download.pytorch.org/whl/cu121

📷 Poppler (pdf2image)

Necesario para convertir páginas PDF a imágenes (usado por pdf2image en el importador de legislación).

winget install oschwartz10612.poppler
# Agregar al PATH: C:\Program Files\poppler\Library\bin

🚀 Potencial del Software — Visión de Futuro

🏛️ Red de Concejos

ECCO puede escalarse a los 125 municipios de Antioquia y a cualquier concejo municipal de Colombia. Un nodo central (ECCO Hub) podría agregar estadísticas departamentales comparando participación, temas y eficiencia legislativa entre municipios.

📊 Observatorio Legislativo

Con datos de múltiples períodos, ECCO puede construir series de tiempo sobre temas prioritarios del Concejo. Dashboards públicos que muestren qué tan frecuentemente se debate educación vs. infraestructura vs. seguridad en los últimos 10 años.

🎙️ Asistente IA para Concejales

Un bot de consulta (RAG sobre toda la legislación + actas) que responda preguntas como "¿Qué acuerdos hay sobre ciclovías en Medellín?" o "¿Quién ha hablado más veces sobre presupuesto participativo en los últimos 3 años?"

🔔 Alertas y Monitoreo

Sistema de alertas para periodistas y ciudadanos: notificación automática cuando se aprueba un acuerdo sobre temas de su interés, resumen semanal de sesiones vía email/Telegram, o transcripción en vivo durante las sesiones.

🌐 Portal Ciudadano

Versión pública de solo lectura (sin acceso a grabaciones), donde cualquier ciudadano pueda buscar en las actas, ver estadísticas de asistencia de su concejal y consultar en qué votó cada representante.

📱 App Móvil Companion

Una app ligera (Flutter o React Native) que consuma la API REST de ECCO: ver sesiones en vivo, recibir notificaciones de votaciones, consultar el perfil y estadísticas del concejal de su preferencia.

💡

Diferenciador clave: soberanía del dato

A diferencia de soluciones en la nube, ECCO procesa todo localmente: el audio, la transcripción, el análisis LLM y el almacenamiento nunca salen del equipo del Concejo. Esto elimina preocupaciones de confidencialidad sobre deliberaciones no públicas, reservas presupuestales o negociaciones políticas sensibles.

⚖️ ECCO vs PLAUD Note — Comparativa

PLAUD Note es un dispositivo hardware de grabación y transcripción con app cloud, lanzado en 2024. Se compara con ECCO en el contexto específico del Concejo de Medellín.

Característica
🏛️ ECCO (este proyecto)
📱 PLAUD Note
Modelo de despliegue
✅ 100% local — sin internet requerido para el pipeline
☁️ Cloud — transcripción en servidores de OpenAI/PLAUD
Costo mensual
✅ $0 operativo (hardware del Concejo ya existente)
💳 ~$8–19 USD/mes (plan PLAUD AI + tokens GPT-4)
Privacidad de datos
✅ Total — datos nunca salen del equipo
⚠️ Limitada — audio enviado a servidores externos
Calidad de transcripción
🟡 Alta — Whisper large-v3 en español, optimizado para sesiones
✅ Muy alta — Whisper via API OpenAI (misma tecnología, mayor recurso)
Identificación de hablantes
✅ Hasta 21 hablantes — pyannote 3.1, configurable para los 21 concejales
🟡 2 hablantes — distinción básica "yo / otro"
Análisis LLM / Resumen
✅ Personalizable — prompts adaptados al Concejo de Medellín, actas según Ley 136/1994
✅ ChatGPT-4o — resumen genérico en múltiples idiomas
Generación de actas
✅ Formato oficial — Word + PDF según reglamento Concejo, numeración automatizada
❌ No — solo exporta transcripción como texto plano
Base de datos legislativa (RAG)
✅ Integrado — ChromaDB + FTS5, importación de PDFs, búsqueda semántica sobre acuerdos
❌ No — PLAUD no tiene repositorio legislativo
Estadísticas y analítica
✅ Dashboards Plotly — participación, asistencia, temas, votaciones, ranking de concejales
❌ No — ninguna analítica institucional
Registro de votaciones
✅ Automático + manual — detección por LLM, registro de voto individual por concejal
❌ No — PLAUD no gestiona votaciones
Gestión de concejales
✅ Perfiles completos — partido, comisiones, fotos, historial, voiceprint para diarización
❌ No — sin gestión de participantes
Hardware requerido
✅ PC existente — i7-8700K + GTX 1660 (hardware ya disponible)
💰 Hardware PLAUD — dispositivo físico $169 USD + teléfono
Múltiples sesiones simultáneas
✅ Sí — proceso en background, pipeline asíncrono
❌ No — un dispositivo = una grabación a la vez
Facilidad de uso inicial
🟡 Técnica — requiere setup Python, Ollama, CUDA
✅ Inmediata — app móvil lista en 2 minutos
Personalización
✅ Total — código abierto, adaptable a cualquier necesidad
❌ Ninguna — producto cerrado
Soporte a idioma español (Colombia)
✅ Nativo — modelo configurado en español, prompts en español colombiano
✅ Sí — soporte multilingüe via OpenAI
Cumplimiento Ley 136/1994
✅ Diseñado para ello — quorum, tipos de sesión, formato de actas según la ley
❌ No — herramienta genérica sin contexto jurídico colombiano
🏆

Veredicto: ECCO gana en el contexto institucional

PLAUD es superior en usabilidad inmediata y potencia bruta de transcripción (GPT-4o). Pero ECCO supera a PLAUD en todas las dimensiones que importan para el Concejo de Medellín: privacidad, costo cero operativo, generación de actas legales, gestión de votaciones, analítica institucional, escalabilidad y cumplimiento normativo colombiano. PLAUD es una grabadora inteligente; ECCO es un sistema de gestión legislativa completo.

🗺️ Hoja de Ruta Sugerida

FasePlazo sugeridoEntregables
Fase 1 — Puesta en producción 1–2 semanas Token HuggingFace configurado · PyTorch resuelto · Pipeline probado con la grabación MP3 disponible · 2 concejales placeholder verificados · Escudo local
Fase 2 — Primera sesión real 1 mes Procesar una sesión plenaria real completa (audio → transcripción → acta) · Validar con la secretaría del Concejo · Ajustar prompts LLM para actas
Fase 3 — Analítica y búsqueda 2–3 meses 10+ sesiones procesadas · Dashboards de estadísticas con datos reales · Búsqueda semántica sobre legislación importada · Análisis de coaliciones
Fase 4 — Portal ciudadano 4–6 meses Versión pública de solo lectura · Búsqueda de actas históricas · Estadísticas de asistencia y votaciones públicas
Fase 5 — Expansión 6–12 meses Piloto en otros concejos de Antioquia · API REST · App móvil companion · ECCO Hub departamental