Skip to content

fix: conectar el Streamlit del backend con el motor real + README honesto#5

Merged
juandmg020407 merged 3 commits into
mainfrom
fix/backend-streamlit-integration
May 27, 2026
Merged

fix: conectar el Streamlit del backend con el motor real + README honesto#5
juandmg020407 merged 3 commits into
mainfrom
fix/backend-streamlit-integration

Conversation

@juandmg020407
Copy link
Copy Markdown
Collaborator

Por qué este PR existe

Tras los merges de feat/llm-chatbot-frontend (#3) y feat/backend-optimization (#4), una auditoría del estado de main reveló tres problemas que el README escondía:

  1. app/main.py era un mock obsoleto del primer commit, con DEMO_DATA hardcoded de 5 pedidos y sin un solo import de src/. El comentario "se eliminan cuando Samuel entregue el CSV" no se había cumplido. Si el jurado seguía las instrucciones del README al pie de la letra, ejecutaba este mock y se llevaba la impresión de que el backend no hacía nada.
  2. optimizar_rutas.py (raíz) era código huérfano del primer commit, no importado por nada.
  3. data/pedidos.csv tenía esquema incompatible con DataProcessor (separador ;, columna peso en lugar de peso_kg, prioridades como strings).
  4. src/test_run.py tenía hardcoded la ruta absoluta del Mac del autor original (/Users/samuelparraechague/...), por lo que solo funcionaba en su máquina.
  5. El README presumía de "integración" cuando en realidad backend y frontend coexisten sin hablarse.

Este PR resuelve los cinco puntos en tres commits.

Cambios

chore: eliminar código huérfano del primer commit (b62dce5)

Borrados optimizar_rutas.py y data/pedidos.csv. Tras esto hay un único dataset oficial (data/pedidos_ejemplo.csv) y un único motor oficial (src/optimizer.py).

fix(backend): usar paths relativos en test_run.py (142f3d7)

workspace_dir = "/Users/samuelparraechague/..." reemplazado por cálculo relativo a __file__. python src/test_run.py ahora funciona en Linux, macOS y Windows desde cualquier directorio de trabajo.

feat(app): reescribir Streamlit para usar el motor real de optimización (407ac89)

Nuevo app/main.py que sí conecta con src/. Lo que ve el jurado al abrir la URL:

  • Sidebar con selector de motor (Google OR-Tools / Heurística propia) y resumen del dataset cargado.
  • Cuadro de impacto en 4 métricas con delta vs baseline manual:
    • Distancia, Coste, CO₂, Retrasos.
  • Mapa Folium interactivo con depósito (icono industrial) + paradas coloreadas por vehículo con popup detallado + polyline cerrada por ruta.
  • Tabla de pedidos con código, cliente, prioridad, peso, franja.
  • Botón "Generar informe" que invoca AIAssistant.generate_explanation (Ollama local con fallback de plantillas dinámicas) y renderiza en markdown.
  • Manejo de errores: si los CSV/JSON faltan o están corruptos, mensaje claro en lugar de stack trace.
  • Cacheado con @st.cache_data para que cambios de motor no recarguen los datos.

Acompaña el código una sección reescrita del README:

  • Sustituido "OpenRoute combina dos piezas que pueden usarse de forma independiente o integrada" por una descripción honesta: dos componentes que se ejecutan por separado, integración HTTP marcada como siguiente iteración del roadmap.
  • Documentado claramente lo que verá el usuario al abrir Streamlit.
  • Añadidas instrucciones para python -m unittest src/test_optimizer.py -v y python src/test_run.py.
  • Aclarado que Ollama es opcional (con fallback de plantillas).

Cómo probarlo

git checkout fix/backend-streamlit-integration
pip install -r requirements.txt
ollama pull llama3.1:8b      # opcional, para el informe AI
streamlit run app/main.py

En la URL que muestra Streamlit, juega con el sidebar (cambia motor), expande el "Detalle por vehículo", abre popups del mapa y pulsa "Generar informe".

cc: @echeguate @giulianpeter

Tres archivos legacy que ningún módulo importa ni usa, removidos para
evitar confusión al jurado y a contribuyentes nuevos:

- optimizar_rutas.py (raíz): implementación inicial standalone de
  OR-Tools del primer commit, sustituida en su día por src/optimizer.py
  (motor dual heurística + OR-Tools con patrón Strategy). No estaba
  importado desde ningún sitio.
- data/pedidos.csv: dataset antiguo con separador ';', columna 'peso'
  en lugar de 'peso_kg', prioridades como strings ("Media"/"Alta"/"Baja").
  Incompatible con DataProcessor que espera coma y enteros. Sustituido
  por data/pedidos_ejemplo.csv (mismo número de filas, esquema correcto,
  direcciones reales de Elche y Alicante).

Tras este commit, hay un único dataset oficial (pedidos_ejemplo.csv)
y un único motor oficial (src/optimizer.py).
El script tenía hardcoded una ruta absoluta al Mac del autor original
("/Users/samuelparraechague/Developer/3_Workspace_Cloudecode") que
hacía que el test end-to-end solo funcionara en su máquina.

Ahora se calcula la raíz del repositorio a partir de __file__ del
propio script, por lo que `python src/test_run.py` funciona en
cualquier sistema (Linux, macOS, Windows) y desde cualquier directorio
de trabajo siempre que el árbol del repo esté intacto.
El app/main.py anterior era un mock del primer commit con DEMO_DATA
hardcoded (5 pedidos ficticios) y un comentario "se eliminan cuando
Samuel entregue el CSV" que nunca se cumplió. NO importaba nada de
src/, no optimizaba nada, no llamaba a OR-Tools ni al asistente IA.

Si el jurado seguía el README al pie de la letra, ejecutaba ese mock
y se iba pensando que el backend "no hace nada".

Este commit lo reemplaza por un panel Streamlit completo que SÍ conecta
con el motor de Samuel y demuestra el valor real del producto.

QUÉ HACE EL NUEVO app/main.py

1. Carga data/pedidos_ejemplo.csv y data/vehiculos_config.json mediante
   src.data_processor.DataProcessor (con @st.cache_data para evitar
   recargas innecesarias en rerun).
2. Construye matrices de distancia/tiempo Haversine ajustadas.
3. Permite al gestor elegir motor en el sidebar:
   - Google OR-Tools (CVRPTW industrial), por defecto.
   - Heurística propia (K-Means + VMC ponderado por prioridad).
4. Ejecuta automáticamente el baseline manual (3 heurísticas humanas)
   y el optimizador elegido, y compara con MetricsEngine.compare_plans.
5. Muestra un cuadro de impacto en 4 columnas (km, €, CO₂, retrasos)
   con deltas frente al baseline.
6. Renderiza un mapa Folium interactivo con:
   - Depósito como icono industrial negro.
   - Paradas coloreadas por vehículo asignado, con popup detallado
     (cliente, hora, ventana, peso, prioridad).
   - Polyline coloreada conectando depósito → paradas → depósito.
7. Tabla compacta de pedidos a la derecha del mapa.
8. Botón "Generar informe" que invoca AIAssistant.generate_explanation
   (Ollama local, con fallback a plantillas heurísticas dinámicas)
   y renderiza el resultado en markdown.
9. Manejo de errores: si los CSV/JSON faltan o están corruptos,
   muestra un mensaje claro en lugar de petar con stack trace.

Acompaña este cambio una sección reescrita del README en "Guía de
Instalación y Uso" que:

- Aclara que Ollama es opcional (con fallback de plantillas).
- Documenta lo que el usuario verá al abrir la URL.
- Añade instrucciones para correr los tests (unittest + test_run.py).
- Sustituye el bloque "OpenRoute combina dos piezas que pueden usarse
  de forma independiente o integrada" por una descripción HONESTA del
  estado actual: dos componentes que se ejecutan por separado, con la
  integración HTTP marcada como siguiente iteración del roadmap.
@juandmg020407 juandmg020407 merged commit 11a5587 into main May 27, 2026
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