Background

Most Web3 projects will have you believe that every single on-chain protocol and application requires the full power of modern state-of-the-art autoregressive (LLMs) and diffusion models.

However, if you approach this from the perspective of what is the surface of existing protocols and apps that can be modified to be smart, a lot of the parameters that govern those protocols can be greatly improved by age-old regression and tree-based models.

Unlike other projects, we take a cohesive approach to enabling smart contracts to become smart, and fully support classical ML models amongst our suite of models.

To have the most seamless experience for developers for enshrining classical models on-chain, we support the most common format that most ML engineers use: ONNX.


Introduction to ONNX

ONNX (Open Neural Network Exchange) is an open-source format for AI models, enabling interoperability between different AI frameworks.

ONNX establishes a set of standardized, core components, enabling developers to leverage models across various frameworks, tools, runtimes, and compilers with ease. ONNX also maintains a wide repository of pre-trained, state-of-the-art models in the format.

Why ONNX for Blockchain?

Using ONNX offers several advantages:

  • Interoperability: ONNX models can be used across different AI frameworks, making it easier to deploy, manage, and extend AI applications on the blockchain, across developers.
  • Efficiency: ONNX models are optimized for performance, ensuring efficient execution of AI computation in a constrained blockchain environment.

Classical ML Inference on Ritual

Ritual supports Classical ML inference via a dedicated ONNX model execution sidecar.

ONNX Inference requests accept model_id, inputs, output_arithmetic, and output_num_decimals as input types:

# Sample Python code via the ritual_sidecars helper library
# to encode an Classical ML Inference request
async def request_onnx_compute(
    model_id: str | MlModelId,
    vector: np.ndarray[Any, Any],
    in_arithmetic: ArithmeticType = ArithmeticType.ieee,
    in_decimals: int = 0,
    out_arithmetic: ArithmeticType = ArithmeticType.ieee,
    out_decimals: int = 0,
    timeout: int = 10,
) -> tuple[str, str]:
    # Generating on-chain input data
    req_bytes = ONNXInferenceRequest(
        ml_model=model_id,
        input=RitualVector.from_numpy(vector),
        result_arithmetic=out_arithmetic,
        result_fixed_point_scale=out_decimals,
    ).to_web3(arithmetic=in_arithmetic, fixed_point_scale=in_decimals)

    # Sending an on-chain compute request
    return await request_sidecar_compute(
        SpcId.inference, req_bytes, timeout=timeout
    )

Notice the use of RitualVector, our custom library for interacting with vector data on-chain.

Key features offered by ONNX

  • Wide range of pre-trained models: Utilize a variety of pre-trained models compatible with the ONNX format, sourced from Hugging Face Hub (web2) or Arweave (web3).
  • Unified API for inputs and outputs: Via RitualVector and the generic ONNX sidecar API, developers can use various model types and classes without worrying about conforming to model I/O requirements.
  • Customizable preprocessing: Users can customize preprocessing steps using hooks before feeding data into ONNX models, ensuring flexibility and adaptability to specific use cases.