Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

114 roadmap create a UI for whitebox server using streamlit or similar tools #131

Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
85ddea2
Initialised streamlit dev
stavrostheocharis Feb 8, 2023
0ea94c0
Added Drift parts
stavrostheocharis Feb 10, 2023
a625120
App formating
stavrostheocharis Feb 11, 2023
fd9badc
Formated overview and drifting tabs
stavrostheocharis Feb 11, 2023
2e65d34
Additions
stavrostheocharis Feb 12, 2023
6bfc696
Added markdowns in functions
stavrostheocharis Feb 12, 2023
3cd5203
Removed unused imports from app
stavrostheocharis Feb 12, 2023
0031cb4
Inferences tab addition
stavrostheocharis Feb 15, 2023
3f9e3c8
Added style to inferences dataframe
stavrostheocharis Feb 15, 2023
4925535
Adjustments and additions
stavrostheocharis Feb 15, 2023
c97f2ff
Added monitors tab
stavrostheocharis Feb 16, 2023
99b2fab
Added alerts tab
stavrostheocharis Feb 16, 2023
e94d818
Added filters in alerts
stavrostheocharis Feb 17, 2023
3e69aad
Formating
stavrostheocharis Feb 17, 2023
8ce1019
Additions for different model types
stavrostheocharis Feb 17, 2023
035c478
Fixed types and name conventions
stavrostheocharis Feb 17, 2023
15e2e10
SDK connection to streamlit
stavrostheocharis Feb 20, 2023
2e6483a
Added sdk functionality in Streamlit
stavrostheocharis Feb 20, 2023
384a5ed
Added connection functionality in sidebar
stavrostheocharis Feb 20, 2023
424ee25
Additions
stavrostheocharis Feb 21, 2023
b086ad0
Adjusted expanders descriptions
stavrostheocharis Feb 21, 2023
10d0de3
Added cache functionality
stavrostheocharis Feb 21, 2023
7235d1a
Minor fixes
stavrostheocharis Feb 21, 2023
bb7e4f5
Additions/adjustments
stavrostheocharis Feb 23, 2023
65d513f
Deleted prints
stavrostheocharis Feb 23, 2023
0648112
Added error catch in inference log
stavrostheocharis Feb 23, 2023
4a1746e
Merge branch 'main' into 114-roadmap-create-a-ui-for-whitebox-server-…
stavrostheocharis Feb 23, 2023
9494457
Black formating
stavrostheocharis Feb 23, 2023
7b9f093
Black formating
stavrostheocharis Feb 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .streamlit/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[theme]
base="dark"
primaryColor="#21babe"
backgroundColor="#1e2025"
secondaryBackgroundColor="#252a33"

6 changes: 6 additions & 0 deletions whitebox/.streamlit/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[theme]
base="dark"
primaryColor="#21babe"
backgroundColor="#1e2025"
secondaryBackgroundColor="#252a33"

61 changes: 58 additions & 3 deletions whitebox/sdk/whitebox.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from enum import Enum
import numpy as np
import pandas as pd
from whitebox.schemas.model import ModelCreateDto, ModelType
from typing import Dict, Optional
from whitebox.schemas.model import ModelCreateDto, ModelType, ModelUpdateDto
from typing import Dict, Optional, Union
import requests
import logging
from fastapi import status
Expand Down Expand Up @@ -75,6 +75,35 @@ def get_model(self, model_id: str) -> dict:

return result.json()

def get_models(self) -> Union[dict, None]:
"""
Returns all the models. If no models exist, returns None.
"""
result = requests.get(
url=f"{self.host}/{self.api_version}/models",
headers={"api-key": self.api_key},
)
if result.status_code == status.HTTP_404_NOT_FOUND:
return None

return result.json()

def update_model(self, model_id: str, body: ModelUpdateDto):
"""
Updates a model by its id. If any error occurs, returns False.
"""
result = requests.put(
url=f"{self.host}/{self.api_version}/models/{model_id}",
json=body,
headers={"api-key": self.api_key},
)
logger.info(result.json())

if result.status_code == status.HTTP_200_OK:
return True

return False

def delete_model(self, model_id: str):
"""
Deletes a model by its id. If any error occurs, returns False.
Expand Down Expand Up @@ -169,6 +198,20 @@ def log_inferences(

return False

def get_inferences(self, model_id: str):
"""
Given a specific model id, this endpoint fetches all the inferences.
If some of the required data isn't found, returns None.
"""
result = requests.get(
url=f"{self.host}/{self.api_version}/inference-rows?model_id={model_id}",
headers={"api-key": self.api_key},
)
if result.status_code == status.HTTP_404_NOT_FOUND:
return None

return result.json()

def get_xai_row(self, inference_row_id: str):
"""
Given a specific inference row id, this endpoint produces an explainability report for this inference.
Expand All @@ -191,8 +234,8 @@ def create_model_monitor(
metric: MonitorMetrics,
severity: AlertSeverity,
email: str,
feature: Optional[str],
lower_threshold: Optional[float],
feature: Optional[Union[str, None]] = None,
) -> dict:
"""
Creates a monitor for a model.
Expand All @@ -218,6 +261,18 @@ def create_model_monitor(
logger.info(result.json())
return result.json()

def get_monitors(self, model_id: str) -> dict:
"""
Returns all monitors for a model.
"""
result = requests.get(
url=f"{self.host}/{self.api_version}/model-monitors?modelId={model_id}",
headers={"api-key": self.api_key},
)

logger.info(result.json())
return result.json()

def get_alerts(self, model_id: str = "") -> dict:
"""
Returns all alerts for a model.
Expand Down
95 changes: 95 additions & 0 deletions whitebox/streamlit/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import numpy as np
import pandas as pd
import streamlit as st
from typing import Dict, Union

from tabs.drifting import *
from tabs.sidebar import *
from tabs.overview import *
from tabs.performance import *
from tabs.inferences import *
from tabs.monitors import *
from tabs.alerts import *
from cards import *
from utils.transformation import get_model_from_name

from whitebox import Whitebox

# wb = Whitebox(
# host="http://127.0.0.1:8000",
# api_key="c37b902f5af13c43af33652770d7c51008f5e18b0cf4cf9cc870ab93bea98f3f",
# )
stavrostheocharis marked this conversation as resolved.
Show resolved Hide resolved
st.set_option("deprecation.showPyplotGlobalUse", False)

# ----------------------------------------------
def format_evaluation_metrics_binary(
accuracy: float,
precision: float,
recall: float,
f1: float,
tn: int,
fp: int,
fn: int,
tp: int,
) -> Dict[str, Union[int, float]]:
formated_metrics_for_binary = {
"accuracy": accuracy,
"precision": precision,
"recall": recall,
"f1": f1,
"true_negative": tn,
"false_positive": fp,
"false_negative": fn,
"true_positive": tp,
}

return formated_metrics_for_binary


evaluation_metrics_binary = format_evaluation_metrics_binary(
0.64, 0.5, 0.11, 0.72, 1200, 600, 840, 260
)
evaluation_metrics_binary_df = pd.DataFrame(evaluation_metrics_binary, index=[0])
base_evaluation_metrics_binary_df = evaluation_metrics_binary_df[
["accuracy", "precision", "recall", "f1"]
]
# Conf matrix
first_part = [
evaluation_metrics_binary["true_positive"],
evaluation_metrics_binary["false_positive"],
]
second_part = [
evaluation_metrics_binary["false_negative"],
evaluation_metrics_binary["true_negative"],
]
cm = np.array([first_part, second_part])

# -----------------------------------
overview, performance, drifting, inferences, monitors, alerts = st.tabs(
["Overview", "Performance", "Drifting", "Inferences", "Monitors", "Alerts"]
)
model_option, models_list, checkbox, wb = create_sidebar()

if checkbox:
model = get_model_from_name(models_list, model_option)
pred_column = model["prediction"]
model_id = model["id"]
model_type = model["type"]
# TODO: Need to connect this one with the db.
with overview:
create_overview_tab(model, cm, base_evaluation_metrics_binary_df)

with performance:
create_performance_tab(wb, model_id, model_type)

with drifting:
create_drift_tab(wb, model_id)

with inferences:
create_inferences_tab(wb, model_id, pred_column)

with monitors:
create_monitors_tab(wb, model_id, model_type)

with alerts:
create_alerts_tab(wb, model_id)
30 changes: 30 additions & 0 deletions whitebox/streamlit/cards.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import streamlit as st


def card1(text1, text2):
st.markdown(
f"""
<div class="card text-white bg-dark mb-3" style="max-width: 280rem;">
<div class="card-body">
<p class="card-text"><b>{text1}</b></p>
<p class="card-text">{text2}</p>
</div>
</div>
""",
unsafe_allow_html=True,
)


def card(text1, text2, text3):
st.markdown(
f"""
<div class="card text-white bg-dark mb-3" style="width: 44rem;">
<div class="card-body">
<h5 class="card-title"><b>{text1}</b></h5>
<h6 class="card-subtitle mb-2 text-muted">type: {text2}</h6>
<p class="card-text">{text3}</p>
</div>
</div>
""",
unsafe_allow_html=True,
)
11 changes: 11 additions & 0 deletions whitebox/streamlit/classification_test_data copy.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
y_testing_binary,y_prediction_binary,y_testing_multi,y_prediction_multi
0,0,0,1
0,0,2,2
0,1,0,0
1,1,1,1
0,0,2,0
1,0,1,1
1,0,1,0
1,1,2,2
0,1,0,1
1,1,1,1
11 changes: 11 additions & 0 deletions whitebox/streamlit/classification_test_data.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
y_testing_binary,y_prediction_binary,y_testing_multi,y_prediction_multi
0,0,0,1
0,0,2,2
0,1,0,0
1,1,1,1
0,0,2,0
1,0,1,1
1,0,1,0
1,1,2,2
0,1,0,1
1,1,1,1
51 changes: 51 additions & 0 deletions whitebox/streamlit/config/config_readme.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
[app]
app_intro = """
This streamlit app allows you to visualise and monitor the results and all related analytics produced by Whitebox.

All you have to do is to select your desired model which is stored in your database and then navigate through the different tabs.
"""
[tooltips]
model_option = """
These are the models that are saved in your connected database.
"""
overview_performance = """
These are the model's performance metrics after it was trained with the training data. 
"""
monitor_name = """
Add your preference name for the new monitor. 
"""
monitor_use_case = """
Add your preference type of monitor. 
"""
stat_thresh_monitor = """
Enter a value between 0 and 1 with max two decimal points, e.g. 0.25. 
"""
alert_trig_monitor = """
Alert will trigger if below the lower threshold or above the upper threshold. 
"""
alert_severity_monitor = """
What alert severity should be associated with the notifications being sent?
"""
notifications_monitor = """
Notifications will be sent via email. Please provide your email below:
"""
host = """
Your host and port combined in a url.
"""
api_key = """
Your api key as was created from the initialisation of Whitebox.
"""
model_name = """
Your desired model name.
"""
model_description = """
Your desired model description.
"""
model_type = """
Your desired model type.
"""
target_column = """
Your desired target column as depicted in your data.
"""
[links]
repo = "https://github.com/squaredev-io/whitebox"
20 changes: 20 additions & 0 deletions whitebox/streamlit/mock/alerts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[
{
"id": 44,
"model_monitor_id": 1,
"timestamp": "2023-03-14",
"description": "fell below the threshold"
},
{
"id": 45,
"model_monitor_id": 1,
"timestamp": "2023-03-16",
"description": "fell below the threshold"
},
{
"id": 46,
"model_monitor_id": 3,
"timestamp": "2023-03-16",
"description": "fell increasinlgy below the threshold"
}
]
Loading