tommymarto commited on
Commit
95df539
Β·
1 Parent(s): 7832cd9
Files changed (1) hide show
  1. demo.py +106 -124
demo.py CHANGED
@@ -15,7 +15,6 @@ def clamp(x, minimum, maximum):
15
  #################################################################################################################################################
16
 
17
 
18
-
19
  # read secret api key
20
  API_KEY = os.environ['ApiKey']
21
  FIREBASE_API_KEY = os.environ['FirebaseSecret']
@@ -23,10 +22,10 @@ FIREBASE_URL = os.environ['FirebaseURL']
23
  SETUP_MODEL = os.environ['SETUP_MODEL']
24
 
25
 
26
- # creds = credentials.Certificate(json.loads(FIREBASE_API_KEY))
27
- # firebase_app = firebase_admin.initialize_app(creds, {'databaseURL': FIREBASE_URL})
28
- # firebase_data_ref = db.reference("data")
29
- # firebase_current_ref = None
30
 
31
  BASE_URL = "https://skapi.polyglot-edu.com/"
32
 
@@ -37,80 +36,23 @@ BASE_URL = "https://skapi.polyglot-edu.com/"
37
  levels = ["Primary School", "Middle School", "High School", "College", "Academy"]
38
  languages = ["English", "Italian", "French", "German", "Spanish"]
39
  type_of_exercise = ["Open Question", "Short Answer Question", "True or False", "Fill in the Blanks", "Single Choice", "Multiple Choice", "Debate", "Essay", "Brainstorming", "Knoledge Exposition"]
 
40
 
41
- def generation_to_dict(experiment, skip=False):
42
- info = {
43
- # experiment info
44
- **experiment,
45
-
46
- # chosen image set info
47
- "corrupted_filename": experiment["corrupted"]["name"],
48
- "options": [img["name"] for img in experiment["options"]],
49
- }
50
-
51
- if skip:
52
- info = {
53
- **info,
54
- # selected image info
55
- "selected_image": "None",
56
- "selected_algo": "None",
57
- }
58
  else:
59
- info = {
60
- **info,
61
- # selected image info
62
- "selected_image": experiment["options"][experiment["selected_image"]]["name"],
63
- "selected_algo": experiment["options"][experiment["selected_image"]]["algo"],
64
- }
65
-
66
- return info
67
-
68
- def generate_new_experiment():
69
- pass
70
- # wanted_corruptions = ["spatter", "impulse_noise", "speckle_noise", "gaussian_noise", "pixelate", "jpeg_compression", "elastic_transform"]
71
- # corruption = random.choice([f for f in list(Path(f"./images/{DATASET}").glob("*/*")) if f.is_dir() and f.name in wanted_corruptions])
72
- # image_id = random.choice(list(corruption.glob("*")))
73
- # imgs_to_sample = (NUMBER_OF_IMAGES_PER_ROW * NUMBER_OF_ROWS) // 2
74
-
75
- # corrupted_image = {"name": str(random.choice(list(image_id.glob("*corrupted*"))))}
76
- # sdedit_images = [
77
- # {"name": str(img), "algo": "SDEdit"}
78
- # for img in random.sample(list((image_id / "sde").glob(f"*")), imgs_to_sample)
79
- # ]
80
- # odedit_images = [
81
- # {"name": str(img), "algo": "ODEdit"}
82
- # for img in random.sample(list((image_id / "ode").glob(f"*")), imgs_to_sample)
83
- # ]
84
- # total_images = sdedit_images + odedit_images
85
- # random.shuffle(total_images)
86
-
87
- # return Experiment(
88
- # DATASET,
89
- # corruption.name,
90
- # image_id.name,
91
- # corrupted_image,
92
- # total_images,
93
- # )
94
-
95
- def save(experiment, corrupted_component, *img_components, mode):
96
- if mode == "save" and (experiment is None or experiment["selected_image"] is None):
97
- gr.Warning("You must select an image before submitting")
98
- return [experiment, corrupted_component, *img_components]
99
- if mode == "skip":
100
- experiment["selected_image"] = None
101
-
102
- dict_to_save = {
103
- **generation_to_dict(experiment, skip=(mode=="skip")),
104
- "timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
105
- }
106
- # firebase_data_ref.push(dict_to_save)
107
-
108
- print("=====================")
109
- print(dict_to_save)
110
- print("=====================")
111
-
112
- gr.Info("Your choice has been saved to Firebase")
113
- return next()
114
 
115
  def analyze_resource(url):
116
  response = requests.post(
@@ -139,8 +81,6 @@ def generate_learning_objective(topic, context, level):
139
  timeout=20
140
  )
141
 
142
- print(topic, context, level)
143
-
144
  if response.status_code != 200:
145
  raise gr.Error(f"Failed to generate learning objective: {response.text}")
146
 
@@ -152,17 +92,17 @@ def generate_exercise(state):
152
  if item in value:
153
  return key
154
  return None
 
 
155
 
156
- step3 = requests.post(
157
- BASE_URL + "Exercises/GenerateExercise",
158
- headers={"ApiKey": API_KEY, "SetupModel": str(SETUP_MODEL)},
159
- json={
160
  # filled in with the data from the previous steps
161
  "macroSubject": state['MacroSubject'],
162
  "title": state['Title'],
163
- "level": state['level'],
164
  "learningObjective": state['learningObjective'],
165
- "bloomLevel": find_key(state["learningObjectiveList"], state['learningObjective']),
166
  "language": state['Language'],
167
  "material": state['material_url'],
168
  "assignmentType": [topic['Type'] for topic in state['MainTopics'] if topic['Topic'] == state['topic']][0],
@@ -170,52 +110,74 @@ def generate_exercise(state):
170
  "temperature": 0,
171
 
172
  # to be filled in manually
173
- "correctAnswersNumber": 0,
174
- "distractorsNumber": 0,
175
- "easilyDiscardableDistractorsNumber": 0,
176
- "typeOfExercise": 0
177
- },
 
 
 
 
 
 
 
178
  timeout=20
179
  )
180
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
  ##################################################################
182
  # UI Layer
183
  ##################################################################
184
 
185
  def format_output(output, exercise_type):
186
- if type_of_exercise[exercise_type] in ["Open Question", "Short Answer Question"]:
187
- return f"<div class='markdown-body'><h3>{output['Assignment']}</h3><p>{output['Solutions'][0]}</p></div>"
188
-
189
- return f"<div class='markdown-body'><h3>Ouput (unknown type)</h3><p>{output['Solutions'][0]}</p></div>"
190
-
191
-
192
- def reset_UI():
193
- return [
194
- {"level": levels[-1], "language": "English"},
195
- ]
196
-
197
- def next():
198
- new_experiment = generate_new_experiment()
199
-
200
- new_img_components = [
201
- gr.Image(value=img["name"], label=f"{i}", elem_id="unsel", show_label=False, show_download_button=False, show_share_button=False, interactive=False)
202
- for i, img in enumerate(new_experiment["options"])
203
- ]
204
- new_corrupted_component = gr.Image(value=new_experiment["corrupted"]["name"], label="corr", elem_id="corrupted", show_label=False, show_download_button=False, show_share_button=False, interactive=False)
205
-
206
- return [new_experiment, new_corrupted_component, *new_img_components]
207
 
208
  def on_url_change(url, state):
 
 
 
 
209
  material = analyze_resource(url)
210
 
211
  topics = [topic['Topic'] for topic in material['MainTopics']]
212
 
213
- components = reset_UI()
214
- state = components[0]
215
  state = state | material
216
  state['material_url'] = url
217
 
218
- return [gr.Radio(label="Topic", choices=topics, interactive=True), state]
 
 
 
 
 
 
219
 
220
  def on_topic_change(topic, old_state):
221
  old_state['topic'] = topic
@@ -251,7 +213,7 @@ body, html {
251
  }
252
  iframe.second-row {
253
  width: 100%; /* Full width */
254
- height: 50vh; /* Full height */
255
  border: none; /* No border */
256
  background-color: #f9f9f9; /* Light background */
257
  }
@@ -268,6 +230,8 @@ iframe.second-row {
268
  box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* Subtle shadow for depth */
269
  max-width: 800px; /* Max width to maintain optimal line length */
270
  margin: 20px auto; /* Center align the Markdown content */
 
 
271
  }
272
 
273
  /* Headings with increased weight and spacing for clear hierarchy */
@@ -351,29 +315,37 @@ iframe.second-row {
351
  }
352
  """
353
 
 
 
 
354
 
355
  with gr.Blocks(title="Educational AI", css=css) as demo:
356
- state = gr.State({"level": levels[-1], "language": "English"})
357
 
358
  with gr.Row(elem_classes=["row-content"]):
359
  with gr.Column(scale=3, elem_classes=["column-content"]):
360
- language_component = gr.Dropdown(languages, label="Exercise Language", value="English")
361
  level_component = gr.Dropdown(label="Level", choices=levels, value=levels[-1])
362
  url_component = gr.Textbox(label="Input URL", placeholder="Enter URL here...")
363
  iframe_component = gr.HTML("<iframe class='second-row' src='' allowfullscreen></iframe>")
364
 
365
  with gr.Column(scale=3):
 
366
  topic_component = gr.Radio(label="Topic", choices=["placeholder"], interactive=False)
367
  lo_component = gr.Dropdown(label="Learning Objective", choices=[], value="placeholder", interactive=False)
368
- question_type_component = gr.Dropdown(label="Question Type", choices=type_of_exercise, type="index")
369
 
370
- correct_answers_component = gr.Number(value=1, minimum=1, maximum=3, step=1, label="Number of correct answers", interactive=False)
371
- easy_distractors_component = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of easy distractors", interactive=False)
372
- distractors_component = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of distractors", interactive=False)
 
 
373
 
374
  with gr.Column(scale=3):
375
- generate_btn = gr.Button("Generate Question")
376
  output_component = gr.HTML("<div class='markdown-body'><h3>Output</h3>Placeholder for output</div>")
 
 
 
 
377
 
378
  # on language change
379
  language_component.change(lambda x, old_state: old_state | {"language": x}, [language_component, state], [state])
@@ -384,7 +356,7 @@ with gr.Blocks(title="Educational AI", css=css) as demo:
384
  # on url change
385
  url_component.change(lambda x: gr.HTML(f"<iframe class='second-row' src='{x}' allowfullscreen></iframe>"), [url_component], [iframe_component])
386
  url_component.change(lambda x: gr.Info(f"Analyzing resource at {x}..."), [url_component], [])
387
- url_component.change(on_url_change, [url_component, state], [topic_component, state])
388
 
389
  # on topic change
390
  topic_component.change(lambda x: gr.Info(f"Generating learning objective for {x}..."), [topic_component], [])
@@ -395,7 +367,17 @@ with gr.Blocks(title="Educational AI", css=css) as demo:
395
 
396
  # on question type change
397
  question_type_component.change(lambda x, old_state: old_state | {"typeOfExercise": x}, [question_type_component, state], [state])
398
-
 
 
 
 
 
 
 
 
 
 
399
 
400
  # on generate question
401
  generate_btn.click(lambda: gr.Info("Generating question..."))
 
15
  #################################################################################################################################################
16
 
17
 
 
18
  # read secret api key
19
  API_KEY = os.environ['ApiKey']
20
  FIREBASE_API_KEY = os.environ['FirebaseSecret']
 
22
  SETUP_MODEL = os.environ['SETUP_MODEL']
23
 
24
 
25
+ creds = credentials.Certificate(json.loads(FIREBASE_API_KEY))
26
+ firebase_app = firebase_admin.initialize_app(creds, {'databaseURL': FIREBASE_URL})
27
+ firebase_data_ref = db.reference("data")
28
+ firebase_current_ref = None
29
 
30
  BASE_URL = "https://skapi.polyglot-edu.com/"
31
 
 
36
  levels = ["Primary School", "Middle School", "High School", "College", "Academy"]
37
  languages = ["English", "Italian", "French", "German", "Spanish"]
38
  type_of_exercise = ["Open Question", "Short Answer Question", "True or False", "Fill in the Blanks", "Single Choice", "Multiple Choice", "Debate", "Essay", "Brainstorming", "Knoledge Exposition"]
39
+ bloom_levels = ["Remembering", "Understanding", "Applying", "Analyzing", "Evaluating", "Creating"]
40
 
41
+ def like():
42
+ global firebase_current_ref
43
+ if firebase_current_ref is not None:
44
+ firebase_current_ref.update({"like": 1})
45
+ gr.Info("Generated text liked.")
 
 
 
 
 
 
 
 
 
 
 
 
46
  else:
47
+ gr.Warning("No generated text to vote.")
48
+
49
+ def dislike():
50
+ global firebase_current_ref
51
+ if firebase_current_ref is not None:
52
+ firebase_current_ref.update({"like": -1})
53
+ gr.Info("Generated text disliked.")
54
+ else:
55
+ gr.Warning("No generated text to vote.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
  def analyze_resource(url):
58
  response = requests.post(
 
81
  timeout=20
82
  )
83
 
 
 
84
  if response.status_code != 200:
85
  raise gr.Error(f"Failed to generate learning objective: {response.text}")
86
 
 
92
  if item in value:
93
  return key
94
  return None
95
+
96
+ gr.Info(find_key(state["learningObjectiveList"], state['learningObjective']))
97
 
98
+ try:
99
+ _json = {
 
 
100
  # filled in with the data from the previous steps
101
  "macroSubject": state['MacroSubject'],
102
  "title": state['Title'],
103
+ "level": levels.index(state['level']),
104
  "learningObjective": state['learningObjective'],
105
+ "bloomLevel": bloom_levels.index(find_key(state["learningObjectiveList"], state['learningObjective'])),
106
  "language": state['Language'],
107
  "material": state['material_url'],
108
  "assignmentType": [topic['Type'] for topic in state['MainTopics'] if topic['Topic'] == state['topic']][0],
 
110
  "temperature": 0,
111
 
112
  # to be filled in manually
113
+ "typeOfExercise": state['typeOfExercise'],
114
+ "correctAnswersNumber": state["correctAnswersNumber"],
115
+ "distractorsNumber": state["distractorsNumber"],
116
+ "easilyDiscardableDistractorsNumber": state["easyDistractorsNumber"],
117
+ }
118
+ except KeyError as e:
119
+ raise gr.Error(f"Missing key: {e}")
120
+
121
+ step3 = requests.post(
122
+ BASE_URL + "Exercises/GenerateExercise",
123
+ headers={"ApiKey": API_KEY, "SetupModel": str(SETUP_MODEL)},
124
+ json=_json,
125
  timeout=20
126
  )
127
 
128
+ if step3.status_code != 200:
129
+ raise gr.Error(f"Failed to generate exercise: {step3.text}")
130
+
131
+ global firebase_current_ref
132
+ firebase_current_ref = firebase_data_ref.push({
133
+ "type": "open_question",
134
+ "input": _json,
135
+ "output": step3.json(),
136
+ "datetime": str(datetime.datetime.now()),
137
+ "like": 0,
138
+ })
139
+
140
+ return format_output(step3.json(), state['typeOfExercise'])
141
+
142
  ##################################################################
143
  # UI Layer
144
  ##################################################################
145
 
146
  def format_output(output, exercise_type):
147
+ if type_of_exercise[exercise_type] in ["Open Question", "Short Answer Question", "True or False"]:
148
+ return f"<div class='markdown-body'><h3>Question:</h3><p>{output['Assignment']}</p><h3>Reference Answer:</h3><p>{output['Solutions'][0]}</p></div>"
149
+ elif type_of_exercise[exercise_type] in ["Multiple Choice", "Single Choice"]:
150
+ return f"""<div class='markdown-body'><h3>Question:</h3><p>{output['Assignment']}</p><h3>Options:</h3><p>{
151
+ "<br/>".join(["βœ…" + x for x in output['Solutions']] + ["❌" + x for x in output['Distractors'] + output["EasilyDiscardableDistractors"]])
152
+ }</p></div>"""
153
+ elif type_of_exercise[exercise_type] in ["Debate", "Essay", "Brainstorming", "Knoledge Exposition"]:
154
+ return f"<div class='markdown-body'><h3>Assignment:</h3><p>{output['Assignment']}</p></div>"
155
+ elif type_of_exercise[exercise_type] in ["Fill in the Blanks"]:
156
+ return f"""<div class='markdown-body'><h3>Paragraph:</h3><p>{output['Plus']}</p><h3>Question:</h3><p>{output['Assignment']}</p><h3>Options:</h3><p>{
157
+ "<br/>".join(["βœ…" + x for x in output['Solutions']] + ["❌" + x for x in output['Distractors'] + output["EasilyDiscardableDistractors"]])
158
+ }</p></div>"""
159
+
160
+ return f"<div class='markdown-body'><h3>Ouput</h3><p>{output['Solutions'][0]}</p></div>"
 
 
 
 
 
 
 
161
 
162
  def on_url_change(url, state):
163
+ for key in ['topic', 'learningObjective', 'learningObjectiveList', 'material_url']:
164
+ if key in state:
165
+ del state[key]
166
+
167
  material = analyze_resource(url)
168
 
169
  topics = [topic['Topic'] for topic in material['MainTopics']]
170
 
 
 
171
  state = state | material
172
  state['material_url'] = url
173
 
174
+ # del state['topic']
175
+ # del state['learningObjective']
176
+ # del state['learningObjectiveList']
177
+
178
+ lo_component = gr.Dropdown(label="Learning Objective", choices=[], value="placeholder", interactive=False)
179
+
180
+ return [gr.Radio(label="Topic", choices=topics, interactive=True), lo_component, state]
181
 
182
  def on_topic_change(topic, old_state):
183
  old_state['topic'] = topic
 
213
  }
214
  iframe.second-row {
215
  width: 100%; /* Full width */
216
+ height: 60vh; /* Full height */
217
  border: none; /* No border */
218
  background-color: #f9f9f9; /* Light background */
219
  }
 
230
  box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* Subtle shadow for depth */
231
  max-width: 800px; /* Max width to maintain optimal line length */
232
  margin: 20px auto; /* Center align the Markdown content */
233
+ max-height: 70vh; /* Max height to prevent scrolling */
234
+ overflow-y: auto; /* Auto-scroll for overflow */
235
  }
236
 
237
  /* Headings with increased weight and spacing for clear hierarchy */
 
315
  }
316
  """
317
 
318
+ def make_visible(components, visible):
319
+ return [gr.update(visible=visible) for _ in range(components)]
320
+
321
 
322
  with gr.Blocks(title="Educational AI", css=css) as demo:
323
+ state = gr.State({"level": levels[-1], "language": "English", "correctAnswersNumber": 1, "easyDistractorsNumber": 1, "distractorsNumber": 1, "typeOfExercise": 0})
324
 
325
  with gr.Row(elem_classes=["row-content"]):
326
  with gr.Column(scale=3, elem_classes=["column-content"]):
 
327
  level_component = gr.Dropdown(label="Level", choices=levels, value=levels[-1])
328
  url_component = gr.Textbox(label="Input URL", placeholder="Enter URL here...")
329
  iframe_component = gr.HTML("<iframe class='second-row' src='' allowfullscreen></iframe>")
330
 
331
  with gr.Column(scale=3):
332
+ language_component = gr.Dropdown(languages, label="Exercise Language", value="English")
333
  topic_component = gr.Radio(label="Topic", choices=["placeholder"], interactive=False)
334
  lo_component = gr.Dropdown(label="Learning Objective", choices=[], value="placeholder", interactive=False)
335
+ question_type_component = gr.Dropdown(label="Question Type", choices=type_of_exercise, type="index", value=0)
336
 
337
+ correct_answers_component = gr.Number(value=1, minimum=1, maximum=3, step=1, label="Number of correct answers", visible=False)
338
+ easy_distractors_component = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of easy distractors", visible=False)
339
+ distractors_component = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of distractors", visible=False)
340
+
341
+ generate_btn = gr.Button("Generate Question")
342
 
343
  with gr.Column(scale=3):
 
344
  output_component = gr.HTML("<div class='markdown-body'><h3>Output</h3>Placeholder for output</div>")
345
+ with gr.Row():
346
+ like_btn = gr.Button("πŸ‘ like")
347
+ dislike_btn = gr.Button("πŸ‘Ž dislike")
348
+ gr.Button(value="πŸ“ Fill our Questionnaire", link="https://forms.gle/T8CS5CiQgPbKUdeM9", interactive=True)
349
 
350
  # on language change
351
  language_component.change(lambda x, old_state: old_state | {"language": x}, [language_component, state], [state])
 
356
  # on url change
357
  url_component.change(lambda x: gr.HTML(f"<iframe class='second-row' src='{x}' allowfullscreen></iframe>"), [url_component], [iframe_component])
358
  url_component.change(lambda x: gr.Info(f"Analyzing resource at {x}..."), [url_component], [])
359
+ url_component.change(on_url_change, [url_component, state], [topic_component, lo_component, state])
360
 
361
  # on topic change
362
  topic_component.change(lambda x: gr.Info(f"Generating learning objective for {x}..."), [topic_component], [])
 
367
 
368
  # on question type change
369
  question_type_component.change(lambda x, old_state: old_state | {"typeOfExercise": x}, [question_type_component, state], [state])
370
+ question_type_component.change(lambda x: make_visible(3, x in [type_of_exercise.index(y) for y in ["Multiple Choice", "Single Choice", "Fill in the Blanks"]]), [question_type_component], [correct_answers_component, easy_distractors_component, distractors_component])
371
+
372
+ # exercise-specific settings
373
+ correct_answers_component.change(lambda x, old_state: old_state | {"correctAnswersNumber": x}, [correct_answers_component, state], [state])
374
+ easy_distractors_component.change(lambda x, old_state: old_state | {"easyDistractorsNumber": x}, [correct_answers_component, state], [state])
375
+ distractors_component.change(lambda x, old_state: old_state | {"distractorsNumber": x}, [correct_answers_component, state], [state])
376
+
377
+ # on like/dislike
378
+ like_btn.click(like)
379
+ dislike_btn.click(dislike)
380
+
381
 
382
  # on generate question
383
  generate_btn.click(lambda: gr.Info("Generating question..."))