Spaces:
Running on Zero
A newer version of the Gradio SDK is available: 6.26.0
title: Animap Inference
emoji: π
colorFrom: green
colorTo: gray
sdk: gradio
sdk_version: 5.49.1
app_file: space_app.py
python_version: 3.12.12
pinned: false
license: apache-2.0
short_description: Livestock models that refuse to invent a result.
Animap inference
This runs validated livestock models against farm photographs and returns what
the model actually produced. Its most important property is what it refuses:
a capability with no checksummed artefact behind it answers unavailable, not a
placeholder and not a plausible-looking number.
Twenty-eight capabilities are registered. Two run. cattle_detection and
poultry_count execute a YOLOX-m ONNX artefact whose sha256 is verified against
its model card at start-up. The other twenty-six say so plainly, which is the
honest answer rather than a gap.
The source is services/inference in the Animap repository. app.py mounts
app.main:app β the same FastAPI service the Azure Container App runs β under a
Gradio page, so /health, /capabilities and /jobs behave exactly as they do
in production and the page is a demonstration of them.
It was a Docker Space until 2026-08-24 and is a Gradio one now, for one reason: ZeroGPU is Gradio-SDK only. The Docker image ran the identical Azure bytes, which was the better provenance story, and it could not be given a GPU at any price β which left CountGD, the one capability a GPU actually unblocks, unmeasurable. See What this Space is not for what the change cost.
What is open and what is not
| Endpoint | Auth | Why |
|---|---|---|
GET /animap/health |
none | Carries no farm data, and a platform probe has to reach it |
GET /animap/capabilities |
none | The published contract: what may be claimed, and what may not |
POST /animap/jobs |
bearer token | Runs a model against a farm's photographs |
GET /animap/jobs/{id} |
bearer token | Returns a farm's result |
space/publish.py --set-secret mints ANIMAP_INFERENCE_TOKEN and sets it as a
Space secret. Check it rather than assuming it: GET /health reports
"authenticated": false when no token is configured, so a deployment that
reached the internet without one says so to anyone who asks.
curl -s https://bluman1-animap-inference.hf.space/animap/health
Running a model
Two public-domain captures are baked in, so a real detection can be obtained
without an Azure account. space/FIXTURES.md in the repository lists their ids,
their sources and the human count on record for each.
curl -s -X POST https://bluman1-animap-inference.hf.space/animap/jobs \
-H "authorization: Bearer $ANIMAP_INFERENCE_TOKEN" \
-H 'content-type: application/json' \
-d '{"capability_key":"cattle_detection",
"subject_type":"herd",
"subject_id":"00000000-0000-0000-0000-000000000001",
"farm_id":"00000000-0000-0000-0000-000000000002",
"media_ids":["aa5e8481-8be6-509d-b1fa-f1a178c7cda0"],
"captured_at":"2026-08-22T10:00:00Z"}'
A frame that settles at the first grid answers in well under a second. A dense one runs all three grids and takes a few seconds; there is no queue, because no capability yet takes tens of seconds.
Read warnings before you read the number. A count is of the animals visible
in one frame β never the herd size, never a flock population, and never a
house reconciliation. When the count keeps rising as the frame is read more
finely, or exceeds twenty, the service publishes count_withheld and no number
at all. That refusal is a feature and it is measured: see the known_limits and
validation_notes on each model card.
What the SDK change cost, and what it did not
Lost: the image is no longer byte-identical to Azure's. A Gradio Space has
no Dockerfile, so the claim "this Space builds from the same Dockerfile" is
gone and cannot be got back while ZeroGPU is Gradio-only. What runs is the same
app/ tree with the same requirements.txt, which is close and is not the same
thing, and this file says so rather than letting the old sentence stand.
Lost: a build-time licence gate. The Docker build failed if an AGPL runtime arrived. There is no build to fail now.
Kept: every gate that actually protects a result. app.py runs
scripts/install_models.py --check before it imports the service, so an
artefact that disagrees with its model card stops the Space at start-up rather
than being found by a farm's job. providers.discover() still refuses to serve
a capability whose artefact fingerprints as a copyleft runtime, and /health
still publishes artefact_licenses so a deployment in breach is visible from
outside.
Gained: the ability to be given a GPU. Nothing here reaches for CUDA yet β YOLOX-m and DINOv3 are both ONNX on CPU β so this buys no speed-up today. It is the prerequisite for CountGD, which gets MAE 14.84 on broiler houses against the deployed detector's 156.80 and has never been runnable anywhere in this project.
What this Space is not
It is not the production media path, and it must not be read as evidence for one. This was true of the Docker Space and the SDK change did nothing to it. Production reads captures out of an Azure Blob container using the Container App's managed identity β no key, no SAS, nothing stored. A Space is not inside Azure and has no managed identity, so that credential is unavailable to it. The alternatives a Space could use are a storage account key or a SAS token in a secret, and neither is the production posture: one hands a public Space full access to every farm's evidence, and the other expires.
So this Space serves ANIMAP_MEDIA_PROVIDER=local against the two baked-in
frames. Everything downstream of the pixels β the quality gate, the detection
pyramid, the counting guard, the observation vocabulary β is the production code
path exactly. Everything upstream of them is not.
No farm data reaches this Space. It cannot read animapmedia, and the only
captures it holds are two public-domain photographs from Wikimedia Commons.
Weights
YOLOX-m, Apache-2.0, from the Megvii 0.1.1rc0 release, vendored into this
repository under Git LFS rather than fetched at build time. The service
verifies its sha256 against models/cattle_detection/model_card.json at
start-up and refuses to load an artefact that does not match. Vendoring is what
lets the build step stay install_models.py --check β verify, never fetch β
which is the posture ADR 0005 asks for and the same command the Azure build
runs.
models/cattle_identity is deliberately absent. Its artefact is DINOv3 under a
bespoke Meta licence whose two published texts disagree about an attribution
obligation, and publishing a copy into a public Space is redistribution. That
capability answers unavailable here, and correctly.
No AGPL-3.0 software is installed and none may be. requirements.txt omits
ultralytics, .dockerignore excludes *.pt, the build fails if one arrives
anyway, and providers.discover() refuses to serve a capability whose artefact
fingerprints as a copyleft runtime. GET /health publishes
artefact_licenses, so a deployment in breach is visible from outside.
Attribution
Third-party notices travel with the image in THIRD_PARTY_NOTICES.md. The two
demonstration captures are CC0 and public domain; their sources are in
space/FIXTURES.md.