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,687 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Beginner Mode: Model Building Game (Ètica en Joc) - Justice & Equity Challenge
|
|
3
|
+
|
|
4
|
+
Purpose:
|
|
5
|
+
A simplified, scaffolded version of the full model building app for first-time or low-tech learners.
|
|
6
|
+
|
|
7
|
+
Structure:
|
|
8
|
+
- Factory: create_model_building_game_beginner_app()
|
|
9
|
+
- Launcher: launch_model_building_game_beginner_app()
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import random
|
|
14
|
+
import contextlib
|
|
15
|
+
from io import StringIO
|
|
16
|
+
|
|
17
|
+
import numpy as np
|
|
18
|
+
import pandas as pd
|
|
19
|
+
import requests
|
|
20
|
+
import gradio as gr
|
|
21
|
+
|
|
22
|
+
from sklearn.model_selection import train_test_split
|
|
23
|
+
from sklearn.preprocessing import StandardScaler
|
|
24
|
+
from sklearn.impute import SimpleImputer
|
|
25
|
+
from sklearn.compose import ColumnTransformer
|
|
26
|
+
from sklearn.pipeline import Pipeline
|
|
27
|
+
from sklearn.preprocessing import OneHotEncoder
|
|
28
|
+
from sklearn.linear_model import LogisticRegression
|
|
29
|
+
from sklearn.tree import DecisionTreeClassifier
|
|
30
|
+
from sklearn.ensemble import RandomForestClassifier
|
|
31
|
+
from sklearn.neighbors import KNeighborsClassifier
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
from aimodelshare.playground import Competition
|
|
35
|
+
except ImportError:
|
|
36
|
+
raise ImportError("Install dependencies: pip install aimodelshare aim-widgets")
|
|
37
|
+
|
|
38
|
+
# ---------------------------------------------------------------------
|
|
39
|
+
# Configuration
|
|
40
|
+
# ---------------------------------------------------------------------
|
|
41
|
+
MY_PLAYGROUND_ID = "https://cf3wdpkg0d.execute-api.us-east-1.amazonaws.com/prod/m"
|
|
42
|
+
|
|
43
|
+
MODEL_TYPES = {
|
|
44
|
+
"The Balanced Generalist": {
|
|
45
|
+
"builder": lambda: LogisticRegression(max_iter=500, random_state=42, class_weight="balanced"),
|
|
46
|
+
"card": "A solid default that learns general patterns. Good first choice."
|
|
47
|
+
},
|
|
48
|
+
"The Rule-Maker": {
|
|
49
|
+
"builder": lambda: DecisionTreeClassifier(random_state=42, class_weight="balanced"),
|
|
50
|
+
"card": "Creates if/then rules. Easy to understand; may miss subtle patterns."
|
|
51
|
+
},
|
|
52
|
+
"The 'Nearest Neighbor'": {
|
|
53
|
+
"builder": lambda: KNeighborsClassifier(),
|
|
54
|
+
"card": "Compares each case to similar past ones. Simple pattern matching."
|
|
55
|
+
},
|
|
56
|
+
"The Deep Pattern-Finder": {
|
|
57
|
+
"builder": lambda: RandomForestClassifier(random_state=42, class_weight="balanced"),
|
|
58
|
+
"card": "Many trees working together. Powerful; can overfit if too complex."
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
DEFAULT_MODEL = "The Balanced Generalist"
|
|
63
|
+
TEAM_NAMES = [
|
|
64
|
+
"The Moral Champions", "The Justice League", "The Data Detectives",
|
|
65
|
+
"The Ethical Explorers", "The Fairness Finders", "The Accuracy Avengers"
|
|
66
|
+
]
|
|
67
|
+
CURRENT_TEAM_NAME = random.choice(TEAM_NAMES)
|
|
68
|
+
|
|
69
|
+
BASIC_NUMERIC = [
|
|
70
|
+
"priors_count", "juv_fel_count", "juv_misd_count",
|
|
71
|
+
"juv_other_count", "days_b_screening_arrest"
|
|
72
|
+
]
|
|
73
|
+
BASIC_CATEGORICAL = ["c_charge_desc"]
|
|
74
|
+
OPTIONAL_FEATURE = "age" # Only unlock at final rank (Explorer)
|
|
75
|
+
|
|
76
|
+
MAX_ROWS = 4000
|
|
77
|
+
TOP_N_CHARGES = 40
|
|
78
|
+
np.random.seed(42)
|
|
79
|
+
|
|
80
|
+
# Globals (initialized at launch)
|
|
81
|
+
playground = None
|
|
82
|
+
X_TRAIN_RAW = None
|
|
83
|
+
X_TEST_RAW = None
|
|
84
|
+
Y_TRAIN = None
|
|
85
|
+
Y_TEST = None
|
|
86
|
+
|
|
87
|
+
# ---------------------------------------------------------------------
|
|
88
|
+
# Data Loading
|
|
89
|
+
# ---------------------------------------------------------------------
|
|
90
|
+
def load_and_prep_data():
|
|
91
|
+
url = "https://raw.githubusercontent.com/propublica/compas-analysis/master/compas-scores-two-years.csv"
|
|
92
|
+
df = pd.read_csv(StringIO(requests.get(url).text))
|
|
93
|
+
|
|
94
|
+
if df.shape[0] > MAX_ROWS:
|
|
95
|
+
df = df.sample(n=MAX_ROWS, random_state=42)
|
|
96
|
+
|
|
97
|
+
if "c_charge_desc" in df.columns:
|
|
98
|
+
top_vals = df["c_charge_desc"].value_counts().head(TOP_N_CHARGES).index
|
|
99
|
+
df["c_charge_desc"] = df["c_charge_desc"].apply(
|
|
100
|
+
lambda v: v if (pd.notna(v) and v in top_vals) else "OTHER"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
needed = BASIC_NUMERIC + BASIC_CATEGORICAL + [OPTIONAL_FEATURE]
|
|
104
|
+
for c in needed:
|
|
105
|
+
if c not in df.columns:
|
|
106
|
+
df[c] = np.nan
|
|
107
|
+
|
|
108
|
+
X = df[needed]
|
|
109
|
+
y = df["two_year_recid"]
|
|
110
|
+
|
|
111
|
+
X_train, X_test, y_train, y_test = train_test_split(
|
|
112
|
+
X, y, test_size=0.25, random_state=42, stratify=y
|
|
113
|
+
)
|
|
114
|
+
return X_train, X_test, y_train, y_test
|
|
115
|
+
|
|
116
|
+
# ---------------------------------------------------------------------
|
|
117
|
+
# Helper Functions
|
|
118
|
+
# ---------------------------------------------------------------------
|
|
119
|
+
def safe_int(value, default=1):
|
|
120
|
+
if value is None:
|
|
121
|
+
return default
|
|
122
|
+
try:
|
|
123
|
+
return int(value)
|
|
124
|
+
except (ValueError, TypeError):
|
|
125
|
+
return default
|
|
126
|
+
|
|
127
|
+
def get_model_card(name):
|
|
128
|
+
return MODEL_TYPES.get(name, {}).get("card", "No description available.")
|
|
129
|
+
|
|
130
|
+
def tune_model(model, complexity_level):
|
|
131
|
+
lvl = int(complexity_level)
|
|
132
|
+
if isinstance(model, LogisticRegression):
|
|
133
|
+
model.C = {1: 0.5, 2: 1.0, 3: 3.0}.get(lvl, 1.0)
|
|
134
|
+
elif isinstance(model, DecisionTreeClassifier):
|
|
135
|
+
model.max_depth = {1: 3, 2: 6, 3: None}.get(lvl, 6)
|
|
136
|
+
elif isinstance(model, RandomForestClassifier):
|
|
137
|
+
model.max_depth = {1: 5, 2: 10, 3: None}.get(lvl, 10)
|
|
138
|
+
model.n_estimators = {1: 30, 2: 60, 3: 100}.get(lvl, 60)
|
|
139
|
+
elif isinstance(model, KNeighborsClassifier):
|
|
140
|
+
model.n_neighbors = {1: 25, 2: 10, 3: 5}.get(lvl, 10)
|
|
141
|
+
return model
|
|
142
|
+
|
|
143
|
+
def compute_rank_state(submissions, current_model, current_complexity, current_size, include_age):
|
|
144
|
+
"""
|
|
145
|
+
Determine unlocked tools based on submission count.
|
|
146
|
+
"""
|
|
147
|
+
if submissions == 0:
|
|
148
|
+
return {
|
|
149
|
+
"rank_msg": "### 🧑🎓 Rank: Trainee\nSubmit 1 model to unlock a second model.",
|
|
150
|
+
"models": [DEFAULT_MODEL],
|
|
151
|
+
"model_value": DEFAULT_MODEL,
|
|
152
|
+
"model_interactive": False,
|
|
153
|
+
"complexity_max": 2,
|
|
154
|
+
"complexity_value": min(current_complexity, 2),
|
|
155
|
+
"size_choices": ["Small (40%)", "Full (100%)"],
|
|
156
|
+
"size_value": "Small (40%)",
|
|
157
|
+
"age_enabled": False,
|
|
158
|
+
"age_checked": False
|
|
159
|
+
}
|
|
160
|
+
elif submissions == 1:
|
|
161
|
+
return {
|
|
162
|
+
"rank_msg": "### 🚀 Rank Up: Junior\nRule-Maker + Complexity Level 3 unlocked.",
|
|
163
|
+
"models": [DEFAULT_MODEL, "The Rule-Maker"],
|
|
164
|
+
"model_value": current_model if current_model in [DEFAULT_MODEL, "The Rule-Maker"] else DEFAULT_MODEL,
|
|
165
|
+
"model_interactive": True,
|
|
166
|
+
"complexity_max": 3,
|
|
167
|
+
"complexity_value": min(current_complexity, 3),
|
|
168
|
+
"size_choices": ["Small (40%)", "Full (100%)"],
|
|
169
|
+
"size_value": current_size,
|
|
170
|
+
"age_enabled": False,
|
|
171
|
+
"age_checked": False
|
|
172
|
+
}
|
|
173
|
+
else:
|
|
174
|
+
return {
|
|
175
|
+
"rank_msg": "### 🌟 Rank: Explorer\nAll models + optional 'Age' feature unlocked.",
|
|
176
|
+
"models": list(MODEL_TYPES.keys()),
|
|
177
|
+
"model_value": current_model if current_model in MODEL_TYPES else DEFAULT_MODEL,
|
|
178
|
+
"model_interactive": True,
|
|
179
|
+
"complexity_max": 3,
|
|
180
|
+
"complexity_value": current_complexity,
|
|
181
|
+
"size_choices": ["Small (40%)", "Full (100%)"],
|
|
182
|
+
"size_value": current_size,
|
|
183
|
+
"age_enabled": True,
|
|
184
|
+
"age_checked": include_age
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
def summarize_leaderboard(team_name, username):
|
|
188
|
+
if playground is None:
|
|
189
|
+
return pd.DataFrame(), pd.DataFrame(), "Playground not connected.", 0.0
|
|
190
|
+
|
|
191
|
+
try:
|
|
192
|
+
df = playground.get_leaderboard()
|
|
193
|
+
if df is None or df.empty or "accuracy" not in df.columns:
|
|
194
|
+
return pd.DataFrame(), pd.DataFrame(), "No submissions yet.", 0.0
|
|
195
|
+
|
|
196
|
+
# Team summary (condensed)
|
|
197
|
+
team_df = pd.DataFrame()
|
|
198
|
+
if "Team" in df.columns:
|
|
199
|
+
team_df = (
|
|
200
|
+
df.groupby("Team")["accuracy"]
|
|
201
|
+
.agg(Best="max", Avg="mean", Subs="count")
|
|
202
|
+
.reset_index()
|
|
203
|
+
.sort_values("Best", ascending=False)
|
|
204
|
+
)
|
|
205
|
+
team_df["Best"] = team_df["Best"].round(4)
|
|
206
|
+
team_df["Avg"] = team_df["Avg"].round(4)
|
|
207
|
+
|
|
208
|
+
# Individual summary
|
|
209
|
+
user_best = df.groupby("username")["accuracy"].max().reset_index().rename(columns={"accuracy": "Best"})
|
|
210
|
+
user_best["Best"] = user_best["Best"].round(4)
|
|
211
|
+
user_best = user_best.sort_values("Best", ascending=False).reset_index(drop=True)
|
|
212
|
+
|
|
213
|
+
# Feedback
|
|
214
|
+
latest_acc = 0.0
|
|
215
|
+
feedback = "Submit a model to appear on the leaderboard."
|
|
216
|
+
my_subs = df[df["username"] == username].sort_values("timestamp", ascending=False)
|
|
217
|
+
if not my_subs.empty:
|
|
218
|
+
latest_acc = my_subs.iloc[0]["accuracy"]
|
|
219
|
+
feedback = f"Your latest accuracy: {latest_acc:.4f}"
|
|
220
|
+
if len(my_subs) > 1:
|
|
221
|
+
prev = my_subs.iloc[1]["accuracy"]
|
|
222
|
+
diff = latest_acc - prev
|
|
223
|
+
if diff > 0.0001:
|
|
224
|
+
feedback += f" (Improved +{diff:.4f})"
|
|
225
|
+
elif diff < -0.0001:
|
|
226
|
+
feedback += f" (Down -{abs(diff):.4f})"
|
|
227
|
+
else:
|
|
228
|
+
feedback += " (No change)"
|
|
229
|
+
return team_df, user_best, feedback, latest_acc
|
|
230
|
+
except Exception as e:
|
|
231
|
+
return pd.DataFrame(), pd.DataFrame(), f"Error loading leaderboard: {e}", 0.0
|
|
232
|
+
|
|
233
|
+
def run_beginner_experiment(
|
|
234
|
+
model_name,
|
|
235
|
+
complexity_level,
|
|
236
|
+
size_choice,
|
|
237
|
+
include_age,
|
|
238
|
+
team_name,
|
|
239
|
+
last_accuracy,
|
|
240
|
+
submissions,
|
|
241
|
+
username
|
|
242
|
+
):
|
|
243
|
+
# ---- Normalize transient/invalid inputs (Gradio 5.x safety) ----
|
|
244
|
+
if not model_name or model_name not in MODEL_TYPES:
|
|
245
|
+
model_name = DEFAULT_MODEL
|
|
246
|
+
size_choice = size_choice if size_choice in ["Small (40%)", "Full (100%)"] else "Small (40%)"
|
|
247
|
+
include_age = bool(include_age)
|
|
248
|
+
|
|
249
|
+
# Coerce slider value to safe integer
|
|
250
|
+
complexity_level = safe_int(complexity_level, 2)
|
|
251
|
+
|
|
252
|
+
log = (
|
|
253
|
+
f"▶ Experiment\n"
|
|
254
|
+
f"Model: {model_name}\n"
|
|
255
|
+
f"Complexity: {complexity_level}\n"
|
|
256
|
+
f"Data Size: {size_choice}\n"
|
|
257
|
+
f"Include Age: {'Yes' if include_age else 'No'}\n"
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
if playground is None:
|
|
261
|
+
state = compute_rank_state(submissions, model_name, complexity_level, size_choice, include_age)
|
|
262
|
+
return (
|
|
263
|
+
log + "\nERROR: Playground not connected.",
|
|
264
|
+
"Playground connection failed.",
|
|
265
|
+
pd.DataFrame(),
|
|
266
|
+
pd.DataFrame(),
|
|
267
|
+
last_accuracy,
|
|
268
|
+
submissions,
|
|
269
|
+
state["rank_msg"],
|
|
270
|
+
gr.update(choices=state["models"], value=state["model_value"], interactive=state["model_interactive"]),
|
|
271
|
+
gr.update(minimum=1, maximum=state["complexity_max"], value=state["complexity_value"]),
|
|
272
|
+
gr.update(choices=state["size_choices"], value=state["size_value"]),
|
|
273
|
+
gr.update(interactive=state["age_enabled"], value=state["age_checked"])
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
try:
|
|
277
|
+
# Data sampling
|
|
278
|
+
frac = 0.4 if "Small" in size_choice else 1.0
|
|
279
|
+
if frac == 1.0:
|
|
280
|
+
X_sample = X_TRAIN_RAW
|
|
281
|
+
y_sample = Y_TRAIN
|
|
282
|
+
else:
|
|
283
|
+
X_sample = X_TRAIN_RAW.sample(frac=frac, random_state=42)
|
|
284
|
+
y_sample = Y_TRAIN.loc[X_sample.index]
|
|
285
|
+
log += f"Rows used: {len(X_sample)} ({int(frac*100)}% of training set)\n"
|
|
286
|
+
|
|
287
|
+
# Features
|
|
288
|
+
numeric = list(BASIC_NUMERIC)
|
|
289
|
+
categorical = list(BASIC_CATEGORICAL)
|
|
290
|
+
if include_age:
|
|
291
|
+
numeric.append(OPTIONAL_FEATURE)
|
|
292
|
+
log += f"Features: {', '.join(numeric + categorical)}\n"
|
|
293
|
+
|
|
294
|
+
num_tf = Pipeline([
|
|
295
|
+
("imputer", SimpleImputer(strategy="median")),
|
|
296
|
+
("scale", StandardScaler())
|
|
297
|
+
])
|
|
298
|
+
cat_tf = Pipeline([
|
|
299
|
+
("imputer", SimpleImputer(strategy="constant", fill_value="missing")),
|
|
300
|
+
("onehot", OneHotEncoder(handle_unknown="ignore", sparse_output=False))
|
|
301
|
+
])
|
|
302
|
+
|
|
303
|
+
ct = ColumnTransformer([
|
|
304
|
+
("num", num_tf, numeric),
|
|
305
|
+
("cat", cat_tf, categorical)
|
|
306
|
+
])
|
|
307
|
+
|
|
308
|
+
X_train_processed = ct.fit_transform(X_sample)
|
|
309
|
+
X_test_processed = ct.transform(X_TEST_RAW)
|
|
310
|
+
log += "Preprocessing complete.\n"
|
|
311
|
+
|
|
312
|
+
base = MODEL_TYPES[model_name]["builder"]()
|
|
313
|
+
tuned = tune_model(base, complexity_level)
|
|
314
|
+
tuned.fit(X_train_processed, y_sample)
|
|
315
|
+
log += "Model trained.\n"
|
|
316
|
+
|
|
317
|
+
preds = tuned.predict(X_test_processed)
|
|
318
|
+
desc = f"{model_name} (C:{complexity_level} Size:{'Full' if frac==1.0 else 'Small'} Age:{include_age})"
|
|
319
|
+
tags = f"team:{team_name},mode:beginner"
|
|
320
|
+
|
|
321
|
+
playground.submit_model(
|
|
322
|
+
model=tuned,
|
|
323
|
+
preprocessor=ct,
|
|
324
|
+
prediction_submission=preds,
|
|
325
|
+
input_dict={"description": desc, "tags": tags},
|
|
326
|
+
custom_metadata={"Team": team_name, "Beginner_Mode": 1}
|
|
327
|
+
)
|
|
328
|
+
log += "Submitted to leaderboard.\n"
|
|
329
|
+
|
|
330
|
+
team_df, indiv_df, feedback, latest_acc = summarize_leaderboard(team_name, username)
|
|
331
|
+
new_submissions = submissions + 1
|
|
332
|
+
state = compute_rank_state(new_submissions, model_name, complexity_level, size_choice, include_age)
|
|
333
|
+
|
|
334
|
+
reflection = (
|
|
335
|
+
f"### 🔍 What Just Happened?\n"
|
|
336
|
+
f"- You trained: {model_name}\n"
|
|
337
|
+
f"- Complexity setting: {complexity_level}\n"
|
|
338
|
+
f"- Data amount: {'All data' if frac==1.0 else 'Partial data'}\n"
|
|
339
|
+
f"- Optional Age included: {'Yes' if include_age else 'No'}\n\n"
|
|
340
|
+
f"Latest Accuracy: {latest_acc:.4f}\n"
|
|
341
|
+
f"Tip: Try changing one setting at a time to learn cause and effect."
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
return (
|
|
345
|
+
log,
|
|
346
|
+
reflection + "\n\n" + feedback,
|
|
347
|
+
team_df,
|
|
348
|
+
indiv_df,
|
|
349
|
+
latest_acc,
|
|
350
|
+
new_submissions,
|
|
351
|
+
state["rank_msg"],
|
|
352
|
+
gr.update(choices=state["models"], value=state["model_value"], interactive=state["model_interactive"]),
|
|
353
|
+
gr.update(minimum=1, maximum=state["complexity_max"], value=state["complexity_value"]),
|
|
354
|
+
gr.update(choices=state["size_choices"], value=state["size_value"]),
|
|
355
|
+
gr.update(interactive=state["age_enabled"], value=state["age_checked"])
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
except Exception as e:
|
|
359
|
+
err = f"ERROR: {e}"
|
|
360
|
+
state = compute_rank_state(submissions, model_name, complexity_level, size_choice, include_age)
|
|
361
|
+
return (
|
|
362
|
+
log + err,
|
|
363
|
+
err,
|
|
364
|
+
pd.DataFrame(),
|
|
365
|
+
pd.DataFrame(),
|
|
366
|
+
last_accuracy,
|
|
367
|
+
submissions,
|
|
368
|
+
state["rank_msg"],
|
|
369
|
+
gr.update(choices=state["models"], value=state["model_value"], interactive=state["model_interactive"]),
|
|
370
|
+
gr.update(minimum=1, maximum=state["complexity_max"], value=state["complexity_value"]),
|
|
371
|
+
gr.update(choices=state["size_choices"], value=state["size_value"]),
|
|
372
|
+
gr.update(interactive=state["age_enabled"], value=state["age_checked"])
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
def initial_load(username):
|
|
376
|
+
team_df, indiv_df, feedback, _ = summarize_leaderboard(CURRENT_TEAM_NAME, username)
|
|
377
|
+
state = compute_rank_state(0, DEFAULT_MODEL, 2, "Small (40%)", False)
|
|
378
|
+
return (
|
|
379
|
+
get_model_card(DEFAULT_MODEL),
|
|
380
|
+
team_df,
|
|
381
|
+
indiv_df,
|
|
382
|
+
state["rank_msg"],
|
|
383
|
+
gr.update(choices=state["models"], value=state["model_value"], interactive=state["model_interactive"]),
|
|
384
|
+
gr.update(minimum=1, maximum=state["complexity_max"], value=state["complexity_value"]),
|
|
385
|
+
gr.update(choices=state["size_choices"], value=state["size_value"]),
|
|
386
|
+
gr.update(interactive=state["age_enabled"], value=state["age_checked"])
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
# ---------------------------------------------------------------------
|
|
390
|
+
# Gradio App Factory
|
|
391
|
+
# ---------------------------------------------------------------------
|
|
392
|
+
def create_model_building_game_beginner_app(theme_primary_hue: str = "indigo") -> "gr.Blocks":
|
|
393
|
+
css = """
|
|
394
|
+
.panel {
|
|
395
|
+
background:#fff;
|
|
396
|
+
padding:18px;
|
|
397
|
+
border-radius:16px;
|
|
398
|
+
border:2px solid #e5e7eb;
|
|
399
|
+
margin-bottom:16px;
|
|
400
|
+
}
|
|
401
|
+
.highlight-box {
|
|
402
|
+
background:#e0f2fe;
|
|
403
|
+
padding:18px;
|
|
404
|
+
border-radius:12px;
|
|
405
|
+
border:2px solid #0284c7;
|
|
406
|
+
}
|
|
407
|
+
.log-box textarea {
|
|
408
|
+
font-family: monospace !important;
|
|
409
|
+
font-size: 13px !important;
|
|
410
|
+
}
|
|
411
|
+
"""
|
|
412
|
+
|
|
413
|
+
with gr.Blocks(theme=gr.themes.Soft(primary_hue=theme_primary_hue), css=css) as demo:
|
|
414
|
+
username = os.environ.get("username")
|
|
415
|
+
# Loading screen
|
|
416
|
+
with gr.Column(visible=False) as loading_screen:
|
|
417
|
+
gr.Markdown(
|
|
418
|
+
"""
|
|
419
|
+
<div style='text-align:center; padding:80px 0;'>
|
|
420
|
+
<h2 style='color:#6b7280;'>⏳ Loading...</h2>
|
|
421
|
+
</div>
|
|
422
|
+
"""
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
# Step 1: Intro
|
|
426
|
+
with gr.Column(visible=True) as step_1:
|
|
427
|
+
gr.Markdown("<h1 style='text-align:center;'>🎯 Beginner Mode: Your First AI Experiments</h1>")
|
|
428
|
+
gr.HTML(
|
|
429
|
+
f"""
|
|
430
|
+
<div class='highlight-box'>
|
|
431
|
+
<p><b>Welcome!</b> You joined <b>Team: {CURRENT_TEAM_NAME}</b>.</p>
|
|
432
|
+
<p>This simplified mode helps you learn the experiment loop step-by-step.</p>
|
|
433
|
+
<ul style='font-size:16px;'>
|
|
434
|
+
<li>Pick a model strategy</li>
|
|
435
|
+
<li>Set complexity</li>
|
|
436
|
+
<li>Choose how much data to use</li>
|
|
437
|
+
<li>Submit & observe the leaderboard</li>
|
|
438
|
+
</ul>
|
|
439
|
+
<p style='margin-top:10px;'>You will unlock more tools by submitting models.</p>
|
|
440
|
+
</div>
|
|
441
|
+
"""
|
|
442
|
+
)
|
|
443
|
+
step_1_next = gr.Button("Start Building ▶️", variant="primary", size="lg")
|
|
444
|
+
|
|
445
|
+
# Step 2: Main Workspace
|
|
446
|
+
with gr.Column(visible=False) as step_2:
|
|
447
|
+
gr.Markdown("<h1 style='text-align:center;'>🛠️ Build a Model</h1>")
|
|
448
|
+
rank_message_display = gr.Markdown("Rank loading...")
|
|
449
|
+
|
|
450
|
+
# Hidden states (buffer all dynamic inputs)
|
|
451
|
+
team_state = gr.State(CURRENT_TEAM_NAME)
|
|
452
|
+
last_acc_state = gr.State(0.0)
|
|
453
|
+
submissions_state = gr.State(0)
|
|
454
|
+
|
|
455
|
+
model_state = gr.State(DEFAULT_MODEL)
|
|
456
|
+
complexity_state = gr.State(2)
|
|
457
|
+
size_state = gr.State("Small (40%)")
|
|
458
|
+
age_state = gr.State(False)
|
|
459
|
+
|
|
460
|
+
with gr.Row():
|
|
461
|
+
with gr.Column(scale=1):
|
|
462
|
+
with gr.Group():
|
|
463
|
+
gr.Markdown("### 1️⃣ Choose Model")
|
|
464
|
+
model_radio = gr.Radio(label="Model", choices=[], interactive=False, value=None)
|
|
465
|
+
model_card = gr.Markdown(get_model_card(DEFAULT_MODEL))
|
|
466
|
+
|
|
467
|
+
with gr.Group():
|
|
468
|
+
gr.Markdown("### 2️⃣ Set Complexity")
|
|
469
|
+
complexity_slider = gr.Slider(
|
|
470
|
+
minimum=1, maximum=2, step=1, value=2,
|
|
471
|
+
label="Complexity",
|
|
472
|
+
info="Higher = deeper patterns, but risk of overfitting."
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
with gr.Group():
|
|
476
|
+
gr.Markdown("### 3️⃣ Data Size")
|
|
477
|
+
size_radio = gr.Radio(
|
|
478
|
+
choices=["Small (40%)", "Full (100%)"],
|
|
479
|
+
value="Small (40%)",
|
|
480
|
+
label="Training Data Amount"
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
with gr.Group():
|
|
484
|
+
gr.Markdown("### 4️⃣ Optional Feature (Ethics)")
|
|
485
|
+
age_checkbox = gr.Checkbox(label="Include Age Feature", value=False, interactive=False)
|
|
486
|
+
gr.Markdown(
|
|
487
|
+
"> Age can improve accuracy but raises fairness concerns. Use thoughtfully."
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
with gr.Group():
|
|
491
|
+
gr.Markdown("### 5️⃣ Submit")
|
|
492
|
+
submit_btn = gr.Button("🔬 Train & Submit", variant="primary")
|
|
493
|
+
experiment_log = gr.Textbox(
|
|
494
|
+
label="Run Log",
|
|
495
|
+
lines=10,
|
|
496
|
+
interactive=False,
|
|
497
|
+
elem_classes=["log-box"],
|
|
498
|
+
placeholder="Your experiment steps will appear here..."
|
|
499
|
+
)
|
|
500
|
+
show_details = gr.Checkbox(label="Show Technical Details", value=False)
|
|
501
|
+
details_box = gr.Markdown(visible=False)
|
|
502
|
+
|
|
503
|
+
with gr.Column(scale=1):
|
|
504
|
+
gr.Markdown("### 📊 Feedback & Leaderboards")
|
|
505
|
+
feedback_md = gr.Markdown("Submit a model to see feedback.")
|
|
506
|
+
team_table = gr.DataFrame(value=pd.DataFrame(), label="Team Summary", interactive=False)
|
|
507
|
+
indiv_table = gr.DataFrame(value=pd.DataFrame(), label="Engineer Summary", interactive=False)
|
|
508
|
+
refresh_btn = gr.Button("🔄 Refresh Leaderboard")
|
|
509
|
+
|
|
510
|
+
step_2_next = gr.Button("Finish & Reflect ▶️", variant="secondary")
|
|
511
|
+
|
|
512
|
+
# Step 3: Completion
|
|
513
|
+
with gr.Column(visible=False) as step_3:
|
|
514
|
+
gr.Markdown("<h1 style='text-align:center;'>✅ Beginner Section Complete</h1>")
|
|
515
|
+
gr.HTML(
|
|
516
|
+
"""
|
|
517
|
+
<div class='highlight-box'>
|
|
518
|
+
<p><b>Great job!</b> You now understand the core experiment loop:</p>
|
|
519
|
+
<ol style='font-size:16px;'>
|
|
520
|
+
<li>Pick a model strategy</li>
|
|
521
|
+
<li>Adjust complexity / data amount</li>
|
|
522
|
+
<li>Submit and observe accuracy</li>
|
|
523
|
+
<li>Iterate to improve</li>
|
|
524
|
+
</ol>
|
|
525
|
+
<p>Next: Try Advanced Mode or explore ethical trade-offs in later sections.</p>
|
|
526
|
+
<h2 style='text-align:center;'>👇 SCROLL DOWN FOR NEXT SECTION 👇</h2>
|
|
527
|
+
</div>
|
|
528
|
+
"""
|
|
529
|
+
)
|
|
530
|
+
step_3_back = gr.Button("◀️ Back to Workspace")
|
|
531
|
+
|
|
532
|
+
# Navigation logic
|
|
533
|
+
all_steps = [step_1, step_2, step_3, loading_screen]
|
|
534
|
+
|
|
535
|
+
def nav(to_show, from_show):
|
|
536
|
+
def _go():
|
|
537
|
+
updates = {loading_screen: gr.update(visible=True)}
|
|
538
|
+
for s in all_steps:
|
|
539
|
+
if s != loading_screen:
|
|
540
|
+
updates[s] = gr.update(visible=False)
|
|
541
|
+
yield updates
|
|
542
|
+
|
|
543
|
+
updates = {to_show: gr.update(visible=True)}
|
|
544
|
+
for s in all_steps:
|
|
545
|
+
if s != to_show:
|
|
546
|
+
updates[s] = gr.update(visible=False)
|
|
547
|
+
yield updates
|
|
548
|
+
return _go
|
|
549
|
+
|
|
550
|
+
step_1_next.click(
|
|
551
|
+
fn=nav(step_2, step_1),
|
|
552
|
+
inputs=None,
|
|
553
|
+
outputs=all_steps,
|
|
554
|
+
show_progress="full",
|
|
555
|
+
js="()=>{window.scrollTo({top:0,behavior:'smooth'})}"
|
|
556
|
+
)
|
|
557
|
+
step_2_next.click(
|
|
558
|
+
fn=nav(step_3, step_2),
|
|
559
|
+
inputs=None,
|
|
560
|
+
outputs=all_steps,
|
|
561
|
+
show_progress="full",
|
|
562
|
+
js="()=>{window.scrollTo({top:0,behavior:'smooth'})}"
|
|
563
|
+
)
|
|
564
|
+
step_3_back.click(
|
|
565
|
+
fn=nav(step_2, step_3),
|
|
566
|
+
inputs=None,
|
|
567
|
+
outputs=all_steps,
|
|
568
|
+
show_progress="full",
|
|
569
|
+
js="()=>{window.scrollTo({top:0,behavior:'smooth'})}"
|
|
570
|
+
)
|
|
571
|
+
|
|
572
|
+
# Interactions
|
|
573
|
+
|
|
574
|
+
# Keep the model card in sync
|
|
575
|
+
model_radio.change(fn=get_model_card, inputs=model_radio, outputs=model_card)
|
|
576
|
+
# Mirror Radio into state (coerce None -> DEFAULT_MODEL)
|
|
577
|
+
model_radio.change(fn=lambda v: v or DEFAULT_MODEL, inputs=model_radio, outputs=model_state)
|
|
578
|
+
|
|
579
|
+
# Mirror Slider into state
|
|
580
|
+
complexity_slider.change(fn=lambda v: v, inputs=complexity_slider, outputs=complexity_state)
|
|
581
|
+
# Mirror size Radio into state (coerce None -> default)
|
|
582
|
+
size_radio.change(fn=lambda v: v or "Small (40%)", inputs=size_radio, outputs=size_state)
|
|
583
|
+
# Mirror Checkbox into state (coerce None -> False)
|
|
584
|
+
age_checkbox.change(fn=lambda v: bool(v), inputs=age_checkbox, outputs=age_state)
|
|
585
|
+
|
|
586
|
+
def toggle_details(show):
|
|
587
|
+
if not show:
|
|
588
|
+
return gr.update(visible=False, value="")
|
|
589
|
+
tech_md = """
|
|
590
|
+
### 🧪 Technical Details
|
|
591
|
+
- Preprocessing: Numeric → Median Impute + StandardScaler; Categorical → Constant Impute + OneHot
|
|
592
|
+
- Metric: Accuracy (correct predictions / total)
|
|
593
|
+
- Models available: LogisticRegression, DecisionTree, KNN, RandomForest (phased unlock)
|
|
594
|
+
"""
|
|
595
|
+
return gr.update(visible=True, value=tech_md)
|
|
596
|
+
|
|
597
|
+
show_details.change(toggle_details, show_details, details_box)
|
|
598
|
+
|
|
599
|
+
# Use **states** as inputs for submit
|
|
600
|
+
submit_btn.click(
|
|
601
|
+
fn=run_beginner_experiment,
|
|
602
|
+
inputs=[
|
|
603
|
+
model_state, # buffered radio
|
|
604
|
+
complexity_state, # buffered slider
|
|
605
|
+
size_state, # buffered radio
|
|
606
|
+
age_state, # buffered checkbox
|
|
607
|
+
team_state,
|
|
608
|
+
last_acc_state,
|
|
609
|
+
submissions_state,
|
|
610
|
+
gr.State(username)
|
|
611
|
+
],
|
|
612
|
+
outputs=[
|
|
613
|
+
experiment_log,
|
|
614
|
+
feedback_md,
|
|
615
|
+
team_table,
|
|
616
|
+
indiv_table,
|
|
617
|
+
last_acc_state,
|
|
618
|
+
submissions_state,
|
|
619
|
+
rank_message_display,
|
|
620
|
+
model_radio,
|
|
621
|
+
complexity_slider,
|
|
622
|
+
size_radio,
|
|
623
|
+
age_checkbox
|
|
624
|
+
],
|
|
625
|
+
show_progress="full",
|
|
626
|
+
js="()=>{window.scrollTo({top:0,behavior:'smooth'})}"
|
|
627
|
+
)
|
|
628
|
+
|
|
629
|
+
refresh_btn.click(
|
|
630
|
+
fn=lambda tm, u: summarize_leaderboard(tm, u)[:2],
|
|
631
|
+
inputs=[team_state, gr.State(username)],
|
|
632
|
+
outputs=[team_table, indiv_table]
|
|
633
|
+
)
|
|
634
|
+
|
|
635
|
+
# Initial load
|
|
636
|
+
demo.load(
|
|
637
|
+
fn=lambda u: initial_load(u),
|
|
638
|
+
inputs=[gr.State(username)],
|
|
639
|
+
outputs=[
|
|
640
|
+
model_card,
|
|
641
|
+
team_table,
|
|
642
|
+
indiv_table,
|
|
643
|
+
rank_message_display,
|
|
644
|
+
model_radio,
|
|
645
|
+
complexity_slider,
|
|
646
|
+
size_radio,
|
|
647
|
+
age_checkbox
|
|
648
|
+
]
|
|
649
|
+
)
|
|
650
|
+
|
|
651
|
+
return demo
|
|
652
|
+
|
|
653
|
+
# ---------------------------------------------------------------------
|
|
654
|
+
# Launcher
|
|
655
|
+
# ---------------------------------------------------------------------
|
|
656
|
+
def launch_model_building_game_beginner_app(height: int = 1100, share: bool = False, debug: bool = False):
|
|
657
|
+
global playground, X_TRAIN_RAW, X_TEST_RAW, Y_TRAIN, Y_TEST
|
|
658
|
+
if playground is None:
|
|
659
|
+
try:
|
|
660
|
+
playground = Competition(MY_PLAYGROUND_ID)
|
|
661
|
+
except Exception as e:
|
|
662
|
+
print(f"WARNING: Could not connect to playground: {e}")
|
|
663
|
+
playground = None
|
|
664
|
+
|
|
665
|
+
if X_TRAIN_RAW is None:
|
|
666
|
+
X_TRAIN_RAW, X_TEST_RAW, Y_TRAIN, Y_TEST = load_and_prep_data()
|
|
667
|
+
|
|
668
|
+
app = create_model_building_game_beginner_app()
|
|
669
|
+
port = int(os.environ.get("PORT", 8080))
|
|
670
|
+
with contextlib.redirect_stdout(open(os.devnull, "w")), contextlib.redirect_stderr(open(os.devnull, "w")):
|
|
671
|
+
app.launch(share=share, inline=True, debug=debug, height=height, server_name="0.0.0.0", server_port=port)
|
|
672
|
+
|
|
673
|
+
# ---------------------------------------------------------------------
|
|
674
|
+
# Entrypoint
|
|
675
|
+
# ---------------------------------------------------------------------
|
|
676
|
+
if __name__ == "__main__":
|
|
677
|
+
print("Initializing Beginner Mode...")
|
|
678
|
+
try:
|
|
679
|
+
playground = Competition(MY_PLAYGROUND_ID)
|
|
680
|
+
print("Playground connected.")
|
|
681
|
+
except Exception as e:
|
|
682
|
+
print(f"Playground connection failed: {e}")
|
|
683
|
+
playground = None
|
|
684
|
+
|
|
685
|
+
X_TRAIN_RAW, X_TEST_RAW, Y_TRAIN, Y_TEST = load_and_prep_data()
|
|
686
|
+
print("Launching Beginner Mode App...")
|
|
687
|
+
create_model_building_game_beginner_app().launch(share=False,debug=True)
|