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_bpm as 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.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for MS846/fitness-gpt2-124m

Finetuned
(2252)
this model