כושר מותאם אישית באמצעות AI: אימונים אדפטיביים המבוססים על ביומטריה

תוכניות כושר סטנדרטיות מתעלמות ממצבו האמיתי של הגוף, מה שמוביל לרמות ולתחלואה. אנחנו בונים מערכות AI שמתאימות אימונים לביומטריה של המשתמש—HRV, דופק ושינה. הצוות שלנו מספק פרויקט מפתח, ומבטיח פתרון אמין עם תמיכה מתמשכת.

תחומי פיתוח AI

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1365
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

תוכניות כושר מותאמות אישית ב-AI: אימונים אדפטיביים המבוססים על נתונים ביומטריים

אפליקציות כושר סטנדרטיות מציעות תוכניות סטטיות שאינן מגיבות למצב הפיזיולוגי בפועל של המשתמש. התוצאה: רמות התקדמות קבועות, אימון יתר ופציעות. אנו בונים מערכות AI שמתאימות את העומס בהתבסס על נתונים ביומטריים: HRV, דופק, איכות שינה והיסטוריית אימונים. הפתרונות שלנו מעלים את שיעורי ההיענות מ-35–45% ל-65–75% — שיפור של פי 1.7. הסיכון לפציעות יורד ב-30–40% (Medicine & Science in Sports & Exercise). תוכניות מותאמות אישית מעלות את ערך הלקוח לאורך זמן (LTV) ב-25–30% ומפחיתות נטישה ב-15–20%. אנו צוות של מהנדסי AI/ML עם 7 שנות ניסיון בפיזיולוגיה של ספורט, עם למעלה מ-15 פרויקטים שהושלמו בהתאמה אישית של אימונים. העריכו את אפשרות היישום — צרו קשר לבדיקה מקדימה.

מדוע התאמה אישית ב-AI עולה על תוכניות סטטיות?

המדד המרכזי אינו עמידה בנורמה, אלא התאמת העומס לרמת ההתאוששות הנוכחית. אפילו התוכנית המושלמת הופכת לחסרת תועלת אם למשתמש יש HRV נמוך או שינה גרועה היום. אנו מפעילים אלגוריתמים שמחשבים ציון מוכנות בכל בוקר (0–100). ציון זה מתאים: סוג האימון, עוצמה (באמצעות מכפיל עומס) והמלצות התאוששות. גישה זו מבטיחה התקדמות חלקה יותר ומפחיתה את הסבירות לפציעות פי 1.5 בהשוואה לתוכניות סטטיות. תוכניות סטטיות משיגות בדרך כלל היענות של 40%, בעוד שהתאמה ב-AI מגיעה ל-70% — גבוה פי 1.75.

כיצד AI קובע את העומס היומי האופטימלי?

המערכת מתחשבת בארבעה גורמים מרכזיים: HRV, דופק במנוחה, איכות שינה ועומס מהיום הקודם. RecoveryMonitor מחשב ציון מוכנות שמשפיע ישירות על עוצמת האימון. אם הציון נמוך מ-55 — מומלץ רק אימון קל או מנוחה. אם הוא מעל 75 — אפשרי אימון כבד בעוצמה של 100%. מופעלת גם פריודיזציה: 3 שבועות של עומס עולה, ואז שבוע התאוששות. דוגמה: משתמש מתעורר עם HRV של 45ms (בסיס 55ms), דופק במנוחה 62 (בסיס 58), שינה 72 נקודות, והיה לו אימון כבד אתמול. RecoveryMonitor מחשב: HRV ירד ב-18% → מינוס 25 נקודות; דופק במנוחה עלה ב-4 → מינוס 15 נקודות; שינה 72 (מעל 60) → ללא קנס; עומס גבוה אתמול → מינוס 10 נקודות. ציון מוכנות סופי = 50 — רק פעילות קלה בעוצמה של 60%.

נתונים נדרשים להתאמה אישית

סט מינימלי: 1–2 שבועות של היסטוריית אימונים ומדדים ביומטריים (HRV, דופק במנוחה, שינה) ממעקב לביש. אם הנתונים אינם מספיקים, אנו יוצרים פרופיל המבוסס על אנתרופומטריה ומטרות, ואז מכיילים אותו עם הגעת מדידות אמיתיות. כל המעקבים המרכזיים נתמכים: Whoop, Oura, Apple Watch, Garmin, Polar.

יישום טכני: Python + Anthropic

להלן הקוד האמיתי למחולל תוכניות שאנו משתמשים בו במערכות ייצור. ערימת הטכנולוגיה המרכזית: Python 3.12, Anthropic Claude 3.5 (באמצעות Anthropic SDK), Pandas לניתוח, NumPy למתמטיקה.

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)}

השוואה: תוכנית סטטית מול התאמה ב-AI

מאפיין תוכנית סטטית התאמה ב-AI (המערכת שלנו)
שימוש בנתונים ביומטריים לא HRV, דופק, שינה, עומס
התאמת עומס פעם בחודש יומי
שיעור היענות 35-45% 65-75%
סיכון לפציעות קו בסיס נמוך ב-30-40%
החזר השקעה (ROI) — 6-12 חודשים

מה כלול בעבודה?

רכיב תיאור
ארכיטקטורת פתרון בחירת מודל (LLaMA 3, Claude), תכנון צינור נתונים לאיסוף ועיבוד נתונים ביומטריים
יצירת תוכניות סוכן RAG עם חיפוש וקטורי (ChromaDB) לתרגילים, טיפול בהתוויות נגד
לוח מחוונים אנליטי מדדים: שיעור היענות, התקדמות תרגילים, ציון מוכנות
אינטגרציה REST API ו-SDK ל-iOS/Android, HealthKit, Google Fit, Polar, Garmin
תמיכה 3 חודשי תמיכה באחריות, הדרכת צוות, תיעוד

תהליך היישום

  1. אנליטיקה — חקר נתונים ביומטריים, סוגי אימונים, ערימה טכנולוגית נוכחית (1–2 ימים).
  2. עיצוב — קביעת ארכיטקטורה: אילו LLMs, כיצד לאחסן embeddings של תרגילים (pgvector).
  3. יישום — כתיבת מודולי RecoveryMonitor, FitnessPlanGenerator, ProgressTracker (2–6 שבועות).
  4. בדיקות — בדיקת A/B על 50–100 משתמשים, הערכת שיפור בהיענות (1–2 שבועות).
  5. פריסה — פריסת מיקרוסרוויסים ב-Kubernetes עם צמתי GPU להסקה (Triton Inference Server).

יעילות כלכלית

עלות יישום פתרון בסיסי מוחזרת תוך 6–12 חודשים על ידי העלאת ערך הלקוח לאורך זמן (LTV) ב-25–30%. החיסכון הממוצע מפיתוח פתרון AI מותאם אישית בהשוואה לרכישת פלטפורמה מוכנה הוא 40%. בנוסף, הפחתת נטישה ב-15–20% מעלה ישירות את ההכנסות. העריכו את ההשפעה הכלכלית עבור המוצר שלכם — צרו קשר לחישוב מקדים.

טעויות נפוצות ביישום התאמה אישית ב-AI

  • התעלמות מנתוני התאוששות. תוכנית המבוססת רק על מטרות (ירידה במשקל/העלאת מסת שריר) ללא התחשבות ב-HRV ושינה מובילה לאימון יתר. אנו תמיד כוללים ציון מוכנות כגורם מתקן.
  • מודל אחד לכולם. LLMs לשימוש כללי (GPT-4 בסיסי) נותנים עצות תבניתיות. אנו משתמשים במודלים מותאמים אישית המבוססים על LLaMA 3, מאומנים על הנתונים שלכם.
  • ללא מנגנון גיבוי. כשלים ב-LLM (השהיה, תגובות לא הולמות) צריכים להפעיל מנוע מבוסס כללים. הארכיטקטורה שלנו כוללת זאת.

קבלו ייעוץ על ארכיטקטורה וצינורות נתונים — צרו קשר כדי לדון במדדים ובתוכנית היישום עבור מוצר הכושר שלכם.