tensor·factory

Reference

CLI reference

Every command across the five packages. Each ships a console script; run them through uv run so the locked workspace environment is used.

Conventions

  • All commands are uv run <script> … from the repo root.
  • --help works on every command and subcommand.
  • Importing a CLI never pulls heavy deps eagerly — tensor-factory --help works without the inference extra; subcommands lazy-import what they need.
ScriptPackagePurpose
tensor-factorytensor-factoryinference: detect, bench
tensor-factory-synthtensor-factory-synthgenerate, label, triage
tensor-factory-traintensor-factory-traintrain + export int8 ONNX
tensor-factory-labeltensor-factory-labelLabel Studio push/pull
tensor-factory-mcptensor-factory-mcpMCP server (stdio)
tensor-factory-httptensor-factory-mcpHTTP detection endpoint

tensor-factory

The inference harness. Two subcommands.

detect

Detect the target object in one image; print the box in normalized and 8-bit form.

tensor-factory detect --model PATH --image PATH [--size 480]
FlagDefaultMeaning
--model— (required)path to the ONNX model
--image— (required)path to the input image
--size480model input size (px)

bench

Measure CPU throughput (fps).

tensor-factory bench --model PATH [--image PATH] [--n 100] [--size 480]
FlagDefaultMeaning
--model— (required)path to the ONNX model
--imagegray frameimage to loop on (default: synthetic gray)
--n100iterations
--size480model input size (px)

tensor-factory-synth

Generation, auto-labeling, and triage. Global flags precede the subcommand.

tensor-factory-synth [--backend mock|gemini] [--size 480] <sample|dataset|triage> …
Global flagDefaultMeaning
--backendmockgeneration backend: mock (anywhere) or gemini (Nano Banana)
--size480image size (px)
--seed0starting seed

sample

Render a contact sheet for one prompt — eyeball aesthetics before a full run.

…synth sample --prompt STR [--n 9] [--cols 3] [--out samples.png]
FlagDefaultMeaning
--prompt— (required)generation prompt
--n9number of samples
--cols3grid columns
--outsamples.pngoutput PNG

dataset

Generate n images, optionally auto-label (gemini backend), and write a COCO dataset + Label Studio pre-annotations.

…synth dataset --prompt STR --features F [F …] [--n 64] [--out dataset] [--no-label] [--skip-errors]
FlagDefaultMeaning
--prompt— (required)generation prompt
--features— (required)one or more feature phrases to detect
--n64number of images
--outdatasetoutput directory
--no-labeloffskip auto-labeling (gemini only)
--skip-errorsofflog and skip per-image failures instead of aborting

Output: images/img_SEED.png, annotations.coco.json, label_studio.json.

triage

Summarize a dataset's review state (approved / pending / rejected, plus trainable count).

…synth triage --data DIR

Batch scripts

Helicoils-example scripts under packages/tensor-factory-synth/scripts/, run with uv run --with google-genai python … (all read GEMINI_API_KEY / GOOGLE_API_KEY):

ScriptKey args (defaults)Produces
gen_samples.py--n 25 --out images --seed 20260620 --reference … --workers 5QC samples + manifest.json
build_ds.pypositional [out] [n=170] [reference]generate → GroundingDINO label → COCO
gen_negatives.py--n 110 --out …/negatives_pool --seed 200000 --workers 6negatives + manifest.json

tensor-factory-train

One subcommand: fit — train on a COCO dataset and export an int8 ONNX model.

tensor-factory-train fit --data DIR [--out model.onnx] [options]
FlagDefaultMeaning
--data— (required)dataset dir (annotations.coco.json + images)
--outmodel.onnxoutput ONNX path
--epochs10training epochs
--batch16batch size
--lr1e-3learning rate
--size480model input size (px)
--width16model channel width
--deviceautocuda/mps/cpu (default resolves cuda → mps → cpu)
--presenceoffadd a YOLO-style objectness head (auto-on when --negatives is given)
--val-frac0.0held-out fraction for metrics + best-checkpoint export
--box-weight1.0weight on the box loss
--presence-weight1.0weight on the objectness loss
--augmentoffrandom flip augmentation
--negativesnoneone or more dirs of no-object images that train the objectness head toward absent (turns the presence head on; box loss masked)
--allow-unreviewedofftrain on un-validated labels too (default: only human-approved)
--freeze-gainofffreeze the soft-argmax gain at 1 (ablation; default lets it learn)

Needs the train extra (torch). See Internals › the model for what --width and --freeze-gain change.

tensor-factory-label

Label Studio integration. Global flags select the server.

tensor-factory-label [--url URL] [--token TOK] <config|push|pull> …
Global flagDefaultMeaning
--url$LABEL_STUDIO_URLhttp://localhost:8080Label Studio base URL
--token$LABEL_STUDIO_API_KEYAPI token (required)

config

Print the RectangleLabels config XML for a project.

…label config [--labels L [L …]] # default: helicoil

push

Create a project and import the COCO dataset, with the candidate boxes as predictions.

…label push --data DIR [--title "tensor_factory"] [--image-base URL]
FlagDefaultMeaning
--data— (required)dataset dir (annotations.coco.json + images/)
--titletensor_factoryproject title
--image-baselocal storageHTTP base serving the images; omit to use Label Studio local storage

Prints the project id and labeling URL.

pull

Export corrected annotations back to COCO, stamped review=approved, source=human (now trainable).

…label pull --project ID [--out annotations.coco.json]

Tasks with no rectangle (or cancelled) annotations are skipped.

tensor-factory-mcp

FastMCP server over stdio. Defaults to the bundled helicoil-presence-cam-v1.onnx.

tensor-factory-mcp [--version]

Three read-only tools, each taking an optional model_path and input_size (16–4096, default 480):

ToolReturns
tensor_factory_detectbox (norm/pixel/uint8), image size, model — plus present/score for a presence-head model (box fields are null when absent)
tensor_factory_model_inforesolved model, input size, input name, ORT providers
tensor_factory_benchmarkfps over n iterations (1–10000, default 100)

On failure each tool returns Error: <type>: <message> rather than raising.

tensor-factory-http

Stdlib http.server endpoint over the same core inference. Binds loopback by default.

tensor-factory-http [--host 127.0.0.1] [--port 8088] [--model PATH] [--input-size 480] [--max-mb 25]
FlagDefaultMeaning
--host127.0.0.1bind host (use 0.0.0.0 to expose deliberately)
--port8088bind port (0 = ephemeral)
--modelbundledONNX model path
--input-size480square model input (px)
--max-mb25reject request bodies larger than this
RouteResponse
GET /health{"status":"ok"}
GET /model_infomodel path, input size, IO name, ORT providers
POST /detectbody = raw image bytes → the same JSON as the MCP detect tool

Bad image bytes → 400; missing Content-Length411; empty body → 400; over --max-mb413; unknown route → 404.

./Quickstart

The repo's top-level entry point.

InvocationDoes
./Quickstartbootstrap (uv sync --locked --all-packages) then run the MCP server (stdio, bundled model)
./Quickstart -cfull local gate: sync → ruff check --fixruff formatty checkpytest -m unit
./Quickstart -uunit tests only
./Quickstart -pfull gate, then uv build + uv publish (needs UV_PUBLISH_TOKEN)

Install extras

The default uv sync stays light. Heavy steps live behind extras you pull only when needed:

ExtraPackagePullsFor
infertensor-factoryonnxruntime, numpy, pillowCPU inference
geminitensor-factory-synthgoogle-genaiNano Banana generation (needs GEMINI_API_KEY)
gputensor-factory-synthtorch, transformers, accelerateGroundingDINO auto-labeling
traintensor-factory-traintorchtraining

Pull an extra with e.g. uv sync --extra gemini, or run a one-off with uv run --with google-genai ….

Environment variables

VariableUsed by
GEMINI_API_KEY / GOOGLE_API_KEYNano Banana generation
LABEL_STUDIO_URL / LABEL_STUDIO_API_KEYLabel Studio push/pull
UV_PUBLISH_TOKEN./Quickstart -p publish
PYTORCH_ENABLE_MPS_FALLBACKset automatically by the auto-labeler for MPS
Prev← The pipeline NextPython API →