app in progress
Browse files
app.py
CHANGED
|
@@ -2,52 +2,25 @@ import streamlit as st
|
|
| 2 |
import pandas as pd
|
| 3 |
import logging
|
| 4 |
from deeploy import Client
|
| 5 |
-
from utils import
|
| 6 |
-
from utils import
|
|
|
|
|
|
|
| 7 |
|
| 8 |
logging.basicConfig(level=logging.INFO)
|
| 9 |
|
| 10 |
st.set_page_config(layout="wide")
|
| 11 |
|
| 12 |
-
|
| 13 |
-
|
| 14 |
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
with st.spinner("Submitting response..."):
|
| 23 |
-
# Call the explain endpoint as it also includes the prediction
|
| 24 |
-
client.evaluate(deployment_id, request_log_id, prediction_log_id, evaluation_input)
|
| 25 |
-
return True
|
| 26 |
-
except Exception as e:
|
| 27 |
-
logging.error(e)
|
| 28 |
-
st.error(
|
| 29 |
-
"Failed to submit feedback."
|
| 30 |
-
+ "Check whether you are using the right model URL and Token. "
|
| 31 |
-
+ "Contact Deeploy if the problem persists."
|
| 32 |
-
)
|
| 33 |
-
st.write(f"Error message: {e}")
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
def get_model_url():
|
| 37 |
-
"""Get model url and retrieve workspace id and deployment id from it"""
|
| 38 |
-
model_url = st.text_area(
|
| 39 |
-
"Model URL (default is the demo deployment)",
|
| 40 |
-
"https://api.app.deeploy.ml/workspaces/708b5808-27af-461a-8ee5-80add68384c7/deployments/1785f8b8-c5a6-4f55-9a83-df8bdb0b9977/",
|
| 41 |
-
height=125,
|
| 42 |
-
)
|
| 43 |
-
elems = model_url.split("/")
|
| 44 |
-
try:
|
| 45 |
-
workspace_id = elems[4]
|
| 46 |
-
deployment_id = elems[6]
|
| 47 |
-
except IndexError:
|
| 48 |
-
workspace_id = ""
|
| 49 |
-
deployment_id = ""
|
| 50 |
-
return model_url, workspace_id, deployment_id
|
| 51 |
|
| 52 |
st.markdown("""
|
| 53 |
<style>
|
|
@@ -65,9 +38,16 @@ with st.sidebar:
|
|
| 65 |
model_url, workspace_id, deployment_id = get_model_url()
|
| 66 |
deployment_token = st.text_input("Deeploy Model Token", "my-secret-token")
|
| 67 |
if deployment_token == "my-secret-token":
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
-
# define client
|
| 71 |
client_options = {
|
| 72 |
"host": host,
|
| 73 |
"deployment_token": deployment_token,
|
|
@@ -75,50 +55,97 @@ with st.sidebar:
|
|
| 75 |
}
|
| 76 |
client = Client(**client_options)
|
| 77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
positive_and_negative_indices = first_five_posneg_indices(response)
|
| 83 |
-
positive_texts, negative_texts = get_texts(positive_and_negative_indices, feature_texts)
|
| 84 |
-
positive_vals, negative_vals = get_input_values(positive_and_negative_indices, example_input)
|
| 85 |
-
|
| 86 |
-
# Create a function to generate a table
|
| 87 |
-
def create_table(texts, values, title):
|
| 88 |
-
# TODO: change color dataframe header -> tried many different options but none worked see below
|
| 89 |
-
# header_style = '''
|
| 90 |
-
# <style>
|
| 91 |
-
# th{
|
| 92 |
-
# background-color: #00052D;
|
| 93 |
-
# }
|
| 94 |
-
# </style>
|
| 95 |
-
# '''
|
| 96 |
-
df = pd.DataFrame({"Feature Explanation": texts, 'Value': values})
|
| 97 |
-
# df = df.style.set_properties(**{
|
| 98 |
-
# 'selector': 'th',
|
| 99 |
-
# 'props': [
|
| 100 |
-
# ('background-color', 'black'),
|
| 101 |
-
# ('color', 'cyan')]
|
| 102 |
-
# })
|
| 103 |
-
# df = df.style.set_properties(**{'background-color': 'black',
|
| 104 |
-
# 'color': 'green'})
|
| 105 |
-
|
| 106 |
-
# headers = {
|
| 107 |
-
# 'selector': 'th',
|
| 108 |
-
# 'props': [('background-color', '#67c5a4')]#'background-color: #000066; color: white;'
|
| 109 |
-
# }
|
| 110 |
-
# df = df.style.set_table_styles([headers])
|
| 111 |
-
st.markdown(f'#### {title}') # Markdown for styling
|
| 112 |
-
st.dataframe(df, hide_index=True) # Display a simple table
|
| 113 |
-
# st.markdown(header_style, unsafe_allow_html=True)
|
| 114 |
-
|
| 115 |
-
# Arrange tables horizontally using Streamlit columns
|
| 116 |
-
col1, col2 = st.columns(2,gap="small")
|
| 117 |
-
|
| 118 |
-
# Display tables in Streamlit columns
|
| 119 |
-
with col1:
|
| 120 |
-
create_table(positive_texts, positive_vals, 'Important Suspicious Variables')
|
| 121 |
-
|
| 122 |
-
with col2:
|
| 123 |
-
create_table(negative_texts, negative_vals, 'Important Unsuspicious Variables')
|
| 124 |
|
|
|
|
| 2 |
import pandas as pd
|
| 3 |
import logging
|
| 4 |
from deeploy import Client
|
| 5 |
+
from utils import get_request_body, get_fake_certainty, get_model_url, get_random_suspicious_transaction
|
| 6 |
+
from utils import get_explainability_texts, get_explainability_values
|
| 7 |
+
from utils import COL_NAMES, feature_texts
|
| 8 |
+
from visual_components import create_data_input_table, create_table, ChangeButtonColour
|
| 9 |
|
| 10 |
logging.basicConfig(level=logging.INFO)
|
| 11 |
|
| 12 |
st.set_page_config(layout="wide")
|
| 13 |
|
| 14 |
+
data = pd.read_pickle("data/preprocessed_data.pkl")
|
| 15 |
+
# data = data.drop('isFraud', axis=1)
|
| 16 |
|
| 17 |
+
# Disable the submit button after it is clicked
|
| 18 |
+
def disable():
|
| 19 |
+
st.session_state.disabled = True
|
| 20 |
|
| 21 |
+
# Initialize disabled for form_submit_button to False
|
| 22 |
+
if "disabled" not in st.session_state:
|
| 23 |
+
st.session_state.disabled = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
st.markdown("""
|
| 26 |
<style>
|
|
|
|
| 38 |
model_url, workspace_id, deployment_id = get_model_url()
|
| 39 |
deployment_token = st.text_input("Deeploy Model Token", "my-secret-token")
|
| 40 |
if deployment_token == "my-secret-token":
|
| 41 |
+
st.warning(
|
| 42 |
+
"Please enter Deeploy API token."
|
| 43 |
+
)
|
| 44 |
+
else:
|
| 45 |
+
st.button("Get suspicious transaction", key="predict_button", help="Click to get a suspicious transaction", use_container_width=True, on_click=disable, disabled=st.session_state.disabled
|
| 46 |
+
) #on_click=lambda: st.experimental_rerun()
|
| 47 |
+
ChangeButtonColour("Get suspicious transaction", '#FFFFFF', "#00052D")#'#FFFFFF', "#00052D"
|
| 48 |
+
|
| 49 |
|
| 50 |
+
# define client optsions and instantiate client
|
| 51 |
client_options = {
|
| 52 |
"host": host,
|
| 53 |
"deployment_token": deployment_token,
|
|
|
|
| 55 |
}
|
| 56 |
client = Client(**client_options)
|
| 57 |
|
| 58 |
+
# st.text(client_options)
|
| 59 |
+
# st.text(deployment_id)
|
| 60 |
+
|
| 61 |
+
if "predict_button" not in st.session_state:
|
| 62 |
+
st.session_state.predict_button = False
|
| 63 |
+
st.title("Money Laundering System")
|
| 64 |
+
st.divider()
|
| 65 |
+
st.info(
|
| 66 |
+
"Fill in left hand side and click on button to observe a potential fraudulent transaction"
|
| 67 |
+
)
|
| 68 |
+
if st.session_state.predict_button:
|
| 69 |
+
try:
|
| 70 |
+
with st.spinner("Loading..."):
|
| 71 |
+
datapoint_pd = get_random_suspicious_transaction(data)
|
| 72 |
+
request_body = get_request_body(datapoint_pd)
|
| 73 |
+
# Call the explain endpoint as it also includes the prediction
|
| 74 |
+
exp = client.explain(request_body=request_body, deployment_id=deployment_id)
|
| 75 |
+
shap_values = exp['explanations'][0]['shap_values']
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
col1, col2 = st.columns(2)
|
| 79 |
+
|
| 80 |
+
with col1:
|
| 81 |
+
|
| 82 |
+
create_data_input_table(datapoint_pd, COL_NAMES)
|
| 83 |
+
with col2:
|
| 84 |
+
certainty = get_fake_certainty()
|
| 85 |
+
st.metric(label='#### Model Certainty', value=certainty)
|
| 86 |
+
|
| 87 |
+
explainability_texts, sorted_indices = get_explainability_texts(shap_values, feature_texts)
|
| 88 |
+
explainability_values = get_explainability_values(sorted_indices, datapoint_pd)
|
| 89 |
+
create_table(explainability_texts, explainability_values, 'Important Suspicious Variables: ')
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
st.divider()
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
# Add prediction evaluation
|
| 96 |
+
st.subheader("Prediction Evaluation")
|
| 97 |
+
st.write("Do you agree with the prediction?")
|
| 98 |
+
|
| 99 |
+
yes_button = st.button("Yes :thumbsup:", key="yes_button")
|
| 100 |
+
if 'eval_selected' not in st.session_state:
|
| 101 |
+
st.session_state['eval_selected'] = False
|
| 102 |
+
if yes_button:
|
| 103 |
+
st.session_state.eval_selected = True
|
| 104 |
+
st.session_state.evaluation_input = {
|
| 105 |
+
"result": 0 # Agree with the prediction
|
| 106 |
+
}
|
| 107 |
+
no_button = st.button("No :thumbsdown:", key="no_button")
|
| 108 |
+
if no_button:
|
| 109 |
+
st.session_state.eval_selected = True
|
| 110 |
+
# desired_output = not predictions[0]
|
| 111 |
+
# st.session_state.evaluation_input = {
|
| 112 |
+
# "result": 1, # Disagree with the prediction
|
| 113 |
+
# "value": {"predictions": [desired_output]},
|
| 114 |
+
# }
|
| 115 |
+
|
| 116 |
+
success = False
|
| 117 |
+
if st.session_state.eval_selected:
|
| 118 |
+
comment = st.text_input("Would you like to add a comment?")
|
| 119 |
+
if comment:
|
| 120 |
+
st.session_state.evaluation_input["explanation"] = comment
|
| 121 |
+
logging.debug("Selected feedback:" + str(st.session_state.evaluation_input))
|
| 122 |
+
if st.button("Submit", key="submit_button"):
|
| 123 |
+
st.session_state.eval_selected = False
|
| 124 |
+
# success = send_evaluation(client, deployment_id, request_log_id, prediction_log_id, st.session_state.evaluation_input)
|
| 125 |
+
if success:
|
| 126 |
+
st.session_state.eval_selected = False
|
| 127 |
+
st.success("Feedback submitted successfully.")
|
| 128 |
+
|
| 129 |
+
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
except Exception as e:
|
| 134 |
+
logging.error(e)
|
| 135 |
+
st.error(
|
| 136 |
+
"Failed to retrieve the prediction or explanation."
|
| 137 |
+
+ "Check whether you are using the right model URL and Token. "
|
| 138 |
+
+ "Contact Deeploy if the problem persists."
|
| 139 |
+
)
|
| 140 |
+
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
st.session_state.successful_call = False
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
|
| 149 |
|
| 150 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
|