| ---
|
| title: FormScout
|
| emoji: ποΈ
|
| colorFrom: green
|
| colorTo: green
|
| 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).
|
|
|