ahanbose commited on
Commit
1b5bb17
Β·
verified Β·
1 Parent(s): b80d0f6

Update src/app.py

Browse files
Files changed (1) hide show
  1. src/app.py +39 -61
src/app.py CHANGED
@@ -33,10 +33,17 @@ if str(ROOT) not in sys.path:
33
  for d in ["data/uploads", "data/faiss_index"]:
34
  Path(d).mkdir(parents=True, exist_ok=True)
35
 
36
- # ── Lazy imports (heavier deps) ────────────────────────────────────────────────
37
- from core.processor import (DocumentProcessor, extract_waste_series,
38
- extract_energy_series, extract_spjimr_metrics_raw)
39
- from core.consultant import ESGConsultant
 
 
 
 
 
 
 
40
 
41
  logging.basicConfig(level=logging.INFO)
42
  logger = logging.getLogger(__name__)
@@ -56,7 +63,7 @@ st.set_page_config(
56
  st.markdown("""
57
  <style>
58
  /* ── Import Fonts ── */
59
- @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700;900&family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@300;400;600&display=swap');
60
 
61
  /* ── Root Variables ── */
62
  :root {
@@ -299,14 +306,16 @@ with st.sidebar:
299
  # Consultant factory (cached per token)
300
  # ═══════════════════════════════════════════════════════════════════════════════
301
 
 
 
 
 
 
302
  def _get_consultant() -> ESGConsultant:
303
- if (
304
- st.session_state.consultant is None
305
- or not st.session_state.hf_token
306
- ):
307
- token = st.session_state.hf_token or "NO_TOKEN"
308
- st.session_state.consultant = ESGConsultant(hf_token=token)
309
- return st.session_state.consultant
310
 
311
 
312
  # ═══════════════════════════════════════════════════════════════════════════════
@@ -520,13 +529,10 @@ def page_dashboard():
520
  line=dict(color="#2ECC71", width=2), marker=dict(size=6)))
521
  _hline(fig_el)
522
  fig_el.update_layout(**LAYOUT, height=260,
523
- title=dict(text="Renewable Energy % Over Time", font=dict(color="#D4AF37")))
524
- # yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="Renewable %", range=[0, 115])
525
- fig_el.update_yaxes(
526
- gridcolor="rgba(255,255,255,0.06)",
527
- title="Renewable %",
528
- range=[0,115]
529
- )
530
  with st.expander("πŸ“‹ Energy Data Table"):
531
  st.dataframe(edf, width="stretch", hide_index=True)
532
 
@@ -566,11 +572,8 @@ def page_dashboard():
566
  fig_w.add_trace(go.Bar(x=periods, y=wdf["rainwater_kl"],
567
  name="Rainwater Harvesting", marker_color="#2ECC71"))
568
  fig_w.update_layout(**LAYOUT, barmode="stack", height=320,
569
- title=dict(text="Water by Source (Kilolitres)", font=dict(color="#D4AF37")))
570
- # yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kL")
571
- fig_el.update_yaxes(
572
- gridcolor="rgba(255,255,255,0.06)",
573
- title="kL")
574
  st.plotly_chart(fig_w, width="stretch")
575
 
576
  with wc2:
@@ -623,11 +626,8 @@ def page_dashboard():
623
  fig_wst.add_trace(go.Bar(x=periods, y=wst["disposed_kg"],
624
  name="Disposed (kg)", marker_color="#E74C3C", opacity=0.8))
625
  fig_wst.update_layout(**LAYOUT, barmode="group", height=320,
626
- title=dict(text="Waste Recovered vs Disposed (kg)", font=dict(color="#D4AF37")))
627
- # yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kg")
628
- fig_el.update_yaxes(
629
- gridcolor="rgba(255,255,255,0.06)",
630
- title="kg")
631
  st.plotly_chart(fig_wst, width="stretch")
632
 
633
  with wst2:
@@ -646,13 +646,8 @@ def page_dashboard():
646
  fig_rp.add_hline(y=50, line_dash="dot", line_color="#D4AF37",
647
  annotation_text="50% Target", annotation_font=dict(color="#D4AF37"))
648
  fig_rp.update_layout(**LAYOUT, height=320,
649
- title=dict(text="Waste Recovery Rate (%)", font=dict(color="#D4AF37")))
650
- # yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="%", range=[0, 110])
651
- fig_rp.update_yaxes(
652
- gridcolor="rgba(255,255,255,0.06)",
653
- title="%",
654
- range=[0, 110]
655
- )
656
  st.plotly_chart(fig_rp, width="stretch")
657
 
658
  # KPI cards
@@ -677,12 +672,8 @@ def page_dashboard():
677
  if col in wdf.columns:
678
  fig.add_trace(go.Bar(x=wdf["period"], y=wdf[col],
679
  name=name, marker_color=color, opacity=0.85))
680
- fig.update_layout(**LAYOUT, barmode="group", height=300)
681
- # yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kg")
682
- fig.update_yaxes(
683
- gridcolor="rgba(255,255,255,0.06)",
684
- title="kg"
685
- )
686
  st.plotly_chart(fig, width="stretch")
687
  else:
688
  st.info("No waste data detected. Upload your SPJIMR Environmental Metrics XLSX.")
@@ -774,13 +765,8 @@ def page_dashboard():
774
  _add_forecast_traces(fig_ef, list(edf_f["period"]), edf_f["renewable_pct"].values, fl, "#2ECC71", "Renewable %")
775
  _hline(fig_ef)
776
  fig_ef.update_layout(**LAYOUT, height=320,
777
- title=dict(text=f"Renewable Energy % Forecast (next {horizon} months)", font=dict(color="#D4AF37")))
778
- # yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="%", range=[0,115])
779
- fig_ef.update_yaxes(
780
- gridcolor="rgba(255,255,255,0.06)",
781
- title="%",
782
- range=[0,115]
783
- )
784
  st.plotly_chart(fig_ef, width="stretch")
785
 
786
  # Waste forecast
@@ -795,12 +781,8 @@ def page_dashboard():
795
  line=dict(color=color, width=2), marker=dict(size=5)))
796
  _add_forecast_traces(fig_wf, list(wst_f["period"]), wst_f[col].values, fl, color, name)
797
  fig_wf.update_layout(**LAYOUT, height=320,
798
- title=dict(text=f"Waste Forecast (next {horizon} months)", font=dict(color="#D4AF37")))
799
- # yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kg")
800
- fig_wf.update_yaxes(
801
- gridcolor="rgba(255,255,255,0.06)",
802
- title="kg"
803
- )
804
  st.plotly_chart(fig_wf, width="stretch")
805
 
806
  # Water forecast
@@ -814,12 +796,8 @@ def page_dashboard():
814
  line=dict(color="#3498DB", width=2), marker=dict(size=5)))
815
  _add_forecast_traces(fig_wtrf, list(wtr_f["period"]), wtr_f["total_kl"].values, fl, "#3498DB", "Total Water")
816
  fig_wtrf.update_layout(**LAYOUT, height=300,
817
- title=dict(text=f"Water Consumption Forecast (next {horizon} months)", font=dict(color="#D4AF37")))
818
- # yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kL")
819
- fig_wtrf.update_yaxes(
820
- gridcolor="rgba(255,255,255,0.06)",
821
- title="kL"
822
- )
823
  st.plotly_chart(fig_wtrf, width="stretch")
824
 
825
  if not has_fc:
 
33
  for d in ["data/uploads", "data/faiss_index"]:
34
  Path(d).mkdir(parents=True, exist_ok=True)
35
 
36
+ # Heavy deps imported lazily inside @st.cache_resource to avoid blocking startup
37
+ @st.cache_resource(show_spinner="⏳ Loading ESG engine…")
38
+ def _load_modules():
39
+ from core.processor import (DocumentProcessor, extract_waste_series,
40
+ extract_energy_series, extract_spjimr_metrics_raw)
41
+ from core.consultant import ESGConsultant
42
+ return DocumentProcessor, extract_waste_series, extract_energy_series, extract_spjimr_metrics_raw, ESGConsultant
43
+
44
+ # Unpack β€” this blocks only on first run, cached on all subsequent reruns
45
+ (DocumentProcessor, extract_waste_series,
46
+ extract_energy_series, extract_spjimr_metrics_raw, ESGConsultant) = _load_modules()
47
 
48
  logging.basicConfig(level=logging.INFO)
49
  logger = logging.getLogger(__name__)
 
63
  st.markdown("""
64
  <style>
65
  /* ── Import Fonts ── */
66
+ /* Fonts: system stack β€” avoids network round-trip on cold start */
67
 
68
  /* ── Root Variables ── */
69
  :root {
 
306
  # Consultant factory (cached per token)
307
  # ═══════════════════════════════════════════════════════════════════════════════
308
 
309
+ @st.cache_resource(show_spinner=False)
310
+ def _cached_consultant(token: str) -> ESGConsultant:
311
+ """One instance per unique token β€” cached across all reruns."""
312
+ return ESGConsultant(hf_token=token or "NO_TOKEN")
313
+
314
  def _get_consultant() -> ESGConsultant:
315
+ token = st.session_state.hf_token or ""
316
+ c = _cached_consultant(token)
317
+ st.session_state.consultant = c
318
+ return c
 
 
 
319
 
320
 
321
  # ═══════════════════════════════════════════════════════════════════════════════
 
529
  line=dict(color="#2ECC71", width=2), marker=dict(size=6)))
530
  _hline(fig_el)
531
  fig_el.update_layout(**LAYOUT, height=260,
532
+ title=dict(text="Renewable Energy % Over Time", font=dict(color="#D4AF37")),
533
+ yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="Renewable %", range=[0, 115]))
534
+ st.plotly_chart(fig_el, width="stretch")
535
+
 
 
 
536
  with st.expander("πŸ“‹ Energy Data Table"):
537
  st.dataframe(edf, width="stretch", hide_index=True)
538
 
 
572
  fig_w.add_trace(go.Bar(x=periods, y=wdf["rainwater_kl"],
573
  name="Rainwater Harvesting", marker_color="#2ECC71"))
574
  fig_w.update_layout(**LAYOUT, barmode="stack", height=320,
575
+ title=dict(text="Water by Source (Kilolitres)", font=dict(color="#D4AF37")),
576
+ yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kL"))
 
 
 
577
  st.plotly_chart(fig_w, width="stretch")
578
 
579
  with wc2:
 
626
  fig_wst.add_trace(go.Bar(x=periods, y=wst["disposed_kg"],
627
  name="Disposed (kg)", marker_color="#E74C3C", opacity=0.8))
628
  fig_wst.update_layout(**LAYOUT, barmode="group", height=320,
629
+ title=dict(text="Waste Recovered vs Disposed (kg)", font=dict(color="#D4AF37")),
630
+ yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kg"))
 
 
 
631
  st.plotly_chart(fig_wst, width="stretch")
632
 
633
  with wst2:
 
646
  fig_rp.add_hline(y=50, line_dash="dot", line_color="#D4AF37",
647
  annotation_text="50% Target", annotation_font=dict(color="#D4AF37"))
648
  fig_rp.update_layout(**LAYOUT, height=320,
649
+ title=dict(text="Waste Recovery Rate (%)", font=dict(color="#D4AF37")),
650
+ yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="%", range=[0, 110]))
 
 
 
 
 
651
  st.plotly_chart(fig_rp, width="stretch")
652
 
653
  # KPI cards
 
672
  if col in wdf.columns:
673
  fig.add_trace(go.Bar(x=wdf["period"], y=wdf[col],
674
  name=name, marker_color=color, opacity=0.85))
675
+ fig.update_layout(**LAYOUT, barmode="group", height=300,
676
+ yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kg"))
 
 
 
 
677
  st.plotly_chart(fig, width="stretch")
678
  else:
679
  st.info("No waste data detected. Upload your SPJIMR Environmental Metrics XLSX.")
 
765
  _add_forecast_traces(fig_ef, list(edf_f["period"]), edf_f["renewable_pct"].values, fl, "#2ECC71", "Renewable %")
766
  _hline(fig_ef)
767
  fig_ef.update_layout(**LAYOUT, height=320,
768
+ title=dict(text=f"Renewable Energy % Forecast (next {horizon} months)", font=dict(color="#D4AF37")),
769
+ yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="%", range=[0,115]))
 
 
 
 
 
770
  st.plotly_chart(fig_ef, width="stretch")
771
 
772
  # Waste forecast
 
781
  line=dict(color=color, width=2), marker=dict(size=5)))
782
  _add_forecast_traces(fig_wf, list(wst_f["period"]), wst_f[col].values, fl, color, name)
783
  fig_wf.update_layout(**LAYOUT, height=320,
784
+ title=dict(text=f"Waste Forecast (next {horizon} months)", font=dict(color="#D4AF37")),
785
+ yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kg"))
 
 
 
 
786
  st.plotly_chart(fig_wf, width="stretch")
787
 
788
  # Water forecast
 
796
  line=dict(color="#3498DB", width=2), marker=dict(size=5)))
797
  _add_forecast_traces(fig_wtrf, list(wtr_f["period"]), wtr_f["total_kl"].values, fl, "#3498DB", "Total Water")
798
  fig_wtrf.update_layout(**LAYOUT, height=300,
799
+ title=dict(text=f"Water Consumption Forecast (next {horizon} months)", font=dict(color="#D4AF37")),
800
+ yaxis=dict(gridcolor="rgba(255,255,255,0.06)", title="kL"))
 
 
 
 
801
  st.plotly_chart(fig_wtrf, width="stretch")
802
 
803
  if not has_fc: