pareidolia / BLOG.md
AndresCarreon's picture
readme: hero GIF + demo video link + field report; add BLOG.md
7b25964 verified
|
Raw
History Blame Contribute Delete
5.24 kB
# The face was always there: building PAREIDOLIA with two small OpenBMB models
*A Build Small Hackathon field report β€” Thousand Token Wood.*
*Live: [build-small-hackathon/pareidolia](https://huggingface.co/spaces/build-small-hackathon/pareidolia)*
---
Pareidolia is the thing your brain does when it sees a face in a power outlet,
in the front of a car, in two windows and a door. Everyone has it. No app
celebrates it.
So we built one. Point your camera at any object. A small vision model studies
the photo the way you study clouds β€” and the face that was *already hiding* in
your fire hydrant opens its eyes, blinks at you, and tells you, in its own
voice, exactly what it has been putting up with.
> *"Forty years on this corner. Not one dog has shown me respect."*
Two models do all of it, and together they're about **11B parameters** β€” well
under the hackathon's 32B ceiling, and every parameter earns its place:
- **[openbmb/MiniCPM-V-4_5](https://huggingface.co/openbmb/MiniCPM-V-4_5)** (8.7B) β€” finds the face and writes the soul.
- **[openbmb/VoxCPM2](https://huggingface.co/openbmb/VoxCPM2)** (2.29B) β€” gives each object a distinct designed voice, from a text description alone, no reference audio.
## The one rule: taste from the model, facts from the code
The failure mode that kills a project like this is obvious once you hit it: no
vision model is *trained* to point at the two bolts on a hydrant and call them
eyes. Ask it for pixel coordinates and it will confidently place an eye in the
sky. A misplaced eye doesn't read as a quirky soul β€” it reads as a broken
sticker.
So we never let the model touch a coordinate. The sΓ©ance is one structured
generation: the model **names visible features** ("the two bonnet bolts," "the
front outlet cap"), reads the object's condition, and writes its grudge β€” then
deterministic OpenCV snaps those names onto the strongest real circles, blobs,
and corners nearby. The model brings taste; the code owns the facts. It's the
pattern this community already celebrates, and it's the whole reason the eyes
land on things that are really there.
The writing is governed the same way β€” not vibes, but a bank of grudge
archetypes keyed to an object's *visible condition* (the veteran/rusted, the
martyr/worn, the perfectionist/pristine, the diva/displayed), with an iron rule
that every line must reference something actually in the photo. A coffee mug
with a violin-shaped handle, unprompted: *"Why a violin? Why not a guitar?"*
## The shared wall, alive with zero GPU
Every awakened object joins a public **Menagerie** β€” one wall, shared by every
visitor. Because each record is deterministic, the overlays (the blinking, the
saccades, the mouth riding the audio) replay entirely client-side from JSON.
The landing page is fully alive even when the GPU is asleep, and every object
gets its own shareable page with a social preview card showing it *with its
eyes*. The GPU only wakes when you awaken something new.
Privacy is structural, not bolted on: the same generation gates real human
faces and NSFW before anything else runs, and nothing reaches the public wall
that hasn't passed that gate. No visitor identity is ever stored.
## What we tried, measured, and threw away
The honest part. We had two "obvious" upgrades and let live measurement veto
both:
- **A punch-up pass** that rewrote each grudge to be funnier. Tested live on six
real awakenings: zero rewrites better than the original, two grammatically
broken. Our acceptance check validated *form* (length, banned openers, cites a
specific) but couldn't see *coherence*. Reverted within the hour. A flat
original beats a broken rewrite.
- **A set-of-marks grounding flip** β€” let OpenCV draw numbered badges and have
the model pick numbers instead of inventing coordinates. It sounded purer. The
bench said no: **3/14** plausible faces versus **8/14** for the coarse-then-snap
flow. The model picked badges sitting on the pavement while confabulating names
for them. The real lesson: a vision model's coarse spatial *intuition*,
corrected by deterministic snapping, beats its discrete *selection* over
badly-curated choices.
Both are written up, with their data, in the repo's
[FIELD_NOTES.md](https://huggingface.co/spaces/build-small-hackathon/pareidolia/blob/main/FIELD_NOTES.md).
Every awakening's full trace β€” the model's JSON, the snap deltas, the chosen
voice β€” is published to a [public dataset](https://huggingface.co/datasets/AndresCarreon/pareidolia-menagerie).
## What shipped to make it survive a judging crowd
- A face-**geometry gate** that measures each placed face (eyes level? cramped?
mouth below? on the object?) and gives the model one in-context do-over when it
fails.
- A **health endpoint and an external watchdog** that auto-restarts the Space if
the ZeroGPU context ever wedges.
- Honest, retryable messaging when the free GPU quota is busy β€” *"the spirits are
overwhelmed; rest a moment and try again, or sign in for your own candle"* β€”
instead of a generic error.
It's small models, used carefully, doing something that genuinely couldn't exist
without them. Go wake something up. It was in there all along. πŸ‘οΈ