Download README.md from Yoad22/surfmatch: direct link, hf CLI and curl.
- Browser
- Download file 4.44 kB
-
https://huggingface.co/spaces/Yoad22/surfmatch/resolve/main/README.md
- Command line
-
hf download hf://spaces/Yoad22/surfmatch/README.md
-
curl -L -o README.md https://huggingface.co/spaces/Yoad22/surfmatch/resolve/main/README.md
A newer version of the Gradio SDK is available: 6.30.0
title: SurfMatch
emoji: 🏄
colorFrom: blue
colorTo: red
sdk: gradio
sdk_version: 5.9.1
app_file: app.py
pinned: false
SurfMatch
Dataset: Yoad22/surfmatch-dataset - 15,000 synthetic rider profiles, 150-board catalog Embedding model: sentence-transformers/all-mpnet-base-v2 - 768-dimensional embeddings Generation model: Qwen/Qwen3-1.7B - structured custom board spec + rationale Space: https://huggingface.co/spaces/Yoad22/surfmatch
What This Is
A surfboard recommendation app. Tell it your height, weight, skill level, current board, typical conditions, and what you're trying to achieve, and it returns the 3 closest-matching boards from a 150-board catalog, plus a 4th board that a small language model designs specifically for you, including dimensions, tail, fins, construction, and a written rationale.
The app is built to also serve surfers who want to change styles, not just riders shopping within the style they already have.
How It Works
1. Category is decided from the rider's stated goal and skill level using a fixed rule, not from text similarity. Testing embeddings for this decision directly (see Key Results) showed they aren't reliable enough for it on their own.
2. Physical fit combines two real sizing guidelines: heavier and less experienced riders need more volume, and taller and less experienced riders want relatively more length, each measured as a percentile within the board's own category (categories differ hugely in scale, so raw liters or feet aren't comparable across them).
3. Embedding similarity (all-mpnet-base-v2) ranks boards within the already-correct category by how well a rider's profile matches each board's description - the comparison the model is demonstrably good at.
4. Diversity picks the final 3 boards so they differ from each other on tail, fins, or construction, instead of returning 3 near-identical boards.
5. The 4th board is generated by Qwen3-1.7B: given the rider's percentiles and the category's real dimension ranges, the model is asked to reason about the right sizing in words first, then commit to dimensions, tail, fins, construction, and a rationale, as structured JSON. It's explicitly allowed to make unconventional choices (e.g. quad fins on a longboard) that the fixed 150-board catalog doesn't offer.
Key Results
| Metric | Value |
|---|---|
| Boards in catalog | 150 |
| Rider profiles generated | 15,000 |
| Embedding model hit_rate@1 (vs. 20% random baseline) | 41.6% |
| Embedding model hit_rate@3 (vs. 49% random baseline) | 45.0% |
| Silhouette score by true category (PCA-50 space) | 0.053 |
| Diversity: hit real per-category ceiling on tail | 100.0% |
| Diversity: hit real per-category ceiling on fins | 97.3% |
| Diversity: hit real per-category ceiling on construction | 96.3% |
| Diversity: hit the ceiling on all three at once | 93.7% |
| Custom board JSON parse rate | ~90% |
The embedding model captures real signal about a rider's best-fit category (41.6% top-1 accuracy against a 20% random baseline), but that signal is not clean enough to decide the category on its own - the silhouette score of 0.053 confirms categories overlap heavily in embedding space. That's why category is decided by a fixed rule and embeddings are used only to rank within a category, where they change at least one of the three recommended boards for roughly half of all riders tested - real, independent work, not a no-op.
An Honest Limitation
The custom board generator's written reasoning (sizing_reasoning) explicitly and correctly
describes how a rider's weight and height percentiles should affect the board's dimensions in
nearly every case. But across three separate real experiments at 30-rider scale - raw
numbers, percentile-grounded numbers, and percentile-grounded numbers with forced
reasoning-before-numbers - the model's actual output dimensions barely correlated with
weight or height (correlation near 0 each time), while skill-based sizing worked reliably
and correctly (correlation consistently and correctly signed). In other words: this small
model's stated reasoning is not fully faithful to what actually drives its numeric output.
This is a genuine, tested limitation of a 1.7B-parameter model on this task, documented here
rather than hidden - the skill-based sizing and the category/tail/fins/construction choices
all work as intended.