tommymarto commited on
Commit
9ae9be9
·
1 Parent(s): d83481f

Upload 3 files

Browse files
Files changed (3) hide show
  1. README.md +2 -2
  2. demo.py +294 -0
  3. requirements.txt +105 -0
README.md CHANGED
@@ -4,8 +4,8 @@ emoji: 🌖
4
  colorFrom: blue
5
  colorTo: purple
6
  sdk: gradio
7
- sdk_version: 4.1.1
8
- app_file: app.py
9
  pinned: false
10
  license: mit
11
  ---
 
4
  colorFrom: blue
5
  colorTo: purple
6
  sdk: gradio
7
+ sdk_version: 4.0.2
8
+ app_file: demo.py
9
  pinned: false
10
  license: mit
11
  ---
demo.py ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import requests
4
+
5
+ def clamp(x, minimum, maximum):
6
+ return max(minimum, min(x, maximum))
7
+
8
+ #################################################################################################################################################
9
+ # API calls
10
+ #################################################################################################################################################
11
+
12
+ # read secret api key
13
+ API_KEY = os.getenv('ApiKey')
14
+
15
+ base_url = "https://skapi.polyglot-edu.com/"
16
+ levels = ["Pre K", "Primary", "Middle School", "High School", "Academic"]
17
+
18
+ def get_level_mapping(level):
19
+ return {
20
+ "Academic": 0,
21
+ "Pre K": 1,
22
+ "Primary": 2,
23
+ "Middle School": 3,
24
+ "High School": 4,
25
+ }[level]
26
+
27
+ def generate_fill_gaps(original_text, level, number_of_words, number_of_gaps, number_of_distractors, temperature):
28
+ """
29
+ Generate a fill-gaps question from a given text.
30
+
31
+
32
+ Parameters
33
+ ----------
34
+ original_text : str
35
+ The original text from which to generate the fill-gaps question.
36
+ number_of_words : int
37
+ The number of words of the generated text.
38
+ number_of_gaps : int
39
+ The number of gaps to generate.
40
+ number_of_distractors : int
41
+ The number of distractors to generate for each gap.
42
+ temperature : float
43
+ The temperature for the generation.
44
+
45
+ Returns
46
+ -------
47
+ str
48
+ The fill-gaps question.
49
+ """
50
+
51
+ match number_of_words:
52
+ case "≈ 150 Words":
53
+ number_of_words = 150
54
+ case "≈ 250 Words":
55
+ number_of_words = 250
56
+ case "≈ 350 Words":
57
+ number_of_words = 350
58
+
59
+ response = requests.post(
60
+ base_url + "FillTheGaps/generateexercise",
61
+ headers={
62
+ "ApiKey": API_KEY
63
+ },
64
+ json={
65
+ "text": original_text,
66
+ "level": get_level_mapping(level),
67
+ "n_o_w": int(number_of_words),
68
+ "n_o_g": int(number_of_gaps),
69
+ "n_o_d": int(number_of_distractors),
70
+ "temperature": int(temperature) * 0.2
71
+ },
72
+ timeout=20
73
+ )
74
+
75
+ if response.status_code == 200:
76
+ return response.text
77
+ raise Exception(f"API call failed with status code {response.status_code} and message {response.text}")
78
+
79
+ def generate_open_question(original_text, level, temperature):
80
+ """
81
+ Generate an open question from a given text.
82
+
83
+
84
+ Parameters
85
+ ----------
86
+ original_text : str
87
+ The original text from which to generate the open question.
88
+ temperature : float
89
+ The temperature for the generation.
90
+
91
+ Returns
92
+ -------
93
+ str
94
+ The open question.
95
+ """
96
+
97
+ response = requests.post(
98
+ base_url + "QuestionExercise/generateexercise",
99
+ headers={
100
+ "ApiKey": API_KEY
101
+ },
102
+ json={
103
+ "text": original_text,
104
+ "level": get_level_mapping(level),
105
+ "temperature": int(temperature) * 0.2
106
+ },
107
+ timeout=20
108
+ )
109
+
110
+ if response.status_code == 200:
111
+ return response.text
112
+ raise Exception(f"API call failed with status code {response.status_code} and message {response.text}")
113
+
114
+ def generate_multiplechoice(original_text, level, number_of_options, number_of_easy_distractors, number_of_distractors, temperature):
115
+ """
116
+ Generate a multiple-choice question from a given text.
117
+
118
+
119
+ Parameters
120
+ ----------
121
+ original_text : str
122
+ The original text from which to generate the multiple-choice question.
123
+ number_of_options : int
124
+ The number of options to generate.
125
+ number_of_easy_distractors : int
126
+ The number of easy distractors to generate for each option.
127
+ number_of_distractors : int
128
+ The number of distractors to generate for each option.
129
+ temperature : float
130
+ The temperature for the generation.
131
+
132
+ Returns
133
+ -------
134
+ str
135
+ The multiple-choice question.
136
+ """
137
+
138
+ response = requests.post(
139
+ base_url + "QuizExercise/generateexercise",
140
+ headers={
141
+ "ApiKey": API_KEY
142
+ },
143
+ json={
144
+ "text": original_text,
145
+ "type": True,
146
+ "level": get_level_mapping(level),
147
+ "n_o_d": int(number_of_distractors),
148
+ "nedd": int(number_of_easy_distractors),
149
+ "temperature": int(temperature) * 0.2
150
+ },
151
+ timeout=20
152
+ )
153
+
154
+ if response.status_code == 200:
155
+ return response.text
156
+ raise Exception(f"API call failed with status code {response.status_code} and message {response.text}")
157
+
158
+ #################################################################################################################################################
159
+ # Interface building
160
+ #################################################################################################################################################
161
+
162
+ flag_link = "https://www.google.com"
163
+ comment_link = "https://www.google.com"
164
+
165
+
166
+ def build_fill_gaps_interface():
167
+ """
168
+ Build the fill-gaps interface.
169
+ """
170
+ with gr.Blocks(title="Fill-gaps") as demo:
171
+ with gr.Row():
172
+ with gr.Column(scale=5):
173
+ input_field = gr.TextArea(lines=10, max_lines=10, label="Input text (can be a text or a url)")
174
+ submit_btn = gr.Button(value="Submit")
175
+ with gr.Column(scale=4):
176
+ output_text_length = gr.Radio(["≈ 150 Words", "≈ 250 Words", "≈ 350 Words"], label="Output text length", value="≈ 150 Words")
177
+ level = gr.Radio(levels, label="Level", value="Primary")
178
+ with gr.Row():
179
+ blanks = gr.Number(value=5, minimum=4, maximum=8, step=1, label="Number of blanks")
180
+ distractors = gr.Number(value=5, minimum=4, maximum=8, step=1, label="Number of distractors")
181
+ temperature = gr.Checkbox(value=False, label="Increase creativity (decreases preciseness)")
182
+
183
+ def update_numeric(output_text_length, blanks, distractors):
184
+ if output_text_length == "≈ 150 Words":
185
+ min_, max_ = 4, 8
186
+ elif output_text_length == "≈ 250 Words":
187
+ min_, max_ = 6, 10
188
+ elif output_text_length == "≈ 350 Words":
189
+ min_, max_ = 8, 12
190
+
191
+ return (
192
+ gr.Number(value=clamp(blanks, min_, max_), minimum=min_, maximum=max_, label="Number of blanks"),
193
+ gr.Number(value=clamp(distractors, 0, blanks), minimum=0, maximum=blanks, label="Number of distractors")
194
+ )
195
+
196
+ def update_blanks(blanks, distractors):
197
+ return gr.Number(value=clamp(distractors, 0, blanks), minimum=0, maximum=blanks, label="Number of distractors")
198
+
199
+ blanks.change(update_blanks, [blanks, distractors], [distractors])
200
+ output_text_length.change(update_numeric, [output_text_length, blanks, distractors], [blanks, distractors])
201
+
202
+ with gr.Row():
203
+ output = gr.TextArea(placeholder="Generated text", label="Output")
204
+ with gr.Row() as button_row:
205
+ upvote_btn = gr.Button(value="👍 Upvote")
206
+ downvote_btn = gr.Button(value="👎 Downvote")
207
+ comment_btn = gr.Button(value="💬 Comment", link=comment_link)
208
+ flag_btn = gr.Button(value="⚠️ Flag", link=flag_link)
209
+
210
+ submit_btn.click(generate_fill_gaps, [input_field, level, output_text_length, blanks, distractors, temperature], [output])
211
+
212
+ return demo
213
+
214
+ def build_multiplechoice_interface():
215
+ """
216
+ Build the open question interface.
217
+ """
218
+ with gr.Blocks(title="Open Question") as demo:
219
+ with gr.Row():
220
+ with gr.Column(scale=5):
221
+ input_field = gr.TextArea(lines=10, max_lines=10, label="Input text (can be a text or a url)")
222
+ submit_btn = gr.Button(value="Submit")
223
+ with gr.Column(scale=4):
224
+ level = gr.Radio(levels, label="Level", value="Primary")
225
+ with gr.Row():
226
+ options = gr.Number(value=4, minimum=2, maximum=8, step=1, label="Number of blanks", interactive=False)
227
+ easy_distractors = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of easy distractors")
228
+ distractors = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of distractors")
229
+ temperature = gr.Checkbox(value=False, label="Increase creativity (decreases preciseness)")
230
+
231
+ def update_options(options, easy_distractors, distractors):
232
+ distractors = clamp(distractors, 0, options)
233
+ easy_distractors = clamp(easy_distractors, 0, distractors)
234
+
235
+ return (
236
+ gr.Number(value=easy_distractors, minimum=0, maximum=distractors, label="Number of easy distractors"),
237
+ gr.Number(value=distractors, minimum=0, maximum=options, label="Number of distractors")
238
+ )
239
+
240
+ def update_distractors(easy_distractors, distractors):
241
+ easy_distractors = clamp(easy_distractors, 0, distractors)
242
+
243
+ return gr.Number(value=easy_distractors, minimum=0, maximum=distractors, label="Number of easy distractors")
244
+
245
+ options.change(update_options, [options, easy_distractors, distractors], [easy_distractors, distractors])
246
+ distractors.change(update_distractors, [easy_distractors, distractors], [easy_distractors])
247
+
248
+ with gr.Row():
249
+ output = gr.TextArea(placeholder="Generated text", label="Output")
250
+ with gr.Row() as button_row:
251
+ upvote_btn = gr.Button(value="👍 Upvote")
252
+ downvote_btn = gr.Button(value="👎 Downvote")
253
+ comment_btn = gr.Button(value="💬 Comment", link=comment_link)
254
+ flag_btn = gr.Button(value="⚠️ Flag", link=flag_link)
255
+
256
+ submit_btn.click(generate_multiplechoice, [input_field, level, options, easy_distractors, distractors, temperature], [output])
257
+
258
+ return demo
259
+
260
+ def build_open_question_interface():
261
+ """
262
+ Build the multiple-choice interface.
263
+ """
264
+ with gr.Blocks(title="Multiple choice") as demo:
265
+ with gr.Row():
266
+ with gr.Column(scale=5):
267
+ input_field = gr.TextArea(lines=10, max_lines=10, label="Input text (can be a text or a url)")
268
+ submit_btn = gr.Button(value="Submit")
269
+ with gr.Column(scale=4):
270
+ level = gr.Radio(levels, label="Level", value="Primary")
271
+ with gr.Row():
272
+ pass
273
+ temperature = gr.Checkbox(value=False, label="Increase creativity (decreases preciseness)")
274
+ with gr.Row():
275
+ output = gr.TextArea(placeholder="Generated text", label="Output")
276
+ with gr.Row() as button_row:
277
+ upvote_btn = gr.Button(value="👍 Upvote")
278
+ downvote_btn = gr.Button(value="👎 Downvote")
279
+ comment_btn = gr.Button(value="💬 Comment", link=comment_link)
280
+ flag_btn = gr.Button(value="⚠️ Flag", link=flag_link)
281
+
282
+ submit_btn.click(generate_open_question, [input_field, level, temperature], [output])
283
+
284
+ return demo
285
+
286
+ def build_demo():
287
+ return gr.TabbedInterface(
288
+ [build_fill_gaps_interface(), build_open_question_interface(), build_multiplechoice_interface()],
289
+ ["Fill-gaps", "Open question", "Multiple-choice"],
290
+ title="Education AI"
291
+ )
292
+
293
+ if __name__ == "__main__":
294
+ build_demo().launch(share=False)
requirements.txt ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==22.1.0
2
+ altair==5.0.1
3
+ annotated-types==0.6.0
4
+ anyio==3.7.1
5
+ asttokens==2.1.0
6
+ attrs==23.1.0
7
+ backcall==0.2.0
8
+ Bottleneck==1.3.5
9
+ Brotli==1.0.9
10
+ certifi==2023.7.22
11
+ cffi==1.15.1
12
+ charset-normalizer==2.0.4
13
+ click==8.1.7
14
+ colorama==0.4.6
15
+ contourpy==1.0.5
16
+ cryptography==41.0.3
17
+ cycler==0.11.0
18
+ debugpy==1.6.3
19
+ decorator==5.1.1
20
+ entrypoints==0.4
21
+ exceptiongroup==1.0.4
22
+ executing==1.2.0
23
+ fastapi==0.103.2
24
+ ffmpy==0.3.0
25
+ filelock==3.9.0
26
+ fonttools==4.25.0
27
+ fsspec==2023.9.2
28
+ gradio==4.0.2
29
+ gradio_client==0.7.0
30
+ h11==0.12.0
31
+ h2==4.0.0
32
+ hpack==4.0.0
33
+ httpcore==0.15.0
34
+ httpx==0.23.0
35
+ huggingface-hub==0.17.3
36
+ hyperframe==6.0.1
37
+ idna==3.4
38
+ importlib-resources==6.1.0
39
+ ipykernel==6.17.1
40
+ ipython==8.6.0
41
+ jedi==0.18.1
42
+ Jinja2==3.1.2
43
+ jsonschema==4.17.3
44
+ jupyter_client==7.4.4
45
+ jupyter_core==5.0.0
46
+ kiwisolver==1.4.4
47
+ markdown-it-py==2.2.0
48
+ MarkupSafe==2.1.1
49
+ matplotlib
50
+ matplotlib-inline==0.1.6
51
+ mdurl==0.1.0
52
+ mkl-fft==1.3.8
53
+ mkl-random==1.2.4
54
+ mkl-service==2.4.0
55
+ munkres==1.1.4
56
+ nest-asyncio==1.5.6
57
+ numexpr==2.8.7
58
+ numpy==1.26.0
59
+ orjson==3.8.8
60
+ packaging==21.3
61
+ pandas==2.1.1
62
+ parso==0.8.3
63
+ pickleshare==0.7.5
64
+ Pillow==10.0.1
65
+ platformdirs==2.5.3
66
+ prompt-toolkit==3.0.32
67
+ psutil==5.9.4
68
+ pure-eval==0.2.2
69
+ pycparser==2.21
70
+ pydantic==2.4.2
71
+ pydantic_core==2.10.1
72
+ pydub==0.25.1
73
+ Pygments==2.13.0
74
+ pyOpenSSL==23.2.0
75
+ pyparsing==3.0.9
76
+ pyrsistent==0.18.0
77
+ PySocks==1.7.1
78
+ python-dateutil==2.8.2
79
+ python-multipart==0.0.6
80
+ pytz==2023.3.post1
81
+ pywin32==305
82
+ PyYAML==6.0.1
83
+ pyzmq==24.0.1
84
+ requests==2.31.0
85
+ rfc3986==1.4.0
86
+ rich==13.3.5
87
+ semantic-version==2.8.5
88
+ shellingham==1.5.0
89
+ six==1.16.0
90
+ sniffio==1.2.0
91
+ stack-data==0.6.0
92
+ starlette==0.27.0
93
+ tomlkit==0.12.0
94
+ toolz==0.12.0
95
+ tornado==6.2
96
+ tqdm==4.65.0
97
+ traitlets==5.5.0
98
+ typer==0.9.0
99
+ typing_extensions==4.7.1
100
+ tzdata==2023c
101
+ urllib3==1.26.18
102
+ uvicorn==0.20.0
103
+ wcwidth==0.2.5
104
+ websockets==10.4
105
+ win-inet-pton==1.1.0