AI-система персонализации фитнес-программ
Персональный тренер — это дорого. AI-тренер доступен 24/7 и учитывает прогресс, восстановление, цели и ограничения. Приложения типа Freeletics, Whoop, Peloton используют ML для адаптации тренировочных планов в реальном времени на основе биометрических данных.
Адаптивный тренировочный план
import numpy as np
import pandas as pd
from dataclasses import dataclass
from typing import Optional
from anthropic import Anthropic
import json
@dataclass
class AthleteProfile:
user_id: str
age: int
sex: str
weight_kg: float
height_cm: float
fitness_level: str # beginner, intermediate, advanced
primary_goal: str # weight_loss, muscle_gain, endurance, general_fitness
available_days_per_week: int
equipment: list # ['dumbbells', 'barbell', 'pull_up_bar']
injuries: list # ['lower_back', 'knee']
vo2max: Optional[float] = None
class FitnessPlanGenerator:
"""Генерация и адаптация тренировочного плана"""
def __init__(self):
self.llm = Anthropic()
def calculate_training_zones(self, profile: AthleteProfile) -> dict:
"""Пульсовые зоны для кардио тренировок"""
# Формула Танака (точнее чем 220-age)
max_hr = 208 - 0.7 * profile.age
return {
'max_hr': int(max_hr),
'zone1_recovery': (int(max_hr * 0.50), int(max_hr * 0.60)),
'zone2_aerobic': (int(max_hr * 0.60), int(max_hr * 0.70)),
'zone3_tempo': (int(max_hr * 0.70), int(max_hr * 0.80)),
'zone4_threshold': (int(max_hr * 0.80), int(max_hr * 0.90)),
'zone5_vo2max': (int(max_hr * 0.90), int(max_hr * 1.00)),
}
def generate_weekly_plan(self, profile: AthleteProfile,
recent_performance: list[dict]) -> list[dict]:
"""Недельный тренировочный план"""
training_zones = self.calculate_training_zones(profile)
# Периодизация: 3 недели нарастающей нагрузки + 1 неделя восстановления
# Определяем текущую неделю периодизации из истории
week_in_cycle = self._get_week_in_cycle(recent_performance)
load_modifier = [0.85, 1.0, 1.15, 0.70][week_in_cycle % 4]
response = self.llm.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=700,
messages=[{
"role": "user",
"content": f"""Create a personalized weekly training plan.
Profile:
- Fitness level: {profile.fitness_level}
- Goal: {profile.primary_goal}
- Available days: {profile.available_days_per_week}
- Equipment: {profile.equipment}
- Injuries to avoid: {profile.injuries}
- Age: {profile.age}, Weight: {profile.weight_kg}kg
Current training intensity: {load_modifier:.0%} of base load
Training zones: Zone 2 aerobic = {training_zones['zone2_aerobic']} bpm
Recent performance (last 5 sessions):
{json.dumps(recent_performance[-5:], ensure_ascii=False)[:400]}
Create {profile.available_days_per_week} training sessions. Return JSON array:
[{{
"day": "Monday",
"session_type": "strength|cardio|hiit|recovery",
"duration_min": 45,
"exercises": [{{"name": "...", "sets": 3, "reps": "8-10", "rest_sec": 90}}],
"cardio_zone": "zone2",
"notes": "..."
}}]"""
}]
)
try:
return json.loads(response.content[0].text)
except Exception:
return []
def _get_week_in_cycle(self, performance: list[dict]) -> int:
if not performance:
return 0
return len(set(p.get('week_number', 0) for p in performance)) % 4
class RecoveryMonitor:
"""Мониторинг восстановления из биометрии"""
def compute_readiness_score(self, biometrics: dict) -> dict:
"""
Скор готовности к тренировке (0-100).
Данные: HRV, RHR, sleep_score, previous_day_load.
"""
score = 100.0
factors = []
# HRV (Heart Rate Variability) — главный индикатор
hrv = biometrics.get('hrv_ms')
hrv_baseline = biometrics.get('hrv_baseline_ms', 50)
if hrv and hrv_baseline:
hrv_ratio = hrv / hrv_baseline
if hrv_ratio < 0.85:
score -= 25
factors.append(f'HRV снижен ({hrv:.0f}ms vs {hrv_baseline:.0f}ms baseline)')
elif hrv_ratio > 1.15:
score += 5 # Хорошее восстановление
# Resting Heart Rate
rhr = biometrics.get('resting_hr_bpm')
rhr_baseline = biometrics.get('rhr_baseline_bpm', 60)
if rhr and rhr_baseline:
if rhr > rhr_baseline + 5:
score -= 15
factors.append(f'RHR повышен ({rhr} vs {rhr_baseline} baseline)')
# Сон
sleep_score = biometrics.get('sleep_score', 80) # 0-100
if sleep_score < 60:
score -= 20
factors.append(f'Плохой сон (скор: {sleep_score})')
elif sleep_score < 75:
score -= 10
# Нагрузка предыдущего дня
previous_load = biometrics.get('yesterday_training_load', 0) # AU (Arbitrary Units)
high_load_threshold = biometrics.get('weekly_avg_load', 300) * 0.4
if previous_load > high_load_threshold:
score -= 10
factors.append('Высокая нагрузка вчера')
score = float(np.clip(score, 0, 100))
if score > 75:
recommendation = 'Отличный день для интенсивной тренировки'
intensity_modifier = 1.0
elif score > 55:
recommendation = 'Умеренная тренировка — снизьте интенсивность на 15%'
intensity_modifier = 0.85
elif score > 35:
recommendation = 'Только лёгкое восстановительное занятие или отдых'
intensity_modifier = 0.60
else:
recommendation = 'Активный отдых или выходной'
intensity_modifier = 0.0
return {
'readiness_score': round(score),
'recommendation': recommendation,
'intensity_modifier': intensity_modifier,
'limiting_factors': factors
}
class ProgressTracker:
"""Отслеживание прогресса и корректировка плана"""
def analyze_progress(self, training_logs: pd.DataFrame,
profile: AthleteProfile,
weeks: int = 8) -> dict:
"""Анализ прогресса за период"""
recent = training_logs[
training_logs['date'] >= pd.Timestamp.now() - pd.Timedelta(weeks=weeks)
]
if recent.empty:
return {}
return {
'sessions_completed': len(recent),
'sessions_planned': weeks * profile.available_days_per_week,
'adherence_rate': len(recent) / (weeks * profile.available_days_per_week),
# Прогресс по ключевым упражнениям
'strength_progress': self._compute_strength_progress(recent),
'endurance_progress': self._compute_endurance_progress(recent),
'avg_session_duration_min': recent.get('duration_minutes', pd.Series([45])).mean(),
'total_volume_kg': recent.get('total_volume_kg', pd.Series([0])).sum(),
}
def _compute_strength_progress(self, logs: pd.DataFrame) -> dict:
"""Изменение максимальных весов в основных упражнениях"""
if 'exercise_name' not in logs.columns:
return {}
key_exercises = ['squat', 'bench_press', 'deadlift', 'overhead_press']
progress = {}
for exercise in key_exercises:
exercise_logs = logs[logs['exercise_name'] == exercise]
if len(exercise_logs) < 2:
continue
first_max = exercise_logs.nsmallest(3, 'date')['max_weight_kg'].mean()
last_max = exercise_logs.nlargest(3, 'date')['max_weight_kg'].mean()
progress[exercise] = round((last_max - first_max) / max(first_max, 1) * 100, 1)
return progress
def _compute_endurance_progress(self, logs: pd.DataFrame) -> dict:
if 'pace_min_per_km' not in logs.columns:
return {}
cardio = logs[logs['session_type'] == 'cardio']
if cardio.empty:
return {}
early = cardio.head(3)['pace_min_per_km'].mean()
recent = cardio.tail(3)['pace_min_per_km'].mean()
improvement = (early - recent) / early * 100 # Снижение темпа = улучшение
return {'pace_improvement_pct': round(improvement, 1)}
Персонализированные фитнес-планы с адаптацией на основе биометрии повышают adherence rate с 35-45% до 65-75% по данным Whoop и Oura. Ключевая метрика: не количество тренировок, а соответствие нагрузки уровню восстановления — это снижает риск травм на 30-40%.







