TestGen / app.py
vladyslav
Added testing data for Gemini 2.0 Flash and Claude 3.7 Sonnet
ec98f81
raw
history blame
15.8 kB
import json
import os
import random
import gradio as gr
from dotenv import load_dotenv
from constants import MODELS, MODELS_PATH, BOOKS, CLASSES, STUDENTS, MODEL_NAME_TO_CHOICE
from utils import save_results, get_test_by_student_class_book
load_dotenv()
if os.getenv("ENV_TYPE") == "dev":
MODELS["Test"] = "test"
MODELS_PATH["Test"] = "test"
BOOKS["Test"] = "test.json"
MODEL_NAME_TO_CHOICE["test"] = "Test"
questions_data = []
current_question_index = 0
answers_log = [] # Log for saving answers
feedback_questions = ""
def get_question():
global questions_data, current_question_index
question = questions_data[current_question_index]
question_text = f"### Питання {current_question_index + 1}/{len(questions_data)}:\n#### {question['question']}"
answers = [answer['answer'] for answer in question['answers']]
random.shuffle(answers)
return question_text, answers
def load_questions(model, book, student_name, class_name):
global questions_data, current_question_index
current_question_index = 0
answers_log.clear()
if not model or not book or student_name is None or class_name is None:
return "# Будь ласка, заповніть усі поля!", []
model_path = MODELS_PATH[model]
book_filename = BOOKS[book]
file_path = os.path.join("questions", model_path, book_filename)
if not os.path.exists(file_path):
return f"Файл за шляхом {file_path} не знайдено.", []
with open(file_path, "r", encoding="utf-8") as file:
questions_data = json.load(file)
if questions_data:
return get_question()
else:
return "У файлі немає питань.", []
def get_next_question(selected_answer):
global current_question_index, answers_log, feedback_questions
if not selected_answer:
question_text, answers = get_question()
return (
question_text, # question_radio
gr.update(choices=answers, value=None, interactive=True, visible=True), # answer_radio
gr.update(visible=True), # next_button
gr.update(visible=False), # feedback_input
gr.update(visible=False), # submit_feedback_button
gr.update(visible=False), # rating_text
gr.update(visible=False), # question_correct
gr.update(visible=False), # answers_correct
gr.update(visible=False), # interesting_question
gr.update(visible=False, value=""), # feedback_questions_output
)
# Writing answer in log
answers_log.append({
"selected": selected_answer,
"isCorrect": any(answer['answer'] == selected_answer and answer['isCorrect'] for answer in
questions_data[current_question_index]['answers'])
})
# Move to the next question
current_question_index += 1
if current_question_index < len(questions_data):
question_text, answers = get_question()
return (
question_text, # question_radio
gr.update(choices=answers, value=None, interactive=True, visible=True), # answer_radio
gr.update(visible=True), # next_button
gr.update(visible=False), # feedback_input
gr.update(visible=False), # submit_feedback_button
gr.update(visible=False), # rating_text
gr.update(visible=False), # question_correct
gr.update(visible=False), # answers_correct
gr.update(visible=False), # interesting_question
gr.update(visible=False, value=""), # feedback_questions_output
)
else:
# All questions are completed — ask for feedback
question_text = "#### Дякуємо за участь у тесті!\n#### Нижче можете переглянути ваші та правильні відповіді\n#### Залиште, будь ласка, відгук про тест в кінці сторінки.\n---"
feedback_questions = prepare_questions_for_feedback(questions_data, answers_log)
return (
question_text, # question_radio
gr.update(visible=False, value=None), # answer_radio
gr.update(visible=False), # next_button
gr.update(visible=True), # feedback_input
gr.update(visible=True), # submit_feedback_button
gr.update(visible=True), # rating_text
gr.update(visible=True), # question_correct
gr.update(visible=True), # answers_correct
gr.update(visible=True), # interesting_question
gr.update(visible=True, value=feedback_questions), # feedback_questions_output
)
def summarize_results(student_name,
class_name,
model,
book,
feedback,
question_correct,
answers_correct,
interesting_question):
global questions_data, answers_log, feedback_questions
questions = []
if question_correct is None or answers_correct is None or interesting_question is None:
return (
"### Залиште відгук про тест!", # question_output
gr.update(visible=True), # feedback_input
gr.update(visible=True), # submit_feedback_button
gr.update(visible=True), # question_correct
gr.update(visible=True), # answers_correct
gr.update(visible=True), # interesting_question
gr.update(visible=True), # rating_text
gr.update(visible=True, value=feedback_questions), # feedback_questions_output
gr.update(visible=True), # feedback_not_provided
)
for question, answer in zip(questions_data, answers_log):
questions.append({
"question": question,
"answer": answer
})
correct_answers_count = sum(1 for answer in answers_log if answer['isCorrect'])
total_questions = len(questions_data)
grade_12 = (correct_answers_count / total_questions) * 12
save_results(
student_name,
class_name,
MODELS[model],
book,
questions,
feedback,
question_correct,
answers_correct,
interesting_question,
grade_12,
correct_answers_count,
)
summary = (
f"#### Тест для моделі {model} закінчено!\n\n"
f"#### Ви відповіли правильно на {correct_answers_count} з {total_questions} питань.\n\n"
f"#### Оцінка за 12-бальною шкалою: {grade_12:.2f}.\n\n"
)
return (
summary, # question_output
gr.update(visible=False, value=""), # feedback_input
gr.update(visible=False), # submit_feedback_button
gr.update(visible=False, value=None), # question_correct
gr.update(visible=False, value=None), # answers_correct
gr.update(visible=False, value=None), # interesting_question
gr.update(visible=False), # rating_text
gr.update(visible=False, value=""), # feedback_questions_output
gr.update(visible=False), # feedback_not_provided
)
def prepare_questions_for_feedback(questions, answer_log):
feedback = []
for i, question in enumerate(questions):
question_text = f"#### Питання: {question['question']}"
quote = f"#### Цитата: *{question['textPart']}*"
user_answer = answer_log[i]['selected']
answers_text = "\n".join(
[
f"- {'**(Правильна)**' if ans['isCorrect'] else ''} {'**(Обрана)**' if ans['answer'] == user_answer else ''} {ans['answer']}"
for ans in question['answers']
]
)
feedback.append(f"{question_text}\n{quote}\n#### Відповіді:\n{answers_text}\n---")
return "\n".join(feedback)
def update_students(class_name):
print('update_students')
students = STUDENTS.get(class_name, [])
return (
gr.update(choices=students, value=None, visible=True), # student_name_input
gr.update(choices=[], value=None, visible=False), # book_radio
gr.update(choices=[], value=None, visible=False), # model_radio
)
def handle_student_name_change(student_name):
print('handle_student_name_change')
if not student_name:
return (
gr.update(choices=[], value=None, visible=False), # book_radio
gr.update(choices=[], value=None, visible=False), # model_radio
)
return (
gr.update(choices=list(BOOKS.keys()), value=None, visible=True), # book_radio
gr.update(choices=[], value=None, visible=False), # model_radio
)
def filter_models(student_name, class_name, book):
print('filter_models')
if not book:
return gr.update(choices=[], value=None, visible=False)
tests = get_test_by_student_class_book(student_name, class_name, book)
available_models = list(MODELS.values())
for test in tests:
if test.get("model") in available_models:
available_models.remove(test.get("model"))
print("Available models (before update):", available_models)
if not available_models:
return gr.update(choices=[], label="Немає доступних моделей", value=None, visible=True)
models_list = []
for model in list(available_models):
models_list.append(MODEL_NAME_TO_CHOICE.get(model))
return gr.update(choices=models_list, value=None, visible=True)
with gr.Blocks() as demo:
with gr.Column():
gr.Markdown("## Оберіть модель та книгу, щоб завантажити питання")
class_name_input = gr.Dropdown(choices=CLASSES, label="Ваш клас", value=None)
student_name_input = gr.Dropdown(label="Ваше ім'я", value=None, visible=False)
book_radio = gr.Radio([], label="Оберіть книгу", interactive=True, value=None, visible=False)
model_radio = gr.Radio([], label="Оберіть модель", interactive=True, value=None, visible=False)
load_button = gr.Button("Завантажити питання")
question_output = gr.Markdown(label="Питання")
answer_radio = gr.Radio([], label="Варіанти відповіді", interactive=True, visible=False)
next_button = gr.Button("Наступне питання", visible=False)
feedback_questions_output = gr.Markdown(label="Пройдені питання", value="Nothing", visible=False)
rating_text = gr.Markdown(
"### Шкала оцінювання:\n\n#### -2 — дуже погано\n\n#### -1 — погано\n\n#### 0 — задовільно\n\n#### 1 — добре\n\n#### 2 — відмінно",
visible=False)
feedback_not_provided = gr.Markdown("# Заповніть поля відгуку та залишіть оцінку!", visible=False)
question_correct_radio = gr.Radio([-2, -1, 0, 1, 2], label="Чи коректно поставлені запитання?", visible=False,
interactive=True)
answers_correct_radio = gr.Radio([-2, -1, 0, 1, 2], label="Чи коректно поставлені варіанти відповідей?",
visible=False, interactive=True)
interesting_question_radio = gr.Radio([-2, -1, 0, 1, 2], label="Чи цікаві були запитання?", visible=False,
interactive=True)
feedback_input = gr.Textbox(label="Будь-який коментар про тест (за бажанням)", visible=False)
submit_feedback_button = gr.Button("Завершити тест", visible=False)
class_name_input.change(
update_students,
inputs=[
class_name_input,
],
outputs=[
student_name_input,
book_radio,
model_radio,
]
)
student_name_input.change(
handle_student_name_change,
inputs=[
student_name_input,
],
outputs=[
book_radio,
model_radio,
]
)
book_radio.change(
filter_models,
inputs=[
student_name_input,
class_name_input,
book_radio,
],
outputs=[
model_radio,
]
)
def update_question(model, book, student_name, class_name):
question, answers = load_questions(model, book, student_name, class_name)
is_field_filled = len(answers) > 0
return (
question, # question_output
gr.update(choices=answers, interactive=True, visible=is_field_filled), # answer_radio
gr.update(visible=is_field_filled), # next_button
gr.update(visible=False, value=""), # feedback_input
gr.update(visible=False), # submit_feedback_button
gr.update(visible=False), # rating_text
gr.update(visible=False, value=None), # question_correct
gr.update(visible=False, value=None), # answers_correct
gr.update(visible=False, value=None), # interesting_question
gr.update(visible=False, value=""), # feedback_questions_output
gr.update(visible=False), # feedback_not_provided
)
load_button.click(
update_question,
inputs=[
model_radio,
book_radio,
student_name_input,
class_name_input,
],
outputs=[
question_output,
answer_radio,
next_button,
feedback_input,
submit_feedback_button,
rating_text,
question_correct_radio,
answers_correct_radio,
interesting_question_radio,
feedback_questions_output,
feedback_not_provided,
]
)
next_button.click(
get_next_question,
inputs=[answer_radio],
outputs=[
question_output,
answer_radio,
next_button,
feedback_input,
submit_feedback_button,
rating_text,
question_correct_radio,
answers_correct_radio,
interesting_question_radio,
feedback_questions_output,
]
)
submit_feedback_button.click(
summarize_results,
inputs=[
student_name_input,
class_name_input,
model_radio,
book_radio,
feedback_input,
question_correct_radio,
answers_correct_radio,
interesting_question_radio,
],
outputs=[
question_output,
feedback_input,
submit_feedback_button,
question_correct_radio,
answers_correct_radio,
interesting_question_radio,
rating_text,
feedback_questions_output,
feedback_not_provided,
]
)
if __name__ == "__main__":
demo.launch()