Oracle3
Oracle3: 예측시장 거래 엔진·MCP 서버
Kobra app con agente IA negociador y ProbPago
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
🐍 MV Kobra AI · Plataforma de Cobranzas Inteligentes MV Kobra AI convierte una cartera de cobranzas en un plan de acción priorizado. Combina un modelo de probabilidad de pago (ProbPago) con un Agente IA Negociador que recomienda la mejor estrategia, descuento, canal y guion, y un Copiloto de Negociación en Vivo que analiza el sentimiento del cliente (voz o WhatsApp) y asesora al gestor en tiempo real — todo dentro de un dashboard gerencial con KPIs, filtros, gráficos y exportación a Excel/CSV.README 전문 보기 ↗
MV Kobra AI convierte una cartera de cobranzas en un plan de acción priorizado. Combina un modelo de probabilidad de pago (ProbPago) con un Agente IA Negociador que recomienda la mejor estrategia, descuento, canal y guion, y un Copiloto de Negociación en Vivo que analiza el sentimiento del cliente (voz o WhatsApp) y asesora al gestor en tiempo real — todo dentro de un dashboard gerencial con KPIs, filtros, gráficos y exportación a Excel/CSV.
Qué es esto (léase primero). MV Kobra AI es una demo comercial funcional construida sobre datos 100% sintéticos (sin nombres de clientes, apta para mostrar sin problemas legales). Todo lo que ves funcionar es real: el pipeline, el copiloto, la integración telefónica, el dashboard. Pero ninguna métrica de impacto o de modelo mostrada acá es evidencia de resultados reales — son ilustrativas de la metodología. La sección Honestidad de los números explica exactamente qué es demostración y qué se valida con datos reales.
Presentación gerencial: presentation/MVKobraAI_Presentacion_Gerencial.pptx
(generada con python presentation/build_ppt.py) · versión Canva editable
(reetiquetada, cifras marcadas como ilustrativas):
https://www.canva.com/d/VJ__8kGcZ2M3Q7D (exportable a PDF/PPTX).
Esta demo genera sus propios datos, y eso tiene una consecuencia directa sobre qué se puede afirmar frente a un cliente:
El "impacto de MV Kobra AI" (+pp de conversión/recupero) es un supuesto
programado, no un resultado medido. El generador de gestiones
(data/generate_gestiones.py) inyecta por diseño una mejora progresiva
en los gestores que "adoptan MV Kobra AI" (una curva de aprendizaje codificada).
La pestaña Gestores & Evolución y outputs/impacto_kobra.json después
"recuperan" ese efecto. Es circular a propósito: demuestra cómo se
mediría el impacto (grupo con vs. sin herramienta, evolución mensual,
uplift por cohorte), no cuánto mejora MV Kobra AI. Nunca presentar esos
números como ROI medido.
El AUC del modelo tampoco prueba desempeño real. La etiqueta pago del
dataset sintético se genera con una función logística conocida; que un
modelo la reaprenda con AUC ≈ 0.87 es trivial y esperable por
construcción. De hecho, en la selección de modelos el mejor resultó la
Regresión Logística (ver outputs/model_selection.json) — coherente con
que los datos son, literalmente, logísticos. Con una cartera real, el
algoritmo ganador y el AUC serán otros. Lo que vale acá es la
metodología (comparación de modelos con validación cruzada +
calibración), no el número.
El sentimiento y la emoción de voz son heurísticos, no modelos de deep learning entrenados: léxico en español con negación/intensificadores para texto, y prosodia (energía, F0, ritmo) para voz. Funcionan bien para la demo y para casos claros; en producción se reemplazan por modelos entrenados (SER tipo wav2vec2/SpeechBrain, diarización pyannote) manteniendo las mismas interfaces, que para eso están diseñadas.
Streamlit es front de demo/piloto, no de SaaS multi-tenant. Aguanta un
piloto con un equipo; para cientos de gestores concurrentes con aislamiento
de datos por cliente, la capa de UI se reescribe (el motor — kobra/ y
realtime/ — se conserva).
Al implementar con la cartera real de un cliente, la evidencia se construye así (y solo entonces se pueden afirmar números):
train.yml ya existe).Camino comercial honesto: demo con datos sintéticos → piloto pago acotado sobre una subcartera real → caso testigo con números medidos → ahí sí, implementación completa con evidencia propia.
| Problema tradicional | Con MV Kobra AI |
|---|---|
| Se gestiona igual a todos los deudores | Se prioriza por valor esperado de recupero |
| Descuentos y planes "a ojo" | Decisiones según probabilidad de pago |
| No se sabe a quién contactar primero | Ranking operativo automático |
| Guiones de negociación improvisados | Guion generado por el agente IA |
| El gestor negocia "a ciegas" | Copiloto en vivo: sentimiento + próxima jugada |
| Reporting manual y lento | Dashboard + export a Excel/CSV |
Cartera (CSV)
│
├─► ProbPago (kobra/probpago.py) modelo de probabilidad de pago (ML)
│
├─► Agente Negociador (kobra/negociador.py) estrategia + descuento + canal + guion
│
├─► Copiloto en Vivo (kobra/copiloto.py) sentimiento + técnicas + asesoría en tiempo real
│ ├─ realtime/ (FastAPI + WebSocket) audio en vivo durante la llamada
│ └─ voz (kobra/voz.py) diarización + emoción acústica de voz
│
├─► Analítica de gestión (kobra/analitica.py) por gestor/mes/tramo/segmento + medición de impacto
│
├─► Entrenamiento ML (kobra/train.py) selección de modelos + calibración (ProbPago)
│
├─► Pipeline (kobra/pipeline.py) orquesta todo y exporta
│ ├─ outputs/kobra_scored.csv / .xlsx
│ ├─ outputs/kobra_bundle.json
│ └─ dashboard_estatico/kobra_data.js
│
├─► Dashboard Streamlit (app/app.py) KPIs · filtros · gráficos · export
├─► Dashboard estático (dashboard_estatico/index.html) zero-install, offline
└─► Presentación gerencial (presentation/*.pptx)
./run.sh # instala deps, genera datos, corre el modelo y abre el dashboard
pip install -r requirements.txt
python data/generate_dataset.py --n 12000 --seed 42 # genera la cartera sintética
python -m kobra.pipeline # entrena ProbPago + negociador + exports
streamlit run app/app.py # dashboard interactivo
python presentation/build_ppt.py # presentación gerencial (PPTX)
En una máquina limpia, dos comandos y listo:
pip install -r requirements.txt -r requirements-dev.txt
python -m pytest -q tests/ # ~560 tests
ruff check . # linter
requirements-dev.txt trae lo que hace falta además para testear (pytest,
httpx, ruff). Antes pytest no figuraba en ningún requirements —solo lo
instalaba una línea suelta del CI—, así que seguir el README no alcanzaba para
correr la suite.
Los tests que necesitan ffmpeg (regeneración del audio de la demo) se saltean
solos si no está: es una dependencia de sistema, no de pip, y su ausencia no
puede romper la suite entera.
api/*.js)La parte del dinero que corre en Vercel —checkout, verificación de pago, firma de licencia— tiene su propia suite, sin dependencias nuevas:
npm install # una vez, para tener `botid` (bot-check) disponible
npm test # node --test, viene con Node (sin runner de terceros)
Corre en CI junto con la suite de Python (.github/workflows/ci.yml). Antes no
corría ahí: el job era solo de Python, así que un cambio en el emisor de
licencias podía llegar a main sin ejecutar una sola de estas pruebas.
No usa Jest ni Vitest a propósito: agregar un test runner de terceros para
esto sería exactamente el tipo de dependencia extra que este proyecto evita
cuando alcanza con lo que ya trae el lenguaje (ver el docstring de
kobra/limitador.py).
Un MVKobraAI_Setup.exe que instala MV Kobra AI como un programa (empaqueta Python,
Node/React ya compilado y todas las librerías; doble clic → se abre la app completa
—la misma interfaz React + FastAPI que corre en la nube, embebida en un solo
proceso local). Se construye en Windows vía GitHub Actions (no se puede
compilar desde Linux/Mac):
build-windows-installer corre en windows-latest
(Node compila webapp/frontend → PyInstaller empaqueta todo, incluida esa
build, → Inno Setup arma el instalador). El .exe queda como
artefacto descargable de cada corrida (pestaña Actions del repo) y, al
taguear vX.Y.Z, se publica en una Release (además de en un repo público
aparte solo para binarios — ver docs/DISTRIBUCION_INSTALADOR.md — porque
este repo es privado).backend_venta/licencias.py — no una contraseña de administrador. El
dashboard clásico (Streamlit, app/app.py) sigue en el paquete y disponible
para correr a mano, pero ya no es lo que abre el instalador por default.electron/ (la app de escritorio: ventana Electron con la UI
React), packaging/kobra_launcher.py (arranca uvicorn sirviendo
webapp/backend/api.py, que a su vez sirve el build de React) y
packaging/kobra.spec (empaquetado PyInstaller del motor). electron-builder
genera el instalador NSIS con accesos directos, ícono y desinstalador
registrado en "Agregar o quitar programas".Actions → build-windows-installer → (Run workflow) → artefacto "MVKobraAI_Setup_Windows"
o → git tag v1.3.0 && push → Release con MVKobraAI_Setup_v1.3.0.exe
kobra/plan.pyLa licencia viaja firmada con plan, cupo_mensual y features, y la app
instalada las aplica. Hasta la v1.3.5 leía una sola cosa —la fecha de
vencimiento—, así que un cliente de Básico recibía exactamente el mismo
producto que uno de Pro: la diferencia estaba emitida y firmada, pero no la
aplicaba nadie dentro del programa.
| Trial | Básico | Starter | Pro | Enterprise | |
|---|---|---|---|---|---|
| Gestiones/mes | 50 | 300 | sin tope¹ | 1.000 | sin tope |
| Al llegar al tope | corta | corta | — | excedente | — |
| white_label · sso | no | no | no | no | sí |
¹ Starter es el plan "traé tus propias APIs": el consumo lo paga el cliente en su cuenta, así que un cupo nuestro no cubriría ningún costo.
backend_venta/app.py).Abrí dashboard_estatico/index.html en cualquier navegador (funciona
offline, con librerías locales). Ideal para demos y para compartir por mail.
docker compose up --build
# Dashboard: http://localhost:8501
# Realtime : http://localhost:8000 (copiloto de audio en vivo)
Una sola imagen sirve ambos servicios (dashboard Streamlit y API realtime). Los datos/modelo se generan en el primer arranque; los volúmenes persisten datos, outputs y la configuración de API keys entre reinicios.
Las keys se cargan de tres formas (prioridad de arriba hacia abajo):
.env (OPENAI_API_KEY, ANTHROPIC_API_KEY,
GEMINI_API_KEY) — ideal en producción.$KOBRA_CONFIG_DIR/config.json, por defecto ~/.kobra), así
se cargan solas en cada arranque sin reingresarlas.Con OPENAI_API_KEY se habilita la transcripción real (Whisper). Para el
razonamiento con IA (Asistente, Copiloto, Gestor IA), el cliente elige en
Configuración con qué proveedor propio quiere trabajar — Claude (Anthropic),
Gemini (Google) o ChatGPT (OpenAI) — y carga la key correspondiente; ver
kobra/llm.py. Por default es Claude, si no se eligió otro.
Siete pestañas, con filtros dinámicos (segmento, producto, tramo de mora, propensión, departamento, monto y ProbPago mínima):
python -m kobra.train → outputs/probpago_model.joblib +
outputs/model_selection.json).kobra/pipeline.py (y por lo tanto el dashboard, Streamlit y estático) carga
automáticamente outputs/probpago_model.joblib cuando ya corriste
python -m kobra.train; si no lo corriste, cae en un Gradient Boosting
ad-hoc sin calibrar y lo etiqueta como tal en pantalla (nunca se muestra
un modelo distinto al que realmente scoreó la cartera)..github/workflows/train.yml).Para cada deudor decide, maximizando el recupero esperado y minimizando la quita:
kobra/portal_pagos.py)El deudor paga solo, sin hablar con nadie. La empresa genera para cada deudor
un link de pago, su código QR y un usuario + código de 6 dígitos
(pestaña Portal de cobros de la webapp, solo admin), y lo comparte por
WhatsApp, mail o impreso en la factura. Al entrar (/#/pagar), el deudor ve
su listado de facturas pendientes (derivado determinístico de la deuda, o
el desglose real si la cartera lo trae) y paga total o parcial por:
KP-…); al declarar la transferencia el pago
queda informado (pendiente de conciliar).Cada pago confirmado queda imputado para el ERP/CRM de la empresa por dos
vías complementarias: un webhook saliente (POST del asiento JSON a la URL
configurada, con reintentos) y un pull por API
(GET /api/erp/imputaciones, cabecera X-API-Key, con parámetro desde
para sincronización incremental) — cualquier ERP/CRM se integra sin
desarrollo del lado de Kobra. Seguridad: token HMAC firmado en el link/QR,
código de acceso con freno anti fuerza bruta (429), y el monto nunca puede
superar el saldo pendiente. Tests: tests/test_portal_pagos.py.
Asiste al gestor durante la negociación telefónica o por WhatsApp
(kobra/copiloto.py):
Funciona 100% offline. Si hay claves en el entorno se enriquece solo:
OPENAI_API_KEY → transcripción de audio (Whisper); evaluación cualitativa
profunda con el proveedor de IA elegido (Claude por default, o Gemini/ChatGPT
si se configuró otro en Configuración — ver kobra/llm.py).
Disponible en tres lugares:
dashboard_estatico/copiloto.js).realtime/ (ver más abajo).realtime/)Backend FastAPI + WebSocket que asiste al gestor mientras habla:
Micrófono/llamada → transcripción en vivo → Copiloto → asesoría en pantalla
POST /transcribe) si hay
OPENAI_API_KEY.python -m realtime.server # http://localhost:8000
En producción telefónica el audio se toma del softphone/PBX (grabación o media stream del canal), no del micrófono; el resto del flujo es idéntico.
kobra/voz.py)Analiza la señal de voz de la llamada, no solo las palabras:
copiloto.analizar_sentimiento(texto, voz=…)), de modo que una voz tensa
del cliente adelanta la alerta aunque las palabras sean neutras.Probalo con la grabación de demo (dual-channel sintética):
python data/generate_audio_demo.py # crea data/ejemplo_llamada.wav
# En el dashboard → pestaña "Copiloto en Vivo" → "Analizar grabación (voz)"
# o por API: POST /analizar_audio al servidor realtime
Un PBX es la central telefónica de la empresa; un softphone es el teléfono por software del gestor. MV Kobra AI no los reemplaza: se conecta al audio que ya manejan. MV Kobra AI es agnóstico de la plataforma — funciona con Avaya, Genesys, Cisco, 3CX, Asterisk/FreePBX, Twilio, etc. — porque toma el audio por mecanismos estándar:
| Plataforma | Cómo se obtiene el audio |
|---|---|
| Avaya | Grabación dual-channel (Avaya AES/DMCC) o media stream vía SIPREC |
| Genesys | AudioHook / SIPREC / grabación por agente |
| Cisco | Built-in Bridge / Network-Based Recording (SIPREC) |
| Asterisk / 3CX | MixMonitor (dual-channel) o forking de RTP |
| Twilio / nube | Media Streams (WebSocket de audio en vivo) |
| Cualquiera | Archivo de grabación .wav dual-channel post-llamada |
Recomendado: grabación dual-channel (una pata por interlocutor) → la diarización es exacta y la emoción por hablante es más precisa. El resto del pipeline (transcripción → copiloto → asesoría) es idéntico en todos los casos.
⚠️ Micrófono de la PC ≠ telefonía. El micrófono solo capta el audio de la PC (útil para VoIP en la PC o pruebas). Para una llamada por central (Avaya, etc.) el audio va por la telefonía: usá la opción “Central telefónica / grabación”. En la app realtime hay un selector “Fuente de audio” que separa ambos modos.
voz.transcribir_llamada() / voz.copiloto_desde_audio() producen la
transcripción por turno y por hablante:
OPENAI_API_KEY → Whisper transcribe el audio real con marcas de
tiempo por segmento, y cada segmento se asigna al hablante diarizado con
mayor solapamiento temporal.Cada turno se fusiona con la emoción acústica de ese tramo, de modo que la
tabla muestra Sent. texto vs Sent. voz+texto — la voz tensa del cliente
empuja la alerta más allá de las palabras. Endpoints:
POST /copiloto_audio (subir grabación) y GET /copiloto_demo.
realtime/connectors.pyPara asesorar mientras la llamada ocurre, el audio de la central entra por WebSocket y el copiloto responde turno a turno:
| Fuente | Endpoint | Formato |
|---|---|---|
| Twilio Media Streams | WS /twilio | μ-law 8 kHz; track inbound→cliente, outbound→gestor (protocolo real de Twilio) |
| SIPREC (Avaya/Genesys/Cisco) | WS /ws_audio | el SBC/grabador forkea el RTP a un media server que reenvía PCM16 |
| Avaya DMCC/AES | WS /ws_audio | el SDK entrega el audio del canal y se reenvía como PCM16 |
StreamSession acumula audio por hablante y, al cerrar cada turno (silencio /
cambio de interlocutor), transcribe (Whisper si hay key), calcula emoción
acústica, fusiona voz+texto y devuelve la asesoría. Probalo sin central real:
python -m realtime.server # levanta el servidor
python -m realtime.simular_stream # stremea la grabación demo a /ws_audio
# o en el navegador: modo "Central telefónica" → "📡 Simular stream en vivo"
Para conectar tu central: apuntá el <Stream> de Twilio a wss://<host>/twilio,
o configurá SIPREC/DMCC para reenviar el media a wss://<host>/ws_audio. La
asesoría se enruta a la pantalla del gestor (WS /ws).
realtime/conector_avaya.py)Puente RTP → MV Kobra AI listo para producción: recibe el audio que la central forkea por RTP (G.711 μ-law o A-law — A-law es el estándar en Uruguay —, paquetes de 20 ms, una pata por puerto UDP), hace VAD por energía, corta cada turno al silencio y lo envía al Copiloto, que devuelve la asesoría en vivo y registra la gestión al colgar.
python -m realtime.conector_avaya --deudor KB-100773 --gestor G03
# --puerto-gestor 5004 --puerto-cliente 5006 --silencio 0.6
# --transcript <archivo del CTI> (opcional, enriquece sin Whisper)
audioop, eliminado en Python 3.13).id_deudor llega por
el CTI (UUI/header SIP) y se pasa con --deudor.Probalo sin central física con el simulador de RTP incluido (emite la llamada demo como paquetes RTP reales, igual que un SBC):
python -m realtime.server # terminal 1
python -m realtime.conector_avaya --deudor KB-100773 # terminal 2
python -m realtime.simular_rtp --codec alaw # terminal 3
Verificado end-to-end: los 10 turnos llegan separados por pata, con emoción de voz detectada (enojo/frustración del cliente), brief pre-llamada, asesoría turno a turno y gestión registrada al cortar.
GET /brief/{id_deudor}: briefing para el screen-pop
del CTI (Avaya Workspaces, etc.): ProbPago, estrategia, descuento máximo,
plan, canal, guion y prioridad, calculados por el pipeline. El marcador
(p. ej. Avaya Proactive Outreach) puede tomar la lista priorizada exportada.start de /ws_audio acepta id_deudor y
gestor_id: MV Kobra AI carga solo el briefing y ajusta la propuesta turno a
turno según el sentimiento (voz + texto) del cliente.stop (acepta resultado con la tipificación
real del CRM; si falta, se infiere del clima + intención de pago) persiste
la negociación en data/kobra_gestiones.csv vía kobra/registro.py:
calidad, sentimiento, emoción dominante, técnicas, resultado y recupero.
Esa es la misma base que alimenta la pestaña Gestores & Evolución, así
el dashboard pasa de la demo a llamadas reales sin ningún cambio.Probalo end-to-end sin central: python -m realtime.simular_stream (muestra el
brief, la asesoría en vivo y la gestión registrada al final).
kobra/gestor_ia.py)El gestor virtual conduce la negociación completa igual que un humano —
por voz (voicebot) o por WhatsApp (chatbot): saluda, valida identidad,
propone según ProbPago/estrategia, maneja objeciones con concesiones
escalonadas dentro del tope autorizado, cierra, completa los campos ERP y
registra la gestión. Aparece en Gestores & Evolución como gestor IA…, así
su desempeño se mide contra los humanos.
kobra/llm.py: Claude/Gemini/ChatGPT, la
cuenta propia que el cliente elija en Configuración) — si hay key
configurada redacta más natural; sin key usa plantillas (funciona igual).realtime/voicebot.py): hasta 50 llamadas
simultáneas (verificado: 50 líneas, pico 50, 0 errores). El canal de voz
real lo pone la telefonía del cliente (Twilio <Connect>, Avaya/SIPREC con
el conector incluido, Asterisk…); en demo hay un cliente simulado.POST /whatsapp/webhook): para quien no quiere hablar
por teléfono. El proxy del canal (WhatsApp Cloud API / Twilio WhatsApp del
cliente) postea {sesion, id_deudor, mensaje} y el Gestor IA negocia y
registra la gestión como canal WhatsApp.python -m realtime.voicebot --lineas 50 --llamadas 50 # campaña saliente
# chatbot WhatsApp: POST /whatsapp/webhook (ver realtime/server.py)
Nota: en la demo, la cohorte del Gestor IA en Gestores & Evolución es sintética e ilustrativa (como el resto). Con la operación real, cada conversación del Gestor IA registra su gestión y el dashboard compara IA vs. humanos con datos medidos.
kobra/analitica.py)Sobre el historial de gestiones responde:
⚠️ En la demo, el historial de gestiones es sintético y el "efecto MV Kobra AI" está inyectado por el generador para ilustrar la metodología. Los uplifts que muestra la pestaña Gestores & Evolución no son resultados medidos. Con el registro post-llamada (
kobra/registro.py) la misma pestaña se alimenta de llamadas reales, y ahí los números sí significan algo.
kobra/train.py)Selección de modelos con validación cruzada (5 folds): compara Regresión Logística, Random Forest, Gradient Boosting e HistGradientBoosting, elige el mejor por ROC-AUC, lo calibra (isotónica) y lo persiste:
python -m kobra.train
# → outputs/probpago_model.joblib y outputs/model_selection.json
Se reentrena en CI vía GitHub Actions (.github/workflows/train.yml,
manual o semanal). El workflow ci.yml corre los tests y un smoke test del
pipeline en cada push/PR.
Tres capas que hacen a MV Kobra AI vendible a una entidad regulada (banco, financiera, cooperativa, estudio de cobranzas) y no solo demostrable.
kobra/cumplimiento.pyGobierna cuándo y cómo se puede contactar a cada deudor, para que la cobranza —humana o del Gestor IA— opere dentro de la ley y las buenas prácticas. Es la capa que legal/compliance exige antes de dejar que un bot llame a una cartera:
es_pedido_no_contactar
→ registrar_no_contactar). El voicebot filtra la base antes de marcar.PoliticaContacto).from kobra import cumplimiento as cp
d = cp.puede_contactar("KB-100773", "Llamada") # Decision(permitido, codigo, motivo)
⚠️ Herramienta de apoyo al cumplimiento, no asesoría legal: cada empresa fija su política con su asesoría jurídica; MV Kobra AI provee el mecanismo para hacerla cumplir y auditar.
kobra/explicabilidad.pyPara cada deudor responde por qué el modelo le asignó esa probabilidad:
qué características la suben y cuáles la bajan, en puntos porcentuales
(atribución por oclusión, model-agnostic — funciona con cualquier modelo
del pipeline). El pipeline agrega la columna motivo_probpago a la cartera
scoreada y al brief pre-llamada, p. ej.:
KB-111022 · ProbPago 99% → Score de buró (+3.9 pp) · Promesas cumplidas (+0.5 pp)
KB-106556 · ProbPago 1% → Promesas incumplidas (-1.1 pp) · Días de mora (-1.0 pp)
Convierte a ProbPago de "caja negra" en una decisión automatizada auditable y defendible — lo que exigen la Ley 18.331 de Uruguay y marcos equivalentes.
kobra/roi.pyTraduce la cartera del comprador en un rango de valor bajo distintos supuestos de uplift, para dimensionar el premio y justificar un piloto pago:
python -m kobra.roi --cartera 100000000 --tasa-base 0.30 --costo-mensual 100000
# [conservador] +2 pp → adicional $U 2.000.000 …
# [ base] +5 pp → adicional $U 5.000.000 · ROI … · payback … m
⚠️ El uplift es un supuesto que carga el usuario, no un resultado medido. El módulo proyecta cuánto valdría, no afirma cuánto sube MV Kobra AI — coherente con la sección Honestidad de los números.
En el dashboard, pestaña "🧪 Probar mi cartera": cargás tus contactos
—escribiéndolos en una tabla, subiendo un CSV/Excel o trayéndolos
directo de tu base de datos (PostgreSQL, MySQL, SQL Server, SQLite… con una
consulta de solo lectura; cartera_manual.desde_base_de_datos)— y el Gestor IA
negocia cada caso (ProbPago + el porqué, estrategia, chequeo de cumplimiento y
la conversación completa). Los resultados se descargan a CSV/Excel. Todo por
menús; no hace falta correr nada.
La pestaña "💰 Caso de negocio" calcula el ROI sobre tu cartera con tus supuestos y también se descarga.
También hay un CLI equivalente (
python -m realtime.mi_cartera) para quien prefiera consola. El CSV con datos reales queda privado (.gitignore).
La conversación se simula. Para llamar de verdad hace falta telefonía
(tu cuenta de Twilio con un número, o tu central Avaya/Asterisk) y el
consentimiento de la persona — guía paso a paso en
docs/GUIA_LLAMADA_REAL_TWILIO.md. Comprar
el número y apuntar su webhook de voz no hace falta hacerlo a mano en la
Console de Twilio: la pestaña Configuración → "📞 Auto-configurar número
Twilio" (kobra/twilio_setup.py) lo hace por API, con las credenciales que
ya cargaste.
⚖️ Proteger MV Kobra AI en Uruguay (derecho de autor + marca, con costos):
docs/GUIA_REGISTRO_LEGAL_URUGUAY.md.
💼 Modelo comercial (PoC + implementación + retainer, propuesta a confirmar):
docs/MODELO_COMERCIAL.md.
🏦 Vender a un banco/financiera (procurement): whitepaper de seguridad (
docs/WHITEPAPER_SEGURIDAD.md), plantilla de acuerdo de tratamiento de datos (docs/PLANTILLA_DPA.md) y plantilla de SLA (docs/PLANTILLA_SLA.md) — los tres son borradores para adaptar con tu asesor legal, no documentos listos para firmar.
🔒 Privacidad. Un CSV con nombres/teléfonos reales es privado:
data/mi_cartera_prueba.csvydata/*_prueba.csvestán en.gitignorey no se suben al repo. El producto que se vende sigue siendo 100 % sintético (Ley 18.331). Para llamar a un tercero necesitás su consentimiento.
kobra/integracion.pyCada gestión —del Gestor IA o de un humano— queda tipificada con su resultado y sus datos, y esa sábana se exporta o sincroniza a cualquier ERP o base de datos:
Pago · Arreglo de pago · Promesa de pago · Informado · No contactado · Fallecido · Negativa · Número erróneo · Sin acuerdo, con fecha_gestion, fecha_compromiso, fecha_pago,
monto_acordado, cuotas, descuento, notas, tipo_gestor (IA/Humano)…aplicar_mapeo) para renombrar las columnas de
MV Kobra AI a las del ERP del cliente.from kobra import integracion as ig
sab = ig.sabana(gestiones_df)
ig.enviar_api(sab, "https://tu-erp.com/api/gestiones", api_key="…")
ig.sincronizar_db(sab, "postgresql://user:pass@host/db", tabla="gestiones")
kobra/consulta_bd.pySe conecta a cualquier base relacional del cliente (PostgreSQL, MySQL/ MariaDB, SQL Server, Oracle, SQLite… cualquiera compatible con SQLAlchemy) y responde preguntas en español, devolviendo el SQL usado, la tabla de resultados y un gráfico automático — sin inventar nombres de tabla/columna:
INSERT/UPDATE/DELETE/DROP/ALTER) antes de ejecutarlo.En el dashboard: pestaña "🔎 Preguntá a tu base de datos" — pegá la URL de conexión (la misma de Integración ERP u otra), conectá, y preguntá.
from kobra import consulta_bd as cb
motor = cb.MotorConsultaBD("postgresql://user:pass@host/db")
r = motor.responder("cuánto cobramos en marzo 2026 por departamento",
api_key="sk-ant-...")
df = motor.resultado_a_dataframe(r)
kobra/seguimiento.pyCierra el círculo después de una "Promesa de pago" o "Arreglo de pago": detecta cuándo la fecha comprometida venció sin que se haya registrado el pago (ni en la misma gestión, ni en una posterior), y arma la agenda del día — a quién recontactar y por qué — respetando la política de cumplimiento vigente (horario, feriados, topes de frecuencia, lista de No Contactar). No es un canal nuevo: el recontacto sigue siendo una gestión normal del Gestor IA o de un humano.
En el dashboard: pestaña "📅 Agenda de seguimiento".
from kobra import seguimiento as kseg
agenda = kseg.agenda_hoy(gestiones_df) # + columnas contactable / motivo_bloqueo
kobra/voz_tts.pyPor defecto las llamadas usan <Say> de Twilio (voces Amazon Polly,
incluidas en la cuenta de Twilio, sin costo extra). Configurando
ELEVENLABS_API_KEY y eligiendo una voz en Configuración, las llamadas
reales pasan a usar ElevenLabs — más voces, acentos regionales reales y
clonación de voz. Tiene costo real por carácter (ver
COSTO_POR_1000_CHARS_USD en el módulo — referencia de mercado, verificar
contra tu plan real antes de fijar precio). Por eso, en el backend de venta
(backend_venta/), esta voz premium requiere la feature "voz_premium"
aparte — no viene incluida por default en ningún plan, para que el precio
fijo de un plan no termine subsidiando un costo variable no cotizado. Si
falla o no está configurada, cae solo a Twilio/Polly — nunca corta la
llamada.
kobra/campana.pyOrquesta el contacto saliente sin intervención manual, corriendo dentro
de realtime/server.py (requiere que ese proceso quede levantado 24/7 —
Docker/servidor real, no un streamlit run que solo vive con el dashboard
abierto):
kobra/seguimiento.py),
después el resto de la cartera por valor_esperado_recupero.kobra.cumplimiento.puede_contactar (horario legal,
feriados, topes de frecuencia, No Contactar tienen la última palabra).TWILIO_WHATSAPP_CONTENT_SID) — es un requisito de la plataforma de
WhatsApp Business para iniciar una conversación, no algo que se pueda
saltear desde acá.SMTP_HOST/USER/ PASSWORD/FROM), con plantilla customizable por tramo de mora
(pestaña Configuración → "Plantillas de email por tramo de mora").Se activa/desactiva desde el dashboard (Configuración → "Campaña automática
de contacto") sin reiniciar el servidor; el scheduler revisa el estado en
cada corrida (CAMPANA_INTERVALO_MIN, default 60 min). Requiere
PUBLIC_BASE_URL (para el callback de Twilio) y un CSV con los contactos
reales de la cartera (id_deudor,telefono,email — el dataset sintético de
la demo no trae contactos reales a propósito).
from kobra import campana as kcamp
plan = kcamp.plan_contacto_hoy(gestiones_df) # prioridad + canal + horario + cumplimiento
telefonos, emails = kcamp.cargar_contactos("mi_cartera_contactos.csv")
kcamp.ejecutar_plan(plan, base_url="https://tu-servidor.com", telefonos=telefonos, emails=emails)
kobra/ayuda.pyEn la pestaña ❓ Guía & Ayuda hay un asistente con IA que responde dudas sobre el propio producto ("¿cómo cargo mi cartera?", "¿qué necesito para llamar de verdad?"), en español y al instante:
docs/*.md del producto — la documentación no se sube a ningún lado.kobra/originacion.pyExtensión upstream del mismo motor: además de cobrar mejor, decidir mejor a quién prestarle. Para cada solicitud de crédito devuelve probabilidad de mora, score 0-1000, decisión sugerida (Aprobar / Derivar a análisis / Rechazar), monto y plazo sugeridos, top-3 razones en lenguaje simple y un nivel de confianza según cuántos datos reales llegaron — con datos insuficientes nunca auto-decide: deriva a un analista humano.
Estándares ML del brief Kobra 2.0: validación walk-forward temporal
(nunca random split), anti-SMOTE (ponderación de muestras), benchmark
honesto contra la regla típica del oficial de crédito, y explicabilidad por
decisión individual. API: POST /api/originacion/score y
GET /api/nba/{id_deudor} (next-best-action de cobranza). Estado completo
del brief: docs/KOBRA_2_0.md.
webapp/Además del dashboard Streamlit, hay una app web SaaS profesional con la misma data y los mismos motores — pensada para el cliente que espera una interfaz de producto comercial:
webapp/backend/api.py, FastAPI): API REST con JWT
(reutiliza las contraseñas admin/gestor de kobra/autenticacion.py) y
multi-tenant por directorio desde el día uno: la empresa principal
usa los datos del repo; cualquier otra resuelve a data/tenants/<empresa>/
con aislamiento verificado por test. Incluye API entrante para
integradores (POST /api/integracion/cartera): el core/ERP del cliente
empuja su cartera como JSON, sin archivos de por medio.webapp/frontend/, React + Vite + Recharts): login, tour de
bienvenida, Visión general (KPIs + 4 gráficos), Cartera priorizada con
filtros/paginado/export y briefing por deudor con guion sugerido,
Agenda de promesas vencidas, ranking de Gestores, Asistente IA y
Configuración de claves (solo admin).cd webapp/frontend && npm install && npm run build # compila el frontend
python -m uvicorn webapp.backend.api:app --port 8800 # sirve API + frontend
El dashboard Streamlit sigue funcionando igual — conviven sobre los mismos CSV/modelos; la app React es la cara comercial, Streamlit el laboratorio.
Kobra/
├── data/generate_dataset.py # generador de cartera sintética (Uruguay)
├── kobra/
│ ├── probpago.py # modelo de probabilidad de pago
│ ├── negociador.py # agente IA negociador
│ ├── copiloto.py # copiloto de negociación en vivo (sentimiento)
│ ├── voz.py # diarización + emoción acústica de voz
│ ├── analitica.py # analítica por gestor / mes / tramo / segmento
│ ├── cumplimiento.py # cumplimiento normativo (horarios, topes, no-contactar)
│ ├── explicabilidad.py # reason codes por deudor (por qué esta ProbPago)
│ ├── roi.py # estimador de caso de negocio (ROI)
│ ├── integracion.py # exportar/sincronizar la sábana a ERP/base de datos
│ ├── consulta_bd.py # NL2SQL: preguntá a la base del cliente en español
│ ├── cartera_manual.py # cargar tu propia cartera de prueba
│ ├── registro.py # briefing pre-llamada + registro post-llamada
│ ├── seguimiento.py # agenda: promesas/arreglos vencidos sin pago
│ ├── voz_tts.py # voz premium opcional (ElevenLabs) — costo por carácter
│ ├── campana.py # campaña automática: canal/horario/prioridad + llamada/WhatsApp/email
│ ├── twilio_setup.py # auto-configurar número Twilio (buscar/comprar/webhook) por API
│ ├── ayuda.py # asistente de ayuda del producto (IA sobre la propia documentación)
│ ├── originacion.py # motor de originación: score + decisión + razones al originar
│ ├── config.py # API keys persistentes (Configuración)
│ ├── train.py # entrenamiento ML (selección de modelos)
│ └── pipeline.py # orquestación end-to-end + exports
├── realtime/ # copiloto de audio en vivo (FastAPI + WebSocket)
├── webapp/ # plataforma web profesional: backend FastAPI (JWT, multi-tenant) + frontend React
├── app/app.py # dashboard Streamlit (7 pestañas)
├── dashboard_estatico/ # dashboard + copiloto zero-install (offline)
│ └── guiones.js # guiones de las demos de voz/WhatsApp (es · pt · en)
├── presentation/build_ppt.py # generador de presentación gerencial
├── marketing/ # kit de contenido para redes (banners + copy + reels)
├── tests/test_kobra.py # pruebas del pipeline y el copiloto
├── referencia_R/ # motor R original adaptado (referencia)
├── .github/workflows/ # CI (tests) + entrenamiento ML programado
├── Dockerfile · docker-compose.yml # despliegue (dashboard + realtime)
├── outputs/ # CSV, Excel, JSON y modelo generados
├── assets/ # capturas del dashboard
├── requirements.txt
└── run.sh
El dataset es 100% sintético, generado localmente y sin nombres ni
datos personales de clientes reales. El esquema es genérico: para usarlo con
una cartera real basta con respetar las mismas columnas
(data/generate_dataset.py documenta el esquema). Apto para demo comercial en
Uruguay sin exponer información sensible.
Origen: el copiloto adapta y generaliza criterios de evaluación de gestiones de un motor de referencia de autoría propia (
referencia_R/), sin marcas ni datos de terceros.