Skip to content

feat: backend de optimización OpenRoute con motor VRP, métricas e IA local#4

Merged
juandmg020407 merged 13 commits into
mainfrom
feat/backend-optimization
May 26, 2026
Merged

feat: backend de optimización OpenRoute con motor VRP, métricas e IA local#4
juandmg020407 merged 13 commits into
mainfrom
feat/backend-optimization

Conversation

@juandmg020407
Copy link
Copy Markdown
Collaborator

Resumen

Integración a main del backend de optimización completo de OpenRoute, desarrollado principalmente por @samuelparraechague (8 commits) + 3 commits de ajuste post-review por @juandmg020407 (migración LLM, limpieza personal, limpieza de PDFs) + merge commit con resolución de conflictos.

Por qué este PR usa una rama derivada de main

La rama original feature/openroute-backend se creó como historia git independiente y GitHub no permitía el PR directo ("main and feature/openroute-backend are entirely different commit histories"). Para no perder los commits de Samuel ni la atribución, se ha creado esta nueva rama feat/backend-optimization derivada de main con un merge --allow-unrelated-histories. El resultado es funcionalmente idéntico: trae todo el backend al main actual.

Lo que entra en main

Motor VRP (carpeta src/)

  • optimizer.py — solver dual con patrón Strategy: heurística propia (clustering K-Means + VMC ponderado) y Google OR-Tools (CVRPTW industrial). Fallback automático.
  • data_processor.py — limpieza, validación y matrices Haversine ajustadas (×1.3 para callejero urbano).
  • metrics.py — simulador baseline manual con 3 heurísticas humanas + cálculo de ahorros.
  • ai_assistant.py — generador de informes en lenguaje natural con Ollama local (mismo modelo que el frontend) + fallback de plantillas heurísticas dinámicas.
  • test_optimizer.py, test_run.py — suite de tests unitarios y test end-to-end.

Datos (carpeta data/)

  • pedidos_ejemplo.csv — 30 pedidos reales en Elche + Alicante con coords precisas.
  • vehiculos_config.json — 3 furgonetas (eléctrica, diésel, apoyo) con capacidad y coste/km.

Módulos reutilizables (carpeta skills/)

  • 1_data_cleaning/clean_orders.py
  • 2_eda/eda_report.py
  • 3_models/route_optimizer_skill.py

Documentación

  • docs/BACKEND_INTEGRATION.md — guía técnica de 3 pasos para consumir el motor desde Streamlit, FastAPI o cualquier otra app Python.

requirements.txt actualizado

Inventario completo: numpy, pandas, ortools, streamlit, folium, streamlit-folium, requests.

Impacto medido sobre 30 pedidos en Elche+Alicante con 3 furgonetas

Métrica Manual (baseline) OpenRoute Ahorro
Distancia 373.51 km 172.39 km −53.8%
Coste € 88.39 44.94 −49.2%
CO2 kg 82.17 37.93 −53.8%
Tiempo h 25.12 18.45 −26.6%

Cambios añadidos antes del merge (sobre los commits originales de Samuel)

1. Migración Gemini API → Ollama local (commit f27fa5f)

ai_assistant.py ahora usa el mismo LLM open source local (llama3.1:8b) que el frontend. Sin GEMINI_API_KEY, sin internet, sin coste. Coherente con "IA Responsable y Abierta" del hackathon.

2. Fix en plantilla de respaldo (commit f27fa5f)

  • Eliminada la referencia personal "Recomendación de Impacto para Samuel Parra" en _generate_local_explanation.
  • Sustituidos valores hardcodeados (VAN-01, VAN-02, 12.50 €, 32%) por cálculo dinámico desde data['vehiculos'].

3. Limpieza del README de la rama (commit dd8d34e)

  • El README.md antiguo mezclaba info personal con guía técnica.
  • Guía técnica útil → docs/BACKEND_INTEGRATION.md (actualizada al nuevo API de AIAssistant).
  • El README principal de main (ampliado en PR Feat/llm chatbot frontend #3) cubre el proyecto completo.

4. Limpieza de archivos personales (commit 65dbcbd)

  • Eliminado .cloudecode_rules (reglas personales del autor para su IDE).
  • Eliminada carpeta OpenRoute/ con PDFs de SEDIA (copyright de la organización) y PDFs internos del equipo (quedan en historial git).

Cómo probarlo

# 1. Modelo Ollama (una sola vez, ~5GB)
ollama pull llama3.1:8b

# 2. Dependencias Python
pip install -r requirements.txt

# 3. Tests unitarios
cd src && python -m unittest test_optimizer.py -v

# 4. Test end-to-end con reporte comparativo
python src/test_run.py

cc: @echeguate @giulianpeter

Co-authored-by: Samuel Parra parrasamuel453@gmail.com

Samuel Parra and others added 13 commits May 25, 2026 14:09
…plantilla

Este cambio unifica el sistema de IA del proyecto en un único LLM open
source local (Ollama llama3.1:8b), el mismo que ya utiliza el frontend
conversacional. Tres motivaciones:

1. Coherencia con el espíritu del hackathon "IA Responsable y Abierta":
   Gemini es un modelo propietario de Google. Usar un LLM local
   open source es más alineado con la filosofía del reto.
2. Reproducibilidad: el usuario que clona el repo ya no necesita una
   GEMINI_API_KEY para ver el "wow" del informe en lenguaje natural.
   Funciona sin internet y sin coste.
3. Un solo LLM en todo el sistema → menos modelos que mantener, mismo
   prompt engineering, mismas garantías de privacidad (los datos del
   cliente no salen de la máquina).

CAMBIOS PRINCIPALES

src/ai_assistant.py:

- Nueva clase OllamaClient con métodos .ping() (verifica que Ollama
  responde y el modelo está disponible) y .generate(prompt) (POST
  /api/chat non-streaming). Configurable vía OLLAMA_BASE_URL y
  OLLAMA_MODEL con defaults razonables (localhost:11434, llama3.1:8b).
- AIAssistant.__init__ instancia OllamaClient y hace ping en el arranque
  para activar el flag _llm_available. Si falla, advertencia en stdout
  y todas las llamadas caerán al fallback local.
- _call_gemini_api renombrado a _call_llm. El prompt no se modifica
  (estaba bien diseñado), solo cambia la capa de transporte.
- Eliminado import google.generativeai, eliminado uso de
  GEMINI_API_KEY.

src/ai_assistant.py — Fix adicional en _generate_local_explanation:

La sección "💡 Recomendación de Impacto" del fallback tenía dos
problemas que aprovecho para corregir junto con la migración:

- "Recomendación de Impacto para Samuel Parra" → eliminada la
  referencia personal. El informe es para el gerente PYME, no para el
  desarrollador.
- Valores hardcodeados (VAN-01, VAN-02, 12.50 €, 32%) → reemplazados
  por un cálculo dinámico que identifica el vehículo más caro y el más
  eficiente en €/km a partir de data['vehiculos'], y estima el ahorro
  potencial de redistribuir un 25% de la carga. Si la flota tiene
  eficiencia homogénea, muestra un mensaje neutro alternativo.

requirements.txt (nuevo):

Inventario claro de las dependencias del backend Python:
  numpy, pandas, ortools, streamlit, folium, streamlit-folium, requests.
Antes no existía como archivo en esta rama; era necesario para que un
tercero pueda reproducir el entorno con `pip install -r requirements.txt`.
El README.md de esta rama contenía:
  1. Las primeras 20 líneas: descripción del entorno de desarrollo personal
     del autor (paths /Users/samuelparraechague/..., perfil de estudiante,
     especificaciones de su Mac M5). Esto no debe estar en main bajo
     ningún concepto.
  2. A partir de la línea 24: una guía técnica útil de cómo integrar el
     motor logístico desde Streamlit u otra aplicación.

Acciones:

- ELIMINADO README.md: no aporta valor al proyecto público y va a crear
  un conflicto de merge contra el README ampliado del frontend
  (feat/llm-chatbot-frontend) que cubre todo el proyecto.
- AÑADIDO docs/BACKEND_INTEGRATION.md: contiene la guía técnica
  depurada de la parte útil, con:
  - Arquitectura de archivos core.
  - Integración en 3 pasos (cargar datos, optimizar, generar informe).
  - Snippet de Python actualizado al nuevo API de AIAssistant
    (sin parámetro api_key, ahora usa Ollama local por defecto).
  - Esquema de salida JSON unificado documentado.
  - Próximos pasos de integración con el frontend Next.js.
- Mantenido el crédito a Samuel Parra como autor del motor.

Tras este commit, al mergear ambos PRs (feat/llm-chatbot-frontend +
feature/openroute-backend) a main:
  - El README principal queda como el ampliado del frontend (cubre
    backend + frontend + sector + impacto + agradecimientos + licencia).
  - docs/BACKEND_INTEGRATION.md aporta los detalles técnicos de cómo
    consumir el motor de Samuel desde código.
  - Cero conflicto.
Tres bloques de limpieza para dejar la rama lista para merge a main
sin ruido:

1. ELIMINADO .cloudecode_rules
   Archivo con reglas personales del autor para su IDE/agente local
   (paths /Users/.../Developer/, su versión específica de Python,
   convenciones personales de carpetas). No aporta al proyecto público.

2. ELIMINADA carpeta OpenRoute/ completa (~5 MB):
   - PPT - Formación Código Abierto.pdf (2.8 MB) y
     Términos y condiciones - Hackathon Aragón.pdf (445 KB):
     material proporcionado por SEDIA/AESIA, copyright de la
     organización del hackathon. No debe redistribuirse en un repo
     público sin permiso explícito. El jurado ya tiene estos documentos.
   - OpenRoutePyME_esquema_inicio_hackathon.pdf (70 KB) y
     OpenRoutePyME_propuesta_hackathon.pdf (916 KB):
     documentos internos del equipo de fases previas al desarrollo.
     Quedan accesibles en el historial git si se necesitan.
   - walkthrough.html (633 KB) y walkthrough.md (7 KB):
     ya cubiertos por docs/BACKEND_INTEGRATION.md y por el README
     ampliado del PR de frontend.

3. CONFIRMADO requirements.txt como inventario oficial de dependencias
   del backend Python (numpy, pandas, ortools, streamlit, folium,
   streamlit-folium, requests).

Resultado: la rama solo contiene código (src/), datos (data/),
módulos reutilizables (skills/) y documentación útil (docs/), lista
para mergear sin conflictos contra feat/llm-chatbot-frontend.
La rama feature/openroute-backend, donde @samuelparraechague desarrolló
el motor de optimización VRP, se creó como historia git independiente
(no parte de un ancestro común con main). Por ello GitHub no permitía
el PR directo: "main and feature/openroute-backend are entirely different
commit histories".

Solución: merge manual con --allow-unrelated-histories sobre una nueva
rama feat/backend-optimization derivada del main actual. Esto produce
una rama con historia coherente y reaplicable como PR estándar al main.

CONFLICTOS RESUELTOS

- .gitignore: conservar versión de main (es superset, ya cubre Python
  + Node + Next.js + SQLite + secretos).
- requirements.txt: conservar versión de feature/openroute-backend
  (añade numpy, ortools y requests; incluye todas las dependencias
  que ya tenía main + las nuevas del optimizador y del cliente Ollama).

CONTENIDO QUE ENTRA A MAIN

- src/optimizer.py, src/data_processor.py, src/metrics.py,
  src/ai_assistant.py, src/test_optimizer.py, src/test_run.py:
  motor VRP dual (heurística propia + Google OR-Tools), procesador de
  datos con matrices Haversine ajustadas, simulador baseline manual,
  asistente IA con Ollama local y tests unitarios.
- data/pedidos_ejemplo.csv (30 pedidos en Elche+Alicante con coords
  reales) y data/vehiculos_config.json (3 furgonetas).
- skills/1_data_cleaning/, skills/2_eda/, skills/3_models/:
  módulos reutilizables académicos.
- docs/BACKEND_INTEGRATION.md: guía de integración del motor.

Tras este merge, main contiene el sistema completo:
  - Frontend Next.js + chatbot LLM en web/ (mergeado en PR #3).
  - Backend Python con VRP + Ollama en src/, data/, skills/.
  - Documentación unificada en docs/.

Co-authored-by: Samuel Parra <parrasamuel453@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant