| --- |
| title: FormScout |
| emoji: ποΈ |
| colorFrom: green |
| colorTo: yellow |
| sdk: gradio |
| app_file: app.py |
| pinned: false |
| license: apache-2.0 |
| short_description: FMS video scoring β movement screen aid |
| --- |
| |
| # FormScout |
|
|
| FMS (Functional Movement Screen) scoring pipeline β a screening aid that scores movement videos 0β3 per test with a written rationale and annotated overlay. |
|
|
| **β οΈ Screening aid β not a diagnosis. Pain or clearing tests require a clinician.** |
|
|
| ## Running locally |
|
|
| ### 1. Clone and install |
|
|
| ```bash |
| git clone https://huggingface.co/silas-therapy/small-functional-movement-screening |
| cd small-functional-movement-screening |
| python3 -m venv .venv && source .venv/bin/activate |
| pip install -r requirements.txt |
| ``` |
|
|
| ### 2. Start the VLM judge (optional but recommended) |
|
|
| The judge uses Qwen3-VL-8B-Instruct via llama.cpp. Without it the app falls back to the deterministic rubric score β fully functional, no GPU needed. |
|
|
| ```bash |
| # Install llama.cpp once |
| brew install llama.cpp |
| |
| # Download the model (one-time, ~6 GB) |
| python3 -c " |
| from huggingface_hub import hf_hub_download |
| for f in ['Qwen3VL-8B-Instruct-Q4_K_M.gguf', 'mmproj-Qwen3VL-8B-Instruct-F16.gguf']: |
| hf_hub_download('Qwen/Qwen3-VL-8B-Instruct-GGUF', f, local_dir='checkpoints/qwen3-vl') |
| " |
| |
| # Start the server (keep this terminal open) |
| ./scripts/serve_judge.sh |
| ``` |
|
|
| To use a fine-tuned GGUF instead of the default: |
| ```bash |
| FORMSCOUT_JUDGE_GGUF=/path/to/finetuned.gguf ./scripts/serve_judge.sh |
| ``` |
|
|
| ### 3. Launch the Gradio app |
|
|
| ```bash |
| python3 app.py |
| # β http://127.0.0.1:7860 |
| ``` |
|
|
| Upload a video, select the FMS test from the dropdown, and click **Analyze**. |
|
|
| ### 4. Headless pipeline (no Gradio) |
|
|
| ```bash |
| python3 -m formscout.run sample.mp4 |
| ``` |
|
|
| ### 5. Tests |
|
|
| ```bash |
| pytest tests/ -v |
| ``` |
|
|
| ### 6. Upload to Hugging Face |
|
|
| ```bash |
| # Pushes source to both model repo and Space, opens a PR on each |
| ./scripts/hf_upload.sh |
| |
| # Or with a custom commit message |
| ./scripts/hf_upload.sh "feat: my change" |
| ``` |
|
|
| ## Architecture |
|
|
| Typed specialist agents orchestrated by a deterministic Director: |
|
|
| ``` |
| Ingest β Pose2D β [Body3D optional] β Biomechanics β Rubric Score β [Judge] β Report |
| ``` |
|
|
| | Agent | Model | Status | |
| |---|---|---| |
| | Pose2D | YOLO26l-Pose (0.026B) + MediaPipe fallback | β
| |
| | Body3D | SAM 3D Body DINOv3 (0.84B) | gated, off by default | |
| | Judge + Classifier | Qwen3-VL-8B-Instruct via llama.cpp (8B) | β
| |
| | Scoring Head | ST-GCN (0.03B) | Phase 3 | |
| | Retrieval | Qwen3-VL-Embedding-8B (8B) | Phase 3 | |
|
|
| See [CLAUDE.md](CLAUDE.md) for full architecture and invariants. |
|
|
| ## Feature flags (`formscout/config.py`) |
|
|
| | Flag | Default | Meaning | |
| |---|---|---| |
| | `ENABLE_JUDGE` | `True` | VLM judge via llama-server; rubric fallback when server is down | |
| | `ENABLE_3D` | `False` | SAM 3D Body β off until integrated | |
| | `ENABLE_STGCN` | `False` | Phase 3 | |
| | `ENABLE_RAG` | `False` | Phase 3 | |
|
|
| ## Model budget |
|
|
| ~18B params total (under 32B cap). See [MODEL_BUDGET.md](MODEL_BUDGET.md). |
|
|
| ## License |
|
|
| Apache-2.0. Built for the Build Small Hackathon (Backyard AI track). |
|
|