| import streamlit as st |
|
|
| st.set_page_config(layout="wide") |
|
|
| st.title("AI Model Fairness Auditing") |
|
|
| |
| |
| |
|
|
| model_owner_actions = { |
| "Fine-tuning / overfitting on auditing test": {"cheating": 25, "cost": 0, "open": -5}, |
| "Fine-tuning on auditing-like distribution": {"cheating": 20, "cost": 0, "open": -3}, |
| "Training special audit behaviour": {"cheating": 30, "cost": 5, "open": -10}, |
| "Withholding training details": {"cheating": 15, "cost": 0, "open": -15}, |
| } |
|
|
| auditor_actions = { |
| "Audit on one dataset": {"cheating": 20, "cost": 10, "open": 5}, |
| "Audit on multiple datasets": {"cheating": -15, "cost": 25, "open": 10}, |
| "Request internal model access": {"cheating": -25, "cost": 30, "open": 30}, |
| "Request training documentation": {"cheating": -10, "cost": 5, "open": 20}, |
| } |
|
|
| |
| |
| |
|
|
| if "owner_selected" not in st.session_state: |
| st.session_state.owner_selected = [] |
|
|
| if "auditor_selected" not in st.session_state: |
| st.session_state.auditor_selected = [] |
|
|
| |
| |
| |
|
|
| def toggle_owner(action): |
| if action in st.session_state.owner_selected: |
| st.session_state.owner_selected.remove(action) |
| else: |
| st.session_state.owner_selected.append(action) |
|
|
| def toggle_auditor(action): |
| if action in st.session_state.auditor_selected: |
| st.session_state.auditor_selected.remove(action) |
| else: |
| st.session_state.auditor_selected.append(action) |
|
|
| |
| |
| |
|
|
| left, right = st.columns(2) |
|
|
| |
| |
| |
|
|
| with left: |
|
|
| st.subheader("Model Owner") |
|
|
| st.caption("Chosen") |
|
|
| with st.container(border=True): |
| if not st.session_state.owner_selected: |
| st.write("None") |
|
|
| for action in st.session_state.owner_selected: |
| st.button( |
| f"✓ {action}", |
| key=f"owner_selected_{action}", |
| on_click=toggle_owner, |
| args=(action,), |
| use_container_width=True |
| ) |
|
|
| st.caption("Available") |
|
|
| with st.container(border=True): |
| for action in model_owner_actions: |
| if action not in st.session_state.owner_selected: |
| st.button( |
| action, |
| key=f"owner_available_{action}", |
| on_click=toggle_owner, |
| args=(action,), |
| use_container_width=True |
| ) |
|
|
| |
| |
| |
|
|
| with right: |
|
|
| st.subheader("Auditor") |
|
|
| st.caption("Chosen") |
|
|
| with st.container(border=True): |
| if not st.session_state.auditor_selected: |
| st.write("None") |
|
|
| for action in st.session_state.auditor_selected: |
| st.button( |
| f"✓ {action}", |
| key=f"auditor_selected_{action}", |
| on_click=toggle_auditor, |
| args=(action,), |
| use_container_width=True |
| ) |
|
|
| st.caption("Available") |
|
|
| with st.container(border=True): |
| for action in auditor_actions: |
| if action not in st.session_state.auditor_selected: |
| st.button( |
| action, |
| key=f"auditor_available_{action}", |
| on_click=toggle_auditor, |
| args=(action,), |
| use_container_width=True |
| ) |
|
|
| |
| |
| |
|
|
| cheating = 50 |
| cost = 0 |
| open_req = 0 |
|
|
| for action in st.session_state.owner_selected: |
| cheating += model_owner_actions[action]["cheating"] |
| cost += model_owner_actions[action]["cost"] |
| open_req += model_owner_actions[action]["open"] |
|
|
| for action in st.session_state.auditor_selected: |
| cheating += auditor_actions[action]["cheating"] |
| cost += auditor_actions[action]["cost"] |
| open_req += auditor_actions[action]["open"] |
|
|
| cheating = max(0, min(100, cheating)) |
| open_req = max(0, open_req) |
|
|
| |
| |
| |
|
|
| st.divider() |
|
|
| c1, c2, c3 = st.columns(3) |
|
|
| c1.metric("Chance of Cheating", f"{cheating}%") |
| c2.metric("Audit Cost", cost) |
| c3.metric("Openness Required", open_req) |
|
|
| st.progress(cheating / 100) |