Skip to main content

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, audio and video - 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 InvalidInput whose 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: .text then raises IncompleteAnswer rather than returning "". Give reasoning models a few thousand tokens, or send reasoning_effort="low" to think less.
  • Every result says what it cost: result.cost.usd, alongside result.timing.duration_ms. f.quote(model=..., input=...) says it before anything runs; max_cost_usd= on run() or submit() refuses a call that would cost more, raising CostCapExceeded.
  • 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: - each w.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. result.usage.units has 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.10

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for factorial-compute 0.1.10
File Size Uploaded Provenance
factorial_compute-0.1.10.tar.gz 55.8 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for factorial-compute 0.1.10
File Interpreter ABI Platform
factorial_compute-0.1.10-py3-none-any.whl Python 3 none any Details

Total release size: 115.6 kB

Release files / factorial_compute-0.1.10.tar.gz

Download URL factorial_compute-0.1.10.tar.gz
Size 55.8 kB
Tags Source
SHA-256 checksum
How to use checksums
bad6804ca8414e8fe5135526170e5e1c5d1669842a70d19b31d5e723b8aa93a8
BLAKE2b-256 checksum
How to use checksums
1e3b89415f9274963be9eaf451530603c943c12012dcf268f64261f91e712051
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 log

Release files / factorial_compute-0.1.10-py3-none-any.whl

Download URL factorial_compute-0.1.10-py3-none-any.whl
Size 59.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a0d5f0d57b44ec42d9c20b4add5d7165227c6fda6819f36900f38da347718293
BLAKE2b-256 checksum
How to use checksums
f8e6230801cc8b2dab74643fc87683e756a47b321737171566d28b2e2766fc7b
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 log

Security for factorial-compute 0.1.10

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.

Select from 2 files

Attestation for factorial_compute-0.1.10.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 log

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page