The LLM narrates, never computes
Every number comes from a deterministic step that has tests. The model turns findings into readable notes and nothing else.
Side project · 2026 · Sports analytics
Training analysis for a triathlon squad and its coach. It reads TrainingPeaks, Garmin and Intervals.icu, computes load, fitness, session types and race predictions, and serves one page per athlete. Every finding comes from a rule with a cited source; the local LLM only narrates.
A coach's data is scattered: plans in TrainingPeaks, files from watches and bike computers, thresholds in Intervals.icu. The same session shows up two or three times, power meters die mid-ride and thresholds drift.
Generic AI coaching makes this worse: confident advice with no basis. Here the numbers come from published methods and the model is only allowed to explain them.
Load monitoring, as the engine applies it. The LLM never sees raw files, only the findings.
skills/load_monitor.md
Rules
CTL ramp > 7 points in 7 days alert
TSB < -30 alert
weekly TSS jump > 10% watch
4 weeks without a lighter week watch
TSB +15 to +25 race form
TSB -10 to -30 productive
Data
pmc.daily (ctl, atl, tsb), weekly52Every number comes from a deterministic step that has tests. The model turns findings into readable notes and nothing else.
A ledger records what happened to each file and entry, and a reconciliation report shows anything unexplained.
The coach's exports are a proprietary binary. The format was reverse-engineered field by field, including the embedded original device file.
FTP is backed out of the platform's own TSS per quarter and threshold heart rate fitted from steady efforts, so old sessions are scored against the fitness of that day.
A power meter that reads zero most of the ride is ignored, and an implausible TSS is replaced by a heart-rate estimate.
Athletes only ever receive their own data. Everything runs self-hosted with a local model.
| Layer | Choice | Why |
|---|---|---|
| Parsing | garmin-fit-sdk, custom WKO4 decoder | Per-second power, heart rate, GPS and laps |
| Pipeline | Python scripts over CSV/JSON | Simple to inspect, easy to rerun |
| App | FastAPI, SQLite, argon2 | Coach and athlete roles, installable web app |
| LLM | Ollama on the host | Notes, morning brief, grounded Q&A |
| Mobile | Capacitor iOS, APNs | Push for new session notes |
| Deploy | Docker Compose on a mini PC | Daily run at 05:00 plus on-demand sync |
In daily use by a small squad. Any public demo uses a synthetic athlete; no real athlete data is shown here.
Tell us the problem, the data and where it needs to run. We'll come back with an architecture and scope proposal.
Email contato@laloop.ai