|
|
import gradio as gr
|
|
|
from knowledge_base import KnowledgeBase
|
|
|
|
|
|
|
|
|
kb = KnowledgeBase()
|
|
|
|
|
|
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.get('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, kb.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'
|
|
|
if course.get('short_desc'):
|
|
|
response += f' {course["short_desc"]}\n'
|
|
|
response += '\n'
|
|
|
|
|
|
return history + [[message, response]], ''
|
|
|
|
|
|
def get_recommendations(programming_exp, math_level, interests, semester, skills):
|
|
|
if not semester:
|
|
|
return 'Пожалуйста, укажите семестр для получения рекомендаций.'
|
|
|
|
|
|
try:
|
|
|
semester = int(semester)
|
|
|
except ValueError:
|
|
|
return 'Пожалуйста, выберите корректный семестр.'
|
|
|
|
|
|
filtered_courses = kb.get_courses_by_semester(semester)
|
|
|
|
|
|
if not filtered_courses:
|
|
|
return f'К сожалению, не найдено курсов для {semester} семестра.'
|
|
|
|
|
|
|
|
|
recommendations = []
|
|
|
for course in filtered_courses[:5]:
|
|
|
score = 0
|
|
|
why_reasons = []
|
|
|
|
|
|
|
|
|
all_interests = interests + skills
|
|
|
matching_tags = [tag for tag in all_interests if tag in course.get('tags', [])]
|
|
|
if matching_tags:
|
|
|
score += 2
|
|
|
why_reasons.append(f'соответствует вашим интересам: {", ".join(matching_tags)}')
|
|
|
|
|
|
|
|
|
if programming_exp >= 3 and any(tag in course.get('tags', []) for tag in ['ml', 'dl', 'systems']):
|
|
|
score += 1
|
|
|
why_reasons.append('подходит для вашего уровня программирования')
|
|
|
|
|
|
|
|
|
if math_level >= 3 and any(tag in course.get('tags', []) for tag in ['math', 'stats', 'dl']):
|
|
|
score += 1
|
|
|
why_reasons.append('соответствует вашему уровню математики')
|
|
|
|
|
|
if score > 0:
|
|
|
recommendations.append({
|
|
|
'name': course['name'],
|
|
|
'credits': course['credits'],
|
|
|
'why': '; '.join(why_reasons) if why_reasons else 'курс из учебного плана программы'
|
|
|
})
|
|
|
|
|
|
if not recommendations:
|
|
|
|
|
|
for course in filtered_courses[:3]:
|
|
|
recommendations.append({
|
|
|
'name': course['name'],
|
|
|
'credits': course['credits'],
|
|
|
'why': 'курс из учебного плана программы'
|
|
|
})
|
|
|
|
|
|
result = f'🎯 Рекомендуемые курсы для {semester} семестра:\n\n'
|
|
|
for i, rec in enumerate(recommendations, 1):
|
|
|
result += f'{i}. {rec["name"]} ({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('### 👤 Профиль для рекомендаций')
|
|
|
|
|
|
with gr.Row():
|
|
|
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 - продвинутый'
|
|
|
)
|
|
|
|
|
|
gr.Markdown('**Интересы:**')
|
|
|
interests = gr.CheckboxGroup(
|
|
|
choices=['ml', 'dl', 'nlp', 'cv', 'product', 'business', 'research', 'data', 'systems'],
|
|
|
value=['ml'],
|
|
|
label='Области интересов',
|
|
|
info='Выберите интересующие направления'
|
|
|
)
|
|
|
|
|
|
gr.Markdown('**Навыки:**')
|
|
|
skills = gr.CheckboxGroup(
|
|
|
choices=['python', 'java', 'sql', 'git', 'docker', 'aws', 'tensorflow', 'pytorch', 'scikit-learn'],
|
|
|
value=['python'],
|
|
|
label='Технические навыки',
|
|
|
info='Выберите имеющиеся навыки'
|
|
|
)
|
|
|
|
|
|
semester = gr.Dropdown(
|
|
|
choices=['1', '2', '3', '4'],
|
|
|
label='Целевой семестр',
|
|
|
info='Для получения рекомендаций'
|
|
|
)
|
|
|
|
|
|
recommend_btn = gr.Button('🎯 Получить рекомендации', variant='primary')
|
|
|
recommendations_output = gr.Textbox(
|
|
|
label='Рекомендации',
|
|
|
lines=12,
|
|
|
interactive=False
|
|
|
)
|
|
|
|
|
|
recommend_btn.click(
|
|
|
get_recommendations,
|
|
|
inputs=[programming_exp, math_level, interests, semester, skills],
|
|
|
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)
|
|
|
|