Skip to main content
Glama
theblacknietzsche

Radar de Riesgo de Devolución

README.md
# Radar de Riesgo de Devolución — Agente MCP con memoria

Proyecto de la **Clase 3 (Estrategias de Integración)**: evoluciona el notebook
`RadarRiesgoDevolucion_MCP_LangChain.ipynb` (Clase 2) hacia un sistema
Python reutilizable, con memoria de corto plazo y múltiples clientes
(Streamlit y Claude Desktop).

## Arquitectura

```
Streamlit / Claude Desktop
        │
        ▼
mcp_agente.py   (MCP del agente — fachada de alto nivel)
        │
        ▼
agent_core.py   (LangChain + OpenAI + memoria por session_id)
        │
        ▼
mcp_datos.py    (MCP de datos — 5 tools de riesgo de devolución)
        │
        ▼
data/ecommerce_demo.db  (SQLite)
```

## 1. Setup del entorno

```bash
cd clase3_agente_mcp_memoria
python -m venv venv
source venv/bin/activate        # En Windows: venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
```

Edita `.env` y completa `OPENAI_API_KEY` (y ajusta `OPENAI_MODEL` si no
tienes acceso a `gpt-5.4-nano`).

## 2. Construir la base de datos

El CSV ya está en `data/ecommerce_orders.csv`. Genera el SQLite:

```bash
python data/build_db.py
```

Esto crea `data/ecommerce_demo.db` con la tabla `orders` e índices.

## 3. Levantar el MCP de datos

```bash
python mcp_datos.py
```

Debe quedar escuchando en `http://127.0.0.1:8000/mcp`. Déjalo corriendo en
esta terminal.

## 4. Levantar el MCP del agente (modo HTTP, para Streamlit)

En una **segunda terminal** (con el mismo entorno virtual activado):

```bash
export MCP_AGENT_TRANSPORT=http   # En Windows (PowerShell): $env:MCP_AGENT_TRANSPORT="http"
python mcp_agente.py
```

Debe quedar escuchando en `http://127.0.0.1:8100/mcp`.

## 5. Probar el núcleo del agente de forma aislada (opcional)

Antes de tocar Streamlit, puedes validar que el agente responde:

```bash
python agent_core.py
```

Esto ejecuta dos consultas de prueba en la misma sesión y muestra si el
agente mantiene contexto entre ellas.

## 6. Levantar Streamlit

En una **tercera terminal**:

```bash
streamlit run app_streamlit.py
```

Se abrirá en el navegador. Prueba la demo de memoria sugerida en la guía:

1. Pregunta: *"Busca clientes Premium con alto riesgo en Fashion"*
2. Sin cambiar de sesión, pregunta: *"Analiza al de mayor consumo"*
3. Haz clic en **Nueva conversación** y repite la segunda pregunta:
   el agente ya no debería poder resolver la referencia.

## 7. Conectar Claude Desktop (host MCP externo)

1. Detén el proceso de `mcp_agente.py` en modo HTTP (Ctrl+C) — Claude
   Desktop necesita transporte `stdio`, no `http`.
2. Copia `config/claude_desktop_config.example.json` a la ubicación de
   configuración de Claude Desktop (revisa la documentación de Claude
   Desktop para la ruta exacta según tu sistema operativo).
3. Reemplaza la ruta del `args` por la ruta absoluta real de tu proyecto,
   y completa tu `OPENAI_API_KEY`.
4. Asegúrate de que `mcp_datos.py` siga corriendo (Paso 3) — el agente lo
   necesita sin importar el cliente que lo use.
5. Reinicia Claude Desktop. Debería descubrir la tool
   `resolver_consulta_ecommerce`.
6. Prueba la misma pregunta usada en Streamlit y compara las respuestas.

## Estructura del proyecto

```
clase3_agente_mcp_memoria/
├── mcp_datos.py              # servidor MCP de datos y las 5 tools SQL
├── agent_core.py             # LangChain, modelo, memoria y orquestación
├── mcp_agente.py              # servidor MCP que empaqueta la capacidad agente
├── app_streamlit.py          # cliente visual propio
├── data/
│   ├── ecommerce_orders.csv  # dataset fuente
│   ├── build_db.py           # script que genera el SQLite
│   └── ecommerce_demo.db     # (se genera al ejecutar build_db.py)
├── config/
│   └── claude_desktop_config.example.json
├── .env.example
├── requirements.txt
├── .gitignore
└── README.md
```

## Las 5 tools del MCP de datos

| Tool | Qué responde |
|---|---|
| `calcular_perfil_riesgo_cliente(customer_id)` | Historial de devolución de un cliente |
| `comparar_cliente_vs_segmento(customer_id)` | Cliente vs. promedio de su segmento |
| `identificar_factores_riesgo_categoria(product_category)` | Qué diferencia devueltas vs. no devueltas en una categoría |
| `calcular_score_riesgo_orden(product_category, delivery_days, discount_percent, coupon_used)` | Heurística transparente de probabilidad de devolución |
| `listar_ordenes_activas_en_riesgo(umbral_pct, limite)` | Órdenes `Processing`/`Shipped` a intervenir hoy |

> **Nota metodológica**: `calcular_score_riesgo_orden` y
> `listar_ordenes_activas_en_riesgo` usan una regla ponderada y transparente
> (tasa histórica de la categoría × multiplicador por días de entrega
> extremos), **no** un modelo de Machine Learning entrenado. El análisis
> exploratorio que fundamenta estos pesos está documentado en el notebook
> original de la Clase 2.

## Variables de entorno relevantes

| Variable | Rol |
|---|---|
| `OPENAI_API_KEY` | Credencial del modelo |
| `OPENAI_MODEL` | Modelo usado por `ChatOpenAI` |
| `DATA_MCP_URL` | Dónde vive el MCP de datos |
| `MCP_AGENT_TRANSPORT` | `http` (Streamlit) o `stdio` (Claude Desktop) |
| `MEMORY_WINDOW_MESSAGES` | Cuántos mensajes recientes se reenvían al modelo |

## Solución de problemas

- **Streamlit no puede contactar al agente**: verifica que `mcp_datos.py`
  Y `mcp_agente.py` (en modo `http`) estén corriendo antes de abrir
  Streamlit.
- **Claude Desktop no descubre la tool**: confirma que
  `MCP_AGENT_TRANSPORT=stdio` en la configuración, que la ruta del script
  es absoluta, y reinicia Claude Desktop por completo.
- **La memoria no se conserva entre preguntas**: confirma que estás usando
  el mismo `session_id` (en Streamlit, no hagas clic en "Nueva
  conversación" entre preguntas relacionadas).