π¨ From kernel to service β InferForge forges any model (CV β LLM β Agent) into production.
Out of the box: sync + async APIs Β· health probes Β· OpenAPI docs Β· Prometheus metrics. Optional (off by default): API-key auth & rate limiting. A template, not a framework: download, adapt, deploy.
InferForge is a serving shell above inference backends: web APIs, logging, exception handling and unified response formats out of the box β a model becomes a deployable service in days. But the business layer above inference is too diverse to generalize, so this is deliberately a template, not a framework: fork it, own the code, and define your own tasks and APIs. The layered architecture keeps every layer replaceable independently β see forking-contract for what to edit and what to keep.
InferForge/
βββ apis/ # FastAPI routers + Pydantic schemas β interface layer
βββ tasks/ # task orchestration; each task owns its predictors
βββ engines/ # BasePredictor contract + YOLOv8n detect/segment/classify reference implementations
βββ utils/ # cross-cutting: envelope, logging, metrics, auth, rate limit
βββ deploy/ # reference artifacts: logrotate, nginx canary, monitoring stack
βββ docs/ # full documentation set (Chinese, indexed by category)
βββ scripts/ # API test clients + callback receiver
βββ tests/ # smoke tests β model-free, CI-run
# 1. Install dependencies
pip install -r requirements.txt
# 2. Put the ONNX model in place
cp /path/to/yolov8n.onnx models/
# 3. Start the service (default: 2 workers on port 8000)
./start.sh # models load lazily on first request
INFERFORGE_PRELOAD=1 ./start.sh # ... or load them at startup (readiness ready immediately)
# 4. Test the API
python3 scripts/test_sync_detect.py --image assets/bus.jpg # local image (base64)
python3 scripts/test_sync_detect.py --url https://ultralytics.com/images/bus.jpg # remote url
# 5. Auto-generated API docs (Swagger UI): http://localhost:8000/docs
# 6. Prometheus metrics: http://localhost:8000/metrics (optional β see docs/metrics.md)Optional: enable the sync segment / classify capabilities (off by default; detection is unaffected):
# 1. Export and place the models (subprocess yolo CLI β never imports ultralytics; auto shape-verified)
python3 scripts/export_yolo.py --task segment --task classify
# 2. Start with the switches (either one works; start.sh only checks enabled models)
INFERFORGE_SEG=1 INFERFORGE_CLS=1 ./start.sh
# 3. Test
python3 scripts/test_sync_segment.py --image assets/bus.jpg --save result_seg.jpg # segment
python3 scripts/test_sync_classify.py --image assets/bus.jpg # classify (top-5)Optional: compose them β the sync pipeline api (detect β crop β fine-grained classify, e.g. detect bus β classify school bus). Reuses the two models above; target classes via INFERFORGE_PIPELINE_TARGETS (default car,truck,bus):
INFERFORGE_PIPELINE=1 ./start.sh
python3 scripts/test_sync_pipeline.py --image assets/bus.jpg --save result_pipeline.jpg # pipeline (detect β classify)Optional: image embedding β batch near-duplicate detection (sync), plus gallery search / duplicate check (async query-only; needs the worker and a built gallery index, see docs/embedding.md). Export a DINOv2-small ONNX into models/ first:
pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # one-off export dep
python3 scripts/export_dinov2.py # -> models/dino2-small.onnx# sync batch dedup: find near-duplicate groups within one batch (threshold via INFERFORGE_DUP_THRESHOLD, default 0.95)
INFERFORGE_DEDUP=1 ./start.sh
python3 scripts/test_sync_dedup.py --image assets/bus.jpg --image assets/bus.jpg --image assets/zidane.jpg # dedup
# async gallery search / dupcheck (worker-only: the milvus-lite index is single-process exclusive)
python3 scripts/build_gallery.py # build the index first β worker must be STOPPED (gallery/ -> data/gallery.db)
INFERFORGE_ASYNC=1 INFERFORGE_SEARCH=1 ./start.sh
python3 scripts/run_search.py --image assets/bus.jpg --check # task layer directly (search / dupcheck)Optional: multi-model routing β copy the example registry and pick models per request (no registry file means single-model behavior, exactly as above):
cp models/registry.example.yaml models/registry.yaml # edit it to list your models
./start.sh # preflight checks every registered model
python3 scripts/test_sync_detect.py --image assets/bus.jpg --model yolov8n # explicit model
python3 scripts/test_sync_detect.py --image assets/bus.jpg # default model (no field)
# details: docs/model-registry.mdRun the smoke tests:
pytest tests/ -vOne async deployment shape β Celery + RabbitMQ + Redis. INFERFORGE_ASYNC=1 registers both apis; callback or query is a per-request choice:
pip install -r requirements-async.txt
INFERFORGE_ASYNC=1 ./start.sh # start web with the async apis
./start_celery.sh # start the workerPush style β server POSTs the result to your callback_url:
python3 scripts/callback_receiver.py # receiver (saves to outputs/callbacks/)
python3 scripts/test_async_detect_callback.py --image assets/bus.jpg \
--callback-url http://localhost:9000/result # result is POSTed backPull style β submit a task, poll until the result is ready (result cached in Redis):
redis-server & # start redis (result store)
python3 scripts/test_async_detect_query.py --image assets/bus.jpg # submit + poll until doneVLM (image understanding via a remote LLM, async-only) β add INFERFORGE_LLM=1 on top of async; the worker calls the remote model:
INFERFORGE_LLM=1 INFERFORGE_ASYNC=1 ./start.sh # start web (registers /predict/vlm/*)
INFERFORGE_LLM_MODEL=your-model \
INFERFORGE_LLM_API_KEY=your-key \
INFERFORGE_LLM_BASE_URL=https://your-llm-endpoint/v1 \
./start_celery.sh # start worker (remote call happens here)
python3 scripts/test_async_vlm_query.py --image assets/bus.jpg # submit + poll until the answer arrivesThe prompt is fixed server-side (INFERFORGE_LLM_PROMPT overrides it); clients submit an image only. See api Β§10.
Config can also live in a .env file (cp .env.example .env and fill in β shell-exported variables take precedence).
Agent (Pydantic AI orchestration demo β detection tool + LLM attribute judgment, async-only) β add INFERFORGE_AGENT=1 on top of async; the worker needs the same INFERFORGE_LLM_* config plus the local model:
INFERFORGE_AGENT=1 INFERFORGE_ASYNC=1 ./start.sh # start web (registers /predict/agent/*)
INFERFORGE_LLM_MODEL=your-model \
INFERFORGE_LLM_API_KEY=your-key \
./start_celery.sh # start worker (agent runs here)
curl -s -X POST http://localhost:8000/predict/agent/query \ # submit; then poll the returned task_id
-H "Content-Type: application/json" \
-d '{"image": "<base64 of assets/zidane.jpg>"}'The demo counts persons with/without hair (zidane.jpg β 2 persons, 1:1); swap the schema + instructions + tool for any other attribute task. See agent.
Full stack in containers β web + worker + RabbitMQ + Redis, no local installs:
cp /path/to/yolov8n.onnx models/ # bind-mounted into the containers, never baked into the image
docker compose up -d
curl http://localhost:8000/health # liveness probeRabbitMQ management UI at http://localhost:15672 (guest/guest). docker compose down stops the stack (-v also drops queue/redis data). See quick-start Β§4 for details.
Optional monitoring stack (Prometheus + Grafana): docker compose -f docker-compose.yml -f deploy/docker-compose.monitoring.yml up -d β see metrics.
- Engineering β concepts Β· quick-start Β· architecture Β· add-engine Β· api Β· deployment Β· benchmark
- Tech stack β stack Β· fastapi-migration
- Standards β status-codes Β· logging Β· metrics Β· testing Β· security Β· forking-contract
Full index with one-line descriptions: docs/README.md.
Model-free and service-free by design: tests inject FakePredictor seams and never load weights or hit the network β CI runs the same commands.
pytest tests/ -v # full suite (no models, no RabbitMQ/Redis needed)
pip install pytest-cov
pytest tests/ -q --cov=app --cov=apis --cov=tasks --cov=engines --cov=utils
python3 -m py_compile app.py apis/*.py tasks/*.py engines/*.py utils/*.py tests/*.py scripts/*.pyCoverage (~81% baseline) is informational, not gated: scripts/ and defensive error branches are intentionally not unit-tested. Test strategy details (seams, async fakes, registry isolation): docs/testing.md.
- Web & serving β FastAPI Β· Uvicorn Β· Gunicorn
- Inference β ONNX Runtime Β· OpenCV Β· NumPy
- Async tasks β Celery Β· RabbitMQ Β· Redis
- LLM & agents β OpenAI SDK Β· Pydantic AI
- Demo model β Ultralytics YOLOv8n
MIT License Β© 2026 zjykzj