burtenshaw
commited on
Commit
·
f49bcc1
1
Parent(s):
5ba66b9
update app with formatting and images
Browse files- app.py +131 -47
- push_data.ipynb +215 -0
- pyproject.toml +1 -0
- uv.lock +48 -0
app.py
CHANGED
@@ -1,10 +1,11 @@
|
|
1 |
import os
|
2 |
from datetime import datetime
|
3 |
import random
|
4 |
-
|
5 |
import gradio as gr
|
6 |
from datasets import load_dataset, Dataset, DatasetDict
|
7 |
from huggingface_hub import whoami, InferenceClient
|
|
|
8 |
|
9 |
# Initialize the inference client
|
10 |
client = InferenceClient(
|
@@ -12,37 +13,64 @@ client = InferenceClient(
|
|
12 |
)
|
13 |
|
14 |
# Load questions from Hugging Face dataset
|
15 |
-
EXAM_MAX_QUESTIONS =
|
16 |
-
|
|
|
|
|
17 |
EXAM_DATASET_ID = "burtenshaw/dummy-code-quiz"
|
18 |
|
19 |
# prep the dataset for the quiz
|
20 |
-
ds = load_dataset(EXAM_DATASET_ID, split="train")
|
21 |
-
quiz_data = ds
|
22 |
random.shuffle(quiz_data)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
|
25 |
-
def check_code(
|
|
|
|
|
26 |
"""
|
27 |
Use LLM to evaluate if the user's code solution is correct.
|
28 |
Returns True if the solution is correct, False otherwise.
|
29 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
prompt = f"""You are an expert Python programming instructor evaluating a student's code solution.
|
31 |
|
32 |
Challenge:
|
33 |
{challenge}
|
34 |
|
35 |
Reference Solution:
|
36 |
-
{
|
37 |
|
38 |
Student's Solution:
|
39 |
-
{
|
|
|
|
|
|
|
40 |
|
41 |
Evaluate if the student's solution is functionally equivalent to the reference solution.
|
42 |
Consider:
|
43 |
1. Does it solve the problem correctly?
|
44 |
2. Does it handle edge cases appropriately?
|
45 |
3. Does it follow the requirements of the challenge?
|
|
|
46 |
|
47 |
Respond with ONLY "CORRECT" or "INCORRECT" followed by a brief explanation.
|
48 |
"""
|
@@ -71,18 +99,40 @@ def check_code(user_code, solution, challenge):
|
|
71 |
except Exception as e:
|
72 |
gr.Warning(f"Error checking code: {str(e)}")
|
73 |
# Fall back to simple string comparison if LLM fails
|
74 |
-
is_correct =
|
75 |
status = "✅ Correct!" if is_correct else "❌ Incorrect!"
|
76 |
gr.Info(f"{status} (Fallback comparison)")
|
77 |
return is_correct
|
78 |
|
79 |
|
80 |
def on_user_logged_in(token: gr.OAuthToken | None):
|
81 |
-
"""
|
|
|
|
|
|
|
|
|
82 |
if token is not None:
|
83 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
else:
|
85 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
|
88 |
def push_results_to_hub(
|
@@ -168,14 +218,20 @@ def handle_quiz(question_idx, user_answers, submitted_code, is_start):
|
|
168 |
question_idx < len(quiz_data) and submitted_code.strip()
|
169 |
): # Only check if there's code
|
170 |
current_q = quiz_data[question_idx]
|
|
|
|
|
171 |
is_correct = check_code(
|
172 |
-
|
|
|
|
|
|
|
173 |
)
|
174 |
user_answers.append(
|
175 |
{
|
176 |
"challenge": current_q["challenge"],
|
177 |
-
"submitted_code":
|
178 |
"correct_solution": current_q["solution"],
|
|
|
179 |
"is_correct": is_correct,
|
180 |
}
|
181 |
)
|
@@ -195,31 +251,36 @@ def handle_quiz(question_idx, user_answers, submitted_code, is_start):
|
|
195 |
results_text += (
|
196 |
f"Question {idx + 1}: {'✅' if answer['is_correct'] else '❌'}\n"
|
197 |
)
|
198 |
-
results_text += (
|
199 |
-
f"Your code:\n```python\n{answer['submitted_code']}\n```\n\n"
|
200 |
-
)
|
201 |
|
202 |
return (
|
203 |
-
"", # question_text
|
204 |
-
gr.update(value="", visible=False), #
|
205 |
-
f"{'✅ Passed!' if grade >=
|
206 |
-
question_idx,
|
207 |
-
user_answers,
|
208 |
-
|
209 |
-
gr.update(
|
|
|
|
|
|
|
210 |
)
|
211 |
else:
|
212 |
# Show the next question
|
213 |
q = quiz_data[question_idx]
|
214 |
challenge_text = f"## Question {question_idx + 1} \n### {q['challenge']}"
|
215 |
return (
|
216 |
-
challenge_text,
|
217 |
-
gr.update(value=q["placeholder"], visible=True),
|
218 |
-
"Submit your code solution and click 'Next' to continue.",
|
219 |
-
question_idx,
|
220 |
-
user_answers,
|
221 |
-
|
222 |
-
gr.update(visible=
|
|
|
|
|
|
|
|
|
|
|
223 |
)
|
224 |
|
225 |
|
@@ -238,35 +299,55 @@ with gr.Blocks() as demo:
|
|
238 |
)
|
239 |
|
240 |
with gr.Row(variant="panel"):
|
241 |
-
|
242 |
-
|
|
|
|
|
|
|
|
|
|
|
243 |
|
244 |
with gr.Row(variant="compact"):
|
245 |
status_text = gr.Markdown("")
|
246 |
|
247 |
with gr.Row(variant="compact"):
|
248 |
-
|
249 |
-
|
250 |
-
next_btn = gr.Button("Next ⏭️")
|
251 |
-
submit_btn = gr.Button("Submit ✅")
|
252 |
|
253 |
with gr.Row(variant="compact"):
|
254 |
-
|
255 |
-
start_btn = gr.Button("Start", visible=False)
|
256 |
|
257 |
-
login_btn.click(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
258 |
|
259 |
start_btn.click(
|
260 |
fn=handle_quiz,
|
261 |
inputs=[question_idx, user_answers, code_input, gr.State(True)],
|
262 |
outputs=[
|
263 |
-
question_text,
|
264 |
-
code_input,
|
265 |
-
status_text,
|
266 |
-
question_idx,
|
267 |
-
user_answers,
|
268 |
-
start_btn,
|
269 |
-
|
|
|
|
|
|
|
270 |
],
|
271 |
)
|
272 |
|
@@ -280,7 +361,10 @@ with gr.Blocks() as demo:
|
|
280 |
question_idx,
|
281 |
user_answers,
|
282 |
start_btn,
|
|
|
|
|
283 |
final_markdown,
|
|
|
284 |
],
|
285 |
)
|
286 |
|
|
|
1 |
import os
|
2 |
from datetime import datetime
|
3 |
import random
|
4 |
+
from typing import List
|
5 |
import gradio as gr
|
6 |
from datasets import load_dataset, Dataset, DatasetDict
|
7 |
from huggingface_hub import whoami, InferenceClient
|
8 |
+
import black # Add black import
|
9 |
|
10 |
# Initialize the inference client
|
11 |
client = InferenceClient(
|
|
|
13 |
)
|
14 |
|
15 |
# Load questions from Hugging Face dataset
|
16 |
+
EXAM_MAX_QUESTIONS = int(
|
17 |
+
os.getenv("EXAM_MAX_QUESTIONS", 5)
|
18 |
+
) # Limit quiz to max questions
|
19 |
+
EXAM_PASSING_SCORE = float(os.getenv("EXAM_PASSING_SCORE", 0.8))
|
20 |
EXAM_DATASET_ID = "burtenshaw/dummy-code-quiz"
|
21 |
|
22 |
# prep the dataset for the quiz
|
23 |
+
ds = load_dataset(EXAM_DATASET_ID, split="train", download_mode="force_redownload")
|
24 |
+
quiz_data = list(ds) # Convert dataset to list instead of using to_list()
|
25 |
random.shuffle(quiz_data)
|
26 |
+
if EXAM_MAX_QUESTIONS:
|
27 |
+
quiz_data = quiz_data[:EXAM_MAX_QUESTIONS]
|
28 |
+
|
29 |
+
|
30 |
+
def format_python_code(code: str) -> str:
|
31 |
+
"""Format Python code using black."""
|
32 |
+
try:
|
33 |
+
return black.format_str(code, mode=black.Mode())
|
34 |
+
except Exception as e:
|
35 |
+
gr.Warning(f"Code formatting failed: {str(e)}")
|
36 |
+
return code
|
37 |
|
38 |
|
39 |
+
def check_code(
|
40 |
+
user_code: str, solution: str, challenge: str, assessment_criteria: List[str]
|
41 |
+
):
|
42 |
"""
|
43 |
Use LLM to evaluate if the user's code solution is correct.
|
44 |
Returns True if the solution is correct, False otherwise.
|
45 |
"""
|
46 |
+
# Format both user code and solution
|
47 |
+
formatted_user_code = format_python_code(user_code)
|
48 |
+
formatted_solution = format_python_code(solution)
|
49 |
+
|
50 |
+
assessment_criteria_str = "\n".join(
|
51 |
+
[f"{i + 1}. {c}" for i, c in enumerate(assessment_criteria)]
|
52 |
+
)
|
53 |
+
|
54 |
prompt = f"""You are an expert Python programming instructor evaluating a student's code solution.
|
55 |
|
56 |
Challenge:
|
57 |
{challenge}
|
58 |
|
59 |
Reference Solution:
|
60 |
+
{formatted_solution}
|
61 |
|
62 |
Student's Solution:
|
63 |
+
{formatted_user_code}
|
64 |
+
|
65 |
+
Assessment Criteria:
|
66 |
+
{assessment_criteria_str}
|
67 |
|
68 |
Evaluate if the student's solution is functionally equivalent to the reference solution.
|
69 |
Consider:
|
70 |
1. Does it solve the problem correctly?
|
71 |
2. Does it handle edge cases appropriately?
|
72 |
3. Does it follow the requirements of the challenge?
|
73 |
+
4. Does it meet the assessment criteria?
|
74 |
|
75 |
Respond with ONLY "CORRECT" or "INCORRECT" followed by a brief explanation.
|
76 |
"""
|
|
|
99 |
except Exception as e:
|
100 |
gr.Warning(f"Error checking code: {str(e)}")
|
101 |
# Fall back to simple string comparison if LLM fails
|
102 |
+
is_correct = formatted_user_code.strip() == formatted_solution.strip()
|
103 |
status = "✅ Correct!" if is_correct else "❌ Incorrect!"
|
104 |
gr.Info(f"{status} (Fallback comparison)")
|
105 |
return is_correct
|
106 |
|
107 |
|
108 |
def on_user_logged_in(token: gr.OAuthToken | None):
|
109 |
+
"""
|
110 |
+
Handle user login state.
|
111 |
+
On a valid token, hide the login button and reveal the Start button while keeping Next and Submit hidden.
|
112 |
+
Also, clear the question text, code input, status, and image.
|
113 |
+
"""
|
114 |
if token is not None:
|
115 |
+
return (
|
116 |
+
gr.update(visible=False), # login_btn hidden
|
117 |
+
gr.update(visible=True), # start_btn shown
|
118 |
+
gr.update(visible=False), # next_btn hidden
|
119 |
+
gr.update(visible=False), # submit_btn hidden
|
120 |
+
"", # Clear question_text
|
121 |
+
gr.update(value="", visible=False), # Clear code_input
|
122 |
+
"", # Clear status_text
|
123 |
+
gr.update(value="", visible=False), # Clear question_image
|
124 |
+
)
|
125 |
else:
|
126 |
+
return (
|
127 |
+
gr.update(visible=True), # login_btn visible
|
128 |
+
gr.update(visible=False), # start_btn hidden
|
129 |
+
gr.update(visible=False), # next_btn hidden
|
130 |
+
gr.update(visible=False), # submit_btn hidden
|
131 |
+
"",
|
132 |
+
gr.update(value="", visible=False),
|
133 |
+
"",
|
134 |
+
gr.update(value="", visible=False),
|
135 |
+
)
|
136 |
|
137 |
|
138 |
def push_results_to_hub(
|
|
|
218 |
question_idx < len(quiz_data) and submitted_code.strip()
|
219 |
): # Only check if there's code
|
220 |
current_q = quiz_data[question_idx]
|
221 |
+
# Format the submitted code before checking
|
222 |
+
formatted_code = format_python_code(submitted_code)
|
223 |
is_correct = check_code(
|
224 |
+
formatted_code,
|
225 |
+
current_q["solution"],
|
226 |
+
current_q["challenge"],
|
227 |
+
current_q["assessment_criteria"],
|
228 |
)
|
229 |
user_answers.append(
|
230 |
{
|
231 |
"challenge": current_q["challenge"],
|
232 |
+
"submitted_code": formatted_code, # Store formatted code
|
233 |
"correct_solution": current_q["solution"],
|
234 |
+
"assessment_criteria": current_q["assessment_criteria"],
|
235 |
"is_correct": is_correct,
|
236 |
}
|
237 |
)
|
|
|
251 |
results_text += (
|
252 |
f"Question {idx + 1}: {'✅' if answer['is_correct'] else '❌'}\n"
|
253 |
)
|
|
|
|
|
|
|
254 |
|
255 |
return (
|
256 |
+
"", # question_text cleared
|
257 |
+
gr.update(value="", visible=False), # hide code_input
|
258 |
+
f"{'✅ Passed!' if grade >= EXAM_PASSING_SCORE else '❌ Did not pass'}", # status_text
|
259 |
+
question_idx, # updated question index
|
260 |
+
user_answers, # accumulated answers
|
261 |
+
gr.update(visible=False), # start_btn hidden for quiz-in-progress
|
262 |
+
gr.update(visible=False), # next_btn hidden on completion
|
263 |
+
gr.update(visible=True), # submit_btn shown
|
264 |
+
gr.update(value=results_text, visible=True), # final_markdown with results
|
265 |
+
gr.update(visible=False), # question_image hidden on completion
|
266 |
)
|
267 |
else:
|
268 |
# Show the next question
|
269 |
q = quiz_data[question_idx]
|
270 |
challenge_text = f"## Question {question_idx + 1} \n### {q['challenge']}"
|
271 |
return (
|
272 |
+
challenge_text, # question_text
|
273 |
+
gr.update(value=q["placeholder"], visible=True), # code_input
|
274 |
+
"Submit your code solution and click 'Next' to continue.", # status_text
|
275 |
+
question_idx, # updated question_idx
|
276 |
+
user_answers, # user_answers
|
277 |
+
gr.update(visible=False), # start_btn hidden
|
278 |
+
gr.update(visible=True), # next_btn visible
|
279 |
+
gr.update(visible=False), # submit_btn hidden
|
280 |
+
gr.update(visible=False), # final_markdown hidden
|
281 |
+
gr.update(
|
282 |
+
value=q["image"], visible=True if q["image"] else False
|
283 |
+
), # question_image with current question image
|
284 |
)
|
285 |
|
286 |
|
|
|
299 |
)
|
300 |
|
301 |
with gr.Row(variant="panel"):
|
302 |
+
with gr.Column():
|
303 |
+
question_text = gr.Markdown("")
|
304 |
+
question_image = gr.Image(
|
305 |
+
label="Question Image", visible=False, type="pil"
|
306 |
+
) # Add image component
|
307 |
+
with gr.Column():
|
308 |
+
code_input = gr.Code(language="python", label="Your Solution", visible=False)
|
309 |
|
310 |
with gr.Row(variant="compact"):
|
311 |
status_text = gr.Markdown("")
|
312 |
|
313 |
with gr.Row(variant="compact"):
|
314 |
+
login_btn = gr.LoginButton()
|
315 |
+
start_btn = gr.Button("Start")
|
316 |
+
next_btn = gr.Button("Next ⏭️", visible=False)
|
317 |
+
submit_btn = gr.Button("Submit ✅", visible=False)
|
318 |
|
319 |
with gr.Row(variant="compact"):
|
320 |
+
final_markdown = gr.Markdown("", visible=False)
|
|
|
321 |
|
322 |
+
login_btn.click(
|
323 |
+
fn=on_user_logged_in,
|
324 |
+
inputs=None,
|
325 |
+
outputs=[
|
326 |
+
login_btn,
|
327 |
+
start_btn,
|
328 |
+
next_btn,
|
329 |
+
submit_btn,
|
330 |
+
question_text,
|
331 |
+
code_input,
|
332 |
+
status_text,
|
333 |
+
question_image,
|
334 |
+
],
|
335 |
+
)
|
336 |
|
337 |
start_btn.click(
|
338 |
fn=handle_quiz,
|
339 |
inputs=[question_idx, user_answers, code_input, gr.State(True)],
|
340 |
outputs=[
|
341 |
+
question_text, # Markdown with question text
|
342 |
+
code_input, # Code input field
|
343 |
+
status_text, # Status text (instructions/status messages)
|
344 |
+
question_idx, # Updated question index (state)
|
345 |
+
user_answers, # Updated user answers (state)
|
346 |
+
start_btn, # Update for start button (will be hidden)
|
347 |
+
next_btn, # Update for next button (shown for in-progress quiz)
|
348 |
+
submit_btn, # Update for submit button (hidden until end)
|
349 |
+
final_markdown, # Final results markdown (hidden until quiz ends)
|
350 |
+
question_image, # Image update for the quiz question
|
351 |
],
|
352 |
)
|
353 |
|
|
|
361 |
question_idx,
|
362 |
user_answers,
|
363 |
start_btn,
|
364 |
+
next_btn,
|
365 |
+
submit_btn,
|
366 |
final_markdown,
|
367 |
+
question_image,
|
368 |
],
|
369 |
)
|
370 |
|
push_data.ipynb
ADDED
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 41,
|
6 |
+
"metadata": {},
|
7 |
+
"outputs": [
|
8 |
+
{
|
9 |
+
"name": "stderr",
|
10 |
+
"output_type": "stream",
|
11 |
+
"text": [
|
12 |
+
"Generating train split: 40 examples [00:00, 9668.75 examples/s]"
|
13 |
+
]
|
14 |
+
},
|
15 |
+
{
|
16 |
+
"name": "stdout",
|
17 |
+
"output_type": "stream",
|
18 |
+
"text": [
|
19 |
+
"DatasetDict({\n",
|
20 |
+
" train: Dataset({\n",
|
21 |
+
" features: ['challenge', 'solution', 'placeholder', 'context', 'assessment_criteria', 'image'],\n",
|
22 |
+
" num_rows: 40\n",
|
23 |
+
" })\n",
|
24 |
+
"})\n"
|
25 |
+
]
|
26 |
+
},
|
27 |
+
{
|
28 |
+
"name": "stderr",
|
29 |
+
"output_type": "stream",
|
30 |
+
"text": [
|
31 |
+
"\n"
|
32 |
+
]
|
33 |
+
}
|
34 |
+
],
|
35 |
+
"source": [
|
36 |
+
"from datasets import load_dataset\n",
|
37 |
+
"\n",
|
38 |
+
"dataset = load_dataset(\"json\", data_files=\"example.json\")\n",
|
39 |
+
"\n",
|
40 |
+
"print(dataset)\n"
|
41 |
+
]
|
42 |
+
},
|
43 |
+
{
|
44 |
+
"cell_type": "code",
|
45 |
+
"execution_count": 42,
|
46 |
+
"metadata": {},
|
47 |
+
"outputs": [
|
48 |
+
{
|
49 |
+
"name": "stderr",
|
50 |
+
"output_type": "stream",
|
51 |
+
"text": [
|
52 |
+
"Map: 100%|██████████| 40/40 [00:00<00:00, 6077.16 examples/s]\n"
|
53 |
+
]
|
54 |
+
}
|
55 |
+
],
|
56 |
+
"source": [
|
57 |
+
"from datasets import Image\n",
|
58 |
+
"from PIL import Image as PILImage\n",
|
59 |
+
"\n",
|
60 |
+
"new_features = dataset[\"train\"].features\n",
|
61 |
+
"new_features[\"image\"] = Image()\n",
|
62 |
+
"\n",
|
63 |
+
"dataset.features = new_features\n",
|
64 |
+
"\n",
|
65 |
+
"dataset = dataset.map(lambda x: {\"image\": PILImage.open(x[\"image\"]) if x[\"image\"] else None})\n"
|
66 |
+
]
|
67 |
+
},
|
68 |
+
{
|
69 |
+
"cell_type": "code",
|
70 |
+
"execution_count": 43,
|
71 |
+
"metadata": {},
|
72 |
+
"outputs": [
|
73 |
+
{
|
74 |
+
"data": {
|
75 |
+
"text/plain": [
|
76 |
+
"{'challenge': Value(dtype='string', id=None),\n",
|
77 |
+
" 'solution': Value(dtype='string', id=None),\n",
|
78 |
+
" 'placeholder': Value(dtype='string', id=None),\n",
|
79 |
+
" 'context': Value(dtype='string', id=None),\n",
|
80 |
+
" 'assessment_criteria': Sequence(feature=Value(dtype='string', id=None), length=-1, id=None),\n",
|
81 |
+
" 'image': Image(mode=None, decode=True, id=None)}"
|
82 |
+
]
|
83 |
+
},
|
84 |
+
"execution_count": 43,
|
85 |
+
"metadata": {},
|
86 |
+
"output_type": "execute_result"
|
87 |
+
}
|
88 |
+
],
|
89 |
+
"source": [
|
90 |
+
"dataset = dataset.cast_column(\"image\", Image())\n",
|
91 |
+
"\n",
|
92 |
+
"dataset[\"train\"].features"
|
93 |
+
]
|
94 |
+
},
|
95 |
+
{
|
96 |
+
"cell_type": "code",
|
97 |
+
"execution_count": 44,
|
98 |
+
"metadata": {},
|
99 |
+
"outputs": [
|
100 |
+
{
|
101 |
+
"name": "stderr",
|
102 |
+
"output_type": "stream",
|
103 |
+
"text": [
|
104 |
+
"Map: 100%|██████████| 40/40 [00:00<00:00, 13932.25 examples/s]it/s]\n",
|
105 |
+
"Creating parquet from Arrow format: 100%|██████████| 1/1 [00:00<00:00, 1119.68ba/s]\n",
|
106 |
+
"Uploading the dataset shards: 100%|██████████| 1/1 [00:01<00:00, 1.36s/it]\n"
|
107 |
+
]
|
108 |
+
},
|
109 |
+
{
|
110 |
+
"data": {
|
111 |
+
"text/plain": [
|
112 |
+
"CommitInfo(commit_url='https://huggingface.co/datasets/burtenshaw/dummy-code-quiz/commit/9fdc884bb54602cce29639e76a7cabedf79811f8', commit_message='Upload dataset', commit_description='', oid='9fdc884bb54602cce29639e76a7cabedf79811f8', pr_url=None, repo_url=RepoUrl('https://huggingface.co/datasets/burtenshaw/dummy-code-quiz', endpoint='https://huggingface.co', repo_type='dataset', repo_id='burtenshaw/dummy-code-quiz'), pr_revision=None, pr_num=None)"
|
113 |
+
]
|
114 |
+
},
|
115 |
+
"execution_count": 44,
|
116 |
+
"metadata": {},
|
117 |
+
"output_type": "execute_result"
|
118 |
+
}
|
119 |
+
],
|
120 |
+
"source": [
|
121 |
+
"dataset.push_to_hub(\"burtenshaw/dummy-code-quiz\", private=False)\n"
|
122 |
+
]
|
123 |
+
},
|
124 |
+
{
|
125 |
+
"cell_type": "code",
|
126 |
+
"execution_count": 15,
|
127 |
+
"metadata": {},
|
128 |
+
"outputs": [
|
129 |
+
{
|
130 |
+
"data": {
|
131 |
+
"text/plain": [
|
132 |
+
"'/Users/ben/code/code_assignment_app/images/1.png'"
|
133 |
+
]
|
134 |
+
},
|
135 |
+
"execution_count": 15,
|
136 |
+
"metadata": {},
|
137 |
+
"output_type": "execute_result"
|
138 |
+
}
|
139 |
+
],
|
140 |
+
"source": [
|
141 |
+
"dataset[\"train\"][0][\"image\"]"
|
142 |
+
]
|
143 |
+
},
|
144 |
+
{
|
145 |
+
"cell_type": "code",
|
146 |
+
"execution_count": 3,
|
147 |
+
"metadata": {},
|
148 |
+
"outputs": [
|
149 |
+
{
|
150 |
+
"name": "stderr",
|
151 |
+
"output_type": "stream",
|
152 |
+
"text": [
|
153 |
+
"Generating burtenshaw split: 100%|██████████| 1/1 [00:00<00:00, 262.13 examples/s]\n"
|
154 |
+
]
|
155 |
+
}
|
156 |
+
],
|
157 |
+
"source": [
|
158 |
+
"response_ds = load_dataset(\"agents-course/dummy-code-quiz_responses\")"
|
159 |
+
]
|
160 |
+
},
|
161 |
+
{
|
162 |
+
"cell_type": "code",
|
163 |
+
"execution_count": 4,
|
164 |
+
"metadata": {},
|
165 |
+
"outputs": [
|
166 |
+
{
|
167 |
+
"data": {
|
168 |
+
"text/plain": [
|
169 |
+
"DatasetDict({\n",
|
170 |
+
" burtenshaw: Dataset({\n",
|
171 |
+
" features: ['username', 'datetime', 'grade', 'challenge', 'submitted_code', 'correct_solution', 'is_correct'],\n",
|
172 |
+
" num_rows: 1\n",
|
173 |
+
" })\n",
|
174 |
+
"})"
|
175 |
+
]
|
176 |
+
},
|
177 |
+
"execution_count": 4,
|
178 |
+
"metadata": {},
|
179 |
+
"output_type": "execute_result"
|
180 |
+
}
|
181 |
+
],
|
182 |
+
"source": [
|
183 |
+
"response_ds"
|
184 |
+
]
|
185 |
+
},
|
186 |
+
{
|
187 |
+
"cell_type": "code",
|
188 |
+
"execution_count": null,
|
189 |
+
"metadata": {},
|
190 |
+
"outputs": [],
|
191 |
+
"source": []
|
192 |
+
}
|
193 |
+
],
|
194 |
+
"metadata": {
|
195 |
+
"kernelspec": {
|
196 |
+
"display_name": ".venv",
|
197 |
+
"language": "python",
|
198 |
+
"name": "python3"
|
199 |
+
},
|
200 |
+
"language_info": {
|
201 |
+
"codemirror_mode": {
|
202 |
+
"name": "ipython",
|
203 |
+
"version": 3
|
204 |
+
},
|
205 |
+
"file_extension": ".py",
|
206 |
+
"mimetype": "text/x-python",
|
207 |
+
"name": "python",
|
208 |
+
"nbconvert_exporter": "python",
|
209 |
+
"pygments_lexer": "ipython3",
|
210 |
+
"version": "3.11.10"
|
211 |
+
}
|
212 |
+
},
|
213 |
+
"nbformat": 4,
|
214 |
+
"nbformat_minor": 2
|
215 |
+
}
|
pyproject.toml
CHANGED
@@ -5,6 +5,7 @@ description = "Add your description here"
|
|
5 |
readme = "README.md"
|
6 |
requires-python = ">=3.11"
|
7 |
dependencies = [
|
|
|
8 |
"datasets>=3.2.0",
|
9 |
"gradio[oauth]>=5.13.2",
|
10 |
"huggingface-hub>=0.28.0",
|
|
|
5 |
readme = "README.md"
|
6 |
requires-python = ">=3.11"
|
7 |
dependencies = [
|
8 |
+
"black>=25.1.0",
|
9 |
"datasets>=3.2.0",
|
10 |
"gradio[oauth]>=5.13.2",
|
11 |
"huggingface-hub>=0.28.0",
|
uv.lock
CHANGED
@@ -200,6 +200,34 @@ wheels = [
|
|
200 |
{ url = "https://files.pythonhosted.org/packages/e8/6a/e83a6c04f8c6014c33d97c135782a55370cf60513f8d9f99f1279c7f9c13/Authlib-1.4.1-py2.py3-none-any.whl", hash = "sha256:edc29c3f6a3e72cd9e9f45fff67fc663a2c364022eb0371c003f22d5405915c1", size = 225610 },
|
201 |
]
|
202 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
[[package]]
|
204 |
name = "certifi"
|
205 |
version = "2024.12.14"
|
@@ -319,6 +347,7 @@ name = "code-assignment-app"
|
|
319 |
version = "0.1.0"
|
320 |
source = { virtual = "." }
|
321 |
dependencies = [
|
|
|
322 |
{ name = "datasets" },
|
323 |
{ name = "gradio", extra = ["oauth"] },
|
324 |
{ name = "huggingface-hub" },
|
@@ -327,6 +356,7 @@ dependencies = [
|
|
327 |
|
328 |
[package.metadata]
|
329 |
requires-dist = [
|
|
|
330 |
{ name = "datasets", specifier = ">=3.2.0" },
|
331 |
{ name = "gradio", extras = ["oauth"], specifier = ">=5.13.2" },
|
332 |
{ name = "huggingface-hub", specifier = ">=0.28.0" },
|
@@ -922,6 +952,15 @@ wheels = [
|
|
922 |
{ url = "https://files.pythonhosted.org/packages/da/d9/f7f9379981e39b8c2511c9e0326d212accacb82f12fbfdc1aa2ce2a7b2b6/multiprocess-0.70.16-py39-none-any.whl", hash = "sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3", size = 133351 },
|
923 |
]
|
924 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
925 |
[[package]]
|
926 |
name = "nest-asyncio"
|
927 |
version = "1.6.0"
|
@@ -1085,6 +1124,15 @@ wheels = [
|
|
1085 |
{ url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650 },
|
1086 |
]
|
1087 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1088 |
[[package]]
|
1089 |
name = "pexpect"
|
1090 |
version = "4.9.0"
|
|
|
200 |
{ url = "https://files.pythonhosted.org/packages/e8/6a/e83a6c04f8c6014c33d97c135782a55370cf60513f8d9f99f1279c7f9c13/Authlib-1.4.1-py2.py3-none-any.whl", hash = "sha256:edc29c3f6a3e72cd9e9f45fff67fc663a2c364022eb0371c003f22d5405915c1", size = 225610 },
|
201 |
]
|
202 |
|
203 |
+
[[package]]
|
204 |
+
name = "black"
|
205 |
+
version = "25.1.0"
|
206 |
+
source = { registry = "https://pypi.org/simple" }
|
207 |
+
dependencies = [
|
208 |
+
{ name = "click" },
|
209 |
+
{ name = "mypy-extensions" },
|
210 |
+
{ name = "packaging" },
|
211 |
+
{ name = "pathspec" },
|
212 |
+
{ name = "platformdirs" },
|
213 |
+
]
|
214 |
+
sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449 }
|
215 |
+
wheels = [
|
216 |
+
{ url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372 },
|
217 |
+
{ url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865 },
|
218 |
+
{ url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699 },
|
219 |
+
{ url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028 },
|
220 |
+
{ url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988 },
|
221 |
+
{ url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985 },
|
222 |
+
{ url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816 },
|
223 |
+
{ url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860 },
|
224 |
+
{ url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673 },
|
225 |
+
{ url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190 },
|
226 |
+
{ url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926 },
|
227 |
+
{ url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613 },
|
228 |
+
{ url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646 },
|
229 |
+
]
|
230 |
+
|
231 |
[[package]]
|
232 |
name = "certifi"
|
233 |
version = "2024.12.14"
|
|
|
347 |
version = "0.1.0"
|
348 |
source = { virtual = "." }
|
349 |
dependencies = [
|
350 |
+
{ name = "black" },
|
351 |
{ name = "datasets" },
|
352 |
{ name = "gradio", extra = ["oauth"] },
|
353 |
{ name = "huggingface-hub" },
|
|
|
356 |
|
357 |
[package.metadata]
|
358 |
requires-dist = [
|
359 |
+
{ name = "black", specifier = ">=25.1.0" },
|
360 |
{ name = "datasets", specifier = ">=3.2.0" },
|
361 |
{ name = "gradio", extras = ["oauth"], specifier = ">=5.13.2" },
|
362 |
{ name = "huggingface-hub", specifier = ">=0.28.0" },
|
|
|
952 |
{ url = "https://files.pythonhosted.org/packages/da/d9/f7f9379981e39b8c2511c9e0326d212accacb82f12fbfdc1aa2ce2a7b2b6/multiprocess-0.70.16-py39-none-any.whl", hash = "sha256:a0bafd3ae1b732eac64be2e72038231c1ba97724b60b09400d68f229fcc2fbf3", size = 133351 },
|
953 |
]
|
954 |
|
955 |
+
[[package]]
|
956 |
+
name = "mypy-extensions"
|
957 |
+
version = "1.0.0"
|
958 |
+
source = { registry = "https://pypi.org/simple" }
|
959 |
+
sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 }
|
960 |
+
wheels = [
|
961 |
+
{ url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 },
|
962 |
+
]
|
963 |
+
|
964 |
[[package]]
|
965 |
name = "nest-asyncio"
|
966 |
version = "1.6.0"
|
|
|
1124 |
{ url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650 },
|
1125 |
]
|
1126 |
|
1127 |
+
[[package]]
|
1128 |
+
name = "pathspec"
|
1129 |
+
version = "0.12.1"
|
1130 |
+
source = { registry = "https://pypi.org/simple" }
|
1131 |
+
sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 }
|
1132 |
+
wheels = [
|
1133 |
+
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 },
|
1134 |
+
]
|
1135 |
+
|
1136 |
[[package]]
|
1137 |
name = "pexpect"
|
1138 |
version = "4.9.0"
|