chore: clean unnecessary markdown files for CV sharing

This commit is contained in:
Renato97
2026-03-31 01:16:12 -03:00
parent dcf887c510
commit 585f4b5839
10 changed files with 0 additions and 6797 deletions

View File

@@ -1,501 +0,0 @@
# 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
```python
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
```python
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
```python
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:
```python
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
```python
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
```python
# 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
```python
# services/ai/provider_factory.py
class ProviderFactory:
def get_provider(self, provider_type: str = "auto") -> BaseProvider: ...
```
### 3. Strategy Pattern
```python
# services/vram_manager.py
class VRAMManager:
def cleanup(self) -> None: ...
def should_cleanup(self) -> bool: ...
def lazy_cleanup(self) -> None: ...
```
### 4. Service Layer Pattern
```python
# 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:
```python
# services/webdav_service.py
webdav_service = WebDAVService()
# services/vram_manager.py
vram_manager = VRAMManager()
```
### 6. Result Pattern
```python
# 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/`:
```python
from processors.base_processor import FileProcessor
class NuevoProcessor(FileProcessor):
def process(self, file_path: str) -> None:
# Implementar procesamiento
pass
```
2. Registrar en `processors/__init__.py`:
```python
from processors.nuevo_processor import NuevoProcessor
__all__ = ['NuevoProcessor', ...]
```
3. Integrar en `main.py`:
```python
from processors.nuevo_processor import NuevoProcessor
nuevo_processor = NuevoProcessor()
```
### Agregar Nuevo AI Provider
1. Crear clase en `services/ai/`:
```python
from services.ai.base_provider import BaseProvider
class NuevoProvider(BaseProvider):
def summarize(self, text: str) -> str:
# Implementar
pass
```
2. Registrar en `provider_factory.py`:
```python
PROVIDERS = {
'nuevo': NuevoProvider,
...
}
```
3. Usar:
```python
provider = factory.get_provider('nuevo')
```
### Agregar Nuevo Servicio
1. Crear archivo en `services/`:
```python
from core.base_service import BaseService
class NuevoService(BaseService):
def initialize(self) -> None:
pass
nuevo_service = NuevoService()
```
2. Inicializar en `main.py`:
```python
from services.nuevo_service import nuevo_service
nuevo_service.initialize()
```
### Agregar Nuevo Endpoint API
1. Editar `api/routes.py`:
```python
@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.

View File

@@ -1,187 +0,0 @@
# 🚀 ROCm Setup para AMD GPU
## ✅ Estado Actual del Sistema
**GPU**: AMD Radeon RX 6800 XT
**ROCm**: 6.0
**PyTorch**: 2.5.0+rocm6.0
## 📋 Comandos Esenciales
### Verificar GPU
```bash
# Información básica de la GPU
lspci | grep -i vga
# Estado en tiempo real de ROCm
rocm-smi
# Información detallada del sistema
rocminfo
```
### Variables de Entorno Críticas
```bash
# CRÍTICO para gfx1030 (RX 6000 series)
export HSA_OVERRIDE_GFX_VERSION=10.3.0
# Agregar al ~/.bashrc o ~/.zshrc
echo 'export HSA_OVERRIDE_GFX_VERSION=10.3.0' >> ~/.bashrc
source ~/.bashrc
```
### Verificar PyTorch con ROCm
```bash
# Test básico de PyTorch
python3 -c "
import torch
print(f'PyTorch: {torch.__version__}')
print(f'ROCm disponible: {torch.cuda.is_available()}')
print(f'Dispositivos: {torch.cuda.device_count()}')
if torch.cuda.is_available():
print(f'GPU: {torch.cuda.get_device_name(0)}')
print(f'Memoria: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.2f} GB')
"
# Benchmark rápido
python3 -c "
import torch, time
a = torch.randn(4096, 4096, device='cuda')
b = torch.randn(4096, 4096, device='cuda')
start = time.time()
c = torch.matmul(a, b)
torch.cuda.synchronize()
print(f'GPU time: {time.time() - start:.4f}s')
"
```
## 🧪 Script de Stress Test
### Ejecutar Stress Test (2 minutos)
```bash
python3 /home/ren/gpu/rocm_stress_test.py
```
## 🔧 Troubleshooting
### Si ROCm no detecta la GPU:
```bash
# Verificar módulos del kernel
lsmod | grep amdgpu
lsmod | grep kfd
# Recargar módulos
sudo modprobe amdgpu
sudo modprobe kfd
# Verificar logs
dmesg | grep amdgpu
```
### Si PyTorch no encuentra ROCm:
```bash
# Reinstalar PyTorch con ROCm
pip uninstall torch torchvision torchaudio
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.0
```
### Si hay errores de memoria:
```bash
# Limpiar cache de GPU
python3 -c "import torch; torch.cuda.empty_cache()"
# Verificar uso de memoria
rocm-smi --meminfo
```
## 📊 Monitoreo Continuo
### Terminal 1 - Monitor en tiempo real
```bash
watch -n 1 rocm-smi
```
### Terminal 2 - Información detallada
```bash
rocm-smi --showtemp --showmeminfo vram --showmeminfo all
```
## 💡 Ejemplos de Uso
### Cargar modelo en GPU
```python
import torch
from transformers import AutoModel
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"Usando dispositivo: {device}")
model = AutoModel.from_pretrained("bert-base-uncased")
model = model.to(device)
# Los tensores ahora se procesarán en la GPU
inputs = torch.tensor([1, 2, 3]).to(device)
```
### Entrenamiento en GPU
```python
import torch
import torch.nn as nn
device = torch.device("cuda")
model = tu_modelo().to(device)
criterion = nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.Adam(model.parameters())
for epoch in range(epochs):
for batch in dataloader:
inputs, labels = batch
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
```
## 🎯 Optimizaciones
### Para mejor rendimiento:
```python
# Usar mixed precision (más rápido en RDNA2)
from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()
with autocast():
output = model(inputs)
loss = criterion(output, targets)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
```
## 📈 Comandos Útiles
```bash
# Ver versión de ROCm
rocm-smi --version
# Verificar HSA
rocminfo
# Test de compatibilidad
python3 /opt/rocm/bin/rocprofiler-compute-test.py
# Verificar BLAS
python3 -c "import torch; print(torch.backends.mps.is_available())" # False en AMD
```
## ⚡ Performance Tips
1. **Siempre mueve datos a GPU**: `.to(device)`
2. **Usa batch sizes grandes**: Aprovecha los 16GB de VRAM
3. **Mixed precision**: Acelera el entrenamiento 1.5-2x
4. **DataLoader con num_workers**: Carga datos en paralelo
5. **torch.cuda.synchronize()**: Para benchmarks precisos

View File

@@ -1,418 +0,0 @@
# Guia de Despliegue - CBCFacil
Esta guia describe las opciones y procedimientos para desplegar CBCFacil en diferentes entornos.
## Opciones de Despliegue
| Metodo | Complejidad | Recomendado para |
|--------|-------------|------------------|
| Docker Compose | Baja | Desarrollo, Produccion ligera |
| Docker Standalone | Media | Produccion con orquestacion |
| Virtual Environment | Baja | Desarrollo local |
| Kubernetes | Alta | Produccion a escala |
## Despliegue con Docker Compose
### Prerrequisitos
- Docker 24.0+
- Docker Compose 2.20+
- NVIDIA Container Toolkit (para GPU)
### Configuracion
1. Crear archivo de configuracion:
```bash
cp .env.example .env.production
nano .env.production
```
2. Configurar variables sensibles:
```bash
# .env.production
NEXTCLOUD_URL=https://nextcloud.example.com/remote.php/webdav
NEXTCLOUD_USER=tu_usuario
NEXTCLOUD_PASSWORD=tu_contrasena_segura
ANTHROPIC_AUTH_TOKEN=sk-ant-...
GEMINI_API_KEY=AIza...
TELEGRAM_TOKEN=bot_token
TELEGRAM_CHAT_ID=chat_id
CUDA_VISIBLE_DEVICES=all
LOG_LEVEL=INFO
```
3. Verificar docker-compose.yml:
```yaml
# docker-compose.yml
version: '3.8'
services:
cbcfacil:
build: .
container_name: cbcfacil
restart: unless-stopped
ports:
- "5000:5000"
volumes:
- ./downloads:/app/downloads
- ./resumenes_docx:/app/resumenes_docx
- ./logs:/app/logs
- ./data:/app/data
environment:
- NEXTCLOUD_URL=${NEXTCLOUD_URL}
- NEXTCLOUD_USER=${NEXTCLOUD_USER}
- NEXTCLOUD_PASSWORD=${NEXTCLOUD_PASSWORD}
- ANTHROPIC_AUTH_TOKEN=${ANTHROPIC_AUTH_TOKEN}
- GEMINI_API_KEY=${GEMINI_API_KEY}
- TELEGRAM_TOKEN=${TELEGRAM_TOKEN}
- TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID}
- CUDA_VISIBLE_DEVICES=${CUDA_VISIBLE_DEVICES}
- LOG_LEVEL=${LOG_LEVEL}
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
interval: 30s
timeout: 10s
retries: 3
```
### Despliegue
```bash
# Construir y levantar
docker compose up -d --build
# Ver logs
docker compose logs -f cbcfacil
# Ver estado
docker compose ps
# Reiniciar
docker compose restart cbcfacil
# Detener
docker compose down
```
### Actualizacion
```bash
# Hacer backup de datos
docker cp cbcfacil:/app/data ./backup/data
# Actualizar imagen
docker compose pull
docker compose up -d --build
# Verificar
docker compose logs -f cbcfacil
```
## Despliegue con Docker Standalone
### Construir Imagen
```bash
# Construir imagen
docker build -t cbcfacil:latest .
# Verificar imagen
docker images cbcfacil
```
### Ejecutar Contenedor
```bash
# Con GPU
docker run -d \
--name cbcfacil \
--gpus all \
-p 5000:5000 \
-v $(pwd)/downloads:/app/downloads \
-v $(pwd)/resumenes_docx:/app/resumenes_docx \
-v $(pwd)/logs:/app/logs \
-e NEXTCLOUD_URL=${NEXTCLOUD_URL} \
-e NEXTCLOUD_USER=${NEXTCLOUD_USER} \
-e NEXTCLOUD_PASSWORD=${NEXTCLOUD_PASSWORD} \
-e ANTHROPIC_AUTH_TOKEN=${ANTHROPIC_AUTH_TOKEN} \
-e GEMINI_API_KEY=${GEMINI_API_KEY} \
cbcfacil:latest
# Ver logs
docker logs -f cbcfacil
# Detener
docker stop cbcfacil && docker rm cbcfacil
```
## Despliegue Local (Virtual Environment)
### Prerrequisitos
- Python 3.10+
- NVIDIA drivers (opcional)
### Instalacion
```bash
# Clonar y entrar al directorio
git clone <repo_url>
cd cbcfacil
# Crear entorno virtual
python3 -m venv .venv
source .venv/bin/activate
# Instalar dependencias
pip install -r requirements.txt
# Configurar variables de entorno
cp .env.example .env.production
nano .env.production
# Crear directorios
mkdir -p downloads resumenes_docx logs data
# Ejecutar
python main.py
```
### Como Servicio Systemd
```ini
# /etc/systemd/system/cbcfacil.service
[Unit]
Description=CBCFacil AI Service
After=network.target
[Service]
Type=simple
User=cbcfacil
WorkingDirectory=/opt/cbcfacil
Environment="PATH=/opt/cbcfacil/.venv/bin"
EnvironmentFile=/opt/cbcfacil/.env.production
ExecStart=/opt/cbcfacil/.venv/bin/python main.py
Restart=always
RestartSec=10
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=cbcfacil
[Install]
WantedBy=multi-user.target
```
```bash
# Instalar servicio
sudo cp cbcfacil.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable cbcfacil
sudo systemctl start cbcfacil
# Verificar estado
sudo systemctl status cbcfacil
# Ver logs
journalctl -u cbcfacil -f
```
## Configuracion de Produccion
### Variables de Entorno Criticas
```bash
# Obligatorias
NEXTCLOUD_URL=...
NEXTCLOUD_USER=...
NEXTCLOUD_PASSWORD=...
# Recomendadas para produccion
DEBUG=false
LOG_LEVEL=WARNING
POLL_INTERVAL=10
# GPU
CUDA_VISIBLE_DEVICES=all
```
### Optimizaciones
```bash
# En .env.production
# Reducir polling para menor carga
POLL_INTERVAL=10
# Optimizar memoria GPU
PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:512
# Limitar threads
OMP_NUM_THREADS=4
MKL_NUM_THREADS=4
```
### Seguridad
```bash
# Crear usuario dedicado
sudo useradd -r -s /bin/false cbcfacil
# Asignar permisos
sudo chown -R cbcfacil:cbcfacil /opt/cbcfacil
# Proteger archivo de variables
sudo chmod 600 /opt/cbcfacil/.env.production
```
## Monitoreo
### Health Check
```bash
# Endpoint de salud
curl http://localhost:5000/health
# Respuesta esperada
{"status": "healthy"}
```
### Logging
```bash
# Ver logs en tiempo real
docker logs -f cbcfacil
# O con journalctl
journalctl -u cbcfacil -f
# Logs estructurados en JSON (produccion)
LOG_LEVEL=WARNING
```
### Metricas
El sistema expone metricas via API:
```bash
# Estado del servicio
curl http://localhost:5000/api/status
```
## Respaldo y Recuperacion
### Respaldo de Datos
```bash
# Directorios a respaldar
# - downloads/ (archivos procesados)
# - resumenes_docx/ (documentos generados)
# - data/ (registros y estados)
# - logs/ (logs del sistema)
# Script de backup
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR=/backup/cbcfacil
mkdir -p $BACKUP_DIR
tar -czf $BACKUP_DIR/cbcfacil_$DATE.tar.gz \
/opt/cbcfacil/downloads \
/opt/cbcfacil/resumenes_docx \
/opt/cbcfacil/data
# Limpiar backups antiguos (mantener ultimos 7 dias)
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete
```
### Recuperacion
```bash
# Detener servicio
docker compose down
# Restaurar datos
tar -xzf backup_*.tar.gz -C /opt/cbcfacil/
# Verificar permisos
chown -R cbcfacil:cbcfacil /opt/cbcfacil
# Reiniciar servicio
docker compose up -d
```
## Troubleshooting de Produccion
### Contenedor no Inicia
```bash
# Verificar logs
docker logs cbcfacil
# Verificar configuracion
docker exec -it cbcfacil python -c "from config import settings; print(settings.has_webdav_config)"
```
### Error de Memoria GPU
```bash
# Verificar GPUs disponibles
nvidia-smi
# Liberar memoria
sudo nvidia-smi --gpu-reset
# O limitar GPU
CUDA_VISIBLE_DEVICES=0
```
### WebDAV Connection Failed
```bash
# Verificar conectividad
curl -u $NEXTCLOUD_USER:$NEXTCLOUD_PASSWORD $NEXTCLOUD_URL
# Verificar credenciales
echo "URL: $NEXTCLOUD_URL"
echo "User: $NEXTCLOUD_USER"
```
### High CPU Usage
```bash
# Reducir threads
OMP_NUM_THREADS=2
MKL_NUM_THREADS=2
# Aumentar intervalo de polling
POLL_INTERVAL=15
```
## Checklist de Produccion
- [ ] Variables de entorno configuradas
- [ ] Credenciales seguras (.env.production)
- [ ] Usuario dedicado creado
- [ ] Permisos correctos asignados
- [ ] Logs configurados
- [ ] Health check funcionando
- [ ] Backup automatizado configurado
- [ ] Monitoreo activo
- [ ] SSL/TLS configurado (si aplica)
- [ ] Firewall configurado
## Recursos Adicionales
- `docs/SETUP.md` - Guia de configuracion inicial
- `docs/TESTING.md` - Guia de testing
- `ARCHITECTURE.md` - Documentacion arquitectonica

View File

@@ -1,337 +0,0 @@
# Guia de Configuracion - CBCFacil
Esta guia describe los pasos para configurar el entorno de desarrollo de CBCFacil.
## Requisitos Previos
### Software Requerido
| Componente | Version Minima | Recomendada |
|------------|----------------|-------------|
| Python | 3.10 | 3.11+ |
| Git | 2.0 | Latest |
| NVIDIA Driver | 535+ | 550+ (para CUDA 12.1) |
| Docker | 24.0 | 25.0+ (opcional) |
| Docker Compose | 2.20 | Latest (opcional) |
### Hardware Recomendado
- **CPU**: 4+ nucleos
- **RAM**: 8GB minimum (16GB+ recomendado)
- **GPU**: NVIDIA con 4GB+ VRAM (opcional, soporta CPU)
- **Almacenamiento**: 10GB+ libres
## Instalacion Paso a Paso
### 1. Clonar el Repositorio
```bash
git clone <repo_url>
cd cbcfacil
```
### 2. Crear Entorno Virtual
```bash
# Crear venv
python3 -m venv .venv
# Activar (Linux/macOS)
source .venv/bin/activate
# Activar (Windows)
.venv\Scripts\activate
```
### 3. Instalar Dependencias
```bash
# Actualizar pip
pip install --upgrade pip
# Instalar dependencias de produccion
pip install -r requirements.txt
# Instalar dependencias de desarrollo (opcional)
pip install -r requirements-dev.txt
```
### 4. Configurar Variables de Entorno
```bash
# Copiar template de configuracion
cp .env.example .env.secrets
# Editar con tus credenciales
nano .env.secrets
```
### 5. Estructura de Archivos Necesaria
```bash
# Crear directorios requeridos
mkdir -p downloads resumenes_docx logs
# Verificar estructura
ls -la
```
## Configuracion de Credenciales
### Nextcloud/WebDAV
```bash
# Obligatorio para sincronizacion de archivos
NEXTCLOUD_URL=https://tu-nextcloud.com/remote.php/webdav
NEXTCLOUD_USER=tu_usuario
NEXTCLOUD_PASSWORD=tu_contrasena
```
### AI Providers (Opcional)
```bash
# Claude via Z.ai
ANTHROPIC_AUTH_TOKEN=sk-ant-...
# Google Gemini
GEMINI_API_KEY=AIza...
# Gemini CLI (opcional)
GEMINI_CLI_PATH=/usr/local/bin/gemini
```
### Telegram (Opcional)
```bash
TELEGRAM_TOKEN=bot_token
TELEGRAM_CHAT_ID=chat_id
```
### GPU Configuration (Opcional)
```bash
# Usar GPU especifica
CUDA_VISIBLE_DEVICES=0
# Usar todas las GPUs
CUDA_VISIBLE_DEVICES=all
# Forzar CPU
CUDA_VISIBLE_DEVICES=
```
## Verificacion de Instalacion
### 1. Verificar Python
```bash
python --version
# Debe mostrar Python 3.10+
```
### 2. Verificar Dependencias
```bash
python -c "import torch; print(f'PyTorch: {torch.__version__}')"
python -c "import flask; print(f'Flask: {flask.__version__}')"
python -c "import whisper; print('Whisper instalado correctamente')"
```
### 3. Verificar Configuracion
```bash
python -c "from config import settings; print(f'WebDAV configurado: {settings.has_webdav_config}')"
python -c "from config import settings; print(f'AI configurado: {settings.has_ai_config}')"
```
### 4. Test Rapido
```bash
# Ejecutar tests basicos
pytest tests/test_config.py -v
```
## Configuracion de Desarrollo
### IDE Recomendado
#### VS Code
```json
// .vscode/settings.json
{
"python.defaultInterpreterPath": ".venv/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"editor.formatOnSave": true,
"python.formatting.provider": "black"
}
```
#### PyCharm
1. Open Settings > Project > Python Interpreter
2. Add Interpreter > Existing Environment
3. Select `.venv/bin/python`
### Git Hooks (Opcional)
```bash
# Instalar pre-commit
pip install pre-commit
pre-commit install
# Verificar hooks
pre-commit run --all-files
```
### Formateo de Codigo
```bash
# Instalar formateadores
pip install black isort
# Formatear codigo
black .
isort .
# Verificar estilo
black --check .
isort --check-only .
```
## Ejecucion del Servicio
### Modo Desarrollo
```bash
# Activar entorno virtual
source .venv/bin/activate
# Ejecutar servicio completo
python main.py
# Con logging verbose
LOG_LEVEL=DEBUG python main.py
```
### Comandos CLI Disponibles
```bash
# Transcribir audio
python main.py whisper <archivo_audio> <directorio_output>
# Procesar PDF
python main.py pdf <archivo_pdf> <directorio_output>
```
### Dashboard
El dashboard estara disponible en:
- URL: http://localhost:5000
- API: http://localhost:5000/api/
## Solucion de Problemas Comunes
### Error: "Module not found"
```bash
# Verificar que el venv esta activado
which python
# Debe mostrar path hacia .venv/bin/python
# Reinstalar dependencias
pip install -r requirements.txt
```
### Error: "CUDA out of memory"
```bash
# Reducir uso de GPU
export CUDA_VISIBLE_DEVICES=
# O usar solo una GPU
export CUDA_VISIBLE_DEVICES=0
```
### Error: "WebDAV connection failed"
```bash
# Verificar credenciales
echo $NEXTCLOUD_URL
echo $NEXTCLOUD_USER
# Probar conexion manualmente
curl -u $NEXTCLOUD_USER:$NEXTCLOUD_PASSWORD $NEXTCLOUD_URL
```
### Error: "Telegram token invalid"
```bash
# Verificar token con BotFather
# https://t.me/BotFather
# Verificar variables de entorno
echo $TELEGRAM_TOKEN
echo $TELEGRAM_CHAT_ID
```
### Error: "Whisper model not found"
```bash
# El modelo se descarga automaticamente la primera vez
# Para forzar recarga:
rm -rf ~/.cache/whisper
```
## Configuracion de GPU (Opcional)
### Verificar Instalacion de CUDA
```bash
# Verificar drivers NVIDIA
nvidia-smi
# Verificar CUDA Toolkit
nvcc --version
# Verificar PyTorch CUDA
python -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}')"
```
### Configurar Memoria GPU
```bash
# En .env.secrets
PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:512
```
## Variables de Entorno Completa
| Variable | Requerido | Default | Descripcion |
|----------|-----------|---------|-------------|
| NEXTCLOUD_URL | Si | - | URL WebDAV de Nextcloud |
| 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" | GPUs a usar |
| POLL_INTERVAL | No | 5 | Segundos entre polls |
| LOG_LEVEL | No | "INFO" | Nivel de logging |
| DEBUG | No | false | Modo debug |
| DASHBOARD_PORT | No | 5000 | Puerto del dashboard |
| DASHBOARD_HOST | No | "0.0.0.0" | Host del dashboard |
## Siguientes Pasos
1. Verificar instalacion con tests
2. Configurar integracion con Nextcloud
3. Probar procesamiento de archivos
4. Configurar notificaciones Telegram (opcional)
Ver juga:
- `docs/TESTING.md` - Guia de testing
- `docs/DEPLOYMENT.md` - Guia de despliegue
- `ARCHITECTURE.md` - Documentacion arquitectonica

View File

@@ -1,482 +0,0 @@
# Guia de Testing - CBCFacil
Esta guia describe como ejecutar y escribir tests para CBCFacil.
## Estructura de Tests
```
tests/
├── conftest.py # Fixtures compartidos
├── 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
```
## Instalacion de Dependencias de Test
```bash
# Activar entorno virtual
source .venv/bin/activate
# Instalar dependencias de desarrollo
pip install -r requirements-dev.txt
# Verificar instalacion
pytest --version
```
## Ejecutar Tests
### Todos los Tests
```bash
# Ejecutar todos los tests
pytest tests/
# Con output detallado
pytest tests/ -v
```
### Tests Especificos
```bash
# Tests de configuracion
pytest tests/test_config.py -v
# Tests de almacenamiento
pytest tests/test_storage.py -v
# Tests de WebDAV
pytest tests/test_webdav.py -v
# Tests de procesadores
pytest tests/test_processors.py -v
# Tests de AI providers
pytest tests/test_ai_providers.py -v
# Tests de VRAM manager
pytest tests/test_vram_manager.py -v
# Tests de integracion
pytest tests/test_main_integration.py -v
```
### Tests con Coverage
```bash
# Coverage basico
pytest tests/ --cov=cbcfacil
# Coverage con reporte HTML
pytest tests/ --cov=cbcfacil --cov-report=html
# Coverage con reporte term-missing
pytest tests/ --cov=cbcfacil --cov-report=term-missing
# Coverage por modulo
pytest tests/ --cov=cbcfacil --cov-report=term-missing --cov-report=annotate
```
### Tests en Modo Watch
```bash
# Recargar automaticamente al detectar cambios
pytest-watch tests/
```
### Tests Parallelos
```bash
# Ejecutar tests en paralelo
pytest tests/ -n auto
# Con numero fijo de workers
pytest tests/ -n 4
```
## Escribir Nuevos Tests
### Estructura Basica
```python
# tests/test_ejemplo.py
import pytest
from pathlib import Path
class TestEjemplo:
"""Clase de tests para un modulo"""
def setup_method(self):
"""Setup antes de cada test"""
pass
def teardown_method(self):
"""Cleanup despues de cada test"""
pass
def test_funcion_basica(self):
"""Test de una funcion basica"""
# Arrange
input_value = "test"
# Act
result = mi_funcion(input_value)
# Assert
assert result is not None
assert result == "expected"
```
### Usar Fixtures
```python
# tests/conftest.py
import pytest
from pathlib import Path
@pytest.fixture
def temp_directory(tmp_path):
"""Fixture para directorio temporal"""
dir_path = tmp_path / "test_files"
dir_path.mkdir()
return dir_path
@pytest.fixture
def mock_settings():
"""Fixture con settings de prueba"""
class MockSettings:
NEXTCLOUD_URL = "https://test.example.com"
NEXTCLOUD_USER = "test_user"
NEXTCLOUD_PASSWORD = "test_pass"
return MockSettings()
# En tu test
def test_con_fixture(temp_directory, mock_settings):
"""Test usando fixtures"""
assert temp_directory.exists()
assert mock_settings.NEXTCLOUD_URL == "https://test.example.com"
```
### Tests de Configuracion
```python
# tests/test_config.py
import pytest
from config import settings
class TestSettings:
"""Tests para configuracion"""
def test_has_webdav_config_true(self):
"""Test con WebDAV configurado"""
# Verificar que las properties funcionan
assert hasattr(settings, 'has_webdav_config')
assert hasattr(settings, 'has_ai_config')
def test_processed_files_path(self):
"""Test del path de archivos procesados"""
path = settings.processed_files_path
assert isinstance(path, Path)
assert path.suffix == ".txt"
```
### Tests de WebDAV
```python
# tests/test_webdav.py
import pytest
from unittest.mock import Mock, patch
class TestWebDAVService:
"""Tests para WebDAV Service"""
@pytest.fixture
def webdav_service(self):
"""Crear instancia del servicio"""
from services.webdav_service import webdav_service
return webdav_service
def test_list_remote_path(self, webdav_service):
"""Test de listado de archivos remotos"""
# Mock del cliente WebDAV
with patch('services.webdav_service.WebDAVClient') as mock_client:
mock_instance = Mock()
mock_instance.list.return_value = ['file1.pdf', 'file2.mp3']
mock_client.return_value = mock_instance
# Inicializar servicio
webdav_service.initialize()
# Test
files = webdav_service.list("TestFolder")
assert len(files) == 2
assert "file1.pdf" in files
```
### Tests de Procesadores
```python
# tests/test_processors.py
import pytest
from unittest.mock import Mock, patch
class TestAudioProcessor:
"""Tests para Audio Processor"""
@pytest.fixture
def processor(self):
"""Crear procesador"""
from processors.audio_processor import AudioProcessor
return AudioProcessor()
def test_process_audio_file(self, processor, tmp_path):
"""Test de procesamiento de audio"""
# Crear archivo de prueba
audio_file = tmp_path / "test.mp3"
audio_file.write_bytes(b"fake audio content")
# Mock de Whisper
with patch('processors.audio_processor.whisper') as mock_whisper:
mock_whisper.load_model.return_value.transcribe.return_value = {
"text": "Texto transcrito de prueba"
}
# Ejecutar
result = processor.process(str(audio_file))
# Verificar
assert result is not None
```
### Tests de AI Providers
```python
# tests/test_ai_providers.py
import pytest
from unittest.mock import Mock, patch
class TestClaudeProvider:
"""Tests para Claude Provider"""
def test_summarize_text(self):
"""Test de resumen con Claude"""
from services.ai.claude_provider import ClaudeProvider
provider = ClaudeProvider()
test_text = "Texto largo para resumir..."
# Mock de la llamada API
with patch.object(provider, '_call_api') as mock_call:
mock_call.return_value = "Texto resumido"
result = provider.summarize(test_text)
assert result == "Texto resumido"
mock_call.assert_called_once()
```
### Tests de Integracion
```python
# tests/test_main_integration.py
import pytest
from unittest.mock import patch
class TestMainIntegration:
"""Tests de integracion del main"""
def test_main_loop_no_files(self):
"""Test del loop principal sin archivos nuevos"""
with patch('main.webdav_service') as mock_webdav:
with patch('main.processed_registry') as mock_registry:
mock_webdav.list.return_value = []
mock_registry.is_processed.return_value = True
# El loop no debe procesar nada
# Verificar que no se llama a procesadores
```
## Configuracion de pytest
```ini
# pytest.ini o pyproject.toml
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"-v",
"--tb=short",
"--strict-markers",
]
filterwarnings = [
"ignore::DeprecationWarning",
]
```
## Mejores Practicas
### 1. Nombrado de Tests
```python
# BIEN
def test_webdav_service_list_returns_files():
...
def test_processed_registry_is_processed_true_for_processed_file():
...
# MAL
def test_list():
...
def test_check():
...
```
### 2. Estructura AAA
```python
def test_ejemplo_aaa():
# Arrange
input_data = {"key": "value"}
expected = "result"
# Act
actual = function_under_test(input_data)
# Assert
assert actual == expected
```
### 3. Tests Aislados
```python
# Cada test debe ser independiente
def test_independent():
# No depender de estado de otros tests
# Usar fixtures para setup/cleanup
pass
```
### 4. Evitar TestLego
```python
# BIEN - Test del comportamiento, no la implementacion
def test_registry_returns_true_for_processed_file():
registry = ProcessedRegistry()
registry.save("file.txt")
assert registry.is_processed("file.txt") is True
# MAL - Test de implementacion
def test_registry_uses_set_internally():
# No testar detalles de implementacion
registry = ProcessedRegistry()
assert hasattr(registry, '_processed_files')
```
### 5. Mocks Appropriados
```python
# Usar mocks para dependencias externas
from unittest.mock import Mock, patch, MagicMock
def test_with_mocked_api():
with patch('requests.get') as mock_get:
mock_response = Mock()
mock_response.json.return_value = {"key": "value"}
mock_get.return_value = mock_response
result = my_api_function()
assert result == {"key": "value"}
```
## Coverage Objetivo
| Componente | Coverage Minimo |
|------------|-----------------|
| config/ | 90% |
| core/ | 90% |
| services/ | 70% |
| processors/ | 60% |
| storage/ | 90% |
| api/ | 80% |
## Integracion con CI/CD
```yaml
# .github/workflows/tests.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements-dev.txt
- name: Run tests
run: |
pytest tests/ --cov=cbcfacil --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v3
```
## Troubleshooting
### Tests Fallan por Imports
```bash
# Verificar que el venv esta activado
source .venv/bin/activate
# Reinstalar el paquete en modo desarrollo
pip install -e .
```
### Tests Muy Lentos
```bash
# Ejecutar en paralelo
pytest tests/ -n auto
# O ejecutar solo tests rapidos
pytest tests/ -m "not slow"
```
### Memory Errors
```bash
# Reducir workers
pytest tests/ -n 2
# O ejecutar secuencial
pytest tests/ -n 0
```
## Recursos Adicionales
- [Documentacion de pytest](https://docs.pytest.org/)
- [Documentacion de unittest.mock](https://docs.python.org/3/library/unittest.mock.html)
- [pytest-cov](https://pytest-cov.readthedocs.io/)

View File

@@ -1,207 +0,0 @@
# Pipeline de Generación de Resúmenes Matemáticos (LaTeX -> PDF)
Este documento contiene un script genérico en Python diseñado para integrarse en pipelines de automatización (GitHub Actions, Jenkins, GitLab CI). El script toma un archivo de texto plano, genera un resumen académico con fórmulas matemáticas usando LLMs (MiniMax, GLM, Gemini) y lo compila a PDF preservando la notación LaTeX.
## 1. Requisitos del Sistema
El entorno donde se ejecute este script debe tener instalado:
- **Python 3.8+**
- **Pandoc** (para conversión de documentos)
- **PDFLaTeX** (generalmente parte de TexLive, para renderizar fórmulas)
### Instalación en Debian/Ubuntu (Docker o CI)
```bash
apt-get update && apt-get install -y pandoc texlive-latex-base texlive-fonts-recommended python3-pip
pip install requests
```
## 2. Script Genérico (`math_summary.py`)
Guarda el siguiente código como `math_summary.py`. Este script es agnóstico al proveedor y se configura mediante argumentos o variables de entorno.
```python
#!/usr/bin/env python3
import os
import sys
import argparse
import subprocess
import requests
import json
# Configuración de Modelos
PROVIDERS = {
"minimax": {
"url": "https://api.minimax.io/anthropic/v1/messages",
"model": "MiniMax-M2",
"header_key": "x-api-key",
"version_header": {"anthropic-version": "2023-06-01"},
"env_var": "MINIMAX_API_KEY"
},
"glm": {
"url": "https://api.z.ai/api/anthropic/v1/messages",
"model": "glm-4.7",
"header_key": "x-api-key",
"version_header": {"anthropic-version": "2023-06-01"},
"env_var": "GLM_API_KEY"
}
}
PROMPT_SYSTEM = """
Eres un asistente académico experto en matemáticas y economía.
Tu tarea es resumir el texto proporcionado manteniendo el rigor científico.
REGLAS DE FORMATO (CRÍTICO):
1. La salida debe ser Markdown válido.
2. TODAS las fórmulas matemáticas deben estar en formato LaTeX.
3. Usa bloques $$ ... $$ para ecuaciones centradas importantes.
4. Usa $ ... $ para ecuaciones en línea.
5. NO uses bloques de código (```latex) para las fórmulas, úsalas directamente en el texto para que Pandoc las renderice.
6. Incluye una sección de 'Conceptos Matemáticos' con las fórmulas desglosadas.
"""
def get_api_key(provider):
env_var = PROVIDERS[provider]["env_var"]
key = os.getenv(env_var)
if not key:
print(f"Error: La variable de entorno {env_var} no está definida.")
sys.exit(1)
return key
def call_llm(provider, text, api_key):
print(f"--- Contactando API: {provider.upper()} ---")
config = PROVIDERS[provider]
headers = {
"Content-Type": "application/json",
config["header_key"]: api_key,
}
if "version_header" in config:
headers.update(config["version_header"])
payload = {
"model": config["model"],
"max_tokens": 4096,
"messages": [
{"role": "user", "content": f"{PROMPT_SYSTEM}\n\nTEXTO A RESUMIR:\n{text}"}
]
}
try:
resp = requests.post(config["url"], json=payload, headers=headers, timeout=120)
resp.raise_for_status()
data = resp.json()
# Manejo específico para MiniMax que puede devolver bloques de "thinking"
content = ""
for part in data.get("content", []):
if part.get("type") == "text":
content += part.get("text", "")
# Fallback si no hay tipo explícito (GLM estándar)
if not content and data.get("content"):
if isinstance(data["content"], list):
content = data["content"][0].get("text", "")
return content
except Exception as e:
print(f"Error llamando a {provider}: {e}")
return None
def convert_to_pdf(markdown_content, output_file):
base_name = os.path.splitext(output_file)[0]
md_file = f"{base_name}.md"
with open(md_file, "w", encoding="utf-8") as f:
f.write(markdown_content)
print(f"--- Generando PDF: {output_file} ---")
cmd = [
"pandoc", md_file,
"-o", output_file,
"--pdf-engine=pdflatex",
"-V", "geometry:margin=2.5cm",
"-V", "fontsize=12pt",
"--highlight-style=tango"
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
print("Éxito: PDF generado correctamente.")
return True
else:
print("Error en Pandoc:")
print(result.stderr)
return False
def main():
parser = argparse.ArgumentParser(description="Generador de Resúmenes Matemáticos PDF")
parser.add_argument("input_file", help="Ruta al archivo de texto (.txt) fuente")
parser.add_argument("--provider", choices=["minimax", "glm"], default="glm", help="Proveedor de IA a usar")
parser.add_argument("--output", default="resumen_output.pdf", help="Nombre del archivo PDF de salida")
args = parser.parse_args()
if not os.path.exists(args.input_file):
print(f"Error: No se encuentra el archivo {args.input_file}")
sys.exit(1)
with open(args.input_file, "r", encoding="utf-8") as f:
text_content = f.read()
api_key = get_api_key(args.provider)
summary_md = call_llm(args.provider, text_content, api_key)
if summary_md:
convert_to_pdf(summary_md, args.output)
else:
print("Fallo en la generación del resumen.")
sys.exit(1)
if __name__ == "__main__":
main()
```
## 3. Ejemplo de Uso en Pipeline
### Ejecución Local
```bash
export GLM_API_KEY="tu_api_key_aqui"
python3 math_summary.py entrada.txt --provider glm --output reporte_final.pdf
```
### GitHub Actions (Ejemplo .yaml)
Este paso automatizaría la creación del PDF cada vez que se sube un .txt a la carpeta `docs/`.
```yaml
name: Generar PDF Matemático
on:
push:
paths:
- 'docs/*.txt'
jobs:
build-pdf:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Instalar dependencias
run: |
sudo apt-get update
sudo apt-get install -y pandoc texlive-latex-base texlive-fonts-recommended
pip install requests
- name: Generar Resumen
env:
GLM_API_KEY: ${{ secrets.GLM_API_KEY }}
run: |
python3 math_summary.py docs/archivo.txt --provider glm --output docs/resumen.pdf
- name: Subir Artefacto
uses: actions/upload-artifact@v3
with:
name: PDF-Resumen
path: docs/resumen.pdf
```

View File

@@ -1,221 +0,0 @@
# Prompt para Generar Resúmenes Académicos en LaTeX
## Instrucciones de Uso
1. Transcribir la clase (audio a texto) usando Whisper o similar
2. Tener el material bibliográfico en formato digital (PDF escaneado con OCR o texto)
3. Copiar el prompt de abajo y completar los campos entre `[corchetes]`
---
## Prompt Template
```
Sos un asistente académico experto en [MATERIA]. Tu tarea es crear un resumen extenso y detallado en LaTeX basado en la transcripción de clase y el material bibliográfico que te proporciono.
## Material de entrada
### Transcripción de clase:
[PEGAR TRANSCRIPCIÓN AQUÍ]
### Material bibliográfico de apoyo:
[PEGAR TEXTO DEL LIBRO/APUNTE O INDICAR QUE LO SUBISTE COMO ARCHIVO]
## Requisitos del resumen
### Extensión y profundidad:
- Mínimo 10 páginas
- Cubrir TODOS los temas mencionados en clase
- Expandir cada concepto con definiciones formales del material bibliográfico
- No resumir demasiado: preferir explicaciones completas
### Estructura obligatoria:
1. Portada con título, materia, fecha y tema
2. Índice (table of contents)
3. Introducción contextualizando el tema
4. Desarrollo organizado en secciones y subsecciones
5. Tablas comparativas cuando haya clasificaciones o tipos
6. Diagramas con TikZ cuando haya procesos, flujos o relaciones
7. Cajas destacadas para definiciones, ejemplos y conceptos importantes
8. Fórmulas matemáticas cuando corresponda
9. Glosario de términos técnicos al final
10. Referencias al material bibliográfico
### Formato LaTeX requerido:
```latex
\documentclass[11pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[spanish,provide=*]{babel}
\usepackage{amsmath,amssymb}
\usepackage{geometry}
\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{arrows.meta,positioning,shapes.geometric,calc}
\usepackage{booktabs}
\usepackage{enumitem}
\usepackage{fancyhdr}
\usepackage{titlesec}
\usepackage{tcolorbox}
\usepackage{array}
\usepackage{multirow}
\geometry{margin=2.5cm}
\pagestyle{fancy}
\fancyhf{}
\fancyhead[L]{[MATERIA] - CBC}
\fancyhead[R]{Clase [N]}
\fancyfoot[C]{\thepage}
% Cajas para destacar contenido
\newtcolorbox{definicion}[1][]{
colback=blue!5!white,
colframe=blue!75!black,
fonttitle=\bfseries,
title=#1
}
\newtcolorbox{importante}[1][]{
colback=red!5!white,
colframe=red!75!black,
fonttitle=\bfseries,
title=#1
}
\newtcolorbox{ejemplo}[1][]{
colback=green!5!white,
colframe=green!50!black,
fonttitle=\bfseries,
title=#1
}
```
### Estilo de contenido:
- Usar \textbf{} para términos clave en su primera aparición
- Usar \textit{} para énfasis y palabras en otros idiomas
- Incluir ejemplos concretos mencionados en clase
- Relacionar teoría con casos prácticos
- Mantener el tono académico pero accesible
- Si el profesor hizo énfasis en algo ("esto es importante", "esto entra en el parcial"), destacarlo en caja roja
### Elementos visuales:
- Tablas con booktabs para comparaciones (usar \toprule, \midrule, \bottomrule)
- Diagramas TikZ para flujos, ciclos o relaciones entre conceptos
- Listas itemize/enumerate para secuencias o características
- Fórmulas centradas con equation o align para expresiones matemáticas
## Ejemplo de calidad esperada
Para cada concepto principal:
1. Definición formal (del libro)
2. Explicación en palabras simples (como lo explicó el profesor)
3. Ejemplo concreto
4. Relación con otros conceptos
5. Por qué es importante / para qué sirve
## Output
Generá el archivo .tex completo, listo para compilar con pdflatex (dos pasadas para el índice).
```
---
## Comandos para compilar
```bash
# Compilar (dos veces para índice)
pdflatex resumen_clase_X.tex
pdflatex resumen_clase_X.tex
# Abrir PDF
xdg-open resumen_clase_X.pdf # Linux
open resumen_clase_X.pdf # macOS
```
---
## Pipeline completo
### 1. Transcripción de audio (con Whisper)
```bash
# Instalar whisper
pip install openai-whisper
# Transcribir audio de clase
whisper "clase_X.mp3" --language Spanish --output_format txt
```
### 2. OCR de PDFs escaneados (con marker-pdf)
```bash
# Crear entorno virtual
python -m venv .venv
source .venv/bin/activate
# Instalar marker
pip install marker-pdf
# Procesar PDF (usa GPU si está disponible)
marker_single "libro_capitulo_X.pdf" --output_dir output/
```
### 3. Generar resumen
Usar el prompt de arriba con:
- Claude (Anthropic)
- GPT-4 (OpenAI)
- Gemini (Google)
### 4. Compilar LaTeX
```bash
pdflatex resumen.tex && pdflatex resumen.tex
```
---
## Tips para mejores resultados
1. **Transcripción completa**: No cortar la transcripción, la IA necesita todo el contexto
2. **Material bibliográfico**: Incluir los capítulos específicos, no todo el libro
3. **Ser específico**: Indicar la materia, el nivel (CBC, carrera, posgrado) y el enfoque del profesor
4. **Iterar**: Si el primer resultado es corto, pedir "expandí la sección X con más detalle"
5. **Diagramas**: Si hay un diagrama importante, describirlo y pedir que lo haga en TikZ
6. **Revisar**: La IA puede cometer errores conceptuales, siempre verificar con el material
---
## Materias donde funciona bien
- Economía (micro/macro)
- Física
- Química
- Matemática (álgebra, análisis)
- Biología
- Sociología
- Historia
- Derecho (con adaptaciones)
- Cualquier materia con contenido teórico estructurado
---
## Ejemplo de uso rápido
```
Sos un asistente académico experto en Física. Creá un resumen extenso en LaTeX sobre "Cinemática" basado en esta transcripción de clase del CBC:
[pegar transcripción]
Material de apoyo: Capítulo 2 de Serway "Movimiento en una dimensión":
[pegar texto del capítulo]
Incluí:
- Definiciones de posición, velocidad, aceleración
- Fórmulas del MRU y MRUV
- Diagramas de movimiento con TikZ
- Gráficos posición-tiempo y velocidad-tiempo
- Ejemplos resueltos paso a paso
- Glosario de términos
```

2447
opus.md

File diff suppressed because it is too large Load Diff

799
plus.md
View File

@@ -1,799 +0,0 @@
# 🚀 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.py` y `tests/__init__.py`
- No hay tests unitarios ni de integración implementados
- Arquitectura mencionada en `ARCHITECTURE.md` indica ~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
```python
# 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
```python
# 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
```python
# 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 normales
- `low`: 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
```python
# 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
```python
# 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 completo
- `processor`: Puede procesar archivos
- `viewer`: Solo lectura
- `api`: Acceso solo API (para integraciones)
---
## 🗄️ 5. Base de Datos (SQLite/PostgreSQL)
### Estado Actual
- Solo `processed_files.txt` como registro
- Sin historial de procesamiento
- Sin metadatos de archivos
### Recomendaciones
#### 5.1 Modelos de Base de Datos
```python
# 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
```sql
-- 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.py` básico
- Sin exportación a sistemas externos
- Sin dashboards de monitoreo
### Recomendaciones
#### 6.1 Prometheus Metrics
```python
# 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
```python
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
```python
# 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
```python
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
```python
# api/websocket/
__init__.py
manager.py # ConnectionManager
events.py # Tipos de eventos
handlers.py # Event handlers
```
#### 8.2 Eventos a Implementar
```python
# 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
```python
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
```python
# 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
- `.dockerignore` existe pero no Dockerfile completo
- Sin docker-compose
- Sin multi-stage builds
### Recomendaciones
#### 10.1 Docker Multi-stage
```dockerfile
# 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
```yaml
# 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.py`
- `services/ai/gemini_provider.py`
- `services/ai/claude_provider.py`
**Recomendación**: Crear interfaz unificada con Chain of Responsibility:
```python
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:
```python
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
```python
# 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
```python
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
```python
# 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
```python
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
```python
# 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
```python
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
```python
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
```python
# 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
```python
# 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
```python
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*

1198
todo.md

File diff suppressed because it is too large Load Diff