Render Configuration: - render.yaml for declarative deployment - requirements-dashboard.txt (lightweight deps for cloud) - Updated .streamlit/config.toml for production - Updated app.py to auto-detect production vs local data Production Data: - Added data/production/test-07/ with 30 real call analyses - Updated .gitignore to allow data/production/ Documentation: - Added Render.com section to DEPLOYMENT.md with step-by-step guide Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
33 KiB
CXInsights - Deployment Guide
Modelo de Deployment
┌─────────────────────────────────────────────────────────────────────────────┐
│ DEPLOYMENT MODEL │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ CXInsights está diseñado para ejecutarse como LONG-RUNNING BATCH JOBS │
│ en un servidor dedicado (físico o VM), NO como microservicio elástico. │
│ │
│ ✅ Modelo principal: Servidor dedicado con ejecución via tmux/systemd │
│ ⚠️ Modelo secundario: Cloud VM (misma arquitectura, diferente hosting) │
│ 📦 Opcional: Docker (para portabilidad, no para orquestación) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Prerequisitos
Software requerido
| Software | Versión | Propósito |
|---|---|---|
| Python | 3.11+ | Runtime |
| Git | 2.40+ | Control de versiones |
| ffmpeg | 6.0+ | Validación de audio (opcional) |
| tmux | 3.0+ | Sesiones persistentes para batch jobs |
Cuentas y API Keys
| Servicio | URL | Necesario para |
|---|---|---|
| AssemblyAI | https://assemblyai.com | Transcripción STT |
| OpenAI | https://platform.openai.com | Análisis LLM |
| Anthropic | https://console.anthropic.com | Backup LLM (opcional) |
Capacity Planning (Sizing Estático)
Requisitos de Hardware
El sizing es estático para el volumen máximo esperado. No hay auto-scaling.
┌─────────────────────────────────────────────────────────────────────────────┐
│ CAPACITY PLANNING │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ VOLUMEN: 5,000 llamadas / batch │
│ ├─ CPU: 4 cores (transcripción es I/O bound, no CPU bound) │
│ ├─ RAM: 8 GB │
│ ├─ Disco: 50 GB SSD (audio + transcripts + outputs) │
│ └─ Red: 100 Mbps (upload audio a STT API) │
│ │
│ VOLUMEN: 20,000 llamadas / batch │
│ ├─ CPU: 4-8 cores │
│ ├─ RAM: 16 GB │
│ ├─ Disco: 200 GB SSD │
│ └─ Red: 100+ Mbps │
│ │
│ NOTA: El cuello de botella es el rate limit de APIs externas, │
│ no el hardware local. Más cores no acelera el pipeline. │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Estimación de espacio en disco
Por cada 1,000 llamadas (AHT = 7 min):
├─ Audio original: ~2-4 GB (depende de bitrate)
├─ Transcripts raw: ~100 MB
├─ Transcripts compressed: ~40 MB
├─ Features: ~20 MB
├─ Labels (processed): ~50 MB
├─ Outputs finales: ~10 MB
└─ TOTAL: ~2.5-4.5 GB por 1,000 calls
Recomendación:
├─ 5K calls: 50 GB disponibles
└─ 20K calls: 200 GB disponibles
Deployment Estándar (Servidor Dedicado)
1. Preparar servidor
# Ubuntu 22.04 LTS (o similar)
sudo apt update
sudo apt install -y python3.11 python3.11-venv git ffmpeg tmux
2. Clonar repositorio
# Ubicación recomendada: /opt/cxinsights o ~/cxinsights
cd /opt
git clone https://github.com/tu-org/cxinsights.git
cd cxinsights
3. Crear entorno virtual
python3.11 -m venv .venv
source .venv/bin/activate
4. Instalar dependencias
# Instalación base
pip install -e .
# Con PII detection (recomendado)
pip install -e ".[pii]"
# Con herramientas de desarrollo
pip install -e ".[dev]"
5. Configurar variables de entorno
cp .env.example .env
nano .env
Contenido de .env:
# === API KEYS ===
ASSEMBLYAI_API_KEY=your_assemblyai_key_here
OPENAI_API_KEY=sk-your_openai_key_here
ANTHROPIC_API_KEY=sk-ant-your_anthropic_key_here # Opcional
# === THROTTLING (ajustar manualmente según tier y pruebas) ===
# Estos son LÍMITES INTERNOS, no promesas de las APIs
MAX_CONCURRENT_TRANSCRIPTIONS=30 # AssemblyAI: empezar conservador
LLM_REQUESTS_PER_MINUTE=200 # OpenAI: depende de tu tier
LLM_BACKOFF_BASE=2.0 # Segundos base para retry
LLM_BACKOFF_MAX=60.0 # Máximo backoff
LLM_MAX_RETRIES=5
# === LOGGING ===
LOG_LEVEL=INFO
LOG_DIR=./data/logs
# === RUTAS ===
DATA_DIR=./data
CONFIG_DIR=./config
6. Crear estructura de datos persistente
# Script de inicialización (ejecutar una sola vez)
./scripts/init_data_structure.sh
O manualmente:
mkdir -p data/{raw/audio,raw/metadata}
mkdir -p data/{transcripts/raw,transcripts/compressed}
mkdir -p data/features
mkdir -p data/processed
mkdir -p data/outputs
mkdir -p data/logs
mkdir -p data/.checkpoints
7. Verificar instalación
python -m cxinsights.pipeline.cli --help
Configuración de Throttling
Concepto clave
Los parámetros MAX_CONCURRENT_* y *_REQUESTS_PER_MINUTE son throttles internos que tú ajustas manualmente según:
- Tu tier en las APIs (OpenAI, AssemblyAI)
- Pruebas reales de comportamiento
- Errores 429 observados
┌─────────────────────────────────────────────────────────────────────────────┐
│ THROTTLING CONFIGURATION │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ASSEMBLYAI: │
│ ├─ Default: 100 concurrent transcriptions (según docs) │
│ ├─ Recomendación inicial: 30 (conservador) │
│ └─ Ajustar según errores observados │
│ │
│ OPENAI: │
│ ├─ Tier 1 (free): 500 RPM → configurar 200 RPM interno │
│ ├─ Tier 2: 5000 RPM → configurar 2000 RPM interno │
│ ├─ Tier 3+: 5000+ RPM → configurar según necesidad │
│ └─ SIEMPRE dejar margen (40-50% del límite real) │
│ │
│ Si ves errores 429: │
│ 1. Reducir *_REQUESTS_PER_MINUTE │
│ 2. El backoff exponencial manejará picos │
│ 3. Loguear y ajustar para siguiente batch │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Ejecución de Batch Jobs
Modelo de ejecución: Long-running batch jobs
CXInsights ejecuta procesos de larga duración (6-24+ horas). Usa tmux o systemd para persistencia.
Opción A: tmux (recomendado para operación manual)
# Crear sesión tmux
tmux new-session -s cxinsights
# Dentro de tmux, ejecutar pipeline
source .venv/bin/activate
python -m cxinsights.pipeline.cli run \
--input ./data/raw/audio/batch_2024_01 \
--batch-id batch_2024_01
# Detach de tmux: Ctrl+B, luego D
# Re-attach: tmux attach -t cxinsights
# Ver logs en otra ventana tmux
# Ctrl+B, luego C (nueva ventana)
tail -f data/logs/pipeline_*.log
Opción B: systemd (recomendado para ejecución programada)
# /etc/systemd/system/cxinsights-batch.service
[Unit]
Description=CXInsights Batch Processing
After=network.target
[Service]
Type=simple
User=cxinsights
WorkingDirectory=/opt/cxinsights
Environment="PATH=/opt/cxinsights/.venv/bin"
ExecStart=/opt/cxinsights/.venv/bin/python -m cxinsights.pipeline.cli run \
--input /opt/cxinsights/data/raw/audio/current_batch \
--batch-id current_batch
Restart=no
StandardOutput=append:/opt/cxinsights/data/logs/systemd.log
StandardError=append:/opt/cxinsights/data/logs/systemd.log
[Install]
WantedBy=multi-user.target
# Activar y ejecutar
sudo systemctl daemon-reload
sudo systemctl start cxinsights-batch
# Ver estado
sudo systemctl status cxinsights-batch
journalctl -u cxinsights-batch -f
Comando básico
python -m cxinsights.pipeline.cli run \
--input ./data/raw/audio/batch_2024_01 \
--batch-id batch_2024_01
Opciones disponibles
python -m cxinsights.pipeline.cli run --help
# Opciones:
# --input PATH Carpeta con archivos de audio [required]
# --output PATH Carpeta de salida [default: ./data]
# --batch-id TEXT Identificador del batch [required]
# --config PATH Archivo de configuración [default: ./config/settings.yaml]
# --stages TEXT Stages a ejecutar (comma-separated) [default: all]
# --skip-transcription Saltar transcripción (usar existentes)
# --skip-inference Saltar inferencia (usar existentes)
# --dry-run Mostrar qué se haría sin ejecutar
# --verbose Logging detallado
Ejecución por stages (útil para debugging)
# Solo transcripción
python -m cxinsights.pipeline.cli run \
--input ./data/raw/audio/batch_01 \
--batch-id batch_01 \
--stages transcription
# Solo features (requiere transcripts)
python -m cxinsights.pipeline.cli run \
--batch-id batch_01 \
--stages features
# Solo inferencia (requiere transcripts + features)
python -m cxinsights.pipeline.cli run \
--batch-id batch_01 \
--stages inference
# Agregación y reportes (requiere labels)
python -m cxinsights.pipeline.cli run \
--batch-id batch_01 \
--stages aggregation,visualization
Resumir desde checkpoint
# Si el pipeline falló o se interrumpió
python -m cxinsights.pipeline.cli resume --batch-id batch_01
# El sistema detecta automáticamente:
# - Transcripciones completadas
# - Features extraídos
# - Labels ya generados
# - Continúa desde donde se quedó
Estimación de costes antes de ejecutar
python -m cxinsights.pipeline.cli estimate --input ./data/raw/audio/batch_01
# Output:
# ┌─────────────────────────────────────────────────┐
# │ COST ESTIMATION (AHT=7min) │
# ├─────────────────────────────────────────────────┤
# │ Files found: 5,234 │
# │ Total duration: ~611 hours │
# │ Avg duration/call: 7.0 min │
# ├─────────────────────────────────────────────────┤
# │ Transcription (STT): $540 - $600 │
# │ Inference (LLM): $2.50 - $3.50 │
# │ TOTAL ESTIMATED: $543 - $604 │
# └─────────────────────────────────────────────────┘
# Proceed? [y/N]:
Política de Logs y Retención
Estructura de logs
data/logs/
├── pipeline_2024_01_15_103000.log # Log principal del batch
├── pipeline_2024_01_15_103000.err # Errores separados
├── transcription_2024_01_15.log # Detalle STT
├── inference_2024_01_15.log # Detalle LLM
└── systemd.log # Si usas systemd
Política de retención
┌─────────────────────────────────────────────────────────────────────────────┐
│ RETENTION POLICY │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ LOGS: │
│ ├─ Pipeline logs: 30 días │
│ ├─ Error logs: 90 días │
│ └─ Rotación: diaria, compresión gzip después de 7 días │
│ │
│ DATOS: │
│ ├─ Audio raw: borrar tras procesamiento exitoso (o retener 30 días) │
│ ├─ Transcripts raw: borrar tras 30 días │
│ ├─ Transcripts compressed: borrar tras procesamiento LLM │
│ ├─ Features: retener mientras existan labels │
│ ├─ Labels (processed): retener indefinidamente (sin PII) │
│ ├─ Outputs (stats, RCA): retener indefinidamente │
│ └─ Checkpoints: borrar tras completar batch │
│ │
│ IMPORTANTE: Los logs NUNCA contienen transcripts completos │
│ Solo: call_id, timestamps, errores, métricas │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Configuración de logrotate (Linux)
# /etc/logrotate.d/cxinsights
/opt/cxinsights/data/logs/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 cxinsights cxinsights
}
Script de limpieza manual
# scripts/cleanup_old_data.sh
#!/bin/bash
# Ejecutar periódicamente (cron semanal)
DATA_DIR="/opt/cxinsights/data"
RETENTION_DAYS=30
echo "Cleaning data older than $RETENTION_DAYS days..."
# Logs antiguos
find "$DATA_DIR/logs" -name "*.log" -mtime +$RETENTION_DAYS -delete
find "$DATA_DIR/logs" -name "*.gz" -mtime +90 -delete
# Transcripts raw antiguos
find "$DATA_DIR/transcripts/raw" -name "*.json" -mtime +$RETENTION_DAYS -delete
# Checkpoints de batches completados (manual review recomendado)
echo "Review and delete completed checkpoints manually:"
ls -la "$DATA_DIR/.checkpoints/"
echo "Cleanup complete."
Dashboard (Visualización)
# Lanzar dashboard
streamlit run src/visualization/dashboard.py -- --batch-id batch_2024_01
# Acceder en: http://localhost:8501
# O si es servidor remoto: http://servidor:8501
Con autenticación (proxy nginx)
Ver TECH_STACK.md sección "Streamlit - Deploy" para configuración de nginx con basic auth.
Estructura de Outputs
Después de ejecutar el pipeline:
data/outputs/batch_2024_01/
├── aggregated_stats.json # Estadísticas consolidadas
├── call_matrix.csv # Todas las llamadas con labels
├── rca_lost_sales.json # Árbol RCA de ventas perdidas
├── rca_poor_cx.json # Árbol RCA de CX deficiente
├── emergent_drivers_review.json # OTHER_EMERGENT para revisión
├── validation_report.json # Resultado de quality gate
├── executive_summary.pdf # Reporte ejecutivo
├── full_analysis.xlsx # Excel con drill-down
└── figures/
├── rca_tree_lost_sales.png
├── rca_tree_poor_cx.png
└── ...
Script de Deployment (deploy.sh)
Script para configuración inicial del entorno persistente.
#!/bin/bash
# deploy.sh - Configuración inicial de entorno persistente
# Ejecutar UNA VEZ al instalar en nuevo servidor
set -e
INSTALL_DIR="${INSTALL_DIR:-/opt/cxinsights}"
PYTHON_VERSION="python3.11"
echo "======================================"
echo "CXInsights - Initial Deployment"
echo "======================================"
echo "Install directory: $INSTALL_DIR"
echo ""
# 1. Verificar Python
if ! command -v $PYTHON_VERSION &> /dev/null; then
echo "ERROR: $PYTHON_VERSION not found"
echo "Install with: sudo apt install python3.11 python3.11-venv"
exit 1
fi
echo "✓ Python: $($PYTHON_VERSION --version)"
# 2. Verificar que estamos en el directorio correcto
if [ ! -f "pyproject.toml" ]; then
echo "ERROR: pyproject.toml not found. Run from repository root."
exit 1
fi
echo "✓ Repository structure verified"
# 3. Crear entorno virtual (si no existe)
if [ ! -d ".venv" ]; then
echo "Creating virtual environment..."
$PYTHON_VERSION -m venv .venv
fi
source .venv/bin/activate
echo "✓ Virtual environment: .venv"
# 4. Instalar dependencias
echo "Installing dependencies..."
pip install -q --upgrade pip
pip install -q -e .
echo "✓ Dependencies installed"
# 5. Configurar .env (si no existe)
if [ ! -f ".env" ]; then
if [ -f ".env.example" ]; then
cp .env.example .env
echo "⚠ Created .env from template - CONFIGURE API KEYS"
else
echo "ERROR: .env.example not found"
exit 1
fi
else
echo "✓ .env exists"
fi
# 6. Crear estructura de datos persistente (idempotente)
echo "Creating data directory structure..."
mkdir -p data/raw/audio
mkdir -p data/raw/metadata
mkdir -p data/transcripts/raw
mkdir -p data/transcripts/compressed
mkdir -p data/features
mkdir -p data/processed
mkdir -p data/outputs
mkdir -p data/logs
mkdir -p data/.checkpoints
# Crear .gitkeep para preservar estructura en git
touch data/raw/audio/.gitkeep
touch data/raw/metadata/.gitkeep
touch data/transcripts/raw/.gitkeep
touch data/transcripts/compressed/.gitkeep
touch data/features/.gitkeep
touch data/processed/.gitkeep
touch data/outputs/.gitkeep
touch data/logs/.gitkeep
echo "✓ Data directories created"
# 7. Verificar API keys en .env
source .env
if [ -z "$ASSEMBLYAI_API_KEY" ] || [ "$ASSEMBLYAI_API_KEY" = "your_assemblyai_key_here" ]; then
echo ""
echo "⚠ WARNING: ASSEMBLYAI_API_KEY not configured in .env"
fi
if [ -z "$OPENAI_API_KEY" ] || [ "$OPENAI_API_KEY" = "sk-your_openai_key_here" ]; then
echo "⚠ WARNING: OPENAI_API_KEY not configured in .env"
fi
# 8. Verificar instalación
echo ""
echo "Verifying installation..."
python -m cxinsights.pipeline.cli --help > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "✓ CLI verification passed"
else
echo "ERROR: CLI verification failed"
exit 1
fi
echo ""
echo "======================================"
echo "Deployment complete!"
echo "======================================"
echo ""
echo "Next steps:"
echo " 1. Configure API keys in .env"
echo " 2. Copy audio files to data/raw/audio/your_batch/"
echo " 3. Start tmux session: tmux new -s cxinsights"
echo " 4. Activate venv: source .venv/bin/activate"
echo " 5. Run pipeline:"
echo " python -m cxinsights.pipeline.cli run \\"
echo " --input ./data/raw/audio/your_batch \\"
echo " --batch-id your_batch"
echo ""
# Uso:
chmod +x deploy.sh
./deploy.sh
Docker (Opcional)
Docker es una opción para portabilidad, no el camino principal de deployment.
┌─────────────────────────────────────────────────────────────────────────────┐
│ DOCKER - DISCLAIMER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Docker es OPCIONAL y se proporciona para: │
│ ├─ Entornos donde no se puede instalar Python directamente │
│ ├─ Reproducibilidad exacta del entorno │
│ └─ Integración con sistemas de CI/CD existentes │
│ │
│ Docker NO es necesario para: │
│ ├─ Ejecución normal en servidor dedicado │
│ ├─ Obtener mejor rendimiento │
│ └─ Escalar horizontalmente (no aplica a este workload) │
│ │
│ El deployment estándar (venv + tmux/systemd) es preferido. │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Dockerfile
FROM python:3.11-slim
WORKDIR /app
# Dependencias del sistema
RUN apt-get update && \
apt-get install -y ffmpeg && \
rm -rf /var/lib/apt/lists/*
# Copiar código
COPY pyproject.toml .
COPY src/ src/
COPY config/ config/
# Instalar dependencias Python
RUN pip install --no-cache-dir -e .
# Volumen para datos persistentes
VOLUME ["/app/data"]
ENTRYPOINT ["python", "-m", "cxinsights.pipeline.cli"]
Uso
# Build
docker build -t cxinsights:latest .
# Run (montar volumen de datos)
docker run -it \
-v /path/to/data:/app/data \
--env-file .env \
cxinsights:latest run \
--input /app/data/raw/audio/batch_01 \
--batch-id batch_01
Cloud VM (Opción Secundaria)
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLOUD VM - DISCLAIMER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Usar Cloud VM (AWS EC2, GCP Compute, Azure VM) cuando: │
│ ├─ No tienes servidor físico disponible │
│ ├─ Necesitas acceso remoto desde múltiples ubicaciones │
│ └─ Quieres delegar mantenimiento de hardware │
│ │
│ La arquitectura es IDÉNTICA al servidor dedicado: │
│ ├─ Mismo sizing estático (no auto-scaling) │
│ ├─ Mismo modelo de ejecución (long-running batch) │
│ ├─ Misma configuración de throttling manual │
│ └─ Solo cambia dónde está el servidor │
│ │
│ COSTE ADICIONAL: $30-100/mes por la VM (según specs) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Setup en Cloud VM
# 1. Crear VM (ejemplo AWS)
# - Ubuntu 22.04 LTS
# - t3.xlarge (4 vCPU, 16 GB RAM) para 20K calls
# - 200 GB gp3 SSD
# - Security group: SSH (22), HTTP opcional (8501 para dashboard)
# 2. Conectar
ssh -i key.pem ubuntu@vm-ip
# 3. Seguir pasos de "Deployment Estándar" arriba
# (idéntico a servidor dedicado)
Troubleshooting
Error: API key inválida
Error: AssemblyAI authentication failed
Solución: Verificar ASSEMBLYAI_API_KEY en .env
Error: Rate limit exceeded (429)
Error: OpenAI rate limit exceeded
Solución:
- Reducir
LLM_REQUESTS_PER_MINUTEen.env - El backoff automático manejará picos temporales
- Revisar tu tier en OpenAI dashboard
Error: Memoria insuficiente
MemoryError: Unable to allocate array
Solución:
- Procesar en batches más pequeños
- Aumentar RAM del servidor
- Usar
--stagespara ejecutar por partes
Error: Transcripción fallida
Error: Transcription failed for call_xxx.mp3
Solución:
- Verificar archivo:
ffprobe call_xxx.mp3 - Verificar que no excede 5 horas (límite AssemblyAI)
- El pipeline continúa con las demás llamadas
Ver logs detallados
# Log principal del pipeline
tail -f data/logs/pipeline_*.log
# Verbose mode
python -m cxinsights.pipeline.cli run ... --verbose
# Si usas systemd
journalctl -u cxinsights-batch -f
Checklist Pre-Ejecución
SERVIDOR:
[ ] Python 3.11+ instalado
[ ] tmux instalado
[ ] Suficiente espacio en disco (ver Capacity Planning)
[ ] Conectividad de red estable
APLICACIÓN:
[ ] Repositorio clonado
[ ] Entorno virtual creado y activado
[ ] Dependencias instaladas (pip install -e .)
[ ] .env configurado con API keys
[ ] Throttling configurado según tu tier
DATOS:
[ ] Archivos de audio en data/raw/audio/batch_id/
[ ] Estimación de costes revisada (estimate command)
[ ] Estructura de directorios creada
EJECUCIÓN:
[ ] Sesión tmux iniciada (o systemd configurado)
[ ] Logs monitoreables
Makefile (Comandos útiles)
.PHONY: install dev test lint run dashboard status logs clean-logs
# Instalación
install:
pip install -e .
install-pii:
pip install -e ".[pii]"
dev:
pip install -e ".[dev]"
# Testing
test:
pytest tests/ -v
test-cov:
pytest tests/ --cov=src --cov-report=html
# Linting
lint:
ruff check src/
mypy src/
format:
ruff format src/
# Ejecución
run:
python -m cxinsights.pipeline.cli run --input $(INPUT) --batch-id $(BATCH)
estimate:
python -m cxinsights.pipeline.cli estimate --input $(INPUT)
resume:
python -m cxinsights.pipeline.cli resume --batch-id $(BATCH)
dashboard:
streamlit run src/visualization/dashboard.py -- --batch-id $(BATCH)
# Monitoreo
status:
@echo "=== Pipeline Status ==="
@ls -la data/.checkpoints/ 2>/dev/null || echo "No active checkpoints"
@echo ""
@echo "=== Recent Logs ==="
@ls -lt data/logs/*.log 2>/dev/null | head -5 || echo "No logs found"
logs:
tail -f data/logs/pipeline_*.log
# Limpieza (CUIDADO: no borrar datos de producción)
clean-logs:
find data/logs -name "*.log" -mtime +30 -delete
find data/logs -name "*.gz" -mtime +90 -delete
clean-checkpoints:
@echo "Review before deleting:"
@ls -la data/.checkpoints/
@read -p "Delete all checkpoints? [y/N] " confirm && [ "$$confirm" = "y" ] && rm -rf data/.checkpoints/*
Uso:
make install
make run INPUT=./data/raw/audio/batch_01 BATCH=batch_01
make logs
make status
make dashboard BATCH=batch_01
Render.com (Dashboard Cloud)
Para publicar el dashboard en una URL publica usando Render.com.
Prerrequisitos
- Cuenta en Render.com (plan Free disponible)
- Repositorio Git subido (ej:
https://git.beyondcx.org/susana/BeyondCX_Insights.git) - Datos de produccion en
data/production/(ya incluido)
Paso 1: Crear cuenta en Render
- Ve a https://render.com
- Click en Get Started for Free
- Registrate con GitHub, GitLab, o email
Paso 2: Conectar repositorio Git
- En el Dashboard de Render, click New + > Web Service
- Selecciona Build and deploy from a Git repository
- Click Next
Configurar acceso al repositorio:
- Repositorio publico: Pega la URL directamente
- Repositorio privado:
- Click Connect account para GitHub/GitLab
- O usa Public Git repository con URL
Para git.beyondcx.org:
- URL:
https://git.beyondcx.org/susana/BeyondCX_Insights.git - Render pedira credenciales si es privado
Paso 3: Configurar el servicio
Completa los campos:
| Campo | Valor |
|---|---|
| Name | cxinsights-dashboard |
| Region | Frankfurt (EU Central) |
| Branch | master |
| Runtime | Python 3 |
| Build Command | pip install -r requirements-dashboard.txt |
| Start Command | streamlit run dashboard/app.py --server.port $PORT --server.address 0.0.0.0 --server.headless true |
Plan:
- Free: Para demos y pruebas (se apaga tras 15 min inactividad)
- Starter ($7/mes): Para produccion (siempre activo)
Paso 4: Variables de entorno
Click en Advanced y añade:
| Key | Value |
|---|---|
PYTHON_VERSION |
3.11.0 |
RENDER |
true |
STREAMLIT_SERVER_HEADLESS |
true |
STREAMLIT_BROWSER_GATHER_USAGE_STATS |
false |
Paso 5: Deploy
- Click Create Web Service
- Render clonara el repo y ejecutara el build
- Espera ~3-5 minutos para el primer deploy
Ver logs: En la pagina del servicio, click en Logs
Paso 6: Acceder al dashboard
Una vez desplegado:
- URL publica:
https://cxinsights-dashboard.onrender.com - (El subdominio exacto depende de disponibilidad)
Actualizaciones automaticas
Por defecto, Render hace auto-deploy cuando:
- Push a la branch
master - Merge de PR
Para desactivar: Settings > Build & Deploy > Auto-Deploy > Off
Actualizar datos de produccion
Para cambiar los datos mostrados en el dashboard:
# 1. Copiar nuevo batch a produccion
cp -r data/output/nuevo-batch/* data/production/nuevo-batch/
# 2. Commit y push
git add data/production/
git commit -m "Update production data with nuevo-batch"
git push origin master
# 3. Render auto-deploys (o manual redeploy)
Troubleshooting Render
Error: "No batch data found"
- Verifica que
data/production/tiene datos - Ejecuta
git statuspara confirmar que no esta gitignored
Error: Build failed
- Revisa logs de build en Render
- Verifica
requirements-dashboard.txttiene todas las dependencias
Dashboard muy lento
- Plan Free tiene recursos limitados (512 MB RAM)
- Considera upgrade a Starter ($7/mes)
Se apaga tras inactividad (Free plan)
- Comportamiento normal del plan Free
- El primer request despues de apagarse toma ~30 segundos
- Upgrade a Starter para siempre activo
Costes estimados Render
| Plan | Precio | RAM | Uso recomendado |
|---|---|---|---|
| Free | $0/mes | 512 MB | Demos, pruebas |
| Starter | $7/mes | 512 MB | Produccion ligera |
| Standard | $25/mes | 2 GB | Produccion con SLA |