Abhishek Thakur commited on
Commit
e259132
·
1 Parent(s): 20116b4

competition creator

Browse files
Files changed (2) hide show
  1. competitions/cli/create.py +4 -280
  2. competitions/create.py +340 -0
competitions/cli/create.py CHANGED
@@ -1,74 +1,8 @@
1
- import io
2
- import json
3
  from argparse import ArgumentParser
4
 
5
- import click
6
- from huggingface_hub import HfApi, get_token
7
- from loguru import logger
8
- from sklearn.metrics import get_scorer_names
9
-
10
  from . import BaseCompetitionsCommand
11
 
12
 
13
- COMPETITION_DESC = """Sample competition description"""
14
- DATASET_DESC = """Sample dataset description"""
15
- SUBMISSION_DESC = """Sample submission description"""
16
- SOLUTION_CSV = """
17
- id,pred,split
18
- 0,1,public
19
- 1,0,private
20
- 2,0,private
21
- 3,1,private
22
- 4,0,public
23
- 5,1,private
24
- 6,1,public
25
- 7,1,private
26
- 8,0,public
27
- 9,0,private
28
- 10,0,private
29
- 11,0,private
30
- 12,1,private
31
- 13,0,private
32
- 14,1,public
33
- 15,1,private
34
- 16,1,private
35
- 17,0,private
36
- 18,0,private
37
- 19,0,public
38
- 20,0,private
39
- 21,0,private
40
- 22,1,private
41
- 23,1,public
42
- 24,0,private
43
- 25,0,private
44
- 26,0,public
45
- 27,1,private
46
- 28,1,private
47
- 29,0,private
48
- 30,0,public
49
- """
50
- SOLUTION_CSV = SOLUTION_CSV.strip()
51
-
52
- DOCKERFILE = """
53
- FROM huggingface/competitions:latest
54
-
55
- CMD uvicorn competitions.app:app --host 0.0.0.0 --port 7860 --workers 1
56
- """
57
- DOCKERFILE = DOCKERFILE.replace("\n", " ").replace(" ", "\n").strip()
58
-
59
- README = """
60
- ---
61
- title: My Competition
62
- emoji: 🤗
63
- colorFrom: indigo
64
- colorTo: gray
65
- sdk: docker
66
- pinned: false
67
- ---
68
- """
69
- README = README.strip()
70
-
71
-
72
  def create_command_factory(args):
73
  return CreateCompetitionAppCommand()
74
 
@@ -76,221 +10,11 @@ def create_command_factory(args):
76
  class CreateCompetitionAppCommand(BaseCompetitionsCommand):
77
  @staticmethod
78
  def register_subcommand(parser: ArgumentParser):
79
- create_project_parser = parser.add_parser("create", description="✨ Create a new competition")
80
  create_project_parser.set_defaults(func=create_command_factory)
81
 
82
- def _create_readme(self, competition_name):
83
- _readme = "---\n"
84
- _readme += f"title: {competition_name}\n"
85
- _readme += "emoji: 🚀\n"
86
- _readme += "colorFrom: green\n"
87
- _readme += "colorTo: indigo\n"
88
- _readme += "sdk: docker\n"
89
- _readme += "pinned: false\n"
90
- _readme += "duplicated_from: autotrain-projects/autotrain-advanced\n"
91
- _readme += "---\n"
92
- _readme = io.BytesIO(_readme.encode())
93
- return _readme
94
-
95
  def run(self):
96
- competition_name_text = "Competition name. Must be unqiue and contain only letters, numbers & hypens."
97
- competition_name = click.prompt(competition_name_text, type=str)
98
- competition_name = competition_name.lower().replace(" ", "-")
99
- competition_name = competition_name.replace("_", "-")
100
- competition_name = competition_name.replace(".", "-")
101
- competition_name = competition_name.replace("/", "-")
102
- competition_name = competition_name.replace("\\", "-")
103
- competition_name = competition_name.replace(":", "-")
104
- competition_name = competition_name.replace(";", "-")
105
- competition_name = competition_name.replace(",", "-")
106
- competition_name = competition_name.replace("!", "-")
107
- competition_name = competition_name.replace("?", "-")
108
- competition_name = competition_name.replace("'", "-")
109
- competition_name = competition_name.replace('"', "-")
110
- competition_name = competition_name.replace("`", "-")
111
- competition_name = competition_name.replace("~", "-")
112
- competition_name = competition_name.replace("@", "-")
113
- competition_name = competition_name.replace("#", "-")
114
-
115
- competition_org_text = "Competition organization. Choose one of the organizations you are a part of."
116
- competition_org = click.prompt(competition_org_text, type=str)
117
-
118
- competition_type_text = "Competition type. Choose one of 'generic', 'script'"
119
- competition_type = click.prompt(competition_type_text, type=str)
120
- if competition_type not in ["generic", "script"]:
121
- raise ValueError(f"Competition type {competition_type} not found in ['generic', 'script']")
122
- if competition_type == "script":
123
- time_limit = click.prompt("Time limit in seconds", type=int)
124
- else:
125
- time_limit = 10
126
-
127
- hardware_choices = [
128
- "cpu-basic",
129
- "cpu-upgrade",
130
- "t4-small",
131
- "t4-medium",
132
- "zero-a10g",
133
- "a10g-small",
134
- "a10g-large",
135
- "a10g-largex2",
136
- "a10g-largex4",
137
- "a100-large",
138
- ]
139
- hardware_text = f"Hardware. Choose one of {hardware_choices}"
140
- hardware = click.prompt(hardware_text, type=str)
141
- if hardware not in hardware_choices:
142
- raise ValueError(f"Hardware {hardware} not found in {hardware_choices}")
143
-
144
- metric_choices = get_scorer_names()
145
- metric_text = f"Metric. Choose one of {metric_choices}"
146
- metric = click.prompt(metric_text, type=str)
147
- if metric not in metric_choices:
148
- raise ValueError(f"Metric {metric} not found in {metric_choices}")
149
-
150
- eval_higher_text = "Is higher metric better? Enter 1, if yes"
151
- eval_higher = click.prompt(eval_higher_text, type=int)
152
- if eval_higher not in [0, 1]:
153
- raise ValueError("Invalid value for eval_higher. Must be 0 or 1")
154
-
155
- submission_limit_text = "Daily submission limit"
156
- submission_limit = click.prompt(submission_limit_text, type=int)
157
- if submission_limit < 1:
158
- raise ValueError("Submission limit must be positive integer, greater than 0")
159
-
160
- end_date_text = "End date. Format: YYYY-MM-DD. Private leaderboard will be available on this date."
161
- end_date = click.prompt(end_date_text, type=str)
162
-
163
- submission_id_col_text = "Submission ID column name. This column will be used to identify submissions."
164
- submission_id_col = click.prompt(submission_id_col_text, type=str)
165
-
166
- submission_cols_text = "Submission columns. Enter comma separated column names, including id column."
167
- submission_cols = click.prompt(submission_cols_text, type=str)
168
-
169
- submission_rows_text = "Submission rows. How many rows are allowed in a submission, exluding header?"
170
- submission_rows = click.prompt(submission_rows_text, type=int)
171
-
172
- competition_logo_text = "Competition logo. Enter URL to logo."
173
- competition_logo = click.prompt(competition_logo_text, type=str)
174
-
175
- conf_json = {
176
- "COMPETITION_TYPE": competition_type,
177
- "SUBMISSION_LIMIT": submission_limit,
178
- "TIME_LIMIT": time_limit,
179
- "SELECTION_LIMIT": 2,
180
- "HARDWARE": hardware,
181
- "END_DATE": end_date,
182
- "EVAL_HIGHER_IS_BETTER": eval_higher,
183
- "SUBMISSION_ID_COLUMN": submission_id_col,
184
- "SUBMISSION_COLUMNS": submission_cols,
185
- "SUBMISSION_ROWS": submission_rows,
186
- "EVAL_METRIC": metric,
187
- "LOGO": competition_logo,
188
- }
189
-
190
- teams_json = {}
191
- user_team_json = {}
192
-
193
- logger.info(f"Creating competition: {competition_name}")
194
-
195
- api = HfApi()
196
- api.create_repo(
197
- repo_id=f"{competition_org}/{competition_name}",
198
- repo_type="dataset",
199
- private=True,
200
- )
201
-
202
- conf_json = json.dumps(conf_json, indent=4)
203
- conf_json_bytes = conf_json.encode("utf-8")
204
- conf_json_buffer = io.BytesIO(conf_json_bytes)
205
- api.upload_file(
206
- path_or_fileobj=conf_json_buffer,
207
- path_in_repo="conf.json",
208
- repo_id=f"{competition_org}/{competition_name}",
209
- repo_type="dataset",
210
- )
211
-
212
- teams_json = json.dumps(teams_json, indent=4)
213
- teams_json_bytes = teams_json.encode("utf-8")
214
- teams_json_buffer = io.BytesIO(teams_json_bytes)
215
- api.upload_file(
216
- path_or_fileobj=teams_json_buffer,
217
- path_in_repo="teams.json",
218
- repo_id=f"{competition_org}/{competition_name}",
219
- repo_type="dataset",
220
- )
221
-
222
- user_team_json = json.dumps(user_team_json, indent=4)
223
- user_team_json_bytes = user_team_json.encode("utf-8")
224
- user_team_json_buffer = io.BytesIO(user_team_json_bytes)
225
- api.upload_file(
226
- path_or_fileobj=user_team_json_buffer,
227
- path_in_repo="user_team.json",
228
- repo_id=f"{competition_org}/{competition_name}",
229
- repo_type="dataset",
230
- )
231
-
232
- comp_desc = io.BytesIO(COMPETITION_DESC.encode())
233
- api.upload_file(
234
- path_or_fileobj=comp_desc,
235
- path_in_repo="COMPETITION_DESC.md",
236
- repo_id=f"{competition_org}/{competition_name}",
237
- repo_type="dataset",
238
- )
239
-
240
- dataset_desc = io.BytesIO(DATASET_DESC.encode())
241
- api.upload_file(
242
- path_or_fileobj=dataset_desc,
243
- path_in_repo="DATASET_DESC.md",
244
- repo_id=f"{competition_org}/{competition_name}",
245
- repo_type="dataset",
246
- )
247
-
248
- submission_desc = io.BytesIO(SUBMISSION_DESC.encode())
249
- api.upload_file(
250
- path_or_fileobj=submission_desc,
251
- path_in_repo="SUBMISSION_DESC.md",
252
- repo_id=f"{competition_org}/{competition_name}",
253
- repo_type="dataset",
254
- )
255
-
256
- solution_csv = io.BytesIO(SOLUTION_CSV.encode())
257
- api.upload_file(
258
- path_or_fileobj=solution_csv,
259
- path_in_repo="solution.csv",
260
- repo_id=f"{competition_org}/{competition_name}",
261
- repo_type="dataset",
262
- )
263
-
264
- # create competition space
265
- api.create_repo(
266
- repo_id=f"{competition_org}/{competition_name}",
267
- repo_type="space",
268
- space_sdk="docker",
269
- space_hardware="cpu-basic" if competition_type == "script" else hardware,
270
- private=True,
271
- )
272
- api.add_space_secret(repo_id=f"{competition_org}/{competition_name}", key="HF_TOKEN", value=get_token())
273
- api.add_space_secret(
274
- repo_id=f"{competition_org}/{competition_name}",
275
- key="COMPETITION_ID",
276
- value=f"{competition_org}/{competition_name}",
277
- )
278
- readme = self._create_readme(competition_name)
279
- api.upload_file(
280
- path_or_fileobj=readme,
281
- path_in_repo="README.md",
282
- repo_id=f"{competition_org}/{competition_name}",
283
- repo_type="space",
284
- )
285
-
286
- _dockerfile = io.BytesIO(DOCKERFILE.encode())
287
- api.upload_file(
288
- path_or_fileobj=_dockerfile,
289
- path_in_repo="Dockerfile",
290
- repo_id=f"{competition_org}/{competition_name}",
291
- repo_type="space",
292
- )
293
 
294
- logger.info(
295
- "Created private dataset and competition space. To make competition public, you should make the space private. Please note that the dataset should always be kept private."
296
- )
 
 
 
1
  from argparse import ArgumentParser
2
 
 
 
 
 
 
3
  from . import BaseCompetitionsCommand
4
 
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  def create_command_factory(args):
7
  return CreateCompetitionAppCommand()
8
 
 
10
  class CreateCompetitionAppCommand(BaseCompetitionsCommand):
11
  @staticmethod
12
  def register_subcommand(parser: ArgumentParser):
13
+ create_project_parser = parser.add_parser("create", description="✨ Start UI to create a new competition")
14
  create_project_parser.set_defaults(func=create_command_factory)
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  def run(self):
17
+ from competitions.create import main
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ demo = main()
20
+ demo.launch()
 
competitions/create.py ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import json
3
+
4
+ import gradio as gr
5
+ from huggingface_hub import HfApi
6
+ from loguru import logger
7
+ from sklearn.metrics import get_scorer_names
8
+
9
+ from competitions.utils import user_authentication
10
+
11
+
12
+ COMPETITION_DESC = """Sample competition description"""
13
+ DATASET_DESC = """Sample dataset description"""
14
+ SUBMISSION_DESC = """Sample submission description"""
15
+ SOLUTION_CSV = """
16
+ id,pred,split
17
+ 0,1,public
18
+ 1,0,private
19
+ 2,0,private
20
+ 3,1,private
21
+ 4,0,public
22
+ 5,1,private
23
+ 6,1,public
24
+ 7,1,private
25
+ 8,0,public
26
+ 9,0,private
27
+ 10,0,private
28
+ 11,0,private
29
+ 12,1,private
30
+ 13,0,private
31
+ 14,1,public
32
+ 15,1,private
33
+ 16,1,private
34
+ 17,0,private
35
+ 18,0,private
36
+ 19,0,public
37
+ 20,0,private
38
+ 21,0,private
39
+ 22,1,private
40
+ 23,1,public
41
+ 24,0,private
42
+ 25,0,private
43
+ 26,0,public
44
+ 27,1,private
45
+ 28,1,private
46
+ 29,0,private
47
+ 30,0,public
48
+ """
49
+ SOLUTION_CSV = SOLUTION_CSV.strip()
50
+
51
+ DOCKERFILE = """
52
+ FROM huggingface/competitions:latest
53
+
54
+ CMD uvicorn competitions.app:app --host 0.0.0.0 --port 7860 --workers 1
55
+ """
56
+ DOCKERFILE = DOCKERFILE.replace("\n", " ").replace(" ", "\n").strip()
57
+
58
+ HARDWARE_CHOICES = [
59
+ "cpu-basic",
60
+ "cpu-upgrade",
61
+ "t4-small",
62
+ "t4-medium",
63
+ "a10g-small",
64
+ "a10g-large",
65
+ "a10g-largex2",
66
+ "a10g-largex4",
67
+ "a100-large",
68
+ ]
69
+ METRIC_CHOICES = get_scorer_names() + ["custom"]
70
+
71
+
72
+ def check_if_user_can_create_competition(user_token):
73
+ """
74
+ Check if the user can create a competition
75
+ :param user_token: the user's token
76
+ :return: True if the user can create a competition, False otherwise
77
+ """
78
+ user_info = user_authentication(user_token)
79
+ return_msg = None
80
+ if "error" in user_info:
81
+ return_msg = "Invalid token. You can find your HF token here: https://huggingface.co/settings/tokens"
82
+
83
+ elif user_info["auth"]["accessToken"]["role"] != "write":
84
+ return_msg = "Please provide a token with write access"
85
+
86
+ if return_msg is not None:
87
+ return gr.Dropdown()
88
+
89
+ orgs = user_info["orgs"]
90
+ valid_orgs = [org for org in orgs if org["canPay"] is True]
91
+
92
+ if len(valid_orgs) == 0:
93
+ return_msg = """You are not a member of any organization with a valid payment method.
94
+ Please add a valid payment method for your organization in order to create competitions."""
95
+ return gr.Dropdown()
96
+
97
+ valid_orgs = [org for org in valid_orgs if org["roleInOrg"] in ("admin", "write")]
98
+
99
+ if len(valid_orgs) == 0:
100
+ return_msg = """You dont have write access for any organization.
101
+ Please contact your organization's admin to add you as a member with write privilages."""
102
+ return gr.Dropdown()
103
+
104
+ valid_entities = {org["name"]: org["id"] for org in valid_orgs}
105
+
106
+ return gr.Dropdown(
107
+ choices=list(valid_entities.keys()),
108
+ visible=True,
109
+ value=list(valid_entities.keys())[0],
110
+ )
111
+
112
+
113
+ def _create_readme(competition_name):
114
+ _readme = "---\n"
115
+ _readme += f"title: {competition_name}\n"
116
+ _readme += "emoji: 🚀\n"
117
+ _readme += "colorFrom: green\n"
118
+ _readme += "colorTo: indigo\n"
119
+ _readme += "sdk: docker\n"
120
+ _readme += "pinned: false\n"
121
+ _readme += "duplicated_from: autotrain-projects/autotrain-advanced\n"
122
+ _readme += "---\n"
123
+ _readme = io.BytesIO(_readme.encode())
124
+ return _readme
125
+
126
+
127
+ def _create(
128
+ user_token,
129
+ organization,
130
+ competition_name,
131
+ competition_logo,
132
+ hardware,
133
+ competition_type,
134
+ time_limit,
135
+ metric,
136
+ metric_higher_is_better,
137
+ submission_limit,
138
+ selection_limit,
139
+ end_date,
140
+ submission_id_column,
141
+ submission_columns,
142
+ submission_rows,
143
+ ):
144
+ """
145
+ Create a competition
146
+ """
147
+
148
+ # make sure competition name is alphanumeric
149
+ competition_name = "".join([c for c in competition_name if c.isalnum()])
150
+ if len(competition_name) == 0:
151
+ raise gr.Error("Please provide a valid alphanumeric competition name")
152
+
153
+ conf_json = {
154
+ "COMPETITION_TYPE": competition_type,
155
+ "SUBMISSION_LIMIT": int(submission_limit),
156
+ "TIME_LIMIT": int(time_limit),
157
+ "SELECTION_LIMIT": int(selection_limit),
158
+ "HARDWARE": hardware,
159
+ "END_DATE": end_date,
160
+ "EVAL_HIGHER_IS_BETTER": metric_higher_is_better == "True",
161
+ "SUBMISSION_ID_COLUMN": submission_id_column,
162
+ "SUBMISSION_COLUMNS": submission_columns,
163
+ "SUBMISSION_ROWS": int(submission_rows),
164
+ "EVAL_METRIC": metric,
165
+ "LOGO": competition_logo,
166
+ }
167
+ teams_json = {}
168
+ user_team_json = {}
169
+
170
+ logger.info(f"Creating competition: {competition_name}")
171
+
172
+ api = HfApi()
173
+ api.create_repo(
174
+ repo_id=f"{organization}/{competition_name}",
175
+ repo_type="dataset",
176
+ private=True,
177
+ )
178
+
179
+ conf_json = json.dumps(conf_json, indent=4)
180
+ conf_json_bytes = conf_json.encode("utf-8")
181
+ conf_json_buffer = io.BytesIO(conf_json_bytes)
182
+ api.upload_file(
183
+ path_or_fileobj=conf_json_buffer,
184
+ path_in_repo="conf.json",
185
+ repo_id=f"{organization}/{competition_name}",
186
+ repo_type="dataset",
187
+ )
188
+
189
+ teams_json = json.dumps(teams_json, indent=4)
190
+ teams_json_bytes = teams_json.encode("utf-8")
191
+ teams_json_buffer = io.BytesIO(teams_json_bytes)
192
+ api.upload_file(
193
+ path_or_fileobj=teams_json_buffer,
194
+ path_in_repo="teams.json",
195
+ repo_id=f"{organization}/{competition_name}",
196
+ repo_type="dataset",
197
+ )
198
+
199
+ user_team_json = json.dumps(user_team_json, indent=4)
200
+ user_team_json_bytes = user_team_json.encode("utf-8")
201
+ user_team_json_buffer = io.BytesIO(user_team_json_bytes)
202
+ api.upload_file(
203
+ path_or_fileobj=user_team_json_buffer,
204
+ path_in_repo="user_team.json",
205
+ repo_id=f"{organization}/{competition_name}",
206
+ repo_type="dataset",
207
+ )
208
+
209
+ comp_desc = io.BytesIO(COMPETITION_DESC.encode())
210
+ api.upload_file(
211
+ path_or_fileobj=comp_desc,
212
+ path_in_repo="COMPETITION_DESC.md",
213
+ repo_id=f"{organization}/{competition_name}",
214
+ repo_type="dataset",
215
+ )
216
+
217
+ dataset_desc = io.BytesIO(DATASET_DESC.encode())
218
+ api.upload_file(
219
+ path_or_fileobj=dataset_desc,
220
+ path_in_repo="DATASET_DESC.md",
221
+ repo_id=f"{organization}/{competition_name}",
222
+ repo_type="dataset",
223
+ )
224
+
225
+ submission_desc = io.BytesIO(SUBMISSION_DESC.encode())
226
+ api.upload_file(
227
+ path_or_fileobj=submission_desc,
228
+ path_in_repo="SUBMISSION_DESC.md",
229
+ repo_id=f"{organization}/{competition_name}",
230
+ repo_type="dataset",
231
+ )
232
+
233
+ solution_csv = io.BytesIO(SOLUTION_CSV.encode())
234
+ api.upload_file(
235
+ path_or_fileobj=solution_csv,
236
+ path_in_repo="solution.csv",
237
+ repo_id=f"{organization}/{competition_name}",
238
+ repo_type="dataset",
239
+ )
240
+
241
+ # create competition space
242
+ api.create_repo(
243
+ repo_id=f"{organization}/{competition_name}",
244
+ repo_type="space",
245
+ space_sdk="docker",
246
+ space_hardware="cpu-basic" if competition_type == "script" else hardware,
247
+ private=True,
248
+ )
249
+ api.add_space_secret(repo_id=f"{organization}/{competition_name}", key="HF_TOKEN", value=user_token)
250
+ api.add_space_secret(
251
+ repo_id=f"{organization}/{competition_name}",
252
+ key="COMPETITION_ID",
253
+ value=f"{organization}/{competition_name}",
254
+ )
255
+ readme = _create_readme(competition_name)
256
+ api.upload_file(
257
+ path_or_fileobj=readme,
258
+ path_in_repo="README.md",
259
+ repo_id=f"{organization}/{competition_name}",
260
+ repo_type="space",
261
+ )
262
+
263
+ _dockerfile = io.BytesIO(DOCKERFILE.encode())
264
+ api.upload_file(
265
+ path_or_fileobj=_dockerfile,
266
+ path_in_repo="Dockerfile",
267
+ repo_id=f"{organization}/{competition_name}",
268
+ repo_type="space",
269
+ )
270
+
271
+ return gr.Markdown(
272
+ value=f"""Created private dataset and competition space.
273
+ To make competition public, you should make the space public.
274
+ Please note that the dataset should always be kept private.
275
+
276
+ Private dataset: https://huggingface.co/datasets/{organization}/{competition_name}
277
+
278
+ Competition space: https://huggingface.co/spaces/{organization}/{competition_name}
279
+
280
+ Note: there's still some work left. Now you must change the solution.csv file to your own solution,
281
+ and make changes to *_desc.md files to reflect your competition. You may also change conf.json
282
+ to suit your needs. Please refer to the [documentation](https://hf.co/docs/competitions) for more information.
283
+ """
284
+ )
285
+
286
+
287
+ def main():
288
+ with gr.Blocks() as demo:
289
+ gr.Markdown("# Hugging Face Competition Creator")
290
+ token = gr.Textbox(label="Your Hugging Face write token", lines=1, type="password")
291
+ with gr.Row():
292
+ organization = gr.Dropdown(label="Organization name", choices=[""])
293
+ competition_name = gr.Textbox(label="Competition name", lines=1)
294
+ competition_logo = gr.Textbox(label="Competition logo", value="https://mysite.com/mylogo.png", lines=1)
295
+ with gr.Row():
296
+ hardware = gr.Dropdown(label="Hardware to use", choices=HARDWARE_CHOICES, value=HARDWARE_CHOICES[0])
297
+ competition_type = gr.Dropdown(label="Competition type", choices=["generic", "script"], value="generic")
298
+ time_limit = gr.Textbox(label="Time limit (s). Only used for script competitions", lines=1, value="3600")
299
+ with gr.Row():
300
+ metric = gr.Dropdown(label="Metric to use", choices=METRIC_CHOICES, value=METRIC_CHOICES[0])
301
+ metric_higher_is_better = gr.Dropdown(label="Is higher metric better?", choices=[True, False], value=True)
302
+ with gr.Row():
303
+ submission_limit = gr.Textbox(label="Submission limit per day", lines=1, value="5")
304
+ selection_limit = gr.Textbox(label="Final selection limit", lines=1, value="2")
305
+ end_date = gr.Textbox(label="End date (YYYY-MM-DD)", lines=1, value="2024-12-31")
306
+ with gr.Row():
307
+ submission_id_column = gr.Textbox(label="Submission id column", lines=1, value="id")
308
+ submission_columns = gr.Textbox(label="Submission columns", lines=1, value="id,pred")
309
+ submission_rows = gr.Textbox(label="Submission total rows (exclusing header)", lines=1, value="10000")
310
+
311
+ output_md = gr.Markdown("Click the button below to create the competition")
312
+ create_competition = gr.Button(value="Create competition")
313
+ token.change(check_if_user_can_create_competition, inputs=token, outputs=organization)
314
+
315
+ create_competition.click(
316
+ _create,
317
+ inputs=[
318
+ token,
319
+ organization,
320
+ competition_name,
321
+ competition_logo,
322
+ hardware,
323
+ competition_type,
324
+ time_limit,
325
+ metric,
326
+ metric_higher_is_better,
327
+ submission_limit,
328
+ selection_limit,
329
+ end_date,
330
+ submission_id_column,
331
+ submission_columns,
332
+ submission_rows,
333
+ ],
334
+ outputs=output_md,
335
+ )
336
+ return demo
337
+
338
+
339
+ if __name__ == "__main__":
340
+ main().launch()