animap-gpu / README.md
bluman1's picture
Publish services/inference
9d36f13 verified
|
Raw
History Blame Contribute Delete
7.42 kB

A newer version of the Gradio SDK is available: 6.26.0

Upgrade
metadata
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.