factorial-compute
One API for AI compute that returns typed answers — text, images, masks, detections, depth, documents, transcripts, speech, video, 3D models, tracks — in the same shape whichever model or supplier produced it.
curl -LsSf https://api.factorialcompute.com/install.sh | sh -s -- inv_... # once per machine
pip install factorial-compute # in your project
from factorial_compute import Client
f = Client() # the key `factorial login` saved, or FACTORIAL_API_KEY if set
# Text, and JSON on request.
print(f.run(model="gpt-oss-120b", input="Name three uses for a forklift.").text)
# An image from a prompt.
result = f.run(model="flux-schnell", input={"prompt": "a red forklift in a warehouse"})
result.images[0].save("forklift.jpg")
# Masks: one per object, each with a box measured from the mask.
result = f.run(model="sam2-segment", input={
"image": "warehouse.jpg", # a local path: uploaded for you
"objects": [{"id": "pallet", "box": [40, 60, 300, 280]},
{"id": "cone", "point": [512, 240]}],
})
for mask in result.masks:
print(mask.id, mask.box)
mask.save(f"{mask.id}.png")
# A transcript, with timestamps.
result = f.run(model="whisper", input={"audio": "meeting.mp3"})
print(result.transcript.text)
for segment in result.transcript.segments:
print(f"{segment.start:6.1f}s {segment.text}")
That is the whole surface for most work: run() with a model id and an
input, then read the typed answer.
In a coding agent
The install line sets up the coding agents it finds - Claude Code, Codex,
Cursor: a skill that tells each what Factorial does, and factorial mcp - six
tools (find_models, describe_model, quote, run, run_batch,
get_result) it can call without writing code, running as the agent's own key.
factorial install sets them up again later.
Teammates
factorial invite bob prints a one-line install to send a teammate. Running
it puts them on your account with a key of their own - the same credit and
history, and no key copied between people. factorial invite --list shows who
has joined.
Rules worth knowing
- Files go in by path, URL or bytes under the keys
image,images,audioandvideo- for vision chat models too. The client uploads them and sends a reference. - Answers are typed.
.text,.images,.masks,.detections,.depth,.document,.transcript,.audio,.video,.mesh,.tracks. Asking a result for the wrong kind raises, rather than returning something empty. - Boxes are
[x0, y0, x1, y1]in pixels everywhere, so a box from a vision model or a detector can be sent straight to a segmenter. - Files come back as handles.
.save(path)writes one;.read()returns the bytes. They stay on the server until you ask. - Retries are safe. Every
run()carries an idempotency key and is retried on connection failures and on 429/502/503/504, so a retry never runs — or bills — the work twice. - Errors say what to change. A refused input raises
InvalidInputwhose message names the field and a value that works. - Reasoning models think before they answer, and the thinking counts
against
max_tokens. Too low a cap is spent thinking:.textthen raisesIncompleteAnswerrather than returning"". Give reasoning models a few thousand tokens, or sendreasoning_effort="low"to think less. - Every result says what it cost:
result.cost.usd, alongsideresult.timing.duration_ms.f.quote(model=..., input=...)says it before anything runs;max_cost_usd=onrun()orsubmit()refuses a call that would cost more, raisingCostCapExceeded. - Answers chain. Pass an earlier answer's file as an input -
{"image": result.images[0]}- and it goes by reference, never downloaded and uploaded again. - Many inputs at once:
f.run_batch(model=..., inputs=[...])runs them in parallel on the server - up to 256 - and returns each answer in order, a failed one as its error rather than losing the rest. - Several models as one workload:
with f.workflow() as w:- eachw.run(...)returns at once, an input can name an earlier step's answer (photo.image,seen.text), and the server runs steps as their inputs become ready, in parallel, with one status, one cost and the whole graph. - Submitted work can call back:
submit(..., webhook_url=...)posts the id and status when it finishes; fetch the execution for the answer. - Masks and boxes draw onto the photo:
result.masks.draw(photo, "out.png")tints and numbers every mask,mask.layer(photo, colour)gives one see-through layer for stacking in HTML,result.detections.draw(...)boxes. - Usage is in the model's own unit: tokens,
images,audio_seconds,characters,video_seconds_generated,object_seconds,meshes,splats.result.usage.unitshas it.
Which models exist
for model in f.models.catalog():
print(model["id"], model.get("output"), model["unit"])
print(" ", model["example"])
The catalogue lists the models you can call right now (catalog(all=True) for
everything, with availability saying which are offline). Each entry says what
kind of answer it returns (output), what every input field means (input),
and gives an example input that works as written.
Robot policies
What a robot should do next, from what it sees:
result = f.run(model="smolvla-libero", input={
"cameras": {"third_person": "agentview.png", "wrist": "wrist.png"},
"state": [...], # the robot's state, in its embodiment's order
"instruction": "put the black bowl on the plate",
})
for action in result.actions: # 50 steps, 7 numbers each, at 10 per second
env.step(action)
Cameras are named by role, whatever the policy calls them in its own code, so
two policies trained for the same robot take the same request. Every answer
carries its embodiment - the robot, what each state number is and what each
action number commands - and result.actions.names lists the action fields.
To evaluate over a recorded episode, send its observations with
f.run_batch(...).
Your own weights
A fine-tune of a catalogue model, as a model only your account can call:
f.models.add("./checkpoints/best.pt", base="sam2-segment", name="pallets")
result = f.run(model="sam2-segment@pallets", input={...}) # the same input as sam2-segment
weights is a local file, a folder (a LoRA adapter's, zipped for you), an
https link, or hf://owner/repo (token= for a private one - used for the
download and kept nowhere). Installing takes a few minutes: the weights are
checked against the base model and called once before they are published, and
add raises with the reason if they are refused. accepts_weights in a
catalogue entry says which models take weights and in what form - today a
fine-tuned SAM 2 / 2.1 (sam2-segment), a LoRA adapter on Qwen3-8B
(qwen3-8b), and a FLUX LoRA (flux-dev, with lora_scale in the input). f.models.weights() lists yours; f.models.remove(id) deletes
one. From a terminal: factorial models add ./best.pt --base sam2-segment --name pallets.
Longer work
handle = f.submit(model="flux-schnell", input={"prompt": "..."})
result = handle.wait()
submit returns before the work runs and survives your process exiting.
Metadata
Release files for factorial-compute 0.1.11
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| factorial_compute-0.1.11.tar.gz | 56.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| factorial_compute-0.1.11-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 116.4 kB
Release files / factorial_compute-0.1.11.tar.gz
| Download URL | factorial_compute-0.1.11.tar.gz |
|---|---|
| Size | 56.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
66cf3e3a116d2e4dfac891f7ad52ea416a8366ba5789de193190868a8c1fa59d
|
|
BLAKE2b-256 checksum How to use checksums |
834ab904a787eb4d93d235ad1904f0dd9bb93de0b4bfb29ddc97833c6ae78b6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logRelease files / factorial_compute-0.1.11-py3-none-any.whl
| Download URL | factorial_compute-0.1.11-py3-none-any.whl |
|---|---|
| Size | 60.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
392f8ba89352392f991f805aa38da6c44713c3c71f157f0aef0841a925e4d54f
|
|
BLAKE2b-256 checksum How to use checksums |
c31a131c0cb056993996eb5333d5fdeb73412c03c1e0e59a7eaf7ae256621321
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logSecurity for factorial-compute 0.1.11
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for factorial_compute-0.1.11.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.