Zaznacz stronę

Moja przygoda z bardziej świadomym treningiem biegowym rozpoczęła się pod koniec 2024 roku. Wcześniej biegałem regularnie, ale raczej intuicyjnie. Patrzyłem na dystans, tempo i tętno, jednak brakowało mi spójnego planu oraz sposobu, który pozwoliłby oceniać treningi w dłuższej perspektywie.

Bezpośredni wpływ na tę zmianę miały dwa wydarzenia. Pierwszym było przypadkowe natrafienie na książkę „Bieganie metodą Danielsa”. Drugim – pierwszy w historii mojej dzielnicy charytatywny bieg, którego organizację planowano na kwiecień 2025 roku. Miałem być zaangażowany w jego przygotowanie, więc naturalnie pojawiła się motywacja, aby nie tylko pomagać przy organizacji, ale również samemu stanąć na starcie w możliwie najlepszej formie.

Od tamtej pory moje bieganie zaczęło się zmieniać. Najpierw był Daniels, później Jeff Galloway, Scott Jurek i Kilian Jornet. Z czasem coraz częściej zadawałem sobie pytanie, czy istnieje jedna najlepsza metoda treningowa, czy raczej każda z nich wnosi coś wartościowego i warto świadomie czerpać z różnych źródeł.

Równolegle zmieniał się mój technologiczny ekosystem. Przez wiele lat korzystałem z zegarków Samsung Galaxy. Ostatnim urządzeniem był Galaxy Watch Ultra, który w połączeniu z aplikacją Samsung Health długo spełniał moje oczekiwania. Oferował świetne funkcje smart, dobrą integrację z telefonem i podstawowe statystyki treningowe. Z czasem zacząłem jednak potrzebować bardziej sportowego narzędzia.

Na początku 2026 roku przeszedłem do ekosystemu COROS. Wybrałem zegarek COROS Apex 4 oraz czujnik tętna COROS HRM. Sprzęt się zmienił, ale jedna decyzja pozostała niezmienna: od początku wszystkie treningi eksportowałem do Stravy. Dzięki integracjom dostępnym zarówno w Samsung Health, jak i COROS mogłem zachować pełną historię aktywności w jednym miejscu. Niezależnie od tego, jaki zegarek miałem aktualnie na nadgarstku, wszystkie treningi trafiały do jednej bazy. Z perspektywy czasu była to jedna z najlepszych decyzji.

Problem, którego wcześniej nie zauważałem

Moje cykle treningowe zwykle trwają od 4 do 8 tygodni. Lubię eksperymentować i nie trzymam się kurczowo jednej metody. Czasami inspiruję się Danielsem, czasami treningiem pod biegi górskie, a innym razem próbuję czegoś zupełnie nowego. Do tej pory przy układaniu planów korzystałem przede wszystkim z własnej wiedzy i doświadczenia. Coraz częściej wspomagałem się również sztuczną inteligencją.

Do sugestii AI podchodziłem jednak ostrożnie. Powód był prosty: model nie znał mnie jako biegacza. Potrafił wygenerować plan treningowy na podstawie ogólnej wiedzy, ale nie miał dostępu do mojej historii treningów, sukcesów, błędów, okresów zmęczenia, startów, kontuzji ani mocnych i słabych stron. W praktyce oznaczało to, że każda rozmowa zaczynała się niemal od zera.

Model znał teorię treningu. Nie znał mnie.

Co by było, gdyby AI mogło przeanalizować całą moją historię treningową?

To pytanie stało się początkiem eksperymentu, który później przerodził się w projekt Virtual Runner Coach.

Co chcę osiągnąć?

Nie chodziło mi o stworzenie kolejnego prostego generatora planów treningowych. Chciałem sprawdzić, czy lokalny model językowy może stać się narzędziem, które zna historię konkretnego biegacza i potrafi ją wykorzystać w rozmowie.

Docelowo chciałbym móc zadawać pytania w rodzaju:

  • Dlaczego moje tętno rośnie przy podobnym tempie?
  • Czy aktualny trening bardziej mnie rozwija, czy przeciąża?
  • Jak wyglądał podobny okres treningowy rok temu?
  • Czy metoda Jacka Danielsa rzeczywiście działała w moim przypadku?
  • Jak połączyć bieganie asfaltowe, górskie i trening uzupełniający?

Aby AI mogło sensownie odpowiedzieć na takie pytania, najpierw musi otrzymać uporządkowane dane. I właśnie od tego zaczyna się ten projekt.

Trzy etapy eksperymentu

Całość podzieliłem na trzy główne etapy.

Etap 1: przygotowanie danych

Najpierw trzeba było odpowiedzieć na podstawowe pytanie:

W jaki sposób nauczyć AI poznawać konkretnego biegacza?

Odpowiedź była oczywista: potrzebne są dane. Nie dowolne dane, tylko moje dane: treningi, aktywności, kilometraż, tempo, tętno, przewyższenia i historia budowania formy. Pierwszym zadaniem stało się więc pobranie danych ze STRAVA, ich normalizacja i przygotowanie w postaci, którą później będzie można wykorzystać do dalszej analizy.

Etap 2: budowa wirtualnego trenera

Drugi etap zakłada stworzenie lokalnego środowiska AI wykorzystującego między innymi:

  • Ollama,
  • Open WebUI,
  • Hermes Agent.

Celem jest stworzenie wirtualnego trenera, który będzie potrafił analizować historię treningową konkretnego zawodnika, oceniać jego formę oraz pomagać w planowaniu kolejnych cykli.

Etap 3: aplikacja dla użytkownika

Ostatecznym celem projektu jest aplikacja, która połączy wszystkie elementy w jeden spójny system: import danych, analizę formy, generowanie planów treningowych i rozmowę z AI.

Etap pierwszy – od eksportu STRAVA do ustrukturyzowanych danych

Pierwszym krokiem było przygotowanie warstwy danych. I tutaj pojawiło się pierwsze zaskoczenie. Strava pozwala pobrać pełny eksport aktywności, ale dane nie są od razu gotowe do wykorzystania przez modele AI. Eksport zawiera wiele plików, różne formaty i różne poziomy szczegółowości. Po rozpakowaniu archiwum znajdziemy między innymi:

activities.csv
activities/
 123456789.tcx.gz
 987654321.fit.gz
 ...

Na pierwszy rzut oka wygląda to dobrze. W praktyce szybko okazało się, że część aktywności ma szczegółowe pliki TCX, część istnieje tylko jako wpis w pliku CSV, a niektóre treningi mają dane zapisane w formacie FIT. Zanim AI będzie mogło cokolwiek analizować, potrzebna jest więc warstwa pośrednia, która zunifikuje te informacje.

Tak powstał pierwszy komponent projektu Virtual Runner Coach:

strava_import.py

Jego zadanie można przedstawić bardzo prosto:

Eksport Stravy (ZIP)
↓
Import danych
↓
Normalizacja danych
↓
runner_summary.json

Importer stanowi fundament całego dalszego procesu analitycznego.

Założenia projektowe

Projektując importer, przyjąłem kilka podstawowych zasad.

Jedna odpowiedzialność

Importer odpowiada wyłącznie za import i normalizację danych ze Stravy. Nie zajmuje się:

  • analizą formy,
  • klasyfikacją treningów,
  • wyznaczaniem VDOT,
  • generowaniem planów treningowych.

To świadoma decyzja architektoniczna. Importer ma przygotować wiarygodne dane wejściowe, a nie podejmować decyzje treningowe. Dzięki temu łatwiej go testować, rozwijać i utrzymywać.

Powtarzalność

Dla tego samego eksportu Stravy skrypt powinien zawsze wygenerować taki sam wynik. Dzięki temu późniejsze analizy mogą opierać się na stabilnym źródle danych.

Zachowanie kompletnej historii treningowej

To założenie okazało się szczególnie ważne. Jeżeli dostępne są szczegółowe dane TCX, importer je wykorzystuje. Jeżeli aktywność występuje wyłącznie w CSV, również zostaje zachowana. Celem było uniknięcie sytuacji, w której część historii treningowej znika tylko dlatego, że dla danej aktywności nie ma szczegółowego pliku.

Proces importu danych

Krok 1: rozpakowanie archiwum ZIP

Importer przyjmuje bezpośrednio plik eksportu:

python strava_import.py export.zip

Archiwum zostaje rozpakowane do katalogu tymczasowego. W tym momencie wykonywana jest również walidacja bezpieczeństwa:

  • sprawdzanie poprawności ścieżek,
  • ochrona przed atakami typu Path Traversal,
  • automatyczne wyszukiwanie wymaganych plików.

Importer odnajduje wymagane elementy niezależnie od tego, jak dokładnie wygląda struktura katalogów wewnątrz archiwum:

activities.csv
activities/

Krok 2: analiza pliku CSV

Następnie odczytywany jest plik:

activities.csv

Importer automatycznie mapuje schemat danych. Przykładowo kolumny:

  • Activity Type,
  • Type,
  • Sport,
  • Workout Type

są traktowane jako ta sama informacja logiczna. Dzięki temu importer jest bardziej odporny na zmiany formatu eksportu.

Krok 3: przetwarzanie plików TCX

Każdy plik:

*.tcx.gz

jest rozpakowywany i analizowany. Z plików odczytywane są między innymi:

  • data aktywności,
  • dystans,
  • czas trwania,
  • tempo,
  • średnie tętno,
  • maksymalne tętno,
  • suma przewyższeń,
  • liczba punktów GPS.

Następnie wszystkie dane są normalizowane:

  • dystans → kilometry,
  • czas → minuty,
  • tempo → min/km,
  • przewyższenie → metry.

To właśnie na tym etapie powstaje jednolity model danych, niezależny od urządzenia, z którego pochodził trening.

Krok 4: łączenie danych TCX i CSV

Pliki TCX zawierają szczegóły treningów, natomiast CSV zawiera metadane, takie jak:

  • typ aktywności,
  • nazwa treningu,
  • nazwa pliku eksportu.

Oba źródła są łączone w jeden rekord. Dopiero taki rekord nadaje się do dalszego wykorzystania przez system analityczny i modele AI.

Krok 5: aktywności dostępne tylko w CSV

To był jeden z ciekawszych problemów. Podczas testów okazało się, że część aktywności istnieje wyłącznie w pliku CSV. W moim przypadku importer wykrył kilkadziesiąt takich treningów. Gdybym analizował jedynie pliki TCX, historia treningowa byłaby niekompletna.

Dlatego importer tworzy uproszczone rekordy również dla aktywności dostępnych wyłącznie w CSV. Dzięki temu zachowana zostaje pełna historia treningowa, nawet jeśli dla części aktywności brakuje szczegółowych danych.

Generowane pliki

Po zakończeniu działania importer tworzy cztery pliki wynikowe.

runner_summary.json

To najważniejszy plik całego procesu. Zawiera:

  • wszystkie aktywności,
  • znormalizowane dane treningowe,
  • podstawowe statystyki,
  • informacje o źródłach danych.

To właśnie ten plik staje się podstawą kolejnych etapów projektu.

weekly_running_summary.csv

To tygodniowe podsumowanie wyłącznie aktywności biegowych. Plik jest przydatny do wizualizacji i analizy kilometrażu.

weekly_all_activities_summary.csv

To analogiczne podsumowanie wszystkich aktywności, między innymi:

  • biegania,
  • roweru,
  • marszów,
  • trekkingu,
  • treningu siłowego.

W przyszłości ten plik może być wykorzystywany do analizy całkowitego obciążenia treningowego, a nie tylko samego biegania.

strava_diagnostics.json

To raport techniczny przeznaczony głównie dla programistów. Zawiera:

  • błędy parsowania,
  • brakujące pliki,
  • wykryte kolumny CSV,
  • aktywności dostępne wyłącznie w CSV,
  • statystyki importu.

To właśnie dzięki temu raportowi udało mi się zauważyć, że część aktywności nie posiada odpowiadających im plików TCX lub FIT.

Dlaczego taka architektura?

Importer został zaprojektowany zgodnie z prostą zasadą:

Surowe dane
↓
Dane ustandaryzowane

Nie podejmuje decyzji treningowych. Nie próbuje być trenerem. Nie próbuje być modelem AI. Jego jedynym zadaniem jest przygotowanie wiarygodnych danych wejściowych dla kolejnych etapów projektu.

Dzięki temu:

  • łatwiej go testować,
  • łatwiej rozwijać,
  • łatwiej utrzymać kompatybilność z przyszłymi wersjami eksportów Stravy,
  • łatwiej oddzielić warstwę danych od późniejszej analizy treningowej.

Podsumowanie

Po wykonaniu polecenia:

python strava_import.py export.zip

cała historia moich aktywności zostaje przekształcona w jeden spójny zbiór danych. Powstały plik runner_summary.json staje się fundamentem dalszych etapów projektu:

  • analizy formy biegacza,
  • klasyfikacji treningów,
  • wyznaczania parametrów wydolnościowych,
  • generowania planów treningowych,
  • pracy z lokalnymi modelami AI.

Cały proces można podsumować następująco:

Eksport Stravy
↓
strava_import.py
↓
runner_summary.json
↓
Virtual Runner Coach

To dopiero pierwszy krok. W następnym artykule pokażę, co można wyczytać z kilku lat historii treningów i jak na podstawie tych danych zacząć budować profil biegacza, który będzie zrozumiały dla sztucznej inteligencji.

Strona projektu w serwisie GitHub: https://github.com/maciejrakoczy/v_runner_coach