|
|
import gradio as gr
|
|
|
import json
|
|
|
import os
|
|
|
|
|
|
|
|
|
TEST_COURSES = [
|
|
|
{
|
|
|
'id': 'ai_1_1',
|
|
|
'program_id': 'ai',
|
|
|
'semester': 1,
|
|
|
'name': 'Машинное обучение',
|
|
|
'credits': 6,
|
|
|
'hours': 108,
|
|
|
'type': 'required',
|
|
|
'tags': ['ml', 'math', 'stats'],
|
|
|
'short_desc': 'Основы машинного обучения, алгоритмы классификации и регрессии'
|
|
|
},
|
|
|
{
|
|
|
'id': 'ai_1_2',
|
|
|
'program_id': 'ai',
|
|
|
'semester': 1,
|
|
|
'name': 'Глубокое обучение',
|
|
|
'credits': 4,
|
|
|
'hours': 72,
|
|
|
'type': 'required',
|
|
|
'tags': ['dl', 'ml', 'neural'],
|
|
|
'short_desc': 'Нейронные сети, CNN, RNN, трансформеры'
|
|
|
},
|
|
|
{
|
|
|
'id': 'ai_2_1',
|
|
|
'program_id': 'ai',
|
|
|
'semester': 2,
|
|
|
'name': 'Обработка естественного языка',
|
|
|
'credits': 5,
|
|
|
'hours': 90,
|
|
|
'type': 'required',
|
|
|
'tags': ['nlp', 'dl', 'text'],
|
|
|
'short_desc': 'Методы обработки текста, токенизация, эмбеддинги'
|
|
|
},
|
|
|
{
|
|
|
'id': 'ai_product_1_1',
|
|
|
'program_id': 'ai_product',
|
|
|
'semester': 1,
|
|
|
'name': 'Продуктовая аналитика',
|
|
|
'credits': 6,
|
|
|
'hours': 108,
|
|
|
'type': 'required',
|
|
|
'tags': ['product', 'business', 'data'],
|
|
|
'short_desc': 'Анализ продуктовых метрик, A/B тестирование'
|
|
|
},
|
|
|
{
|
|
|
'id': 'ai_product_1_2',
|
|
|
'program_id': 'ai_product',
|
|
|
'semester': 1,
|
|
|
'name': 'Управление проектами',
|
|
|
'credits': 4,
|
|
|
'hours': 72,
|
|
|
'type': 'required',
|
|
|
'tags': ['pm', 'business', 'management'],
|
|
|
'short_desc': 'Методологии управления проектами, Agile, Scrum'
|
|
|
}
|
|
|
]
|
|
|
|
|
|
def is_itmo_query(message):
|
|
|
itmo_keywords = [
|
|
|
'итмо', 'магистратура', 'учебный план', 'дисциплина', 'курс',
|
|
|
'ии', 'ai', 'ai product', 'институт ии', 'программа',
|
|
|
'машинное обучение', 'глубокое обучение', 'nlp', 'компьютерное зрение'
|
|
|
]
|
|
|
message_lower = message.lower()
|
|
|
return any(keyword in message_lower for keyword in itmo_keywords)
|
|
|
|
|
|
def simple_search(query, courses):
|
|
|
query_lower = query.lower()
|
|
|
results = []
|
|
|
|
|
|
for course in courses:
|
|
|
course_text = f"{course['name']} {course['short_desc']}".lower()
|
|
|
if any(word in course_text for word in query_lower.split()):
|
|
|
results.append(course)
|
|
|
|
|
|
return results[:3]
|
|
|
|
|
|
def chat_with_bot(message, history):
|
|
|
if not message.strip():
|
|
|
return history, ''
|
|
|
|
|
|
if not is_itmo_query(message):
|
|
|
return history + [[message, '''Похоже, вопрос не относится к магистратурам ITMO и их учебным планам.
|
|
|
|
|
|
Попробуйте спросить, например:
|
|
|
• "Какие дисциплины по NLP в 1 семестре программы ИИ?"
|
|
|
• "Расскажи о программе AI Product"
|
|
|
• "Какие курсы по машинному обучению есть в программе ИИ?"
|
|
|
• "Сколько кредитов за дисциплину 'Глубокое обучение'?"''']], ''
|
|
|
|
|
|
results = simple_search(message, TEST_COURSES)
|
|
|
|
|
|
if not results:
|
|
|
response = 'К сожалению, не нашел релевантной информации в учебных планах ITMO.'
|
|
|
else:
|
|
|
response = 'Найденные курсы:\n\n'
|
|
|
for i, course in enumerate(results, 1):
|
|
|
response += f'{i}. {course["name"]} ({course["semester"]} семестр, {course["credits"]} кредитов)\n'
|
|
|
response += f' {course["short_desc"]}\n\n'
|
|
|
|
|
|
return history + [[message, response]], ''
|
|
|
|
|
|
def get_recommendations(programming_exp, math_level, interests, semester):
|
|
|
if not semester:
|
|
|
return 'Пожалуйста, укажите семестр для получения рекомендаций.'
|
|
|
|
|
|
semester = int(semester)
|
|
|
filtered_courses = [c for c in TEST_COURSES if c['semester'] == semester]
|
|
|
|
|
|
if not filtered_courses:
|
|
|
return f'К сожалению, не найдено курсов для {semester} семестра.'
|
|
|
|
|
|
|
|
|
recommendations = []
|
|
|
for course in filtered_courses[:5]:
|
|
|
why = 'Курс из учебного плана программы'
|
|
|
if interests:
|
|
|
matching_tags = [tag for tag in interests if tag in course.get('tags', [])]
|
|
|
if matching_tags:
|
|
|
why = f'Соответствует вашим интересам: {", ".join(matching_tags)}'
|
|
|
|
|
|
recommendations.append({
|
|
|
'name': course['name'],
|
|
|
'semester': course['semester'],
|
|
|
'credits': course['credits'],
|
|
|
'why': why
|
|
|
})
|
|
|
|
|
|
result = '🎯 Рекомендуемые курсы (из официальных учебных планов ITMO):\n\n'
|
|
|
for i, rec in enumerate(recommendations, 1):
|
|
|
result += f'{i}. {rec["name"]} ({rec["semester"]} семестр, {rec["credits"]} кредитов)\n'
|
|
|
result += f' {rec["why"]}\n\n'
|
|
|
|
|
|
return result
|
|
|
|
|
|
def update_data_ui():
|
|
|
return 'Данные успешно обновлены! (Тестовые данные уже загружены)'
|
|
|
|
|
|
def update_data_thread():
|
|
|
return gr.update(value='Обновление данных...', interactive=False)
|
|
|
|
|
|
with gr.Blocks(title='ITMO Магистратура - Чат-бот', theme=gr.themes.Soft()) as demo:
|
|
|
gr.Markdown('# 🤖 Чат-бот для абитуриентов магистратур ITMO')
|
|
|
gr.Markdown('Задавайте вопросы о программах ИИ и AI Product, получайте персональные рекомендации по курсам.')
|
|
|
|
|
|
with gr.Row():
|
|
|
with gr.Column(scale=2):
|
|
|
chatbot_interface = gr.ChatInterface(
|
|
|
chat_with_bot,
|
|
|
title='💬 Чат с ботом',
|
|
|
description='Спрашивайте о дисциплинах, программах, учебных планах',
|
|
|
examples=[
|
|
|
'Какие дисциплины по NLP в 1 семестре программы ИИ?',
|
|
|
'Расскажи о программе AI Product',
|
|
|
'Какие курсы по машинному обучению есть в программе ИИ?',
|
|
|
'Сколько кредитов за дисциплину "Глубокое обучение"?'
|
|
|
]
|
|
|
)
|
|
|
|
|
|
with gr.Column(scale=1):
|
|
|
gr.Markdown('### 👤 Профиль для рекомендаций')
|
|
|
|
|
|
programming_exp = gr.Slider(
|
|
|
minimum=0, maximum=5, value=2, step=1,
|
|
|
label='Опыт программирования (0-5)',
|
|
|
info='0 - нет опыта, 5 - эксперт'
|
|
|
)
|
|
|
|
|
|
math_level = gr.Slider(
|
|
|
minimum=0, maximum=4, value=2, step=1,
|
|
|
label='Уровень математики (0-4)',
|
|
|
info='0 - базовый, 4 - продвинутый'
|
|
|
)
|
|
|
|
|
|
interests = gr.CheckboxGroup(
|
|
|
choices=['ml', 'dl', 'nlp', 'cv', 'product', 'business', 'research', 'data', 'systems'],
|
|
|
value=['ml'],
|
|
|
label='Интересы',
|
|
|
info='Выберите интересующие направления'
|
|
|
)
|
|
|
|
|
|
semester = gr.Dropdown(
|
|
|
choices=['1', '2', '3', '4'],
|
|
|
label='Целевой семестр',
|
|
|
info='Для получения рекомендаций'
|
|
|
)
|
|
|
|
|
|
recommend_btn = gr.Button('🎯 Получить рекомендации', variant='primary')
|
|
|
recommendations_output = gr.Textbox(
|
|
|
label='Рекомендации',
|
|
|
lines=10,
|
|
|
interactive=False
|
|
|
)
|
|
|
|
|
|
recommend_btn.click(
|
|
|
get_recommendations,
|
|
|
inputs=[programming_exp, math_level, interests, semester],
|
|
|
outputs=recommendations_output
|
|
|
)
|
|
|
|
|
|
with gr.Row():
|
|
|
update_btn = gr.Button('🔄 Обновить данные', variant='secondary')
|
|
|
update_status = gr.Textbox(
|
|
|
label='Статус обновления',
|
|
|
interactive=False,
|
|
|
visible=False
|
|
|
)
|
|
|
|
|
|
update_btn.click(
|
|
|
update_data_thread,
|
|
|
outputs=update_status
|
|
|
).then(
|
|
|
update_data_ui,
|
|
|
outputs=update_status
|
|
|
)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
demo.launch(server_name='0.0.0.0', server_port=7860)
|
|
|
|