| --- |
| title: curbcheck |
| emoji: 🅿️ |
| colorFrom: red |
| colorTo: gray |
| sdk: gradio |
| app_file: app.py |
| pinned: true |
| license: mit |
| tags: |
| - build-small-hackathon |
| - backyard-ai |
| - vision-language-model |
| - qlora |
| - qwen2.5-vl |
| - track:backyard |
| - sponsor:modal |
| - achievement:welltuned |
| - achievement:fieldnotes |
| short_description: Can a small VLM tell you if you can legally park in SF? |
| --- |
| |
| # 🅿️ curbcheck |
|
|
| **Can a small vision-language model tell you if you can legally park in San Francisco?** |
|
|
| Upload a photo of a parking-sign pole, pick a day and time, and a QLoRA-tuned |
| **Qwen2.5-VL-3B** reads each sign into structured rules. A tiny deterministic resolver |
| then applies them to that moment and returns the verdict, showing you *both* what the |
| model read and why. Read-then-resolve: the VLM only perceives; the logic is exact. |
|
|
| I came to SF for a week in April 2026 and left with two parking tickets, both because I |
| couldn't parse a pole holding four stacked signs. curbcheck is the model that gets it. |
|
|
| ## Demo video |
|
|
| <video controls src="https://huggingface.co/spaces/build-small-hackathon/curbcheck/resolve/main/curbcheck_demo.mp4"></video> |
|
|
| [▶ Watch the demo](https://huggingface.co/spaces/build-small-hackathon/curbcheck/resolve/main/curbcheck_demo.mp4) |
|
|
| ## Track & badges |
|
|
| - **Track:** Backyard AI (a real, local, personal problem solved with a small model) |
| - A 3B model, well under the 32B cap, runs on ZeroGPU. |
|
|
| ## How it works |
|
|
| ``` |
| photo ─▶ VLM (reads each sign to JSON) ─▶ deterministic resolver ─▶ verdict + reason |
| ``` |
|
|
| - The model only **reads** the pole into structured restrictions (kind, days, hours, limits, permits). |
| - A deterministic resolver (`rules.py`, no model in the loop) applies them to the current time. |
| - Both halves are shown, so misreads are visible, not buried in a confident sentence. |
|
|
| ## The result |
|
|
| A stock Qwen2.5-VL-3B scores 0.16 on "can I park here right now", below random. One QLoRA |
| run takes it to **0.82 reasoning** and **0.98 read accuracy** on the synthetic benchmark; on |
| real SF photos the read-then-resolve pipeline reasons at **0.89**. |
|
|
| Full benchmark, training, and honest results: **https://github.com/shubhamgoel27/curbcheck** |
|
|
| ## Results in brief |
|
|
| | | base Qwen2.5-VL-3B | tuned (QLoRA) | |
| |---|:---:|:---:| |
| | Read F1 (synthetic) | 0.34 | **0.98** | |
| | Reasoning (synthetic) | 0.16 | **0.82** | |
| | Read F1 (real SF photos) | 0.04 | **0.34** | |
| | Pipeline reasoning (real) | 0.78 | **0.89** | |
|
|
| The honest part: more real data barely moved real-photo reading (0.33 to 0.34), so that gap |
| is model capacity, not data volume. The deterministic resolver keeps pipeline reasoning at |
| 0.89 even when reading is hard. Full, honest results in the repo. |
|
|
| ## Links |
|
|
| - **Live demo (this Space):** https://huggingface.co/spaces/build-small-hackathon/curbcheck |
| - **Demo video:** https://huggingface.co/spaces/build-small-hackathon/curbcheck/resolve/main/curbcheck_demo.mp4 |
| - **Code + benchmark (GitHub):** https://github.com/shubhamgoel27/curbcheck |
| - **Fine-tuned model (QLoRA adapter):** https://huggingface.co/shubhamgoel27/curbcheck-qwen25vl3b-v4-lora |
| - **Base model:** https://huggingface.co/Qwen/Qwen2.5-VL-3B-Instruct |
| - **Writeup:** https://shubham.gg/artifold-share/30da5524.html |
| |