feat: backend de optimización OpenRoute con motor VRP, métricas e IA local#4
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resumen
Integración a
maindel 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-backendse 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 ramafeat/backend-optimizationderivada demaincon un merge--allow-unrelated-histories. El resultado es funcionalmente idéntico: trae todo el backend almainactual.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.py2_eda/eda_report.py3_models/route_optimizer_skill.pyDocumentació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.txtactualizadoInventario completo:
numpy,pandas,ortools,streamlit,folium,streamlit-folium,requests.Impacto medido sobre 30 pedidos en Elche+Alicante con 3 furgonetas
Cambios añadidos antes del merge (sobre los commits originales de Samuel)
1. Migración Gemini API → Ollama local (commit
f27fa5f)ai_assistant.pyahora usa el mismo LLM open source local (llama3.1:8b) que el frontend. SinGEMINI_API_KEY, sin internet, sin coste. Coherente con "IA Responsable y Abierta" del hackathon.2. Fix en plantilla de respaldo (commit
f27fa5f)_generate_local_explanation.data['vehiculos'].3. Limpieza del README de la rama (commit
dd8d34e)README.mdantiguo mezclaba info personal con guía técnica.docs/BACKEND_INTEGRATION.md(actualizada al nuevo API deAIAssistant).main(ampliado en PR Feat/llm chatbot frontend #3) cubre el proyecto completo.4. Limpieza de archivos personales (commit
65dbcbd).cloudecode_rules(reglas personales del autor para su IDE).OpenRoute/con PDFs de SEDIA (copyright de la organización) y PDFs internos del equipo (quedan en historial git).Cómo probarlo
cc: @echeguate @giulianpeter
Co-authored-by: Samuel Parra parrasamuel453@gmail.com