Spaces:
Runtime error
Runtime error
import datetime | |
import os | |
import json | |
import gradio as gr | |
import requests | |
import firebase_admin | |
from itertools import chain | |
from firebase_admin import db, credentials | |
def clamp(x, minimum, maximum): | |
return max(minimum, min(x, maximum)) | |
################################################################################################################################################# | |
# API calls | |
################################################################################################################################################# | |
# read secret api key | |
API_KEY = os.environ['ApiKey'] | |
FIREBASE_API_KEY = os.environ['FirebaseSecret'] | |
FIREBASE_URL = os.environ['FirebaseURL'] | |
SETUP_MODEL = os.environ['SETUP_MODEL'] | |
# creds = credentials.Certificate(json.loads(FIREBASE_API_KEY)) | |
# firebase_app = firebase_admin.initialize_app(creds, {'databaseURL': FIREBASE_URL}) | |
# firebase_data_ref = db.reference("data") | |
# firebase_current_ref = None | |
BASE_URL = "https://skapi.polyglot-edu.com/" | |
################################################################## | |
# Data Layer | |
################################################################## | |
levels = ["Primary School", "Middle School", "High School", "College", "Academy"] | |
languages = ["English", "Italian", "French", "German", "Spanish"] | |
type_of_exercise = ["Open Question", "Short Answer Question", "True or False", "Fill in the Blanks", "Single Choice", "Multiple Choice", "Debate", "Essay", "Brainstorming", "Knoledge Exposition"] | |
def generation_to_dict(experiment, skip=False): | |
info = { | |
# experiment info | |
**experiment, | |
# chosen image set info | |
"corrupted_filename": experiment["corrupted"]["name"], | |
"options": [img["name"] for img in experiment["options"]], | |
} | |
if skip: | |
info = { | |
**info, | |
# selected image info | |
"selected_image": "None", | |
"selected_algo": "None", | |
} | |
else: | |
info = { | |
**info, | |
# selected image info | |
"selected_image": experiment["options"][experiment["selected_image"]]["name"], | |
"selected_algo": experiment["options"][experiment["selected_image"]]["algo"], | |
} | |
return info | |
def generate_new_experiment(): | |
pass | |
# wanted_corruptions = ["spatter", "impulse_noise", "speckle_noise", "gaussian_noise", "pixelate", "jpeg_compression", "elastic_transform"] | |
# corruption = random.choice([f for f in list(Path(f"./images/{DATASET}").glob("*/*")) if f.is_dir() and f.name in wanted_corruptions]) | |
# image_id = random.choice(list(corruption.glob("*"))) | |
# imgs_to_sample = (NUMBER_OF_IMAGES_PER_ROW * NUMBER_OF_ROWS) // 2 | |
# corrupted_image = {"name": str(random.choice(list(image_id.glob("*corrupted*"))))} | |
# sdedit_images = [ | |
# {"name": str(img), "algo": "SDEdit"} | |
# for img in random.sample(list((image_id / "sde").glob(f"*")), imgs_to_sample) | |
# ] | |
# odedit_images = [ | |
# {"name": str(img), "algo": "ODEdit"} | |
# for img in random.sample(list((image_id / "ode").glob(f"*")), imgs_to_sample) | |
# ] | |
# total_images = sdedit_images + odedit_images | |
# random.shuffle(total_images) | |
# return Experiment( | |
# DATASET, | |
# corruption.name, | |
# image_id.name, | |
# corrupted_image, | |
# total_images, | |
# ) | |
def save(experiment, corrupted_component, *img_components, mode): | |
if mode == "save" and (experiment is None or experiment["selected_image"] is None): | |
gr.Warning("You must select an image before submitting") | |
return [experiment, corrupted_component, *img_components] | |
if mode == "skip": | |
experiment["selected_image"] = None | |
dict_to_save = { | |
**generation_to_dict(experiment, skip=(mode=="skip")), | |
"timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
} | |
# firebase_data_ref.push(dict_to_save) | |
print("=====================") | |
print(dict_to_save) | |
print("=====================") | |
gr.Info("Your choice has been saved to Firebase") | |
return next() | |
def analyze_resource(url): | |
response = requests.post( | |
BASE_URL + "Analyser/analyseMaterial", | |
headers={"ApiKey": API_KEY, "SetupModel": str(SETUP_MODEL)}, | |
json={ | |
"material": url | |
}, | |
timeout=20 | |
) | |
if response.status_code != 200: | |
raise gr.Error(f"Failed to analyze resource: {response.text}") | |
return response.json() | |
def generate_learning_objective(topic, context, level): | |
response = requests.post( | |
BASE_URL + "LOGenerator/generatelearningobjective", | |
headers={"ApiKey": API_KEY, "SetupModel": str(SETUP_MODEL)}, | |
json={ | |
"topic": topic, | |
"context": context, | |
"level": levels.index(level) | |
}, | |
timeout=20 | |
) | |
print(topic, context, level) | |
if response.status_code != 200: | |
raise gr.Error(f"Failed to generate learning objective: {response.text}") | |
return response.json() | |
def generate_exercise(state): | |
def find_key(d, item): | |
for key, value in d.items(): | |
if item in value: | |
return key | |
return None | |
step3 = requests.post( | |
BASE_URL + "Exercises/GenerateExercise", | |
headers={"ApiKey": API_KEY, "SetupModel": str(SETUP_MODEL)}, | |
json={ | |
# filled in with the data from the previous steps | |
"macroSubject": state['MacroSubject'], | |
"title": state['Title'], | |
"level": state['level'], | |
"learningObjective": state['learningObjective'], | |
"bloomLevel": find_key(state["learningObjectiveList"], state['learningObjective']), | |
"language": state['Language'], | |
"material": state['material_url'], | |
"assignmentType": [topic['Type'] for topic in state['MainTopics'] if topic['Topic'] == state['topic']][0], | |
"topic": state['topic'], | |
"temperature": 0, | |
# to be filled in manually | |
"correctAnswersNumber": 0, | |
"distractorsNumber": 0, | |
"easilyDiscardableDistractorsNumber": 0, | |
"typeOfExercise": 0 | |
}, | |
timeout=20 | |
) | |
################################################################## | |
# UI Layer | |
################################################################## | |
def format_output(output, exercise_type): | |
if type_of_exercise[exercise_type] in ["Open Question", "Short Answer Question"]: | |
return f"<div class='markdown-body'><h3>{output['Assignment']}</h3><p>{output['Solutions'][0]}</p></div>" | |
return f"<div class='markdown-body'><h3>Ouput (unknown type)</h3><p>{output['Solutions'][0]}</p></div>" | |
def reset_UI(): | |
return [ | |
{"level": levels[-1], "language": "English"}, | |
] | |
def next(): | |
new_experiment = generate_new_experiment() | |
new_img_components = [ | |
gr.Image(value=img["name"], label=f"{i}", elem_id="unsel", show_label=False, show_download_button=False, show_share_button=False, interactive=False) | |
for i, img in enumerate(new_experiment["options"]) | |
] | |
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) | |
return [new_experiment, new_corrupted_component, *new_img_components] | |
def on_url_change(url, state): | |
material = analyze_resource(url) | |
topics = [topic['Topic'] for topic in material['MainTopics']] | |
components = reset_UI() | |
state = components[0] | |
state = state | material | |
state['material_url'] = url | |
return [gr.Radio(label="Topic", choices=topics, interactive=True), state] | |
def on_topic_change(topic, old_state): | |
old_state['topic'] = topic | |
learning_objective = generate_learning_objective(topic, f"A {old_state['level']} class", old_state["level"]) | |
old_state['learningObjectiveList'] = learning_objective | |
possible_objectives = list(chain.from_iterable(learning_objective.values())) | |
return [gr.Dropdown(label="Learning Objective", choices=possible_objectives, value=possible_objectives[0], interactive=True), old_state] | |
css = """ | |
body, html { | |
margin: 0; | |
height: 100%; /* Full height */ | |
width: 100%; /* Full width */ | |
overflow: hidden; /* Prevent scrolling */ | |
} | |
.interface, .block-container { | |
display: flex; | |
flex-direction: column; | |
height: 100%; /* Full height */ | |
width: 100%; /* Full width */ | |
} | |
.row-content { | |
height: 90vh; /* Full height */ | |
} | |
.column-content { | |
display: flex; | |
flex-direction: column; | |
flex: 1; /* Flexibly take up available space */ | |
height: 100%; /* Full height */ | |
} | |
iframe.second-row { | |
width: 100%; /* Full width */ | |
height: 50vh; /* Full height */ | |
border: none; /* No border */ | |
background-color: #f9f9f9; /* Light background */ | |
} | |
/* Base style for Markdown content */ | |
.markdown-body { | |
font-family: 'Helvetica Neue', Arial, sans-serif; /* Clean and modern font */ | |
line-height: 1.6; /* Ample line height for readability */ | |
font-size: 16px; /* Standard font size for readability */ | |
color: #333; /* Dark grey color for text for less strain */ | |
background-color: #f9f9f9; /* Light background to reduce glare */ | |
padding: 20px; /* Padding around text */ | |
border-radius: 8px; /* Slightly rounded corners for a softer look */ | |
box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* Subtle shadow for depth */ | |
max-width: 800px; /* Max width to maintain optimal line length */ | |
margin: 20px auto; /* Center align the Markdown content */ | |
} | |
/* Headings with increased weight and spacing for clear hierarchy */ | |
.markdown-body h1, | |
.markdown-body h2, | |
.markdown-body h3, | |
.markdown-body h4, | |
.markdown-body h5, | |
.markdown-body h6 { | |
color: #2a2a2a; /* Slightly darker than the text color */ | |
margin-top: 24px; | |
margin-bottom: 16px; | |
font-weight: bold; | |
} | |
.markdown-body h1 { | |
font-size: 2em; /* Larger size for main titles */ | |
} | |
.markdown-body h2 { | |
font-size: 1.5em; | |
} | |
.markdown-body h3 { | |
font-size: 1.17em; | |
} | |
/* Paragraphs with bottom margin for better separation */ | |
.markdown-body p { | |
margin-bottom: 16px; | |
} | |
/* Links with a subtle color to stand out */ | |
.markdown-body a { | |
color: #0656b5; | |
text-decoration: none; /* No underline */ | |
} | |
.markdown-body a:hover, | |
.markdown-body a:focus { | |
text-decoration: underline; /* Underline on hover/focus for visibility */ | |
} | |
/* Lists styled with padding and margin for clarity */ | |
.markdown-body ul, | |
.markdown-body ol { | |
padding-left: 20px; | |
margin-top: 0; | |
margin-bottom: 16px; | |
} | |
.markdown-body li { | |
margin-bottom: 8px; /* Space between list items */ | |
} | |
/* Blockquotes with a left border and padding for emphasis */ | |
.markdown-body blockquote { | |
padding: 10px 20px; | |
margin: 0; | |
border-left: 5px solid #ccc; /* Subtle grey line to indicate quotes */ | |
background-color: #f0f0f0; /* Very light background for contrast */ | |
font-style: italic; | |
} | |
/* Code styling for inline and blocks */ | |
.markdown-body code { | |
font-family: monospace; | |
background-color: #eee; /* Light grey background */ | |
padding: 2px 4px; | |
border-radius: 3px; /* Rounded corners for code blocks */ | |
font-size: 90%; | |
} | |
.markdown-body pre { | |
background-color: #f4f4f4; /* Slightly different background for distinction */ | |
border: 1px solid #ddd; /* Border for definition */ | |
padding: 10px; /* Padding inside code blocks */ | |
overflow: auto; /* Auto-scroll for overflow */ | |
line-height: 1.45; | |
border-radius: 5px; | |
} | |
""" | |
with gr.Blocks(title="Educational AI", css=css) as demo: | |
state = gr.State({"level": levels[-1], "language": "English"}) | |
with gr.Row(elem_classes=["row-content"]): | |
with gr.Column(scale=3, elem_classes=["column-content"]): | |
language_component = gr.Dropdown(languages, label="Exercise Language", value="English") | |
level_component = gr.Dropdown(label="Level", choices=levels, value=levels[-1]) | |
url_component = gr.Textbox(label="Input URL", placeholder="Enter URL here...") | |
iframe_component = gr.HTML("<iframe class='second-row' src='' allowfullscreen></iframe>") | |
with gr.Column(scale=3): | |
topic_component = gr.Radio(label="Topic", choices=["placeholder"], interactive=False) | |
lo_component = gr.Dropdown(label="Learning Objective", choices=[], value="placeholder", interactive=False) | |
question_type_component = gr.Dropdown(label="Question Type", choices=type_of_exercise, type="index") | |
correct_answers_component = gr.Number(value=1, minimum=1, maximum=3, step=1, label="Number of correct answers", interactive=False) | |
easy_distractors_component = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of easy distractors", interactive=False) | |
distractors_component = gr.Number(value=1, minimum=0, maximum=8, step=1, label="Number of distractors", interactive=False) | |
with gr.Column(scale=3): | |
generate_btn = gr.Button("Generate Question") | |
output_component = gr.HTML("<div class='markdown-body'><h3>Output</h3>Placeholder for output</div>") | |
# on language change | |
language_component.change(lambda x, old_state: old_state | {"language": x}, [language_component, state], [state]) | |
# on level change | |
level_component.change(lambda x, old_state: old_state | {"level": x}, [level_component, state], [state]) | |
# on url change | |
url_component.change(lambda x: gr.HTML(f"<iframe class='second-row' src='{x}' allowfullscreen></iframe>"), [url_component], [iframe_component]) | |
url_component.change(lambda x: gr.Info(f"Analyzing resource at {x}..."), [url_component], []) | |
url_component.change(on_url_change, [url_component, state], [topic_component, state]) | |
# on topic change | |
topic_component.change(lambda x: gr.Info(f"Generating learning objective for {x}..."), [topic_component], []) | |
topic_component.change(on_topic_change, [topic_component, state], [lo_component, state]) | |
# on lo change | |
lo_component.change(lambda x, old_state: old_state | {"learningObjective": x}, [lo_component, state], [state]) | |
# on question type change | |
question_type_component.change(lambda x, old_state: old_state | {"typeOfExercise": x}, [question_type_component, state], [state]) | |
# on generate question | |
generate_btn.click(lambda: gr.Info("Generating question...")) | |
generate_btn.click(generate_exercise, [state], [output_component]) | |
demo.launch(show_api=False) |