File size: 6,826 Bytes
5d2b004 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | """
Exam backend functions for AI Examiner Agent.
"""
import json
import random
import os
from datetime import datetime
from typing import TypedDict, Literal
TOPICS = [
"Tokenization and text preprocessing",
"Word embeddings (Word2Vec, GloVe, FastText)",
"Recurrent neural networks (RNN, LSTM, GRU)",
"Attention mechanism and Transformers",
"BERT and pre-trained language models",
"Named Entity Recognition (NER)",
"Sentiment analysis",
"Machine translation",
"Text classification",
"Language model evaluation metrics (BLEU, ROUGE, Perplexity)",
]
STUDENTS = [
{"name": "Stanislav Androshchuk", "email": "Stanislav.Androshchuk.mKNSSh.2025@lpnu.ua"},
{"name": "Oleksandr Babilia", "email": "Oleksandr.Babilia.mKNSSh.2025@lpnu.ua"},
{"name": "Vitalii Bahrynets", "email": "Vitalii.Bahrynets.mKNSSh.2025@lpnu.ua"},
{"name": "Dmytro Betsa", "email": "Dmytro.Betsa.mKNSSh.2025@lpnu.ua"},
{"name": "Kateryna Bilyk", "email": "Kateryna.Bilyk.mKNSSh.2025@lpnu.ua"},
{"name": "Iryna Boiko", "email": "Iryna.Boiko.mKNSSh.2025@lpnu.ua"},
{"name": "Ihor Boklach", "email": "Ihor.Boklach.mKNSSh.2025@lpnu.ua"},
{"name": "Bohdan Boretskyi", "email": "Bohdan.Boretskyi.mKNSSh.2025@lpnu.ua"},
{"name": "Yaroslav Borys", "email": "Yaroslav.Borys.mKNSSh.2025@lpnu.ua"},
{"name": "Denys Brativnyk", "email": "Denys.Brativnyk.mKNSSh.2025@lpnu.ua"},
{"name": "Oleksandr Vlasiuk", "email": "Oleksandr.Vlasiuk.mKNSSh.2025@lpnu.ua"},
{"name": "Oleksandr Voznyi", "email": "Oleksandr.Voznyi.mKNSSh.2025@lpnu.ua"},
{"name": "Khrystyna Dolynska", "email": "Khrystyna.Dolynska.mKNSSh.2025@lpnu.ua"},
{"name": "Viktor Zharkivskyi", "email": "Viktor.Zharkivskyi.mKNSSh.2025@lpnu.ua"},
{"name": "Olena Kalenchuk", "email": "Olena.Kalenchuk.mKNSSh.2025@lpnu.ua"},
{"name": "Dmytro Kostinskyi", "email": "Dmytro.Kostinskyi.mKNSSh.2025@lpnu.ua"},
{"name": "Anastasiia Kudybovska", "email": "Anastasiia.Kudybovska.mKNSSh.2025@lpnu.ua"},
{"name": "Vladyslav Kuchynskyi", "email": "Vladyslav.Kuchynskyi.mKNSSh.2025@lpnu.ua"},
{"name": "Olena Litovska", "email": "Olena.Litovska.mKNSSh.2025@lpnu.ua"},
{"name": "Oleh Lozovyi", "email": "Oleh.Lozovyi.mKNSSh.2025@lpnu.ua"},
{"name": "Roman Maior", "email": "Roman.Maior.mKNSSh.2025@lpnu.ua"},
{"name": "Yevhen Makarenko", "email": "Yevhen.Makarenko.mKNSSh.2025@lpnu.ua"},
{"name": "Serhii Matsyshyn", "email": "Serhii.Matsyshyn.mKNSSh.2025@lpnu.ua"},
{"name": "Maksym Myna", "email": "Maksym.Myna.mKNSSh.2025@lpnu.ua"},
{"name": "Artem Mikanov", "email": "Artem.Mikanov.mKNSSh.2025@lpnu.ua"},
{"name": "Vitalii Mil", "email": "Vitalii.Mil.mKNSSh.2025@lpnu.ua"},
{"name": "Vladyslav Miniailo", "email": "Vladyslav.Miniailo.mKNSSh.2025@lpnu.ua"},
{"name": "Vladyslav Moiseienko", "email": "Vladyslav.Moiseienko.mKNSSh.2025@lpnu.ua"},
{"name": "Tymofii Nasobko", "email": "Tymofii.Nasobko.mKNSSh.2025@lpnu.ua"},
{"name": "Arsenii Ohar", "email": "Arsenii.Ohar.mKNSSh.2025@lpnu.ua"},
{"name": "Marta Oliinyk", "email": "Marta.Oliinyk.mKNSSh.2025@lpnu.ua"},
{"name": "Oleksii Oliinyk", "email": "Oleksii.Oliinyk.mKNSSh.2025@lpnu.ua"},
{"name": "Roman Omelchuk", "email": "Roman.Omelchuk.mKNSSh.2025@lpnu.ua"},
{"name": "Maksym Orlianskyi", "email": "Maksym.Orlianskyi.mKNSSh.2025@lpnu.ua"},
{"name": "Alina Pavliv", "email": "Alina.Pavliv.mKNSSh.2025@lpnu.ua"},
{"name": "Andrii Pytel", "email": "Andrii.Pytel.mKNSSh.2025@lpnu.ua"},
{"name": "Oleksii Postovyi", "email": "Oleksii.Postovyi.mKNSSh.2025@lpnu.ua"},
{"name": "Myroslav Pronyshyn", "email": "Myroslav.Pronyshyn.mKNSSh.2025@lpnu.ua"},
{"name": "Yurii Pukhta", "email": "Yurii.Pukhta.mKNSSh.2025@lpnu.ua"},
{"name": "Denys Ratushniak", "email": "Denys.Ratushniak.mKNSSh.2025@lpnu.ua"},
{"name": "Nazar Savitskyi", "email": "Nazar.Savitskyi.mKNSSh.2025@lpnu.ua"},
{"name": "Oleksandr Siryk", "email": "Oleksandr.Siryk.mKNSSh.2025@lpnu.ua"},
{"name": "Petro Slobodian", "email": "Petro.Slobodian.mKNSSh.2025@lpnu.ua"},
{"name": "Artem Somar", "email": "Artem.Somar.mKNSSh.2025@lpnu.ua"},
{"name": "Vladyslav Spivakov", "email": "Vladyslav.Spivakov.mKNSSh.2025@lpnu.ua"},
{"name": "Pavlo Stetsiuk", "email": "Pavlo.Stetsiuk.mKNSSh.2025@lpnu.ua"},
{"name": "Vladyslav Taraban", "email": "Vladyslav.Taraban.mKNSSh.2025@lpnu.ua"},
{"name": "Andrii Tarasov", "email": "Andrii.Tarasov.mKNSSh.2025@lpnu.ua"},
{"name": "Illia Feloniuk", "email": "Illia.Feloniuk.mKNSSh.2025@lpnu.ua"},
{"name": "Sviatoslav Shainoha", "email": "Sviatoslav.Shainoha.mKNSSh.2025@lpnu.ua"},
{"name": "Sviatoslav Shylkov", "email": "Sviatoslav.Shylkov.mKNSSh.2025@lpnu.ua"},
{"name": "Vitalii Yuzvyn", "email": "Vitalii.Yuzvyn.mKNSSh.2025@lpnu.ua"},
{"name": "Vladyslav Yakymchuk", "email": "Vladyslav.Yakymchuk.mKNSSh.2025@lpnu.ua"},
# demo
{"name": "Test", "email": "test@test.com"},
]
DB_FILE = "exam_db.json"
def _load_db() -> dict:
if os.path.exists(DB_FILE):
with open(DB_FILE, "r", encoding="utf-8") as f:
return json.load(f)
return {"exams": []}
def _save_db(db: dict) -> None:
with open(DB_FILE, "w", encoding="utf-8") as f:
json.dump(db, f, ensure_ascii=False, indent=2)
def start_exam(email: str, name: str) -> list[str]:
student = next(
(s for s in STUDENTS if s["email"].lower() == email.strip().lower()),
None,
)
if student is None:
raise ValueError(
f"Student with email '{email}' not found. Please check your email address."
)
topics = random.sample(TOPICS, k=random.randint(2, 3))
db = _load_db()
db["exams"].append({
"email": email,
"name": name,
"started_at": datetime.now().isoformat(),
"topics": topics,
"score": None,
"finished_at": None,
})
_save_db(db)
print(f"[DB] Exam started for {name} <{email}>. Topics: {topics}")
return topics
_topic_queue: list[str] = []
def set_topic_queue(topics: list[str]) -> None:
global _topic_queue
_topic_queue = list(topics)
def get_next_topic() -> str:
if _topic_queue:
return _topic_queue.pop(0)
return ""
class Message(TypedDict):
role: Literal["system", "user", "tool_call"]
content: str
datetime: str
def end_exam(email: str, score: float, history: list[Message]) -> None:
db = _load_db()
for exam in reversed(db["exams"]):
if exam["email"].lower() == email.lower() and exam["score"] is None:
exam["score"] = score
exam["finished_at"] = datetime.now().isoformat()
exam["history"] = history
break
_save_db(db)
print(f"[DB] Exam finished for {email}. Score: {score}/10") |