Skip to main content

FNNX for Python

The Python package runs, inspects, and creates FNNX artifacts. The FNNX specification defines the format and its execution semantics.

Installation

FNNX requires Python 3.10 or later. Add the base package with uv.

uv add fnnx

The package provides extras for features with additional dependencies.

Extra Support
core NumPy arrays and ONNX_v1 execution with ONNX Runtime.
extras Reader, PyfuncBuilder, and local MLflow model conversion.
mlflow Remote MLflow URI resolution and conversion verification.
compiler Compilation of pipeline artifacts to C99.

Combine extras when one application needs several features.

uv add "fnnx[core,extras]"
uv add "fnnx[extras,mlflow]"
uv add "fnnx[compiler]"

Running an artifact

Runtime accepts an unpacked artifact directory or an uncompressed tar artifact. It uses LocalHandler unless you select another handler.

This example assumes model.fnnx declares x and y as Array[float32] values.

import numpy as np

from fnnx.stable.v1 import LocalHandler, LocalHandlerConfig, Runtime

runtime = Runtime(
    "model.fnnx",
    handler=LocalHandler,
    handler_config=LocalHandlerConfig(n_workers=2, n_workers_node=2),
    device_map="cpu",
)
inputs = {"x": np.asarray([[1.0, 2.0]], dtype=np.float32)}
outputs = runtime.compute(inputs, {})
print(outputs["y"])

The input and output names must match the artifact manifest. Pass dynamic attributes as the second mapping to compute.

Every dynamic attribute value must be a string. Call compute_async from an async function when the caller must not block.

n_workers sets the artifact worker-thread count. n_workers_node sets the operation worker-thread count.

The extra_ops field maps operation names to custom operation classes.

Inspecting an artifact

Reader reads a tar artifact without executing it. It exposes the effective manifest, ordered metadata, and raw environment document.

from fnnx.extras.reader import Reader

reader = Reader("model.fnnx")
print(reader.manifest.model_dump())
print([entry.model_dump() for entry in reader.metadata])
print(reader.env)

reader.pyenv contains the parsed python3::conda_pip environment when the artifact declares one. It is None for other environment kinds.

Running in an artifact environment

StdIOHandler starts a worker in the environment declared by the artifact. It supports the python3::conda_pip environment kind.

The default CondaLikeEnvManager searches for micromamba, mamba, or conda. Set FNNX_CONDA_EXE to select another executable path.

Use UvEnvManager to create the worker command with uv.

from fnnx.envs.uv import UvEnvManager
from fnnx.handlers.stdio import StdIOHandler, StdIOHandlerConfig
from fnnx.stable.v1 import Runtime

runtime = Runtime(
    "model.fnnx",
    handler=StdIOHandler,
    handler_config=StdIOHandlerConfig(env_manager=UvEnvManager),
    device_map="cpu",
)
outputs = runtime.compute({"x": [[1.0, 2.0]]}, {})
print(outputs["y"])

UvEnvManager requires uv on PATH, or a path in FNNX_UV_EXE. It ignores declared build dependencies.

LocalHandler does not provision the artifact environment. Use StdIOHandler when the worker needs the dependencies from env.json.

Creating a pyfunc artifact

A pyfunc artifact stores a PyFunc subclass. PyfuncBuilder reads that class from its Python source file and writes a tar artifact.

The following file builds and runs an echo artifact.

from __future__ import annotations

from typing import Any

from fnnx.variants.pyfunc import PyFunc


class Echo(PyFunc):
    def warmup(self) -> None:
        pass

    def compute(
        self,
        inputs: dict[str, Any],
        dynamic_attributes: dict[str, str],
    ) -> dict[str, Any]:
        return {"echo": inputs["message"]}

    async def compute_async(
        self,
        inputs: dict[str, Any],
        dynamic_attributes: dict[str, str],
    ) -> dict[str, Any]:
        return self.compute(inputs, dynamic_attributes)


if __name__ == "__main__":
    from fnnx.extras.builder import PyfuncBuilder
    from fnnx.extras.pydantic_models.manifest import NDJSON
    from fnnx.stable.v1 import Runtime

    builder = PyfuncBuilder(Echo, model_name="echo", model_version="1")
    builder.add_input(
        NDJSON(
            name="message",
            content_type="NDJSON",
            dtype="NDContainer[string]",
            shape=["batch"],
        )
    )
    builder.add_output(
        NDJSON(
            name="echo",
            content_type="NDJSON",
            dtype="NDContainer[string]",
            shape=["batch"],
        )
    )
    builder.add_fnnx_runtime_dependency()
    builder.save("echo.fnnx")

    result = Runtime("echo.fnnx").compute({"message": ["hello"]}, {})
    print(result["echo"].data)

Use add_runtime_dependency for imports that the stored class needs. Use add_file or add_module to include local resources.

The pyfunc variant specification defines the stored entry point and its context.

Converting an MLflow model

package_mlflow_model converts a local MLflow model directory or an MLflow URI to a pyfunc artifact. It derives inputs from the MLflow signature.

from fnnx.extras.mlflow import package_mlflow_model

package_mlflow_model(
    "mlflow-model",
    "forecast.fnnx",
    name="forecast",
    verify=True,
)

Remote URIs and verify=True require the mlflow extra. Verification loads the artifact and uses its saved input example when one exists.

Use input_specs or output_specs when the inferred interface is not suitable. The converter stores the source MLflow model inside the artifact.

Compiling an artifact to C

The compiler turns a pipeline artifact into one self-contained C99 header and one JSON report. The result runs without a Python interpreter and without a runtime library.

uv run python -m fnnx.extras.compilers.c model.fnnx \
    --output-dir build/model-c \
    --runtime-dim batch=64 \
    --prefix model

Use --dim NAME=VALUE to fix a symbolic dimension. Symbolic dimensions without a binding default to 1.

Use --runtime-dim NAME=MAX to set a per-call dimension with a fixed maximum. The compiler rejects operations and types it cannot emit.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fnnx-0.1.0.tar.gz (513.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fnnx-0.1.0-py3-none-any.whl (327.2 kB view details)

Uploaded Python 3

File details

Details for the file fnnx-0.1.0.tar.gz.

File metadata

  • Download URL: fnnx-0.1.0.tar.gz
  • Upload date:
  • Size: 513.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fnnx-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ab88669e10d5c09278977ca14c3651f21a5cc1bdee3ab3154c158e0a6ec2aa10
MD5 acf32fe9d0dd60b2df7b68badd5de80a
BLAKE2b-256 cbd61d317dd72086eec240c9dace83e03e88dc950c27831e103a69546b36f5ee

See more details on using hashes here.

Provenance

The following attestation bundles were made for fnnx-0.1.0.tar.gz:

Publisher: pypi_publish.yml on fnnx-ai/FNNX

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fnnx-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: fnnx-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 327.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fnnx-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 29224ef7e59b107dba6f749efff42b96af8569388619e37fff8b739ad4fbc3f0
MD5 fc2f12b9e8c33b2b490ac6160fa3aafe
BLAKE2b-256 8c75e92fdf508037e3c5523cc7f587291d6bcb2c382b7efe0e081ef6f92b68d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for fnnx-0.1.0-py3-none-any.whl:

Publisher: pypi_publish.yml on fnnx-ai/FNNX

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

0.0.13

2 files

0.0.12

2 files

0.0.11

2 files

0.0.10

2 files

0.0.9

2 files

0.0.8

2 files

0.0.7

2 files

0.0.6

2 files

0.0.5

2 files

0.0.4

2 files

0.0.3

2 files

0.0.2

2 files

0.0.1

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page