Skip to main content

Run Your First Model

FieldValue
DifficultyBeginner
Estimated Read Time<5 minutes
Labelsmodel, inference, foundations

Concept

Load a compiled ResNet-50 model archive, feed it an image, and read the top-1 class in three lines of Python. This is the shortest path from "I have a model archive" to "I have a prediction."

A compiled model is a deployable .tar.gz model archive containing an MPK inference contract that Neat can load and execute on the target device. It contains the model artifacts and runtime metadata needed for inference — you provide input, call run(), and read outputs.

APIs introduced

  • pyneat.Model(model_path) — load the compiled model.
  • model.run(input, timeout_ms) — synchronous inference; returns a Sample with the model's output tensor.
    • timeout_ms is the max wall time (ms) to wait for output. -1 (the default) blocks indefinitely; any > 0 value throws on timeout so stalls surface loudly. Prefer a finite value (e.g. 2000) in production code, -1 only when you trust the runtime to always produce output.

When to use this Fastest way to verify an model archive loads and runs on hardware. For throughput, batching, or live streams, move on to chapter 002.

Prerequisites None — this is the entry chapter.

References

Learning Process

  1. Set up runtime inputs: parse CLI args, locate the compiled ResNet50 model archive, and prepare sample input data.
  2. Build the minimal model execution path for one model and one input stream.
  3. Run synchronous inference to keep behavior deterministic and easy to debug.

Run

Python:

python3 share/sima-neat/tutorials/001_run_your_first_model/run_your_first_model.py \
--model /tmp/resnet_50.tar.gz

C++ (prebuilt):

./lib/sima-neat/tutorials/tutorial_001_run_your_first_model \
--model /tmp/resnet_50.tar.gz

C++ (build from source):

./build.sh --target tutorial_001_run_your_first_model
./build/tutorials-standalone/tutorial_001_run_your_first_model \
--model /tmp/resnet_50.tar.gz

To integrate this chapter's C++ source into your own project with a custom CMakeLists.txt (no extras folder required), see How to Run Tutorials on the landing page.

In Practice

Where the tutorials and tests look for model archives (.tar.gz) and sample assets, and how to provide them locally. This is the prerequisite for every model-backed tutorial.

Ensure sima-cli is on PATH

Some tests invoke sima-cli from non-interactive shells. Use this once after installing sima-cli:

SIMA_CLI_BIN_DIR="<path-to-sima-cli-bin>"
grep -Fqx "export PATH=\"${SIMA_CLI_BIN_DIR}:\$PATH\"" ~/.bashrc || echo "export PATH=\"${SIMA_CLI_BIN_DIR}:\$PATH\"" >> ~/.bashrc
source ~/.bashrc

Then verify:

/bin/sh -c 'command -v sima-cli'

Model archive locations and environment variables

Extraction/runtime placement knobs:

  • SIMA_MPK_EXTRACT_ROOT=<dir> sets the base extract directory.
  • SIMA_MPK_CLEANUP_EXTRACTED=0 preserves extracted proc_* model data after process exit.
  • SIMA_MPK_EXTRACT_GC_STALE_PROC=0 disables dead-proc_* cleanup on startup.

ResNet50

Search order:

  1. SIMA_RESNET50_TAR (per-model override)
  2. SIMA_MODEL_TAR (shared fallback for model-archive tests/examples)
  3. tmp/resnet_50.tar.gz
  4. Local files moved into tmp/ if found: resnet_50.tar.gz, resnet-50.tar.gz

Download (if sima-cli is available):

sima-cli modelzoo get resnet_50

YOLOv8 (v8s)

Search order:

  1. SIMA_YOLO_TAR (per-model override)
  2. SIMA_MODEL_TAR (shared fallback for model-archive tests/examples)
  3. tmp/yolo_v8s.tar.gz
  4. Common local names (moved into tmp/ if found): yolo_v8s.tar.gz, yolo-v8s.tar.gz, yolov8s.tar.gz, yolov8_s.tar.gz

Download (if sima-cli is available):

sima-cli modelzoo get yolo_v8s

Sample images

Default image candidates used in tutorials/tests:

  • tmp/coco_sample.jpg (downloaded if missing)
  • test.jpg
  • tests/assets/preproc_dynamic/ilena_488.jpg

You can override the COCO image URL used by tests with:

SIMA_COCO_URL=<custom_url>

Where tests download to

Tests and examples generally place downloaded assets under tmp/ in the repo root. Tutorials will skip gracefully if required assets are missing.

Troubleshooting assets

  • If a tutorial prints SKIP: missing ..., provide the asset or pass a flag (e.g., --model <path>, --image <path>).
  • If sima-cli is unavailable, set the env vars to point to local model archives.

Code

tutorials/001_run_your_first_model/run_your_first_model.cpp
// Run a ResNet-50 model on an image in three lines of Neat.
//
// Usage:
// tutorial_001_run_your_first_model --model /path/to/resnet_50.tar.gz [--image /path/to.jpg]

#include "neat.h"

#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

#include <cstring>
#include <filesystem>
#include <iostream>
#include <stdexcept>
#include <string>

namespace fs = std::filesystem;

namespace {

bool get_arg(int argc, char** argv, const std::string& key, std::string& out) {
for (int i = 1; i + 1 < argc; ++i) {
if (key == argv[i]) {
out = argv[i + 1];
return true;
}
}
return false;
}

cv::Mat load_rgb(const fs::path& image_path, int size) {
cv::Mat bgr = cv::imread(image_path.string(), cv::IMREAD_COLOR);
if (bgr.empty())
throw std::runtime_error("failed to read image: " + image_path.string());
if (bgr.cols != size || bgr.rows != size) {
cv::resize(bgr, bgr, cv::Size(size, size), 0, 0, cv::INTER_AREA);
}
cv::Mat rgb;
cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
if (!rgb.isContinuous())
rgb = rgb.clone();
return rgb;
}

simaai::neat::Model::Options build_options(int size) {
simaai::neat::Model::Options opt;
opt.preprocess.color_convert.input_format = simaai::neat::PreprocessColorFormat::RGB;
opt.preprocess.input_max_width = size;
opt.preprocess.input_max_height = size;
opt.preprocess.input_max_depth = 3;
opt.preprocess.normalize.mean = {0.485f, 0.456f, 0.406f};
opt.preprocess.normalize.stddev = {0.229f, 0.224f, 0.225f};
return opt;
}

int top1_from_output(const simaai::neat::TensorList& out) {
if (out.empty())
throw std::runtime_error("no tensor output");
const simaai::neat::Mapping m = out.front().map_read();
const size_t n = m.size_bytes / sizeof(float);
const float* p = reinterpret_cast<const float*>(m.data);
int best = 0;
for (size_t i = 1; i < n && i < 1000; ++i) {
if (p[i] > p[best])
best = static_cast<int>(i);
}
return best;
}

} // namespace

int main(int argc, char** argv) {
try {
std::string model_path, image;
if (!get_arg(argc, argv, "--model", model_path)) {
std::cerr << "Usage: tutorial_001_run_your_first_model --model <path> [--image <path>]\n";
return 1;
}
get_arg(argc, argv, "--image", image);

const int size = 224;

// CORE LOGIC
// The three-line Neat story:
simaai::neat::Model model(model_path, build_options(size));
cv::Mat input = image.empty() ? cv::Mat(size, size, CV_8UC3, cv::Scalar(99, 99, 99))
: load_rgb(image, size);
simaai::neat::TensorList sample = model.run(std::vector<cv::Mat>{input}, /*timeout_ms=*/2000);

std::cout << "top1=" << top1_from_output(sample) << "\n";
std::cout << "[OK] 001_run_your_first_model\n";
return 0;
} catch (const std::exception& e) {
std::cerr << "[FAIL] " << e.what() << "\n";
return 1;
}
}

Source