Spaces:
Running
Running
File size: 10,869 Bytes
b2ebfa6 b43c522 b2ebfa6 32e0771 9f98f96 b2ebfa6 181dd78 b2ebfa6 181dd78 f9f4f9a 181dd78 c33e98e f9f4f9a b2ebfa6 181dd78 b2ebfa6 181dd78 b2ebfa6 181dd78 b2ebfa6 181dd78 b2ebfa6 f9f4f9a 181dd78 0446dcd 181dd78 80dfdac 181dd78 b2ebfa6 181dd78 b43c522 181dd78 0446dcd f9f4f9a 181dd78 b43c522 f9f4f9a b2ebfa6 181dd78 b2ebfa6 181dd78 b2ebfa6 181dd78 b2ebfa6 181dd78 b2ebfa6 181dd78 b2ebfa6 181dd78 f9f4f9a 181dd78 b2ebfa6 181dd78 b2ebfa6 b43c522 181dd78 b43c522 181dd78 0446dcd 181dd78 0446dcd 181dd78 b43c522 b2ebfa6 181dd78 0446dcd 181dd78 f9f4f9a 181dd78 f9f4f9a 181dd78 b2ebfa6 181dd78 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | ---
title: PawMap
emoji: πΎ
colorFrom: green
colorTo: green
sdk: docker
app_file: app.py
pinned: true
license: mit
short_description: Collaborative stray animal mapping with AI
tags:
- stray-animals
- animal-welfare
- maps
- computer-vision
- small-models
- gradio
- build-small-hackathon
- track:backyard
- sponsor:nvidia
- achievement:offbrand
- achievement:sharing
- backyard-ai
- leaflet
- cosine-similarity
models:
- meta-llama/Llama-3.2-11B-Vision-Instruct
- nvidia/Nemotron-Mini-4B-Instruct
- sentence-transformers/all-MiniLM-L6-v2
---
# PawMap πΎ β Collaborative stray animal mapping with AI
Take a photo of the stray animal you just spotted. The AI identifies species, breed and color β and checks if it's already been registered before.
Over time, the map tells each animal's story: where it shows up, who helped, whether it's doing okay.
Built for the [**Build Small Hackathon 2026**](https://huggingface.co/build-small-hackathon) Β· **Backyard AI** track π‘
**Try it:** [live Space](https://huggingface.co/spaces/build-small-hackathon/viralata-mapper) Β· **Traces:** [dataset on the Hub](https://huggingface.co/datasets/build-small-hackathon/viralata-mapper-storage)
> π¬ **Demo video:** `TODO β paste your YouTube / Vimeo / Loom link here before submitting`
> π£ **Social post:** `TODO β paste your X / LinkedIn / Bluesky / Mastodon post link here before submitting`
---
## The Problem
BrasΓlia, DF β the capital of Brazil β has thousands of stray dogs and cats scattered across its residential wings, parking lots and green areas. Independent rescuers know each animal by nickname, by street, by habit. But that knowledge lives in WhatsApp groups, in individual memory, nowhere persistent.
The friend who inspired this app has been feeding a colony of cats near the Asa Norte commercial strip for years. She knows exactly which ones have been neutered, which ones have a history of injury, which one vanished last month. But when someone new wants to help β or when she needs backing to request food donations β there's nothing to show. No map, no timeline, no proof that a specific animal has been living on that block for two years.
**PawMap is that record.** Anyone takes a photo of a stray animal with their phone. The AI identifies it, GPS pins the location, and the app checks whether that animal has been seen before β linking all sightings to its profile. The map is public. The animal's trail becomes visible. Anyone who wants to help knows exactly where to go.
---
## How it works
There are two AI-powered flows: **registering a sighting** and **recording help**.
### Sighting flow
```mermaid
flowchart TD
A["π· Photo from phone"] --> B["π€ Vision AI\nLlama-3.2-11B-Vision\n(NVIDIA NIM / HF)"]
B -->|"is it an animal?"| C{Animal detected?}
C -->|"No"| ERR["β Error message\n'No dog or cat identified'"]
C -->|"Yes"| D["π Structured JSON\nNemotron Mini 4B Instruct structures\nspecies Β· breed Β· color Β· condition Β· marks"]
D --> E["π’ Semantic embedding\nall-MiniLM-L6-v2 Β· 384 dim\n(local, 22M params)"]
E --> F{Cosine similarity\nβ₯ 0.80?}
F -->|"Yes β known animal"| G["β New sighting\nadded to existing animal"]
F -->|"No β new animal"| H["π New animal\nregistered in the database"]
G --> I["πΎ SQLite"]
H --> I
I --> J["πΊοΈ Leaflet map\nprofiles Β· trail Β· gallery"]
```
Before confirming, the user sees the top 3 most similar animals already in the database β they can edit what the AI detected, give the animal a name, and note its condition. Only then is the sighting saved.
### Help flow
When someone wants to help an animal, they can submit a **help proof** β a photo showing they fed it, treated a wound, or got it to a vet. The AI does two things with that photo:
```mermaid
flowchart TD
A["π· Help proof photo\n(optional)"] --> B["π€ Vision AI\nanalyzes the new photo"]
B --> C["π’ New embedding\ngenerated from description"]
C --> D{Cosine similarity\nagainst registered animal?}
D -->|"Match β₯ 0.80\nsame animal ID"| E["β
AI-verified\nmatch score shown"]
D -->|"No match"| F["β οΈ Unverified\nstill recorded"]
B --> G{Condition improved?}
G -->|"e.g. injured β healthy"| H["π Condition update\nlogged on profile"]
G -->|"same or worse"| I["No change"]
E --> J["πΎ Help event saved\nto sightings table"]
F --> J
H --> J
I --> J
```
The profile page shows the full help history with photos, help type (fed / treated / rescued / other), AI verification status and any detected condition improvement.
The map uses color to signal urgency: **π’ green** = dog Β· **π orange** = cat Β· **π΄ red** = not seen in +30 days.
---
## What's inside
| Component | Model / Library | Where it runs |
|---|---|---|
| Visual identification | **Llama-3.2-11B-Vision-Instruct** (11B) via NVIDIA NIM (or HF Serverless) | remote API |
| Text reasoning / JSON | **Nemotron Mini 4B Instruct** via NVIDIA NIM | remote API |
| Semantic embedding | **all-MiniLM-L6-v2** (384 dim, 22M params) | CPU, local |
| Animal matching | Cosine similarity (threshold 0.80) | CPU, local |
| Database | SQLite | local / persistent |
| Frontend | SPA via `gradio.Server` + Leaflet.js + Lucide Icons | browser |
**Total parameters running locally: ~22M** (MiniLM). The vision and reasoning models run via serverless API β nothing heavy on the Space machine. **Every model used is well under the 32B hackathon cap:** Llama-3.2-11B-Vision (11B), Nemotron Mini 4B Instruct (4B) and MiniLM-L6-v2 (22M).
---
## Screens
| Screen | Description |
|---|---|
| πΊοΈ **Map** | Color-coded pins by species/urgency, floating card with "View profile" |
| π· **Register** | Photo upload + automatic GPS + AI analysis |
| π€ **Analysis** | Auto-identification with editable fields + top 3 similar animals |
| β
**Confirm** | Sighting summary before saving |
| ποΈ **Spotted** | List of all registered animals |
| πΎ **Profile** | Full animal card with gallery, map trail and help history |
---
## Badges
This submission earns the following hackathon bonus quests:
- π¨ **Off-Brand** β Fully custom interface via `gradio.Server`, no default Gradio components visible. SPA frontend with Leaflet.js for the map, Lucide Icons, and custom design.
- π‘ **Sharing is Caring** β Full traces of every sighting (photo β AI analysis β embedding β matching result) are automatically published as a dataset on the Hub via `/admin/push-traces`.
- π€ **Tiny Titan** β The only on-device model is `all-MiniLM-L6-v2` (22M params, far under 4B): all animal matching runs locally on a tiny embedding model.
- π© **NVIDIA / Nemotron** β Structured identification is normalized by `Nemotron-Mini-4B-Instruct` via NVIDIA NIM β small (4B), well under the 32B cap.
---
## Running locally
```bash
git clone https://huggingface.co/spaces/build-small-hackathon/viralata-mapper
cd viralata-mapper
pip install -r requirements.txt
# Recommended: NVIDIA NIM powers both vision (Llama-3.2-11B-Vision) and Nemotron Mini 4B
NVIDIA_API_KEY=nvapi_... python app.py
# Alternative: vision via HuggingFace Serverless
HF_TOKEN=hf_... python app.py
# no key β runs in fallback mode without AI identification
python app.py
# open http://localhost:7860
```
On first run the app seeds the database with demo animals around BrasΓlia so the map isn't empty.
---
## Space configuration
### Secrets
| Secret | Description |
|---|---|
| `NVIDIA_API_KEY` | NVIDIA NIM key β powers **both** vision (Llama-3.2-11B-Vision) and Nemotron Mini 4B normalization. A single key is enough. |
| `HF_TOKEN` | Optional β vision via HF Serverless if you don't use NVIDIA NIM |
| `MATCH_THRESHOLD` | Optional. Similarity threshold. Default: `0.80` |
| `HF_DATASET_ID` | Optional. Hub dataset for trace publishing (e.g. `org/dataset-name`) |
> Without a Vision AI key the app runs in fallback mode β registration and matching still work, but automatic breed/color/condition identification is disabled.
### Persistent Storage
Set up a **Persistent Storage Bucket** in the Space and mount it at `/data/` so photos and the database survive restarts. Without it, all data is wiped on each deploy.
---
## Repository structure
```
.
βββ app.py # Entrypoint β FastAPI routes + Gradio Server
βββ requirements.txt
βββ Dockerfile
βββ index.html # SPA frontend
βββ static/
β βββ app.js # Client logic (map, camera, registration flow)
β βββ style.css
β βββ lottie/ # Loading animations
βββ core/
β βββ ai.py # Vision AI (HF or NVIDIA NIM) + embeddings
β βββ database.py # SQLite β animals and sightings
β βββ matcher.py # Cosine similarity for animal matching
β βββ seed.py # Demo data for the initial map (BrasΓlia, DF)
β βββ tracer.py # Trace logging + push to HF Hub
βββ db/
β βββ schema.sql # Database schema
βββ data/ # Runtime β SQLite database + photos + traces
βββ viralata.db
βββ photos/
βββ traces.jsonl
```
---
## Limitations
- **Vision AI via API** β breed identification requires `HF_TOKEN` or `NVIDIA_API_KEY`. Without a key, registrations use generic data (breed "SRD / Domestic Shorthair").
- **GPS on mobile** β accuracy depends on the device. Indoors or with weak signal, coordinates may be imprecise.
- **Matching is not foolproof** β the 0.80 threshold is conservative to avoid false positives, but two very similar animals (e.g. two caramel SRDs) may get grouped together. The user reviews the candidates before confirming and can correct.
- **Portuguese / English only** β the interface is in Portuguese; the AI generates descriptions in English for embedding consistency.
---
## Credits
- **[Meta](https://ai.meta.com/llama/)** β Llama 3.2 11B Vision Instruct (Llama 3.2 Community License).
- **[NVIDIA](https://build.nvidia.com/)** β Nemotron Mini 4B Instruct via NVIDIA NIM.
- **[Hugging Face](https://huggingface.co/)** β `sentence-transformers/all-MiniLM-L6-v2`, Serverless Inference, Space hosting.
- **[Leaflet.js](https://leafletjs.com/)** β interactive map.
- **[Gradio](https://gradio.app/)** β `gradio.Server` for the custom frontend.
- **[Lucide Icons](https://lucide.dev/)** β UI icons.
---
## License
MIT for the application code. Models follow their own licenses β see the Meta (Llama 3.2) and NVIDIA (Nemotron Mini 4B Instruct) model cards for full terms.
---
*Built for BrasΓlia, DF β capital of Brazil β and any city that wants to map its stray animals.* πΎ
|