import logging # Ленивая загрузка LLM _generator = None def load_model(): """Ленивая загрузка модели""" global _generator if _generator is None: try: from transformers import pipeline print('Загрузка LLM модели...') _generator = pipeline('text2text-generation', model='cointegrated/rut5-base-multitask') print('LLM модель загружена') except Exception as e: print(f'Ошибка загрузки LLM: {e}') _generator = None return _generator def answer(question, context, system_prompt=None): """Генерирует ответ с помощью LLM""" generator = load_model() if not generator or not context: return fallback_answer(context) try: # Формируем контекст context_text = 'Доступные курсы:\n' for i, course in enumerate(context[:6], 1): context_text += f'{i}. {course["name"]} ({course["semester"]} семестр, {course["credits"]} кредитов)\n' context_text += f' Описание: {course["short_desc"]}\n' context_text += f' Теги: {", ".join(course["tags"])}\n\n' # Системные инструкции if system_prompt is None: system_prompt = '''Ты помощник для абитуриентов магистратуры ITMO. Отвечай только по предоставленному контексту. Если в контексте нет нужной информации — ответь: "в предоставленных данных об этом не сказано." Отвечай кратко и по делу. Не выдумывай факты и не давай общих ответов без ссылок на элементы контекста.''' # Формируем промпт prompt = f'''{system_prompt} {context_text} Вопрос: {question}''' # Генерируем ответ response = generator( prompt, max_new_tokens=180, temperature=0.3, do_sample=True )[0]['generated_text'] return response.strip() except Exception as e: print(f'Ошибка генерации LLM: {e}') return fallback_answer(context) def fallback_answer(context): """Fallback ответ без LLM""" if not context: return 'В предоставленных данных об этом не сказано.' courses = [] for item in context[:3]: courses.append(f'{item["name"]} ({item["semester"]} семестр, {item["credits"]} кредитов)') return f'Найденные курсы: {", ".join(courses)}.' def generate_recommendations(courses, profile): """Генерирует рекомендации с помощью LLM""" generator = load_model() if not generator or not courses: return fallback_recommendations(courses, profile) try: # Формируем контекст курсов courses_text = 'Доступные курсы:\n' for i, course in enumerate(courses[:7], 1): courses_text += f'{i}. {course["name"]} ({course["credits"]} кредитов)\n' courses_text += f' Сложность: {course.get("difficulty", "не указана")}, Теги: {", ".join(course["tags"])}\n' courses_text += f' Описание: {course["short_desc"]}\n\n' # Профиль студента programming_exp = profile.get('programming_experience', 2) math_level = profile.get('math_level', 2) interests = profile.get('interests', []) semester = profile.get('semester', 'не указан') prompt = f'''Ты эксперт по выбору курсов. Дай персонализированные рекомендации студенту. Профиль студента: - Опыт программирования: {programming_exp}/5 - Уровень математики: {math_level}/4 - Интересы: {", ".join(interests)} - Целевой семестр: {semester} {courses_text} Дай 5-7 лучших рекомендаций с объяснением почему они подходят. Учитывай уровень сложности и интересы. Отвечай кратко, по делу.''' response = generator( prompt, max_new_tokens=300, temperature=0.4, do_sample=True )[0]['generated_text'] return response.strip() except Exception as e: print(f'Ошибка генерации рекомендаций: {e}') return fallback_recommendations(courses, profile) def fallback_recommendations(courses, profile): """Fallback рекомендации без LLM""" if not courses: semester = profile.get('semester', 'не указан') return f'Нет курсов для {semester} семестра.' programming_exp = profile.get('programming_experience', 2) math_level = profile.get('math_level', 2) interests = profile.get('interests', []) semester = profile.get('semester', 'не указан') result = f'🎯 Рекомендации для {semester} семестра:\n\n' for i, course in enumerate(courses[:7], 1): result += f'{i}. {course["name"]} ({course["credits"]} кредитов)\n' # Объяснение почему подходит reasons = [] matching_tags = [tag for tag in interests if tag in course.get('tags', [])] if matching_tags: reasons.append(f'подходит по интересам: {", ".join(matching_tags)}') if programming_exp <= 2 and 'python' in course.get('tags', []): reasons.append('подходит для начинающих программистов') elif programming_exp >= 4 and 'dl' in course.get('tags', []): reasons.append('подходит для опытных программистов') if math_level >= 2 and 'math' in course.get('tags', []): reasons.append('требует хорошую математическую подготовку') if reasons: result += f' Почему подходит: {"; ".join(reasons)}\n' result += '\n' return result