tthhanh commited on
Commit
30fed09
·
1 Parent(s): 87a8551

docs: add coach summary training report

Browse files
Files changed (1) hide show
  1. docs/coach-summary-training-report.md +370 -0
docs/coach-summary-training-report.md ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Coach Summary Training Report
2
+
3
+ Generated from the current Pozify codebase state on June 14, 2026.
4
+
5
+ ## Summary
6
+
7
+ The coach-summary model in Pozify is a grounded JSON-to-JSON generation component, not a generic
8
+ fitness chatbot. Its job is to convert structured workout-analysis artifacts into a safe,
9
+ evidence-bounded `coach_summary.json`, then pass that output through a verifier before it is shown
10
+ in the app.
11
+
12
+ The current training stack is:
13
+
14
+ - Base model: `Qwen/Qwen3-14B`
15
+ - Fine-tuning method: LoRA / QLoRA-style SFT on Modal
16
+ - Training target: Pozify-native structured summary generation
17
+ - Runtime fallback: deterministic conservative summary when model generation fails or verification fails
18
+
19
+ The current codebase already supports:
20
+
21
+ - dataset building from real Pozify run artifacts
22
+ - Modal stages for prepare/train/evaluate/merge/publish
23
+ - verifier-based evaluation
24
+ - merged full-model publishing
25
+ - UI metadata for provider/model/source reporting
26
+
27
+ The main deployment gap at the time of this report is not training infrastructure. The main gap is
28
+ that the published Hugging Face merged repo is still not accepted by the current Hugging Face
29
+ Inference API path used by the app, so the app falls back to rule-based summaries when that repo is
30
+ selected.
31
+
32
+ ## Objective
33
+
34
+ The coach-summary model is designed to generate these grounded sections:
35
+
36
+ - `summary`
37
+ - `what_you_did`
38
+ - `what_looked_good`
39
+ - `what_changed_across_reps`
40
+ - `valid_variation_vs_issue`
41
+ - `top_fixes`
42
+ - `next_session_plan`
43
+ - `confidence_notes`
44
+
45
+ Unlike a free-form assistant, this model is instructed to:
46
+
47
+ - use only structured evidence and retrieved knowledge cards
48
+ - never invent issue labels outside `issue_markers.json`
49
+ - avoid diagnosis language
50
+ - avoid injury-prevention claims
51
+ - preserve valid variation context instead of overcorrecting it
52
+
53
+ This contract is implemented in the prompt builder and enforced again by the verifier.
54
+
55
+ ## Training Data
56
+
57
+ The current SFT data is Pozify-native and built from real run artifacts under `runs/`.
58
+
59
+ ### Source artifacts per example
60
+
61
+ Each SFT row is constructed from:
62
+
63
+ - `user_profile.json`
64
+ - `exercise_classification.json`
65
+ - `reps.json`
66
+ - `rep_analysis.json`
67
+ - `variation.json`
68
+ - `issue_markers.json`
69
+ - `coach_summary.json`
70
+
71
+ The dataset builder reconstructs typed contracts from those files, retrieves the same knowledge
72
+ cards used at runtime, and serializes a chat-style SFT example with:
73
+
74
+ - system prompt
75
+ - user message containing structured evidence JSON
76
+ - assistant message containing the target `coach_summary.json`
77
+
78
+ ### Current local dataset size
79
+
80
+ From the checked-in data in `data/sft/`:
81
+
82
+ | File | Rows |
83
+ | --- | ---: |
84
+ | `coach_summary_train.jsonl` | 22 |
85
+ | `coach_summary_eval.jsonl` | 5 |
86
+ | `public_fitness_style.jsonl` | 854 |
87
+
88
+ The style dataset is much larger than the grounded task dataset, so the training script samples
89
+ only a small portion of style rows according to `style_weight`.
90
+
91
+ ## Prompt and Grounding Design
92
+
93
+ The prompt builder creates a structured instruction block plus a structured evidence block.
94
+
95
+ ### Evidence included in the prompt
96
+
97
+ - `user_profile`
98
+ - `exercise_classification`
99
+ - `variation`
100
+ - `rep_summary`
101
+ - `issue_summary`
102
+ - `priority_cues`
103
+ - `knowledge_cards`
104
+
105
+ ### Core prompt rules
106
+
107
+ - Use only the evidence JSON and retrieved knowledge cards.
108
+ - Do not infer new issues absent from `issue_summary.issues`.
109
+ - Do not diagnose injuries or pathology.
110
+ - Do not claim injury prevention.
111
+ - Do not treat valid variation labels or not-issue labels as errors.
112
+ - Include exact issue or variation labels in backticks when referenced.
113
+ - Return JSON only.
114
+
115
+ This is a good fit for small-model fine-tuning because the task is narrow, repetitive, and highly
116
+ structured.
117
+
118
+ ## Model and Training Setup
119
+
120
+ ### Current default base model
121
+
122
+ The codebase now defaults to:
123
+
124
+ - `Qwen/Qwen3-14B`
125
+
126
+ This is used in:
127
+
128
+ - `configs/coach_summary_lora.default.json`
129
+ - `scripts/train_coach_summary_lora.py`
130
+ - runtime default in `src/pozify/slm/providers.py`
131
+
132
+ ### Default training hyperparameters
133
+
134
+ | Hyperparameter | Value |
135
+ | --- | ---: |
136
+ | Base model | `Qwen/Qwen3-14B` |
137
+ | LoRA rank | 16 |
138
+ | LoRA alpha | 32 |
139
+ | LoRA dropout | 0.05 |
140
+ | Learning rate | 0.0002 |
141
+ | Epochs | 2 |
142
+ | Batch size per device | 1 |
143
+ | Gradient accumulation | 8 |
144
+ | Max sequence length | 4096 |
145
+ | Default style weight | 0.2 |
146
+
147
+ ### Modal implementation
148
+
149
+ The full training pipeline is implemented in `scripts/coach_summary_modal.py` with these stages:
150
+
151
+ - `prepare-data`
152
+ - `train`
153
+ - `evaluate`
154
+ - `merge`
155
+ - `publish`
156
+ - `publish-merged`
157
+ - `all`
158
+
159
+ The training stage:
160
+
161
+ - loads the base model with 4-bit quantization
162
+ - fine-tunes with TRL `SFTTrainer`
163
+ - saves adapter weights and tokenizer to the Modal model volume
164
+
165
+ The merge stage:
166
+
167
+ - loads base model plus adapter
168
+ - calls `merge_and_unload()`
169
+ - writes a merged full checkpoint to `merged_model/`
170
+
171
+ ## Evaluation Design
172
+
173
+ The evaluation stage is not based on generic BLEU or chat preference metrics. It uses task-specific
174
+ checks that match Pozify's production constraints.
175
+
176
+ ### Reported evaluation metrics
177
+
178
+ - JSON validity rate
179
+ - verifier pass rate
180
+ - section completeness rate
181
+ - failure count and example failures
182
+
183
+ ### Verifier checks
184
+
185
+ The verifier currently enforces:
186
+
187
+ - `no_issue_outside_json`
188
+ - `variation_not_overcorrected`
189
+ - `no_diagnosis`
190
+ - `no_injury_prevention_claim`
191
+ - `confidence_notes_present_when_required`
192
+
193
+ This is a strong design choice for Pozify because it measures whether the model behaves safely and
194
+ stays grounded, not just whether it sounds fluent.
195
+
196
+ ## Latest Observed Training Outcome
197
+
198
+ From the latest visible Modal training logs for the full coach-summary flow:
199
+
200
+ ### Training summary
201
+
202
+ | Metric | Value |
203
+ | --- | ---: |
204
+ | Train rows | 22 |
205
+ | Eval rows | 5 |
206
+ | Style rows mixed in | 4 |
207
+ | Merged train rows | 26 |
208
+ | Epochs | 2 |
209
+ | Global steps | 8 |
210
+ | Training loss | 1.0797 |
211
+
212
+ ### Evaluation summary
213
+
214
+ | Metric | Value |
215
+ | --- | ---: |
216
+ | Evaluated count | 5 |
217
+ | JSON valid count | 2 |
218
+ | JSON validity rate | 0.40 |
219
+ | Verifier pass count | 0 |
220
+ | Verifier pass rate | 0.00 |
221
+ | Section completeness rate | 0.00 |
222
+
223
+ ### Observed failure modes
224
+
225
+ - missing required top-level fields such as `summary`
226
+ - malformed JSON with delimiter errors
227
+ - outputs that fail schema extraction before verifier success is even possible
228
+
229
+ These numbers suggest that the current grounded task setup is correct in principle, but the dataset
230
+ is still too small and the model is not yet reliably producing the full required schema.
231
+
232
+ ## Runtime Behavior in the App
233
+
234
+ At runtime the pipeline does this:
235
+
236
+ 1. Generate a model summary from structured evidence.
237
+ 2. Parse the model output into `coach_summary.json`.
238
+ 3. Run the verifier.
239
+ 4. If generation fails, use `fallback_initial`.
240
+ 5. If generation succeeds but verification fails, use `fallback_after_verification` unless bypass is enabled.
241
+
242
+ The final report stores:
243
+
244
+ - `coach_summary_provider`
245
+ - `coach_summary_model`
246
+ - `coach_summary_source`
247
+ - verifier bypass metadata
248
+
249
+ This makes the UI traceable and helps distinguish:
250
+
251
+ - cloud model output
252
+ - local model output
253
+ - conservative fallback output
254
+
255
+ ## Current Deployment Status
256
+
257
+ ### What works
258
+
259
+ - grounded prompt contract
260
+ - deterministic knowledge-card retrieval
261
+ - SFT dataset builder from Pozify artifacts
262
+ - Modal train/evaluate/merge/publish pipeline
263
+ - verifier integration
264
+ - fallback summary integration
265
+ - runtime metadata reporting in UI
266
+
267
+ ### What is currently failing
268
+
269
+ The published merged Hugging Face repo for the fine-tuned coach model is still not accepted by the
270
+ Hugging Face inference route currently used in `HFInferenceCoachSummaryModel`.
271
+
272
+ Observed runtime failure:
273
+
274
+ - `The requested model 'build-small-hackathon/pozify-coach-summary1' is not a chat model.`
275
+
276
+ Because of that, the app falls back even when the runtime resolves the correct repo ID.
277
+
278
+ ### Practical implication
279
+
280
+ For the app to avoid fallback today, the safest temporary runtime choice is a cloud-hosted model
281
+ that is already supported by Hugging Face Inference, such as:
282
+
283
+ - `Qwen/Qwen3-14B`
284
+
285
+ The fine-tuned merged repo is still useful as a training artifact, but it is not yet plug-and-play
286
+ through the current cloud inference path.
287
+
288
+ ## Assessment
289
+
290
+ ### Strengths
291
+
292
+ - The task definition is well-scoped and matches the product.
293
+ - The prompt is strongly grounded on structured artifacts.
294
+ - The verifier is aligned with real product risk, not just language quality.
295
+ - The dataset builder is tightly coupled to actual runtime contracts.
296
+ - The pipeline supports both model generation and deterministic fallback.
297
+
298
+ ### Weaknesses
299
+
300
+ - The grounded SFT dataset is still very small.
301
+ - Schema reliability is not yet strong enough.
302
+ - Verifier pass rate is currently too low for production dependence.
303
+ - Published merged artifacts are not yet working cleanly with the current Hugging Face inference strategy.
304
+ - Modal config reuse can accidentally preserve stale training settings if old volume artifacts are not cleaned.
305
+
306
+ ## Recommendations
307
+
308
+ ### Short term
309
+
310
+ 1. Use `Qwen/Qwen3-14B` as the temporary runtime cloud model.
311
+ 2. Keep the fallback summary enabled in production.
312
+ 3. Expand the grounded SFT dataset from more real runs before increasing training complexity.
313
+ 4. Add stronger output-format controls or post-processing to improve JSON validity.
314
+ 5. Clean or version Modal model volumes when switching base models.
315
+
316
+ ### Medium term
317
+
318
+ 1. Grow the Pozify-native dataset to at least 100 to 300 high-quality examples.
319
+ 2. Evaluate `epochs=1` vs `epochs=2` and `style_weight=0.1` vs `0.2`.
320
+ 3. Add targeted eval slices:
321
+ - no-issue cases
322
+ - valid-variation cases
323
+ - multi-issue cases
324
+ - low-confidence / low-pose-coverage cases
325
+ 4. Improve inference compatibility for the merged repo or support local merged-model inference directly.
326
+
327
+ ## Reproduction Commands
328
+
329
+ Build the grounded SFT dataset from run artifacts:
330
+
331
+ ```bash
332
+ uv run python scripts/build_coach_summary_sft_dataset.py
333
+ ```
334
+
335
+ Run the full Modal training flow:
336
+
337
+ ```bash
338
+ uv run modal run scripts/coach_summary_modal.py --stage all --epochs 2 --style-weight 0.2 --repo-id build-small-hackathon/pozify-coach-summary1
339
+ ```
340
+
341
+ Run the app against a cloud-supported fallback-safe runtime model:
342
+
343
+ ```bash
344
+ unset POZIFY_COACH_SUMMARY_MODEL
345
+ uv run python app.py
346
+ ```
347
+
348
+ Or set the runtime model explicitly:
349
+
350
+ ```bash
351
+ export POZIFY_COACH_SUMMARY_MODEL=Qwen/Qwen3-14B
352
+ uv run python app.py
353
+ ```
354
+
355
+ ## Conclusion
356
+
357
+ Pozify's coach-summary model training architecture is directionally strong. The core design choice
358
+ to train a grounded summary model on structured evidence, then gate it with a verifier, is the
359
+ right one for this product.
360
+
361
+ The current bottleneck is not lack of infrastructure. It is model reliability and inference
362
+ deployment maturity:
363
+
364
+ - too few grounded examples
365
+ - low schema-compliance rate
366
+ - no verifier passes in the latest visible eval
367
+ - published merged repo still not usable through the current HF inference path
368
+
369
+ The codebase is ready for the next iteration. The next high-leverage step is to improve dataset
370
+ size and output reliability while keeping the verifier and fallback architecture intact.