🚀 Mejoras principales: - Dashboard Flask ahora corre en thread daemon independiente - Integración con python-dotenv para variables de entorno - Configuración de puerto vía DASHBOARD_PORT (default: 5000) - Mejor logging con Thread-ID para debugging 📦 Nuevos archivos: - kubectl: binary de Kubernetes para deployments - plus.md: documentación adicional del proyecto - todo.md: roadmap y tareas pendientes 🔧 Cambios técnicos: - run_dashboard_thread(): ejecuta Flask en thread separado - start_dashboard(): crea y arranca daemon thread - Configuración de reloader desactivado en threaded mode Esto permite que el dashboard corra sin bloquear el loop principal de procesamiento, mejorando la arquitectura del servicio.
20 KiB
20 KiB
🚀 CBCFacil - Mejoras y Extensiones Recomendadas
Documento con recomendaciones para hacer el proyecto más complejo, robusto y profesional.
📋 Resumen Ejecutivo
Después de analizar todo el proyecto, identifiqué las siguientes áreas principales de mejora:
| Área | Prioridad | Complejidad | Estado Actual |
|---|---|---|---|
| Testing | 🔴 Alta | Media | Solo conftest.py existe |
| Frontend Dashboard | 🔴 Alta | Alta | Template básico sin JS |
| Sistema de Colas | 🟡 Media | Alta | Loop síncrono simple |
| Autenticación API | 🔴 Alta | Media | Sin autenticación |
| Base de Datos | 🟡 Media | Media | Solo archivo TXT |
| Métricas/Observabilidad | 🟡 Media | Media | Básico |
| Video Processor | 🟢 Baja | Alta | No existe |
| WebSockets | 🟢 Baja | Media | No existe |
| Internacionalización | 🟢 Baja | Baja | Solo español |
🧪 1. Testing Completo (CRÍTICO)
Estado Actual
- Solo existe
tests/conftest.pyytests/__init__.py - No hay tests unitarios ni de integración implementados
- Arquitectura mencionada en
ARCHITECTURE.mdindica ~60% cobertura (falso)
Recomendaciones
1.1 Tests Unitarios
tests/
├── unit/
│ ├── test_settings.py # Validar configuración
│ ├── test_validators.py # Validar validators.py
│ ├── test_result.py # Patrón Result
│ ├── test_exceptions.py # Excepciones personalizadas
│ ├── test_bloom_filter.py # BloomFilter en registry
│ ├── test_token_bucket.py # Rate limiter
│ └── test_circuit_breaker.py # Circuit breaker
1.2 Tests de Integración
tests/
├── integration/
│ ├── test_webdav_service.py # Mock de Nextcloud
│ ├── test_telegram_service.py # Mock de Telegram API
│ ├── test_ai_providers.py # Mock de APIs AI
│ ├── test_audio_processor.py # Con audio de prueba
│ ├── test_pdf_processor.py # Con PDF de prueba
│ └── test_document_generator.py
1.3 Tests E2E
tests/
├── e2e/
│ ├── test_full_audio_workflow.py
│ ├── test_full_pdf_workflow.py
│ └── test_api_endpoints.py
1.4 Fixtures de Prueba
# tests/fixtures/
# - sample_audio.mp3 (5 segundos de audio en español)
# - sample_pdf.pdf (2 páginas con texto)
# - expected_transcription.txt
# - expected_summary.md
🖥️ 2. Dashboard Frontend Completo
Estado Actual
- Solo existe
templates/con un archivo básico - API REST sin interfaz visual
- Sin JavaScript interactivo
Recomendaciones
2.1 Estructura Frontend
frontend/
├── src/
│ ├── components/
│ │ ├── FileList.js # Lista de archivos
│ │ ├── FileCard.js # Tarjeta individual
│ │ ├── ProcessingStatus.js # Estado en tiempo real
│ │ ├── GPUMonitor.js # Monitor VRAM
│ │ ├── QueueViewer.js # Cola de procesamiento
│ │ └── NotificationBell.js # Notificaciones
│ ├── pages/
│ │ ├── Dashboard.js # Vista principal
│ │ ├── Files.js # Gestión de archivos
│ │ ├── Settings.js # Configuración
│ │ └── Logs.js # Visor de logs
│ └── services/
│ ├── api.js # Cliente API
│ └── websocket.js # Conexión WS
├── public/
│ └── index.html
└── package.json
2.2 Funcionalidades
- Drag & drop para subir archivos
- Preview de PDFs y audio
- Visor de transcripciones lado a lado
- Editor de resúmenes con Markdown preview
- Gráficas de uso de GPU/CPU
- Historial de procesamiento
- Búsqueda en contenido
- Dark mode / Light mode
📬 3. Sistema de Colas (Celery/RQ)
Estado Actual
- Loop infinito síncrono en
main.py - Sin priorización de tareas
- Sin reintentos configurables
- Sin distribución de carga
Recomendaciones
3.1 Implementar Celery
# services/queue/
├── __init__.py
├── celery_app.py # Configuración Celery
├── tasks/
│ ├── __init__.py
│ ├── audio_tasks.py # Tareas de audio
│ ├── pdf_tasks.py # Tareas de PDF
│ └── notification_tasks.py
└── workers/
└── worker_config.py
3.2 Estructura de Tareas
# tasks/audio_tasks.py
from celery import shared_task
@shared_task(bind=True, max_retries=3, default_retry_delay=60)
def process_audio(self, file_path: str, options: dict) -> dict:
"""Procesar audio con reintentos automáticos"""
...
@shared_task
def transcribe_audio(file_path: str) -> str:
"""Transcribir audio con Whisper"""
...
@shared_task
def generate_summary(transcription: str, base_name: str) -> dict:
"""Generar resumen con IA"""
...
3.3 Prioridades de Cola
high: Archivos pequeños (<10MB)default: Archivos normaleslow: Archivos grandes (>100MB)
🔐 4. Autenticación y Autorización
Estado Actual
- API completamente abierta
- Sin manejo de sesiones
- Sin roles de usuario
Recomendaciones
4.1 Implementar JWT
# api/auth/
├── __init__.py
├── jwt_handler.py # Generación/validación JWT
├── middleware.py # Middleware de autenticación
├── decorators.py # @require_auth, @require_admin
└── models.py # User, Role, Permission
4.2 Endpoints de Auth
# api/routes_auth.py
POST /api/auth/login # Login con usuario/password
POST /api/auth/refresh # Refrescar token
POST /api/auth/logout # Invalidar token
GET /api/auth/me # Perfil del usuario
4.3 Roles Sugeridos
admin: Acceso completoprocessor: Puede procesar archivosviewer: Solo lecturaapi: Acceso solo API (para integraciones)
🗄️ 5. Base de Datos (SQLite/PostgreSQL)
Estado Actual
- Solo
processed_files.txtcomo registro - Sin historial de procesamiento
- Sin metadatos de archivos
Recomendaciones
5.1 Modelos de Base de Datos
# storage/models/
├── __init__.py
├── base.py # SQLAlchemy base
├── file.py # Modelo File
├── processing_job.py # Modelo ProcessingJob
├── user.py # Modelo User
└── audit_log.py # Modelo AuditLog
5.2 Esquema Propuesto
-- files
CREATE TABLE files (
id SERIAL PRIMARY KEY,
filename VARCHAR(255) NOT NULL,
original_path TEXT,
file_type VARCHAR(20),
file_size BIGINT,
checksum VARCHAR(64),
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- processing_jobs
CREATE TABLE processing_jobs (
id SERIAL PRIMARY KEY,
file_id INTEGER REFERENCES files(id),
job_type VARCHAR(50),
status VARCHAR(20),
started_at TIMESTAMP,
completed_at TIMESTAMP,
error_message TEXT,
result_path TEXT,
metadata JSONB
);
-- audit_logs
CREATE TABLE audit_logs (
id SERIAL PRIMARY KEY,
user_id INTEGER,
action VARCHAR(50),
resource_type VARCHAR(50),
resource_id INTEGER,
details JSONB,
timestamp TIMESTAMP DEFAULT NOW()
);
📊 6. Métricas y Observabilidad
Estado Actual
services/metrics_collector.pybásico- Sin exportación a sistemas externos
- Sin dashboards de monitoreo
Recomendaciones
6.1 Prometheus Metrics
# services/observability/
├── __init__.py
├── prometheus_exporter.py # Endpoint /metrics
├── metrics.py # Definición de métricas
└── tracing.py # Tracing distribuido
6.2 Métricas a Implementar
from prometheus_client import Counter, Histogram, Gauge
# Contadores
files_processed_total = Counter('files_processed_total', 'Total files processed', ['type', 'status'])
ai_requests_total = Counter('ai_requests_total', 'AI API requests', ['provider', 'operation'])
# Histogramas
processing_duration = Histogram('processing_duration_seconds', 'Processing time', ['type'])
ai_response_time = Histogram('ai_response_time_seconds', 'AI response time', ['provider'])
# Gauges
active_jobs = Gauge('active_jobs', 'Currently processing jobs')
vram_usage = Gauge('vram_usage_bytes', 'GPU memory usage')
queue_size = Gauge('queue_size', 'Jobs in queue', ['priority'])
6.3 Integración
- Grafana dashboard preconfigurado
- Alertas con AlertManager
- Logs estructurados con Loki
- Tracing con Jaeger/Zipkin
🎬 7. Video Processor (NUEVO)
Recomendaciones
7.1 Estructura
# processors/video_processor.py
class VideoProcessor(FileProcessor):
"""Processor for video files"""
def extract_audio(self, video_path: str) -> str:
"""Extraer audio de video con ffmpeg"""
...
def extract_frames(self, video_path: str, interval: int = 60) -> List[str]:
"""Extraer frames cada N segundos para análisis"""
...
def analyze_frames(self, frames: List[str]) -> Dict[str, Any]:
"""Analizar frames con visión AI (Gemini Vision)"""
...
def process(self, file_path: str) -> Dict[str, Any]:
"""Pipeline completo: audio + frames + análisis"""
...
7.2 Extensiones de Video
VIDEO_EXTENSIONS = {".mp4", ".avi", ".mkv", ".mov", ".webm"}
7.3 Funcionalidades
- Transcripción de audio del video
- Extracción de frames clave
- Análisis visual con IA (slides, pizarra)
- Generación de índice por escenas
- Subtítulos automáticos (SRT/VTT)
🔌 8. WebSockets para Tiempo Real
Estado Actual
- Solo API REST
- Sin actualizaciones en tiempo real
- Polling pesado para estado
Recomendaciones
8.1 Implementación
# api/websocket/
├── __init__.py
├── manager.py # ConnectionManager
├── events.py # Tipos de eventos
└── handlers.py # Event handlers
8.2 Eventos a Implementar
# Eventos del servidor -> cliente
{
"type": "file.processing_started",
"data": {"file_id": 1, "filename": "audio.mp3"}
}
{
"type": "file.processing_progress",
"data": {"file_id": 1, "progress": 45, "stage": "transcribing"}
}
{
"type": "file.processing_completed",
"data": {"file_id": 1, "result_path": "/path/to/result.docx"}
}
{
"type": "system.gpu_usage",
"data": {"vram_used": 4.5, "vram_total": 8.0}
}
8.3 Integración con Flask
from flask_socketio import SocketIO, emit
socketio = SocketIO(app, cors_allowed_origins="*")
@socketio.on('connect')
def handle_connect():
emit('connected', {'status': 'ok'})
@socketio.on('subscribe')
def handle_subscribe(data):
join_room(data['file_id'])
🌐 9. API versioning y OpenAPI
Estado Actual
- API sin versionado
- Sin documentación OpenAPI/Swagger
- Endpoints inconsistentes
Recomendaciones
9.1 Versionado de API
/api/v1/files
/api/v1/process
/api/v1/health
/api/v2/files (futura versión)
9.2 OpenAPI Spec
# api/openapi/
├── spec.yaml # Especificación OpenAPI 3.0
└── swagger_ui.py # Swagger UI integration
# Usar flask-restx o flasgger
from flask_restx import Api, Resource, fields
api = Api(app,
version='1.0',
title='CBCFacil API',
description='API para procesamiento de documentos'
)
🐳 10. Containerización Mejorada
Estado Actual
.dockerignoreexiste pero no Dockerfile completo- Sin docker-compose
- Sin multi-stage builds
Recomendaciones
10.1 Docker Multi-stage
# Dockerfile
FROM python:3.11-slim as builder
WORKDIR /app
COPY requirements.txt .
RUN pip wheel --no-cache-dir -w /wheels -r requirements.txt
FROM nvidia/cuda:12.1-runtime-ubuntu22.04 as runtime
# ... instalación optimizada
10.2 Docker Compose
# docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "5000:5000"
environment:
- NVIDIA_VISIBLE_DEVICES=all
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
redis:
image: redis:7-alpine
celery-worker:
build: .
command: celery -A celery_app worker -l info
depends_on:
- redis
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
grafana:
image: grafana/grafana
ports:
- "3000:3000"
🔧 11. Unificación y Refactoring
11.1 AIProvider Unificado
Actualmente existe lógica duplicada entre:
services/ai_service.pyservices/ai/gemini_provider.pyservices/ai/claude_provider.py
Recomendación: Crear interfaz unificada con Chain of Responsibility:
class AIProviderChain:
"""Cadena de proveedores con fallback automático"""
def __init__(self, providers: List[AIProvider]):
self.providers = providers
def generate(self, prompt: str) -> str:
for provider in self.providers:
try:
if provider.is_available():
return provider.generate_text(prompt)
except Exception as e:
logging.warning(f"{provider.name} failed: {e}")
raise AllProvidersFailedError()
11.2 Procesadores Unificados
Crear pipeline unificado:
class ProcessingPipeline:
def __init__(self):
self.steps = []
def add_step(self, processor: FileProcessor):
self.steps.append(processor)
return self
def process(self, file_path: str) -> Dict[str, Any]:
result = {}
for step in self.steps:
if step.can_process(file_path):
result.update(step.process(file_path))
return result
📱 12. Notificaciones Mejoradas
Estado Actual
- Solo Telegram
- Sin templates de mensajes
- Sin notificaciones push
Recomendaciones
12.1 Multi-canal
# services/notifications/
├── __init__.py
├── base_notifier.py # Interface base
├── telegram_notifier.py # Actual optimizado
├── email_notifier.py # Nuevo
├── slack_notifier.py # Nuevo
├── webhook_notifier.py # Para integraciones
└── notification_manager.py # Orquestador
12.2 Templates de Mensaje
TEMPLATES = {
"processing_started": "🎵 Procesando: {filename}\n⏱️ Estimado: {eta}",
"processing_completed": "✅ Completado: {filename}\n📄 Resumen: {summary_url}",
"processing_failed": "❌ Error en {filename}\n🔍 Detalles: {error}",
"daily_summary": "📊 Resumen del día:\n- Procesados: {count}\n- Tiempo total: {time}"
}
🗂️ 13. Sistema de Plugins
Recomendaciones
# plugins/
├── __init__.py
├── base_plugin.py # Interface de plugin
├── plugin_manager.py # Gestor de plugins
└── examples/
├── custom_ocr/ # Plugin OCR personalizado
├── s3_storage/ # Plugin para AWS S3
└── discord_notifier/ # Plugin Discord
Interfaz de Plugin
class BasePlugin(ABC):
"""Base class for plugins"""
@property
@abstractmethod
def name(self) -> str: ...
@property
@abstractmethod
def version(self) -> str: ...
@abstractmethod
def initialize(self, config: dict) -> None: ...
@abstractmethod
def execute(self, context: dict) -> dict: ...
@abstractmethod
def cleanup(self) -> None: ...
📈 14. Mejoras de Rendimiento
14.1 Caching Avanzado
# services/cache/
├── __init__.py
├── cache_manager.py # Gestor de cache
├── redis_cache.py # Cache en Redis
└── file_cache.py # Cache en disco
14.2 Batch Processing
class BatchProcessor:
"""Procesar múltiples archivos en paralelo"""
def process_batch(self, files: List[str], max_workers: int = 4) -> List[dict]:
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {executor.submit(self.process_single, f): f for f in files}
results = []
for future in as_completed(futures):
results.append(future.result())
return results
14.3 Streaming de Archivos Grandes
def stream_process(file_path: str, chunk_size: int = 1024*1024):
"""Procesar archivos grandes en streaming"""
with open(file_path, 'rb') as f:
while chunk := f.read(chunk_size):
yield process_chunk(chunk)
🔒 15. Seguridad Adicional
15.1 Validación de Archivos
# services/security/
├── __init__.py
├── file_validator.py # Validación de archivos
├── malware_scanner.py # Escaneo de malware
└── rate_limiter.py # Rate limiting por IP
15.2 Checks de Seguridad
- Validar tipos MIME reales (no solo extensiones)
- Limitar tamaño máximo de archivo
- Sanitizar nombres de archivo
- Escanear con ClamAV
- Rate limiting por usuario/IP
- Logs de auditoría
📝 16. CLI Mejorado
Estado Actual
- Solo comandos básicos en
main.py
Recomendaciones
# cli/
├── __init__.py
├── main.py # Click/Typer app
├── commands/
│ ├── process.py # cbcfacil process audio.mp3
│ ├── queue.py # cbcfacil queue list/stats
│ ├── config.py # cbcfacil config show/set
│ └── db.py # cbcfacil db migrate/seed
Ejemplo con Typer
import typer
app = typer.Typer()
@app.command()
def process(
file: str,
output_dir: str = ".",
format: str = "docx",
ai_provider: str = "auto"
):
"""Procesar archivo de audio o PDF"""
...
@app.command()
def status():
"""Mostrar estado del servicio"""
...
@app.command()
def queue(action: str):
"""Gestionar cola de procesamiento"""
...
📁 Resumen de Nuevos Archivos/Directorios
cbc/
├── tests/
│ ├── unit/
│ ├── integration/
│ ├── e2e/
│ └── fixtures/
├── frontend/
│ ├── src/
│ └── public/
├── services/
│ ├── queue/
│ ├── cache/
│ ├── notifications/
│ ├── observability/
│ └── security/
├── api/
│ ├── auth/
│ ├── websocket/
│ └── openapi/
├── storage/
│ └── models/
├── processors/
│ └── video_processor.py
├── plugins/
├── cli/
├── docker-compose.yml
├── prometheus.yml
└── grafana/
✅ Checklist de Implementación
Fase 1 - Fundamentos (2-3 semanas)
- Implementar tests unitarios básicos
- Agregar autenticación JWT
- Migrar a base de datos SQLite
Fase 2 - Mejoras Core (3-4 semanas)
- Implementar sistema de colas con Celery
- Agregar WebSockets
- Crear dashboard frontend básico
Fase 3 - Observabilidad (1-2 semanas)
- Prometheus metrics
- Grafana dashboards
- Logging estructurado
Fase 4 - Extensiones (2-3 semanas)
- Video processor
- Multi-canal de notificaciones
- Sistema de plugins
Fase 5 - Producción (2 semanas)
- Docker compose completo
- CI/CD pipeline
- Documentación completa
Documento generado por análisis exhaustivo del proyecto CBCFacil v9