aimodelshare 0.3.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. aimodelshare/README.md +26 -0
  2. aimodelshare/__init__.py +100 -0
  3. aimodelshare/aimsonnx.py +2381 -0
  4. aimodelshare/api.py +836 -0
  5. aimodelshare/auth.py +163 -0
  6. aimodelshare/aws.py +511 -0
  7. aimodelshare/aws_client.py +173 -0
  8. aimodelshare/base_image.py +154 -0
  9. aimodelshare/bucketpolicy.py +106 -0
  10. aimodelshare/color_mappings/color_mapping_keras.csv +121 -0
  11. aimodelshare/color_mappings/color_mapping_pytorch.csv +117 -0
  12. aimodelshare/containerisation.py +244 -0
  13. aimodelshare/containerization.py +712 -0
  14. aimodelshare/containerization_templates/Dockerfile.txt +8 -0
  15. aimodelshare/containerization_templates/Dockerfile_PySpark.txt +23 -0
  16. aimodelshare/containerization_templates/buildspec.txt +14 -0
  17. aimodelshare/containerization_templates/lambda_function.txt +40 -0
  18. aimodelshare/custom_approach/__init__.py +1 -0
  19. aimodelshare/custom_approach/lambda_function.py +17 -0
  20. aimodelshare/custom_eval_metrics.py +103 -0
  21. aimodelshare/data_sharing/__init__.py +0 -0
  22. aimodelshare/data_sharing/data_sharing_templates/Dockerfile.txt +3 -0
  23. aimodelshare/data_sharing/data_sharing_templates/__init__.py +1 -0
  24. aimodelshare/data_sharing/data_sharing_templates/buildspec.txt +15 -0
  25. aimodelshare/data_sharing/data_sharing_templates/codebuild_policies.txt +129 -0
  26. aimodelshare/data_sharing/data_sharing_templates/codebuild_trust_relationship.txt +12 -0
  27. aimodelshare/data_sharing/download_data.py +620 -0
  28. aimodelshare/data_sharing/share_data.py +373 -0
  29. aimodelshare/data_sharing/utils.py +8 -0
  30. aimodelshare/deploy_custom_lambda.py +246 -0
  31. aimodelshare/documentation/Makefile +20 -0
  32. aimodelshare/documentation/karma_sphinx_theme/__init__.py +28 -0
  33. aimodelshare/documentation/karma_sphinx_theme/_version.py +2 -0
  34. aimodelshare/documentation/karma_sphinx_theme/breadcrumbs.html +70 -0
  35. aimodelshare/documentation/karma_sphinx_theme/layout.html +172 -0
  36. aimodelshare/documentation/karma_sphinx_theme/search.html +50 -0
  37. aimodelshare/documentation/karma_sphinx_theme/searchbox.html +14 -0
  38. aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css +2 -0
  39. aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css.map +1 -0
  40. aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css +2751 -0
  41. aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css.map +1 -0
  42. aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css +2 -0
  43. aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css.map +1 -0
  44. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.eot +0 -0
  45. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.svg +32 -0
  46. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.ttf +0 -0
  47. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff +0 -0
  48. aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff2 +0 -0
  49. aimodelshare/documentation/karma_sphinx_theme/static/js/theme.js +68 -0
  50. aimodelshare/documentation/karma_sphinx_theme/theme.conf +9 -0
  51. aimodelshare/documentation/make.bat +35 -0
  52. aimodelshare/documentation/requirements.txt +2 -0
  53. aimodelshare/documentation/source/about.rst +18 -0
  54. aimodelshare/documentation/source/advanced_features.rst +137 -0
  55. aimodelshare/documentation/source/competition.rst +218 -0
  56. aimodelshare/documentation/source/conf.py +58 -0
  57. aimodelshare/documentation/source/create_credentials.rst +86 -0
  58. aimodelshare/documentation/source/example_notebooks.rst +132 -0
  59. aimodelshare/documentation/source/functions.rst +151 -0
  60. aimodelshare/documentation/source/gettingstarted.rst +390 -0
  61. aimodelshare/documentation/source/images/creds1.png +0 -0
  62. aimodelshare/documentation/source/images/creds2.png +0 -0
  63. aimodelshare/documentation/source/images/creds3.png +0 -0
  64. aimodelshare/documentation/source/images/creds4.png +0 -0
  65. aimodelshare/documentation/source/images/creds5.png +0 -0
  66. aimodelshare/documentation/source/images/creds_file_example.png +0 -0
  67. aimodelshare/documentation/source/images/predict_tab.png +0 -0
  68. aimodelshare/documentation/source/index.rst +110 -0
  69. aimodelshare/documentation/source/modelplayground.rst +132 -0
  70. aimodelshare/exceptions.py +11 -0
  71. aimodelshare/generatemodelapi.py +1270 -0
  72. aimodelshare/iam/codebuild_policy.txt +129 -0
  73. aimodelshare/iam/codebuild_trust_relationship.txt +12 -0
  74. aimodelshare/iam/lambda_policy.txt +15 -0
  75. aimodelshare/iam/lambda_trust_relationship.txt +12 -0
  76. aimodelshare/json_templates/__init__.py +1 -0
  77. aimodelshare/json_templates/api_json.txt +155 -0
  78. aimodelshare/json_templates/auth/policy.txt +1 -0
  79. aimodelshare/json_templates/auth/role.txt +1 -0
  80. aimodelshare/json_templates/eval/policy.txt +1 -0
  81. aimodelshare/json_templates/eval/role.txt +1 -0
  82. aimodelshare/json_templates/function/policy.txt +1 -0
  83. aimodelshare/json_templates/function/role.txt +1 -0
  84. aimodelshare/json_templates/integration_response.txt +5 -0
  85. aimodelshare/json_templates/lambda_policy_1.txt +15 -0
  86. aimodelshare/json_templates/lambda_policy_2.txt +8 -0
  87. aimodelshare/json_templates/lambda_role_1.txt +12 -0
  88. aimodelshare/json_templates/lambda_role_2.txt +16 -0
  89. aimodelshare/leaderboard.py +174 -0
  90. aimodelshare/main/1.txt +132 -0
  91. aimodelshare/main/1B.txt +112 -0
  92. aimodelshare/main/2.txt +153 -0
  93. aimodelshare/main/3.txt +134 -0
  94. aimodelshare/main/4.txt +128 -0
  95. aimodelshare/main/5.txt +109 -0
  96. aimodelshare/main/6.txt +105 -0
  97. aimodelshare/main/7.txt +144 -0
  98. aimodelshare/main/8.txt +142 -0
  99. aimodelshare/main/__init__.py +1 -0
  100. aimodelshare/main/authorization.txt +275 -0
  101. aimodelshare/main/eval_classification.txt +79 -0
  102. aimodelshare/main/eval_lambda.txt +1709 -0
  103. aimodelshare/main/eval_regression.txt +80 -0
  104. aimodelshare/main/lambda_function.txt +8 -0
  105. aimodelshare/main/nst.txt +149 -0
  106. aimodelshare/model.py +1543 -0
  107. aimodelshare/modeluser.py +215 -0
  108. aimodelshare/moral_compass/README.md +408 -0
  109. aimodelshare/moral_compass/__init__.py +65 -0
  110. aimodelshare/moral_compass/_version.py +3 -0
  111. aimodelshare/moral_compass/api_client.py +601 -0
  112. aimodelshare/moral_compass/apps/__init__.py +69 -0
  113. aimodelshare/moral_compass/apps/ai_consequences.py +540 -0
  114. aimodelshare/moral_compass/apps/bias_detective.py +714 -0
  115. aimodelshare/moral_compass/apps/ethical_revelation.py +898 -0
  116. aimodelshare/moral_compass/apps/fairness_fixer.py +889 -0
  117. aimodelshare/moral_compass/apps/judge.py +888 -0
  118. aimodelshare/moral_compass/apps/justice_equity_upgrade.py +853 -0
  119. aimodelshare/moral_compass/apps/mc_integration_helpers.py +820 -0
  120. aimodelshare/moral_compass/apps/model_building_game.py +1104 -0
  121. aimodelshare/moral_compass/apps/model_building_game_beginner.py +687 -0
  122. aimodelshare/moral_compass/apps/moral_compass_challenge.py +858 -0
  123. aimodelshare/moral_compass/apps/session_auth.py +254 -0
  124. aimodelshare/moral_compass/apps/shared_activity_styles.css +349 -0
  125. aimodelshare/moral_compass/apps/tutorial.py +481 -0
  126. aimodelshare/moral_compass/apps/what_is_ai.py +853 -0
  127. aimodelshare/moral_compass/challenge.py +365 -0
  128. aimodelshare/moral_compass/config.py +187 -0
  129. aimodelshare/placeholders/model.onnx +0 -0
  130. aimodelshare/placeholders/preprocessor.zip +0 -0
  131. aimodelshare/playground.py +1968 -0
  132. aimodelshare/postprocessormodules.py +157 -0
  133. aimodelshare/preprocessormodules.py +373 -0
  134. aimodelshare/pyspark/1.txt +195 -0
  135. aimodelshare/pyspark/1B.txt +181 -0
  136. aimodelshare/pyspark/2.txt +220 -0
  137. aimodelshare/pyspark/3.txt +204 -0
  138. aimodelshare/pyspark/4.txt +187 -0
  139. aimodelshare/pyspark/5.txt +178 -0
  140. aimodelshare/pyspark/6.txt +174 -0
  141. aimodelshare/pyspark/7.txt +211 -0
  142. aimodelshare/pyspark/8.txt +206 -0
  143. aimodelshare/pyspark/__init__.py +1 -0
  144. aimodelshare/pyspark/authorization.txt +258 -0
  145. aimodelshare/pyspark/eval_classification.txt +79 -0
  146. aimodelshare/pyspark/eval_lambda.txt +1441 -0
  147. aimodelshare/pyspark/eval_regression.txt +80 -0
  148. aimodelshare/pyspark/lambda_function.txt +8 -0
  149. aimodelshare/pyspark/nst.txt +213 -0
  150. aimodelshare/python/my_preprocessor.py +58 -0
  151. aimodelshare/readme.md +26 -0
  152. aimodelshare/reproducibility.py +181 -0
  153. aimodelshare/sam/Dockerfile.txt +8 -0
  154. aimodelshare/sam/Dockerfile_PySpark.txt +24 -0
  155. aimodelshare/sam/__init__.py +1 -0
  156. aimodelshare/sam/buildspec.txt +11 -0
  157. aimodelshare/sam/codebuild_policies.txt +129 -0
  158. aimodelshare/sam/codebuild_trust_relationship.txt +12 -0
  159. aimodelshare/sam/codepipeline_policies.txt +173 -0
  160. aimodelshare/sam/codepipeline_trust_relationship.txt +12 -0
  161. aimodelshare/sam/spark-class.txt +2 -0
  162. aimodelshare/sam/template.txt +54 -0
  163. aimodelshare/tools.py +103 -0
  164. aimodelshare/utils/__init__.py +78 -0
  165. aimodelshare/utils/optional_deps.py +38 -0
  166. aimodelshare/utils.py +57 -0
  167. aimodelshare-0.3.7.dist-info/METADATA +298 -0
  168. aimodelshare-0.3.7.dist-info/RECORD +171 -0
  169. aimodelshare-0.3.7.dist-info/WHEEL +5 -0
  170. aimodelshare-0.3.7.dist-info/licenses/LICENSE +5 -0
  171. aimodelshare-0.3.7.dist-info/top_level.txt +1 -0
@@ -0,0 +1,853 @@
1
+ """
2
+ Activity 9: Justice & Equity Upgrade - Gradio application for the Justice & Equity Challenge.
3
+
4
+ This app teaches:
5
+ 1. Elevating fairness through accessibility and inclusion
6
+ 2. Stakeholder engagement and community participation
7
+ 3. Final Moral Compass score reveal and team leaderboard
8
+ 4. Certificate unlock and challenge completion
9
+
10
+ Structure:
11
+ - Factory function `create_justice_equity_upgrade_app()` returns a Gradio Blocks object
12
+ - Convenience wrapper `launch_justice_equity_upgrade_app()` launches it inline (for notebooks)
13
+
14
+ Moral Compass Integration:
15
+ - Uses ChallengeManager for progress tracking (tasks A-F)
16
+ - Debounced sync prevents excessive API calls
17
+ - Team aggregation via synthetic team: username
18
+ - Force Sync button for manual refresh
19
+ """
20
+ import contextlib
21
+ import os
22
+ import logging
23
+
24
+ # Import moral compass integration helpers
25
+ from .mc_integration_helpers import (
26
+ get_challenge_manager,
27
+ sync_user_moral_state,
28
+ sync_team_state,
29
+ build_moral_leaderboard_html,
30
+ get_moral_compass_widget_html,
31
+ )
32
+
33
+ logger = logging.getLogger("aimodelshare.moral_compass.apps.justice_equity_upgrade")
34
+
35
+
36
+ def _get_user_stats():
37
+ """Get user statistics for final score reveal."""
38
+ try:
39
+ username = os.environ.get("username")
40
+ team_name = os.environ.get("TEAM_NAME", "Unknown Team")
41
+
42
+ return {
43
+ "username": username or "Guest",
44
+ "team_name": team_name,
45
+ "is_signed_in": bool(username)
46
+ }
47
+ except Exception:
48
+ return {
49
+ "username": "Guest",
50
+ "team_name": "Unknown Team",
51
+ "is_signed_in": False
52
+ }
53
+
54
+
55
+ def create_justice_equity_upgrade_app(theme_primary_hue: str = "indigo") -> "gr.Blocks":
56
+ """Create the Justice & Equity Upgrade Gradio Blocks app (not launched yet)."""
57
+ try:
58
+ import gradio as gr
59
+ gr.close_all(verbose=False)
60
+ except ImportError as e:
61
+ raise ImportError(
62
+ "Gradio is required for the justice & equity upgrade app. Install with `pip install gradio`."
63
+ ) from e
64
+
65
+ # Get user stats and initialize challenge manager
66
+ user_stats = _get_user_stats()
67
+ challenge_manager = None
68
+ if user_stats["is_signed_in"]:
69
+ challenge_manager = get_challenge_manager(user_stats["username"])
70
+
71
+ # Track state
72
+ moral_compass_points = {"value": 0}
73
+ server_moral_score = {"value": None}
74
+ is_synced = {"value": False}
75
+ accessibility_features = []
76
+ diversity_improvements = []
77
+ stakeholder_priorities = []
78
+
79
+ def sync_moral_state(override=False):
80
+ """Sync moral state to server (debounced unless override)."""
81
+ if not challenge_manager:
82
+ return {
83
+ 'widget_html': get_moral_compass_widget_html(
84
+ local_points=moral_compass_points["value"],
85
+ server_score=None,
86
+ is_synced=False
87
+ ),
88
+ 'status': 'Guest mode - sign in to sync'
89
+ }
90
+
91
+ # Mark task E (Accessibility) as completed
92
+ challenge_manager.complete_task('E')
93
+
94
+ # Sync to server
95
+ sync_result = sync_user_moral_state(
96
+ cm=challenge_manager,
97
+ moral_points=moral_compass_points["value"],
98
+ override=override
99
+ )
100
+
101
+ # Update state
102
+ if sync_result['synced']:
103
+ server_moral_score["value"] = sync_result.get('server_score')
104
+ is_synced["value"] = True
105
+
106
+ # Trigger team sync if user sync succeeded
107
+ if user_stats.get("team_name"):
108
+ sync_team_state(user_stats["team_name"])
109
+
110
+ # Generate widget HTML
111
+ widget_html = get_moral_compass_widget_html(
112
+ local_points=moral_compass_points["value"],
113
+ server_score=server_moral_score["value"],
114
+ is_synced=is_synced["value"]
115
+ )
116
+
117
+ return {
118
+ 'widget_html': widget_html,
119
+ 'status': sync_result['message']
120
+ }
121
+
122
+ def apply_accessibility_features(multilang, plaintext, screenreader):
123
+ """Apply accessibility features."""
124
+ features_added = []
125
+
126
+ if multilang:
127
+ features_added.append("Multi-language support (Catalan, Spanish, English)")
128
+ accessibility_features.append("multilang")
129
+
130
+ if plaintext:
131
+ features_added.append("Plain text summaries for non-technical users")
132
+ accessibility_features.append("plaintext")
133
+
134
+ if screenreader:
135
+ features_added.append("Screen reader compatibility")
136
+ accessibility_features.append("screenreader")
137
+
138
+ if features_added:
139
+ moral_compass_points["value"] += 75
140
+
141
+ # Update ChallengeManager if available
142
+ if challenge_manager:
143
+ challenge_manager.answer_question('E', 'E1', 1) # Correct answer for accessibility task
144
+
145
+ report = "## Accessibility Features Applied\n\n"
146
+ for feature in features_added:
147
+ report += f"- ✓ {feature}\n"
148
+ report += f"\n**Impact:** These features ensure **equal opportunity of access** for all users, "
149
+ report += "regardless of language, technical background, or disability.\n\n"
150
+ report += "🏆 +75 Moral Compass points for improving accessibility!"
151
+
152
+ # Trigger sync
153
+ sync_result = sync_moral_state()
154
+ report += f"\n\n{sync_result['status']}"
155
+ else:
156
+ report = "Select accessibility features to apply."
157
+
158
+ return report
159
+
160
+ def apply_diversity_improvements(team_diversity, community_voices, diverse_review):
161
+ """Apply diversity improvements."""
162
+ improvements = []
163
+
164
+ if team_diversity:
165
+ improvements.append("Diverse team composition (gender, ethnicity, background)")
166
+ diversity_improvements.append("team_diversity")
167
+
168
+ if community_voices:
169
+ improvements.append("Community advisory board with affected population representatives")
170
+ diversity_improvements.append("community_voices")
171
+
172
+ if diverse_review:
173
+ improvements.append("Diverse review panel for model evaluation")
174
+ diversity_improvements.append("diverse_review")
175
+
176
+ if improvements:
177
+ moral_compass_points["value"] += 100
178
+
179
+ # Update ChallengeManager if available
180
+ if challenge_manager:
181
+ challenge_manager.complete_task('F') # Diversity task
182
+
183
+ report = "## Diversity & Inclusion Improvements\n\n"
184
+ for improvement in improvements:
185
+ report += f"- ✓ {improvement}\n"
186
+ report += f"\n**Impact:** Diverse perspectives help identify blind spots and ensure the "
187
+ report += "system serves all communities fairly.\n\n"
188
+ report += "🏆 +100 Moral Compass points for advancing inclusion!"
189
+
190
+ # Trigger sync
191
+ sync_result = sync_moral_state()
192
+ report += f"\n\n{sync_result['status']}"
193
+ else:
194
+ report = "Select diversity improvements to apply."
195
+
196
+ return report
197
+
198
+ def visualize_improvements():
199
+ """Show before/after comparison."""
200
+ report = """
201
+ ## Before/After: System-Level Transformation
202
+
203
+ ### Before (Original System)
204
+ - ❌ English-only interface
205
+ - ❌ Technical jargon throughout
206
+ - ❌ No accessibility accommodations
207
+ - ❌ Homogeneous development team
208
+ - ❌ No community input
209
+ - ❌ Decisions made in isolation
210
+
211
+ ### After (Justice & Equity Upgrade)
212
+ """
213
+
214
+ if "multilang" in accessibility_features:
215
+ report += "- ✅ Multi-language support\n"
216
+ if "plaintext" in accessibility_features:
217
+ report += "- ✅ Plain language explanations\n"
218
+ if "screenreader" in accessibility_features:
219
+ report += "- ✅ Screen reader compatibility\n"
220
+ if "team_diversity" in diversity_improvements:
221
+ report += "- ✅ Diverse development team\n"
222
+ if "community_voices" in diversity_improvements:
223
+ report += "- ✅ Community advisory board\n"
224
+ if "diverse_review" in diversity_improvements:
225
+ report += "- ✅ Inclusive review process\n"
226
+
227
+ if accessibility_features or diversity_improvements:
228
+ report += "\n**Result:** A more **inclusive, accessible, and just** AI system.\n"
229
+ else:
230
+ report += "\n*Apply accessibility and diversity improvements to see the transformation.*\n"
231
+
232
+ return report
233
+
234
+ def prioritize_stakeholders(judges_pri, defendants_pri, families_pri, community_pri, ngos_pri):
235
+ """Check stakeholder prioritization."""
236
+ scoring = {
237
+ "Defendants": defendants_pri == "Critical",
238
+ "Community Advocates": community_pri == "Critical",
239
+ "Families": families_pri == "High",
240
+ "Judges": judges_pri == "High",
241
+ "NGOs": ngos_pri in ["High", "Medium"]
242
+ }
243
+
244
+ score = sum(scoring.values())
245
+ feedback = []
246
+
247
+ if scoring["Defendants"]:
248
+ feedback.append("✓ Defendants are critical - they're directly affected by decisions.")
249
+ else:
250
+ feedback.append("⚠️ Defendants should be 'Critical' - they're most impacted.")
251
+
252
+ if scoring["Community Advocates"]:
253
+ feedback.append("✓ Community Advocates are critical - they represent affected populations.")
254
+ else:
255
+ feedback.append("⚠️ Community Advocates should be 'Critical' - they ensure community voice.")
256
+
257
+ if scoring["Families"]:
258
+ feedback.append("✓ Families are highly important - they're indirectly affected.")
259
+ else:
260
+ feedback.append("⚠️ Families should be 'High' importance - they suffer consequences too.")
261
+
262
+ if scoring["Judges"]:
263
+ feedback.append("✓ Judges are highly important - they make final decisions.")
264
+ else:
265
+ feedback.append("⚠️ Judges should be 'High' importance - they're key decision makers.")
266
+
267
+ points = 0
268
+ if score >= 4:
269
+ points = 100
270
+ moral_compass_points["value"] += points
271
+ feedback.append(f"\n🎉 Excellent stakeholder prioritization!\n🏆 +{points} Moral Compass points!")
272
+ elif score >= 3:
273
+ points = 50
274
+ moral_compass_points["value"] += points
275
+ feedback.append(f"\n🏆 +{points} Moral Compass points!")
276
+
277
+ # Store prioritization
278
+ for stakeholder in ["Defendants", "Families", "Judges", "Community Advocates", "NGOs"]:
279
+ stakeholder_priorities.append(stakeholder)
280
+
281
+ # Update ChallengeManager if available (stakeholder engagement = task F)
282
+ if challenge_manager and score >= 3:
283
+ challenge_manager.answer_question('F', 'F1', 1)
284
+
285
+ explanation = "\n\n**Why certain groups are critical:**\n"
286
+ explanation += "- **Defendants & Community Advocates:** Directly affected by AI decisions\n"
287
+ explanation += "- **Families:** Bear consequences of incorrect predictions\n"
288
+ explanation += "- **Judges:** Need to trust the system they're using\n"
289
+ explanation += "- **NGOs:** Provide oversight and advocacy\n"
290
+
291
+ result = "\n".join(feedback) + explanation
292
+
293
+ # Trigger sync if points were awarded
294
+ if points > 0:
295
+ sync_result = sync_moral_state()
296
+ result += f"\n\n{sync_result['status']}"
297
+
298
+ return result
299
+
300
+ def check_stakeholder_question(answer):
301
+ """Check stakeholder identification question."""
302
+ if answer == "Defendants and community members directly affected by the system":
303
+ moral_compass_points["value"] += 50
304
+ return "✓ Correct! Those directly affected by AI decisions must have a voice in system design and oversight.\n\n🏆 +50 Moral Compass points!"
305
+ else:
306
+ return "✗ Not quite. Think about who faces the real-world consequences of AI predictions."
307
+
308
+ def check_inclusion_question(answer):
309
+ """Check inclusion definition question."""
310
+ if answer == "Actively involving diverse stakeholders in design, development, and oversight":
311
+ moral_compass_points["value"] += 50
312
+ return "✓ Correct! Inclusion means bringing diverse voices into the process, not just serving diverse populations.\n\n🏆 +50 Moral Compass points!"
313
+ else:
314
+ return "✗ Not quite. Inclusion is about participation and voice, not just access."
315
+
316
+ def reveal_final_score():
317
+ """Reveal final Moral Compass score with growth visualization."""
318
+ user_stats = _get_user_stats()
319
+ total_score = moral_compass_points["value"]
320
+
321
+ # Simulated score progression through activities
322
+ activity7_score = min(400, int(total_score * 0.3))
323
+ activity8_score = min(800, int(total_score * 0.6))
324
+ activity9_score = total_score
325
+
326
+ report = f"""
327
+ # 🎊 Final Moral Compass Score Reveal
328
+
329
+ ## Your Justice & Equity Journey
330
+
331
+ ### Score Progression
332
+ - **Activity 7 (Bias Detective):** {activity7_score} points
333
+ - **Activity 8 (Fairness Fixer):** {activity8_score} points
334
+ - **Activity 9 (Justice & Equity Upgrade):** {activity9_score} points
335
+
336
+ ### Total Moral Compass Score: {total_score} points
337
+
338
+ ---
339
+
340
+ ## 🏆 Achievement Unlocked: **Justice & Equity Champion**
341
+
342
+ You've demonstrated mastery of:
343
+ - ✅ Expert fairness frameworks (OEIAC)
344
+ - ✅ Bias detection and diagnosis
345
+ - ✅ Technical fairness interventions
346
+ - ✅ Representative data strategies
347
+ - ✅ Accessibility and inclusion
348
+ - ✅ Stakeholder engagement
349
+
350
+ ---
351
+
352
+ ## Team Leaderboard
353
+ """
354
+
355
+ if user_stats["is_signed_in"]:
356
+ report += f"""
357
+ **Your Team:** {user_stats["team_name"]}
358
+ **Username:** {user_stats["username"]}
359
+ **Your Score:** {total_score} points
360
+
361
+ *Check the full leaderboard in the Model Building Game app to see team rankings!*
362
+ """
363
+ else:
364
+ report += """
365
+ *Sign in to see your team ranking and compete on the leaderboard!*
366
+ """
367
+
368
+ report += """
369
+ ---
370
+
371
+ ## 🎖️ Badge Earned
372
+
373
+ **Justice & Equity Champion**
374
+
375
+ *Awarded for completing Activities 7, 8, and 9 with demonstrated understanding
376
+ of fairness principles, technical fixes, and systemic improvements.*
377
+ """
378
+
379
+ return report
380
+
381
+ def generate_completion_certificate():
382
+ """Generate completion message with certificate unlock."""
383
+ user_stats = _get_user_stats()
384
+
385
+ certificate = f"""
386
+ # 🎓 Certificate of Completion
387
+
388
+ ## Ethics at Play: Justice & Equity Challenge
389
+
390
+ **This certifies that**
391
+
392
+ ### {user_stats["username"]}
393
+
394
+ **has successfully completed Activities 7, 8, and 9:**
395
+
396
+ - 🕵️ **Bias Detective:** Diagnosed bias in AI systems using expert frameworks
397
+ - 🔧 **Fairness Fixer:** Applied technical fairness interventions
398
+ - 🌟 **Justice & Equity Upgrade:** Elevated the system through inclusion and accessibility
399
+
400
+ **Final Moral Compass Score:** {moral_compass_points["value"]} points
401
+
402
+ **Team:** {user_stats["team_name"]}
403
+
404
+ ---
405
+
406
+ ### Skills Demonstrated:
407
+ - Expert fairness evaluation (OEIAC framework)
408
+ - Demographic bias identification
409
+ - Group-level disparity analysis
410
+ - Feature and proxy removal
411
+ - Representative data strategy
412
+ - Continuous improvement planning
413
+ - Accessibility enhancement
414
+ - Stakeholder engagement
415
+
416
+ **Date Completed:** [Auto-generated in production]
417
+
418
+ ---
419
+
420
+ ### Next Steps:
421
+ Proceed to **Section 10** to continue your Ethics at Play journey!
422
+ """
423
+
424
+ return certificate
425
+
426
+ # Create the Gradio app
427
+ with gr.Blocks(
428
+ title="Activity 9: Justice & Equity Upgrade",
429
+ theme=gr.themes.Soft(primary_hue=theme_primary_hue)
430
+ ) as app:
431
+ gr.Markdown("# 🌟 Activity 9: Justice & Equity Upgrade")
432
+ gr.Markdown(
433
+ """
434
+ **Objective:** Elevate fairness improvements by addressing inclusion, accessibility,
435
+ stakeholder engagement, and structural justice.
436
+
437
+ **Your Role:** You're now a **Justice Architect**.
438
+
439
+ **Progress:** Activity 9 of 10 — Elevate the System
440
+
441
+ **Estimated Time:** 8–10 minutes
442
+ """
443
+ )
444
+
445
+ # Moral Compass widget with Force Sync
446
+ with gr.Row():
447
+ with gr.Column(scale=3):
448
+ moral_compass_display = gr.HTML(
449
+ get_moral_compass_widget_html(
450
+ local_points=0,
451
+ server_score=None,
452
+ is_synced=False
453
+ )
454
+ )
455
+ with gr.Column(scale=1):
456
+ force_sync_btn = gr.Button("Force Sync", variant="secondary", size="sm")
457
+ sync_status = gr.Markdown("")
458
+
459
+ # Force Sync handler
460
+ def handle_force_sync():
461
+ sync_result = sync_moral_state(override=True)
462
+ return sync_result['widget_html'], sync_result['status']
463
+
464
+ force_sync_btn.click(
465
+ fn=handle_force_sync,
466
+ outputs=[moral_compass_display, sync_status]
467
+ )
468
+
469
+ gr.Markdown(
470
+ """
471
+ ### Quick Recap
472
+
473
+ In Activities 7 & 8, you addressed **technical fairness**:
474
+ - Removed biased features
475
+ - Eliminated proxy variables
476
+ - Created representative data guidelines
477
+
478
+ Now, let's elevate to **systemic justice** through inclusion and accessibility.
479
+ """
480
+ )
481
+
482
+ # Section 9.2: Access & Inclusion Makeover
483
+ with gr.Tab("9.2 Access & Inclusion"):
484
+ gr.Markdown(
485
+ """
486
+ ## Access & Inclusion Makeover
487
+
488
+ **Principles:**
489
+ - **Equal Opportunity of Access:** Everyone can use the system
490
+ - **Inclusion and Diversity:** Diverse voices shape the system
491
+
492
+ ### 📚 Real-World Example: Court Interface Multilanguage Support
493
+
494
+ <details>
495
+ <summary><b>Click to expand: Barcelona Court System Case Study</b></summary>
496
+
497
+ **Scenario:** A court in Barcelona implemented an AI risk assessment tool but provided
498
+ the interface only in Spanish.
499
+
500
+ **Problem:**
501
+ - Many defendants spoke primarily Catalan or were immigrants with limited Spanish
502
+ - Unable to understand the AI's reasoning or contest decisions
503
+ - Violated equal access principles
504
+
505
+ **Solution:**
506
+ - Added Catalan, Spanish, and English interfaces
507
+ - Included plain-language summaries of technical terms
508
+ - Provided audio explanations for low-literacy users
509
+
510
+ **Outcome:**
511
+ - 40% increase in defendants able to understand their risk scores
512
+ - Reduced appeals due to miscommunication
513
+ - Improved trust in the justice system
514
+
515
+ </details>
516
+
517
+ ---
518
+
519
+ ### Accessibility Features
520
+
521
+ Select features to add:
522
+ """
523
+ )
524
+
525
+ multilang_toggle = gr.Checkbox(label="Multi-language support (Catalan, Spanish, English)", value=False)
526
+ plaintext_toggle = gr.Checkbox(label="Plain text summaries (non-technical language)", value=False)
527
+ screenreader_toggle = gr.Checkbox(label="Screen reader compatibility", value=False)
528
+
529
+ accessibility_btn = gr.Button("Apply Accessibility Features", variant="primary")
530
+ accessibility_output = gr.Markdown("")
531
+
532
+ def update_widget_after_accessibility(multilang, plaintext, screenreader):
533
+ result = apply_accessibility_features(multilang, plaintext, screenreader)
534
+ widget_html = get_moral_compass_widget_html(
535
+ local_points=moral_compass_points["value"],
536
+ server_score=server_moral_score["value"],
537
+ is_synced=is_synced["value"]
538
+ )
539
+ return result, widget_html
540
+
541
+ accessibility_btn.click(
542
+ fn=update_widget_after_accessibility,
543
+ inputs=[multilang_toggle, plaintext_toggle, screenreader_toggle],
544
+ outputs=[accessibility_output, moral_compass_display]
545
+ )
546
+
547
+ gr.Markdown(
548
+ """
549
+ ### Diversity & Inclusion
550
+
551
+ ### 📚 Case Study: Homogeneous vs Diverse Design Reviews
552
+
553
+ <details>
554
+ <summary><b>Click to expand: Impact of Team Diversity</b></summary>
555
+
556
+ **Scenario A - Homogeneous Team:**
557
+ - 5 data scientists, all from same demographic background
558
+ - Reviewed pretrial risk model
559
+ - Found model "looks good" - high accuracy on test set
560
+ - Deployed to production
561
+
562
+ **Result:**
563
+ - Within 3 months, community advocates identified severe racial bias
564
+ - Model was over-predicting risk for minority defendants
565
+ - Legal challenges filed; model withdrawn
566
+
567
+ **Scenario B - Diverse Team:**
568
+ - Same 5 data scientists + 3 community advocates + 2 affected individuals + 1 civil rights lawyer
569
+ - Reviewed same pretrial risk model
570
+ - Identified 7 potential fairness issues before deployment
571
+
572
+ **Result:**
573
+ - Addressed bias in training data
574
+ - Removed problematic proxy features
575
+ - Added fairness constraints
576
+ - Successful deployment with ongoing monitoring
577
+
578
+ **Lesson:** Diverse perspectives catch blind spots that homogeneous teams miss.
579
+
580
+ </details>
581
+
582
+ ---
583
+ """
584
+ )
585
+
586
+ team_diversity_toggle = gr.Checkbox(label="Diverse team composition (gender, ethnicity, expertise)", value=False)
587
+ community_toggle = gr.Checkbox(label="Community advisory board", value=False)
588
+ review_diversity_toggle = gr.Checkbox(label="Diverse review panel", value=False)
589
+
590
+ diversity_btn = gr.Button("Apply Diversity Improvements", variant="primary")
591
+ diversity_output = gr.Markdown("")
592
+
593
+ def update_widget_after_diversity(team_diversity, community_voices, diverse_review):
594
+ result = apply_diversity_improvements(team_diversity, community_voices, diverse_review)
595
+ widget_html = get_moral_compass_widget_html(
596
+ local_points=moral_compass_points["value"],
597
+ server_score=server_moral_score["value"],
598
+ is_synced=is_synced["value"]
599
+ )
600
+ return result, widget_html
601
+
602
+ diversity_btn.click(
603
+ fn=update_widget_after_diversity,
604
+ inputs=[team_diversity_toggle, community_toggle, review_diversity_toggle],
605
+ outputs=[diversity_output, moral_compass_display]
606
+ )
607
+
608
+ gr.Markdown("### Before/After Comparison")
609
+
610
+ compare_btn = gr.Button("Show System Transformation", variant="secondary")
611
+ compare_output = gr.Markdown("")
612
+
613
+ compare_btn.click(
614
+ fn=visualize_improvements,
615
+ outputs=compare_output
616
+ )
617
+
618
+ # Section 9.3: Stakeholder Mapping
619
+ with gr.Tab("9.3 Stakeholder Mapping"):
620
+ gr.Markdown(
621
+ """
622
+ ## Stakeholder Prioritization Map
623
+
624
+ **Principle:** Affected community members must have a voice.
625
+
626
+ ### 📊 Stakeholder Analysis Framework
627
+
628
+ <details>
629
+ <summary><b>Click to expand: Power vs Impact vs Voice Matrix</b></summary>
630
+
631
+ | Stakeholder Group | Power* | Impact** | Voice*** | Priority |
632
+ |-------------------|--------|----------|----------|----------|
633
+ | **Defendants** | Low | High | Low | **CRITICAL** |
634
+ | **Community Advocates** | Medium | High | Medium | **CRITICAL** |
635
+ | **Families** | Low | High | Low | **HIGH** |
636
+ | **Judges** | High | Medium | High | **HIGH** |
637
+ | **Data Scientists** | Medium | Low | High | **MEDIUM** |
638
+ | **NGOs** | Medium | Medium | Medium | **HIGH** |
639
+ | **System Administrators** | Medium | Low | Medium | **MEDIUM** |
640
+
641
+ *Power = ability to influence system design
642
+ **Impact = how much they're affected by system decisions
643
+ ***Voice = current representation in decision-making
644
+
645
+ **Key Insight:** Those with **high impact but low voice** (defendants, families)
646
+ must be prioritized to achieve justice.
647
+
648
+ </details>
649
+
650
+ ---
651
+
652
+ ### Exercise: Prioritize Stakeholders
653
+
654
+ Assign each stakeholder to the appropriate priority level:
655
+ - **Critical:** Must be involved in all decisions
656
+ - **High:** Important voice in major decisions
657
+ - **Medium:** Should be consulted periodically
658
+ """
659
+ )
660
+
661
+ judges_priority = gr.Radio(
662
+ choices=["Critical", "High", "Medium"],
663
+ label="Judges (use the system to make decisions):",
664
+ value=None
665
+ )
666
+ defendants_priority = gr.Radio(
667
+ choices=["Critical", "High", "Medium"],
668
+ label="Defendants (directly affected by predictions):",
669
+ value=None
670
+ )
671
+ families_priority = gr.Radio(
672
+ choices=["Critical", "High", "Medium"],
673
+ label="Families (indirectly affected):",
674
+ value=None
675
+ )
676
+ community_priority = gr.Radio(
677
+ choices=["Critical", "High", "Medium"],
678
+ label="Community Advocates (represent affected populations):",
679
+ value=None
680
+ )
681
+ ngos_priority = gr.Radio(
682
+ choices=["Critical", "High", "Medium"],
683
+ label="NGOs (provide oversight):",
684
+ value=None
685
+ )
686
+
687
+ stakeholder_btn = gr.Button("Submit Prioritization", variant="primary")
688
+ stakeholder_output = gr.Markdown("")
689
+
690
+ stakeholder_btn.click(
691
+ fn=prioritize_stakeholders,
692
+ inputs=[judges_priority, defendants_priority, families_priority, community_priority, ngos_priority],
693
+ outputs=stakeholder_output
694
+ ).then(
695
+ fn=lambda: f"## 🧭 Moral Compass Score: {moral_compass_points['value']} points",
696
+ outputs=moral_compass_display
697
+ )
698
+
699
+ gr.Markdown("### Check-In Questions")
700
+
701
+ stakeholder_question = gr.Radio(
702
+ choices=[
703
+ "Technical experts and data scientists",
704
+ "Government officials and administrators",
705
+ "Defendants and community members directly affected by the system",
706
+ "Only judges who use the system"
707
+ ],
708
+ label="Who should have the strongest voice in AI criminal justice systems?",
709
+ value=None
710
+ )
711
+ stakeholder_check_btn = gr.Button("Check Answer")
712
+ stakeholder_feedback = gr.Markdown("")
713
+
714
+ stakeholder_check_btn.click(
715
+ fn=check_stakeholder_question,
716
+ inputs=stakeholder_question,
717
+ outputs=stakeholder_feedback
718
+ ).then(
719
+ fn=lambda: f"## 🧭 Moral Compass Score: {moral_compass_points['value']} points",
720
+ outputs=moral_compass_display
721
+ )
722
+
723
+ inclusion_question = gr.Radio(
724
+ choices=[
725
+ "Making sure the system works for everyone",
726
+ "Hiring diverse employees",
727
+ "Actively involving diverse stakeholders in design, development, and oversight",
728
+ "Translating the interface into multiple languages"
729
+ ],
730
+ label="What does 'Inclusion' mean in the context of AI ethics?",
731
+ value=None
732
+ )
733
+ inclusion_check_btn = gr.Button("Check Answer")
734
+ inclusion_feedback = gr.Markdown("")
735
+
736
+ inclusion_check_btn.click(
737
+ fn=check_inclusion_question,
738
+ inputs=inclusion_question,
739
+ outputs=inclusion_feedback
740
+ ).then(
741
+ fn=lambda: f"## 🧭 Moral Compass Score: {moral_compass_points['value']} points",
742
+ outputs=moral_compass_display
743
+ )
744
+
745
+ # Section 9.4: Final Score Reveal
746
+ with gr.Tab("9.4 Final Score"):
747
+ gr.Markdown(
748
+ """
749
+ ## 🎊 Final Moral Compass Score Reveal
750
+
751
+ See how you've grown from the start of Section 7 to now!
752
+ """
753
+ )
754
+
755
+ reveal_btn = gr.Button("Reveal My Final Score", variant="primary", size="lg")
756
+ score_output = gr.Markdown("")
757
+
758
+ reveal_btn.click(
759
+ fn=reveal_final_score,
760
+ outputs=score_output
761
+ )
762
+
763
+ # Ethics Leaderboard Tab
764
+ with gr.Tab("Ethics Leaderboard"):
765
+ gr.Markdown(
766
+ """
767
+ ## 🏆 Ethics Leaderboard
768
+
769
+ This leaderboard shows **combined ethical engagement + performance scores**,
770
+ different from the Model Building Game's accuracy-only leaderboard.
771
+
772
+ **What's measured:**
773
+ - Your moral compass points (ethical decision-making)
774
+ - Your model accuracy (technical performance)
775
+ - Combined score = accuracy × normalized_moral_points
776
+
777
+ **Difference from Model Game Leaderboard:**
778
+ - Model Game: Pure accuracy/performance
779
+ - Ethics Leaderboard: Holistic score (ethics + accuracy)
780
+ """
781
+ )
782
+
783
+ leaderboard_display = gr.HTML("")
784
+ refresh_leaderboard_btn = gr.Button("Refresh Leaderboard", variant="secondary")
785
+
786
+ def load_leaderboard():
787
+ return build_moral_leaderboard_html(
788
+ highlight_username=user_stats.get("username"),
789
+ include_teams=True
790
+ )
791
+
792
+ # Load on tab open
793
+ refresh_leaderboard_btn.click(
794
+ fn=load_leaderboard,
795
+ outputs=leaderboard_display
796
+ )
797
+
798
+ # Also load initially
799
+ app.load(fn=load_leaderboard, outputs=leaderboard_display)
800
+
801
+ # Section 9.5: Completion
802
+ with gr.Tab("9.5 Completion"):
803
+ gr.Markdown(
804
+ """
805
+ ## 🎓 Activity 9 Complete!
806
+
807
+ Generate your completion certificate and unlock the next section.
808
+ """
809
+ )
810
+
811
+ certificate_btn = gr.Button("Generate Certificate", variant="primary", size="lg")
812
+ certificate_output = gr.Markdown("")
813
+
814
+ certificate_btn.click(
815
+ fn=generate_completion_certificate,
816
+ outputs=certificate_output
817
+ )
818
+
819
+ gr.Markdown(
820
+ """
821
+ ---
822
+
823
+ ### 🎉 Congratulations!
824
+
825
+ You've completed the **Justice & Equity Challenge** (Activities 7, 8, and 9).
826
+
827
+ **What you've learned:**
828
+ - How to diagnose bias using expert frameworks
829
+ - Technical fairness interventions
830
+ - Representative data strategies
831
+ - Accessibility and inclusion principles
832
+ - Stakeholder engagement best practices
833
+
834
+ **Next:** Continue to **Section 10** to complete your Ethics at Play journey!
835
+ """
836
+ )
837
+
838
+ return app
839
+
840
+
841
+ def launch_justice_equity_upgrade_app(
842
+ share: bool = False,
843
+ server_name: str = None,
844
+ server_port: int = None,
845
+ theme_primary_hue: str = "indigo"
846
+ ) -> None:
847
+ """Convenience wrapper to create and launch the justice & equity upgrade app inline."""
848
+ app = create_justice_equity_upgrade_app(theme_primary_hue=theme_primary_hue)
849
+ # Use provided values or fall back to PORT env var and 0.0.0.0
850
+
851
+ if server_port is None:
852
+ server_port = int(os.environ.get("PORT", 8080))
853
+ app.launch(share=share, server_port=server_port)