File size: 16,978 Bytes
9a997e4
1ba3f22
 
 
 
 
 
 
9a997e4
 
 
 
 
 
 
 
 
 
b47829b
 
 
9a997e4
 
bc345ce
8e0d56d
bc345ce
8e0d56d
9a997e4
1ad0c1c
b47829b
1ba3f22
 
 
 
 
 
 
 
 
 
 
 
03475de
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235e54a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59a3f3b
 
 
 
 
 
 
235e54a
747c295
0a14c46
 
747c295
 
316f8e9
 
 
747c295
 
 
 
bc345ce
bf71bfa
 
 
bc345ce
 
74c0c8e
 
 
 
 
 
747c295
0a14c46
 
747c295
 
e3103dd
 
8e0d56d
 
 
 
 
61cd73f
 
 
 
747c295
 
 
1ba3f22
 
482af6f
b47829b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8a003cf
 
b47829b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1ba3f22
0a14c46
 
8e0d56d
9a997e4
8e0d56d
1ba3f22
 
0287aa5
0a14c46
 
482af6f
0a14c46
 
 
 
 
 
 
8a003cf
 
c119738
9a997e4
c119738
1ba3f22
 
0287aa5
0a14c46
 
482af6f
0a14c46
 
 
 
 
 
 
 
8a003cf
 
8e0d56d
1ba3f22
8e0d56d
9a997e4
 
1ba3f22
8e0d56d
74c0c8e
8e0d56d
 
74c0c8e
 
03475de
74c0c8e
 
 
 
 
 
 
03475de
74c0c8e
 
8e0d56d
74c0c8e
8e0d56d
 
b47829b
03475de
74c0c8e
 
03475de
0a14c46
 
1ba3f22
747c295
 
 
 
32a7fbc
 
747c295
1ba3f22
 
03475de
1ba3f22
 
 
 
74c0c8e
03475de
74c0c8e
0a14c46
 
 
1ba3f22
747c295
8e0d56d
316f8e9
 
 
 
747c295
1ba3f22
 
747c295
8a003cf
 
8e0d56d
747c295
1ba3f22
 
747c295
7ba6721
bf71bfa
7ba6721
1ba3f22
0e9fc02
1ba3f22
 
1ad0c1c
 
 
 
03475de
9a997e4
1ba3f22
482af6f
0a14c46
74c0c8e
 
8e0d56d
61cd73f
74c0c8e
61cd73f
74c0c8e
61cd73f
 
 
 
 
74c0c8e
9a997e4
b47829b
74c0c8e
9a997e4
b47829b
61cd73f
9a997e4
1ba3f22
74c0c8e
b47829b
 
 
03475de
9a997e4
1ba3f22
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
"""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,
    FAMILY_MIN_MAX,
    INCOME_TYPES,
    OCCUPATION_TYPES,
    HOUSING_TYPES,
    EDUCATION_TYPES,
    FAMILY_STATUS,
    YEARS_EMPLOYED_BINS,
    INCOME_VALUE,
    AGE_VALUE,
)
from backend import (
    keygen_send,
    pre_process_encrypt_send_applicant,
    pre_process_encrypt_send_bank,
    pre_process_encrypt_send_credit_bureau,
    run_fhe,
    get_output_and_decrypt,
    explain_encrypt_run_decrypt,
)


subprocess.Popen(["uvicorn", "server:app"], cwd=REPO_DIR)
time.sleep(3)


demo = gr.Blocks()


print("Starting the demo...")
with demo:
    gr.Markdown(
        """
        <p align="center">
            <img width=200 src="file/images/logos/zama.jpg">
        </p>
        <h1 align="center">Encrypted Credit Card Approval Prediction Using Fully Homomorphic Encryption</h1>
        <p align="center">
            <a href="https://github.com/zama-ai/concrete-ml"> <img style="vertical-align: middle; display:inline-block; margin-right: 3px;" width=15 src="file/images/logos/github.png">Concrete-ML</a>
            β€”
            <a href="https://docs.zama.ai/concrete-ml"> <img style="vertical-align: middle; display:inline-block; margin-right: 3px;" width=15 src="file/images/logos/documentation.png">Documentation</a>
            β€”
            <a href="https://zama.ai/community"> <img style="vertical-align: middle; display:inline-block; margin-right: 3px;" width=15 src="file/images/logos/community.png">Community</a>
            β€”
            <a href="https://twitter.com/zama_fhe"> <img style="vertical-align: middle; display:inline-block; margin-right: 3px;" width=15 src="file/images/logos/x.png">@zama_fhe</a>
        </p>
        """
    )

    with gr.Accordion("What is credit scoring for card approval?", open=False):
        gr.Markdown(
            """
            It is a complex process that involves several entities: the applicant, the bank, the 
            credit bureau, and the credit scoring agency. When you apply for a credit card, you
            provide personal and financial information to the bank. This might include your income,
            employment status, and existing debts. The bank uses this information to assess your 
            creditworthiness. To do this, they often turn to credit bureaus and credit scoring 
            agencies. 
            - Credit bureaus collect and maintain data on consumers' credit and payment 
            histories. This data includes your past and current debts, payment history, and the 
            length of your credit history. 
            - Credit scoring agencies use algorithms to analyze 
            the data from credit bureaus and generate a credit score. This score is a numerical 
            representation of your creditworthiness. 
            - The bank uses your credit score, along with 
            the information you provided, to make a decision on your credit card application. A 
            higher credit score generally increases your chances of being approved and may result 
            in better terms (like a lower interest rate). 
            """
        )

    with gr.Accordion("Why is it critical to add a new privacy layer to this process?", open=False):
        gr.Markdown(
            """
            The data involved is highly sensitive. It includes personal details like your Social 
            Security number, income, and credit history. There's significant sharing of data 
            between different entities. Your information is not just with the bank, but also with 
            credit bureaus and scoring agencies. The more entities that have access to your data, 
            the greater the risk of a data breach. This can lead to identity theft and financial 
            fraud. There's also the issue of data accuracy. Mistakes in credit reports can lead to 
            unjustly low credit scores, affecting your ability to get credit. 
            """
        )

    with gr.Accordion(
        "Why is Fully Homomorphic Encryption (FHE) a solution for better credit scoring?", 
        open=False,
    ):
        gr.Markdown(
            """
            Fully Homomorphic Encryption (FHE) is seen as an ideal solution for enhancing privacy 
            and accuracy in credit scoring processes involving multiple parties like applicants, 
            banks, credit bureaus, and credit scoring agencies. It allows data to be encrypted and 
            processed without ever needing to decrypt it. This means that sensitive data can be 
            shared and analyzed without exposing the actual information to any of the parties or 
            the server processing it. In the context of credit scoring, this would enable a more 
            thorough and accurate assessment of a person's creditworthiness. Data from various 
            sources can be combined and analyzed to make a more informed decision, yet each party's 
            data remains confidential. As a result, the risk of data leaks or breaches is 
            significantly minimized, addressing major privacy concerns. 

            To summarize, FHE provides a means to make more accurate credit eligibility decisions 
            while maintaining strict data privacy, offering a sophisticated solution to the delicate 
            balance between data utility and confidentiality.
            """
        )

    gr.Markdown(
        """
        <p align="center">
            <img src="file/images/banner.png">
        </p>
        """
    )

    gr.Markdown("## Step 1: Generate the keys.")
    gr.Markdown("<hr />")
    gr.Markdown("<span style='color:grey'>Applicant, Bank and Credit bureau setup</span>")
    gr.Markdown(
        """
        - The private key is generated jointly by the entities that collaborate to compute the 
            credit score. It is used to encrypt and decrypt the data and shall never be shared with 
            any other party.
        - 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)
    
    # Button generate the keys
    keygen_button.click(
        keygen_send,
        outputs=[client_id, evaluation_key, keygen_button],
    )

    gr.Markdown("## Step 2: Fill in some information.")
    gr.Markdown("<hr />")
    gr.Markdown("<span style='color:grey'>Applicant, Bank and Credit bureau setup</span>")
    gr.Markdown(
        """
        Select the information that corresponds to the profile you want to evaluate. Three sources 
        of information are represented in this model:
        - the applicant's personal information in order to evaluate his/her credit card eligibility;
        - the applicant bank account history, which provides any type of information on the 
        applicant's banking information relevant to the decision (here, we consider duration of 
        account);
        - and credit bureau information, which represents any other information (here, 
        employment history) that could provide additional insight relevant to the decision.
        
        Please always encrypt and send the values (through the buttons on the right) once updated
        before running the FHE inference.
        """
    )

    with gr.Row():
        with gr.Column():
            gr.Markdown("### Step 2.1 - Applicant information πŸ§‘β€πŸ’»")
            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,
                value=INCOME_VALUE,
                label="Income", 
                info="What's you total yearly income (in euros) ?"
            )
            age = gr.Slider(
                **AGE_MIN_MAX,
                value=AGE_VALUE, 
                step=1, 
                label="Age", 
                info="How old are you ?"
            )

        with gr.Column():
            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.Row():
        with gr.Column(scale=2):
            encrypt_button_applicant = gr.Button("Encrypt the inputs and send to server.")
            
            encrypted_input_applicant = gr.Textbox(
                label="Encrypted input representation:", max_lines=2, interactive=False
            )

    gr.Markdown("<hr />")
    with gr.Column():
        gr.Markdown("### Step 2.2 - Bank information 🏦")
        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.Row():
        with gr.Column(scale=2):
            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
            )

    gr.Markdown("<hr />")
    with gr.Column():
        gr.Markdown("### Step 2.3 - Credit bureau information 🏒")
        employed = gr.Radio(["Yes", "No"], label="Is the person employed ?", value="Yes")
        years_employed = gr.Dropdown(
            choices=YEARS_EMPLOYED_BINS, 
            value=YEARS_EMPLOYED_BINS[0], 
            label="Years of employment", 
            info="How long have this person been employed (in years) ?"
        )

    with gr.Row():
        with gr.Column(scale=2):
            encrypt_button_credit_bureau = gr.Button("Encrypt the inputs and send to server.")

            encrypted_input_credit_bureau = gr.Textbox(
                label="Encrypted input representation:", max_lines=2, interactive=False
            )

    # Button to pre-process, generate the key, encrypt and send the applicant inputs from the client 
    # side to the server
    encrypt_button_applicant.click(
        pre_process_encrypt_send_applicant,
        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_applicant, encrypt_button_applicant],
    )

    # 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, encrypt_button_bank],
    )

    # Button to pre-process, generate the key, encrypt and send the credit bureau inputs from the 
    # client side to the server    
    encrypt_button_credit_bureau.click(
        pre_process_encrypt_send_credit_bureau,
        inputs=[client_id, years_employed, employed],
        outputs=[encrypted_input_credit_bureau, encrypt_button_credit_bureau],
    )

    gr.Markdown("## Step 3: Run the FHE evaluation.")
    gr.Markdown("<hr />")
    gr.Markdown("<span style='color:grey'>Server Side</span>")
    gr.Markdown(
        """
        Once the server receives the encrypted inputs, it can compute the prediction without ever 
        needing to decrypt any value.

        This server employs a [Decision Tree](https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html)
        classifier model that has been trained on a synthetic data-set.
        """
    )

    execute_fhe_button = gr.Button("Run the FHE evaluation.")
    fhe_execution_time = gr.Textbox(
        label="Total FHE execution time (in seconds):", max_lines=1, interactive=False
    )

    # Button to send the encodings to the server using post method
    execute_fhe_button.click(run_fhe, inputs=[client_id], outputs=[fhe_execution_time, execute_fhe_button])

    gr.Markdown("## Step 4: Receive the encrypted output from the server and decrypt.")
    gr.Markdown("<hr />")
    gr.Markdown("<span style='color:grey'>Applicant, Bank and Credit bureau decryption</span>")
    gr.Markdown(
        """
        Once the server completed the inference, the encrypted output is returned to the applicant.

        The three entities that provide the information to compute the credit score are the only 
        ones that can decrypt the result. They take part in a decryption protocol that allows to 
        only decrypt the full result when all three parties decrypt their share of the result.
        """
    )
    gr.Markdown(
        """
        The first value displayed below is a shortened byte representation of the actual encrypted 
        output.
        The applicant is then able to decrypt the value using its private key.
        """
    )

    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
    )
    prediction_output = gr.Textbox(
        label="Prediction", max_lines=1, interactive=False
    )

    # Button to send the encodings to the server using post method
    get_output_button.click(
        get_output_and_decrypt, 
        inputs=[client_id], 
        outputs=[prediction_output, encrypted_output_representation, get_output_button],
    )

    gr.Markdown("## Step 5: Explain the prediction (only if your credit card is likely to be denied).")
    gr.Markdown("<hr />")
    gr.Markdown(
        """
        In case the credit card is likely to be denied, the applicant can ask for how many years of 
        employment would most likely be required in order to increase the chance of getting a 
        credit card approval.
        
        All of the above steps are combined into a single button for simplicity. The following 
        button therefore encrypts the same inputs (except the years of employment, which varies) 
        from all three parties, runs the new prediction in FHE and decrypts the output. 
        
        In case the following states to try a new "Years of employment" input, one can simply 
        update the value in Step 2 and directly run Step 6 once more.  
        """
    )
    explain_button = gr.Button(
        "Encrypt the inputs, compute in FHE and decrypt the output."
    )
    explain_prediction = gr.Textbox(
        label="Additional years of employed required.", interactive=False
    )

    # Button to explain the prediction
    explain_button.click(
        explain_encrypt_run_decrypt,
        inputs=[client_id, prediction_output, years_employed, employed],
        outputs=[explain_prediction, explain_button],
    )

    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 &#11088;."
    )

demo.launch(share=False)