Computer Vision

From raw pixels to production models. At any scale.

From dataset curation to distributed training to batch inference, Union orchestrates vision pipelines with frame-level parallelism, reproducibility by design, and cloud-native scaling.

Try the devbox

A free, local sandbox to
explore the Union.ai platform.

Chat with an engineer

Trusted by leading computer vision teams

Built on Flyte

Open source at the core.

Union is built on Flyte, the open-source AI runtime we create and maintain under the Linux Foundation AI & Data.

4000+

companies using Flyte today

17M+

Flyte SDK downloads

Fan-Out & Scale

Fan out on durable asyncio.

Vision work is one small task repeated a hundred million times. A week of fleet footage decodes into more frames than your cluster has cores, and fanning out over them is plain async, with the cluster scaling back to zero when the run is done.

  • Concurrency you can cap. `flyte.map.aio(fn, frames, concurrency=500)` bounds how many run at once, for a fan-out wider than the cluster.
  • Retries with pacing. `retries=5`, or a `RetryStrategy` with exponential backoff so a throttled object store gets time to come back.
  • Built for spot. `interruptible=True` puts decode and inference on spot nodes and cuts compute costs by more than 90%. Losing one frame is expected here, not an incident.
Infrastructure as Context

Except blocks can change the hardware.

Images are not uniform, and neither is the memory they need. A batch of 640px crops fits comfortably in 8Gi, and the same code on gigapixel pathology slides or 8K video does not. Union hands you a typed error instead of a stack trace, so the batch that blows memory comes back as an exception you can catch and re-run on a bigger box.

Typed infrastructure errors. `OOMError`, `TaskInterruptedError`, `TaskTimeoutError`, `ImagePullBackOffError`. Failures you can branch on.

Resources changed at runtime. `.override(resources=...)` re-runs the same batch with different memory, or moves it from an L4 to an A100.

The policy is yours. Write the handler once and every vision pipeline in your org can import it.

The handler does not have to be human. Provisioning is an ordinary Python call, so the same API you write a retry policy against is one an agent can call while a run is in flight.
Function-Level Checkpointing

Recover. Fork. Replay.

Restarting a training run from the top is a second full GPU bill. A fine-tune dies nine hours in on the last shard, or a preprocessing job loses a spot node with four million frames already labeled. Union records what finished as the run happens, outside the node doing the work, and that record is what you resume from.

Recover what failed. Point `recover` at a prior run. Finished frames are reused and only what failed or changed runs again, even without caching enabled.

Fork from any step. `flyte.rerun` starts a prior run again at the step you pick, with a new backbone or a different augmentation policy.

Replay with today's code. `--rerun-from` runs a prior run's inputs against the code on your machine right now.
Durable Artifacts

Outputs that outlive the run.

A trained detector should not be a checkpoint file someone remembers the path to. Artifacts are typed, versioned values that persist past the run that made them, so an evaluation workflow consumes last week's weights without re-training them, and a fresh batch of labels can fire the next run by itself.

Passed between workflows and apps. One pipeline's curated dataset is another's typed input, without re-running the producer.

Versioned, not overwritten. A new version is a new artifact, so an eval run resolves to the exact weights it scored.

Events, not polling. `flyte.OnArtifact` fires a run whenever a new annotation batch lands, with no cron hacks in between.
Run History & Versioning

Reproduce a run from months ago.

Someone is asking which model version flagged that image, and what it was trained on. Every run keeps what it takes to reproduce a result: the code that executed, the infrastructure it ran on, and the configuration applied to both. That is what makes a pipeline shareable rather than personal, and it is the same record an audit or a postmortem needs.

Inputs and outputs per run. Open a training run from months ago and see exactly which frames went in and which weights came out.

The code that ran, not the code today. Each run resolves to its own code bundle and container image, down to the CUDA and OpenCV versions.

Full lineage back to source footage. Every intermediate and final output traces to the raw images that produced it.
Pure Python

Vision pipelines in pure Python.

Decoding, detection, and evaluation, no YAML, no DSLs. Write it in Python, run it at scale on Union, with automatic retries, checkpointing, and recovery built in.

import flyteimport flyte.errors  async def retry_with_memory(    task_fn,    *args,    initial_memory: str = "250Mi",    increment: str = "200Mi",    max_memory: str = "4Gi",    cpu: int = 1,    **kwargs,):    current_memory_mi = parse_memory(initial_memory)    increment_mi = parse_memory(increment)    max_memory_mi = parse_memory(max_memory)     attempt = 1     while current_memory_mi <= max_memory_mi:        mem_str = format_memory(current_memory_mi)        print(f"Attempt {attempt}: running with memory: {mem_str}")         try:            result = await task_fn.override(                resources=flyte.Resources(cpu=cpu, memory=mem_str)            )(*args, **kwargs)            print(f"Success with memory: {mem_str}")            return result         except flyte.errors.OOMError as e:            print(f"OOMError with memory {mem_str}: {e}")            if current_memory_mi + increment_mi > max_memory_mi:                break            current_memory_mi += increment_mi            attempt += 1     raise RuntimeError(        f"Task failed with OOM even after retrying up to "        f"{format_memory(max_memory_mi)} across {attempt} attempts"    )

except flyte.errors.OOMError

An OOM kill is an exception, not a dead run. So are TaskInterruptedError, TaskTimeoutError, and RetriesExhaustedError.

.override(resources=...)

The handler changes the hardware for the next attempt. Infrastructure as context, with a signature.

It is just Python

A while loop and a try block. Write it yourself, share it as a helper, or let an agent write it against the same API.

From the Community

Running where a bad batch is expensive.

Autonomous driving, medical imaging, and satellite analysis at catalog scale. Long runs on infrastructure large enough to fail constantly.

See a training run survive a node failure.

Bring a pipeline you've lost data to before, and watch what happens when the machine under it goes away.

Try the devbox

A free, local sandbox to
explore the Union.ai platform.

Chat with an engineer