-
-
A six-step guided tour, opt in. It never opens itself, Escape leaves it, and it works by keyboard alone.
-
Photos in, a closed vocabulary out. The model proposes a constrained scene graph, never free-text coordinates.
-
Correct anything by dragging. Confirming a field is not the same as verifying it, and the app says so on screen.
-
The wait estimate comes from real completed renders, and says how many cases it counted rather than inventing a range.
-
Rendering runs as a background job the page submits and polls, because a real illustration takes minutes.
-
Both layers side by side. The schematic carries the facts, the generated clip carries visual style only.
-
Content-addressed on Backblaze B2, with the authorship split sealed: what we computed, and what the model contributed.
-
Press Verify: 18 named server-side checks re-run from the stored bytes, all passed.
-
A sealed case is a link that still works next week. This one was reopened from it, sealed files and all.
-
Ports and adapters: a live vision ladder, a deterministic renderer, real Backblaze B2, and Genblaze seeded from our own raster.
-
Extraction accuracy on the record, with its own honest scope note: a staged eval set, and real phone photos score lower.
Inspiration
After a crash, the first job is documentation: which cars, which damage, which road, what happened. People already photograph the scene on their phones. The gap is turning those photos into something a claims handler or an insurer can read and trust.
Generative video makes that easy to fake and hard to trust. A convincing AI "reconstruction" that is actually a guess is worse than nothing in a claim or a courtroom. Insurers are already warning about AI-generated images in fraudulent claims, and courts are debating new rules for machine-generated evidence. So we built the opposite of a black box: an app where the factual layer is deterministic, the generative layer is clearly labeled as illustration, and every input and output is sealed with provenance you can verify yourself.
What it does
ClaimScene turns accident photos into a documented case:
- Extract. A vision-language model reads the photos into a strict, constrained scene description: vehicles and their damage (by clock position), the road layout, each vehicle's approach and maneuver, and the impact points. No free-form coordinates, only a fixed vocabulary the model must answer in.
- Review and adjust. You see the extracted scene and correct it with simple controls (dropdowns, a 12-position clock picker), and a top-down schematic redraws live as you edit. The AI proposes; you confirm. Nothing is generated from an unreviewed guess.
- Render. A deterministic layout engine turns the confirmed scene into an animated top-down schematic, the factual layer, watermarked "ILLUSTRATION — NOT EVIDENCE" on every frame. Then a raster of that same schematic seeds a short Genblaze illustration clip, clearly disclosed as AI-generated. The seed is our own deterministic drawing, not a generated still, because a live render proved a diffusion model does not reliably preserve the layout it is given.
- Seal. Every input photo, the schematic, the illustration, and an incident report are stored content-addressed on Backblaze B2 and sealed into a SHA-256 manifest that records, per input, where it came from (uploaded, staged, public-domain, or synthetic) and its license. You can re-verify the seal in the browser.
The public demo runs on synthetic and staged photos only. No real accident imagery or personal data.
How we built it
Ports and adapters, offline-first, so the whole pipeline including the real SHA-256 provenance runs in CI with zero credentials. The orchestrator depends on four ports: a VisionExtractor, a MediaProvider, a StorageBackend, and a SchematicRenderer. Live adapters wrap a GMI Cloud VLM (through an OpenAI-compatible client) and a real Genblaze Pipeline writing to Backblaze B2; deterministic fakes implement the same ports for tests and the offline demo. A FastAPI service exposes it, a React and TypeScript frontend ships in the same container on Cloud Run, and every backend is used only when its credentials are present, otherwise the app degrades transparently and never 500s.
The anti-hallucination core is the constrained vocabulary. We never ask the model for pixel coordinates. We ask for enums (approach direction, maneuver, damage clock position, road template), validate the answer against a strict schema with one repair round-trip, and let a deterministic layout engine place everything. That is what makes the human review step small and the schematic trustworthy.
How it uses Backblaze B2
- Every artifact lands on B2 under content-addressed keys: input photos, the schematic animation, the illustration still and clip, the report, and the manifest.
- The sealed manifest records per-input source and license attribution (uploaded / staged_demo / public_domain / licensed / synthetic_generated), so the case says where every pixel came from. Provenance of the inputs, not just the outputs.
- A durable JSONL index catalogues every object with size and content type, a queryable case ledger across the whole store.
- The live playback route mints fresh presigned GET URLs per request (region and SigV4 correct), so nothing signed is ever stored and the manifest hashes stay canonical.
How it uses Genblaze
- Illustration generation is a real Genblaze Pipeline: a raster of the case's own deterministic schematic, seeded into an image-to-video clip (pixverse-v6-i2v by default, Kling-Image2Video-V2.1-Master as a premium option).
- Genblaze's ObjectStorageSink content-addresses each generated asset, persists it to B2, and seals a per-asset SHA-256 manifest, which ClaimScene folds into the case-level manifest.
- Every Genblaze call is contract-tested in CI against the published SDK, including an assertion that input assets actually reach the pipeline step, so API drift fails the build instead of the demo.
AI providers and models used
| Role | Model | Provider |
|---|---|---|
| Scene extraction (primary) | google/gemma-4-31b-it | GMI Cloud |
| Scene extraction (fallback) | google/gemini-3.5-flash | GMI Cloud |
| Scene extraction (independent fallback) | Qwen/Qwen2.5-VL-72B-Instruct | Nebius |
| Illustration seed still | none, it is a raster of our own schematic | computed locally, no model |
| Illustration clip (image-to-video) | pixverse-v6-i2v (default) / Kling-Image2Video-V2.1-Master (premium) | GMI Cloud via Genblaze |
Measured extraction accuracy
The primary VLM (google/gemma-4-31b-it) scores 100% weighted field accuracy on a committed 7-scenario evaluation set: vehicle count, kind and color, road layout and signal, approach and maneuver, and damage and impact clock positions within one hour. The eval set is staged toy-diorama photos (three consistent seedream-rendered views per scenario) with hand-authored ground truth, sealed as synthetic_generated. It is self-consistent by construction, and we say so in the README, but it makes the accuracy claim reproducible from the repo.
Challenges we ran into
The honest lesson came from the live path. Our contract tests run against the real Genblaze SDK, but its mock provider does no server-side validation, so a step that never attached its input image can pass every test and only fail live. We had hit exactly that class of bug on a sibling project, so here we wrote the contract test to assert the input assets reach the pipeline step, and it held. We also learned that region-less presigned URLs 401 on B2, that a brand-new cloud project needs a minute for its build service agent to provision, and that a multi-minute live render must use the direct origin rather than a 60-second edge proxy.
Accomplishments that we're proud of
- Provenance that covers inputs, not just outputs: the manifest says where every photo came from and under what license.
- A measured accuracy number (100% on the committed set) instead of a vibe.
- A human-in-the-loop review step that is the trust story and the production-readiness story at once.
- A sealed AI→human approval receipt: the render seals the exact proposed→confirmed scene diff with a recomputable
decision_digestthat self-voids if the confirmed scene drifts, and the whole case re-verifies from stored bytes through a named-check receipt (GET /cases/{id}/verify) plus a detached, self-sealed receipt written as its own B2 object. - over 550 backend tests plus over 350 frontend tests and 38 real-browser specs, gitleaks, CodeQL and a machine-checkable readiness gate, all runnable with zero credentials.
What we learned
Constrain the model to a vocabulary and let deterministic code do the geometry. Label the generative layer loudly. And make honesty a data structure: a sealed manifest that records sources and disclosure by construction, not a promise in the footer.
What's next for ClaimScene
First-notice-of-loss integrations, multi-incident case files, a reviewer audit trail, and more Genblaze providers behind the same port. The wedge is any workflow where a synthetic image must be self-disclosing: insurance, fleet safety, and legal intake.
Built With
- backblaze-b2
- computer-vision
- fastapi
- ffmpeg
- genblaze
- gmi-cloud
- google-cloud-run
- insurtech
- provenance
- python
- react
- typescript

Log in or sign up for Devpost to join the conversation.