Files
cbc2027/ARCHITECTURE.md

15 KiB

Arquitectura CBCFacil v9

Resumen Ejecutivo

CBCFacil es un servicio de IA modular para procesamiento de documentos (audio, PDF, texto) con integracion a Nextcloud. Este documento describe la arquitectura actual, patrones de diseno utilizados y guia de extension del sistema.

Evucion Arquitectonica

Problema Original (v7)

El proyecto sufria de un archivo monolitico de 3167 lineas (main.py) que contenia todas las responsabilidades en un solo archivo.

Solucion Actual (v9)

Arquitectura modular con separacion clara de responsabilidades en capas independientes.

                              FLUJO DE DATOS
                              =============

  1. MONITOREO              2. DESCARGA            3. PROCESAMIENTO
  +---------------+         +---------------+       +---------------+
  |   Nextcloud   |-------->|  Downloads/   |------>|  Processors   |
  |   (WebDAV)    |         |   Local       |       |  (Audio/PDF)  |
  +---------------+         +---------------+       +---------------+
         |                                                  |
         v                                                  v
  +---------------+                                +---------------+
  |   WebDAV      |                                |   AI Services |
  |   Service     |                                |   (Claude/    |
  +---------------+                                |    Gemini)    |
                                                     +---------------+
                                                             |
                                                             v
  4. GENERACION            5. REGISTRO            6. NOTIFICACION
  +---------------+         +---------------+       +---------------+
  |   Document    |-------->|   Processed   |------>|   Telegram    |
  |   Generators  |         |   Registry    |       |   Service     |
  +---------------+         +---------------+       +---------------+
         |                                                  |
         v                                                  v
  +---------------+                                +---------------+
  |   Nextcloud   |                                |   Dashboard   |
  |   (Upload)    |                                |   (Flask)     |
  +---------------+                                +---------------+

Estructura de Directorios

cbcfacil/
├── main.py                      # Orquestador principal (149 lineas)
├── run.py                       # Script de ejecucion alternativo
├── config/                      # Configuracion centralizada
│   ├── __init__.py              # Exports: settings, validate_environment
│   ├── settings.py              # Configuracion desde variables de entorno
│   └── validators.py            # Validadores de configuracion
├── core/                        # Nucleo compartido
│   ├── __init__.py              # Exports: excepciones, Result
│   ├── exceptions.py            # Excepciones personalizadas
│   ├── result.py                # Patron Result/Error handling
│   └── base_service.py          # Clase base BaseService
├── services/                    # Servicios externos
│   ├── __init__.py              # Exports de servicios
│   ├── webdav_service.py        # WebDAV/Nextcloud operaciones
│   ├── vram_manager.py          # GPU memory management
│   ├── telegram_service.py      # Telegram notificaciones
│   ├── metrics_collector.py     # Metricas y estadisticas
│   ├── ai_service.py            # Servicio AI unificado
│   └── ai/                      # AI Providers
│       ├── __init__.py
│       ├── base_provider.py     # Interfaz BaseProvider
│       ├── claude_provider.py   # Claude (Z.ai) implementation
│       ├── gemini_provider.py   # Gemini API/CLI implementation
│       └── provider_factory.py  # Factory para proveedores
├── processors/                  # Procesadores de archivos
│   ├── __init__.py              # Exports de procesadores
│   ├── base_processor.py        # Clase base FileProcessor
│   ├── audio_processor.py       # Whisper transcription
│   ├── pdf_processor.py         # PDF OCR processing
│   └── text_processor.py        # Text summarization
├── document/                    # Generacion de documentos
│   ├── __init__.py
│   └── generators.py            # DOCX/PDF/Markdown generation
├── storage/                     # Persistencia y cache
│   ├── __init__.py
│   └── processed_registry.py    # Registro de archivos procesados
├── api/                         # API REST
│   ├── __init__.py
│   └── routes.py                # Flask routes y endpoints
├── tests/                       # Tests unitarios e integracion
│   ├── conftest.py              # Fixtures pytest
│   ├── test_config.py           # Tests de configuracion
│   ├── test_storage.py          # Tests de almacenamiento
│   ├── test_webdav.py           # Tests de WebDAV
│   ├── test_processors.py       # Tests de procesadores
│   ├── test_ai_providers.py     # Tests de AI providers
│   ├── test_vram_manager.py     # Tests de VRAM manager
│   └── test_main_integration.py # Tests de integracion main
├── docs/                        # Documentacion
│   ├── archive/                 # Documentacion historica
│   ├── SETUP.md                 # Guia de configuracion
│   ├── TESTING.md               # Guia de testing
│   └── DEPLOYMENT.md            # Guia de despliegue
├── requirements.txt             # Dependencias produccion
├── requirements-dev.txt         # Dependencias desarrollo
├── .env.example                 # Template de configuracion
├── .env.secrets                 # Configuracion local (no versionar)
└── Dockerfile                   # Container Docker

Componentes Principales

1. Servicios (services/)

WebDAVService

Archivo: services/webdav_service.py

Responsabilidades:

  • Conexion y operaciones con Nextcloud via WebDAV
  • Download/upload de archivos
  • Listado y creacion de directorios remotos
  • Manejo de errores con reintentos configurables
class WebDAVService:
    def initialize(self) -> None: ...
    def list(self, remote_path: str) -> List[str]: ...
    def download(self, remote_path: str, local_path: Path) -> None: ...
    def upload(self, local_path: Path, remote_path: str) -> None: ...
    def mkdir(self, remote_path: str) -> None: ...

VRAMManager

Archivo: services/vram_manager.py

Responsabilidades:

  • Gestion de memoria GPU
  • Carga/descarga de modelos (Whisper, OCR, TrOCR)
  • Limpieza automatica de VRAM ociosa
  • Fallback a CPU cuando GPU no disponible
class VRAMManager:
    def initialize(self) -> None: ...
    def cleanup(self) -> None: ...
    def should_cleanup(self) -> bool: ...
    def lazy_cleanup(self) -> None: ...

TelegramService

Archivo: services/telegram_service.py

Responsabilidades:

  • Envio de notificaciones a Telegram
  • Throttling de errores para evitar spam
  • Notificaciones de inicio/parada del servicio
class TelegramService:
    def configure(self, token: str, chat_id: str) -> None: ...
    def send_message(self, message: str) -> None: ...
    def send_error_notification(self, context: str, error: str) -> None: ...
    def send_start_notification(self) -> None: ...

2. Procesadores (processors/)

AudioProcessor

Archivo: processors/audio_processor.py

Responsabilidades:

  • Transcripcion de audio usando Whisper
  • Modelo: medium (optimizado para espanol)
  • Soporte GPU/CPU automatico
  • Post-procesamiento de texto transcrito

PDFProcessor

Archivo: processors/pdf_processor.py

Responsabilidades:

  • Extraccion de texto de PDFs
  • OCR con EasyOCR + Tesseract + TrOCR en paralelo
  • Correccion de texto con IA
  • Generacion de documentos DOCX

TextProcessor

Archivo: processors/text_processor.py

Responsabilidades:

  • Resumenes usando IA (Claude/Gemini)
  • Clasificacion de contenido
  • Generacion de quizzes opcionales

3. AI Services (services/ai/)

ProviderFactory

Archivo: services/ai/provider_factory.py

Patron Factory para seleccion dinamica de proveedor de IA:

class ProviderFactory:
    def get_provider(self, provider_type: str = "auto") -> BaseProvider: ...

Proveedores disponibles:

  • claude: Claude via Z.ai API
  • gemini: Google Gemini API
  • gemini_cli: Gemini CLI local
  • auto: Seleccion automatica basada en disponibilidad

4. Document Generation (document/)

DocumentGenerator

Archivo: document/generators.py

Responsabilidades:

  • Creacion de documentos DOCX
  • Conversion a PDF
  • Formateo Markdown
  • Plantillas de documentos

5. Storage (storage/)

ProcessedRegistry

Archivo: storage/processed_registry.py

Responsabilidades:

  • Registro persistente de archivos procesados
  • Cache en memoria con TTL
  • File locking para thread-safety
class ProcessedRegistry:
    def initialize(self) -> None: ...
    def load(self) -> Set[str]: ...
    def save(self, file_path: str) -> None: ...
    def is_processed(self, file_path: str) -> bool: ...
    def mark_for_reprocess(self, file_path: str) -> None: ...

6. API (api/)

Flask Routes

Archivo: api/routes.py

Endpoints REST disponibles:

  • GET /api/files - Listado de archivos
  • POST /api/reprocess - Reprocesar archivo
  • POST /api/mark-unprocessed - Resetear estado
  • GET /api/refresh - Sincronizar con Nextcloud
  • GET /health - Health check

Patrones de Diseno Utilizados

1. Repository Pattern

# storage/processed_registry.py
class ProcessedRegistry:
    def save(self, file_path: str) -> None: ...
    def load(self) -> Set[str]: ...
    def is_processed(self, file_path: str) -> bool: ...

2. Factory Pattern

# services/ai/provider_factory.py
class ProviderFactory:
    def get_provider(self, provider_type: str = "auto") -> BaseProvider: ...

3. Strategy Pattern

# services/vram_manager.py
class VRAMManager:
    def cleanup(self) -> None: ...
    def should_cleanup(self) -> bool: ...
    def lazy_cleanup(self) -> None: ...

4. Service Layer Pattern

# services/webdav_service.py
class WebDAVService:
    def list(self, remote_path: str) -> List[str]: ...
    def download(self, remote_path: str, local_path: Path) -> None: ...
    def upload(self, local_path: Path, remote_path: str) -> None: ...

5. Singleton Pattern

Servicios implementados como singletons para compartir estado:

# services/webdav_service.py
webdav_service = WebDAVService()

# services/vram_manager.py
vram_manager = VRAMManager()

6. Result Pattern

# core/result.py
class Result:
    @staticmethod
    def success(value): ...
    @staticmethod
    def failure(error): ...

Decisiones Arquitectonicas (ADR)

ADR-001: Arquitectura Modular

Decision: Separar el monolito en modulos independientes.

Contexto: El archivo main.py de 3167 lineas era dificil de mantener y testar.

Decision: Separar en capas: config/, core/, services/, processors/, document/, storage/, api/.

Consecuencias:

  • Positivo: Codigo mas mantenible y testeable
  • Positivo: Reutilizacion de componentes
  • Negativo: Mayor complejidad inicial

ADR-002: Configuracion Centralizada

Decision: Usar clase Settings con variables de entorno.

Contexto: Credenciales hardcodeadas representan riesgo de seguridad.

Decision: Todas las configuraciones via variables de entorno con .env.secrets.

Consecuencias:

  • Positivo: Seguridad mejorada
  • Positivo: Facil despliegue en diferentes entornos
  • Negativo: Requiere documentacion de variables

ADR-003: GPU-First con CPU Fallback

Decision: Optimizar para GPU pero soportar CPU.

Contexto: No todos los usuarios tienen GPU disponible.

Decision: VRAMManager con lazy loading y cleanup automatico.

Consecuencias:

  • Positivo: Performance optimo en GPU
  • Positivo: Funciona sin GPU
  • Negativo: Complejidad adicional en gestion de memoria

ADR-004: Factory para AI Providers

Decision: Abstraer proveedores de IA detras de interfaz comun.

Contexto: Multiples proveedores (Claude, Gemini) con diferentes APIs.

Decision: BaseProvider con implementaciones concretas y ProviderFactory.

Consecuencias:

  • Positivo: Facilidad para agregar nuevos proveedores
  • Positivo: Fallback entre proveedores
  • Negativo: Sobrecarga de abstraccion

Guia de Extension del Sistema

Agregar Nuevo Procesador

  1. Crear archivo en processors/:
from processors.base_processor import FileProcessor

class NuevoProcessor(FileProcessor):
    def process(self, file_path: str) -> None:
        # Implementar procesamiento
        pass
  1. Registrar en processors/__init__.py:
from processors.nuevo_processor import NuevoProcessor

__all__ = ['NuevoProcessor', ...]
  1. Integrar en main.py:
from processors.nuevo_processor import NuevoProcessor

nuevo_processor = NuevoProcessor()

Agregar Nuevo AI Provider

  1. Crear clase en services/ai/:
from services.ai.base_provider import BaseProvider

class NuevoProvider(BaseProvider):
    def summarize(self, text: str) -> str:
        # Implementar
        pass
  1. Registrar en provider_factory.py:
PROVIDERS = {
    'nuevo': NuevoProvider,
    ...
}
  1. Usar:
provider = factory.get_provider('nuevo')

Agregar Nuevo Servicio

  1. Crear archivo en services/:
from core.base_service import BaseService

class NuevoService(BaseService):
    def initialize(self) -> None:
        pass

nuevo_service = NuevoService()
  1. Inicializar en main.py:
from services.nuevo_service import nuevo_service

nuevo_service.initialize()

Agregar Nuevo Endpoint API

  1. Editar api/routes.py:
@app.route('/api/nuevo', methods=['GET'])
def nuevo_endpoint():
    return {'status': 'ok'}, 200

Configuracion Detallada

Variables de Entorno Principales

Variable Requerido Default Descripcion
NEXTCLOUD_URL Si - URL de Nextcloud WebDAV
NEXTCLOUD_USER Si - Usuario Nextcloud
NEXTCLOUD_PASSWORD Si - Contrasena Nextcloud
ANTHROPIC_AUTH_TOKEN No - Token Claude/Z.ai
GEMINI_API_KEY No - API Key Gemini
TELEGRAM_TOKEN No - Token Bot Telegram
TELEGRAM_CHAT_ID No - Chat ID Telegram
CUDA_VISIBLE_DEVICES No "all" GPU a usar
POLL_INTERVAL No 5 Segundos entre polls
LOG_LEVEL No "INFO" Nivel de logging

Metricas y Benchmarks

Metrica Valor
Lineas main.py 149 (antes 3167)
Modulos independientes 8+
Cobertura tests ~60%+
Tiempo inicio 5-10s
Transcripcion Whisper ~1x tiempo audio (GPU)
OCR PDF 0.5-2s/pagina

Beneficios de la Arquitectura

  1. Mantenibilidad: Cada responsabilidad en su propio modulo
  2. Testabilidad: Servicios independientes y testeables
  3. Escalabilidad: Facil agregar nuevos procesadores/servicios
  4. Reutilizacion: Componentes desacoplados
  5. Legibilidad: Codigo organizado y documentado
  6. Seguridad: Configuracion centralizada sin hardcoding

Licencia

MIT License - Ver LICENSE para detalles.