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.
- aimodelshare/README.md +26 -0
- aimodelshare/__init__.py +100 -0
- aimodelshare/aimsonnx.py +2381 -0
- aimodelshare/api.py +836 -0
- aimodelshare/auth.py +163 -0
- aimodelshare/aws.py +511 -0
- aimodelshare/aws_client.py +173 -0
- aimodelshare/base_image.py +154 -0
- aimodelshare/bucketpolicy.py +106 -0
- aimodelshare/color_mappings/color_mapping_keras.csv +121 -0
- aimodelshare/color_mappings/color_mapping_pytorch.csv +117 -0
- aimodelshare/containerisation.py +244 -0
- aimodelshare/containerization.py +712 -0
- aimodelshare/containerization_templates/Dockerfile.txt +8 -0
- aimodelshare/containerization_templates/Dockerfile_PySpark.txt +23 -0
- aimodelshare/containerization_templates/buildspec.txt +14 -0
- aimodelshare/containerization_templates/lambda_function.txt +40 -0
- aimodelshare/custom_approach/__init__.py +1 -0
- aimodelshare/custom_approach/lambda_function.py +17 -0
- aimodelshare/custom_eval_metrics.py +103 -0
- aimodelshare/data_sharing/__init__.py +0 -0
- aimodelshare/data_sharing/data_sharing_templates/Dockerfile.txt +3 -0
- aimodelshare/data_sharing/data_sharing_templates/__init__.py +1 -0
- aimodelshare/data_sharing/data_sharing_templates/buildspec.txt +15 -0
- aimodelshare/data_sharing/data_sharing_templates/codebuild_policies.txt +129 -0
- aimodelshare/data_sharing/data_sharing_templates/codebuild_trust_relationship.txt +12 -0
- aimodelshare/data_sharing/download_data.py +620 -0
- aimodelshare/data_sharing/share_data.py +373 -0
- aimodelshare/data_sharing/utils.py +8 -0
- aimodelshare/deploy_custom_lambda.py +246 -0
- aimodelshare/documentation/Makefile +20 -0
- aimodelshare/documentation/karma_sphinx_theme/__init__.py +28 -0
- aimodelshare/documentation/karma_sphinx_theme/_version.py +2 -0
- aimodelshare/documentation/karma_sphinx_theme/breadcrumbs.html +70 -0
- aimodelshare/documentation/karma_sphinx_theme/layout.html +172 -0
- aimodelshare/documentation/karma_sphinx_theme/search.html +50 -0
- aimodelshare/documentation/karma_sphinx_theme/searchbox.html +14 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css +2 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/custom.css.map +1 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css +2751 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/theme.css.map +1 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css +2 -0
- aimodelshare/documentation/karma_sphinx_theme/static/css/theme.min.css.map +1 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.eot +0 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.svg +32 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.ttf +0 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff +0 -0
- aimodelshare/documentation/karma_sphinx_theme/static/font/fontello.woff2 +0 -0
- aimodelshare/documentation/karma_sphinx_theme/static/js/theme.js +68 -0
- aimodelshare/documentation/karma_sphinx_theme/theme.conf +9 -0
- aimodelshare/documentation/make.bat +35 -0
- aimodelshare/documentation/requirements.txt +2 -0
- aimodelshare/documentation/source/about.rst +18 -0
- aimodelshare/documentation/source/advanced_features.rst +137 -0
- aimodelshare/documentation/source/competition.rst +218 -0
- aimodelshare/documentation/source/conf.py +58 -0
- aimodelshare/documentation/source/create_credentials.rst +86 -0
- aimodelshare/documentation/source/example_notebooks.rst +132 -0
- aimodelshare/documentation/source/functions.rst +151 -0
- aimodelshare/documentation/source/gettingstarted.rst +390 -0
- aimodelshare/documentation/source/images/creds1.png +0 -0
- aimodelshare/documentation/source/images/creds2.png +0 -0
- aimodelshare/documentation/source/images/creds3.png +0 -0
- aimodelshare/documentation/source/images/creds4.png +0 -0
- aimodelshare/documentation/source/images/creds5.png +0 -0
- aimodelshare/documentation/source/images/creds_file_example.png +0 -0
- aimodelshare/documentation/source/images/predict_tab.png +0 -0
- aimodelshare/documentation/source/index.rst +110 -0
- aimodelshare/documentation/source/modelplayground.rst +132 -0
- aimodelshare/exceptions.py +11 -0
- aimodelshare/generatemodelapi.py +1270 -0
- aimodelshare/iam/codebuild_policy.txt +129 -0
- aimodelshare/iam/codebuild_trust_relationship.txt +12 -0
- aimodelshare/iam/lambda_policy.txt +15 -0
- aimodelshare/iam/lambda_trust_relationship.txt +12 -0
- aimodelshare/json_templates/__init__.py +1 -0
- aimodelshare/json_templates/api_json.txt +155 -0
- aimodelshare/json_templates/auth/policy.txt +1 -0
- aimodelshare/json_templates/auth/role.txt +1 -0
- aimodelshare/json_templates/eval/policy.txt +1 -0
- aimodelshare/json_templates/eval/role.txt +1 -0
- aimodelshare/json_templates/function/policy.txt +1 -0
- aimodelshare/json_templates/function/role.txt +1 -0
- aimodelshare/json_templates/integration_response.txt +5 -0
- aimodelshare/json_templates/lambda_policy_1.txt +15 -0
- aimodelshare/json_templates/lambda_policy_2.txt +8 -0
- aimodelshare/json_templates/lambda_role_1.txt +12 -0
- aimodelshare/json_templates/lambda_role_2.txt +16 -0
- aimodelshare/leaderboard.py +174 -0
- aimodelshare/main/1.txt +132 -0
- aimodelshare/main/1B.txt +112 -0
- aimodelshare/main/2.txt +153 -0
- aimodelshare/main/3.txt +134 -0
- aimodelshare/main/4.txt +128 -0
- aimodelshare/main/5.txt +109 -0
- aimodelshare/main/6.txt +105 -0
- aimodelshare/main/7.txt +144 -0
- aimodelshare/main/8.txt +142 -0
- aimodelshare/main/__init__.py +1 -0
- aimodelshare/main/authorization.txt +275 -0
- aimodelshare/main/eval_classification.txt +79 -0
- aimodelshare/main/eval_lambda.txt +1709 -0
- aimodelshare/main/eval_regression.txt +80 -0
- aimodelshare/main/lambda_function.txt +8 -0
- aimodelshare/main/nst.txt +149 -0
- aimodelshare/model.py +1543 -0
- aimodelshare/modeluser.py +215 -0
- aimodelshare/moral_compass/README.md +408 -0
- aimodelshare/moral_compass/__init__.py +65 -0
- aimodelshare/moral_compass/_version.py +3 -0
- aimodelshare/moral_compass/api_client.py +601 -0
- aimodelshare/moral_compass/apps/__init__.py +69 -0
- aimodelshare/moral_compass/apps/ai_consequences.py +540 -0
- aimodelshare/moral_compass/apps/bias_detective.py +714 -0
- aimodelshare/moral_compass/apps/ethical_revelation.py +898 -0
- aimodelshare/moral_compass/apps/fairness_fixer.py +889 -0
- aimodelshare/moral_compass/apps/judge.py +888 -0
- aimodelshare/moral_compass/apps/justice_equity_upgrade.py +853 -0
- aimodelshare/moral_compass/apps/mc_integration_helpers.py +820 -0
- aimodelshare/moral_compass/apps/model_building_game.py +1104 -0
- aimodelshare/moral_compass/apps/model_building_game_beginner.py +687 -0
- aimodelshare/moral_compass/apps/moral_compass_challenge.py +858 -0
- aimodelshare/moral_compass/apps/session_auth.py +254 -0
- aimodelshare/moral_compass/apps/shared_activity_styles.css +349 -0
- aimodelshare/moral_compass/apps/tutorial.py +481 -0
- aimodelshare/moral_compass/apps/what_is_ai.py +853 -0
- aimodelshare/moral_compass/challenge.py +365 -0
- aimodelshare/moral_compass/config.py +187 -0
- aimodelshare/placeholders/model.onnx +0 -0
- aimodelshare/placeholders/preprocessor.zip +0 -0
- aimodelshare/playground.py +1968 -0
- aimodelshare/postprocessormodules.py +157 -0
- aimodelshare/preprocessormodules.py +373 -0
- aimodelshare/pyspark/1.txt +195 -0
- aimodelshare/pyspark/1B.txt +181 -0
- aimodelshare/pyspark/2.txt +220 -0
- aimodelshare/pyspark/3.txt +204 -0
- aimodelshare/pyspark/4.txt +187 -0
- aimodelshare/pyspark/5.txt +178 -0
- aimodelshare/pyspark/6.txt +174 -0
- aimodelshare/pyspark/7.txt +211 -0
- aimodelshare/pyspark/8.txt +206 -0
- aimodelshare/pyspark/__init__.py +1 -0
- aimodelshare/pyspark/authorization.txt +258 -0
- aimodelshare/pyspark/eval_classification.txt +79 -0
- aimodelshare/pyspark/eval_lambda.txt +1441 -0
- aimodelshare/pyspark/eval_regression.txt +80 -0
- aimodelshare/pyspark/lambda_function.txt +8 -0
- aimodelshare/pyspark/nst.txt +213 -0
- aimodelshare/python/my_preprocessor.py +58 -0
- aimodelshare/readme.md +26 -0
- aimodelshare/reproducibility.py +181 -0
- aimodelshare/sam/Dockerfile.txt +8 -0
- aimodelshare/sam/Dockerfile_PySpark.txt +24 -0
- aimodelshare/sam/__init__.py +1 -0
- aimodelshare/sam/buildspec.txt +11 -0
- aimodelshare/sam/codebuild_policies.txt +129 -0
- aimodelshare/sam/codebuild_trust_relationship.txt +12 -0
- aimodelshare/sam/codepipeline_policies.txt +173 -0
- aimodelshare/sam/codepipeline_trust_relationship.txt +12 -0
- aimodelshare/sam/spark-class.txt +2 -0
- aimodelshare/sam/template.txt +54 -0
- aimodelshare/tools.py +103 -0
- aimodelshare/utils/__init__.py +78 -0
- aimodelshare/utils/optional_deps.py +38 -0
- aimodelshare/utils.py +57 -0
- aimodelshare-0.3.7.dist-info/METADATA +298 -0
- aimodelshare-0.3.7.dist-info/RECORD +171 -0
- aimodelshare-0.3.7.dist-info/WHEEL +5 -0
- aimodelshare-0.3.7.dist-info/licenses/LICENSE +5 -0
- aimodelshare-0.3.7.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tutorial Gradio application for onboarding users to the Justice & Equity Challenge.
|
|
3
|
+
|
|
4
|
+
This app teaches:
|
|
5
|
+
1. How to advance slideshow-style steps
|
|
6
|
+
2. How to interact with sliders/buttons
|
|
7
|
+
3. How model prediction output appears
|
|
8
|
+
|
|
9
|
+
Structure:
|
|
10
|
+
- Factory function `create_tutorial_app()` returns a Gradio Blocks object
|
|
11
|
+
- Convenience wrapper `launch_tutorial_app()` launches it inline (for notebooks)
|
|
12
|
+
"""
|
|
13
|
+
import contextlib
|
|
14
|
+
import os
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _build_synthetic_model():
|
|
18
|
+
"""Build a tiny linear regression model on synthetic study habit data."""
|
|
19
|
+
import numpy as np
|
|
20
|
+
from sklearn.linear_model import LinearRegression
|
|
21
|
+
|
|
22
|
+
rng = np.random.default_rng(7)
|
|
23
|
+
n = 200
|
|
24
|
+
hours_study = rng.uniform(0, 12, n)
|
|
25
|
+
hours_sleep = rng.uniform(4, 10, n)
|
|
26
|
+
attendance = rng.uniform(50, 100, n)
|
|
27
|
+
exam_score = (
|
|
28
|
+
5 * hours_study
|
|
29
|
+
+ 3 * hours_sleep
|
|
30
|
+
+ 0.5 * attendance
|
|
31
|
+
+ rng.normal(0, 10, n)
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
X = np.column_stack([hours_study, hours_sleep, attendance])
|
|
35
|
+
y = exam_score
|
|
36
|
+
lin_reg = LinearRegression().fit(X, y)
|
|
37
|
+
|
|
38
|
+
def predict_exam(sl, slp, att):
|
|
39
|
+
pred = float(lin_reg.predict([[sl, slp, att]])[0])
|
|
40
|
+
import numpy as np
|
|
41
|
+
|
|
42
|
+
pred = float(np.clip(pred, 0, 100))
|
|
43
|
+
return f"{round(pred, 1)}%"
|
|
44
|
+
|
|
45
|
+
return predict_exam
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def create_tutorial_app(theme_primary_hue: str = "indigo") -> "gr.Blocks":
|
|
49
|
+
"""Create the tutorial Gradio Blocks app (not launched yet)."""
|
|
50
|
+
try:
|
|
51
|
+
import gradio as gr
|
|
52
|
+
|
|
53
|
+
gr.close_all(verbose=False)
|
|
54
|
+
|
|
55
|
+
except ImportError as e:
|
|
56
|
+
raise ImportError(
|
|
57
|
+
"Gradio is required for the tutorial app. Install with `pip install gradio`."
|
|
58
|
+
) from e
|
|
59
|
+
|
|
60
|
+
predict_exam = _build_synthetic_model()
|
|
61
|
+
|
|
62
|
+
# All custom colors use Gradio theme variables + dark-mode overrides.
|
|
63
|
+
css = """
|
|
64
|
+
/* ---------------------------------------------------- */
|
|
65
|
+
/* CORE TYPOGRAPHY / COMPONENT OVERRIDES */
|
|
66
|
+
/* ---------------------------------------------------- */
|
|
67
|
+
|
|
68
|
+
/* Prediction output styled with theme accent color */
|
|
69
|
+
#prediction_output_textbox textarea {
|
|
70
|
+
font-size: 2.5rem !important;
|
|
71
|
+
font-weight: bold !important;
|
|
72
|
+
text-align: center !important;
|
|
73
|
+
color: var(--color-accent) !important;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* Tutorial intro container at top */
|
|
77
|
+
.tutorial-intro-box {
|
|
78
|
+
text-align: left;
|
|
79
|
+
font-size: 20px;
|
|
80
|
+
max-width: 800px;
|
|
81
|
+
margin: auto;
|
|
82
|
+
padding: 15px;
|
|
83
|
+
border-radius: 8px;
|
|
84
|
+
|
|
85
|
+
background-color: var(--block-background-fill);
|
|
86
|
+
color: var(--body-text-color);
|
|
87
|
+
border: 1px solid var(--border-color-primary);
|
|
88
|
+
|
|
89
|
+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Slide-style emphasis box (Step 1) */
|
|
93
|
+
.slide-box {
|
|
94
|
+
font-size: 28px;
|
|
95
|
+
text-align: center;
|
|
96
|
+
padding: 28px;
|
|
97
|
+
border-radius: 16px;
|
|
98
|
+
min-height: 150px;
|
|
99
|
+
|
|
100
|
+
background-color: var(--block-background-fill);
|
|
101
|
+
color: var(--body-text-color);
|
|
102
|
+
border: 1px solid var(--border-color-primary);
|
|
103
|
+
|
|
104
|
+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Step 2 explanation box */
|
|
108
|
+
.interactive-info-box {
|
|
109
|
+
font-size: 20px;
|
|
110
|
+
text-align: left;
|
|
111
|
+
padding: 20px;
|
|
112
|
+
border-radius: 16px;
|
|
113
|
+
|
|
114
|
+
background-color: var(--block-background-fill);
|
|
115
|
+
color: var(--body-text-color);
|
|
116
|
+
border: 1px solid var(--border-color-primary);
|
|
117
|
+
|
|
118
|
+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Completion message (Step 3) */
|
|
122
|
+
.complete-box {
|
|
123
|
+
font-size: 1.5rem;
|
|
124
|
+
padding: 28px;
|
|
125
|
+
border-radius: 16px;
|
|
126
|
+
|
|
127
|
+
background-color: var(--block-background-fill);
|
|
128
|
+
color: var(--body-text-color);
|
|
129
|
+
border: 2px solid var(--color-accent);
|
|
130
|
+
|
|
131
|
+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Loading title text */
|
|
135
|
+
.loading-title {
|
|
136
|
+
font-size: 2rem;
|
|
137
|
+
color: var(--secondary-text-color);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* ---------------------------------------------------- */
|
|
141
|
+
/* NAVIGATION LOADING OVERLAY */
|
|
142
|
+
/* ---------------------------------------------------- */
|
|
143
|
+
|
|
144
|
+
#nav-loading-overlay {
|
|
145
|
+
position: fixed;
|
|
146
|
+
top: 0;
|
|
147
|
+
left: 0;
|
|
148
|
+
width: 100%;
|
|
149
|
+
height: 100%;
|
|
150
|
+
|
|
151
|
+
/* Use theme background, slightly blended with transparency */
|
|
152
|
+
background: color-mix(in srgb, var(--body-background-fill) 95%, transparent);
|
|
153
|
+
|
|
154
|
+
z-index: 9999;
|
|
155
|
+
display: none;
|
|
156
|
+
flex-direction: column;
|
|
157
|
+
align-items: center;
|
|
158
|
+
justify-content: center;
|
|
159
|
+
opacity: 0;
|
|
160
|
+
transition: opacity 0.3s ease;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.nav-spinner {
|
|
164
|
+
width: 50px;
|
|
165
|
+
height: 50px;
|
|
166
|
+
border: 5px solid var(--border-color-primary);
|
|
167
|
+
border-top: 5px solid var(--color-accent);
|
|
168
|
+
border-radius: 50%;
|
|
169
|
+
animation: nav-spin 1s linear infinite;
|
|
170
|
+
margin-bottom: 20px;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@keyframes nav-spin {
|
|
174
|
+
0% { transform: rotate(0deg); }
|
|
175
|
+
100% { transform: rotate(360deg); }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
#nav-loading-text {
|
|
179
|
+
font-size: 1.3rem;
|
|
180
|
+
font-weight: 600;
|
|
181
|
+
color: var(--color-accent);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* ---------------------------------------------------- */
|
|
185
|
+
/* DARK MODE OVERRIDES (HIGH-CONFIDENCE ZONE) */
|
|
186
|
+
/* ---------------------------------------------------- */
|
|
187
|
+
|
|
188
|
+
@media (prefers-color-scheme: dark) {
|
|
189
|
+
.tutorial-intro-box,
|
|
190
|
+
.slide-box,
|
|
191
|
+
.interactive-info-box,
|
|
192
|
+
.complete-box {
|
|
193
|
+
/* Explicit dark background for strong contrast */
|
|
194
|
+
background-color: #2D323E;
|
|
195
|
+
color: white;
|
|
196
|
+
border-color: #555555;
|
|
197
|
+
box-shadow: none;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
#nav-loading-overlay {
|
|
201
|
+
background: rgba(15, 23, 42, 0.9);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.nav-spinner {
|
|
205
|
+
border-color: rgba(148, 163, 184, 0.4);
|
|
206
|
+
border-top-color: var(--color-accent);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
"""
|
|
210
|
+
|
|
211
|
+
with gr.Blocks(theme=gr.themes.Soft(primary_hue=theme_primary_hue), css=css) as demo:
|
|
212
|
+
# Persistent top anchor for scroll-to-top navigation
|
|
213
|
+
gr.HTML("<div id='app_top_anchor' style='height:0;'></div>")
|
|
214
|
+
|
|
215
|
+
# Navigation loading overlay with spinner and dynamic message
|
|
216
|
+
gr.HTML(
|
|
217
|
+
"""
|
|
218
|
+
<div id='nav-loading-overlay'>
|
|
219
|
+
<div class='nav-spinner'></div>
|
|
220
|
+
<span id='nav-loading-text'>Loading...</span>
|
|
221
|
+
</div>
|
|
222
|
+
"""
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
gr.Markdown("<h1 style='text-align:center;'>👋 How to Use an App (A Quick Tutorial)</h1>")
|
|
226
|
+
gr.Markdown(
|
|
227
|
+
"""
|
|
228
|
+
<div class='tutorial-intro-box'>
|
|
229
|
+
This is a simple, 3-step tutorial.<br><br>
|
|
230
|
+
<b>Your Task:</b> Just read the instructions for each step and click the "Next" button to continue.
|
|
231
|
+
</div>
|
|
232
|
+
"""
|
|
233
|
+
)
|
|
234
|
+
gr.HTML("<hr style='margin:24px 0;'>")
|
|
235
|
+
|
|
236
|
+
# --- Loading screen ---
|
|
237
|
+
with gr.Column(visible=False) as loading_screen:
|
|
238
|
+
gr.Markdown(
|
|
239
|
+
"""
|
|
240
|
+
<div style='text-align:center; padding: 100px 0;'>
|
|
241
|
+
<h2 class='loading-title'>⏳ Loading...</h2>
|
|
242
|
+
</div>
|
|
243
|
+
"""
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
# Step 1
|
|
247
|
+
with gr.Column(visible=True, elem_id="step-1") as step_1_container:
|
|
248
|
+
gr.Markdown("<h2 style='text-align:center;'>Step 1: How to Use \"Slideshows\"</h2>")
|
|
249
|
+
gr.Markdown(
|
|
250
|
+
"""
|
|
251
|
+
<div class='slide-box'>
|
|
252
|
+
<b>This is a "Slideshow" step.</b><br><br>
|
|
253
|
+
Some apps are just for reading. Your only task is to click the "Next" button to move to the next step.
|
|
254
|
+
</div>
|
|
255
|
+
"""
|
|
256
|
+
)
|
|
257
|
+
step_1_next = gr.Button("Next Step ▶️", variant="primary")
|
|
258
|
+
|
|
259
|
+
# Step 2
|
|
260
|
+
with gr.Column(visible=False, elem_id="step-2") as step_2_container:
|
|
261
|
+
gr.Markdown("<h2 style='text-align:center;'>Step 2: How to Use \"Interactive Demos\"</h2>")
|
|
262
|
+
gr.Markdown(
|
|
263
|
+
"""
|
|
264
|
+
<div class='interactive-info-box'>
|
|
265
|
+
<b>This is an "Interactive Demo."</b><br><br>
|
|
266
|
+
Just follow the numbered steps below (from top to bottom) to see how it works!
|
|
267
|
+
</div>
|
|
268
|
+
"""
|
|
269
|
+
)
|
|
270
|
+
gr.HTML("<br>")
|
|
271
|
+
gr.Markdown(
|
|
272
|
+
"""
|
|
273
|
+
<div style="font-size: 24px; text-align:left; padding-left: 10px;">
|
|
274
|
+
<b>[ 1 ] Use these sliders to change the inputs.</b>
|
|
275
|
+
</div>
|
|
276
|
+
"""
|
|
277
|
+
)
|
|
278
|
+
s_hours = gr.Slider(0, 12, step=0.5, value=6, label="Hours Studied per Week")
|
|
279
|
+
s_sleep = gr.Slider(4, 10, step=0.5, value=7, label="Hours of Sleep per Night")
|
|
280
|
+
s_att = gr.Slider(50, 100, step=1, value=90, label="Class Attendance %")
|
|
281
|
+
|
|
282
|
+
gr.HTML("<hr style='margin: 20px 0;'>")
|
|
283
|
+
|
|
284
|
+
gr.Markdown(
|
|
285
|
+
"""
|
|
286
|
+
<div style="font-size: 24px; text-align:left; padding-left: 10px;">
|
|
287
|
+
<b>[ 2 ] Click this button to run.</b>
|
|
288
|
+
</div>
|
|
289
|
+
"""
|
|
290
|
+
)
|
|
291
|
+
with gr.Row():
|
|
292
|
+
gr.HTML(visible=False)
|
|
293
|
+
go = gr.Button("🔮 Predict", variant="primary", scale=2)
|
|
294
|
+
gr.HTML(visible=False)
|
|
295
|
+
|
|
296
|
+
gr.HTML("<hr style='margin: 20px 0;'>")
|
|
297
|
+
|
|
298
|
+
gr.Markdown(
|
|
299
|
+
"""
|
|
300
|
+
<div style="font-size: 24px; text-align:left; padding-left: 10px;">
|
|
301
|
+
<b>[ 3 ] See the result here!</b>
|
|
302
|
+
</div>
|
|
303
|
+
"""
|
|
304
|
+
)
|
|
305
|
+
out = gr.Textbox(
|
|
306
|
+
label="🔮 Predicted Exam Score",
|
|
307
|
+
elem_id="prediction_output_textbox",
|
|
308
|
+
interactive=False,
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# Added scroll_to_output so the page scrolls to the prediction result automatically.
|
|
312
|
+
go.click(
|
|
313
|
+
predict_exam,
|
|
314
|
+
[s_hours, s_sleep, s_att],
|
|
315
|
+
out,
|
|
316
|
+
scroll_to_output=True,
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
gr.HTML("<hr style='margin: 15px 0;'>")
|
|
320
|
+
with gr.Row():
|
|
321
|
+
step_2_back = gr.Button("◀️ Back")
|
|
322
|
+
step_2_next = gr.Button("Finish Tutorial ▶️", variant="primary")
|
|
323
|
+
|
|
324
|
+
# Step 3
|
|
325
|
+
with gr.Column(visible=False, elem_id="step-3") as step_3_container:
|
|
326
|
+
gr.Markdown(
|
|
327
|
+
"""
|
|
328
|
+
<div style='text-align:center;'>
|
|
329
|
+
<h2 style='text-align:center; font-size: 2.5rem;'>✅ Tutorial Complete!</h2>
|
|
330
|
+
<div class='complete-box'>
|
|
331
|
+
You've mastered the basics!<br><br>
|
|
332
|
+
Your next step is <b>outside</b> this app window.<br><br>
|
|
333
|
+
<h1 style='margin:0; font-size: 3rem;'>👇 SCROLL DOWN 👇</h1><br>
|
|
334
|
+
Look below this app to find <b>Section 3</b> and begin the challenge!
|
|
335
|
+
</div>
|
|
336
|
+
</div>
|
|
337
|
+
"""
|
|
338
|
+
)
|
|
339
|
+
with gr.Row():
|
|
340
|
+
step_3_back = gr.Button("◀️ Back")
|
|
341
|
+
|
|
342
|
+
# --- NAVIGATION LOGIC (GENERATOR-BASED) ---
|
|
343
|
+
all_steps = [step_1_container, step_2_container, step_3_container, loading_screen]
|
|
344
|
+
|
|
345
|
+
def create_nav_generator(current_step, next_step):
|
|
346
|
+
"""A helper to create the generator functions to avoid repetitive code."""
|
|
347
|
+
|
|
348
|
+
def navigate():
|
|
349
|
+
updates = {loading_screen: gr.update(visible=True)}
|
|
350
|
+
for step in all_steps:
|
|
351
|
+
if step != loading_screen:
|
|
352
|
+
updates[step] = gr.update(visible=False)
|
|
353
|
+
yield updates
|
|
354
|
+
|
|
355
|
+
updates = {next_step: gr.update(visible=True)}
|
|
356
|
+
for step in all_steps:
|
|
357
|
+
if step != next_step:
|
|
358
|
+
updates[step] = gr.update(visible=False)
|
|
359
|
+
yield updates
|
|
360
|
+
|
|
361
|
+
return navigate
|
|
362
|
+
|
|
363
|
+
# Helper function to generate navigation JS with loading overlay
|
|
364
|
+
def nav_js(target_id: str, message: str, min_show_ms: int = 1200) -> str:
|
|
365
|
+
"""
|
|
366
|
+
Generate JavaScript for enhanced slide navigation with loading overlay.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
target_id: Element ID of the target slide (e.g., 'step-2')
|
|
370
|
+
message: Loading message to display during transition
|
|
371
|
+
min_show_ms: Minimum time to show overlay (prevents flicker)
|
|
372
|
+
|
|
373
|
+
Returns:
|
|
374
|
+
JavaScript arrow function string for Gradio's js parameter
|
|
375
|
+
"""
|
|
376
|
+
return f"""
|
|
377
|
+
()=>{{
|
|
378
|
+
try {{
|
|
379
|
+
const overlay = document.getElementById('nav-loading-overlay');
|
|
380
|
+
const messageEl = document.getElementById('nav-loading-text');
|
|
381
|
+
if(overlay && messageEl) {{
|
|
382
|
+
messageEl.textContent = '{message}';
|
|
383
|
+
overlay.style.display = 'flex';
|
|
384
|
+
setTimeout(() => {{ overlay.style.opacity = '1'; }}, 10);
|
|
385
|
+
}}
|
|
386
|
+
|
|
387
|
+
const startTime = Date.now();
|
|
388
|
+
|
|
389
|
+
setTimeout(() => {{
|
|
390
|
+
const anchor = document.getElementById('app_top_anchor');
|
|
391
|
+
const container = document.querySelector('.gradio-container') || document.scrollingElement || document.documentElement;
|
|
392
|
+
|
|
393
|
+
function doScroll() {{
|
|
394
|
+
if(anchor) {{ anchor.scrollIntoView({{behavior:'smooth', block:'start'}}); }}
|
|
395
|
+
else {{ container.scrollTo({{top:0, behavior:'smooth'}}); }}
|
|
396
|
+
|
|
397
|
+
try {{
|
|
398
|
+
if(window.parent && window.parent !== window && window.frameElement) {{
|
|
399
|
+
const top = window.frameElement.getBoundingClientRect().top + window.parent.scrollY;
|
|
400
|
+
window.parent.scrollTo({{top: Math.max(top - 10, 0), behavior:'smooth'}});
|
|
401
|
+
}}
|
|
402
|
+
}} catch(e2) {{}}
|
|
403
|
+
}}
|
|
404
|
+
|
|
405
|
+
doScroll();
|
|
406
|
+
let scrollAttempts = 0;
|
|
407
|
+
const scrollInterval = setInterval(() => {{
|
|
408
|
+
scrollAttempts++;
|
|
409
|
+
doScroll();
|
|
410
|
+
if(scrollAttempts >= 3) clearInterval(scrollInterval);
|
|
411
|
+
}}, 130);
|
|
412
|
+
}}, 40);
|
|
413
|
+
|
|
414
|
+
const targetId = '{target_id}';
|
|
415
|
+
const minShowMs = {min_show_ms};
|
|
416
|
+
let pollCount = 0;
|
|
417
|
+
const maxPolls = 77;
|
|
418
|
+
|
|
419
|
+
const pollInterval = setInterval(() => {{
|
|
420
|
+
pollCount++;
|
|
421
|
+
const elapsed = Date.now() - startTime;
|
|
422
|
+
const target = document.getElementById(targetId);
|
|
423
|
+
const isVisible = target && target.offsetParent !== null &&
|
|
424
|
+
window.getComputedStyle(target).display !== 'none';
|
|
425
|
+
|
|
426
|
+
if((isVisible && elapsed >= minShowMs) || pollCount >= maxPolls) {{
|
|
427
|
+
clearInterval(pollInterval);
|
|
428
|
+
if(overlay) {{
|
|
429
|
+
overlay.style.opacity = '0';
|
|
430
|
+
setTimeout(() => {{ overlay.style.display = 'none'; }}, 300);
|
|
431
|
+
}}
|
|
432
|
+
}}
|
|
433
|
+
}}, 90);
|
|
434
|
+
|
|
435
|
+
}} catch(e) {{ console.warn('nav-js error', e); }}
|
|
436
|
+
}}
|
|
437
|
+
"""
|
|
438
|
+
|
|
439
|
+
step_1_next.click(
|
|
440
|
+
fn=create_nav_generator(step_1_container, step_2_container),
|
|
441
|
+
inputs=None,
|
|
442
|
+
outputs=all_steps,
|
|
443
|
+
show_progress="full",
|
|
444
|
+
js=nav_js("step-2", "Learning to interact..."),
|
|
445
|
+
)
|
|
446
|
+
step_2_back.click(
|
|
447
|
+
fn=create_nav_generator(step_2_container, step_1_container),
|
|
448
|
+
inputs=None,
|
|
449
|
+
outputs=all_steps,
|
|
450
|
+
show_progress="full",
|
|
451
|
+
js=nav_js("step-1", "Returning to start..."),
|
|
452
|
+
)
|
|
453
|
+
step_2_next.click(
|
|
454
|
+
fn=create_nav_generator(step_2_container, step_3_container),
|
|
455
|
+
inputs=None,
|
|
456
|
+
outputs=all_steps,
|
|
457
|
+
show_progress="full",
|
|
458
|
+
js=nav_js("step-3", "Completing tutorial..."),
|
|
459
|
+
)
|
|
460
|
+
step_3_back.click(
|
|
461
|
+
fn=create_nav_generator(step_3_container, step_2_container),
|
|
462
|
+
inputs=None,
|
|
463
|
+
outputs=all_steps,
|
|
464
|
+
show_progress="full",
|
|
465
|
+
js=nav_js("step-2", "Going back..."),
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
return demo
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
def launch_tutorial_app(height: int = 950, share: bool = False, debug: bool = False) -> None:
|
|
472
|
+
"""Convenience wrapper to create and launch the tutorial app inline."""
|
|
473
|
+
demo = create_tutorial_app()
|
|
474
|
+
try:
|
|
475
|
+
import gradio as gr # noqa: F401
|
|
476
|
+
except ImportError as e:
|
|
477
|
+
raise ImportError("Gradio must be installed to launch the tutorial app.") from e
|
|
478
|
+
port = int(os.environ.get("PORT", 8080))
|
|
479
|
+
demo.launch(share=share, inline=True, debug=debug, height=height, server_port=port)
|
|
480
|
+
|
|
481
|
+
|