Lab6 / exam_functions.py
Denysyk's picture
Upload 5 files
5d2b004 verified
Raw History Blame Contribute Delete
6.83 kB
"""
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")