Ritual ML Workflows
Tutorials
Simple classifier tutorial

💿 Tutorial: Simple logistic classifier with ZK verification

Train A Model

While notebooks are excellent for data exploration and experimentation, at Ritual we believe it's important to structure your training and inference workflows for reproducibility and standardization.

(Note: If you have an existing MLOps / workflow setup and have a trained torch or sci-kit learn model ready, you can use the deployer tool to deploy models, explained in more detail in the next section.)

Start by creating a custom classic ml workflow that extends ml.workflows.training.BaseClassicTrainingWorkflow. This class defines several common stages in a ML training workflow meant to be overridden and implemented.

Placeholder Image

What's in a typical AI pipeline? Infernet methods
Below are a few methods that the infernet SDK supports that commonly exists in an AI pipeline.
  1. Ingest: Collecting or accessing data from various sources to be used in the pipeline.
  2. Validate: Ensuring that the ingested data meets certain quality criteria or format specifications.
  3. Transform: Applying processing steps to convert raw data into a format suitable for analysis, which may include normalization or scaling.
  4. Feature Generation: Creating new features from the transformed data that can be used to train a machine learning model.
  5. Feature Engineering: Selecting the most relevant features or constructing new features to improve model performance.
  6. Label Generation: Creating or assigning labels to the data points which will be used for supervised learning.
  7. Label Engineering: Modifying or ensuring that the labels are correctly assigned and are in the right format for model training.
  8. Split: Dividing the dataset into training, validation, and testing sets to prepare for model training and evaluation.
  9. Training: The process where a machine learning model learns from the data by adjusting its parameters with respect to a predefined loss function.
  10. Scoring: Evaluating the trained model using a held-out dataset (usually the test set) to measure its performance.
  11. Decision Loop "Performance Acceptable?": Checks if the model's performance is up to the required standard before deployment; if not, the process may iterate through additional rounds of training and evaluation.
  12. Deploy: If the performance is acceptable, the model is deployed into a production environment for practical use.

Infernet offers integration with existing sklearn pipelines and workflows for hook on. ml.workflows.training.base_sklearn_training_workflow.BaseSklearnTrainingWorkflow. Examples can be found in the ml.workflows.training.example_workflow.BalanceClassifierEzklWorkflow class.

Proof Generation

Once you've implemented the necessary steps to train a model and are satisfied with its performance, you can move on to implementing proof generation as part of your deployment. Currently, the open source library EZKL is used as a backend for implementing proofs, though in the future we envision plugging in different proof systems depending on use case and feature set.

Rather than implementing Zero-Knowledge circuits directly, EZKL (opens in a new tab) compiles model circuits from the ONNX Runtimes (opens in a new tab) format. Leveraging built-in compatibility and conversion tools such as sk2torch, this allows us to leverage existing popular machine learning toolkits like Scikit-Learn and Torch. Again, you may reference ml.workflows.training.example_workflow.BalanceClassifierEzklWorkflow for an implementation.

The lifecycle of a zero-knowledge proof can be divided into 3 stages

  1. proof setup
  2. prove
  3. verify

To setup our workflow for these 3 stages, follow the below.

Setup
1. Ready the existing model for formats compatible with zkps. 1. We first prepare our model to make sure it is in the right format. EZKL expects models in .onnx format, which means we need to first export our torch models:
torch.onnx.export(
torch_model,
torch_input,
paths.onnx_model_path,
export_params=
True, # store the trained parameter weights inside the model file
opset_version=10, # the ONNX version to export the model to
do_constant_folding=
True, # whether to execute constant folding for optimization
input_names=["input"], # the model's input names
output_names=["output"], # the model's output names
dynamic_axes={
"input": {
0: "batch_size"
}, # variable length axes
"output": {
0: "batch_size"
},
},
)
  1. next we need to compile our model into a circuit. Depending on use case, this may involve tweaking model visibility settings or providing additional calibration data ( this affects the quantization used by EZKL and may affect the precision of the compiled model).
# generate and calibrate settings (with witness data)
ezkl_utils.gen_and_calibrate_settings(paths)
  1. Generate circuit
res = ezkl.compile_circuit(
paths.onnx_model_path,
paths.compiled_model_path,
paths.settings_path,
)
  1. Once the model is compiled, we can generate the structured reference string (SRS) that is also required for the setup ceremony.
res = ezkl.get_srs(paths.srs_path, paths.settings_path)
 

We generate the proving and verifying key as part of the set up process

ezkl_utils.setup(paths)
 
Proof generation
To generate a proof, a witness must be generated. This is generally composed of the input and ouput of the model, which is then further processed according to the settings.
ezkl_utils.generate_witness(paths.data_path, paths.compiled_model_path,
paths.witness_path)
 

Together with the proving key, a proof can be generated

ezkl_utils.generate_proof(paths)
 
Verification
An on chain verifier needs to be generated and deployed with the verifying key. If you set deploy to true, the code attempts to deploy based on the provided rpc url. Otherwise, the solidity code is generated for separate compilation and deployment.
ezkl_utils.generate_verifier(paths, deploy=False)

This verifier can perform verification if provided the proper proof call data and verifier address.

Monitoring and file uploads with MLFlow

Our training workflows use MLFlow (opens in a new tab) to track file uploads for the proof generation and verification steps. MLFlow is an open-source machine learning experiment tracking tool, similar to other tools such as AzureML and Weights and Biases.

In MLFlow, workflow run artifacts are organized by experiment, allowing you to compare results for related runs.

ml.drivers.base_driver.BaseTrainingDriver provides a base class that by default associates workflow runs with an experiment name equal to the workflow class name. See ml.drivers.example_workflow_driver.ExampleWorkflowDriver for an example implementation.

By default, your artifacts are stored locally in a ml/mlruns directory. You may prefer to run a MLFlow server directly (a docker image is provided to simplify this), in which case the workflows can be configured to communicate with the server by setting the MLFLOW_TRACKING_URI environment variable.

Deployment

Deploying models and proofs from the workflow.

There are 3 services included in the infernet ml api meant to serve classic model inference, LLM model inference, and classic model ZK proofs.

Artifacts are parameters or parts of the configurations needed for the workflow in separate files. To serve proofs and inference, 5 artifacts are required in addition to the torch model (used for inference):

  • compiled circuit
  • Proving key
  • Verifying key
  • Settings
  • SRS string

The above are the minimum set of artifacts needed to deploy a workflow. Artifact version control can be easily managed via Huggingface through upload_prover_files_hf in the ezkl_utils library can help you do this:

ezkl_utils.upload_prover_files_hf(MODEL_NAME,
self.ezkl_paths,
model_path=model_path)
Details on deployment options and model support
Using deployer script

This is a simple program that deploys a classic model for inference and EZKL based Zero-Knowledge Proof serving. Currently, Torch and Sklearn (via sk2learn) models are supported.

Ensure to set up the HUGGING_FACE_HUB_TOKEN environment variable appropriately.

Running this program will:

  1. (Optionally) convert a sklearn model to a torch model
  2. Convert the torch model to an onnx model, and compile the EZKL circuit
  3. Generate the artifacts required for EZKL proving setups
  4. (If model_name specified) upload the torch model and artifacts to the specified Huggingface model repo (can be turned off)
  5. Generate verifier contracts for further deployment
  6. (If onchain data provided) generate data attester contracts for further deployment

The onchain data json file should match EZKL expected on chain data format. See EZKL Data Attest Example (opens in a new tab) for more details.

Options

  • --model FILE
  • --model_name TEXT
  • --use_sk2torch / --no_sk2torch
  • --sample_input_json PATH
  • --onchain_data FILE
  • --calibration_data FILE
  • --sample_input_dtype [float|double|cfloat|cdouble|half|bfloatuint8|int8|short|int|long|bool]
  • --output_dir DIRECTORY
  • --input_visibility [hashed|private|public]
  • --output_visibility [hashed|private|public]
  • --param_visibility [hashed|private|public]
  • --help