File size: 3,287 Bytes
556524e
72e2b6e
 
556524e
 
 
 
 
 
 
 
72e2b6e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
556524e
72e2b6e
 
 
 
 
556524e
72e2b6e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
556524e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import importlib.util
from pathlib import Path

_client_path = Path(__file__).parent.parent / "api_client.py"
_spec = importlib.util.spec_from_file_location("api_client", _client_path)
_module = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(_module)
api_ab_stats = _module.api_ab_stats
api_drift = _module.api_drift
api_reset_monitoring = _module.api_reset_monitoring
require_api = _module.require_api

import streamlit as st

require_api()

st.title("Monitoring Dashboard")
st.caption("Live A/B test stats and data drift detection.")

st.subheader("A/B Test Stats")

if st.button("Refresh stats"):
    st.rerun()

try:
    stats = api_ab_stats()

    col1, col2 = st.columns(2)

    with col1:
        st.markdown(f"### Model A — `{stats['model_a']['model_name']}`")
        st.metric("Requests", stats["model_a"]["request_count"])
        st.metric("Avg Latency", f"{stats['model_a']['avg_latency_ms']:.2f} ms")
        st.metric("Avg Confidence", f"{stats['model_a']['avg_confidence']:.2%}")
        st.metric("OOS Rate", f"{stats['model_a']['oos_rate']:.2%}")

    with col2:
        st.markdown(f"### Model B — `{stats['model_b']['model_name']}`")
        st.metric("Requests", stats["model_b"]["request_count"])
        st.metric("Avg Latency", f"{stats['model_b']['avg_latency_ms']:.2f} ms")
        st.metric("Avg Confidence", f"{stats['model_b']['avg_confidence']:.2%}")
        st.metric("OOS Rate", f"{stats['model_b']['oos_rate']:.2%}")

    st.caption(f"Configured split: {stats['split']:.0%} to model B")

except Exception as e:
    st.warning(f"No A/B stats yet. Make some predictions on the Predict page first. ({e})")

if st.button("Reset A/B stats"):
    api_reset_monitoring()
    st.success("Stats reset.")
    st.rerun()

st.divider()
st.subheader("Data Drift Report")
st.caption("Compares reference traffic (initial baseline) against recent production traffic.")

if st.button("Run drift check"):
    try:
        with st.spinner("computing drift..."):
            drift = api_drift()

        col1, col2, col3 = st.columns(3)
        col1.metric("Drifted Columns", int(drift["drift_summary"].get("drifted_columns_count", 0)))
        col2.metric(
            "Confidence Drop",
            f"{drift['confidence_drift']['confidence_drop']:.2%}",
            delta=f"{-drift['confidence_drift']['confidence_drop']:.2%}",
        )
        col3.metric("OOS Rate Increase", f"{drift['oos_rate_drift']['oos_rate_increase']:.2%}")

        if drift["confidence_drift"]["is_degraded"]:
            st.error("Confidence has degraded significantly vs reference traffic.")
        else:
            st.success("Confidence is stable vs reference traffic.")

        if drift["oos_rate_drift"]["is_anomalous"]:
            st.error("OOS rate has increased anomalously — possible topic drift in incoming queries.")
        else:
            st.success("OOS rate is within normal range.")

        with st.expander("Raw drift details"):
            st.json(drift)

    except Exception as e:
        st.warning(
            "No reference/current data available yet. Run `verify_phase11.py` first to "
            f"generate baseline monitoring data. ({e})"
        )