Dashboard Features: - 8 navigation sections: Overview, Outcomes, Poor CX, FCR, Churn, Agent, Call Explorer, Export - Beyond Brand Identity styling (colors #6D84E3, Outfit font) - RCA Sankey diagram (Driver → Outcome → Churn Risk flow) - Correlation heatmaps (driver co-occurrence, driver-outcome) - Outcome Deep Dive (root causes, correlation, duration analysis) - Export functionality (Excel, HTML, JSON) Blueprint Compliance: - FCR: 4 categories (Primera Llamada/Rellamada × Sin/Con Riesgo de Fuga) - Churn: Binary view (Sin Riesgo de Fuga / En Riesgo de Fuga) - Agent: Talento Para Replicar / Oportunidades de Mejora - Fixed FCR rate calculation (only FIRST_CALL counts as success) Technical: - Streamlit + Plotly for interactive visualizations - Light theme configuration (.streamlit/config.toml) - Fixed Plotly colorbar titlefont deprecation Documentation: - Updated PROJECT_CONTEXT.md, TODO.md, CHANGELOG.md - Added 4 new technical decisions (TD-014 to TD-017) - Created TROUBLESHOOTING.md with 10 common issues Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
580 lines
21 KiB
Markdown
580 lines
21 KiB
Markdown
# CXInsights - Stack Tecnológico
|
||
|
||
## Resumen de Decisiones
|
||
|
||
| Componente | Elección | Alternativas Soportadas |
|
||
|------------|----------|-------------------------|
|
||
| **STT (Speech-to-Text)** | AssemblyAI (default) | Whisper, Google STT, AWS Transcribe (via adapter) |
|
||
| **LLM** | OpenAI GPT-4o-mini | Claude 3.5 Sonnet (fallback) |
|
||
| **Data Processing** | pandas + DuckDB | - |
|
||
| **Visualization** | Streamlit (internal dashboard) | - |
|
||
| **PDF Generation** | ReportLab | - |
|
||
| **Config Management** | Pydantic Settings | - |
|
||
| **PII Handling** | Presidio (opcional) + redaction pre-LLM | - |
|
||
|
||
---
|
||
|
||
## 1. Speech-to-Text: Arquitectura con Adapter
|
||
|
||
### Decisión: **AssemblyAI (default)** + alternativas via STT Provider Adapter
|
||
|
||
El sistema usa una **interfaz abstracta `Transcriber`** que permite cambiar de proveedor sin modificar el código del pipeline.
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ STT PROVIDER ADAPTER │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ Interface: Transcriber │
|
||
│ └─ transcribe(audio) → TranscriptContract │
|
||
│ │
|
||
│ Implementations: │
|
||
│ ├─ AssemblyAITranscriber (DEFAULT - mejor calidad español) │
|
||
│ ├─ WhisperTranscriber (local, offline, $0) │
|
||
│ ├─ GoogleSTTTranscriber (alternativa cloud) │
|
||
│ └─ AWSTranscribeTranscriber (alternativa cloud) │
|
||
│ │
|
||
│ Config: STT_PROVIDER=assemblyai|whisper|google|aws │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Comparativa de Proveedores
|
||
|
||
| Criterio | AssemblyAI | Whisper (local) | Google STT | AWS Transcribe |
|
||
|----------|------------|-----------------|------------|----------------|
|
||
| **Calidad español** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ |
|
||
| **Speaker diarization** | ✅ Incluido | ❌ Requiere pyannote | ✅ Incluido | ✅ Incluido |
|
||
| **Coste/minuto** | $0.015 | $0 (GPU local) | $0.016 | $0.015 |
|
||
| **Setup complexity** | Bajo (API key) | Alto (GPU, modelos) | Medio | Medio |
|
||
| **Batch processing** | ✅ Async nativo | Manual | ✅ | ✅ |
|
||
| **Latencia** | ~0.3x realtime | ~1x realtime | ~0.2x realtime | ~0.3x realtime |
|
||
|
||
### Por qué AssemblyAI como Default
|
||
|
||
1. **Mejor modelo para español**: AssemblyAI Best tiene excelente rendimiento en español latinoamericano y castellano
|
||
2. **Speaker diarization incluido**: Crítico para separar agente de cliente sin código adicional
|
||
3. **API simple**: SDK Python bien documentado, async nativo
|
||
4. **Batch processing**: Configurable concurrency, poll por resultados
|
||
5. **Sin infraestructura**: No necesitas GPU ni mantener modelos
|
||
|
||
### Cuándo usar alternativas
|
||
|
||
| Alternativa | Usar cuando... |
|
||
|-------------|----------------|
|
||
| **Whisper local** | Presupuesto $0, tienes GPU (RTX 3080+), datos muy sensibles (offline) |
|
||
| **Google STT** | Ya usas GCP, necesitas latencia mínima |
|
||
| **AWS Transcribe** | Ya usas AWS, integración con S3 |
|
||
|
||
### Estimación de Costes STT (AHT = 7 min)
|
||
|
||
```
|
||
AssemblyAI pricing: $0.015/minuto
|
||
|
||
5,000 llamadas × 7 min = 35,000 min
|
||
├─ Estimación baja (sin retries): $525
|
||
├─ Estimación media: $550
|
||
└─ Estimación alta (+10% retries): $580
|
||
|
||
20,000 llamadas × 7 min = 140,000 min
|
||
├─ Estimación baja: $2,100
|
||
├─ Estimación media: $2,200
|
||
└─ Estimación alta: $2,400
|
||
|
||
RANGO TOTAL STT:
|
||
├─ 5K calls: $525 - $580
|
||
└─ 20K calls: $2,100 - $2,400
|
||
```
|
||
|
||
---
|
||
|
||
## 2. LLM: OpenAI GPT-4o-mini
|
||
|
||
### Decisión: **GPT-4o-mini** (primary) + **Claude 3.5 Sonnet** (fallback)
|
||
|
||
### Comparativa
|
||
|
||
| Criterio | GPT-4o-mini | GPT-4o | Claude 3.5 Sonnet |
|
||
|----------|-------------|--------|-------------------|
|
||
| **Coste input** | $0.15/1M tokens | $2.50/1M tokens | $3.00/1M tokens |
|
||
| **Coste output** | $0.60/1M tokens | $10.00/1M tokens | $15.00/1M tokens |
|
||
| **Calidad español** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||
| **JSON structured** | ✅ Excelente | ✅ Excelente | ✅ Muy bueno |
|
||
| **Context window** | 128K | 128K | 200K |
|
||
| **Rate limits** | Depende del tier | Depende del tier | Depende del tier |
|
||
|
||
### Rate Limits y Throttling
|
||
|
||
**Los rate limits dependen del tier de tu cuenta OpenAI:**
|
||
|
||
| Tier | RPM (requests/min) | TPM (tokens/min) |
|
||
|------|-------------------|------------------|
|
||
| Tier 1 (free) | 500 | 200K |
|
||
| Tier 2 | 5,000 | 2M |
|
||
| Tier 3 | 5,000 | 4M |
|
||
| Tier 4+ | 10,000 | 10M |
|
||
|
||
**Requisitos obligatorios en el código:**
|
||
- Implementar throttling con tasa configurable (`LLM_REQUESTS_PER_MINUTE`)
|
||
- Exponential backoff en errores 429 (rate limit exceeded)
|
||
- Retry con jitter para evitar thundering herd
|
||
- Logging de rate limit warnings
|
||
|
||
```python
|
||
# Configuración recomendada (conservadora)
|
||
LLM_REQUESTS_PER_MINUTE=300 # Empezar bajo, escalar según tier
|
||
LLM_BACKOFF_BASE=2.0 # Segundos base para backoff
|
||
LLM_BACKOFF_MAX=60.0 # Máximo backoff
|
||
LLM_MAX_RETRIES=5
|
||
```
|
||
|
||
### Estimación de Costes LLM por Llamada
|
||
|
||
**IMPORTANTE**: Estos cálculos asumen **compresión previa del transcript** (Module 2).
|
||
|
||
#### Escenario A: Con compresión (RECOMENDADO)
|
||
|
||
```
|
||
Transcript comprimido: ~1,200-1,800 tokens input
|
||
Prompt template: ~400-600 tokens
|
||
Output esperado: ~250-400 tokens
|
||
|
||
Total por llamada (comprimido):
|
||
├─ Input: ~2,000 tokens × $0.15/1M = $0.0003
|
||
├─ Output: ~350 tokens × $0.60/1M = $0.0002
|
||
└─ Total: $0.0004 - $0.0006 por llamada
|
||
|
||
RANGO (5K calls): $2 - $3
|
||
RANGO (20K calls): $8 - $12
|
||
```
|
||
|
||
#### Escenario B: Sin compresión (full transcript)
|
||
|
||
```
|
||
Transcript completo: ~4,000-8,000 tokens input (x3-x6)
|
||
Prompt template: ~400-600 tokens
|
||
Output esperado: ~250-400 tokens
|
||
|
||
Total por llamada (full transcript):
|
||
├─ Input: ~6,000 tokens × $0.15/1M = $0.0009
|
||
├─ Output: ~350 tokens × $0.60/1M = $0.0002
|
||
└─ Total: $0.0010 - $0.0020 por llamada
|
||
|
||
RANGO (5K calls): $5 - $10
|
||
RANGO (20K calls): $20 - $40
|
||
|
||
⚠️ RECOMENDACIÓN: Siempre usar compresión para reducir costes 3-6x
|
||
```
|
||
|
||
### Por qué GPT-4o-mini
|
||
|
||
1. **Coste-efectividad**: 17x más barato que GPT-4o, calidad suficiente para clasificación
|
||
2. **Structured outputs**: JSON mode nativo, reduce errores de parsing
|
||
3. **Consistencia**: Respuestas muy consistentes con prompts bien diseñados
|
||
|
||
### Cuándo escalar a GPT-4o
|
||
|
||
- Análisis que requiera razonamiento complejo
|
||
- Casos edge con transcripciones ambiguas
|
||
- Síntesis final de RCA trees (pocas llamadas, coste marginal)
|
||
|
||
### Claude 3.5 Sonnet como fallback
|
||
|
||
Usar cuando:
|
||
- OpenAI tiene downtime
|
||
- Necesitas segunda opinión en casos difíciles
|
||
- Contexto muy largo (>100K tokens)
|
||
|
||
---
|
||
|
||
## 3. Data Processing: pandas + DuckDB
|
||
|
||
### Decisión: **pandas** (manipulación) + **DuckDB** (queries analíticas)
|
||
|
||
### Por qué esta combinación
|
||
|
||
| Componente | Uso | Justificación |
|
||
|------------|-----|---------------|
|
||
| **pandas** | Load/transform JSON, merge data | Estándar de facto, excelente para datos semi-estructurados |
|
||
| **DuckDB** | Queries SQL sobre datos, aggregations | SQL analítico sin servidor, integra con pandas |
|
||
|
||
### Por qué NO Polars
|
||
|
||
- Polars es más rápido, pero pandas es suficiente para 20K filas
|
||
- Mejor ecosistema y documentación
|
||
- Equipo probablemente ya conoce pandas
|
||
|
||
### Por qué NO SQLite/PostgreSQL
|
||
|
||
- DuckDB es columnar, optimizado para analytics
|
||
- No requiere servidor ni conexión
|
||
- Syntax SQL estándar
|
||
- Lee/escribe parquet nativamente
|
||
|
||
### Ejemplo de uso
|
||
|
||
```python
|
||
import pandas as pd
|
||
import duckdb
|
||
|
||
# Cargar todos los labels
|
||
labels = pd.read_json("data/processed/*.json") # via glob
|
||
|
||
# Query analítico con DuckDB
|
||
result = duckdb.sql("""
|
||
SELECT
|
||
lost_sale_driver,
|
||
COUNT(*) as count,
|
||
COUNT(*) * 100.0 / SUM(COUNT(*)) OVER () as pct
|
||
FROM labels
|
||
WHERE outcome = 'no_sale'
|
||
GROUP BY lost_sale_driver
|
||
ORDER BY count DESC
|
||
""").df()
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Visualization: Streamlit
|
||
|
||
### Decisión: **Streamlit** (dashboard interno)
|
||
|
||
### Alcance y Limitaciones
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ STREAMLIT - ALCANCE │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ ✅ ES: │
|
||
│ ├─ Dashboard interno para equipo de análisis │
|
||
│ ├─ Visualización de resultados de batch procesado │
|
||
│ ├─ Drill-down por llamada individual │
|
||
│ └─ Exportación a PDF/Excel │
|
||
│ │
|
||
│ ❌ NO ES: │
|
||
│ ├─ Portal enterprise multi-tenant │
|
||
│ ├─ Aplicación de producción con SLA │
|
||
│ ├─ Dashboard para >50 usuarios concurrentes │
|
||
│ └─ Sistema con autenticación compleja │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Comparativa
|
||
|
||
| Criterio | Streamlit | Plotly Dash | FastAPI+React |
|
||
|----------|-----------|-------------|---------------|
|
||
| **Setup time** | 1 hora | 4 horas | 2-3 días |
|
||
| **Interactividad** | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||
| **Aprendizaje** | Bajo | Medio | Alto |
|
||
| **Customización** | Limitada | Alta | Total |
|
||
| **Usuarios concurrentes** | ~10-50 | ~50-100 | Sin límite |
|
||
|
||
### Deploy
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ OPCIONES DE DEPLOY │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ OPCIÓN 1: Local (desarrollo/análisis personal) │
|
||
│ $ streamlit run src/visualization/dashboard.py │
|
||
│ → http://localhost:8501 │
|
||
│ │
|
||
│ OPCIÓN 2: VM/Servidor interno (equipo pequeño) │
|
||
│ $ streamlit run dashboard.py --server.port 8501 │
|
||
│ → Sin auth, acceso via VPN/red interna │
|
||
│ │
|
||
│ OPCIÓN 3: Con proxy + auth básica (recomendado producción) │
|
||
│ Nginx/Caddy → Basic Auth → Streamlit │
|
||
│ → Auth configurable via .htpasswd o OAuth proxy │
|
||
│ │
|
||
│ OPCIÓN 4: Streamlit Cloud (demos/POC) │
|
||
│ → Gratis, pero datos públicos (no para producción) │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Configuración de Auth (opcional)
|
||
|
||
```nginx
|
||
# nginx.conf - Basic Auth para Streamlit
|
||
server {
|
||
listen 443 ssl;
|
||
server_name dashboard.internal.company.com;
|
||
|
||
auth_basic "CXInsights Dashboard";
|
||
auth_basic_user_file /etc/nginx/.htpasswd;
|
||
|
||
location / {
|
||
proxy_pass http://localhost:8501;
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Upgrade $http_upgrade;
|
||
proxy_set_header Connection "upgrade";
|
||
}
|
||
}
|
||
```
|
||
|
||
### Alternativa futura
|
||
|
||
Si necesitas dashboard enterprise:
|
||
- Migrar a FastAPI backend + React frontend
|
||
- Reusar lógica de aggregation
|
||
- Añadir auth, multi-tenant, RBAC
|
||
|
||
---
|
||
|
||
## 5. PII Handling
|
||
|
||
### Decisión: **Redaction pre-LLM obligatoria** + retención controlada
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ PII HANDLING STRATEGY │
|
||
├─────────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ PRINCIPIO: Minimizar PII enviado a APIs externas │
|
||
│ │
|
||
│ 1. REDACTION PRE-LLM (obligatorio) │
|
||
│ ├─ Nombres → [NOMBRE] │
|
||
│ ├─ Teléfonos → [TELEFONO] │
|
||
│ ├─ Emails → [EMAIL] │
|
||
│ ├─ DNI/NIE → [DOCUMENTO] │
|
||
│ ├─ Tarjetas → [TARJETA] │
|
||
│ └─ Direcciones → [DIRECCION] │
|
||
│ │
|
||
│ 2. RETENCIÓN POR BATCH │
|
||
│ ├─ Transcripts raw: borrar tras 30 días o fin de proyecto │
|
||
│ ├─ Transcripts compressed: borrar tras procesamiento │
|
||
│ ├─ Labels (sin PII): retener para análisis │
|
||
│ └─ Aggregated stats: retener indefinidamente │
|
||
│ │
|
||
│ 3. LOGS │
|
||
│ ├─ NUNCA loguear transcript completo │
|
||
│ ├─ Solo loguear: call_id, timestamps, errores │
|
||
│ └─ Logs en volumen separado, rotación 7 días │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Implementación
|
||
|
||
```python
|
||
# Opción 1: Regex básico (mínimo viable)
|
||
REDACTION_PATTERNS = {
|
||
r'\b\d{8,9}[A-Z]?\b': '[DOCUMENTO]', # DNI/NIE
|
||
r'\b\d{9}\b': '[TELEFONO]', # Teléfono
|
||
r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b': '[EMAIL]',
|
||
r'\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b': '[TARJETA]',
|
||
}
|
||
|
||
# Opción 2: Presidio (recomendado para producción)
|
||
# Más preciso, soporta español, detecta contexto
|
||
from presidio_analyzer import AnalyzerEngine
|
||
from presidio_anonymizer import AnonymizerEngine
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Dependencias Python
|
||
|
||
### Core Dependencies
|
||
|
||
```toml
|
||
[project]
|
||
dependencies = [
|
||
# STT
|
||
"assemblyai>=0.26.0",
|
||
|
||
# LLM
|
||
"openai>=1.40.0",
|
||
"anthropic>=0.34.0", # fallback
|
||
|
||
# Data Processing
|
||
"pandas>=2.2.0",
|
||
"duckdb>=1.0.0",
|
||
"pydantic>=2.8.0",
|
||
|
||
# Visualization
|
||
"streamlit>=1.38.0",
|
||
"plotly>=5.24.0",
|
||
"matplotlib>=3.9.0",
|
||
|
||
# PDF/Excel Export
|
||
"reportlab>=4.2.0",
|
||
"openpyxl>=3.1.0",
|
||
"xlsxwriter>=3.2.0",
|
||
|
||
# Config & Utils
|
||
"pydantic-settings>=2.4.0",
|
||
"python-dotenv>=1.0.0",
|
||
"pyyaml>=6.0.0",
|
||
"tqdm>=4.66.0",
|
||
"tenacity>=8.5.0", # retry logic
|
||
|
||
# JSON (performance + validation)
|
||
"orjson>=3.10.0", # Fast JSON serialization
|
||
"jsonschema>=4.23.0", # Schema validation
|
||
|
||
# Async
|
||
"aiofiles>=24.1.0",
|
||
"httpx>=0.27.0",
|
||
]
|
||
|
||
[project.optional-dependencies]
|
||
# PII detection (opcional pero recomendado)
|
||
pii = [
|
||
"presidio-analyzer>=2.2.0",
|
||
"presidio-anonymizer>=2.2.0",
|
||
"spacy>=3.7.0",
|
||
"es-core-news-sm @ https://github.com/explosion/spacy-models/releases/download/es_core_news_sm-3.7.0/es_core_news_sm-3.7.0-py3-none-any.whl",
|
||
]
|
||
|
||
dev = [
|
||
"pytest>=8.3.0",
|
||
"pytest-asyncio>=0.24.0",
|
||
"pytest-cov>=5.0.0",
|
||
"ruff>=0.6.0",
|
||
"mypy>=1.11.0",
|
||
]
|
||
```
|
||
|
||
### Justificación de cada dependencia
|
||
|
||
| Dependencia | Propósito | Por qué esta |
|
||
|-------------|-----------|--------------|
|
||
| `assemblyai` | SDK oficial STT | Mejor integración, async nativo |
|
||
| `openai` | SDK oficial GPT | Structured outputs, streaming |
|
||
| `anthropic` | SDK oficial Claude | Fallback LLM |
|
||
| `pandas` | Manipulación datos | Estándar industria |
|
||
| `duckdb` | Queries SQL | Analytics sin servidor |
|
||
| `pydantic` | Validación schemas | Type safety, JSON parsing |
|
||
| `streamlit` | Dashboard | Rápido, Python-only |
|
||
| `plotly` | Gráficos interactivos | Mejor para web |
|
||
| `matplotlib` | Gráficos estáticos | Export PNG |
|
||
| `reportlab` | PDF generation | Maduro, flexible |
|
||
| `openpyxl` | Excel read/write | Pandas integration |
|
||
| `pydantic-settings` | Config management | .env + validation |
|
||
| `tqdm` | Progress bars | UX en CLI |
|
||
| `tenacity` | Retry logic | Rate limits, API errors |
|
||
| `orjson` | JSON serialization | 10x más rápido que json stdlib |
|
||
| `jsonschema` | Schema validation | Validar outputs LLM |
|
||
| `httpx` | HTTP client async | Mejor que requests |
|
||
| `presidio-*` | PII detection | Precisión en español, contexto |
|
||
|
||
---
|
||
|
||
## 7. Versiones de Python
|
||
|
||
### Decisión: **Python 3.11+**
|
||
|
||
### Justificación
|
||
|
||
- 3.11: 10-60% más rápido que 3.10
|
||
- 3.11: Better error messages
|
||
- 3.12: Algunas libs aún no compatibles
|
||
- Match pattern (3.10+) útil para parsing
|
||
|
||
---
|
||
|
||
## 8. Consideraciones de Seguridad
|
||
|
||
### API Keys
|
||
|
||
```bash
|
||
# .env (NUNCA en git)
|
||
ASSEMBLYAI_API_KEY=xxx
|
||
OPENAI_API_KEY=sk-xxx
|
||
ANTHROPIC_API_KEY=sk-ant-xxx # opcional
|
||
```
|
||
|
||
### Rate Limiting (implementación obligatoria)
|
||
|
||
```python
|
||
# src/inference/client.py
|
||
from tenacity import retry, wait_exponential, stop_after_attempt
|
||
|
||
@retry(
|
||
wait=wait_exponential(multiplier=2, min=1, max=60),
|
||
stop=stop_after_attempt(5),
|
||
retry=retry_if_exception_type(RateLimitError)
|
||
)
|
||
async def call_llm(prompt: str) -> str:
|
||
# Throttle requests
|
||
await self.rate_limiter.acquire()
|
||
# ... llamada a API
|
||
```
|
||
|
||
### Checklist de seguridad
|
||
|
||
- [ ] API keys en .env, nunca en código
|
||
- [ ] .env en .gitignore
|
||
- [ ] PII redactado antes de LLM
|
||
- [ ] Logs sin transcripts completos
|
||
- [ ] Rate limiting implementado
|
||
- [ ] Backoff exponencial en errores 429
|
||
|
||
---
|
||
|
||
## 9. Alternativas Descartadas
|
||
|
||
### Whisper Local
|
||
- **Pro**: Gratis, offline, datos sensibles
|
||
- **Contra**: Necesita GPU, sin diarization nativo, más lento
|
||
- **Decisión**: Soportado via adapter, no es default
|
||
|
||
### LangChain
|
||
- **Pro**: Abstracciones útiles, chains
|
||
- **Contra**: Overhead innecesario para este caso, complejidad
|
||
- **Decisión**: Llamadas directas a SDK son suficientes
|
||
|
||
### PostgreSQL/MySQL
|
||
- **Pro**: Persistencia, queries complejas
|
||
- **Contra**: Requiere servidor, overkill para batch
|
||
- **Decisión**: DuckDB + archivos JSON/parquet
|
||
|
||
### Celery/Redis
|
||
- **Pro**: Job queue distribuida
|
||
- **Contra**: Infraestructura adicional
|
||
- **Decisión**: asyncio + checkpointing es suficiente
|
||
|
||
---
|
||
|
||
## 10. Resumen de Costes
|
||
|
||
### Parámetros base
|
||
|
||
- **AHT (Average Handle Time)**: 7 minutos
|
||
- **Compresión de transcript**: Asumida (reducción ~60% tokens)
|
||
|
||
### Por 5,000 llamadas
|
||
|
||
| Servicio | Cálculo | Rango |
|
||
|----------|---------|-------|
|
||
| AssemblyAI STT | 35,000 min × $0.015/min | $525 - $580 |
|
||
| OpenAI LLM (comprimido) | 5,000 × $0.0005 | $2 - $3 |
|
||
| OpenAI RCA synthesis | ~10 calls × $0.02 | $0.20 |
|
||
| **TOTAL** | | **$530 - $590** |
|
||
|
||
### Por 20,000 llamadas
|
||
|
||
| Servicio | Cálculo | Rango |
|
||
|----------|---------|-------|
|
||
| AssemblyAI STT | 140,000 min × $0.015/min | $2,100 - $2,400 |
|
||
| OpenAI LLM (comprimido) | 20,000 × $0.0005 | $8 - $12 |
|
||
| OpenAI RCA synthesis | ~10 calls × $0.02 | $0.20 |
|
||
| **TOTAL** | | **$2,110 - $2,420** |
|
||
|
||
### Sin compresión (escenario pesimista)
|
||
|
||
| Volumen | STT | LLM (full transcript) | Total |
|
||
|---------|-----|----------------------|-------|
|
||
| 5,000 calls | $525-580 | $5-10 | **$530 - $590** |
|
||
| 20,000 calls | $2,100-2,400 | $20-40 | **$2,120 - $2,440** |
|
||
|
||
### Coste de infraestructura
|
||
|
||
| Opción | Coste |
|
||
|--------|-------|
|
||
| Local (tu máquina) | $0 |
|
||
| VM cloud (procesamiento) | $20-50/mes |
|
||
| Streamlit Cloud (demos) | Gratis |
|
||
| VM + Nginx (producción) | $30-80/mes |
|