YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
FAIR-Coach model archive (private)
Private archive. Do not make public until dataset and model licences are verified.
Trained artefacts of the PhD thesis FAIR-Coach: diagnosis-aligned biomechanical evidence for AI exercise coaching (Monica Vahdati, University of Ottawa).
- Code: https://github.com/MonicaVahd/FAIR-Coach
- Matching version: tag
v0.1.0, commit49af0b534d614d51acd31ac737c023aba2401699
The models only work with this code version: the code defines the model classes, the evidence extraction and the input format.
Contents
| Folder | Content | Status |
|---|---|---|
dpo_adapter/ |
LoRA-DPO adapter that turns a fixed diagnosis into coaching feedback (base model Qwen3.8-27B) | Private. Licence checks pending |
diagnosis_heads/ |
Frozen diagnosis models mapping biomechanical evidence to 8 squat-error labels, plus two byte-identical snapshots | Private. QEVD licence check pending; they depend on the Path-B classifier |
pathb_stgcn/ |
ST-GCN classifier (correct / incorrect) behind the Path A and Path B evidence | Never make public. Release reason: unverified provenance; likely includes private third-party video and CC BY-NC 4.0 data. |
support_files/ |
Normalisation statistics, a reduced spatial-feature statistics file (mu_train and sd_train only) and the sanitised freeze manifest that the diagnosis loaders need |
Private |
Each folder has its own README.md with SHA-256 values and limitations.
Quick start
Clone the code at the matching version:
git clone https://github.com/MonicaVahd/FAIR-Coach.git cd FAIR-Coach git checkout v0.1.0Install the environment as described in
docs/INSTALL.md. The models were produced with Python 3.10.20, PyTorch 2.5.1+cu121, Transformers 5.17.0 and PEFT 0.20.0.Download this archive (a Hugging Face token with access to this private repository is required):
hf auth login hf download MonicaVahd/fair-coach-models-private --local-dir ./fair-coach-modelsCopy the files into the code repository:
From the archive To the code repository pathb_stgcn/best_stgcn.pthoutput/best_stgcn.pthdiagnosis_heads/*.ptoutput/phase9_checkpoints/dpo_adapter/(whole folder)output/phase12c_dpo_lora/support_files/phase7_train_normalization.jsonoutput/support_files/phase10f_spatial_diag_features_full8.mu_sd_only.npzoutput/phase10f_spatial_diag_features_full8.npz(rename it; it holds onlymu_trainandsd_train)support_files/phase10f_diag_spatial_freeze_manifest.jsonoutput/The diagnosis loader (
analysis/live_diagnosis.py) refuses the diagnosis-aligned Concat+MLP and Reasoner v2 checkpoints if their SHA-256 differs from the freeze manifest. The reduced.npzis enough for that loader; scripts undertools/that read other arrays from the full feature file cannot run from this archive.Run the pipeline as described in
docs/USAGE.md. Datasets are not included; obtain them from their official sources (see the dataset table in the code README).
Models
dpo_adapter/: LoRA-DPO language layer
- Purpose: verbalise a diagnosis that is already fixed, without adding unsupported claims. It never changes the diagnosis.
- Base model:
Qwen/Qwen3.8-27B(set inconfig.py). Files:adapter_model.safetensors(about 21 MB),adapter_config.json, tokenizer files,train_info.sanitized.json. Keep the tokenizer files next to the adapter: the code loads the tokenizer from the adapter folder. - Training: LoRA rank 8, alpha 16, dropout 0.05, targets q/k/v/o projections, learning rate 5e-5, DPO beta 0.1, 156 steps, 420 template-constructed preference pairs (disjoint from the 40 evaluation examples).
- Reported result (thesis, 40 held-out examples, rule-based scoring): unsupported-claim rate 75% to 17.5%, evidence specificity 75% to 92.5%, own-label consistency 22.5% to 77.5%. The evaluation is small and template-based, and no template baseline was run.
- Loading (mirrors
feedback/dpo_feedback.py: 4-bit NF4, as in the thesis):The thesis code passesimport torch from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig from peft import PeftModel adapter_dir = "output/phase12c_dpo_lora" bnb = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.bfloat16, bnb_4bit_use_double_quant=True, ) tokenizer = AutoTokenizer.from_pretrained(adapter_dir) model = AutoModelForCausalLM.from_pretrained( "Qwen/Qwen3.8-27B", quantization_config=bnb, device_map="auto", dtype=torch.bfloat16, ) model = PeftModel.from_pretrained(model, adapter_dir)trust_remote_code=Truewhen loading both the tokenizer and the base model; enable it only after reviewing the model repository. Generation in the thesis used greedy decoding (do_sample=False). A GPU is expected to be needed for a 4-bit 27B model (the code usesdevice_map="auto"); memory needs were not measured.
diagnosis_heads/: frozen diagnosis models
Each model outputs 8 logits; apply a sigmoid and threshold at 0.5. Label order:
no_obvious_issue, shallow, knees_over_toes, back_not_straight, narrow, wide, over_90_degrees, insufficient.
| File | Model (class, location) | Evidence input | Parameters | TEST micro-F1 (seed 42) |
|---|---|---|---|---|
phase8_8_concat_mlp_frozen.pt |
Generic Concat+MLP, original fixed-epoch baseline (ConcatMLP, tools/train_concat_mlp.py) |
27 generic features + mask (54) | 2,024 | 0.2901 |
fine8_relations_off_frozen.pt |
8-group model, relations off (RelationalDiagnosisModel, analysis/relational_diagnosis.py) |
generic | 3,576 | 0.2905 |
fine8_relations_on_frozen.pt |
8-group model, relations on (same class) | generic | 4,377 | 0.2969 |
reasoner_v2_frozen.pt |
Reasoner v2 (ReasonerV2, analysis/reasoner_v2.py) |
generic | 3,432 | 0.2932 |
relational_reasoner_locked.pt |
Coarse 5-group message passing (RelationalDiagnosisModel) |
generic | 3,513 | 0.2648 |
diag_concat_mlp_27plus10_frozen.pt |
Diagnosis-aligned Concat+MLP, default backend (FlexConcatMLP, analysis/live_diagnosis.py) |
27 generic + 10 diagnosis-aligned features + masks (74) | 2,664 | 0.3435 |
reasoner_v2_diag_spatial_frozen.pt |
Reasoner v2, diagnosis-aligned (ReasonerV2Diag, analysis/reasoner_v2_diag.py) |
37 features | 3,752 | 0.3322 |
reasoner_v2_diag_spatial_val.pt and reasoner_v2_exploratory.pt are byte-identical to their frozen counterparts.
- Checkpoint layout: the 8.8 baseline, the three relational files and
diag_concat_mlp_27plus10_frozen.ptstore a wrapper dictionary with astate_dictkey. The two Reasoner v2 frozen files are flat state dictionaries. The tensors were saved oncuda:0, so load withmap_location="cpu"when no GPU is present. - Input: a
RepEvidencerecord (schemas.py) for one validated squat repetition, encoded into the 27 generic features byanalysis/reasoning_xy.py; the 10 spatial features come fromspatial_features_coreintools/phase10f_spatial_diag_features.py. The 27 generic features are z-scored withphase7_train_normalization.json; the 10 spatial features use the first 10 entries ofmu_trainandsd_trainfromphase10f_spatial_diag_features_full8.npz.support_files/holds the normalisation JSON and a reduced copy of that.npzwith onlymu_trainandsd_train. QEVD-derived evidence files are not included. - Use the code loaders (
analysis/live_diagnosis.pyand the scripts undertools/) rather than loading the files by hand. - How to read the results: these are thesis results within QEVD, not independent replications. The TEST split has five participants (1,052 clips). The default model's TEST value was observed before it was designated the default, so it is not an untouched estimate. The diagnosis-aligned models add features and input dimensions compared with the generic ones, so the gain cannot be attributed to alignment alone.
pathb_stgcn/: ST-GCN behind Path A and Path B
- File:
best_stgcn.pth(12,389,290 bytes, SHA-25604bedce9ab63032072f8be06324e2ac43f4add5b344d6f71032ef32766c70fc2), a flat state dictionary. - Model: ST-GCN (
lib/net/st_gcn.py), built bybuild_stgcn_modelinutils.py: 3 input channels (x, y, confidence), 2 classes (class 0 incorrect, class 1 correct), OpenPose-18 spatial graph, input shape (batch, 3, 100, 18, 1) built from COCO-17 keypoints. - Provenance and use: Training record not preserved; the 614 stored sequences match, by class counts, EC3D + REHAB24-6 + a private custom collection of 282 YouTube-derived sequences (indirect; not verified at sample level). Used for Path A windows and Path B repetitions in the live system.
- Dependency: its Path-B outputs are generic evidence for every diagnosis model, so the diagnosis results cannot be reproduced without it.
- Not recorded: the seed and held-out accuracy were not recorded, and the training script sets no seed.
- Release reason: unverified provenance; likely includes private third-party video and CC BY-NC 4.0 data.
Intended use and limitations
- Research and reproducibility only. This is not a medical or deployment-ready system.
- Absolute diagnostic performance is modest (micro-F1 about 0.34), and the probabilities are poorly calibrated.
- The grounding evaluation did not demonstrate that diagnoses depend on the intended biomechanical evidence.
- All results are offline, squat-based and within QEVD.
Licences
- Code: Apache-2.0 (see the GitHub repository), except the ST-GCN files under
lib/net/, which keep their upstream BSD-style licence (seeNOTICE). - Base model Qwen3.8-27B: licence to be confirmed from its official page.
- Datasets are not redistributed here. REHAB24-6 is CC BY-NC 4.0; check the licences of QEVD, EC3D and UI-PRMD before any release.
Citation
Citation information will be added once the thesis is published.