LeonardoMdSA commited on
Commit
700e2b6
·
1 Parent(s): 88260af
Dockerfile.hf DELETED
@@ -1 +0,0 @@
1
- # HF Spaces–compatible
 
 
app/api/routes.py CHANGED
@@ -44,14 +44,15 @@ async def predict_file(background_tasks: BackgroundTasks, file: UploadFile = Fil
44
  # Correctly get numeric drift scores per column
45
  _, drift_dict = run_drift_check(df[predictor.features], reference_df[predictor.features], "v1")
46
 
47
- # Ensure minimal values for chart and safe numeric handling
48
  drift_for_chart = []
49
  for col, score in drift_dict.items():
50
  try:
51
  score_value = float(score)
52
- score_value = max(score_value, 0.01)
 
53
  except Exception:
54
- score_value = 0.01
55
  drift_for_chart.append({"column": col, "score": score_value})
56
 
57
  # Schedule full drift in background as before
 
44
  # Correctly get numeric drift scores per column
45
  _, drift_dict = run_drift_check(df[predictor.features], reference_df[predictor.features], "v1")
46
 
47
+ # Ensure numeric drift values safe for frontend Plotly chart
48
  drift_for_chart = []
49
  for col, score in drift_dict.items():
50
  try:
51
  score_value = float(score)
52
+ if not np.isfinite(score_value):
53
+ score_value = 0.0
54
  except Exception:
55
+ score_value = 0.0
56
  drift_for_chart.append({"column": col, "score": score_value})
57
 
58
  # Schedule full drift in background as before
app/monitoring/drift.py CHANGED
@@ -1,4 +1,4 @@
1
- # Evidently logic
2
  import os
3
  import pandas as pd
4
  from evidently.report import Report
@@ -23,7 +23,7 @@ def run_drift_check(current_data: pd.DataFrame, reference_data: pd.DataFrame, mo
23
  """
24
  Run Evidently DataDriftPreset on current vs reference data,
25
  save HTML report, and run governance checks.
26
- Returns a tuple: (alerts, report_metrics)
27
  """
28
  os.makedirs(REPORT_DIR, exist_ok=True)
29
 
@@ -34,10 +34,22 @@ def run_drift_check(current_data: pd.DataFrame, reference_data: pd.DataFrame, mo
34
  # Extract numeric drift scores per column
35
  report_dict = report.as_dict() if hasattr(report, "as_dict") else {}
36
  drift_scores = {}
37
- for metric in report_dict.get("metrics", []):
38
- if metric["metric"] == "DataDriftMetric":
39
- for col_name, col_data in metric["result"].get("dataset_drift", {}).items():
40
- drift_scores[col_name] = col_data.get("drift_score", 0.0)
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  # Run governance checks (keeps existing alerts)
43
  alerts = governance.check_metrics(report_dict, model_version=model_version)
 
1
+ # app/monitoring/drift.py
2
  import os
3
  import pandas as pd
4
  from evidently.report import Report
 
23
  """
24
  Run Evidently DataDriftPreset on current vs reference data,
25
  save HTML report, and run governance checks.
26
+ Returns a tuple: (alerts, drift_scores)
27
  """
28
  os.makedirs(REPORT_DIR, exist_ok=True)
29
 
 
34
  # Extract numeric drift scores per column
35
  report_dict = report.as_dict() if hasattr(report, "as_dict") else {}
36
  drift_scores = {}
37
+
38
+ metrics_list = report_dict.get("metrics", [])
39
+
40
+ for metric in metrics_list:
41
+ result = metric.get("result", {})
42
+ # Check column-level drift
43
+ drift_by_columns = result.get("drift_by_columns", {})
44
+ if drift_by_columns:
45
+ for col, info in drift_by_columns.items():
46
+ score = info.get("drift_score", 0.0)
47
+ if score is None or not pd.notna(score):
48
+ score = 0.0
49
+ drift_scores[col] = float(score)
50
+ # fallback: Dataset-level drift metric (PSI share)
51
+ elif metric.get("metric") == "DatasetDriftMetric":
52
+ drift_scores["dataset"] = float(result.get("share_of_drifted_columns", 0.0))
53
 
54
  # Run governance checks (keeps existing alerts)
55
  alerts = governance.check_metrics(report_dict, model_version=model_version)
app/templates/dashboard.html CHANGED
@@ -21,46 +21,45 @@
21
  <div id="drift-chart"></div>
22
 
23
  <script>
24
- async function fetchResults(csvFile) {
25
- const formData = new FormData();
26
- formData.append("file", csvFile);
27
 
28
- const response = await fetch("/predict", {
29
- method: "POST",
30
- body: formData
31
- });
32
-
33
- const data = await response.json();
34
 
35
- /* ✅ FIX: API returns `results`, not `predictions` */
36
- document.getElementById("predictions").innerHTML =
37
- `<pre>${JSON.stringify(data.results, null, 2)}</pre>`;
38
 
39
- const driftContainer = document.getElementById("drift-chart");
40
- driftContainer.innerHTML = "";
41
 
42
- if (Array.isArray(data.drift)) {
43
- const cols = data.drift.map(d => d.column);
44
- const scores = data.drift.map(d => d.score);
 
 
 
 
45
 
46
- Plotly.newPlot(driftContainer, [{
47
- x: cols,
48
- y: scores,
49
- type: "bar"
50
- }]);
51
- } else {
52
- driftContainer.innerHTML =
53
- "<p>Drift report scheduled. Open the Evidently HTML report.</p>";
54
- }
55
  }
 
56
 
57
- document.getElementById("upload-form").addEventListener("submit", async (e) => {
58
- e.preventDefault();
59
- const fileInput = e.target.file.files[0];
60
- if (fileInput) {
61
- await fetchResults(fileInput);
62
- }
63
- });
64
  </script>
65
  </body>
66
  </html>
 
21
  <div id="drift-chart"></div>
22
 
23
  <script>
24
+ async function fetchResults(csvFile) {
25
+ const formData = new FormData();
26
+ formData.append("file", csvFile);
27
 
28
+ const response = await fetch("/predict", { method: "POST", body: formData });
29
+ const data = await response.json();
 
 
 
 
30
 
31
+ document.getElementById("predictions").innerHTML =
32
+ `<pre>${JSON.stringify(data.results, null, 2)}</pre>`;
 
33
 
34
+ const driftContainer = document.getElementById("drift-chart");
35
+ driftContainer.innerHTML = "";
36
 
37
+ if (Array.isArray(data.drift)) {
38
+ const cols = data.drift.map(d => d.column);
39
+ const scores = data.drift.map(d => {
40
+ let val = Number(d.score);
41
+ if (!Number.isFinite(val)) val = 0;
42
+ return val;
43
+ });
44
 
45
+ Plotly.newPlot(driftContainer, [{
46
+ x: cols,
47
+ y: scores,
48
+ type: "bar"
49
+ }]);
50
+ } else {
51
+ driftContainer.innerHTML =
52
+ "<p>Drift report scheduled. Open the Evidently HTML report.</p>";
 
53
  }
54
+ }
55
 
56
+ document.getElementById("upload-form").addEventListener("submit", async (e) => {
57
+ e.preventDefault();
58
+ const fileInput = e.target.file.files[0];
59
+ if (fileInput) {
60
+ await fetchResults(fileInput);
61
+ }
62
+ });
63
  </script>
64
  </body>
65
  </html>
open_drift.py DELETED
@@ -1,3 +0,0 @@
1
- import webbrowser
2
- report_path = r"C:\Users\Rayquaza\Desktop\IT\ML Inference Service with Drift Detection\reports\evidently\drift_report.html"
3
- webbrowser.open(f"file://{report_path}")
 
 
 
 
reports/evidently/drift_report.html CHANGED
The diff for this file is too large to render. See raw diff
 
scripts/evaluate.py DELETED
@@ -1 +0,0 @@
1
- # offline evaluation
 
 
scripts/run_drift_check.py DELETED
@@ -1 +0,0 @@
1
- # batch drift job