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.

Metadata

Release files for fnnx 0.1.0

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

Source distribution (sdist)

Source distribution for fnnx 0.1.0
File Size Uploaded
fnnx-0.1.0.tar.gz 513.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fnnx 0.1.0
File Interpreter ABI Platform
fnnx-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 840.7 kB

Release files / fnnx-0.1.0.tar.gz

Download URL fnnx-0.1.0.tar.gz
Size 513.4 kB
Tags Source
SHA-256 checksum
How to use checksums
ab88669e10d5c09278977ca14c3651f21a5cc1bdee3ab3154c158e0a6ec2aa10
BLAKE2b-256 checksum
How to use checksums
cbd61d317dd72086eec240c9dace83e03e88dc950c27831e103a69546b36f5ee
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 Aug 22, 2026.

Transparency log

Release files / fnnx-0.1.0-py3-none-any.whl

Download URL fnnx-0.1.0-py3-none-any.whl
Size 327.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
29224ef7e59b107dba6f749efff42b96af8569388619e37fff8b739ad4fbc3f0
BLAKE2b-256 checksum
How to use checksums
8c75e92fdf508037e3c5523cc7f587291d6bcb2c382b7efe0e081ef6f92b68d1
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 Aug 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

0.0.13

2 release files

0.0.12

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

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