YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

SlowestLooser FoodJSON+Activity v2

HuggingFace: https://huggingface.co/Juhuu/slowestlooser-v2-4bit Published: 2026-05-13 Status: Active. Supersedes v1 (food-only).

What this model does

QLoRA fine-tune of mlx-community/Qwen3-1.7B-4bit that handles both the SlowestLooser food-text path AND the activity-text path. iOS routes by system prompt; the model emits the matching JSON schema.

  • Food queries (system: foodAnalysisSystemNoTools): CompositeDTO JSON with items[]
  • Activity queries (system: activityAnalysisSystem with embedded 40-entry MET catalog): Single object {"name", "minutes", "calories"} (multi-activity sums into one row)

Base model

mlx-community/Qwen3-1.7B-4bit (1.72B params, pre-quantized 4-bit MXFP)

Training (QLoRA via mlx-lm on M4 Pro)

Setting Value
Method QLoRA
Optimizer AdamW
Iterations 1500 (vs v1's 1000)
Batch size 4
Learning rate 2e-4
LoRA rank 32
LoRA target layers last 16 attention layers
Max seq length 2048
Trainable params 4.98M (0.29% of base)
Wall time 135 min
Peak memory 16.4 GB

Loss trajectory

Iter Val loss Train loss
1 2.892 β€”
500 0.068 0.073
1000 0.061 0.056
1500 0.046 0.047

Val loss still improving at iter 1500 β€” extending from v1's 1000 was worth it. v1 plateaued at val=0.053 (iter 900).

Dataset

4802 records (4321 train + 481 holdout).

Slice Records Share
Food 3644 84%
Activity 677 16%

Food dataset (unchanged from v1):

  • 38 curated DB entries oversampled to 20 variants each
  • 400 simple-label OFF entries Γ— 4 variants
  • 30% multi-ingredient queries; 60% include β‰₯1 curated seed

Activity dataset (new in v2):

  • 40-entry curated MET catalog (daily life β†’ endurance sports; broad β†’ specific)
  • 15 variants per activity via GPT-4o-mini synthesis (durations, intensity modifiers, Swiss German + English synonyms)
  • 10% multi-activity composites
  • Calorie targets computed deterministically: MET Γ— 70kg Γ— hours

See data/activity_catalog.json for the full 40-entry MET catalog used in both training data and the iOS system prompt.

Eval: Matrix sweep against iOS QualitySpec (real production prompts)

Real prompts mirrored from SlowestLooser/Services/QualitySpecs.swift::QualitySpec.all.

Food (39 prompts)

Base Qwen3 1.7B v1 FT v2 FT
Valid JSON 1/39 (3%) 39/39 (100%) 39/39 (100%)
Avg latency 3.10s 1.69s ~2.4s

Activity (19 prompts; one empty-string prompt skipped)

v2 FT
Valid JSON 19/19 (100%)
Avg latency ~0.7s (no DB prefetch needed)

Single-activity calorie sanity

The v2 model emits deterministic, MET-formula-correct calories:

Prompt Output Expected Status
Joggen / 30 min Joggen 30min / 245kcal 7.0 Γ— 70 Γ— 0.5 = 245 exact
Velofahren 30min / 210kcal 6.0 Γ— 70 Γ— 0.5 = 210 exact
Schwimmen 30min / 280kcal 8.0 Γ— 70 Γ— 0.5 = 280 exact
HIIT 30min / 350kcal 10.0 Γ— 70 Γ— 0.5 = 350 exact
Sprinten 30min / 420kcal 12.0 Γ— 70 Γ— 0.5 = 420 exact
1 Stunde Velo 60min / 420kcal 6.0 Γ— 70 Γ— 1.0 = 420 exact
45 Minuten Schwimmen 45min / 385kcal 8.0 Γ— 70 Γ— 0.75 = 420 ~ 9% under
2h Wandern 120min / 700kcal 5.5 Γ— 70 Γ— 2 = 770 ~ 9% under
Spazieren 30min / 122kcal 3.5 Γ— 70 Γ— 0.5 = 122.5 exact

Multi-activity calorie sums

Less precise β€” model interpolates between known activities:

Prompt v2 Output Catalog-strict sum
Joggen und Schwimmen 60min / 595kcal 245 + 280 = 525
30 min Velo dann 15 min Joggen 60min / 560kcal 210 + 122.5 = 332.5

Acceptable for ship; could tighten in v3 with more multi-activity training samples.

Drift comparison (the v1 production motivation)

Activity calorie variance for "30 min Joggen" in v1.30.x production releases:

Release Output Source
v1.30.1 168 Base Qwen
v1.30.3 147 OpenAI (consistent across runs)
v1.30.4 140 Base Qwen
v1.30.5 110 Base Qwen β€” drift continued
v2 FT 245 Deterministic

v2 emits the canonical MET-formula answer (245) on every run.

Known issues

  • g_wasser filtering (carried over from v1) β€” water entry with 0 kcal gets filtered by load_vector_index. Query "Wasser" matches "Birken Wasser" from BM25. Relax to cals < 0 in v3.
  • dl unit not parsed (carried over from v1) β€” 1.5dl Milch embeds quantity in name. Add dl/cl to QuantityParser.
  • Multi-activity calorie sum is approximate β€” see table above. ~12% over on tested cases. Acceptable for ship but could tighten with more multi-activity training data.
  • 2h Wandern slight under-estimate β€” model used MET=5 instead of catalog 5.5 (700 vs 770 kcal).

Notes on design

  • Design B chosen for activity MET routing: 40-entry catalog embedded in system prompt (compact Name=MET comma-separated, ~250 tokens). Avoided full RAG (Design C) β€” Swift-side activity matcher would have added infrastructure for a 40-entry static dataset.
  • MET catalog Python ↔ Swift byte-equal: prompt.py::SYSTEM_ACTIVITY and PromptTemplates.swift::activityAnalysisSystem are intentionally byte-equal. Training prompt = production prompt = no drift.
  • One combined model (vs two separate adapters): saves a download + a model load on iOS. The 1.7B has capacity for both schemas.

Commits

  • Activity training + model card scaffolding: b4ee122
  • 40-entry catalog + Design B compact MET prompt: 8011d10 (Python) + a6a4eef (iOS)
  • v2 dataset + training: (commit hash after this docs commit)

Why retired v1

v1 was food-only. Users were typing "30 min joggen" and getting drifting calorie values (168/140/110 across releases). v2 trains one combined model on both schemas with deterministic calorie math baked in.

Downloads last month
27
Safetensors
Model size
0.3B params
Tensor type
BF16
Β·
U32
Β·
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support