Розробка AI-системи персоналізації освітньої траєкторії
Студент записався на курс з машинного навчання, але замість Python отримує просунутий Reinforcement Learning. Знайомо? Платформи викидають контент за рейтингом або популярністю, не перевіряючи готовність. Результат — відсів 40% на другому тижні та втрачена мотивація. За даними A/B-тестів на платформах з 5000+ студентів, персоналізований підхід дозволяє утримувати до 80% учнів на другому тижні.
Ми вирішуємо цю проблему за допомогою AI-системи, яка будує граф залежностей навчальних модулів, передбачає оптимальний порядок та розподіляє навантаження по тижнях. Персоналізований шлях скорочує середній час до першої компетенції на 30-40% — за даними A/B-тестів на платформах з 5000+ студентів. Економія на кожному завершеному курсі студентом становить в середньому $1500 для освітнього закладу.
Чому важлива персоналізація навчального шляху?
Традиційні рекомендаційні системи (як у Netflix) оптимізують клікабельність — студент отримує «цікавий» модуль, але без бази провалюється. Наш підхід враховує педагогічну послідовність: не можна рекомендувати advanced-модуль без пройдених пререквізитів. Інакше вироблення неправильних нейронних зв'язків та втрата часу. Саме тому AI-освітня система повинна включати формалізацію залежностей у вигляді графа знань.
Як AI-система персоналізації освітньої траєкторії вирішує проблему дроблення контенту?
Ми будуємо орієнтований граф (DAG), де кожне ребро prerequisite → module означає «вивчи A перед B». Це дозволяє системі завжди пропонувати актуальні модулі, що відповідають поточному рівню студента. В результаті completion rate лінійного плану 55% перетворюється на 78% при персоналізованому підході — різниця в 1.4 рази.
import networkx as nx
import numpy as np
import pandas as pd
from sklearn.ensemble import GradientBoostingClassifier
class KnowledgeGraph:
"""Граф залежностей навчальних модулів"""
def __init__(self):
self.graph = nx.DiGraph()
def add_module(self, module_id: str, metadata: dict):
self.graph.add_node(module_id, **metadata)
def add_prerequisite(self, module_id: str, prerequisite_id: str):
"""prerequisite → module (потрібно вивчити prerequisite перед module)"""
self.graph.add_edge(prerequisite_id, module_id)
def get_unlocked_modules(self, completed_modules: set[str]) -> list[str]:
"""Модулі, доступні після проходження completed"""
unlocked = []
for node in self.graph.nodes():
if node in completed_modules:
continue
predecessors = set(self.graph.predecessors(node))
if predecessors.issubset(completed_modules):
unlocked.append(node)
return unlocked
def get_shortest_path_to_goal(self, start_modules: set[str],
goal_module: str) -> list[str]:
"""Мінімальний шлях до цілі через граф залежностей"""
# Віртуальний стартовий вузол
self.graph.add_node('__start__')
for m in start_modules:
self.graph.add_edge('__start__', m)
try:
path = nx.shortest_path(self.graph, '__start__', goal_module)
return [p for p in path if p != '__start__']
except nx.NetworkXNoPath:
return []
finally:
self.graph.remove_node('__start__')
class LearningPathRecommender:
"""Персоналізований навчальний маршрут"""
def __init__(self, knowledge_graph: KnowledgeGraph):
self.kg = knowledge_graph
self.completion_predictor = GradientBoostingClassifier(
n_estimators=100, random_state=42
)
def recommend_path(self, student: dict,
goal: str,
max_modules: int = 10) -> list[dict]:
"""
Рекомендація навчального шляху до цілі.
Враховує: завершені модулі, швидкість навчання, уподобання формату.
"""
completed = set(student.get('completed_modules', []))
unlocked = self.kg.get_unlocked_modules(completed)
# Фільтруємо лише модулі на шляху до цілі
path_modules = self.kg.get_shortest_path_to_goal(completed, goal)
relevant = [m for m in unlocked if m in path_modules]
if not relevant:
relevant = unlocked[:max_modules]
# Скоринг кожного модуля
scored = []
for module_id in relevant[:20]: # Обмежуємо перебір
module = self.kg.graph.nodes[module_id]
score = self._score_module(module, student)
scored.append({
'module_id': module_id,
'title': module.get('title', ''),
'type': module.get('type', 'video'),
'duration_min': module.get('duration_min', 30),
'difficulty': module.get('difficulty', 3),
'score': score,
'reason': self._explain_score(module, student, score)
})
scored.sort(key=lambda x: -x['score'])
return scored[:max_modules]
def _score_module(self, module: dict, student: dict) -> float:
"""Скоринг: релевантність + формат + складність"""
# Складність відносно рівня студента
student_level = student.get('avg_score', 0.6)
module_difficulty = module.get('difficulty', 3) / 5 # 0-1
difficulty_fit = 1.0 - abs(student_level - 0.7 - (module_difficulty - 0.5) * 0.4)
# Відповідність уподобанням формату
preferred_types = student.get('preferred_content_types', ['video'])
format_score = 1.2 if module.get('type') in preferred_types else 0.8
# Популярність (соціальний доказ)
completion_rate = module.get('completion_rate', 0.5)
# Оцінка цінності з урахуванням кар'єрної цілі
goal_relevance = module.get('goal_tags', {}).get(student.get('career_goal', ''), 0.5)
return difficulty_fit * 0.3 + format_score * 0.2 + completion_rate * 0.2 + goal_relevance * 0.3
def _explain_score(self, module: dict, student: dict, score: float) -> str:
reasons = []
if module.get('completion_rate', 0) > 0.8:
reasons.append(f"{module['completion_rate']:.0%} студентів завершили")
if module.get('type') in student.get('preferred_content_types', []):
reasons.append(f"Ваш улюблений формат: {module['type']}")
if not reasons:
reasons.append("Рекомендовано на основі прогресу")
return '; '.join(reasons)
class StudyScheduler:
"""Планувальник навчального розкладу"""
def create_schedule(self, path: list[dict],
available_hours_per_week: float,
deadline_weeks: int = None) -> pd.DataFrame:
"""Розподіл модулів по тижнях"""
total_hours = sum(m['duration_min'] / 60 for m in path)
if deadline_weeks:
required_hours_per_week = total_hours / deadline_weeks
if required_hours_per_week > available_hours_per_week * 1.2:
# Нереалістичний план — попереджаємо
return pd.DataFrame({'warning': [
f'Для досягнення цілі до дедлайну потрібно {required_hours_per_week:.1f} год/тижд, '
f'у вас лише {available_hours_per_week} год/тижд'
]})
schedule = []
current_week = 1
week_hours = 0
for module in path:
module_hours = module['duration_min'] / 60
if week_hours + module_hours > available_hours_per_week and week_hours > 0:
current_week += 1
week_hours = 0
schedule.append({
'week': current_week,
'module_id': module['module_id'],
'title': module['title'],
'duration_hours': round(module_hours, 1)
})
week_hours += module_hours
return pd.DataFrame(schedule)
Що входить в роботу під ключ?
| Етап | Тривалість | Результат |
|---|---|---|
| Аналіз контенту та цілей | 1-2 дні | Структурований список модулів, метаданих, пререквізитів |
| Побудова графа залежностей | 2-3 дні | Knowledge Graph з 300+ модулями, верифікований викладачами |
| Навчання ML-моделі скорингу | 3-5 днів | Gradient Boosting model з точністю передбачення completion rate >85% |
| Інтеграція через REST API | 4-7 днів | Документація, тестовий стенд, ендпоінти для отримання персонального шляху |
| Пілотне тестування | 3-5 днів | A/B-тест на 500 студентах, звіт за метриками (time-to-competency, retention) |
Деталі пілотного тестування
Ми проводимо A/B-тест на групі з 500 студентів: 250 отримують лінійний план, 250 — персоналізований. Вимірюємо time-to-competency, completion rate та середній бал. За результатами донавчаємо модель scorer для підвищення точності. Зазвичай вже на першій ітерації персоналізований маршрут показує покращення completion rate в 1.4 рази.Як ми гарантуємо результат?
За більш ніж 7 років реалізації EdTech-проектів ми виробили процес, який виключає провальні впровадження. Наші інженери сертифіковані з NLP та MLOps. Перед стартом ми проводимо аудит даних — якщо вони непридатні, попередимо та запропонуємо альтернативу.
Приклад з практики: Клієнт — онлайн-університет з 200 курсами. Після впровадження системи персоналізації середній час отримання сертифіката скоротився з 8 до 5 тижнів (навантаження залишилося незмінним — 10 год/тижд). Completion rate зріс з 55% до 78%. Економія — кожен додатковий завершений курс приніс університету $300.
Порівняння: лінійний план vs персоналізований маршрут
| Метрика | Лінійний курс (A) | Персоналізований (B) | Відмінність B від A |
|---|---|---|---|
| Time-to-competency | 8 тижнів | 5 тижнів | −37% |
| Completion rate | 55% | 78% | +42% (в 1.4 рази) |
| Пропуск непотрібних модулів | 30% | 5% | −83% |
Етапи впровадження
- Discovery-сесія: аудит поточної навчальної програми, виявлення цілей студентів, збір історичних логів.
- Побудова графа знань: разом з вашими методистами формалізуємо залежності та теги.
- Розробка та калібрування ML-моделі: налаштовуємо scorer під ваші дані, валідуємо на відкладеній вибірці.
- Інтеграція: віддаємо API, пишемо мікросервіс (FastAPI + Redis), консультуємо фронтенд-команду.
- Пілот та ітерація: запускаємо на групі 200-500 студентів, збираємо метрики, донавчаємо.
- Продакшн та підтримка: передаємо код, документацію, навчаємо вашу команду.
Що входить в deliverables?
- Повний код репозиторію (ML-модель, API, конфіги).
- Docker-образи для розгортання.
- Документація: архітектура, інструкція з оновлення графа, посібник адміністратора.
- Доступ до дашборду метрик (Grafana) з Real-time моніторингом.
- 3 місяці техпідтримки та гарантія баг-фіксів.
Вартість та терміни
Терміни — від 2 до 4 тижнів залежно від обсягу контенту та складності інтеграції. Вартість розраховується індивідуально після аудиту: оцінюємо кількість модулів, необхідну точність моделі, глибину кастомізації UI. Для швидкої оцінки вашого сценарію просто опишіть платформу та проблеми. Ми проаналізуємо та запропонуємо оптимальну архітектуру — безкоштовно та без зобов'язань. Замовте дзвінок або напишіть на пошту.







