"""A gradio app for credit card approval prediction using FHE.""" import subprocess import time import gradio as gr from settings import ( REPO_DIR, ACCOUNT_MIN_MAX, CHILDREN_MIN_MAX, INCOME_MIN_MAX, AGE_MIN_MAX, EMPLOYED_MIN_MAX, FAMILY_MIN_MAX, INCOME_TYPES, OCCUPATION_TYPES, HOUSING_TYPES, EDUCATION_TYPES, FAMILY_STATUS, ) from backend import ( keygen_send, pre_process_encrypt_send_user, pre_process_encrypt_send_bank, pre_process_encrypt_send_third_party, run_fhe, get_output, decrypt_output, ) subprocess.Popen(["uvicorn", "server:app"], cwd=REPO_DIR) time.sleep(3) demo = gr.Blocks() print("Starting the demo...") with demo: gr.Markdown( """

Encrypted Credit Card Approval Prediction Using Fully Homomorphic Encryption

""" ) gr.Markdown("# Client side") gr.Markdown("## Step 1: Generate the keys.") gr.Markdown( """ - The private key is used to encrypt and decrypt the data and shall never be shared. - The evaluation key is a public key that the server needs to process encrypted data. It is therefore transmitted to the server for further processing as well. """ ) keygen_button = gr.Button("Generate the keys and send evaluation key to the server.") evaluation_key = gr.Textbox( label="Evaluation key representation:", max_lines=2, interactive=False ) client_id = gr.Textbox(label="", max_lines=2, interactive=False, visible=False) gr.Markdown("## Step 2: Fill in some information.") gr.Markdown( """ Select the information that corresponds to the profile you want to evaluate. Three sources of information are represented in this model: - a user's personal information in order to evaluate his/her credit card eligibility; - the user’s bank account history, which provides any type of information on the user's banking information relevant to the decision (here, we consider duration of account); - and third party information, which represents any other information (here, employment history) that could provide additional insight relevant to the decision. """ ) with gr.Row(): with gr.Column(): gr.Markdown("### User") bool_inputs = gr.CheckboxGroup(["Car", "Property", "Mobile phone"], label="Which of the following do you actively hold or own?") num_children = gr.Slider(**CHILDREN_MIN_MAX, step=1, label="Number of children", info="How many children do you have ?") household_size = gr.Slider(**FAMILY_MIN_MAX, step=1, label="Household size", info="How many members does your household have? ?") total_income = gr.Slider(**INCOME_MIN_MAX, label="Income", info="What's you total yearly income (in euros) ?") age = gr.Slider(**AGE_MIN_MAX, step=1, label="Age", info="How old are you ?") income_type = gr.Dropdown(choices=INCOME_TYPES, value=INCOME_TYPES[0], label="Income type", info="What is your main type of income ?") education_type = gr.Dropdown(choices=EDUCATION_TYPES, value=EDUCATION_TYPES[0], label="Education", info="What is your education background ?") family_status = gr.Dropdown(choices=FAMILY_STATUS, value=FAMILY_STATUS[0], label="Family", info="What is your family status ?") occupation_type = gr.Dropdown(choices=OCCUPATION_TYPES, value=OCCUPATION_TYPES[0], label="Occupation", info="What is your main occupation ?") housing_type = gr.Dropdown(choices=HOUSING_TYPES, value=HOUSING_TYPES[0], label="Housing", info="In what type of housing do you live ?") with gr.Column(): gr.Markdown("### Bank ") account_age = gr.Slider(**ACCOUNT_MIN_MAX, step=1, label="Account age (months)", info="How long have this person had this bank account (in months) ?") with gr.Column(): gr.Markdown("### Third party ") employed = gr.Radio(["Yes", "No"], label="Is the person employed ?", value="Yes") years_employed = gr.Slider(**EMPLOYED_MIN_MAX, step=1, label="Years of employment", info="How long have this person been employed (in years) ?") gr.Markdown("## Step 3: Encrypt the inputs using FHE and send them to the server.") with gr.Row(): with gr.Column(): gr.Markdown("### User") encrypt_button_user = gr.Button("Encrypt the inputs and send to server.") encrypted_input_user = gr.Textbox( label="Encrypted input representation:", max_lines=2, interactive=False ) with gr.Column(): gr.Markdown("### Bank ") encrypt_button_bank = gr.Button("Encrypt the inputs and send to server.") encrypted_input_bank = gr.Textbox( label="Encrypted input representation:", max_lines=2, interactive=False ) with gr.Column(): gr.Markdown("### Third Party ") encrypt_button_third_party = gr.Button("Encrypt the inputs and send to server.") encrypted_input_third_party = gr.Textbox( label="Encrypted input representation:", max_lines=2, interactive=False ) gr.Markdown("# Server side") gr.Markdown( """ Once the server receives the encrypted inputs, it can compute the prediction without ever needing to decrypt any value. This server employs an [XGBoost](https://github.com/dmlc/xgboost) classifier model that has been trained on a synthetic data-set. """ ) gr.Markdown("## Step 4: Run FHE execution.") execute_fhe_button = gr.Button("Run FHE execution.") fhe_execution_time = gr.Textbox( label="Total FHE execution time (in seconds):", max_lines=1, interactive=False ) gr.Markdown("# Client side") gr.Markdown( """ Once the server completed the inference, the encrypted output is returned to the user. """ ) gr.Markdown("## Step 5: Receive the encrypted output from the server.") gr.Markdown( """ The value displayed below is a shortened byte representation of the actual encrypted output. """ ) get_output_button = gr.Button("Receive the encrypted output from the server.") encrypted_output_representation = gr.Textbox( label="Encrypted output representation: ", max_lines=2, interactive=False ) gr.Markdown("## Step 6: Decrypt the output.") gr.Markdown( """ The user is able to decrypt the prediction using its private key. """ ) decrypt_button = gr.Button("Decrypt the output") prediction_output = gr.Textbox( label="Prediction", max_lines=1, interactive=False ) # Button generate the keys keygen_button.click( keygen_send, outputs=[client_id, evaluation_key, keygen_button], ) # Button to pre-process, generate the key, encrypt and send the user inputs from the client # side to the server encrypt_button_user.click( pre_process_encrypt_send_user, inputs=[client_id, bool_inputs, num_children, household_size, total_income, age, \ income_type, education_type, family_status, occupation_type, housing_type], outputs=[encrypted_input_user], ) # Button to pre-process, generate the key, encrypt and send the bank inputs from the client # side to the server encrypt_button_bank.click( pre_process_encrypt_send_bank, inputs=[client_id, account_age], outputs=[encrypted_input_bank], ) # Button to pre-process, generate the key, encrypt and send the third party inputs from the # client side to the server encrypt_button_third_party.click( pre_process_encrypt_send_third_party, inputs=[client_id, employed, years_employed], outputs=[encrypted_input_third_party], ) # Button to send the encodings to the server using post method execute_fhe_button.click(run_fhe, inputs=[client_id], outputs=[fhe_execution_time]) # Button to send the encodings to the server using post method get_output_button.click( get_output, inputs=[client_id], outputs=[encrypted_output_representation], ) # Button to decrypt the output decrypt_button.click( decrypt_output, inputs=[client_id], outputs=[prediction_output], ) gr.Markdown( "The app was built with [Concrete-ML](https://github.com/zama-ai/concrete-ml), a " "Privacy-Preserving Machine Learning (PPML) open-source set of tools by [Zama](https://zama.ai/). " "Try it yourself and don't forget to star on Github ⭐." ) demo.launch(share=False)