Skip to content

About

Hardware-aware multimodal vision platform: real-time object detection + vision-language understanding + JEPA-style future-representation prediction, compared across CPU/GPU/browser/server runtimes. FastAPI + ONNX Runtime backend, React/TS frontend, honest capability detection, runtime model-switching with rollback, and measured benchmarking.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

InferenceLab

Multimodal AI inference, profiling and benchmarking.

InferenceLab is a hardware-aware multimodal benchmarking platform that decomposes AI inference from input decoding to device execution and network transport. It compares vision, language, speech, image and video models across local, browser, edge and remote runtimes using reproducible latency, throughput, memory, utilization, energy and quality measurements.

Formerly VisionEdge Lab. See docs/MIGRATION.md for what changed and how existing deployments carry forward.

InferenceLab demonstrates three complementary levels of visual intelligence and β€” just as importantly β€” the deployment engineering around them: model conversion, quantization, runtime selection, capability detection, benchmarking, graceful fallback, and local-vs-server trade-offs.

  1. Object detection β€” what objects are present and where (YOLOv8, ONNX Runtime, from-scratch NumPy decoding).
  2. Vision-language understanding β€” what is happening; scene description and visual question answering (pluggable VLM backends).
  3. JEPA-style predictive understanding β€” how the scene changes; future-representation prediction and anomaly-from-prediction-error (faithful lightweight I-JEPA reimplementation).

Honesty first

This is a portfolio/research project built on a single laptop-class GPU (RTX 2060, 6 GB) in a RAM-constrained WSL2 environment. It never fabricates capabilities, benchmark numbers, or model quality. Where a component is a mock, an opt-in integration, or a simplified reimplementation, it says so β€” see What is real vs. planned and docs/RESEARCH_LIMITATIONS.md. The lightweight JEPA implementation is not Meta's V-JEPA/V-JEPA 2 and is never claimed to be.


What is real vs. planned

Measured on the reference box (i7-9750H, 12 threads, RTX 2060 6 GB, ~1 GB free RAM, WSL2). Every "working" row below is covered by tests in this repository.

Benchmarking platform

Capability Status
Phase-decomposed latency on a monotonic clock, with device synchronization βœ… Working & tested
Residual overhead reported explicitly, never folded into a real phase βœ… Working & tested
Raw per-iteration retention; percentiles recomputable from stored samples βœ… Working & tested
Warm-up / cold-start / steady-state separation βœ… Working & tested
Failed-iteration tracking, cancellation, timeouts βœ… Working & tested
Integrity warnings (thin sample, background load, throttling, dirty tree) βœ… Working & tested
Environment fingerprint + comparison guard that refuses incompatible runs βœ… Working & tested
CPU/RAM probes (psutil), GPU probes (NVML: utilization, clocks, temp, power, VRAM) βœ… Working β€” every field a real probe
Energy by integrating measured GPU power βœ… Working β€” derived, GPU-only, refuses below 3 samples
Sampler self-cost measurement; perturbation measured at <4% (interleaved) βœ… Working & tested
Versioned result schema, SQLite migrations, JSON/CSV/Markdown export βœ… Working & tested
CLI sharing one engine with the API (same fingerprint for the same config) βœ… Working & tested
Remote inference: correlation ids, server timing envelope, transport residual βœ… Working & tested β€” verified over real HTTP
CPU package energy (RAPL) β›” Not readable under WSL2 β€” reported unavailable with that reason
Framework GPU allocated/reserved memory β›” Not exposed by ONNX Runtime β€” reported unavailable, NVML device totals shown separately

Modalities

Task Model Status
Object detection YOLOv8n (ONNX, AGPL-3.0) βœ… Working & tested β€” from-scratch NumPy decode, equivalence-tested
Image classification MobileNetV4 Conv Small (ONNX, Apache-2.0) βœ… Working & tested β€” timm preprocessing read from the model config
Text embedding all-MiniLM-L6-v2 (ONNX, Apache-2.0) βœ… Working & tested β€” masked mean pooling, semantic ordering asserted
Vision-language mock backend; SmolVLM opt-in 🟑 Mock working & labelled; local VLM guarded/opt-in
Speech-to-text, TTS, image/video generation, LLM β€” β›” Contracts and scenarios only β€” no runtime fits ~1 GB free RAM here; every entry says so

Runtimes

Runtime Status
ONNX Runtime (CPU) βœ… Working
ONNX Runtime (CUDA) 🟑 Probed and refused β€” provider is listed but session creation fails (libcublasLt.so.12 missing), so the load is rejected rather than silently falling back to CPU
PyTorch, TensorRT, OpenVINO, CoreML, TFLite, MLX, llama.cpp, vLLM, TGI, browser, remote-streaming 🟑 Declared and probed β€” each reports whether the dependency is missing or the adapter is unimplemented

Vision slice (from VisionEdge Lab, preserved)

Capability Status
Live WebSocket inference with bounded queue and frame drop βœ… Working
Model switching with rollback, auto-benchmark on switch βœ… Working & tested
Caddy + compose deployment, per-IP rate limiting, TLS βœ… Working β€” live
JEPA primitives, temporal buffer, anomaly scorer, orchestration 🟑 Reimplemented primitives + tests; full training runs planned

Architecture

                           β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                           β”‚ Camera / Image/Video β”‚
                           β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                      β”‚
                             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                             β”‚ Frame Scheduler β”‚
                             β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚ Object Detector β”‚   β”‚ Visual Encoder  β”‚   β”‚ Frame Buffer     β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚ Tracker / Zones β”‚   β”‚ Embedding Store β”‚   β”‚ JEPA Predictor  β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
                     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                     β”‚ Event Router    β”‚   β”‚ Anomaly Scorer  β”‚
                     β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                                β”‚ VLM Invocation  β”‚  (selective, event-triggered)
                                β”‚ Policy          β”‚
                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                                β”‚ Local / Server  β”‚
                                β”‚ VLM Backend     β”‚
                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”
                                β”‚ UI / Logs / DB  β”‚
                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Full detail: docs/ARCHITECTURE.md.


Supported execution modes

Mode Camera Inference Status
PC local PC/browser On the PC (ONNX Runtime CPU today; CUDA/OpenVINO/TensorRT opt-in) βœ… Working
Local server Phone/PC On a PC on your LAN via WebSocket βœ… Working (same WS transport)
Remote server Any Configurable remote endpoint (VLM: OpenAI-compatible, opt-in, TLS, auth) 🟑 VLM path implemented; detection remote is same transport
Phone local (browser) Phone In the mobile browser (ORT-Web/WebGPU) β›” Planned (interfaces stubbed)

Trade-offs at a glance

Latency Bandwidth Privacy Battery Model quality Hardware need
PC local Low None High (frames stay local) PC-powered Bounded by local GPU/CPU GPU helps
Phone local Low-med None Highest Drains phone Small models only Modern phone
Local server Low (LAN) LAN only High (stays on LAN) Light on phone Larger models A PC on LAN
Remote server Network-bound Uploads frames Lowest (frames leave device) Light on client Largest models None on client

Installation

Prereqs: Python 3.11+, Node 18+. A CUDA GPU is optional.

git clone <this-repo> visionedge-lab && cd visionedge-lab
cp .env.example .env

# --- backend (CPU-first) ---
make venv
make install                 # base.txt: fastapi, onnxruntime, opencv, numpy, ...
make model                   # export YOLOv8n -> models/yolov8n.onnx (+ checksum)

# --- frontend ---
make frontend-install

CPU-only setup

The default. make install + make model is all you need β€” detection runs on ONNX Runtime CPU and the VLM defaults to the deterministic mock.

NVIDIA / CUDA setup

# PyTorch CUDA (pick your CUDA version's index-url) + onnxruntime-gpu:
backend/.venv/bin/pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
backend/.venv/bin/pip install -r backend/requirements/cuda.txt   # onnxruntime-gpu

Then the ONNX CUDA execution provider and PyTorch-CUDA backend light up automatically (verified via /api/capabilities).

OpenVINO setup

backend/.venv/bin/pip install -r backend/requirements/openvino.txt
backend/.venv/bin/python scripts/convert_openvino.py --input models/yolov8n.onnx --precision fp16

TensorRT setup

TensorRT engines are GPU/driver-specific and must be built on the target machine:

backend/.venv/bin/pip install -r backend/requirements/tensorrt.txt
backend/.venv/bin/python scripts/build_tensorrt.py --input models/yolov8n.onnx --precision fp16

Local VLM (SmolVLM) setup

backend/.venv/bin/pip install -r backend/requirements/vlm.txt   # transformers, pillow
# then switch the VLM to smolvlm-256m in the Multimodal Assistant page (opt-in download).

On <4 GB RAM this may be slow or OOM β€” the backend reports that honestly and rolls back to the mock.


Running

make backend      # FastAPI on http://localhost:8000  (docs at /docs)
make frontend     # Vite dev server (defaults to http://localhost:5173)

Open the frontend, go to Live Inference, allow camera access, and press Start. Or try detection headlessly:

curl -F "file=@benchmark-data/sample_bus.jpg" "http://localhost:8000/api/infer?confidence=0.25"

Phone on your LAN

Set VITE_API_BASE in .env to your PC's LAN IP over https (browsers require a secure context for camera access on non-localhost). See docs/ARCHITECTURE.md for an HTTPS dev-cert recipe. IPs are never hardcoded β€” they come from env only.


API

Endpoint Purpose
GET /health, /ready, /metrics Liveness, readiness, Prometheus metrics
GET /api/capabilities Real hardware + runtime detection
GET /api/models, /api/model-registry, /api/classes Registry + COCO classes/groups
POST /api/infer Single-image detection
POST /api/detection/switch Runtime model/runtime switch (with rollback)
POST /api/detection/benchmark Measured benchmark
WS /api/ws/detect Real-time detection (bounded queue, frame dropping)
GET /api/runtime-status, /api/sessions, /api/benchmarks Status/history
GET /api/benchmarks/comparison Per-model comparison, median across runs with run count
GET /api/jobs Background job status (auto-benchmark progress)
GET /api/vlm/models, POST /api/vlm/analyze-image, /api/vlm/ask, /api/vlm/analyze-frames VLM (mock default)

Model conversion, quantization, calibration, benchmarking

All under scripts/ (each has --help). Examples:

python scripts/export_onnx.py     --model nano --size 640
python scripts/validate_onnx.py   --input models/yolov8n.onnx      # output-agreement vs PyTorch reference
python scripts/quantize_onnx.py   --input models/yolov8n.onnx --precision int8 --calibration-dir calibration/
python scripts/benchmark_model.py --model models/yolov8n.onnx --runs 50   # MEASURED, never hardcoded

Details: docs/MODEL_OPTIMIZATION.md.


Testing

make test            # backend pytest (detection, registry, switching/rollback, VLM, API, JEPA/temporal/orchestration)
make frontend-test   # frontend vitest (class selection, model switching)

Documentation

Deployment

The app is served from a single origin behind a Caddy reverse proxy: Caddy serves the built SPA and proxies /api (including the /api/ws/detect WebSocket) and /health to the backend. Same origin means no CORS, wss:// derived for free, and one certificate. Camera capture requires HTTPS, which Caddy's automatic TLS provides.

# 1. Point an A/AAAA record at the host, and open ports 80 and 443
#    (Caddy needs 80 for the ACME challenge).

# 2. Fetch the detection weights (12.8 MB, checksum-verified against the registry).
#    A fresh clone has no .onnx: model binaries are gitignored.
python scripts/download_models.py --install yolov8n-onnx

# 3. Start it.
SITE_ADDRESS=visionedge.c-maron.space docker compose -f docker-compose.prod.yml up -d

On a Windows host without WSL2, the compose file cannot run β€” those are Linux containers, and nested virtualization is disabled on many Windows VPS plans. See docs/DEPLOY_WINDOWS.md for the native path: same single-origin design with Caddy and the backend as ordinary Windows processes.

Set IL_RATE_LIMIT_PER_MIN for anything internet-facing β€” every /api/infer and /api/vlm/* request is a real model forward pass, so an unlimited public endpoint is a cost and abuse vector. The limit is enforced in the backend (app/api/ratelimit.py) rather than at the proxy, so it holds however you deploy. The SQLite database must stay on a mounted volume (IL_DB_PATH), or benchmark history and sessions are discarded on every restart.

The hosted demo runs on different hardware

Every number this project reports is measured on the machine it runs on. This README's framing β€” a laptop-class RTX 2060 with 6 GB in WSL2 β€” describes the development machine. On a hosted deployment, the Device Capabilities page and every benchmark will honestly report that server's hardware instead, which is typically a CPU-only VPS with no GPU at all. The two sets of numbers are not comparable, and neither is wrong: they are measurements of different machines.

Note also that the YOLOv8 weights are AGPL-3.0 (see License); AGPL covers network use, so a public deployment serving them should keep its corresponding source available β€” which this public repository does.

Privacy & security

  • Camera frames are not stored by default. Remote frame transmission is off unless you set IL_ALLOW_FRAME_TRANSMISSION=true.
  • Remote endpoints use env-based API keys and TLS. No public server is exposed by default.
  • CORS is * for local dev only β€” set explicit origins for any deployment.

Known limitations

See docs/RESEARCH_LIMITATIONS.md. Highlights: single-GPU/low-RAM dev environment; JEPA is educational-scale (not foundation-scale); "output agreement" is not formal mAP; phone-local browser inference and native mobile are planned, not built.

License

Code in this repository: MIT. YOLOv8 weights: AGPL-3.0 (Ultralytics). SmolVLM/Qwen2.5-VL: Apache-2.0. Review model licenses before any commercial use.

About

Hardware-aware multimodal vision platform: real-time object detection + vision-language understanding + JEPA-style future-representation prediction, compared across CPU/GPU/browser/server runtimes. FastAPI + ONNX Runtime backend, React/TS frontend, honest capability detection, runtime model-switching with rollback, and measured benchmarking.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages