adollbo commited on
Commit
32a7408
·
1 Parent(s): 79c440a

working version

Browse files
Files changed (3) hide show
  1. app.py +131 -89
  2. utils.py +7 -0
  3. visual_components.py +14 -9
app.py CHANGED
@@ -3,7 +3,7 @@ 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
 
@@ -15,16 +15,30 @@ st.title("Money Laundering System")
15
  st.divider()
16
 
17
  data = pd.read_pickle("data/preprocessed_data.pkl")
18
- # data = data.drop('isFraud', axis=1)
19
 
20
- # Disable the submit button after it is clicked
21
- def disable():
22
- st.session_state.disabled = True
 
 
 
23
 
24
- # Initialize disabled for form_submit_button to False
25
  if "disabled" not in st.session_state:
26
  st.session_state.disabled = False
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  st.markdown("""
29
  <style>
30
  [data-testid=stSidebar] {
@@ -39,16 +53,16 @@ with st.sidebar:
39
  # Ask for model URL and token
40
  host = st.text_input("Host (changing is optional)", "app.deeploy.ml")
41
  model_url, workspace_id, deployment_id = get_model_url()
42
- deployment_token = st.text_input("Deeploy Model Token", "my-secret-token")
43
  if deployment_token == "my-secret-token":
44
  st.warning(
45
  "Please enter Deeploy API token."
46
  )
47
- else:
48
- 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
49
  ) #on_click=lambda: st.experimental_rerun()
50
  ChangeButtonColour("Get suspicious transaction", '#FFFFFF', "#00052D")#'#FFFFFF', "#00052D"
51
-
52
 
53
  # define client optsions and instantiate client
54
  client_options = {
@@ -58,82 +72,31 @@ with st.sidebar:
58
  }
59
  client = Client(**client_options)
60
 
61
- # st.text(client_options)
62
- # st.text(deployment_id)
 
 
 
 
 
63
 
64
- if "predict_button" not in st.session_state:
65
- st.session_state.predict_button = False
66
- st.info(
67
- "Fill in left hand side and click on button to observe a potential fraudulent transaction"
68
- )
69
- if st.session_state.predict_button:
70
  try:
71
  with st.spinner("Loading..."):
72
  datapoint_pd = get_random_suspicious_transaction(data)
73
  request_body = get_request_body(datapoint_pd)
74
- # Call the explain endpoint as it also includes the prediction
75
  exp = client.explain(request_body=request_body, deployment_id=deployment_id)
76
- shap_values = exp['explanations'][0]['shap_values']
77
-
78
-
79
- col1, col2 = st.columns(2)
80
-
81
- with col1:
82
-
83
- create_data_input_table(datapoint_pd, COL_NAMES)
84
- with col2:
85
- st.subheader('Prediction Explanation: ')
86
  certainty = get_fake_certainty()
87
- st.metric(label='#### Model Certainty', value=certainty)
88
-
89
- explainability_texts, sorted_indices = get_explainability_texts(shap_values, feature_texts)
90
- explainability_values = get_explainability_values(sorted_indices, datapoint_pd)
91
- create_table(explainability_texts, explainability_values, 'Important Suspicious Variables: ')
92
-
93
- st.subheader("")
94
- # st.markdown("<h2 style='text-align: center; white: red;'>Evaluation</h2>", unsafe_allow_html=True)
95
-
96
- col3, col4 = st.columns(2)
97
-
98
- with col3:
99
- st.button("Send to FIU", key="yes_button", use_container_width=True)
100
- ChangeButtonColour("Send to FIU", '#FFFFFF', "#DD360C")
101
- if 'eval_selected' not in st.session_state:
102
- st.session_state['eval_selected'] = False
103
- # if yes_button:
104
- # st.session_state.eval_selected = True
105
- # st.session_state.evaluation_input = {
106
- # "result": 0 # Agree with the prediction
107
- # }
108
-
109
- with col4:
110
- st.button("Not money laundering", key="no_button", use_container_width=True)
111
- ChangeButtonColour("Not money laundering", '#FFFFFF', "#46B071")
112
- # if no_button:
113
- # st.session_state.eval_selected = True
114
- # desired_output = not predictions[0]
115
- # st.session_state.evaluation_input = {
116
- # "result": 1, # Disagree with the prediction
117
- # "value": {"predictions": [desired_output]},
118
- # }
119
-
120
- success = False
121
- if st.session_state.eval_selected:
122
- comment = st.text_input("Would you like to add a comment?")
123
- if comment:
124
- st.session_state.evaluation_input["explanation"] = comment
125
- logging.debug("Selected feedback:" + str(st.session_state.evaluation_input))
126
- if st.button("Submit", key="submit_button"):
127
- st.session_state.eval_selected = False
128
- # success = send_evaluation(client, deployment_id, request_log_id, prediction_log_id, st.session_state.evaluation_input)
129
- if success:
130
- st.session_state.eval_selected = False
131
- st.success("Feedback submitted successfully.")
132
-
133
-
134
-
135
-
136
-
137
  except Exception as e:
138
  logging.error(e)
139
  st.error(
@@ -142,14 +105,93 @@ if st.session_state.predict_button:
142
  + "Contact Deeploy if the problem persists."
143
  )
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
-
147
-
148
-
149
- st.session_state.successful_call = False
150
-
151
-
152
-
153
-
154
-
155
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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, send_evaluation, get_explanation
7
  from utils import COL_NAMES, feature_texts
8
  from visual_components import create_data_input_table, create_table, ChangeButtonColour
9
 
 
15
  st.divider()
16
 
17
  data = pd.read_pickle("data/preprocessed_data.pkl")
 
18
 
19
+ if 'predict_button_clicked' not in st.session_state:
20
+ st.session_state.predict_button_clicked = False
21
+
22
+
23
+ if "submitted_disabled" not in st.session_state:
24
+ st.session_state.submitted_disabled = False
25
 
 
26
  if "disabled" not in st.session_state:
27
  st.session_state.disabled = False
28
 
29
+ def disabled():
30
+ # st.session_state.predict_button_clicked = True
31
+ st.session_state.disabled = True
32
+
33
+ def rerun():
34
+ st.session_state.predict_button_clicked = True
35
+ st.session_state.submitted_disabled = False
36
+
37
+
38
+ def submitted_disabled():
39
+ st.session_state.submitted_disabled = True
40
+
41
+
42
  st.markdown("""
43
  <style>
44
  [data-testid=stSidebar] {
 
53
  # Ask for model URL and token
54
  host = st.text_input("Host (changing is optional)", "app.deeploy.ml")
55
  model_url, workspace_id, deployment_id = get_model_url()
56
+ deployment_token = st.text_input("Deeploy Model Token", "DPTjVXffSvkAATY1KEeNRGghUEd0iugjYBGKTLTIjtZa3aheZcF1esLBP4F6mYhvk48hF8vy8uZmC8MzwUVFwE7JIPeNCSEjxTCqHOjzsGzNW0ydFA4W") # my-secret-token
57
  if deployment_token == "my-secret-token":
58
  st.warning(
59
  "Please enter Deeploy API token."
60
  )
61
+ else:
62
+ st.button("Get suspicious transaction", key="predict_button", help="Click to get a suspicious transaction", use_container_width=True, on_click=disabled, disabled=st.session_state.disabled
63
  ) #on_click=lambda: st.experimental_rerun()
64
  ChangeButtonColour("Get suspicious transaction", '#FFFFFF', "#00052D")#'#FFFFFF', "#00052D"
65
+
66
 
67
  # define client optsions and instantiate client
68
  client_options = {
 
72
  }
73
  client = Client(**client_options)
74
 
75
+ if st.session_state.predict_button: # and not st.session_state.predict_button_clicked
76
+ st.session_state.predict_button_clicked = True
77
+
78
+ # if 'explanation' not in st.session_state:
79
+ # st.session_state.explanation = ""
80
+ if 'got_explanation' not in st.session_state:
81
+ st.session_state.got_explanation = False
82
 
83
+ if st.session_state.predict_button_clicked:
 
 
 
 
 
84
  try:
85
  with st.spinner("Loading..."):
86
  datapoint_pd = get_random_suspicious_transaction(data)
87
  request_body = get_request_body(datapoint_pd)
88
+ # Call the explain endpoint as it also includes the prediction
89
  exp = client.explain(request_body=request_body, deployment_id=deployment_id)
90
+ # request_log_id = exp["requestLogId"]
91
+ # prediction_log_id = exp["predictionLogIds"][0]
92
+ st.session_state.shap_values = exp['explanations'][0]['shap_values']
93
+ st.session_state.request_log_id = exp["requestLogId"]
94
+ st.session_state.prediction_log_id = exp["predictionLogIds"][0]
95
+ st.session_state.datapoint_pd = datapoint_pd
 
 
 
 
96
  certainty = get_fake_certainty()
97
+ st.session_state.certainty = certainty
98
+ st.session_state.got_explanation = True
99
+ st.session_state.predict_button_clicked = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  except Exception as e:
101
  logging.error(e)
102
  st.error(
 
105
  + "Contact Deeploy if the problem persists."
106
  )
107
 
108
+ if not st.session_state.got_explanation:
109
+ st.info(
110
+ "Fill in left hand side and click on button to observe a potential fraudulent transaction"
111
+ )
112
+ if st.session_state.got_explanation:
113
+ shap_values = st.session_state.shap_values
114
+ request_log_id = st.session_state.request_log_id
115
+ prediction_log_id = st.session_state.prediction_log_id
116
+ datapoint_pd = st.session_state.datapoint_pd
117
+ certainty = st.session_state.certainty
118
+
119
+ col1, col2 = st.columns(2)
120
+
121
+ with col1:
122
+ create_data_input_table(datapoint_pd, COL_NAMES)
123
+
124
+ with col2:
125
+ st.subheader('Prediction Explanation: ')
126
+ # st.metric(label='#### Model Certainty', value=certainty)
127
+ st.markdown('#### Model Certainty')
128
+ st.success(f'{certainty}')
129
+
130
+ explainability_texts, sorted_indices = get_explainability_texts(shap_values, feature_texts)
131
+ explainability_values = get_explainability_values(sorted_indices, datapoint_pd)
132
+ create_table(explainability_texts, explainability_values, 'Important Suspicious Variables: ')
133
+
134
+ st.subheader("")
135
+ # st.markdown("<h2 style='text-align: center; white: red;'>Evaluation</h2>", unsafe_allow_html=True)
136
+
137
+ if 'eval_selected' not in st.session_state:
138
+ st.session_state['eval_selected'] = False
139
+
140
+
141
+ col3, col4 = st.columns(2)
142
+ with col3:
143
+ eval1 = st.empty()
144
+ eval1.button("Send to FIU", key="yes_button", use_container_width=True, disabled=st.session_state.submitted_disabled)
145
+ ChangeButtonColour("Send to FIU", '#FFFFFF', "#DD360C")
146
+ st.session_state.yes_button_clicked = False
147
+
148
+ if st.session_state.yes_button:
149
+ st.session_state.eval_selected = True
150
+ st.session_state.evaluation_input = {
151
+ "result": 0 # Agree with the prediction
152
+ }
153
+
154
+ with col4:
155
+ eval2 = st.empty()
156
+ eval2.button("Not money laundering", key="no_button", use_container_width=True, disabled=st.session_state.submitted_disabled)
157
+ ChangeButtonColour("Not money laundering", '#FFFFFF', "#46B071")
158
+ st.session_state.no_button_clicked = False
159
+
160
+
161
+ if st.session_state.no_button:
162
+ st.session_state.no_button_clicked = True
163
+ if st.session_state.no_button_clicked:
164
+ st.session_state.eval_selected = True
165
+ desired_output = 1
166
+ st.session_state.evaluation_input = {
167
+ "result": 1, # Disagree with the prediction
168
+ "value": {"predictions": [desired_output]},
169
+ }
170
 
171
+ success = False
172
+ if st.session_state.eval_selected:
173
+ # st.write('after eval')
174
+ # st.write(st.session_state)
175
+ if st.session_state.yes_button:
176
+ explanation = get_explanation(certainty, explainability_texts, explainability_values)
177
+ comment = st.text_area("Reason for evaluation:", explanation)
178
+ st.session_state.evaluation_input["explanation"] = comment
179
+ if st.session_state.no_button:
180
+ comment = st.text_area("Reason for evaluation:", "I don't think this transaction is money laundering because...")
181
+ st.session_state.evaluation_input["explanation"] = comment
182
+ logging.debug("Selected feedback:" + str(st.session_state.evaluation_input))
183
+ eval3 = st.empty()
184
+ eval3.button("Submit", key="submit_button", use_container_width=True, on_click=submitted_disabled, disabled=st.session_state.submitted_disabled)
185
+ ChangeButtonColour("Submit", '#FFFFFF', "#00052D")
186
+ if st.session_state.submit_button:
187
+ st.session_state.eval_selected = False
188
+ success = send_evaluation(client, deployment_id, request_log_id, prediction_log_id, st.session_state.evaluation_input)
189
+ if success:
190
+ st.session_state.eval_selected = False
191
+ st.session_state.submitted = True
192
+ eval1.empty()
193
+ eval2.empty()
194
+ eval3.empty()
195
+ st.success("Feedback submitted successfully.")
196
+ st.button("Next", key='next', use_container_width=True, on_click=rerun)
197
+ ChangeButtonColour("Next", '#FFFFFF', "#F9B917")
utils.py CHANGED
@@ -120,3 +120,10 @@ def get_model_url():
120
  deployment_id = ""
121
  return model_url, workspace_id, deployment_id
122
 
 
 
 
 
 
 
 
 
120
  deployment_id = ""
121
  return model_url, workspace_id, deployment_id
122
 
123
+ def get_explanation(certainty, explainability_texts, explainability_values):
124
+ cleaned = [x.replace(':', '') for x in explainability_texts]
125
+ fi = [f'{explainability_texts[i]} is {x}' for i,x in enumerate(cleaned)]
126
+ fi.insert(0, 'Important suspicious features: ')
127
+ result = '\n'.join(fi)
128
+ comment = f"Model certainty is {certainty}" + '\n''\n' + result
129
+ return comment
visual_components.py CHANGED
@@ -24,22 +24,27 @@ def create_table(texts, values, title):
24
  # df = df.style.set_properties(**{
25
  # 'selector': 'th',
26
  # 'props': [
27
- # ('background-color', 'black'),
28
  # ('color', 'cyan')]
29
  # })
30
  # df = df.style.set_properties(**{'background-color': 'black',
31
  # 'color': 'green'})
32
 
33
  st.markdown(f'#### {title}') # Markdown for styling
34
- headers = {
35
- 'selector': 'th',
36
- 'props': 'background-color' '#67c5a4'#'background-color: #000066; color: white;'
37
- }
 
 
 
 
38
 
39
- df = df.style.set_table_styles({
40
- ('Feature Explanation', 'Value'): [{'selector': 'th', 'props': 'border-left: 1px solid white'},
41
- {'selector': 'td', 'props': 'border-left: 1px solid #000066'}]
42
- }, axis=0)
 
43
 
44
  # df.style.set_table_styles([headers])
45
  st.dataframe(df, hide_index=True, width=450) # Display a simple table
 
24
  # df = df.style.set_properties(**{
25
  # 'selector': 'th',
26
  # 'props': [
27
+ # ('background-color', 'black'),``
28
  # ('color', 'cyan')]
29
  # })
30
  # df = df.style.set_properties(**{'background-color': 'black',
31
  # 'color': 'green'})
32
 
33
  st.markdown(f'#### {title}') # Markdown for styling
34
+ # headers = {
35
+ # 'selector': 'th',
36
+ # 'props': 'background-color' '#67c5a4'#'background-color: #000066; color: white;'
37
+ # }
38
+ header = {
39
+ 'selector': 'th',
40
+ 'props': 'background-color: #000066; color: white;'
41
+ }
42
 
43
+ # df = df.style.set_table_styles({
44
+ # ('Feature Explanation', 'Value'): [{'selector': 'th', 'props': 'border-left: 1px solid white'},
45
+ # {'selector': 'td', 'props': 'border-left: 1px solid #000066'}]
46
+ # }, axis=0)
47
+ df = df.style.set_table_styles([header])
48
 
49
  # df.style.set_table_styles([headers])
50
  st.dataframe(df, hide_index=True, width=450) # Display a simple table