import gradio as gr import html import time import re # ── Словники для аналізу ────────────────────────────────────────── PARTS_KEYWORDS = { "організаційний момент": ["організаційний", "привітання", "перевірка присутніх", "готовність"], "актуалізація знань": ["актуалізація", "пригадаємо", "повторення попередньої", "що ви знаєте"], "мотивація": ["мотивація", "навіщо", "проблемне питання", "загадка", "цікавий факт", "мотив"], "вивчення нового матеріалу": ["новий матеріал", "тема уроку", "ознайомимося", "вивчення", "нова тема"], "закріплення": ["закріплення", "виконайте вправу", "завдання", "практик", "вправ"], "підсумок": ["підсумок", "що нового дізналися", "рефлексія", "висновок", "підведемо"], "домашнє завдання": ["домашнє завдання", "д/з", "вдома виконайте", "додому"], } METHODS_KEYWORDS = { "пояснення вчителя": ["пояснення", "розповідає", "розповідь", "лекція", "вчитель пояснює"], "бесіда": ["бесіда", "запитання", "запитує", "відповідають", "обговорення", "діалог"], "демонстрація": ["демонстра", "показує", "презентація", "таблиця", "схема", "малюнок", "ілюстрац"], "практична робота": ["практична", "виконують вправу", "розв'язують", "пишуть", "розв'яжіть"], "самостійна робота": ["самостійна", "індивідуально", "кожен учень", "самостійно"], "гра": ["гра", "ігровий", "вікторина", "змагання", "грають"], "групова робота": ["група", "групова", "команда", "разом", "парна робота", "в парах"], "проєктна робота": ["проєкт", "дослідження", "міні-проєкт"], "дискусія": ["дискусія", "думки", "різні точки зору", "полемік", "дебат"], } LESSON_TYPE_RULES = [ ("урок вивчення нового матеріалу", ["новий матеріал", "нова тема", "вперше", "ознайомимося"]), ("урок закріплення знань", ["закріплення", "вправи", "тренування", "відпрацювання"]), ("урок повторення та узагальнення", ["повторення", "узагальнення", "систематизація", "пригадаємо"]), ("урок контролю знань", ["контроль", "тестування", "самостійна робота", "перевірка"]), ("комбінований урок", []), ] SUBJECT_KEYWORDS = { "математика": ["число", "задач", "приклад", "рівнян", "геометр", "дріб", "додаван", "множен"], "українська мова": ["слово", "речення", "текст", "орфограф", "частини мови", "дієслово", "іменник"], "природознавство": ["природа", "рослин", "тварин", "екосистем", "географ", "клімат", "ґрунт"], "читання": ["читання", "твір", "автор", "казка", "оповідання", "вірш", "герой"], "історія": ["історія", "подія", "епоха", "держава", "культура", "суспільство"], "біологія": ["клітина", "організм", "біологія", "еволюція", "фотосинтез"], } # ── Аналіз ──────────────────────────────────────────────────────── def detect_parts(text: str) -> list[str]: t = text.lower() return [p for p, kws in PARTS_KEYWORDS.items() if any(k in t for k in kws)] or ["структуру не визначено"] def detect_methods(text: str) -> list[str]: t = text.lower() return [m for m, kws in METHODS_KEYWORDS.items() if any(k in t for k in kws)] or ["загальні методи"] def detect_lesson_type(text: str) -> str: t = text.lower() for lesson_type, kws in LESSON_TYPE_RULES[:-1]: if any(k in t for k in kws): return lesson_type has_new = any(k in t for k in ["новий матеріал", "нова тема", "вивчення"]) has_fix = any(k in t for k in ["закріплення", "вправи", "практич"]) if has_new and has_fix: return "комбінований урок" if has_new: return "урок вивчення нового матеріалу" return "комбінований урок" def detect_subject(text: str) -> str: t = text.lower() scores = {subj: sum(1 for k in kws if k in t) for subj, kws in SUBJECT_KEYWORDS.items()} best = max(scores, key=scores.get) return best if scores[best] > 0 else "не визначено" def extract_topic(text: str) -> str: """Витягує тему уроку з конспекту""" patterns = [ r"тема[:\s]+(.+?)[\n\r]", r"тема уроку[:\s]+(.+?)[\n\r]", r"урок[:\s]+(.+?)[\n\r]", ] for pattern in patterns: m = re.search(pattern, text, re.IGNORECASE) if m: return m.group(1).strip() first_line = text.strip().split("\n")[0] return first_line[:80] if first_line else "не визначено" def extract_goal(text: str) -> str: """Витягує мету уроку""" patterns = [ r"мета[:\s]+(.+?)[\n\r]", r"мета уроку[:\s]+(.+?)[\n\r]", r"завдання уроку[:\s]+(.+?)[\n\r]", ] for pattern in patterns: m = re.search(pattern, text, re.IGNORECASE) if m: return m.group(1).strip() return "не визначено" def count_activity_words(text: str) -> dict: """Підраховує показники активності учнів""" t = text.lower() return { "активність учнів": sum(t.count(k) for k in ["учні", "діти", "школярі", "вони виконують"]), "робота вчителя": sum(t.count(k) for k in ["вчитель", "педагог", "викладач"]), "взаємодія": sum(t.count(k) for k in ["разом", "обговорення", "відповідають", "запитує"]), } FORMS_KEYWORDS = { "фронтальна робота": ["фронтальна", "весь клас", "усі учні", "клас відповідає"], "індивідуальна робота": ["індивідуально", "кожен учень", "самостійно", "індивідуальна"], "парна робота": ["в парах", "парна", "сусід по парті", "разом із сусідом"], "групова робота": ["група", "групова", "команда", "по групах", "в групах"], "колективна робота": ["колективна", "спільно", "разом", "увесь клас"], } TOOLS_KEYWORDS = { "підручник": ["підручник", "с.", "сторінка", "впр.", "вправа"], "зошит": ["зошит", "записують", "пишуть у зошиті"], "дошка": ["дошка", "на дошці", "записує на дошці"], "презентація": ["презентація", "слайд", "проєктор", "екран"], "картки": ["картка", "роздатковий матеріал", "картки"], "таблиця / схема": ["таблиця", "схема", "малюнок", "ілюстрація", "діаграма"], "натуральні об'єкти":["гербарій", "модель", "макет", "реальний об'єкт", "муляж"], "відео / аудіо": ["відео", "аудіо", "запис", "прослуховування", "перегляд"], } TASKS_KEYWORDS = { "читання тексту": ["читають", "прочитайте", "читання"], "письмові вправи": ["пишуть", "запишіть", "написати", "вправа у зошиті"], "усні відповіді": ["відповідають", "розкажіть", "усна відповідь", "говорять"], "розв'язання задач": ["розв'язують", "задача", "розв'яжіть", "приклад"], "робота з підручником": ["підручник", "відкрийте", "знайдіть у підручнику"], "заповнення таблиці": ["заповніть таблицю", "заповнюють", "таблицю"], "малювання / схеми": ["намалюйте", "схема", "зарисуйте", "позначте"], "тестові завдання": ["тест", "тестові", "обери правильну відповідь"], "творчі завдання": ["придумайте", "складіть", "творче завдання", "власний приклад"], "спостереження": ["спостерігають", "розгляньте", "опишіть що бачите"], } def detect_forms(text: str) -> list[str]: t = text.lower() return [f for f, kws in FORMS_KEYWORDS.items() if any(k in t for k in kws)] or ["не визначено"] def detect_tools(text: str) -> list[str]: t = text.lower() return [tool for tool, kws in TOOLS_KEYWORDS.items() if any(k in t for k in kws)] or ["не визначено"] def detect_tasks(text: str) -> list[str]: t = text.lower() return [task for task, kws in TASKS_KEYWORDS.items() if any(k in t for k in kws)] or ["не визначено"] def build_lesson_narrative( topic: str, goal: str, lesson_type: str, subject: str, parts: list[str], methods: list[str], forms: list[str], tools: list[str], tasks: list[str], teacher: str, text: str, ) -> str: """Генерує детальний текст спостереження уроку у стилі педагогічного протоколу""" teacher_str = html.escape(teacher) if teacher.strip() else "Вчитель" topic_str = html.escape(topic) if topic != "не визначено" else "—" goal_str = html.escape(goal) if goal != "не визначено" else "—" subj_str = html.escape(subject) if subject != "не визначено" else "" t = text.lower() paragraphs = [] # ── 1. Вступна характеристика ───────────────────────────────── subj_part = f" з {subj_str}" if subj_str else "" paragraphs.append( f"{teacher_str} провів(ла) {html.escape(lesson_type)}{subj_part}. " f"Тема уроку — «{topic_str}». " f"Мета: {goal_str}." ) # ── 2. Структура уроку ──────────────────────────────────────── valid_parts = [p for p in parts if p != "структуру не визначено"] if valid_parts: parts_list = "; ".join(f"{html.escape(p)}" for p in valid_parts) paragraphs.append( f"Урок включав такі структурні етапи: {parts_list}. " + ("Усі етапи логічно пов'язані між собою та відповідають обраному типу уроку." if len(valid_parts) >= 5 else "Окремі структурні етапи у конспекті чітко не виділені — рекомендується деталізувати план.") ) else: paragraphs.append( "Структурні етапи уроку у конспекті окремо не позначені." ) # ── 3. Організаційний момент / мотивація ───────────────────── org_phrases = [] if any(k in t for k in ["організаційний", "привітання", "готовність"]): org_phrases.append( f"На початку уроку {teacher_str} організував(ла) клас: " "привітав(ла) учнів, перевірив(ла) готовність робочих місць." ) if any(k in t for k in ["мотивація", "загадка", "цікавий факт", "проблемне питання", "мотив"]): org_phrases.append( "Для мотивації навчальної діяльності було використано проблемно-ігровий прийом або " "цікаве запитання, що зацікавило учнів та налаштувало їх на роботу." ) if any(k in t for k in ["актуалізація", "пригадаємо", "повторення"]): org_phrases.append( "Актуалізація опорних знань відбувалась через усне опитування або повторення " "раніше вивченого матеріалу." ) if org_phrases: paragraphs.append(" ".join(org_phrases)) # ── 4. Методи навчання ──────────────────────────────────────── valid_methods = [m for m in methods if m != "загальні методи"] if valid_methods: m_str = ", ".join(f"{html.escape(m)}" for m in valid_methods) paragraphs.append( f"У ході уроку {teacher_str} застосовував(ла) такі методи навчання: {m_str}. " ) method_details = [] if any(k in t for k in ["пояснення", "розповідає", "розповідь"]): method_details.append( "Словесний метод — пояснення — використовувався для ознайомлення учнів " "з новим матеріалом. Вчитель чітко й доступно викладав навчальний зміст, " "ілюструючи пояснення прикладами." ) if any(k in t for k in ["бесіда", "запитання", "відповідають", "обговорення"]): method_details.append( "Бесіда застосовувалась як метод діалогічної взаємодії: " "вчитель ставив запитання, учні формулювали відповіді, " "що сприяло розвитку мовлення та критичного мислення." ) if any(k in t for k in ["демонстра", "таблиця", "схема", "презентація", "малюнок"]): method_details.append( "Наочно-демонстраційний метод реалізовувався через показ таблиць, " "схем або ілюстрацій, що забезпечувало наочність сприймання нового матеріалу." ) if any(k in t for k in ["практична", "вправу", "розв'язують", "пишуть"]): method_details.append( "Практичний метод — виконання вправ і завдань — забезпечував " "відпрацювання навичок та закріплення вивченого." ) if any(k in t for k in ["самостійна", "індивідуально", "кожен учень"]): method_details.append( "Самостійна робота сприяла формуванню вміння учнів працювати " "без безпосередньої допомоги вчителя та розвитку навчальної самостійності." ) if any(k in t for k in ["гра", "ігровий", "вікторина"]): method_details.append( "Ігровий метод підвищував мотивацію та активність учнів, " "забезпечував емоційне залучення до навчального процесу." ) if method_details: paragraphs.extend(method_details) # ── 5. Форми організації ────────────────────────────────────── valid_forms = [f for f in forms if f != "не визначено"] if valid_forms: f_str = ", ".join(f"{html.escape(f)}" for f in valid_forms) form_comment = "" if "індивідуальна робота" in valid_forms and "фронтальна робота" in valid_forms: form_comment = ( " Поєднання фронтальної та індивідуальної форм роботи " "забезпечувало як колективне засвоєння, так і особистісну перевірку знань кожного учня." ) elif "групова робота" in valid_forms: form_comment = ( " Групова форма роботи розвивала комунікативні навички " "та вміння співпрацювати в команді." ) paragraphs.append( f"Форми організації навчальної діяльності: {f_str}.{form_comment}" ) # ── 6. Засоби навчання ──────────────────────────────────────── valid_tools = [t_ for t_ in tools if t_ != "не визначено"] if valid_tools: tools_str = ", ".join(f"{html.escape(t_)}" for t_ in valid_tools) paragraphs.append( f"Засоби навчання, використані на уроці: {tools_str}. " "Добір засобів відповідав змісту уроку та віковим особливостям учнів." ) # ── 7. Завдання учнів (деталізовано) ───────────────────────── task_details = [] if any(k in t for k in ["читають", "прочитайте", "читання"]): task_details.append( "Учні читали текст (або умову задачі), що розвивало навички " "свідомого читання та розуміння навчального матеріалу." ) if any(k in t for k in ["пишуть", "запишіть", "написати", "у зошиті", "зошит"]): task_details.append( "Виконувались письмові вправи у зошитах: учні записували " "відповіді, вирази або слова відповідно до завдань вчителя." ) if any(k in t for k in ["відповідають", "розкажіть", "усна відповідь"]): task_details.append( "Учні давали усні відповіді на запитання вчителя, " "формулювали власні думки та висновки." ) if any(k in t for k in ["задача", "розв'яжіть", "розв'язують", "приклад"]): task_details.append( "Виконувалось розв'язання задач і прикладів: " "учні аналізували умову, обирали дію, записували розв'язок і відповідь." ) if any(k in t for k in ["підручник", "відкрийте", "с.", "сторінка", "впр."]): task_details.append( "Проводилась робота з підручником: виконання вправ " "за вказаними сторінками та завданнями." ) if any(k in t for k in ["тест", "тестові", "обери правильну"]): task_details.append( "Учні виконували тестові завдання для перевірки рівня " "засвоєння вивченого матеріалу." ) if any(k in t for k in ["придумайте", "складіть", "творче"]): task_details.append( "Пропонувались творчі завдання — скласти власний приклад, " "придумати продовження або варіант завдання." ) if any(k in t for k in ["таблицю", "заповніть", "схема", "намалюйте"]): task_details.append( "Учні заповнювали таблиці або схеми, що сприяло " "систематизації та структуруванню знань." ) if task_details: paragraphs.append( f"Завдання, які виконували учні на уроці:" ) paragraphs.extend(task_details) # ── 8. Рефлексія ───────────────────────────────────────────── if any(k in t for k in ["рефлексія", "підсумок", "що дізналися", "висновок"]): paragraphs.append( f"Завершальний етап уроку містив підсумок та рефлексію. " f"{teacher_str} організував(ла) обговорення результатів роботи: " "учні відповіли на запитання про те, що нового дізналися, " "що сподобалося, що було складним. " "Це сприяло усвідомленню власних навчальних досягнень." ) if any(k in t for k in ["домашнє завдання", "д/з", "вдома"]): paragraphs.append( f"{teacher_str} повідомив(ла) домашнє завдання, " "надавши необхідні інструкції щодо його виконання." ) # ── 9. Загальний висновок ───────────────────────────────────── score = len(valid_parts) + len(valid_methods) + len(valid_forms) + len(valid_tools) if score >= 10: conclusion = ( "Урок відзначається чіткою структурою, різноманітністю методів та форм роботи. " "Конспект свідчить про ретельну підготовку вчителя та методичну грамотність." ) elif score >= 5: conclusion = ( "Урок має достатньо опрацьований конспект з визначеними методами та формами роботи. " "Окремі аспекти можна деталізувати додатково." ) else: conclusion = ( "Конспект потребує детальнішого опрацювання: варто чіткіше прописати " "методи, форми роботи, засоби навчання та завдання для учнів." ) paragraphs.append(conclusion) return "".join( f'

{p}

' for p in paragraphs ) # ── HTML-компоненти ─────────────────────────────────────────────── def pill(text: str, bg: str, color: str) -> str: return (f'' f'{html.escape(text)}') def pills(items: list[str], bg: str, color: str) -> str: return "".join(pill(i, bg, color) for i in items) def card(icon: str, title: str, body: str, border: str = "#2196F3", bg: str = "#e8f4f8") -> str: return (f'
' f'
' f'{icon} {html.escape(title)}
' f'
{body}
') def activity_bar(label: str, value: int, max_val: int, color: str) -> str: pct = min(100, int(value / max(max_val, 1) * 100)) return (f'
' f'
' f'{html.escape(label)}: {value}
' f'
' f'
') # ── Валідація ───────────────────────────────────────────────────── def validate(text: str) -> tuple[bool, str]: text = text or "" if not text.strip(): return False, "⚠️ Будь ласка, введіть конспект уроку." if len(text.strip()) < 80: return False, "⚠️ Конспект задто короткий (мінімум 80 символів)." if len(text) > 20_000: return False, "⚠️ Конспект задто довгий (максимум 20 000 символів)." return True, "" # ── Головна функція ─────────────────────────────────────────────── def analyze( lesson_text: str, teacher: str, school: str, date: str, observer: str, show_recs: bool, ) -> tuple[str, str]: lesson_text = lesson_text or "" teacher = teacher or "" school = school or "" date = date or "" observer = observer or "" ok, err = validate(lesson_text) if not ok: return f'
{err}
', "" try: t0 = time.time() # Аналіз topic = extract_topic(lesson_text) goal = extract_goal(lesson_text) lesson_type = detect_lesson_type(lesson_text) subject = detect_subject(lesson_text) parts = detect_parts(lesson_text) methods = detect_methods(lesson_text) forms = detect_forms(lesson_text) tools = detect_tools(lesson_text) tasks = detect_tasks(lesson_text) activity = count_activity_words(lesson_text) elapsed = round(time.time() - t0, 3) # Narrative narrative = build_lesson_narrative( topic, goal, lesson_type, subject, parts, methods, forms, tools, tasks, teacher, lesson_text ) # Метадані meta_items = [v for v in [ f"Вчитель: {html.escape(teacher)}" if teacher else "", f"Школа: {html.escape(school)}" if school else "", f"Дата: {html.escape(date)}" if date else "", f"Спостерігач: {html.escape(observer)}" if observer else "", ] if v] meta_html = ( f'
' + "  |  ".join(meta_items) + "
" ) if meta_items else "" # Повнота структури found_count = len([p for p in parts if p != "структуру не визначено"]) total_parts = len(PARTS_KEYWORDS) completeness = round(found_count / total_parts * 100) comp_color = "#4CAF50" if completeness >= 70 else "#FF9800" if completeness >= 40 else "#f44336" comp_bar = ( f'
' f'
' f'
' f'
' f'
' f'Виявлено {found_count} з {total_parts} частин ({completeness}%)
' ) # Активність max_act = max(activity.values()) if any(activity.values()) else 1 act_html = "".join( activity_bar(k, v, max_act, c) for (k, v), c in zip(activity.items(), ["#2196F3", "#FF9800", "#4CAF50"]) ) # Рекомендації recs_html = "" if show_recs: recs = [] if "організаційний момент" not in parts: recs.append("Додайте організаційний момент на початку конспекту.") if "мотивація" not in parts: recs.append("Включіть мотиваційний етап для активізації пізнавального інтересу.") if "підсумок" not in parts: recs.append("Завершіть урок підсумком або рефлексією.") if "домашнє завдання" not in parts: recs.append("Вкажіть домашнє завдання у конспекті.") if len(methods) < 2: recs.append("Урізноманітніть методи — використайте 2–3 різні прийоми.") if forms and forms[0] == "не визначено": recs.append("Вкажіть форми організації роботи учнів (фронтальна, групова, індивідуальна).") if tools and tools[0] == "не визначено": recs.append("Опишіть засоби навчання, які використовуватимуться на уроці.") if activity["активність учнів"] < activity["робота вчителя"]: recs.append("Збільшіть частку активної роботи учнів відносно монологу вчителя.") if not recs: recs.append("Конспект відповідає основним дидактичним вимогам. Гарна робота!") li = "".join(f"
  • {html.escape(r)}
  • " for r in recs) recs_html = card( "💡", "Методичні рекомендації", f"", "#FFA000", "#fff8e1" ) result = f"""

    📋 Спостереження уроку

    {meta_html}
    📝 Загальна характеристика уроку
    {narrative}
    🏗️ Структурні частини уроку
    {pills(parts, "#bbdefb", "#0d47a1")} {comp_bar}
    🎓 Методи та прийоми навчання
    {pills(methods, "#c8e6c9", "#1b5e20")}
    👥 Форми організації роботи
    {pills(forms, "#e1bee7", "#4a148c")}
    🛠️ Засоби навчання
    {pills(tools, "#ffe0b2", "#bf360c")}
    ✏️ Завдання учнів
    {pills(tasks, "#b2ebf2", "#004d40")}
    📊 Активність у конспекті
    {act_html}
    {recs_html}
    ⏱ Аналіз виконано за {elapsed} сек. | Символів: {len(lesson_text)}
    """ return result, "✅ Аналіз завершено" except Exception as e: return ( f'
    ' f'❌ Помилка: {html.escape(str(e))}
    ', "❌ Помилка", ) # ── Сесія ───────────────────────────────────────────────────────── def save_to_history(result_html: str, history: list) -> tuple[list, str]: history = history or [] if result_html and "Спостереження уроку" in result_html: history = history + [{"n": len(history) + 1, "html": result_html}] return history, f"Збережено: {len(history)} аналіз(ів)" def render_history(history: list) -> str: history = history or [] if not history: return "

    Немає збережених аналізів.

    " return "".join( f'
    ' f'' f'Аналіз #{i["n"]}' f'
    {i["html"]}
    ' for i in history ) # ── Інтерфейс ───────────────────────────────────────────────────── EXAMPLES = [ [ "Тема: Додавання чисел у межах 10\n" "Мета: навчити учнів додавати числа; розвивати логічне мислення.\n" "Організаційний момент: привітання, перевірка готовності.\n" "Актуалізація: пригадаємо вивчені числа від 1 до 9.\n" "Мотивація: загадка про числа.\n" "Вивчення нового матеріалу: вчитель пояснює на прикладах із предметами.\n" "Закріплення: учні виконують вправи в зошиті самостійно.\n" "Підсумок: що нового дізналися сьогодні?\n" "Домашнє завдання: с. 45, впр. 3.", "Іваненко О.М.", "ЗОШ №3, 2-А клас", "03.06.2025", "Петренко В.С.", True, ], [ "Тема: Рослини нашого краю\n" "Мета: ознайомити з місцевими рослинами; виховувати любов до природи.\n" "Організаційний момент. Мотивація: демонстрація гербарію.\n" "Бесіда: які рослини знаєте? Де вони ростуть? Учні відповідають.\n" "Вивчення нового матеріалу: розповідь з таблицею та схемою.\n" "Самостійна робота: учні підписують малюнки рослин індивідуально.\n" "Підсумок уроку та рефлексія. Домашнє завдання: вдома виконайте впр. 5.", "Коваль Н.П.", "НВК №7, 3-Б клас", "03.06.2025", "Студент-практикант", True, ], ] with gr.Blocks(theme=gr.themes.Soft(), title="LessonObserver") as demo: session = gr.State([]) gr.Markdown( "# 📚 LessonObserver\n" "**Автоматичний аналіз конспекту уроку для студентів педколеджу**" ) with gr.Tabs(): with gr.Tab("🔍 Аналіз уроку"): with gr.Row(): with gr.Column(scale=2): lesson_in = gr.Textbox( label="📄 Конспект уроку", placeholder="Вставте сюди текст конспекту уроку...", lines=14, ) with gr.Column(scale=1): with gr.Accordion("ℹ️ Інформація про урок (необов'язково)", open=False): teacher_in = gr.Textbox(label="Вчитель", placeholder="Прізвище та ім'я") school_in = gr.Textbox(label="Школа / клас", placeholder="ЗОШ №5, 2-А клас") date_in = gr.Textbox(label="Дата", placeholder="03.06.2025") observer_in = gr.Textbox(label="Спостерігач", placeholder="Ваше ім'я") recs_check = gr.Checkbox(label="Показати рекомендації", value=True) btn_analyze = gr.Button("🔎 Аналізувати", variant="primary", size="lg") status_out = gr.Textbox(label="Статус", interactive=False, max_lines=1) result_out = gr.HTML() gr.Examples( examples=EXAMPLES, inputs=[lesson_in, teacher_in, school_in, date_in, observer_in, recs_check], label="📌 Приклади конспектів", ) btn_save = gr.Button("💾 Зберегти в сесію", size="sm") save_status = gr.Textbox(label="", interactive=False, max_lines=1) with gr.Tab("📂 Збережені аналізи"): btn_refresh = gr.Button("🔄 Оновити список") history_out = gr.HTML() with gr.Tab("❓ Довідка"): gr.Markdown(""" ## Як користуватися 1. Вставте текст конспекту уроку (мінімум 80 символів). 2. За бажанням заповніть поля вчителя, школи, дати, спостерігача. 3. Натисніть **«Аналізувати»**. 4. Отримайте структуроване спостереження. ## Що аналізує застосунок | Компонент | Метод | |-----------|-------| | Тема та мета уроку | Пошук за шаблоном у тексті | | Тип уроку | Аналіз ключових слів | | Навчальний предмет | Тематичні словники | | Структурні частини | Ключові слова кожного етапу | | Методи навчання | Дидактичний словник | | Активність учнів | Підрахунок згадувань | | Рекомендації | Правила дидактики | ## Обмеження - Аналіз базується на ключових словах — що детальніший конспект, то точніший результат - Не перевіряє фактичну правильність навчального матеріалу - Оптимальна довжина конспекту: 200–3000 символів """) btn_analyze.click( fn=analyze, inputs=[lesson_in, teacher_in, school_in, date_in, observer_in, recs_check], outputs=[result_out, status_out], ) btn_save.click( fn=save_to_history, inputs=[result_out, session], outputs=[session, save_status], ) btn_refresh.click( fn=render_history, inputs=[session], outputs=[history_out], ) demo.launch()