Pipeline Builder Quickstart
Alpha
Core operators (detection, classification, pose, segmentation, tracking)
are stable. Cascade (op.foreach, op.croproi) and streaming APIs are still in development.
The Voyager SDK Pipeline Builder runs ML pipelines on the Axelera Metis AIPU.
Two steps: compile your model to a .axm file, then build a pipeline
around it. Pre- and postprocessing run as C/C++ operators dispatched
across the AIPU and host; you compose them in Python without managing
hardware placement.
Quick Example
Two packages, two roles:
axelera-devkitis only needed to compile (Step 1). Install it on your dev machine.axelera-rtis the lightweight runtime that runs.axmfiles (Step 2). Install it anywhere you want to deploy.
Compile once, copy the .axm to any target with axelera-rt installed,
and run. The devkit does not need to be present at deployment.
For this walkthrough you need both Axelera packages plus opencv-python
(used for image I/O). The Axelera packages come from our Artifactory
index; opencv-python comes from public PyPI:
pip install --no-cache-dir \
--extra-index-url https://software.axelera.ai/artifactory/api/pypi/axelera-pypi/simple \
axelera-rt axelera-devkit opencv-python
Ultralytics is optional. The Quick Example below uses it to export a
YOLO to .axm in Step 1, but any compile path (ONNX/PyTorch via the
compiler API, or a pre-built .axm) works. Install it only if you want
the YOLO export shortcut:
pip install ultralytics
Ultralytics can also install the Axelera packages on demand during
export/predict, but with no progress output it's easy to mistake for
a hang, so installing up front is usually better. See
Install the Voyager SDK for the full
guide, including runtime-only installs for target devices.
# --- Step 1: Compile (one-time) ---
# Easiest path: Ultralytics export
from ultralytics import YOLO
model = YOLO("yolo11n.pt")
model.export(format="axelera")
# Output: yolo11n_axelera_model/yolo11n.axm
# --- Step 2: Run (your application) ---
from axelera.runtime2 import op
import urllib.request
import cv2
pipeline = op.seq(
op.colorconvert("RGB", src="BGR"), # OpenCV gives BGR; YOLO wants RGB
op.letterbox(640, 640),
op.totensor(),
op.load("yolo11n_axelera_model/yolo11n.axm"),
op.decode_detections(algo="yolov8", num_classes=80),
op.nms(),
op.to_image_space(),
op.axdetection(class_id_type=op.CocoClasses),
)
# Grab Ultralytics' sample image (swap for your own file anytime).
urllib.request.urlretrieve("https://ultralytics.com/images/bus.jpg", "bus.jpg")
image = cv2.imread("bus.jpg") # BGR, which the pipeline converts above
detections = pipeline(image)
# `det.class_id` is a CocoClasses enum member because we passed
# `class_id_type=op.CocoClasses` above; `.name` gives the readable label.
# Without `class_id_type`, `det.class_id` is a plain int.
for det in detections:
print(f"{det.class_id.name}: {det.score:.2f} at {det.bbox}")
Using Your Own YOLO
model.export(format="axelera") runs on whatever .pt you load, so
custom weights compile the same way:
from ultralytics import YOLO
YOLO("my_trained.pt").export(format="axelera")
# Output: my_trained_axelera_model/my_trained.axm
Two things in the runtime snippet then change:
-
num_classesinop.decode_detections(...)must match your model. -
Class names.
op.CocoClassesonly applies to the 80-class COCO set. For your own labels, load them from a file withop.load_classesand pass the result asclass_id_type:# Ultralytics dataset YAML (the same one you trained with) works
# directly: the `names:` field is read whether it's a list or a
# {id: name} dict. A plain .txt / .names file (one label per line)
# also works.
MyClasses = op.load_classes("my_dataset.yaml")
pipeline = op.seq(
op.colorconvert("RGB", src="BGR"),
op.letterbox(640, 640),
op.totensor(),
op.load("my_trained_axelera_model/my_trained.axm"),
op.decode_detections(algo="yolov8", num_classes=len(MyClasses)),
op.nms(),
op.to_image_space(),
op.axdetection(class_id_type=MyClasses),
)
class_id_type is optional. Omit it and det.class_id is a plain int,
which is fine if you only need IDs or will look up names yourself.
.axm vs .axe
Two file formats you'll encounter:
.axmis just the compiled model.op.load()returns raw output tensors; you build the pre/postprocessing around it (as in the Quick Example above)..axeis a bundled pipeline (model + pre/postprocessing). A singleop.load("...axe")gives you a ready-to-run callable.
See Model Formats for the full
description, including how to save a pipeline you've built as an .axe.
Where to Go Next
Already have a .axm file? Jump to the
Pipeline Overview for full examples covering detection,
classification, pose estimation, segmentation, tracking, and cascades.
Need to compile first? See Model Compilation for the Ultralytics path, the generic ONNX/PyTorch path, and how to validate accuracy before deploying.