Проблема: чому готові плани не працюють
Користувач завантажує фітнес-додаток, відповідає на пару запитань і отримує шаблон «3×10 присідань». Але в нього травма коліна, вдома немає штанги, а вчора було тренування ніг. Результат — біль, розчарування, видалення додатку. Статичні плани — основна причина низького утримання: без врахування контексту користувач кидає заняття вже через тиждень. Ми вирішуємо цю проблему, створюючи AI-асистента, який враховує реальні дані: історію тренувань, доступне обладнання, фізичні обмеження та цілі. Він не дає стандартних порад — він підлаштовується під конкретну людину в реальному часі. В одному з проектів інтеграція такого асистента підвищила утримання на 30-й день на 40% у порівнянні зі статичними планами.
Чому AI-асистент кращий за готові плани?
Статичні програми ігнорують контекст. AI-асистент, навпаки, збирає дані з кількох джерел: профіль користувача (антропометрія, цілі, травми), дані HealthKit (iOS) або Health Connect (Android), історію завершених тренувань. Він у 3 рази точніше підбирає вправи порівняно з ручним підбором (наші внутрішні A/B-тести). Також асистент знижує ризик перенапруження — автоматично уникає груп м'язів, навантажених за останні 48 годин. Більше 5 років ми розробляємо фітнес-додатки та впровадили такі рішення в 30+ проектах. Гарантуємо сумісність з останніми версіями iOS та Android.
Як ми збираємо дані для персоналізації?
Якість рекомендацій безпосередньо залежить від повноти профілю. Мінімальний набір полів:
| Поле | Тип | Приклад |
|---|---|---|
| Ціль | enum | схуднення, маса, витривалість, реабілітація |
| Рівень | enum | новачок, середній, просунутий |
| Обладнання | мультивибір | штанга, гантелі, турнік, TRX, вага тіла |
| Обмеження | текст | коліно, поперек, плечі |
| Доступний час | число (хв) | 30 |
| Частота занять | число (днів/тиждень) | 3 |
| Історія | дані з API | останні 7 тренувань |
З нативних джерел додаємо дані HealthKit (iOS) або Health Connect (Android 14+):
// iOS: завантаження тренувань за останній тиждень з HealthKit func fetchRecentWorkouts() async throws -> [HKWorkout] { let workoutType = HKObjectType.workoutType() let predicate = HKQuery.predicateForSamples( withStart: Calendar.current.date(byAdding: .day, value: -7, to: Date())!, end: Date() ) let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false) return try await withCheckedThrowingContinuation { continuation in let query = HKSampleQuery( sampleType: workoutType, predicate: predicate, limit: 20, sortDescriptors: [sortDescriptor] ) { _, samples, error in if let error { continuation.resume(throwing: error); return } continuation.resume(returning: (samples as? [HKWorkout]) ?? []) } healthStore.execute(query) } } Документація Apple HealthKit підтверджує правильність підходу до вилучення даних. Додатково імпортуємо параметри сну та варіабельність серцевого ритму (HRV) — вони критичні для оцінки відновлення.
Генерація тренувального плану
Промпт з повним контекстом:
func buildWorkoutPrompt(profile: UserProfile, recentWorkouts: [WorkoutSummary]) -> String { let workoutHistory = recentWorkouts.map { "\($0.date.formatted()): \($0.type), \($0.duration) min, \($0.muscleGroups.joined(separator: "+"))" }.joined(separator: "; ") return """ Create a workout plan for today. User profile: - Goal: \(profile.goal) - Level: \(profile.level) - Available time: \(profile.availableMinutes) minutes - Equipment: \(profile.equipment.joined(separator: ", ")) - Limitations: \(profile.limitations.isEmpty ? "none" : profile.limitations.joined(separator: ", ")) Recent workouts (last 7 days): \(workoutHistory.isEmpty ? "none" : workoutHistory) Rules: - Avoid muscle groups trained in last 48 hours - If limitation mentions specific area (knee, back), exclude exercises for that area - Balance push/pull if goal is hypertrophy Return JSON: { name, totalMinutes, exercises: [{ name, sets, reps, restSeconds, muscleGroups: [], notes, videoSearchQuery }] } """ } videoSearchQuery — ключове поле. Їм формуємо пошуковий запит для YouTube/Vimeo, щоб показати демо вправи прямо в картці.
Адаптація під час тренування
Асистент не повинен мовчати після видачі плану. Три тригери для адаптації:
- Користувач натиснув «Занадто важко» → LLM замінює вправу на легшу.
- Минуло часу більше запланованого → пропонує скоротити решту сетів.
- Усі вправи виконані за 15 хвилин раніше → додає бонусний блок.
// Android - адаптація вправи suspend fun substituteExercise( exercise: Exercise, reason: SubstitutionReason, availableEquipment: List<String> ): Exercise { val prompt = """ The user cannot do "${exercise.name}". Reason: ${reason.description} Available equipment: ${availableEquipment.joinToString(", ")} Target muscles: ${exercise.muscleGroups.joinToString(", ")} Suggest ONE simpler/alternative exercise that targets the same muscles. Return JSON: {name, sets, reps, restSeconds, muscleGroups: [], notes} """ val response = openAIClient.chat( model = "gpt-4o-mini", messages = listOf(Message("user", prompt)), responseFormat = ResponseFormat.JsonObject ) return json.decodeFromString(response.content) } Як AI-асистент визначає дні відпочинку?
AI-асистент повинен рекомендувати не тренуватися, коли це потрібно. Якщо HealthKit показує зниження HKQuantityType.heartRateVariability або Sleep Analysis менше 6 годин — план змінюється на розтяжку або активний відпочинок.
func shouldRecommendRestDay(healthData: HealthSnapshot) -> Bool { return healthData.sleepHours < 6.0 || healthData.restingHeartRate > healthData.averageRestingHR * 1.1 || healthData.hrvTrend == .declining } Це не AI-запит — проста евристика за нативними даними. LLM тут не потрібен.
Як налаштувати профіль для точних рекомендацій?
Щоб AI-асистент видавав максимально релевантні плани, користувач повинен коректно вказати свої дані. Наприклад, якщо ціль — схуднення, а рівень — просунутий, асистент згенерує високоінтенсивну програму з акцентом на спалювання калорій. Якщо ж у користувача травма коліна, всі вправи з присіданнями та випадами будуть виключені. Рекомендуємо заповнити всі поля, включаючи доступне обладнання — це підвищує точність підбору на 50%.
Що входить у розробку?
- Архітектура: синхронізація HealthKit/Health Connect, зберігання профілю, кеш тренувань.
- Генерація планів: промпт-інжиніринг, валідація JSON-відповіді, обробка помилок LLM.
- Адаптація: тригери заміни вправ, таймер відпочинку, rule-based коригування.
- UI/UX: екран профілю, картка тренування, відео-демонстрації, кнопка «Занадто важко».
- Тестування: unit-тести, A/B-тест конверсії (ціль — підвищення утримання на 20%), бета-тест через TestFlight.
- Деплой: публікація в App Store та Google Play, налаштування push-повідомлень (APNs/FCM).
- Документація: схема даних, опис евристик, інструкція з оновлення промптів.
Окрім цього, ми проводимо аудит вашого поточного додатку та пропонуємо оптимальну архітектуру інтеграції. Замовте консультацію — ми покажемо, як AI-асистент підвищить залученість користувачів.
Орієнтовні терміни
| Етап | Строк |
|---|---|
| Профіль і збір даних | 1–2 тижні |
| Генерація плану (базовий) | 3–5 днів |
| Адаптація під час тренування | 1–2 тижні |
| HealthKit/Health Connect інтеграція | 2–3 дні |
| UI/UX та тестування | 2 тижні |
| Разом: MVP | 4–6 тижнів |
Вартість розраховується індивідуально залежно від складності інтеграцій та необхідного функціоналу. Наші інженери мають сертифікати Apple та Google, а також досвід роботи з HealthKit і Health Connect. Зв'яжіться з нами для обговорення вашого проекту — отримайте консультацію з інтеграції AI-асистента вже сьогодні. Дізнайтеся вартість розробки під ваш проект — залиште заявку.







