Fitness Agent — GPT-2 small (124M) instruction-tuned
A fine-tuned GPT-2 small (124M parameters) that interprets daily wearable data snapshots (sleep, heart rate, activity, subjective wellness) and gives grounded fitness chat responses. Designed to run on-device on Android phones via llama.cpp + GGUF quantization (~169 MB at Q8_0).
Model details
| Architecture | GPT-2 small (124M, custom from-scratch impl in GPT2.py) |
| Base model | OpenAI GPT-2 small (BPE vocab, 1024 ctx) |
| Fine-tuning data | ~4,440 instruction tuples (85% PMData-grounded, 15% MedQuAD general) |
| Training | PyTorch + tiktoken, AdamW lr 5e-5, 3 epochs |
| Final val loss | 0.66 |
| File | model_fitness_small.pth (PyTorch state dict, ~670 MB) |
| License (weights) | CC BY-NC 4.0 (inherits from PMData) |
Intended use
The model answers questions about a user's wearable data using a fixed Alpaca-style prompt:
Below is an instruction that describes a task. Write a response that appropriately completes the request.
### Instruction:
Should I do a hard workout today?
### Input:
Sleep: 7h 31m total (deep 2h 23m, REM 1h 54m, score 88/100)
Resting HR: 55 bpm (-1.9 vs 7-day baseline)
Activity: 58 very-active min
Subjective: fatigue 2/5, stress 4/5, soreness 3/5, mood 3/5, sleep quality 4/5, readiness 3/10
### Response:
Trained question types include:
- Should I do a hard workout / long session / intervals today?
- Should I take a rest day?
- Why am I tired?
- How was my recovery?
- What does my data say overall?
- Interpret my resting heart rate
- Sleep stages, sleep quality questions
- Workout effectiveness
- Stress interpretation
- Sparse-data handling ("I didn't log everything…")
Out of scope
- Not medical advice
- Not for diagnosis or treatment
- Hardware HRV / SpO2 fields are not in PMData; the model is trained to use
resting_hr_baseline_delta_bpmas a proxy and not to fabricate HRV values
How to use
Direct inference (PyTorch)
import torch, tiktoken
from huggingface_hub import hf_hub_download
import sys; sys.path.append("path/to/fitness-gpt2-agent")
from GPT2 import GPTModel
from util import generate
BASE_CONFIG = {
"vocab_size": 50257, "context_length": 1024, "drop_rate": 0.0,
"qkv_bias": True, "emb_dim": 768, "n_layers": 12, "n_heads": 12,
}
device = "mps" if torch.backends.mps.is_available() else "cpu"
ckpt_path = hf_hub_download(repo_id="MS846/fitness-gpt2-124m",
filename="model_fitness_small.pth")
model = GPTModel(BASE_CONFIG)
model.load_state_dict(torch.load(ckpt_path, map_location=device, weights_only=True))
model.to(device).eval()
tokenizer = tiktoken.get_encoding("gpt2")
prompt = "..." # Alpaca-style as shown above
ids = torch.tensor(tokenizer.encode(prompt)).unsqueeze(0).to(device)
out_ids = generate(model=model, idx=ids, max_new_tokens=200,
context_size=1024, eos_id=50256, top_k=50, temperature=0.7)
print(tokenizer.decode(out_ids[0].tolist())[len(prompt):])
On-device (Android via llama.cpp GGUF)
Convert to GGUF then bundle into the Android app — see the code repo
for the full pipeline (fitness_app/01_model_export/convert_to_gguf.sh).
Training data
Generated synthetically from real wearable snapshots:
- PMData (Simula, CC BY-NC 4.0) — 16 participants × 5 months of Fitbit + subjective wellness data → 1,897 daily snapshots → ~3,770 grounded Q&A
- MedQuAD (NIH/NLM, CC BY 4.0) — fitness/health Q&A filtered to ~660 pairs
- Curated supplement — 71 hand-written general fitness Q&A
Dataset synthesis pipeline is in the code repo.
Evaluation
Tested on a held-out set of 444 PMData snapshot Q&A pairs:
- Similarity to expected answer (token + bigram F1 + number recall): mean 61.7, median 67.2
- Independent quality rubric (length, value grounding, no repetition, coherence, vocab, caveat): mean 82.6, median 85.0
- 71% of responses scored ≥80 on quality
The lower similarity reflects the model picking valid but template-diverse answers, not memorising specific instances.
Limitations
- 124M parameters is small for multi-signal reasoning. With only steps or only subjective data, the model can produce off-topic recommendations.
- Best results when the input snapshot includes resting HR baseline delta + at least one subjective rating.
- No HRV / SpO2 in training data (Fitbit Versa 2 doesn't export them in PMData). The model is trained to admit these as unavailable.
- Designed for English only.
Citation
If you use this model:
@misc{sharma2026fitnessagent,
author = {Sharma, Mayank},
title = {Fitness Agent: A Fine-tuned GPT-2 124M for On-Device Wearable Data Interpretation},
year = {2026},
url = {https://github.com/mak846/fitness-gpt2-agent}
}
License
- Code (training pipeline, Android app): MIT, see GitHub repo
- Weights in this repo: CC BY-NC 4.0 — research and non-commercial use only (inherits from PMData training data)
Disclaimer
This model produces fitness insights, not medical advice. Consult a qualified clinician for any health concerns.
Model tree for MS846/fitness-gpt2-124m
Base model
openai-community/gpt2