File size: 17,184 Bytes
6571e75
e733251
6571e75
f4fb0fb
 
 
e733251
 
 
 
f4fb0fb
cfd40e9
e733251
 
 
98e29c4
cfd40e9
b052718
e733251
 
 
cfd40e9
 
e733251
 
65f24dd
e733251
a469d8f
 
 
 
f4fb0fb
e733251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f4fb0fb
e733251
f4fb0fb
e733251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
adea9fe
 
 
 
 
 
 
 
 
 
 
 
 
 
a0e7778
4a41d27
 
 
 
adea9fe
2174f21
 
 
 
a469d8f
 
 
f4fb0fb
e81b9bf
a0e7778
 
 
 
 
f4fb0fb
98e29c4
a0e7778
 
941a624
 
5aa6a89
 
 
 
 
 
 
 
 
 
a0e7778
5aa6a89
 
f4fb0fb
e81b9bf
98e29c4
a0e7778
 
f4fb0fb
 
7269140
2d2f463
e733251
f4fb0fb
2d2f463
f4fb0fb
e733251
2d2f463
7269140
98e29c4
f4fb0fb
7269140
f4fb0fb
e733251
f4fb0fb
5aa6a89
 
 
e733251
5aa6a89
 
7269140
 
5aa6a89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7269140
5aa6a89
 
98e29c4
5aa6a89
 
 
a469d8f
8b7ecaf
 
 
 
5ee61ec
a469d8f
7269140
a469d8f
 
4a41d27
79746f2
 
 
8b7ecaf
 
fbbf69b
79746f2
adea9fe
5ee61ec
a469d8f
 
 
a635b88
fbbf69b
 
 
 
 
79746f2
fbbf69b
 
5ee61ec
fbbf69b
79746f2
 
 
fbbf69b
 
 
98e29c4
79746f2
 
 
fbbf69b
a469d8f
7269140
f4fb0fb
2cb848b
 
 
 
 
6cbc9d8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
adea9fe
 
eae9bf6
f9b174b
eae9bf6
 
adea9fe
f9b174b
eae9bf6
 
 
 
 
2cb848b
eae9bf6
956fd2d
eae9bf6
 
 
6cbc9d8
eae9bf6
 
956fd2d
2cb848b
eae9bf6
2cb848b
eae9bf6
 
 
 
 
6cbc9d8
eae9bf6
 
956fd2d
6cbc9d8
eae9bf6
7f5090e
a469d8f
7269140
 
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
import yaml
from utils import set_operator_role_and_location, set_eu_market_status, check_within_scope_act, check_prohibited

# TODO tells the user where the compliance analysis failed
# TODO cite article from yaml file as explanation

def check_overall_compliance_ui(cards):
   
    project_cc = cards['project_file']

    dispositive_variables = {
    "ai_project_type": {
        "ai_system": project_cc['ai_system']['ai_system']['value'],
        "gpai_model": project_cc['gpai_model']['gpai_model']['value'],
        "high_risk_ai_system": False,
        "gpai_model_systemic_risk": False
    },
    "operator_details": {
        "provider": project_cc['operator_details']['provider']['value'],
        "eu_located": project_cc['operator_details']['eu_located']['value'],
        "output_used": project_cc['operator_details']['output_used']['value']
    },
    "eu_market_status": {
        "placed_on_market": project_cc['eu_market_status']['placed_on_market']['value'],
        "put_into_service": project_cc['eu_market_status']['put_into_service']['value']
    },
    "project_intended_purposes": [],
    "project_cc_pass": False,
    "data_cc_pass": False,
    "model_cc_pass": False,
    "msg": []
    }
   
    # check intended purposes 
    for card in cards['data_files']:
        data_cc = card[1]
        dispositive_variables = check_intended_purpose(dispositive_variables, project_cc, data_cc)
        
    for card in cards['model_files']:
        model_cc = card[1]
        dispositive_variables = check_intended_purpose(dispositive_variables, project_cc, model_cc)
   
    # for each model_cc and data_cc - run analysis with ref to project_cc
    dispositive_variables = run_compliance_analysis_on_project(dispositive_variables, project_cc)

    for card in cards['data_files']:
        data_cc = card[1]
        dispositive_variables = run_compliance_analysis_on_data(dispositive_variables, data_cc)
            
    for card in cards['model_files']:
        model_cc = card[1]
        dispositive_variables = run_compliance_analysis_on_model(dispositive_variables, model_cc)

    return dispositive_variables

def check_overall_compliance(cards):
   
    with open(cards['project_file'], 'r') as project_filepath:
        print(project_filepath)
        project_cc = yaml.safe_load(project_filepath.read())

    dispositive_variables = {
    "ai_project_type": {
        "ai_system": project_cc['ai_system']['ai_system']['value'],
        "gpai_model": project_cc['gpai_model']['gpai_model']['value'],
        "high_risk_ai_system": False,
        "gpai_model_systemic_risk": False
    },
    "operator_details": {
        "provider": project_cc['operator_details']['provider']['value'],
        "eu_located": project_cc['operator_details']['eu_located']['value'],
        "output_used": project_cc['operator_details']['output_used']['value']
    },
    "eu_market_status": {
        "placed_on_market": project_cc['eu_market_status']['placed_on_market']['value'],
        "put_into_service": project_cc['eu_market_status']['put_into_service']['value']
    },
    "project_intended_purposes": [],
    "project_cc_pass": False,
    "data_cc_pass": False,
    "model_cc_pass": False,
    "msg": []
    }
   
    # check intended purposes 
    for card in cards['data_files']:
        with open(card, 'r') as data_filepath:
            data_cc = yaml.safe_load(data_filepath.read())
            dispositive_variables = check_intended_purpose(dispositive_variables, project_cc, data_cc)
        
    for card in cards['model_files']:
        with open(card, 'r') as model_filepath:
            model_cc = yaml.safe_load(model_filepath.read())
            dispositive_variables = check_intended_purpose(dispositive_variables, project_cc, model_cc)
   
    # for each model_cc and data_cc - run analysis with ref to project_cc
    dispositive_variables = run_compliance_analysis_on_project(dispositive_variables, project_cc)

    for card in cards['data_files']:
        with open(card, 'r') as data_filepath:
            data_cc = yaml.safe_load(data_filepath.read())
            dispositive_variables = run_compliance_analysis_on_data(dispositive_variables, data_cc)
            
    for card in cards['model_files']:
        with open(card, 'r') as model_filepath:
            model_cc = yaml.safe_load(model_filepath.read())
            dispositive_variables = run_compliance_analysis_on_model(dispositive_variables, model_cc)

    return dispositive_variables

def run_compliance_analysis_on_project(dispositive_variables, project_cc_yaml):
        
    # Project Type    
    if project_cc_yaml['ai_system']['ai_system']['value']:
        dispositive_variables['ai_project_type']['ai_system'] = True
    if project_cc_yaml['gpai_model']['gpai_model']['value']:
        dispositive_variables['ai_project_type']['gpai_model'] = True
    if project_cc_yaml['ai_system']['ai_system']['value'] == True and project_cc_yaml['gpai_model']['gpai_model']['value'] == True:
        dispositive_variables['msg'].append("Your project cannot be both an AI system and a GPAI model. Please revise your Project CC accordingly.")
        return dispositive_variables
    
    if any(item['value'] for item in project_cc_yaml['high_risk_ai_system'].values()) == True:
        dispositive_variables['ai_project_type']["high_risk_ai_system"] = True
    
    if dispositive_variables['ai_project_type']['ai_system'] == True:
        for value in project_cc_yaml['high_risk_ai_system']:
            if value and sum(map(bool, [
                    project_cc_yaml['high_risk_ai_system_exceptions']['filter_exception_rights']['value'], 
                    project_cc_yaml['high_risk_ai_system_exceptions']['filter_exception_narrow']['value'],
                    project_cc_yaml['high_risk_ai_system_exceptions']['filter_exception_human']['value'],
                    project_cc_yaml['high_risk_ai_system_exceptions']['filter_exception_deviation']['value'], 
                    project_cc_yaml['high_risk_ai_system_exceptions']['filter_exception_prep']['value']])
                    ) >= 1:
                
                dispositive_variables['ai_project_type']["high_risk_ai_system"] = False
    
    if dispositive_variables['ai_project_type']['gpai_model'] == True:
        if project_cc_yaml['gpai_model_systemic_risk']['evaluation']['value'] or project_cc_yaml['gpai_model_systemic_risk']['flops']['value']:
            dispositive_variables['ai_project_type']["gpai_model_systemic_risk"] = True
    
    # Operator Type
    dispositive_variables = set_operator_role_and_location(dispositive_variables, project_cc_yaml)
    dispositive_variables = set_eu_market_status(dispositive_variables, project_cc_yaml)

    # Check if project is within scope of the Compliance Cards project. If not, inform user.
    if project_cc_yaml['operator_details']['provider']['value'] == True:
        dispositive_variables['msg'].append("Project is within the scope of the Compliance Cards system. Let's continue...") 
    else: 
        dispositive_variables['msg'].append("Project is not within the scope of the initial version of the Compliance Cards system.")
        return dispositive_variables
    
    # Check if the project is within scope of the Act. If it's not, the analysis is over.
    if check_within_scope_act(dispositive_variables, project_cc_yaml):
        dispositive_variables['msg'].append("Project is within the scope of Act. Let's continue...") 
    else: 
        dispositive_variables['msg'].append("Project is not within the scope of what is regulated by the Act.")
        return dispositive_variables

    # Check for prohibited practices. If any exist, the analysis is over.
    if check_prohibited(project_cc_yaml) == True: 
        dispositive_variables['msg'].append("Project is non-compliant due to a prohibited practice.")
        return dispositive_variables
    else: 
        print("Project does not contain prohibited practies. Let's continue...")

    # If project is high-risk AI system, check that is has met all the requirements for such systems: 
    if dispositive_variables['ai_project_type']["high_risk_ai_system"] == True:

        for key in project_cc_yaml['risk_management_system']:
            if project_cc_yaml['risk_management_system'][f'{key}']['value'] == True:
                dispositive_variables['msg'].append("Because of project-level characteristics, this high-risk AI system fails the risk management requirements under Article 9.")
        for key in project_cc_yaml['technical_documentation']:
            if project_cc_yaml['technical_documentation'][f'{key}']['value'] == True:
                dispositive_variables['msg'].append("Because of project-level characteristics, this high-risk AI system fails the risk management requirements under Article 11.")            
        
        for key in project_cc_yaml['record_keeping']:
            if project_cc_yaml['record_keeping'][f'{key}']['value'] == True:
                dispositive_variables['msg'].append("Because of project-level characteristics, this high-risk AI system fails the risk management requirements under Article 12.")     
        
        for key in project_cc_yaml['transparency_and_provision_of_information_to_deployers']:
            if project_cc_yaml['transparency_and_provision_of_information_to_deployers'][f'{key}']['value'] == True:
                dispositive_variables['msg'].append("Because of project-level characteristics, this high-risk AI system fails the transparency requirements under Article 13.")  
        
        for key in project_cc_yaml['human_oversight']:
            if project_cc_yaml['human_oversight'][f'{key}']['value'] == True:
                dispositive_variables['msg'].append("Because of project-level characteristics, this high-risk AI system fails the human oversight requirements under Article 14.")  
        
        for key in project_cc_yaml['accuracy_robustness_cybersecurity']:
            if project_cc_yaml['accuracy_robustness_cybersecurity'][f'{key}']['value'] == True:
                dispositive_variables['msg'].append("Because of project-level characteristics, this high-risk AI system fails the accuracy, robustness, and cybersecurity requirements under Article 15.")  
        
        for key in project_cc_yaml['quality_management_system']:
            if project_cc_yaml['quality_management_system'][f'{key}']['value'] == True:
                dispositive_variables['msg'].append("Because of project-level characteristics, this high-risk AI system fails the accuracy, robustness, and cybersecurity requirements under Article 17.") 

    if dispositive_variables['ai_project_type']["gpai_model"] == True:
        
        if dispositive_variables['ai_project_type']["gpai_model_systemic_risk"] == True:
            for key in project_cc_yaml['gpai_models_with_systemic_risk_obligations']:
                if project_cc_yaml['gpai_models_with_systemic_risk_obligations'][f'{key}']['value'] == True:
                    dispositive_variables['msg'].append("GPAI model with systematic risk fails the transparency requirements under Article 55.")

        for obligation_cat in project_cc_yaml['gpai_model_obligations']:
            for obligation in project_cc_yaml['gpai_model_obligations'][f'{obligation_cat}']:
                if project_cc_yaml['gpai_model_obligations'][f'{obligation_cat}'][f'{obligation}']['value'] == True:
                    dispositive_variables['msg'].append("GPAI model fails the transparency requirements under Article 53.")
    
    return dispositive_variables

def run_compliance_analysis_on_data(dispositive_variables, data_cc_yaml): 
    
    if dispositive_variables['ai_project_type']["high_risk_ai_system"] == True:
        for key in data_cc_yaml['high_risk_ai_system_requirements']:
            if data_cc_yaml['high_risk_ai_system_requirements'][f'{key}']['value'] == True:
                dispositive_variables['msg'].append(f"This high-risk AI system fails the {key} requirements under {data_cc_yaml['high_risk_ai_system_requirements'][f'{key}']['article']}.")

    if dispositive_variables['ai_project_type']["gpai_model"] == True:
        for value in data_cc_yaml['gpai_model_requirements']:
            if data_cc_yaml['gpai_model_requirements'][f'{value}'] == True:
                dispositive_variables['msg'].append(f"")

    return dispositive_variables
    
def run_compliance_analysis_on_model(dispositive_variables, model_cc_yaml):  
    
    # If project involves a high-risk AI system, then make sure all the relevant model requirements are met (relevant attributes are positive)

    if dispositive_variables['ai_project_type']["high_risk_ai_system"] == True:
        for value in model_cc_yaml['high_risk_ai_system_requirements']:
            if model_cc_yaml['high_risk_ai_system_requirements'][f'{value}'] == True:
                dispositive_variables['msg'].append(f"This high-risk AI system fails the {key} requirements under {model_cc_yaml['high_risk_ai_system_requirements'][f'{key}']['article']}.")

    # If project involves a GPAI model, then make sure all the relevant model requirements are met (relevant attributes are positive)
    
    if dispositive_variables['ai_project_type']["gpai_model"] == True:
        for key in model_cc_yaml['gpai_model_requirements']:
            if model_cc_yaml['gpai_model_requirements'][f'{key}']['value'] == True:
                dispositive_variables['msg'].append(f"This high-risk AI system fails the {key} requirements under {model_cc_yaml['gpai_model_requirements'][f'{key}']['article']}.")

        # If the GPAI model additionally carries systemic risk, then make sure all the relevant model requirements are met (relevant attributes are positive)
        
        if dispositive_variables['ai_project_type']["gpai_model_systemic_risk"] == True:          
            for key in model_cc_yaml['gpai_model_with_systemic_risk_requirements']:
                if model_cc_yaml['gpai_model_with_systemic_risk_requirements'][f'{key}']['value'] == True:
                    dispositive_variables['msg'].append(f"This high-risk AI system fails the {key} requirements under {model_cc_yaml['gpai_model_with_systemic_risk_requirements'][f'{key}']['article']}.")
   
    return dispositive_variables

def check_intended_purpose(dispositive_variables, project_cc, other_cc):
    
    # We want to run this function for everything classified as a high_risk_ai_system
    # We also need to run it for all 
    # Add any of the intended purposes of the overall project to a set of intended purposes
    
    # intended_purpose = ['safety_component',
    #                     "product_regulated_machinery",
    #                     "product_regulated_toy",
    #                     "product_regulated_watercraft",
    #                     "biometric_categorization",
    #                     "emotion_recognition",
    #                     "critical_infrastructure",
    #                     "admission",
    #                     "recruitment",
    #                     "public_assistance",
    #                     "victim_assessment",
    #                     "polygraph",
    #                     "judicial"]
    
    project_intended_purposes = []
    dataset_intended_purposes = []
    model_intended_purposes = []

    if dispositive_variables['ai_project_type']['high_risk_ai_system'] == False:
        dispositive_variables['msg'].append(f"Not high-risk")
        return dispositive_variables
    
    if dispositive_variables['ai_project_type']['high_risk_ai_system'] == True:
        for key in project_cc['high_risk_ai_system']:
            if project_cc['high_risk_ai_system'][f'{key}']['value']:
                project_intended_purposes.append(key) 
        
        # For each Data CC, put the intended uses in a set and then make sure the Project's intended use is in the set
    
        if other_cc['card_details']['card_type'] == 'data':
            data_cc = other_cc
            for key in data_cc['intended_purpose']:
                if data_cc['intended_purpose'][f'{key}']['value']:
                    dataset_intended_purposes.append(key) 

            for purpose in project_intended_purposes:
                if purpose not in dataset_intended_purposes:
                    dispositive_variables['msg'].append(f"You are not compliant because {purpose} is not a valid purpose for {data_cc['card_details']['card_label']}")

        # Now do the exact same thing for all models

        if other_cc['card_details']['card_type'] == 'model':
            model_cc = other_cc        
            for key in model_cc['intended_purpose']:
                if model_cc['intended_purpose'][f'{key}']['value']:
                    model_intended_purposes.append(key) 

            for purpose in project_intended_purposes:
                if purpose not in model_intended_purposes:
                    dispositive_variables['msg'].append(f"You are not compliant because {purpose} is not a valid purpose for {model_cc['card_details']['card_label']}")

        dispositive_variables['project_intended_purposes'] = project_intended_purposes

    return dispositive_variables