deeploy-adubowski commited on
Commit
039500b
·
1 Parent(s): 3309e17

Update request body logic

Browse files
Files changed (1) hide show
  1. app.py +82 -65
app.py CHANGED
@@ -3,6 +3,7 @@ import streamlit.components.v1 as components
3
  import streamlit as st
4
  import pandas as pd
5
  import logging
 
6
  from deeploy import Client
7
  from constants import (
8
  relationship_dict,
@@ -75,6 +76,7 @@ with st.sidebar:
75
  # Ask for model URL and token
76
  host = st.text_input("Host (Changing is optional)", "app.deeploy.ml")
77
  model_url, workspace_id, deployment_id = get_model_url()
 
78
  deployment_token = st.text_input("Deeploy Model Token", "my-secret-token")
79
  if deployment_token == "my-secret-token":
80
  st.warning("Please enter Deeploy API token.")
@@ -101,13 +103,55 @@ if "evaluation_submitted" not in st.session_state:
101
  if "predict_button_clicked" not in st.session_state:
102
  st.session_state.predict_button_clicked = False
103
 
 
 
 
 
 
 
104
  if "exp" not in st.session_state:
105
  st.session_state.exp = None
106
 
107
- def set_prediction_view():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  st.session_state.predict_button_clicked = True
109
  st.session_state.evaluation_submitted = False
110
- hide_expander()
111
 
112
  def hide_expander():
113
  st.session_state.expander_toggle = False
@@ -142,51 +186,44 @@ def submit_and_clear(evaluation: str):
142
  # st.write(st.session_state)
143
 
144
  # Attributes
145
- st.subheader("Loan Application")
146
- with st.expander("Application form", expanded=st.session_state.expander_toggle):
147
  # Split view in 2 columns
148
  col1, col2 = st.columns(2)
149
  with col1:
150
  # Create input fields for attributes from constant dicts
151
- age = st.number_input("Age", min_value=0, max_value=100, value=30)
152
- marital_status = st.selectbox("Marital Status", marital_status_dict.keys())
153
- marital_status_id = marital_status_dict[marital_status]
154
  native_country = st.selectbox(
155
- "Native Country", countries_dict.keys(), index=len(countries_dict) - 1
156
  )
157
- native_country_id = countries_dict[native_country]
158
- relationship = st.selectbox("Family situation", relationship_dict.keys())
159
- relationship_id = relationship_dict[relationship]
160
- occupation = st.selectbox("Occupation", occupation_dict.keys(), index=1)
161
- occupation_id = occupation_dict[occupation]
162
 
163
  with col2:
164
- education = st.selectbox("Highest education level", education_dict.keys(), index=4)
165
- education_id = education_dict[education]
166
- type_of_work = st.selectbox("Type of work", type_of_work_dict.keys())
167
- type_of_work_id = type_of_work_dict[type_of_work]
168
  hours_per_week = st.number_input(
169
- "Working hours per week", min_value=0, max_value=100, value=40
170
  )
171
  capital_gain = st.number_input(
172
- "Yearly income [€]", min_value=0, max_value=1000000, value=70000
173
  )
174
  capital_loss = st.number_input(
175
- "Yearly expenditures [€]", min_value=0, max_value=1000000, value=60000
176
  )
177
  data_df = pd.DataFrame(
178
  [
179
  [
180
- age,
181
- type_of_work,
182
- education,
183
- marital_status,
184
- occupation,
185
- relationship,
186
- capital_gain,
187
- capital_loss,
188
- hours_per_week,
189
- native_country,
190
  ]
191
  ],
192
  columns=[
@@ -203,35 +240,12 @@ with st.expander("Application form", expanded=st.session_state.expander_toggle):
203
  ],
204
  )
205
  data_df_t = data_df.T
206
- request_body = {
207
- "instances": [
208
- [
209
- age,
210
- type_of_work_id,
211
- education_id,
212
- marital_status_id,
213
- occupation_id,
214
- relationship_id,
215
- capital_gain,
216
- capital_loss,
217
- hours_per_week,
218
- native_country_id,
219
- ]
220
- ]
221
- }
222
 
223
  # Show predict button if token is set
224
  if deployment_token != "my-secret-token" and st.session_state.exp is None:
225
  predict_button = st.button(
226
- "Send loan application", key="predict_button", help="Click to get the AI prediction.", on_click=set_prediction_view
227
- )
228
- if predict_button:
229
- with st.spinner("Loading prediction and explanation..."):
230
- # Call the explain endpoint as it also includes the prediction
231
- exp = client.explain(
232
- request_body=request_body, deployment_id=deployment_id
233
- )
234
- st.session_state.exp = exp
235
 
236
  if st.session_state.evaluation_submitted:
237
  st.success("Evaluation submitted successfully!")
@@ -257,10 +271,11 @@ elif st.session_state.predict_button_clicked and st.session_state.exp is not Non
257
  exp_df_t = data_df_t.merge(exp_df_t, left_index=True, right_index=True)
258
 
259
  weight_feat = "Weight"
260
- exp_df_t.columns = ["Feature value", weight_feat]
 
261
  exp_df_t["Feature"] = exp_df_t.index
262
- exp_df_t = exp_df_t[["Feature", "Feature value", weight_feat]]
263
- exp_df_t["Feature value"] = exp_df_t["Feature value"].astype(str)
264
 
265
  # Filter values below 0.01
266
  exp_df_t = exp_df_t[
@@ -279,14 +294,14 @@ elif st.session_state.predict_button_clicked and st.session_state.exp is not Non
279
  pos_feats = pos_exp_df_t[weight_feat].nlargest(3).index.tolist()
280
  # For feature, get feature value and concatenate into a single string
281
  pos_feats = [
282
- f"{feat}: {pos_exp_df_t.loc[feat, 'Feature value']}"
283
  for feat in pos_feats
284
  ]
285
  # Get 3 features with highest negative relevance score
286
  neg_feats = neg_exp_df_t[weight_feat].nlargest(3).index.tolist()
287
  # For feature, get feature value and concatenate into a single string
288
  neg_feats = [
289
- f"{feat}: {neg_exp_df_t.loc[feat, 'Feature value']}"
290
  for feat in neg_feats
291
  ]
292
  if predictions[0]:
@@ -304,7 +319,7 @@ elif st.session_state.predict_button_clicked and st.session_state.exp is not Non
304
  + " \n- ".join(pos_feats)
305
  )
306
  with col2:
307
- st.warning(
308
  "However, the following features weight against the loan applicant: \n - "
309
  + " \n- ".join(neg_feats)
310
  # + " \n For more details, see full explanation of the credit assessment below.",
@@ -315,18 +330,20 @@ elif st.session_state.predict_button_clicked and st.session_state.exp is not Non
315
  with col1:
316
  # If prediction is negative, first show negative features, then positive features
317
  st.error(
318
- "The most important characteristics in favor of loan rejection are: \n - "
319
  + " \n - ".join(neg_feats)
320
  )
321
  with col2:
322
- st.warning(
323
  "However, the following factors weigh in favor of the loan applicant: \n - "
324
  + " \n - ".join(pos_feats)
325
  )
326
  try:
327
  # Show explanation
328
- col_pos, col_neg = st.columns(2)
329
-
 
 
330
  with col_pos:
331
  st.subheader("Factors :green[in favor] of loan approval")
332
  # st.success("**Factors in favor of loan approval**")
 
3
  import streamlit as st
4
  import pandas as pd
5
  import logging
6
+ import time
7
  from deeploy import Client
8
  from constants import (
9
  relationship_dict,
 
76
  # Ask for model URL and token
77
  host = st.text_input("Host (Changing is optional)", "app.deeploy.ml")
78
  model_url, workspace_id, deployment_id = get_model_url()
79
+ st.session_state.deployment_id = deployment_id
80
  deployment_token = st.text_input("Deeploy Model Token", "my-secret-token")
81
  if deployment_token == "my-secret-token":
82
  st.warning("Please enter Deeploy API token.")
 
103
  if "predict_button_clicked" not in st.session_state:
104
  st.session_state.predict_button_clicked = False
105
 
106
+ if "request_body" not in st.session_state:
107
+ st.session_state.request_body = None
108
+
109
+ if "deployment_id" not in st.session_state:
110
+ st.session_state.deployment_id = None
111
+
112
  if "exp" not in st.session_state:
113
  st.session_state.exp = None
114
 
115
+ def form_request_body():
116
+ """Create the request body for the prediction endpoint"""
117
+ marital_status_id = marital_status_dict[st.session_state.marital_status]
118
+ native_country_id = countries_dict[st.session_state.native_country]
119
+ relationship_id = relationship_dict[st.session_state.relationship]
120
+ occupation_id = occupation_dict[st.session_state.occupation]
121
+ education_id = education_dict[st.session_state.education]
122
+ type_of_work_id = type_of_work_dict[st.session_state.type_of_work]
123
+ return {
124
+ "instances": [
125
+ [
126
+ st.session_state.age,
127
+ type_of_work_id,
128
+ education_id,
129
+ marital_status_id,
130
+ occupation_id,
131
+ relationship_id,
132
+ st.session_state.capital_gain,
133
+ st.session_state.capital_loss,
134
+ st.session_state.hours_per_week,
135
+ native_country_id,
136
+ ]
137
+ ]
138
+ }
139
+
140
+
141
+ def predict_callback():
142
+ """Callback function to call the prediction endpoint"""
143
+ request_body = form_request_body()
144
+ st.session_state.exp = None
145
+ with st.spinner("Loading prediction and explanation..."):
146
+ # Call the explain endpoint as it also includes the prediction
147
+ exp = client.explain(
148
+ request_body=request_body, deployment_id=st.session_state.deployment_id
149
+ )
150
+ st.session_state.exp = exp
151
+ time.sleep(0.5)
152
+
153
  st.session_state.predict_button_clicked = True
154
  st.session_state.evaluation_submitted = False
 
155
 
156
  def hide_expander():
157
  st.session_state.expander_toggle = False
 
186
  # st.write(st.session_state)
187
 
188
  # Attributes
189
+ with st.expander("**Loan application form**", expanded=st.session_state.expander_toggle):
 
190
  # Split view in 2 columns
191
  col1, col2 = st.columns(2)
192
  with col1:
193
  # Create input fields for attributes from constant dicts
194
+ age = st.number_input("Age", min_value=10, max_value=100, value=30, key="age", on_change=predict_callback)
195
+ marital_status = st.selectbox("Marital Status", marital_status_dict.keys(), key="marital_status", on_change=predict_callback,)
 
196
  native_country = st.selectbox(
197
+ "Native Country", countries_dict.keys(), index=len(countries_dict) - 1, key="native_country",on_change=predict_callback
198
  )
199
+ relationship = st.selectbox("Family situation", relationship_dict.keys(), key="relationship", on_change=predict_callback)
200
+ occupation = st.selectbox("Occupation", occupation_dict.keys(), index=1, key="occupation", on_change=predict_callback)
 
 
 
201
 
202
  with col2:
203
+ education = st.selectbox("Highest education level", education_dict.keys(), key="education", index=4, on_change=predict_callback)
204
+ type_of_work = st.selectbox("Type of work", type_of_work_dict.keys(), key="type_of_work", on_change=predict_callback)
 
 
205
  hours_per_week = st.number_input(
206
+ "Working hours per week", min_value=0, max_value=100, value=40, key="hours_per_week", on_change=predict_callback,
207
  )
208
  capital_gain = st.number_input(
209
+ "Yearly income [€]", min_value=0, max_value=10000000, value=70000, key="capital_gain", on_change=predict_callback,
210
  )
211
  capital_loss = st.number_input(
212
+ "Yearly expenditures [€]", min_value=0, max_value=10000000, value=60000, key="capital_loss", on_change=predict_callback,
213
  )
214
  data_df = pd.DataFrame(
215
  [
216
  [
217
+ st.session_state.age,
218
+ st.session_state.type_of_work,
219
+ st.session_state.education,
220
+ st.session_state.marital_status,
221
+ st.session_state.occupation,
222
+ st.session_state.relationship,
223
+ st.session_state.capital_gain,
224
+ st.session_state.capital_loss,
225
+ st.session_state.hours_per_week,
226
+ st.session_state.native_country,
227
  ]
228
  ],
229
  columns=[
 
240
  ],
241
  )
242
  data_df_t = data_df.T
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
  # Show predict button if token is set
245
  if deployment_token != "my-secret-token" and st.session_state.exp is None:
246
  predict_button = st.button(
247
+ "Send loan application", key="predict_button", help="Click to get the AI prediction.", on_click=predict_callback,
248
+ )
 
 
 
 
 
 
 
249
 
250
  if st.session_state.evaluation_submitted:
251
  st.success("Evaluation submitted successfully!")
 
271
  exp_df_t = data_df_t.merge(exp_df_t, left_index=True, right_index=True)
272
 
273
  weight_feat = "Weight"
274
+ feat_val_col = "Value"
275
+ exp_df_t.columns = [feat_val_col, weight_feat]
276
  exp_df_t["Feature"] = exp_df_t.index
277
+ exp_df_t = exp_df_t[["Feature", feat_val_col, weight_feat]]
278
+ exp_df_t[feat_val_col] = exp_df_t[feat_val_col].astype(str)
279
 
280
  # Filter values below 0.01
281
  exp_df_t = exp_df_t[
 
294
  pos_feats = pos_exp_df_t[weight_feat].nlargest(3).index.tolist()
295
  # For feature, get feature value and concatenate into a single string
296
  pos_feats = [
297
+ f"{feat}: {pos_exp_df_t.loc[feat, feat_val_col]}"
298
  for feat in pos_feats
299
  ]
300
  # Get 3 features with highest negative relevance score
301
  neg_feats = neg_exp_df_t[weight_feat].nlargest(3).index.tolist()
302
  # For feature, get feature value and concatenate into a single string
303
  neg_feats = [
304
+ f"{feat}: {neg_exp_df_t.loc[feat, feat_val_col]}"
305
  for feat in neg_feats
306
  ]
307
  if predictions[0]:
 
319
  + " \n- ".join(pos_feats)
320
  )
321
  with col2:
322
+ st.error(
323
  "However, the following features weight against the loan applicant: \n - "
324
  + " \n- ".join(neg_feats)
325
  # + " \n For more details, see full explanation of the credit assessment below.",
 
330
  with col1:
331
  # If prediction is negative, first show negative features, then positive features
332
  st.error(
333
+ "The most important reasons for loan rejection are: \n - "
334
  + " \n - ".join(neg_feats)
335
  )
336
  with col2:
337
+ st.success(
338
  "However, the following factors weigh in favor of the loan applicant: \n - "
339
  + " \n - ".join(pos_feats)
340
  )
341
  try:
342
  # Show explanation
343
+ if predictions[0]:
344
+ col_pos, col_neg = st.columns(2)
345
+ else:
346
+ col_neg, col_pos = st.columns(2) # Swap columns if prediction is negative
347
  with col_pos:
348
  st.subheader("Factors :green[in favor] of loan approval")
349
  # st.success("**Factors in favor of loan approval**")