IA abierta y explicable para la optimización logística de última milla en pymes.
El problema real de la logística local no es calcular una ruta de A a B. El verdadero reto para las pymes es ordenar decenas de entregas con restricciones de tiempo y capacidad, repartirlas entre vehículos y justificar esas decisiones de forma transparente.
OpenRoute democratiza las capacidades de planificación que usan los grandes operadores. Convertimos una simple lista de pedidos (CSV) en rutas optimizadas, explicables en lenguaje natural y totalmente accionables desde una interfaz unificada.
OpenRoute presenta un único producto al usuario: el frontend conversacional Next.js, donde un chatbot LLM local actúa como centro de comandos. Por detrás conviven dos motores de optimización:
| Componente | Función | Cómo se invoca | Cuándo se usa |
|---|---|---|---|
Frontend conversacional (web/) |
Next.js 14 + chatbot Ollama + mapa Leaflet + Prisma/SQLite. UI única que ven los usuarios. | cd web && npm run dev (puerto 3000) |
Siempre. Es la cara del producto. |
Microservicio FastAPI (app/) |
Wrapper HTTP sobre el motor VRP de Python (src/). Expone /health, /optimize, /baseline, /compare, /optimize-csv. |
uvicorn app.main:app --port 8000 |
Cuando el chatbot llama al tool optimize_with_ortools o el usuario sube un CSV desde /import. |
Motor Python (src/) |
Solver VRP dual: heurística propia (K-Means + VMC) + Google OR-Tools (CVRPTW). Procesador de datos, simulador baseline manual y asistente IA con Ollama. | Llamado por el FastAPI internamente | Cuando se pide optimización industrial con time windows y capacidades. |
| Ollama local | LLM llama3.2:3b con tool calling (configurable vía OLLAMA_MODEL). Mismo modelo para el chatbot del frontend y para los informes explicativos del motor Python. |
ollama serve (puerto 11434) |
Continuamente mientras el chatbot está en uso. |
Flujo típico:
- El despachador escribe "Optimiza el día con OR-Tools" al chatbot del frontend.
- El LLM invoca el tool
optimize_with_ortools. - Next.js (
web/src/lib/python-optimizer.ts) hace POST a:8000/comparecon los pedidos y vehículos actuales de la DB. - El FastAPI llama a
src/optimizer.pyy devuelve plan + baseline + ahorros. - El chatbot resume el resultado en lenguaje natural; el frontend pinta la ruta con polyline real por calles vía OSRM.
Para rutas rápidas con pocas paradas (≤10) el chatbot también puede usar el tool suggest_routes, que resuelve un TSP simple directamente con OSRM /trip sin necesidad de arrancar el backend Python.
Ver docs/ARCHITECTURE.md para el detalle técnico.
- Chatbot como UI principal: el LLM no es un añadido, es la forma natural de operar. "Sugiere rutas para hoy", "Optimiza con OR-Tools", "Asigna la opción B a Juan", "Mi furgo se ha averiado, 60 minutos".
- Dos motores de optimización combinables: TSP rápido (OSRM) integrado, o VRP industrial (Google OR-Tools) cuando hay restricciones estrictas. El chatbot decide o el usuario lo pide explícitamente.
- IA Explicativa (XAI): el motor Python no es una caja negra. Cuando se invoca, devuelve métricas frente a un plan manual baseline (ahorro de km, €, CO₂, retrasos evitados).
- Privacidad por diseño: Ollama corre 100% local, los datos del cliente no salen de la máquina.
- Mapa real: Leaflet + OSRM dibujan la ruta optimizada por calles reales, no líneas rectas.
- Auto-gestión de averías: ante una avería, el chatbot reoptimiza la ruta restante, mueve pedidos al día siguiente y comunica las nuevas ETAs en una sola frase.
- Auditoría completa: cada turno del chatbot queda registrado con sus tool calls para reproducibilidad y trazabilidad.
- Next.js 14 (App Router) + TypeScript + Tailwind + shadcn/ui.
- Prisma + SQLite (cambio a Postgres con una variable de entorno).
- Leaflet + OpenStreetMap + OSRM público para mapa y TSP rápido.
- Nominatim de OSM para geocoding con caché persistente.
- Ollama con
llama3.2:3bpor defecto (configurable víaOLLAMA_MODEL, soportallama3.1:8bpara entornos con GPU o más CPU). Tool calling nativo y fiable. El 3b llama a las herramientas correctamente sin alucinar datos como hacen modelos más pequeños. - JWT en cookie
httpOnlypara auth.
- FastAPI + uvicorn como microservicio HTTP.
pandasynumpypara procesamiento de datos.- Google OR-Tools (CVRPTW industrial) en
src/optimizer.py. - Heurística académica propia (K-Means + Vecino Más Cercano Ponderado) como alternativa.
- Matriz de distancias OSRM
/tablepor defecto (callejero real); fallback automático a Haversine × factor urbano si OSRM no responde (src/osrm_client.py). Desactivable conOPENROUTE_DISABLE_OSRM=1para entornos sin red. - Bounding box configurable (
OPENROUTE_BBOX="lat_min,lat_max,lon_min,lon_max"oworldwide): por defecto Alicante/Elche, pero cualquier pyme puede operar en su propia zona sin tocar código. La pantalla/importtambién lo expone como selector. - Cliente Ollama propio en
src/ai_assistant.pypara generar informes en lenguaje natural.
Arquitectura detallada en docs/ARCHITECTURE.md.
OpenRoute necesita tres procesos en paralelo: el frontend Next.js, el microservicio Python y Ollama. Tienes dos caminos:
- Opción A — Docker (recomendada): un único comando arranca todo. Ideal para que el jurado o una pyme prueben OpenRoute sin instalar nada.
- Opción B — Local (desarrollo): tres terminales, control total, ideal si quieres iterar el código.
Atajo (Windows, opción B): una vez instaladas las dependencias (pasos 2A, 2B, 2C),
.\start.ps1desde la raíz verifica los prerrequisitos y arranca FastAPI + Next.js automáticamente. Ollama se asume corriendo como servicio. Ahorra abrir 3 terminales.
Requisitos: Docker y Docker Compose instalados (incluidos en Docker Desktop).
Antes de arrancar: en Docker Desktop → Settings → Resources, asigna mínimo 6 GB de RAM y 4 CPUs. Con menos, el chatbot puede colgarse al cargar el modelo en memoria.
git clone https://github.com/ComunidadIA-OS/OpenRoute.git
cd OpenRoute
docker compose up --buildEl primer arranque tarda 10-20 minutos:
- Pull de imágenes base (
python:3.12-slim,node:20-alpine,ollama/ollama): ~3 min. - Build de las imágenes del motor y el frontend: ~4 min (el seed de la DB ocurre durante el build).
- El servicio
ollama-pulldescargallama3.2:3b(~2 GB, modelo activo por defecto) yllama3.2:1b(~1.3 GB) como alternativa rápida: ~5-10 min según la red.
Mientras se descarga el modelo el frontend está accesible, pero el chat dará error hasta que termine.
Para seguir el progreso del download:
docker compose logs -f ollama-pullCuando aparezca [ollama-pull] Modelos listos. Saliendo., ya está. Verifica con:
docker compose ps # los 3 servicios en (healthy)
docker exec openroute-ollama ollama list # debe listar llama3.2:3b (y opcionalmente llama3.2:1b)Tras eso:
- Frontend: http://localhost:3000 (login
admin / admin123). - API del motor: http://localhost:8000/docs.
- Ollama: http://localhost:11434.
Sobre el chatbot: corre 100% local sin GPU. La primera respuesta tras inactividad larga tarda 30-60 s (carga del modelo de 2 GB en RAM); las siguientes son de 15-30 s por iteración. Es deliberado: todo el procesamiento de los datos del cliente ocurre dentro de tu máquina, no se envía nada a la nube. Eso es lo que defendemos como IA responsable. Si dispones de GPU o más CPU, cambia
OLLAMA_MODELallama3.1:8bendocker-compose.yml(más capaz, también más lento sin acelerador).
Comandos útiles:
docker compose logs -f web # ver logs del frontend
docker compose logs -f optimizer # ver logs del motor VRP
docker compose down # parar (mantiene DB y modelos)
docker compose down -v # parar y borrar volúmenes (reset total)Detalles de configuración (bbox propio, OSRM auto-hospedado, etc.) en docker-compose.yml.
git clone https://github.com/ComunidadIA-OS/OpenRoute.git
cd OpenRoute# Descargar el modelo (una sola vez, ~2 GB)
ollama pull llama3.2:3b
# En Windows ya arranca como servicio. En macOS/Linux:
ollama serveRequisitos: Python 3.9+.
# Crear entorno virtual (recomendado)
python -m venv .venv
source .venv/bin/activate # macOS / Linux
.venv\Scripts\activate # Windows PowerShell
# Instalar dependencias
pip install -r requirements.txt
# Lanzar el microservicio FastAPI
uvicorn app.main:app --reload --port 8000Verifica que está vivo: http://localhost:8000/health debería devolver {"status":"ok",...}.
Los endpoints disponibles:
GET /health— comprobación.POST /optimize— devuelve el plan optimizado.POST /baseline— devuelve el plan manual de referencia.POST /compare— devuelve ambos + cuadro de ahorros (el que usa el chatbot).POST /optimize-csv— optimiza uno o varios CSVs sin tocar la DB.
# Suite unitaria (24 tests: schema, capacidad, ventanas, OSRM fallback,
# bbox configurable, serialización JSON sin numpy.bool)
OPENROUTE_DISABLE_OSRM=1 python -m unittest src/test_optimizer.py -v
# Test end-to-end con reporte comparativo en consola
python src/test_run.pyRequisitos: Node.js 20+, Ollama ya arrancado en el paso 2A (con llama3.2:3b descargado), conexión a internet (para OSRM y Nominatim públicos).
# Configurar la app (no hace falta volver a `ollama pull`, ya lo hiciste en 2A)
cd web
cp .env.example .env
# (revisa .env, ajusta JWT_SECRET en producción)
# Instalar dependencias y preparar la DB
npm install
npx prisma migrate dev
npm run db:seed
# Arrancar el servidor de desarrollo
npm run devAbre http://localhost:3000. Inicia sesión con admin / admin123.
Usuarios demo sembrados:
| Usuario | Contraseña | Rol | Furgoneta |
|---|---|---|---|
| admin | admin123 | ADMIN | — |
| despacho | despacho123 | ADMIN | — |
| juan | juan123 | DRIVER | 1234-ABC |
| maria | maria123 | DRIVER | 5678-DEF |
| carlos | carlos123 | DRIVER | 9012-GHI |
⚠️ Las contraseñas demo están publicadas a propósito. Cambiar antes de cualquier despliegue real.
- Login como
admin/admin123. - Pestaña Pedidos → tabla con 47 pedidos repartidos por Alicante (35 del día + 12 históricos).
- Pestaña Rutas → ya hay 2 rutas pre-asignadas (
RT-YYYY-MM-DD-Apara Juan,RT-YYYY-MM-DD-Bpara María). El seed las crea con el optimizador real, así que la demo arranca con el mapa poblado sin tocar el chat. - Click en una ruta → mapa Leaflet con polyline real por calles (OSRM) + marcadores numerados + panel lateral con paradas en orden óptimo y ETAs.
- Pestaña Importar → arrastra un CSV propio de la pyme (ej. el de
data/pedidos_ejemplo.csvu otro). Selecciona motor OR-Tools y Zona "Sin restricción" si no es Alicante/Elche. Verás el plan optimizado, los ahorros vs reparto manual y los pedidos diferidos. Pulsa "Importar al sistema" y los pedidos aparecen en/orders. - Pestaña Chat:
- "Sugiere rutas para hoy" → el LLM llama a
current_time, luegosuggest_routes, devuelve 3 opciones con resumen (entregas, distancia, duración). - "Asigna la opción C a Carlos" → el LLM crea una nueva ruta y la asigna.
- "Mi furgo se ha averiado en RT-..., 60 minutos" → el LLM reoptimiza la ruta restante, mueve los pedidos que ya no caben a mañana (
RESCHEDULED), registra incidencia, comunica las nuevas ETAs.
- "Sugiere rutas para hoy" → el LLM llama a
Sobre la velocidad del chat: corre 100% local con
llama3.2:3ben CPU sin GPU. Cada respuesta tarda 15-30 s — es el coste de no enviar datos a la nube. Para demos en hardware modesto, los pasos 1-5 son visuales e instantáneos; el paso 6 luce mejor con paciencia.
Este proyecto se desarrolla para el Hackathon "IA Responsable y Abierta en Industria" Mayo'26 organizado por la Secretaría de Estado de Digitalización e Inteligencia Artificial (SEDIA) y la Agencia Española de Supervisión de la Inteligencia Artificial (AESIA), en el marco de la Comunidad IA de Código Abierto, con la colaboración del EDIH de Aragón (ITA + Universidad de Zaragoza).
- Reto: soluciones de IA responsable y abierta aplicables en entornos industriales.
- TRL objetivo: TRL5 (validación de componente en entorno relevante).
- IA responsable: la autoevaluación de impacto en derechos humanos (HRIA) realizada con la herramienta del PNUD (https://hria.eu/#use-cases) se documenta en
docs/HRIA.md. - Compromiso: el código se publica bajo licencia Apache 2.0 y está pensado para ser auditable, reproducible y reutilizable por terceros. La política de divulgación responsable de vulnerabilidades vive en
SECURITY.md; el historial de cambios enCHANGELOG.md.
Lo que viene después del hackathon: ver docs/ROADMAP.md. Resumen:
- Corto plazo: integración Python ↔ web/ (el chatbot delega al OR-Tools), tests automatizados, CI/CD, Docker, migración a Postgres.
- Medio plazo: ficha técnica del conductor (KPIs), app móvil PWA, notificaciones al cliente, vista en tiempo real para el despachador.
- Largo plazo: multi-tenant, integración con ERPs y e-commerce, internacionalización.
¡Bienvenidas las contribuciones! Lee CONTRIBUTING.md para empezar. Áreas donde nos vendría bien ayuda:
- 🧪 Tests automatizados (ambos componentes)
- 🐳 Docker compose con todo levantado
- 🔗 Integración backend Python ↔ frontend web/ vía HTTP
- 🌍 Internacionalización
- ♿ Accesibilidad
- 📊 Ficha técnica del conductor
Este proyecto sigue el Contributor Covenant Code of Conduct.
OpenRoute se apoya en el ecosistema open source. Devolvemos visibilidad a los proyectos sobre los que está construido:
Backend Python:
- FastAPI (MIT) — microservicio HTTP del motor.
- Uvicorn (BSD-3) — servidor ASGI.
- pandas (BSD-3) — procesamiento de datos.
- NumPy (BSD-3) — cómputo numérico y matrices.
- Google OR-Tools (Apache 2.0) — solver VRP (CVRPTW).
- Pydantic (MIT) — validación de schemas del API.
Frontend web/:
- Next.js (MIT) — framework full-stack.
- Prisma (Apache 2.0) — ORM.
- Tailwind CSS (MIT) — estilos.
- shadcn/ui (MIT) — primitivos de UI accesibles.
- Leaflet (BSD-2) — librería de mapas.
- OpenStreetMap (ODbL) — datos cartográficos.
- OSRM (BSD-2) — motor de routing y TSP.
- Nominatim (GPL-2, usado como servicio externo) — geocoding.
- Ollama (MIT) — runtime local para LLMs.
- Llama 3.2 (Llama 3.2 Community License) — modelo de lenguaje.
- Lucide (ISC) — iconos.
- Zod (MIT) — validación de inputs.
Sin estos proyectos, OpenRoute no existiría. Si encuentras un bug en una de estas dependencias mientras contribuyes, abre un issue upstream — eso también es devolver.
Apache License 2.0 © 2026 Equipo OpenRoute.
Eres libre de usar, modificar y distribuir este software, incluso comercialmente, conservando el aviso de copyright y la licencia original.
- Issues y discusiones técnicas → GitHub Issues
- AUTORES → David Morales Samuel Parra Giulian Peterlecean