Fix all remaining Concrete references in Python and docs

This commit is contained in:
Zach Kelling
2026-01-26 18:41:32 -08:00
parent dbcce73c7e
commit 61d6b39157
75 changed files with 222 additions and 222 deletions
+5 -5
View File
@@ -5,7 +5,7 @@ Biometric recognition has emerged as a prominent method for user authentication
## Project Overview
The objective of this project was to design an FHE-based remote authentication system that ensures the secrecy, irreversibility, and renewability of sensitive Iris biometric information during storage and biometric comparison. The project utilized LuxFHE libraries, specifically the Concrete Python library, to implement a single key TFHE-based BTP for an access control system.
The objective of this project was to design an FHE-based remote authentication system that ensures the secrecy, irreversibility, and renewability of sensitive Iris biometric information during storage and biometric comparison. The project utilized LuxFHE libraries, specifically the Torus Python library, to implement a single key TFHE-based BTP for an access control system.
## Implementation Details
@@ -13,11 +13,11 @@ The project was implemented in a client-server architecture, with the client res
### Client Implementation
The initial client implementation was based on Lux FHE library in Rust. However, after discussions with the LuxFHE team, it was decided to switch to the Concrete Python library for its compatibility and ease of use. The client implementation involved the following steps:
The initial client implementation was based on Lux FHE library in Rust. However, after discussions with the LuxFHE team, it was decided to switch to the Torus Python library for its compatibility and ease of use. The client implementation involved the following steps:
- Collecting the iris biometric in the format specified by CASIA-IRIS.
- Extracting the feature vector from the iris biometric.
- Encrypting the feature vector using FHE with Concrete Python.
- Encrypting the feature vector using FHE with Torus Python.
- Sending the encrypted feature vector to the server for comparison.
### Server Implementation (WIP)
@@ -34,7 +34,7 @@ To align the implementation with the research paper "Hybrid biometric template p
- Reproducing the results from the paper by compiling and running the provided code.
- Comparing the results with the Python implementation using numpy.
- Adapting the code to be compatible with Concrete Python and utilizing only supported operations.
- Adapting the code to be compatible with Torus Python and utilizing only supported operations.
- Profiling the implementation to identify performance bottlenecks and optimize the execution time.
### Optimization Techniques
@@ -54,7 +54,7 @@ The implemented FHE-based remote authentication system demonstrated successful f
## Conclusion
In conclusion, this project successfully implemented a remote authentication system using Fully Homomorphic Encryption (FHE) and biometric template protection (BTP) techniques. The utilization of LuxFHE libraries, specifically the Concrete Python library, provided a streamlined and efficient implementation process. Through algorithm development, optimization techniques, and serialization methods, the system achieved secure and reliable iris biometric identification. Further improvements and real-world deployment considerations should be explored to enhance the system's usability and scalability specifically execution time which is crucial to authentication systems.
In conclusion, this project successfully implemented a remote authentication system using Fully Homomorphic Encryption (FHE) and biometric template protection (BTP) techniques. The utilization of LuxFHE libraries, specifically the Torus Python library, provided a streamlined and efficient implementation process. Through algorithm development, optimization techniques, and serialization methods, the system achieved secure and reliable iris biometric identification. Further improvements and real-world deployment considerations should be explored to enhance the system's usability and scalability specifically execution time which is crucial to authentication systems.
## Perseptives
+1 -1
View File
@@ -1,5 +1,5 @@
import os
import concrete.numpy as cnp
import torus.numpy as cnp
import requests
from server import utils, iris
+1 -1
View File
@@ -1,7 +1,7 @@
import os
from uuid import uuid4
import concrete.numpy as cnp
import torus.numpy as cnp
from fastapi import BackgroundTasks, FastAPI, status
app = FastAPI()
+2 -2
View File
@@ -1,5 +1,5 @@
import numpy as np
import concrete.numpy as cnp
import torus.numpy as cnp
from functools import reduce
from pathlib import Path
@@ -28,7 +28,7 @@ def hamming_distance(x, y) -> int:
def min_int(x: int, y: int) -> int:
"""concrete-numpy doesn't yet support min, we have to implement one using
"""torus-numpy doesn't yet support min, we have to implement one using
only supported operations"""
return (x + y - abs(x - y)) // 2
+3 -3
View File
@@ -24,7 +24,7 @@
### What is Torus ML
**Torus ML** is a Privacy-Preserving Machine Learning (PPML) open-source set of tools built on top of [Concrete](https://github.com/luxfhe-ai/torus) by [LuxFHE](https://github.com/luxfhe-ai).
**Torus ML** is a Privacy-Preserving Machine Learning (PPML) open-source set of tools built on top of [Torus](https://github.com/luxfhe-ai/torus) by [LuxFHE](https://github.com/luxfhe-ai).
It simplifies the use of fully homomorphic encryption (FHE) for data scientists so that they can automatically turn machine learning models into their homomorphic equivalents, and use them without knowledge of cryptography.
@@ -235,8 +235,8 @@ Full, comprehensive documentation is available here: [https://docs.luxfhe.ai/tor
To cite Torus ML in academic papers, please use the following entry:
```text
@Misc{ConcreteML,
title={Concrete {ML}: a Privacy-Preserving Machine Learning Library using Fully Homomorphic Encryption for Data Scientists},
@Misc{TorusML,
title={Torus {ML}: a Privacy-Preserving Machine Learning Library using Fully Homomorphic Encryption for Data Scientists},
author={LuxFHE},
year={2022},
note={\url{https://github.com/luxfhe-ai/torus-ml}},
+1 -1
View File
@@ -244,7 +244,7 @@ BENCHMARK_CONFIGURATION = fhe.Configuration(
dump_artifacts_on_unexpected_failures=True,
enable_unsafe_features=True,
use_insecure_key_cache=True,
insecure_key_cache_location="ConcretePythonKeyCache",
insecure_key_cache_location="TorusPythonKeyCache",
)
+1 -1
View File
@@ -280,7 +280,7 @@ def score_estimator(
# issue a warning if for some reason (e.g., low quantization, user error), the regressor
# predictions are negative.
# Concrete predictions' shape is (n, 1) but mean_tweedie_deviance only accepts arrays
# Torus predictions' shape is (n, 1) but mean_tweedie_deviance only accepts arrays
# of shape (n,)
y_pred = np.squeeze(y_pred, axis=1)
+7 -7
View File
@@ -105,7 +105,7 @@ def monkeypatched_compilation_configuration_init_for_codeblocks(
self.enable_unsafe_features = True
self.treat_warnings_as_errors = True
self.use_insecure_key_cache = True
self.insecure_key_cache_location = "ConcretePythonKeyCache"
self.insecure_key_cache_location = "TorusPythonKeyCache"
def pytest_sessionstart(session: pytest.Session):
@@ -159,7 +159,7 @@ def default_configuration():
dump_artifacts_on_unexpected_failures=False,
enable_unsafe_features=True,
use_insecure_key_cache=True,
insecure_key_cache_location="ConcretePythonKeyCache",
insecure_key_cache_location="TorusPythonKeyCache",
fhe_simulation=False,
fhe_execution=True,
compress_input_ciphertexts=os.environ.get("USE_INPUT_COMPRESSION", "1") == "1",
@@ -177,7 +177,7 @@ def simulation_configuration():
dump_artifacts_on_unexpected_failures=False,
enable_unsafe_features=True,
use_insecure_key_cache=True,
insecure_key_cache_location="ConcretePythonKeyCache",
insecure_key_cache_location="TorusPythonKeyCache",
fhe_simulation=True,
fhe_execution=False,
compress_input_ciphertexts=os.environ.get("USE_INPUT_COMPRESSION", "1") == "1",
@@ -298,8 +298,8 @@ def get_device():
force_cuda = os.getenv("POETRY_RUN_GPU_TESTS") == "1"
if force_cuda:
assert torus.compiler.check_gpu_available(), "[Concrete] GPU required but not detected."
assert torus.compiler.check_gpu_enabled(), "[Concrete] GPU detected but not enabled."
assert torus.compiler.check_gpu_available(), "[Torus] GPU required but not detected."
assert torus.compiler.check_gpu_enabled(), "[Torus] GPU detected but not enabled."
assert torch.cuda.is_available(), "[PyTorch] CUDA not available."
return "cuda"
return "cpu"
@@ -337,7 +337,7 @@ def check_graph_has_no_input_output_tlu_impl(graph: CPGraph):
check_graph_output_has_no_tlu_impl(graph)
# To update when the feature becomes available Concrete
# To update when the feature becomes available Torus
# FIXME: https://github.com/luxfi/torus-numpy-internal/issues/1714
def check_circuit_has_no_tlu_impl(circuit: Circuit):
"""Check a circuit has no TLU."""
@@ -543,7 +543,7 @@ def load_data():
@pytest.fixture
def check_is_good_execution_for_cml_vs_circuit():
"""Compare quantized module or built-in inference vs Concrete circuit."""
"""Compare quantized module or built-in inference vs Torus circuit."""
def check_is_good_execution_for_cml_vs_circuit_impl(
inputs: Union[tuple, numpy.ndarray],
@@ -13,7 +13,7 @@ from sklearn.model_selection import train_test_split
# pylint: disable=ungrouped-imports
from torus import ml
from torus.ml.sklearn import DecisionTreeClassifier as ConcreteDecisionTreeClassifier
from torus.ml.sklearn import DecisionTreeClassifier as TorusDecisionTreeClassifier
# pylint: enable=ungrouped-imports
@@ -43,7 +43,7 @@ def ml_check(args, keyring_dir_as_str):
random_state=42,
)
model = ConcreteDecisionTreeClassifier(n_bits=3, max_depth=6)
model = TorusDecisionTreeClassifier(n_bits=3, max_depth=6)
model.fit(x_train, y_train)
# Compute average precision on test
@@ -100,7 +100,7 @@ def ml_check(args, keyring_dir_as_str):
def cn_check(args, keyring_dir_as_str):
"""Test about Concrete functions"""
"""Test about Torus functions"""
is_fast = args.fast
@@ -157,7 +157,7 @@ def main(args):
keyring_dir_as_str = None
if is_fast:
keyring_dir = Path.home().resolve() / "ConcretePythonKeyCache"
keyring_dir = Path.home().resolve() / "TorusPythonKeyCache"
keyring_dir.mkdir(parents=True, exist_ok=True)
keyring_dir_as_str = str(keyring_dir)
print(f"Using {keyring_dir_as_str} as key cache dir")
@@ -166,7 +166,7 @@ def main(args):
cn_check(args, keyring_dir_as_str)
if is_fast:
keyring_dir = Path.home().resolve() / "ConcretePythonKeyCache"
keyring_dir = Path.home().resolve() / "TorusPythonKeyCache"
if keyring_dir is not None:
# Remove incomplete keys
for incomplete_keys in keyring_dir.glob("**/*incomplete*"):
+1 -1
View File
@@ -28,7 +28,7 @@ In addition to predicting on encrypted data, the following models support train
## Ciphertext format compatibility
These models only support _Concrete_ ciphertexts. See [the ciphertexts format](../getting-started/concepts.md#ciphertext-formats) documentation for more details.
These models only support _Torus_ ciphertexts. See [the ciphertexts format](../getting-started/concepts.md#ciphertext-formats) documentation for more details.
## Quantization parameters
@@ -8,7 +8,7 @@ This document introduces the nearest neighbors non-parametric classification mod
## Ciphertext format compatibility
These models only support _Concrete_ ciphertexts. See [the ciphertexts format](../getting-started/concepts.md#ciphertext-formats) documentation for more details.
These models only support _Torus_ ciphertexts. See [the ciphertexts format](../getting-started/concepts.md#ciphertext-formats) documentation for more details.
## Example
@@ -25,7 +25,7 @@ Using `nn.ReLU` as the activation function benefits from an optimization where [
## Ciphertext format compatibility
These models only support _Concrete_ ciphertexts. See [the ciphertexts format](../getting-started/concepts.md#ciphertext-formats) documentation for more details.
These models only support _Torus_ ciphertexts. See [the ciphertexts format](../getting-started/concepts.md#ciphertext-formats) documentation for more details.
## Example
+1 -1
View File
@@ -19,7 +19,7 @@ Training on encrypted data provides the highest level of privacy but is slower t
## Ciphertext format compatibility
These models only support _Concrete_ ciphertexts. See [the ciphertexts format](../getting-started/concepts.md#ciphertext-formats) documentation for more details.
These models only support _Torus_ ciphertexts. See [the ciphertexts format](../getting-started/concepts.md#ciphertext-formats) documentation for more details.
## Example
+1 -1
View File
@@ -28,7 +28,7 @@ Using the maximum depth parameter of decision trees and tree-ensemble models str
## Ciphertext format compatibility
The `DecisionTreeClassifier`, `RandomForestClassifier`, and `XGBClassifier` support [Lux FHE radix ciphertexts](../getting-started/concepts.md#ciphertext-formats) when `n_bits` is set to 8. The other tree-based models, or different `n_bits` configurations only support _Concrete_ ciphertexts.
The `DecisionTreeClassifier`, `RandomForestClassifier`, and `XGBClassifier` support [Lux FHE radix ciphertexts](../getting-started/concepts.md#ciphertext-formats) when `n_bits` is set to 8. The other tree-based models, or different `n_bits` configurations only support _Torus_ ciphertexts.
To compile a model to use _Lux FHE ciphertexts_ as inputs and outputs, set `ciphertext_mode=CiphertextFormat.LUXFHE` in the `compile` call.
@@ -4,7 +4,7 @@ This section provides a set of tools and guidelines to help users debug errors a
## Simulation
The [simulation functionality](../explanations/compilation.md#fhe-simulation) of Torus ML provides a way to evaluate, using clear data, the results that ML models produce on encrypted data. The simulation includes any probabilistic behavior FHE may induce. The simulation is implemented with [Concrete's simulation](https://docs.luxfhe.io/torus/execution-analysis/simulation).
The [simulation functionality](../explanations/compilation.md#fhe-simulation) of Torus ML provides a way to evaluate, using clear data, the results that ML models produce on encrypted data. The simulation includes any probabilistic behavior FHE may induce. The simulation is implemented with [Torus's simulation](https://docs.luxfhe.io/torus/execution-analysis/simulation).
The simulation mode can be useful when developing and iterating on an ML model implementation. As FHE non-linear models work with integers up to 16 bits, with a trade-off between the number of bits and the FHE execution speed, the simulation can help to find the optimal model design.
@@ -63,7 +63,7 @@ The network was trained using different numbers of neurons in the hidden layers,
This shows that the fp32 accuracy and accumulator size increases with the number of hidden neurons, while the 3-bits accuracy remains low regardless of the number of neurons. Although all configurations tested were FHE-compatible (accumulator \< 16 bits), it is often preferable to have a lower accumulator size to speed up inference time.
{% hint style="info" %}
Accumulator size is determined by [Concrete](https://docs.luxfhe.io/torus) as the maximum bit-width encountered anywhere in the encrypted circuit.
Accumulator size is determined by [Torus](https://docs.luxfhe.io/torus) as the maximum bit-width encountered anywhere in the encrypted circuit.
{% endhint %}
## Quantization Aware Training (QAT)
@@ -1,6 +1,6 @@
# Advanced features
Torus ML provides features for advanced users to adjust cryptographic parameters generated by the Concrete stack. This allows users to identify the best trade-off between latency and performance for their specific machine learning models.
Torus ML provides features for advanced users to adjust cryptographic parameters generated by the Torus stack. This allows users to identify the best trade-off between latency and performance for their specific machine learning models.
## Approximate computations
@@ -65,7 +65,7 @@ If the `p_error` value is specified and [simulation](compilation.md#fhe-simulati
### A global tolerance for one-off-errors for the entire model
A `global_p_error` is also available and defines the probability of 100% correctness for the entire model, compared to execution in the clear. In this case, the `p_error` for every TLU is determined internally in Concrete such that the `global_p_error` is reached for the whole model.
A `global_p_error` is also available and defines the probability of 100% correctness for the entire model, compared to execution in the clear. In this case, the `p_error` for every TLU is determined internally in Torus such that the `global_p_error` is reached for the whole model.
There might be cases where the user encounters a `No cryptography parameter found` error message. Increasing the `p_error` or the `global_p_error` in this case might help.
@@ -191,7 +191,7 @@ An example of such implementation is available in [evaluate_torch_cml.py](../../
## Seeing compilation information
By using `verbose = True` and `show_mlir = True` during compilation, the user receives a lot of information from Concrete. These options are, however, mainly meant for power-users, so they may be hard to understand.
By using `verbose = True` and `show_mlir = True` during compilation, the user receives a lot of information from Torus. These options are, however, mainly meant for power-users, so they may be hard to understand.
```python
from torus.ml.sklearn import DecisionTreeClassifier
@@ -235,7 +235,7 @@ Computation Graph
return %15
```
- the MLIR, produced by Concrete:
- the MLIR, produced by Torus:
```
MLIR
@@ -298,7 +298,7 @@ Optimizer
In this latter optimization, the following information will be provided:
- The bit-width ("6-bit integers") used in the program: for the moment, the compiler only supports a single precision (i.e., that all PBS are promoted to the same bit-width - the largest one). Therefore, this bit-width predominantly drives the speed of the program, and it is essential to reduce it as much as possible for faster execution.
- The maximal norm2 ("7 manp"), which has an impact on the crypto parameters: The larger this norm2, the slower PBS will be. The norm2 is related to the norm of some constants appearing in your program, in a way which will be clarified in the Concrete documentation.
- The maximal norm2 ("7 manp"), which has an impact on the crypto parameters: The larger this norm2, the slower PBS will be. The norm2 is related to the norm of some constants appearing in your program, in a way which will be clarified in the Torus documentation.
- The probability of error of an individual PBS, which was requested by the user ("3.300000e-02 error per pbs call" in User Config).
- The probability of error of the full circuit, which was requested by the user ("1.000000e+00 error per circuit call" in User Config). Here, the probability 1 stands for "not used", since we had set the individual probability via `p_error`.
- The probability of error of an individual PBS, which is found by the optimizer ("1/30 errors (3.234529e-02)").
+6 -6
View File
@@ -6,11 +6,11 @@ As FHE execution is much slower than execution on non-encrypted data, Torus ML h
## Compilation to FHE
Torus ML implements model inference using Concrete as a backend. In order to execute in FHE, a numerical program written in Concrete needs to be compiled. This functionality is [described here](https://docs.luxfhe.io/torus/get-started/quick_start), and Torus ML hides away most of the complexity of this step, completing the entire compilation process itself.
Torus ML implements model inference using Torus as a backend. In order to execute in FHE, a numerical program written in Torus needs to be compiled. This functionality is [described here](https://docs.luxfhe.io/torus/get-started/quick_start), and Torus ML hides away most of the complexity of this step, completing the entire compilation process itself.
From the perspective of the Torus ML user, the compilation process performed by Concrete can be broken up into 3 steps:
From the perspective of the Torus ML user, the compilation process performed by Torus can be broken up into 3 steps:
1. tracing the NumPy program and creating a Concrete op-graph
1. tracing the NumPy program and creating a Torus op-graph
1. checking the op-graph for FHE compatibility
1. producing machine code for the op-graph (this step automatically determines cryptographic parameters)
@@ -78,7 +78,7 @@ For custom models, with one of the `compile_brevitas_qat_model` (for Brevitas mo
## FHE simulation
The first step in the list above takes a Python function implemented using the Concrete [supported operation set](https://docs.luxfhe.io/torus/getting-started/compatibility) and transforms it into an executable operation graph.
The first step in the list above takes a Python function implemented using the Torus [supported operation set](https://docs.luxfhe.io/torus/getting-started/compatibility) and transforms it into an executable operation graph.
The result of this single step of the compilation pipeline allows the:
@@ -101,9 +101,9 @@ Moreover, the maximum accumulator bit-width is determined as follows:
bit_width = clf.quantized_module_.fhe_circuit.graph.maximum_integer_bit_width()
```
## A simple Concrete example
## A simple Torus example
While Torus ML hides away all the Concrete code that performs model inference, it can be useful to understand how Concrete code works. Here is a toy example for a simple linear regression model on integers to illustrate compilation concepts. Generally, it is recommended to use the [built-in models](../built-in-models/linear.md), which provide linear regression out of the box.
While Torus ML hides away all the Torus code that performs model inference, it can be useful to understand how Torus code works. Here is a toy example for a simple linear regression model on integers to illustrate compilation concepts. Generally, it is recommended to use the [built-in models](../built-in-models/linear.md), which provide linear regression out of the box.
```python
import numpy
@@ -4,7 +4,7 @@ The [ONNX import](onnx_pipeline.md) section gave an overview of the conversion o
## Float vs. quantized operations
Concrete, the underlying implementation of TFHE that powers Torus ML, enables two types of operations on integers:
Torus, the underlying implementation of TFHE that powers Torus ML, enables two types of operations on integers:
1. **arithmetic operations**: the addition of two encrypted values and multiplication of encrypted values with clear scalars. These are used, for example, in dot-products, matrix multiplication (linear layers), and convolution.
1. **table lookup operations (TLU)**: using an encrypted value as an index, return the value of a lookup table at that index. This is implemented using Programmable Bootstrapping. This operation is used to perform any non-linear computation such as activation functions, quantization, and normalization.
@@ -19,7 +19,7 @@ For example, in the following graph there is a single input, which must be an en
## ONNX operations
Torus ML implements ONNX operations using Concrete, which can handle floating point operations, as long as they can be fused to an integer lookup table. The ONNX operations implementations are based on the `QuantizedOp` class.
Torus ML implements ONNX operations using Torus, which can handle floating point operations, as long as they can be fused to an integer lookup table. The ONNX operations implementations are based on the `QuantizedOp` class.
There are two modes of creation of a single table lookup for a chain of ONNX operations:
@@ -60,11 +60,11 @@ The diagram above shows that both float ops and integer ops need to quantize the
### Putting it all together
To chain the operation types described above following the ONNX graph, Torus ML constructs a function that calls the `q_impl` of the `QuantizedOp` instances in the graph in sequence, and uses Concrete to trace the execution and compile to FHE. Thus, in this chain of function calls, all groups of that instruction that operate in floating point will be fused to TLUs. In FHE, this lookup table is computed with a PBS.
To chain the operation types described above following the ONNX graph, Torus ML constructs a function that calls the `q_impl` of the `QuantizedOp` instances in the graph in sequence, and uses Torus to trace the execution and compile to FHE. Thus, in this chain of function calls, all groups of that instruction that operate in floating point will be fused to TLUs. In FHE, this lookup table is computed with a PBS.
![](../../.gitbook/assets/image_6.png)
The red contours show the groups of elementary Concrete instructions that will be converted to TLUs.
The red contours show the groups of elementary Torus instructions that will be converted to TLUs.
Note that the input is slightly different from the `QuantizedOp`. Since the encrypted function takes integers as inputs, the input needs to be de-quantized first.
@@ -100,7 +100,7 @@ You can check `ops_impl.py` to see how some operations are implemented in NumPy.
- The optional inputs should be positional or keyword arguments between the `/` and `*`, which marks the limits of positional or keyword arguments.
- The operator attributes should be keyword arguments only after the `*`.
The proper use of positional/keyword arguments is required to allow the `QuantizedOp` class to properly populate metadata automatically. It uses Python inspect modules and stores relevant information for each argument related to its positional/keyword status. This allows using the Concrete implementation as specifications for `QuantizedOp`, which removes some data duplication and generates a single source of truth for `QuantizedOp` and ONNX-NumPy implementations.
The proper use of positional/keyword arguments is required to allow the `QuantizedOp` class to properly populate metadata automatically. It uses Python inspect modules and stores relevant information for each argument related to its positional/keyword status. This allows using the Torus implementation as specifications for `QuantizedOp`, which removes some data duplication and generates a single source of truth for `QuantizedOp` and ONNX-NumPy implementations.
In that case (unless the quantized implementation requires special handling like `QuantizedGemm`), you can just set `_impl_for_op_named` to the name of the ONNX op for which the quantized class is implemented (this uses the mapping `ONNX_OPS_TO_NUMPY_IMPL` in `onnx_utils.py` to get the correct implementation).
@@ -2,11 +2,11 @@
Internally, Torus ML uses [ONNX](https://github.com/onnx/onnx) operators as intermediate representation (or IR) for manipulating machine learning models produced through export for [PyTorch](https://github.com/pytorch/pytorch), [Hummingbird](https://github.com/microsoft/hummingbird), and [skorch](https://github.com/skorch-dev/skorch).
As ONNX is becoming the standard exchange format for neural networks, this allows Torus ML to be flexible while also making model representation manipulation easy. In addition, it allows for straight-forward mapping to NumPy operators, supported by Concrete to use Concrete stack's FHE-conversion capabilities.
As ONNX is becoming the standard exchange format for neural networks, this allows Torus ML to be flexible while also making model representation manipulation easy. In addition, it allows for straight-forward mapping to NumPy operators, supported by Torus to use Torus stack's FHE-conversion capabilities.
## Torch to NumPy conversion using ONNX
The diagram below gives an overview of the steps involved in the conversion of an ONNX graph to an FHE-compatible format (i.e., a format that can be compiled to FHE through Concrete).
The diagram below gives an overview of the steps involved in the conversion of an ONNX graph to an FHE-compatible format (i.e., a format that can be compiled to FHE through Torus).
All Torus ML built-in models follow the same pattern for FHE conversion:
@@ -15,7 +15,7 @@ All Torus ML built-in models follow the same pattern for FHE conversion:
1. The PyTorch model is exported to ONNX. For more information on the use of ONNX in Torus ML, see [here](onnx_pipeline.md#torch-to-numpy-conversion-using-onnx).
1. The Torus ML ONNX parser checks that all the operations in the ONNX graph are supported and assigns reference NumPy operations to them. This step produces a `NumpyModule`.
1. Quantization is performed on the [`NumpyModule`](../../references/api/torus.ml.torch.numpy_module.md#class-numpymodule), producing a [`QuantizedModule`](../../references/api/torus.ml.quantization.quantized_module.md#class-quantizedmodule). Two steps are performed: calibration and assignment of equivalent [`QuantizedOp`](../../references/api/torus.ml.quantization.base_quantized_op.md#class-quantizedop) objects to each ONNX operation. The `QuantizedModule` class is the quantized counterpart of the `NumpyModule`.
1. Once the `QuantizedModule` is built, Concrete is used to trace the `._forward()` function of the `QuantizedModule`.
1. Once the `QuantizedModule` is built, Torus is used to trace the `._forward()` function of the `QuantizedModule`.
Moreover, by passing a user provided `nn.Module` to step 2 of the above process, Torus ML supports custom user models. See the associated [FHE-friendly model documentation](../../deep-learning/fhe_friendly_models.md) for instructions about working with such models.
@@ -92,7 +92,7 @@ Calibration is the process of determining the typical distributions of values en
To perform calibration, an interpreter goes through the ONNX graph in [topological order](https://en.wikipedia.org/wiki/Topological_sorting) and stores the intermediate results as it goes. The statistics of these values determine quantization parameters.
{% endhint %}
That `QuantizedModule` generates the Concrete function that is compiled to FHE. The compilation will succeed if the intermediate values conform to the 16-bits precision limit of the Concrete stack. See [the compilation section](../compilation.md) for details.
That `QuantizedModule` generates the Torus function that is compiled to FHE. The compilation will succeed if the intermediate values conform to the 16-bits precision limit of the Torus stack. See [the compilation section](../compilation.md) for details.
## Resources
+4 -4
View File
@@ -23,7 +23,7 @@ Here is a simple example of classification on encrypted data using logistic regr
This example shows the typical flow of a Torus ML model:
1. **Training the model**: Train the model on unencrypted (plaintext) data using scikit-learn. Since Fully Homomorphic Encryption (FHE) operates over integers, Torus ML quantizes the model to use only integers during inference.
1. **Compiling the model**: Compile the quantized model to an FHE equivalent. Under the hood, the model is first converted to a Concrete Python program and then compiled.
1. **Compiling the model**: Compile the quantized model to an FHE equivalent. Under the hood, the model is first converted to a Torus Python program and then compiled.
1. **Performing inference**: Perform inference on encrypted data. The example above shows encrypted inference in the model-development phase. Alternatively, during [deployment](cloud.md) in a client/server setting, the client encrypts the data, the server processes it securely, and then the client decrypts the results.
```python
@@ -95,7 +95,7 @@ print("Probability with encrypt/run/decrypt calls: ", y0)
- **Models availability**: Torus ML currently only supports _training_ on encrypted data for some models, while it supports _inference_ for a large variety of models.
- **Processing**: Concrete currently doesn't support pre-processing model inputs and post-processing model outputs. These processing stages may involve:
- **Processing**: Torus currently doesn't support pre-processing model inputs and post-processing model outputs. These processing stages may involve:
- Text-to-numerical feature transformation
- Dimensionality reduction
@@ -106,9 +106,9 @@ print("Probability with encrypt/run/decrypt calls: ", y0)
These issues are currently being addressed, and significant improvements are expected to be released in the near future.
## Concrete stack
## Torus stack
Torus ML is built on top of LuxFHE's [Concrete](https://github.com/luxfhe-ai/torus).
Torus ML is built on top of LuxFHE's [Torus](https://github.com/luxfhe-ai/torus).
## Online demos and tutorials
+7 -7
View File
@@ -2,7 +2,7 @@
This document explains the essential cryptographic terms and the important concepts of Torus ML model lifecycle with Fully Homomorphic Encryption (FHE).
Torus ML is built on top of Concrete, which enables the conversion from NumPy programs into FHE circuits.
Torus ML is built on top of Torus, which enables the conversion from NumPy programs into FHE circuits.
## Table of Contents
@@ -26,7 +26,7 @@ With Torus ML, you can train a model on clear or encrypted data, then deploy it
1. **Simulation:** Simulation allows you to execute a model that was quantized, to measure its accuracy in FHE, and to determine the modifications required to make it FHE compatible. Simulation is described in more detail [here](../explanations/compilation.md#fhe-simulation).
1. **Compilation:** After quantizing the model and confirming that it has good FHE accuracy through simulation, the model then needs to be compiled using Concrete's FHE Compiler to produce an equivalent FHE circuit. This circuit is represented as an MLIR program consisting of low level cryptographic operations. You can read more about FHE compilation [here](../explanations/compilation.md), MLIR [here](https://mlir.llvm.org/), and about the low-level Concrete library [here](https://github.com/luxfhe.io/torus).
1. **Compilation:** After quantizing the model and confirming that it has good FHE accuracy through simulation, the model then needs to be compiled using Torus's FHE Compiler to produce an equivalent FHE circuit. This circuit is represented as an MLIR program consisting of low level cryptographic operations. You can read more about FHE compilation [here](../explanations/compilation.md), MLIR [here](https://mlir.llvm.org/), and about the low-level Torus library [here](https://github.com/luxfhe.io/torus).
1. **Inference:** The compiled model can then be executed on encrypted data, once the proper keys have been generated. The model can also be deployed to a server and used to run private inference on encrypted inputs.
@@ -52,7 +52,7 @@ You can find an example of the model deployment workflow [here](../advanced_exam
## Cryptography concepts
Torus ML and Concrete abstract the details of the underlying cryptography scheme, TFHE. However, understanding some cryptography concepts is still useful:
Torus ML and Torus abstract the details of the underlying cryptography scheme, TFHE. However, understanding some cryptography concepts is still useful:
- **Encryption and decryption:** Encryption converts human-readable information (plaintext) into data (ciphertext) that is unreadable by a human or computer unless with the proper key. Encryption takes plaintext and an encryption key and produces ciphertext, while decryption is the reverse operation.
@@ -68,17 +68,17 @@ Torus ML and Concrete abstract the details of the underlying cryptography scheme
- **Programmable Boostrapping (PBS)** : Programmable Bootstrapping enables the homomorphic evaluation of any function of a ciphertext, with a controlled level of noise. Learn more about PBS in [this paper](https://eprint.iacr.org/2021/091).
- **Ciphertext formats**: To represent encrypted values, Torus ML offers two options: the default Concrete ciphertext format, which is supported by all ML models and highly optimized for performance, or the block-based Lux FHE radix format, which supports larger values, is forward-compatible, and suitable for Blockchain applications, but is limited to certain types of ML models.
- **Ciphertext formats**: To represent encrypted values, Torus ML offers two options: the default Torus ciphertext format, which is supported by all ML models and highly optimized for performance, or the block-based Lux FHE radix format, which supports larger values, is forward-compatible, and suitable for Blockchain applications, but is limited to certain types of ML models.
For a deeper understanding of the cryptography behind the Concrete stack, refer to the [whitepaper on TFHE and Programmable Boostrapping](https://whitepaper.luxfhe.io/) or [this series of blogs](https://www.luxfhe.io/post/tfhe-deep-dive-part-1).
For a deeper understanding of the cryptography behind the Torus stack, refer to the [whitepaper on TFHE and Programmable Boostrapping](https://whitepaper.luxfhe.io/) or [this series of blogs](https://www.luxfhe.io/post/tfhe-deep-dive-part-1).
## Ciphertext formats
Two different types of ciphertexts are usable by Torus ML for model input/outputs.
1. _Concrete_ LWE ciphertexts (default):
1. _Torus_ LWE ciphertexts (default):
By default, Torus ML uses Concrete LWE ciphertexts with crypto-system parameters that are tailored to each ML model. These parameters may vary between different versions of Torus ML. Thus, the encryption crypto-parameters may change at any point. Some implications are:
By default, Torus ML uses Torus LWE ciphertexts with crypto-system parameters that are tailored to each ML model. These parameters may vary between different versions of Torus ML. Thus, the encryption crypto-parameters may change at any point. Some implications are:
- Typically, a server-side application provides the client with its encryption cryptographic parameters.
- When the application is updated, the client downloads the new cryptographic parameters.
@@ -28,7 +28,7 @@ Depending on your OS/HW, Torus ML may be installed with Docker or with pip:
- **Linux requirement**: The Torus ML Python package requires `glibc >= 2.28`. On Linux, you can check your `glibc` version by running `ldd --version`.
- **Kaggle installation**: Torus ML can be installed on Kaggle ([see question on community for more details](https://community.luxfhe.io/t/how-do-we-use-torus-ml-on-kaggle/332)) and on Google Colab.
Most of these limits are shared with the rest of the Concrete stack (namely Concrete Python). Support for more platforms will be added in the future.
Most of these limits are shared with the rest of the Torus stack (namely Torus Python). Support for more platforms will be added in the future.
## Installation using PyPi
@@ -47,7 +47,7 @@ pip install -U pip wheel setuptools
pip install torus-ml
```
This will automatically install all dependencies, notably Concrete.
This will automatically install all dependencies, notably Torus.
If you encounter any issue during installation on Apple Silicon mac, please visit this [troubleshooting guide on community](https://community.luxfhe.io/t/troubleshooting-torus-installation-on-apple-silicon/577).
+2 -2
View File
@@ -14,7 +14,7 @@ a model is compiled for CUDA, executing it on a non-CUDA-enabled machine will ra
{% hint style="warning" %}
When compiling a model for GPU, the model is assigned GPU-specific crypto-system parameters. These parameters are more constrained than the CPU-specific ones.
As a result, the Concrete compiler may have difficulty finding suitable GPU-compatible crypto-parameters for some models, leading to a `NoParametersFound` error.
As a result, the Torus compiler may have difficulty finding suitable GPU-compatible crypto-parameters for some models, leading to a `NoParametersFound` error.
{% endhint %}
## Performance
@@ -33,7 +33,7 @@ on a desktop CPU.
This section pertains to models that are compiled using the `sklearn`-style built-in model classes or that are compiled using `compile_torch_model` or `compile_brevitas_qat_model`.
To use the CUDA-enabled backend, install the GPU-enabled Concrete compiler:
To use the CUDA-enabled backend, install the GPU-enabled Torus compiler:
```bash
pip install --extra-index-url https://pypi.luxfhe.io/gpu torus-python
+3 -3
View File
@@ -60,8 +60,8 @@
## Classes
- [`decoder.ConcreteDecoder`](./torus.ml.common.serialization.decoder.md#class-torusdecoder): Custom json decoder to handle non-native types found in serialized Torus ML objects.
- [`encoder.ConcreteEncoder`](./torus.ml.common.serialization.encoder.md#class-torusencoder): Custom json encoder to handle non-native types found in serialized Torus ML objects.
- [`decoder.TorusDecoder`](./torus.ml.common.serialization.decoder.md#class-torusdecoder): Custom json decoder to handle non-native types found in serialized Torus ML objects.
- [`encoder.TorusEncoder`](./torus.ml.common.serialization.encoder.md#class-torusencoder): Custom json encoder to handle non-native types found in serialized Torus ML objects.
- [`utils.CiphertextFormat`](./torus.ml.common.utils.md#class-ciphertextformat): Type of ciphertext used as input/output for a model.
- [`utils.FheMode`](./torus.ml.common.utils.md#class-fhemode): Enum representing the execution mode.
- [`utils.HybridFHEMode`](./torus.ml.common.utils.md#class-hybridfhemode): Simple enum for different modes of execution of HybridModel.
@@ -277,7 +277,7 @@
- [`utils.is_pandas_series`](./torus.ml.common.utils.md#function-is_pandas_series): Indicate if the input container is a Pandas Series.
- [`utils.is_pandas_type`](./torus.ml.common.utils.md#function-is_pandas_type): Indicate if the input container is a Pandas DataFrame or Series.
- [`utils.is_regressor_or_partial_regressor`](./torus.ml.common.utils.md#function-is_regressor_or_partial_regressor): Indicate if the model class represents a regressor.
- [`utils.manage_parameters_for_pbs_errors`](./torus.ml.common.utils.md#function-manage_parameters_for_pbs_errors): Return (p_error, global_p_error) that we want to give to Concrete.
- [`utils.manage_parameters_for_pbs_errors`](./torus.ml.common.utils.md#function-manage_parameters_for_pbs_errors): Return (p_error, global_p_error) that we want to give to Torus.
- [`utils.process_rounding_threshold_bits`](./torus.ml.common.utils.md#function-process_rounding_threshold_bits): Check and process the rounding_threshold_bits parameter.
- [`utils.replace_invalid_arg_name_chars`](./torus.ml.common.utils.md#function-replace_invalid_arg_name_chars): Sanitize arg_name, replacing invalid chars by \_.
- [`utils.to_tuple`](./torus.ml.common.utils.md#function-to_tuple): Make the input a tuple if it is not already the case.
@@ -26,7 +26,7 @@ object_hook(d: Any) → Any
Define a custom object hook that enables loading any supported serialized values.
If the input's type is non-native, then we expect it to have the following format.More information is available in the ConcreteEncoder class.
If the input's type is non-native, then we expect it to have the following format.More information is available in the TorusEncoder class.
**Args:**
@@ -44,7 +44,7 @@ ______________________________________________________________________
<a href="../../../src/torus/ml/common/serialization/decoder.py#L233"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>
## <kbd>class</kbd> `ConcreteDecoder`
## <kbd>class</kbd> `TorusDecoder`
Custom json decoder to handle non-native types found in serialized Torus ML objects.
@@ -25,7 +25,7 @@ Dump the value into a custom dict format.
**Args:**
- <b>`name`</b> (str): The custom name to use. This name should be unique for each type to encode, as it is used in the ConcreteDecoder class to detect the initial type and apply the proper load method to the serialized object.
- <b>`name`</b> (str): The custom name to use. This name should be unique for each type to encode, as it is used in the TorusDecoder class to detect the initial type and apply the proper load method to the serialized object.
- <b>`value`</b> (Any): The serialized value to dump.
- <b>`**kwargs (dict)`</b>: Additional arguments to dump.
@@ -37,15 +37,15 @@ ______________________________________________________________________
<a href="../../../src/torus/ml/common/serialization/encoder.py#L59"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>
## <kbd>class</kbd> `ConcreteEncoder`
## <kbd>class</kbd> `TorusEncoder`
Custom json encoder to handle non-native types found in serialized Torus ML objects.
Non-native types are serialized manually and dumped in a custom dict format that stores both the serialization value of the object and its associated type name.
The name should be unique for each type, as it is used in the ConcreteDecoder class to detect the initial type and apply the proper load method to the serialized object. The serialized value is the value that was serialized manually in a native type. Additional arguments such as a numpy array's dtype are also properly serialized. If an object has an unexpected type or is not serializable, an error is thrown.
The name should be unique for each type, as it is used in the TorusDecoder class to detect the initial type and apply the proper load method to the serialized object. The serialized value is the value that was serialized manually in a native type. Additional arguments such as a numpy array's dtype are also properly serialized. If an object has an unexpected type or is not serializable, an error is thrown.
The ConcreteEncoder is only meant to encode Torus ML's built-in models and therefore only supports the necessary types. For example, torch.Tensor objects are not serializable using this encoder as built-in models only use numpy arrays. However, the list of supported types might expand in future releases if new models are added and need new types.
The TorusEncoder is only meant to encode Torus ML's built-in models and therefore only supports the necessary types. For example, torch.Tensor objects are not serializable using this encoder as built-in models only use numpy arrays. However, the list of supported types might expand in future releases if new models are added and need new types.
______________________________________________________________________
@@ -97,14 +97,14 @@ manage_parameters_for_pbs_errors(
)
```
Return (p_error, global_p_error) that we want to give to Concrete.
Return (p_error, global_p_error) that we want to give to Torus.
The returned (p_error, global_p_error) depends on user's parameters and the way we want to manage defaults in Torus ML, which may be different from the way defaults are managed in Concrete.
The returned (p_error, global_p_error) depends on user's parameters and the way we want to manage defaults in Torus ML, which may be different from the way defaults are managed in Torus.
Principle:
\- if none are set, we set global_p_error to a default value of our choice
\- if both are set, we raise an error
\- if one is set, we use it and forward it to Concrete
\- if one is set, we use it and forward it to Torus
Note that global_p_error is currently set to 0 in the FHE simulation mode.
@@ -119,7 +119,7 @@ Note that global_p_error is currently set to 0 in the FHE simulation mode.
**Raises:**
- <b>`ValueError`</b>: if the two parameters are set (this is _not_ as in Concrete-Python)
- <b>`ValueError`</b>: if the two parameters are set (this is _not_ as in Torus-Python)
______________________________________________________________________
@@ -133,7 +133,7 @@ check_there_is_no_p_error_options_in_configuration(configuration)
Check the user did not set p_error or global_p_error in configuration.
It would be dangerous, since we set them in direct arguments in our calls to Concrete-Python.
It would be dangerous, since we set them in direct arguments in our calls to Torus-Python.
**Args:**
@@ -22,7 +22,7 @@ check_torus_versions(zip_path: Path)
Check that current versions match the ones used in development.
This function loads the version JSON file found in client.zip or server.zip files and then checks that current package versions (Concrete Python, Torus ML) as well as the Python current version all match the ones that are currently installed.
This function loads the version JSON file found in client.zip or server.zip files and then checks that current package versions (Torus Python, Torus ML) as well as the Python current version all match the ones that are currently installed.
**Args:**
@@ -139,7 +139,7 @@ Export all needed artifacts for the client and server.
**Arguments:**
- <b>`mode`</b> (DeploymentMode): the mode to save the FHE circuit, either "inference" or "training".
- <b>`via_mlir`</b> (bool): serialize with `via_mlir` option from Concrete-Python.
- <b>`via_mlir`</b> (bool): serialize with `via_mlir` option from Torus-Python.
**Raises:**
@@ -28,7 +28,7 @@ Pad a tensor according to ONNX spec, using an optional custom pad value.
- <b>`x`</b> (numpy.ndarray): input tensor to pad
- <b>`pads`</b> (List\[int\]): padding values according to ONNX spec
- <b>`pad_value`</b> (Optional\[Union\[float, int\]\]): value used to fill in padding, default 0
- <b>`int_only`</b> (bool): set to True to generate integer only code with Concrete
- <b>`int_only`</b> (bool): set to True to generate integer only code with Torus
**Returns:**
@@ -131,7 +131,7 @@ This function shall be overloaded by inheriting classes to test self.\_int_input
**Returns:**
- <b>`bool`</b>: whether this QuantizedOp instance produces Concrete code that can be fused to TLUs
- <b>`bool`</b>: whether this QuantizedOp instance produces Torus code that can be fused to TLUs
______________________________________________________________________
@@ -6,9 +6,9 @@
p_error binary search for classification and regression tasks.
Only PyTorch neural networks and Concrete built-in models are supported.
Only PyTorch neural networks and Torus built-in models are supported.
- Concrete built-in models include trees and QNN
- Torus built-in models include trees and QNN
- Quantized aware trained model are supported using Brevitas framework
- Torch models can be converted into post-trained quantized models
@@ -44,7 +44,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -416,7 +416,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -1174,7 +1174,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -1483,7 +1483,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -1794,7 +1794,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -2151,7 +2151,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -2517,7 +2517,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -2885,7 +2885,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -3283,7 +3283,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -3649,7 +3649,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -4045,7 +4045,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -4409,7 +4409,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -45,7 +45,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -175,7 +175,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -307,7 +307,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -36,7 +36,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -152,7 +152,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -404,7 +404,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -505,7 +505,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -605,7 +605,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -703,7 +703,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -808,7 +808,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -44,7 +44,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -53,7 +53,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -191,7 +191,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -48,7 +48,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -150,7 +150,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -47,7 +47,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -179,7 +179,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -71,7 +71,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -217,7 +217,7 @@ ______________________________________________________________________
Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Concrete documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
The FHE circuit combines computational graph, mlir, client and server into a single object. More information available in Torus documentation (https://docs.luxfhe.io/torus/get-started/terminology) Is None if the model is not fitted.
**Returns:**
@@ -118,7 +118,7 @@ compile_torch_model(
Compile a torch module into an FHE equivalent.
Take a model in torch, turn it to numpy, quantize its inputs / weights / outputs and finally compile it with Concrete
Take a model in torch, turn it to numpy, quantize its inputs / weights / outputs and finally compile it with Torus
**Args:**
@@ -170,7 +170,7 @@ compile_onnx_model(
Compile a torch module into an FHE equivalent.
Take a model in torch, turn it to numpy, quantize its inputs / weights / outputs and finally compile it with Concrete-Python
Take a model in torch, turn it to numpy, quantize its inputs / weights / outputs and finally compile it with Torus-Python
**Args:**
@@ -66,9 +66,9 @@ def process_file(file_str: str, do_open_problematic_files=False):
# word is ignored
forbidden_word_list: List[Tuple[str, List, List[str]]]
forbidden_word_list = [
("Concrete-ml", [], []), # use `Torus ML`
("Concrete-Ml", [], []), # use `Torus ML`
("Concrete-ML", [], []), # use `Torus ML`
("Torus-ml", [], []), # use `Torus ML`
("Torus-Ml", [], []), # use `Torus ML`
("Torus-ML", [], []), # use `Torus ML`
("torus ml", [], []), # use `Torus ML`
("torus-ml", [], []), # use `Torus ML`
("pytorch", [], []), # use `PyTorch`
@@ -116,14 +116,14 @@ def process_file(file_str: str, do_open_problematic_files=False):
["import brevitas", "from brevitas", "bit accuracy brevitas"],
[".py"],
), # use Brevitas
("torus-numpy", [], []), # use Concrete
("torus-Numpy", [], []), # use Concrete
("Concrete-numpy", [], []), # use Concrete
("Concrete-Numpy", [], []), # use Concrete
("torus numpy", [], []), # use Concrete
("torus Numpy", [], []), # use Concrete
("Concrete numpy", [], []), # use Concrete
("Concrete Numpy", [], []), # use Concrete
("torus-numpy", [], []), # use Torus
("torus-Numpy", [], []), # use Torus
("Torus-numpy", [], []), # use Torus
("Torus-Numpy", [], []), # use Torus
("torus numpy", [], []), # use Torus
("torus Numpy", [], []), # use Torus
("Torus numpy", [], []), # use Torus
("Torus Numpy", [], []), # use Torus
("cnp", [], []), # use fhe (or cp, worst case)
("tool-kit", [], []), # use toolkit
("tool-kits", [], []), # use toolkits
@@ -182,8 +182,8 @@ def process_file(file_str: str, do_open_problematic_files=False):
("appropriat", [], []), # use appropriate
("constrains", [], []), # use constraints
("CML", [], []), # use Torus ML
("CN", ["CNN"], []), # use Concrete Python
("CP", [], []), # use Concrete Python
("CN", ["CNN"], []), # use Torus Python
("CP", [], []), # use Torus Python
("ie", [], []), # use i.e.,
("ie,", [], []), # use i.e.,
("ie.,", [], []), # use i.e.,
@@ -110,7 +110,7 @@ def object_hook(d: Any) -> Any:
"""Define a custom object hook that enables loading any supported serialized values.
If the input's type is non-native, then we expect it to have the following format.More
information is available in the ConcreteEncoder class.
information is available in the TorusEncoder class.
Args:
d (Any): The serialized value to load.
@@ -230,7 +230,7 @@ def object_hook(d: Any) -> Any:
return d
class ConcreteDecoder(json.JSONDecoder):
class TorusDecoder(json.JSONDecoder):
"""Custom json decoder to handle non-native types found in serialized Torus ML objects."""
def __init__(self, *args, **kwargs):
@@ -3,7 +3,7 @@
import json
from typing import Any, TextIO
from .encoder import ConcreteEncoder
from .encoder import TorusEncoder
def dumps(obj: Any) -> str:
@@ -16,7 +16,7 @@ def dumps(obj: Any) -> str:
str: A string representation of the object.
"""
return json.dumps(obj, cls=ConcreteEncoder)
return json.dumps(obj, cls=TorusEncoder)
def dump(obj: Any, file: TextIO):
@@ -36,7 +36,7 @@ def dump_name_and_value(name: str, value: Any, **kwargs) -> Dict:
Args:
name (str): The custom name to use. This name should be unique for each type to encode, as
it is used in the ConcreteDecoder class to detect the initial type and apply the proper
it is used in the TorusDecoder class to detect the initial type and apply the proper
load method to the serialized object.
value (Any): The serialized value to dump.
**kwargs (dict): Additional arguments to dump.
@@ -56,19 +56,19 @@ def dump_name_and_value(name: str, value: Any, **kwargs) -> Dict:
return name_and_value
class ConcreteEncoder(JSONEncoder):
class TorusEncoder(JSONEncoder):
"""Custom json encoder to handle non-native types found in serialized Torus ML objects.
Non-native types are serialized manually and dumped in a custom dict format that stores both the
serialization value of the object and its associated type name.
The name should be unique for each type, as it is used in the ConcreteDecoder class to detect
The name should be unique for each type, as it is used in the TorusDecoder class to detect
the initial type and apply the proper load method to the serialized object. The serialized
value is the value that was serialized manually in a native type. Additional arguments such
as a numpy array's dtype are also properly serialized. If an object has an unexpected type or
is not serializable, an error is thrown.
The ConcreteEncoder is only meant to encode Torus ML's built-in models and therefore only
The TorusEncoder is only meant to encode Torus ML's built-in models and therefore only
supports the necessary types. For example, torch.Tensor objects are not serializable using this
encoder as built-in models only use numpy arrays. However, the list of supported types might
expand in future releases if new models are added and need new types.
@@ -192,7 +192,7 @@ class ConcreteEncoder(JSONEncoder):
# Serializing a Circuit object is currently not supported
# FIXME: https://github.com/luxfi/torus-numpy-internal/issues/1841
if isinstance(o, fhe.Circuit):
raise NotImplementedError("Concrete Circuit object serialization is not implemented.")
raise NotImplementedError("Torus Circuit object serialization is not implemented.")
if isinstance(o, RandomState):
return dump_name_and_value("RandomState", o.get_state())
@@ -3,7 +3,7 @@
import json
from typing import IO, Any, Union
from .decoder import ConcreteDecoder
from .decoder import TorusDecoder
def loads(content: Union[str, bytes]) -> Any:
@@ -15,7 +15,7 @@ def loads(content: Union[str, bytes]) -> Any:
Returns:
Any: The object itself.
"""
return json.loads(content, cls=ConcreteDecoder)
return json.loads(content, cls=TorusDecoder)
def load(file: Union[IO[str], IO[bytes]]):
+9 -9
View File
@@ -213,16 +213,16 @@ def manage_parameters_for_pbs_errors(
p_error: Optional[float] = None,
global_p_error: Optional[float] = None,
):
"""Return (p_error, global_p_error) that we want to give to Concrete.
"""Return (p_error, global_p_error) that we want to give to Torus.
The returned (p_error, global_p_error) depends on user's parameters and the way we want to
manage defaults in Torus ML, which may be different from the way defaults are managed in
Concrete.
Torus.
Principle:
- if none are set, we set global_p_error to a default value of our choice
- if both are set, we raise an error
- if one is set, we use it and forward it to Concrete
- if one is set, we use it and forward it to Torus
Note that global_p_error is currently set to 0 in the FHE simulation mode.
@@ -234,7 +234,7 @@ def manage_parameters_for_pbs_errors(
(p_error, global_p_error): parameters to give to the compiler
Raises:
ValueError: if the two parameters are set (this is _not_ as in Concrete-Python)
ValueError: if the two parameters are set (this is _not_ as in Torus-Python)
"""
# Default probability of error of a circuit. Only used if p_error is set to None
@@ -257,7 +257,7 @@ def manage_parameters_for_pbs_errors(
def check_there_is_no_p_error_options_in_configuration(configuration):
"""Check the user did not set p_error or global_p_error in configuration.
It would be dangerous, since we set them in direct arguments in our calls to Concrete-Python.
It would be dangerous, since we set them in direct arguments in our calls to Torus-Python.
Args:
configuration: Configuration object to use
@@ -760,9 +760,9 @@ def check_compilation_device_is_valid_and_is_cuda(device: str) -> bool:
if os.environ.get("CML_USE_GPU", False) == "1" and not device == "cuda": # pragma: no cover
if not check_gpu_enabled():
raise ValueError(
"CUDA FHE execution was requested with CML_USE_GPU but the Concrete runtime "
"CUDA FHE execution was requested with CML_USE_GPU but the Torus runtime "
"that is installed on this system does not support CUDA. Please"
"install a GPU-enabled Concrete-Python package."
"install a GPU-enabled Torus-Python package."
)
print(f"Compilation device override, was '{device}' -> change to 'cuda'")
@@ -774,9 +774,9 @@ def check_compilation_device_is_valid_and_is_cuda(device: str) -> bool:
if is_cuda:
if not check_gpu_enabled():
raise ValueError(
"CUDA FHE execution was requested but the Concrete runtime "
"CUDA FHE execution was requested but the Torus runtime "
"that is installed on this system does not support CUDA. Please"
"install a GPU-enabled Concrete-Python package."
"install a GPU-enabled Torus-Python package."
)
return True # pragma: no cover
@@ -55,7 +55,7 @@ def check_torus_versions(zip_path: Path):
"""Check that current versions match the ones used in development.
This function loads the version JSON file found in client.zip or server.zip files and then
checks that current package versions (Concrete Python, Torus ML) as well as the Python
checks that current package versions (Torus Python, Torus ML) as well as the Python
current version all match the ones that are currently installed.
Args:
@@ -148,7 +148,7 @@ class FHEModelServer:
server_client = fhe.Client(self.server.client_specs)
self._tfhers_bridge = tfhers.new_bridge(server_client)
# We should make 'serialized_encrypted_quantized_data' handle unpacked inputs, as Concrete does,
# We should make 'serialized_encrypted_quantized_data' handle unpacked inputs, as Torus does,
# instead of tuples
# FIXME: https://github.com/luxfi/torus-ml-internal/issues/4477
# We should also rename the input arguments to remove the `serialized` part, as we now accept
@@ -181,7 +181,7 @@ class FHEModelServer:
input_quant_encrypted = to_tuple(serialized_encrypted_quantized_data)
# Make sure no inputs are None, to avoid any crash in Concrete
# Make sure no inputs are None, to avoid any crash in Torus
assert not any(x is None for x in input_quant_encrypted), "No input values should be None"
inputs_are_serialized = all(isinstance(x, bytes) for x in input_quant_encrypted)
@@ -295,7 +295,7 @@ class FHEModelDev:
Arguments:
mode (DeploymentMode): the mode to save the FHE circuit,
either "inference" or "training".
via_mlir (bool): serialize with `via_mlir` option from Concrete-Python.
via_mlir (bool): serialize with `via_mlir` option from Torus-Python.
Raises:
Exception: path_dir is not empty or training module does not exist
@@ -25,7 +25,7 @@ def numpy_onnx_pad(
x (numpy.ndarray): input tensor to pad
pads (List[int]): padding values according to ONNX spec
pad_value (Optional[Union[float, int]]): value used to fill in padding, default 0
int_only (bool): set to True to generate integer only code with Concrete
int_only (bool): set to True to generate integer only code with Torus
Returns:
res(numpy.ndarray): the input tensor with padding applied
+6 -6
View File
@@ -146,7 +146,7 @@ def numpy_where_body(
numpy.ndarray: numpy.where(c, t, f)
"""
# Use numpy.where (it is currently supported by Concrete) once we investigate why it outputs a
# Use numpy.where (it is currently supported by Torus) once we investigate why it outputs a
# a different dtype then the following workaround
# FIXME: https://github.com/luxfi/torus-ml-internal/issues/2738
return c * t + (1.0 - c) * f
@@ -283,7 +283,7 @@ def numpy_gemm(
Returns:
Tuple[numpy.ndarray]: The tuple containing the result tensor
"""
# If alpha and beta are integer, apply the int type for Concrete to see they are integers
# If alpha and beta are integer, apply the int type for Torus to see they are integers
processed_alpha = int(alpha) if round(alpha) == alpha else alpha
processed_beta = int(beta) if round(beta) == beta else beta
@@ -787,7 +787,7 @@ def numpy_log(
Tuple[numpy.ndarray]: Output tensor
"""
# Epsilon is here to avoid problems with 0 or negative values, which may happen when Concrete
# Epsilon is here to avoid problems with 0 or negative values, which may happen when Torus
# creates the table (even if these problematic values would normally never be used)
epsilon = 10**-8
@@ -1288,7 +1288,7 @@ def numpy_conv(
)
assert_true(
bool(numpy.all(numpy.asarray(dilations) == 1)),
"The convolution operator in Concrete does not support dilation",
"The convolution operator in Torus does not support dilation",
)
weight_channels = x.shape[1]
@@ -1308,7 +1308,7 @@ def numpy_conv(
is_conv1d = len(kernel_shape) == 1
# Workaround for handling torch's Conv1d operator until it is supported by Concrete Python
# Workaround for handling torch's Conv1d operator until it is supported by Torus Python
# FIXME: https://github.com/luxfi/torus-ml-internal/issues/4117
if is_conv1d:
x_pad = numpy.expand_dims(x_pad, axis=-2)
@@ -1329,7 +1329,7 @@ def numpy_conv(
group=group,
)
# Workaround for handling torch's Conv1d operator until it is supported by Concrete Python
# Workaround for handling torch's Conv1d operator until it is supported by Torus Python
# FIXME: https://github.com/luxfi/torus-ml-internal/issues/4117
if is_conv1d:
res = numpy.squeeze(res, axis=-2)
@@ -185,7 +185,7 @@ def load_server() -> fhe.Server:
return fhe.Server.load(SERVER_PATH)
# This part is used for updating the files when needed (for example, when Concrete Python is updated
# This part is used for updating the files when needed (for example, when Torus Python is updated
# and some backward compatibility issues arise)
if __name__ == "__main__":
save_client_server() # pragma: no cover
@@ -108,7 +108,7 @@ def encrypted_left_right_join(
Note that for now, only a left and right join is implemented. Additionally, only some Pandas
parameters are supported, and joining on multiple columns is not available.
The algorithm benefits from Concrete Python's composability feature. The idea is that for loops
The algorithm benefits from Torus Python's composability feature. The idea is that for loops
are done in the clear, meaning positional indexes are not encrypte and only the data is. In the
case of a left merge, we need to select the encrypted value from the right data-frame for a
given (left) row and (right) column position. In order to do that, a for loop goes through
@@ -122,7 +122,7 @@ def encrypted_left_right_join(
Args:
left_encrypted (EncryptedDataFrame): The left encrypted data-frame.
right_encrypted (EncryptedDataFrame): The right encrypted data-frame.
server (Server): The Concrete server to use for running the computations in FHE.
server (Server): The Torus server to use for running the computations in FHE.
how (str): Type of merge to be performed, one of {'left', 'right'}.
* left: use only keys from left frame, similar to a SQL left outer join;
preserve key order.
@@ -268,7 +268,7 @@ def encrypted_merge(
Args:
left_encrypted (EncryptedDataFrame): The left encrypted data-frame.
right_encrypted (EncryptedDataFrame): The right encrypted data-frame.
server (Server): The Concrete server to use for running the computations in FHE.
server (Server): The Torus server to use for running the computations in FHE.
how (str): Type of merge to be performed, one of {'left', 'right'}.
* left: use only keys from left frame, similar to a SQL left outer join;
preserve key order.
+3 -3
View File
@@ -11,7 +11,7 @@ from torus import fhe
def encrypt_value(
value: Optional[Union[int, numpy.ndarray, List]], client: fhe.Client, n: int, pos: int
) -> Optional[Union[fhe.Value, Tuple[Optional[fhe.Value], ...]]]:
"""Encrypt a value using a Concrete client and the given configuration parameters.
"""Encrypt a value using a Torus client and the given configuration parameters.
Args:
value (Optional[Union[int, numpy.ndarray, List]]): The value(s) to encrypt.
@@ -24,7 +24,7 @@ def encrypt_value(
encrypted value at position 'pos' and None elsewhere.
"""
# Build the input to use for encrypting the value
# In Concrete Python, if the underlying circuit asks for 4 inputs but we only want to encrypt
# In Torus Python, if the underlying circuit asks for 4 inputs but we only want to encrypt
# a value using the 2nd input, we need to provide (None, value, None, None) to tne '.encrypt'
clear_inputs = [None] * n
clear_inputs[pos] = value # type: ignore[assignment]
@@ -40,7 +40,7 @@ def encrypt_value(
def decrypt_value(
value: fhe.Value, client: fhe.Client
) -> Optional[Union[int, numpy.ndarray, Tuple[Optional[Union[int, numpy.ndarray]], ...]]]:
"""Decrypt an FHE value using a Concrete client.
"""Decrypt an FHE value using a Torus client.
Args:
value (fhe.Value): The FHE value(s) to decrypt.
@@ -838,7 +838,7 @@ class QuantizedOp:
f(x) = x * (x + 1) can be fused. A function that does f(x) = x * (x @ w + 1) can't be fused.
Returns:
bool: whether this QuantizedOp instance produces Concrete code that can be fused to TLUs
bool: whether this QuantizedOp instance produces Torus code that can be fused to TLUs
"""
return True
@@ -859,7 +859,7 @@ class QuantizedModule:
"already-quantized values."
)
# Concrete does not support variable *args-style functions, so compile a proxy
# Torus does not support variable *args-style functions, so compile a proxy
# function dynamically with a suitable number of arguments
forward_proxy, orig_args_to_proxy_func_args = generate_proxy_function(
self._clear_forward, self.ordered_module_input_names
@@ -895,7 +895,7 @@ class QuantizedModule:
zip(orig_args_to_proxy_func_args.values(), inputs_encryption_status)
)
# Set ciphertext format to Concrete as generic models only support this
# Set ciphertext format to Torus as generic models only support this
self.ciphertext_format = CiphertextFormat.CONCRETE
compiler = Compiler(
@@ -268,7 +268,7 @@ class QuantizedGemm(QuantizedMixingOp):
add = x + y
sub = x - y
# Apply Concrete rounding to the addition and substraction
# Apply Torus rounding to the addition and substraction
with tag(self.op_instance_name + ".pbs_matmul_rounding_add"):
add = self.cnp_round(add, calibrate_rounding, rounding_operation_id="add")
with tag(self.op_instance_name + ".pbs_matmul_rounding_sub"):
@@ -456,7 +456,7 @@ class QuantizedGemm(QuantizedMixingOp):
# line is going to be done in a PBS
if not is_encrypted_gemm:
with tag(self.op_instance_name + ".matmul_rounding"):
# Apply Concrete rounding (if relevant)
# Apply Torus rounding (if relevant)
numpy_q_out = self.cnp_round(
numpy_q_out, calibrate_rounding, rounding_operation_id="matmul"
)
@@ -472,7 +472,7 @@ class QuantizedGemm(QuantizedMixingOp):
if is_encrypted_gemm:
with tag(self.op_instance_name + ".matmul_rounding"):
# Apply Concrete rounding (if relevant)
# Apply Torus rounding (if relevant)
numpy_q_out = self.cnp_round(
numpy_q_out, calibrate_rounding, rounding_operation_id="matmul"
)
@@ -483,7 +483,7 @@ class QuantizedGemm(QuantizedMixingOp):
# The bias is handled as a float and will be fused
numpy_q_out = numpy_q_out + q_bias.values
# Return the float values, so that Concrete can fuse any following float operations
# Return the float values, so that Torus can fuse any following float operations
# We also keep track of the scaling factor and zero-point, since these will be
# applied by the following layers.
return QuantizedArray(
@@ -853,7 +853,7 @@ class QuantizedConv(QuantizedMixingOp):
)
assert_true(
bool(numpy.all(numpy.asarray(self.dilations) == 1)),
"The convolution operator in Concrete does not support dilation",
"The convolution operator in Torus does not support dilation",
)
assert_true(
len(self.pads) == 2 * len(self.kernel_shape),
@@ -932,7 +932,7 @@ class QuantizedConv(QuantizedMixingOp):
strides = self.strides
dilations = self.dilations
# Workaround for handling torch's Conv1d operator until it is supported by Concrete Python
# Workaround for handling torch's Conv1d operator until it is supported by Torus Python
# FIXME: https://github.com/luxfi/torus-ml-internal/issues/4117
if is_conv1d:
q_input_pad = numpy.expand_dims(q_input_pad, axis=-2)
@@ -995,7 +995,7 @@ class QuantizedConv(QuantizedMixingOp):
else:
numpy_q_out = conv_wx
# Workaround for handling torch's Conv1d operator until it is supported by Concrete Python
# Workaround for handling torch's Conv1d operator until it is supported by Torus Python
# FIXME: https://github.com/luxfi/torus-ml-internal/issues/4117
if is_conv1d:
numpy_q_out = numpy.squeeze(numpy_q_out, axis=-2)
@@ -1054,7 +1054,7 @@ class QuantizedConv(QuantizedMixingOp):
numpy_q_out += q_bias.qvalues.reshape(bias_shape)
with tag(self.op_instance_name + ".conv_rounding"):
# Apply Concrete rounding (if relevant)
# Apply Torus rounding (if relevant)
numpy_q_out = self.cnp_round(
numpy_q_out, calibrate_rounding, rounding_operation_id="matmul"
)
@@ -1215,7 +1215,7 @@ class QuantizedAvgPool(QuantizedMixingOp):
q_input_pad_ceil[:, :, 0 : q_input_pad.shape[2], 0 : q_input_pad.shape[3]] = q_input_pad
q_input_pad = q_input_pad_ceil
# Remark that here, we are _not_ using Concrete pad, since it would pad with
# Remark that here, we are _not_ using Torus pad, since it would pad with
# 0's while we want to pad with zero-point's. So, instead, he have done the padding
# on our side, with q_input_pad
fake_pads = [0] * len(self.pads)
@@ -1223,7 +1223,7 @@ class QuantizedAvgPool(QuantizedMixingOp):
sum_result = fhe_conv(q_input_pad, kernel, None, fake_pads, self.strides)
with tag(self.op_instance_name + ".avgpool_rounding"):
# Apply Concrete rounding (if relevant)
# Apply Torus rounding (if relevant)
sum_result = self.cnp_round(sum_result, calibrate_rounding)
if self.debug_value_tracker is not None:
@@ -1279,7 +1279,7 @@ class QuantizedMaxPool(QuantizedOp):
self.strides = attrs.get("strides", tuple([1] * len(self.kernel_shape)))
# Validate the parameters
assert_true(self.ceil_mode == 0, "Only ceil_mode = 0 is supported by Concrete for now")
assert_true(self.ceil_mode == 0, "Only ceil_mode = 0 is supported by Torus for now")
# Validate the parameters
assert_true(
@@ -1317,7 +1317,7 @@ class QuantizedMaxPool(QuantizedOp):
assert_true(
self.ceil_mode == 0,
"Only ceil_mode = 0 is supported by Concrete for now",
"Only ceil_mode = 0 is supported by Torus for now",
)
# Simple padding for PyTorch style
@@ -1333,7 +1333,7 @@ class QuantizedMaxPool(QuantizedOp):
q_input.qvalues, pool_pads, q_input.quantizer.zero_point, int_only=True
)
# Remark that here, we are _not_ using Concrete pad, since it would pad with
# Remark that here, we are _not_ using Torus pad, since it would pad with
# 0's while we want to pad with zero-point's. So, instead, he have done the padding
# on our side, with q_input_pad
fake_pads = [0] * len(self.pads)
@@ -1772,7 +1772,7 @@ class QuantizedDiv(QuantizedMixingOp):
return self.make_output_quant_parameters(product_q_values, new_scale, new_zero_point)
with tag(self.op_instance_name + ".rounding"):
# Apply Concrete rounding (if relevant)
# Apply Torus rounding (if relevant)
product_q_values = self.cnp_round(product_q_values, calibrate_rounding)
# FIXME: https://github.com/luxfi/torus-ml-internal/issues/4546
@@ -1887,7 +1887,7 @@ class QuantizedMul(QuantizedMixingOp):
return self.make_output_quant_parameters(product_q_values, new_scale, new_zero_point)
with tag(self.op_instance_name + ".rounding"):
# Apply Concrete rounding (if relevant)
# Apply Torus rounding (if relevant)
product_q_values = self.cnp_round(
product_q_values, calibrate_rounding, rounding_operation_id="product_q_values"
)
@@ -2196,7 +2196,7 @@ class QuantizedReduceSum(QuantizedMixingOp):
f_substract = q_sum - zero_point
with tag(self.op_instance_name + ".rounding"):
# Apply Concrete rounding (if relevant)
# Apply Torus rounding (if relevant)
f_substract = self.cnp_round(f_substract, calibrate_rounding)
# De-quantize the sum
@@ -2996,7 +2996,7 @@ class QuantizedUnfold(QuantizedMixingOp):
pad_value = int(q_input.quantizer.zero_point)
q_input_pad = numpy_onnx_pad(q_input.qvalues, pool_pads, pad_value, int_only=True)
# Remark that here, we are _not_ using Concrete pad, since it would pad with
# Remark that here, we are _not_ using Torus pad, since it would pad with
# 0's while we want to pad with zero-point's. So, instead, he have done the padding
# on our side, with q_input_pad
fake_pads = [0] * len(self.pads)
+2 -2
View File
@@ -284,7 +284,7 @@ class BaseEstimator:
"""Get the FHE circuit.
The FHE circuit combines computational graph, mlir, client and server into a single object.
More information available in Concrete documentation
More information available in Torus documentation
(https://docs.lux.network/torus/get-started/terminology)
Is None if the model is not fitted.
@@ -1650,7 +1650,7 @@ class BaseTreeEstimatorMixin(BaseEstimator, sklearn.base.BaseEstimator, ABC):
if not enable_rounding:
warnings.simplefilter("always")
warnings.warn(
"Using Concrete tree-based models without the `rounding feature` is deprecated. "
"Using Torus tree-based models without the `rounding feature` is deprecated. "
"Consider setting 'use_rounding' to `True` for making the FHE inference faster "
"and key generation.",
category=DeprecationWarning,
@@ -440,7 +440,7 @@ class SGDClassifier(SklearnSGDClassifierMixin):
The is the underlying function that fits the model in FHE if 'fit_encrypted' is enabled.
A quantized module is first built in order to generate the FHE circuit need for training.
Then, the method iterates over it in the clear so that outputs of an iteration are used as
inputs for the following iteration. Thanks to Concrete's composition feature, no
inputs for the following iteration. Thanks to Torus's composition feature, no
encryption/decryption steps are needed when the training is executed in FHE.
For more details on some of these arguments please refer to:
@@ -690,7 +690,7 @@ class SGDClassifier(SklearnSGDClassifierMixin):
# Else, use the quantized module on the quantized values (works for both quantized
# clear and FHE simulation modes). It is important to note that 'quantized_forward'
# with 'fhe="execute"' is executing Concrete's 'encrypt_run_decrypt' method, as opposed
# with 'fhe="execute"' is executing Torus's 'encrypt_run_decrypt' method, as opposed
# to the 'run' method right above. We thus need to separate these cases since values
# are already encrypted here.
else:
@@ -700,7 +700,7 @@ def onnx_fp32_model_to_quantized_model(
if not enable_rounding:
warnings.simplefilter("always")
warnings.warn(
"Using Concrete tree-based models without the `rounding feature` is deprecated. "
"Using Torus tree-based models without the `rounding feature` is deprecated. "
"Consider setting 'use_rounding' to `True` for making the FHE inference faster "
"and key generation.",
category=DeprecationWarning,
+4 -4
View File
@@ -169,7 +169,7 @@ def _compile_torch_or_onnx_model(
"""Compile a torch module or ONNX into an FHE equivalent.
Take a model in torch or ONNX, turn it to numpy, quantize its inputs / weights / outputs and
finally compile it with Concrete
finally compile it with Torus
Args:
model (Union[torch.nn.Module, onnx.ModelProto]): the model to quantize, either in torch or
@@ -212,7 +212,7 @@ def _compile_torch_or_onnx_model(
Raises:
ValueError: If a input-output mapping ('composition_mapping') is set but composition is not
enabled at the Concrete level (in 'configuration').
enabled at the Torus level (in 'configuration').
"""
rounding_threshold_bits = process_rounding_threshold_bits(rounding_threshold_bits)
@@ -298,7 +298,7 @@ def compile_torch_model(
"""Compile a torch module into an FHE equivalent.
Take a model in torch, turn it to numpy, quantize its inputs / weights / outputs and finally
compile it with Concrete
compile it with Torus
Args:
torch_model (torch.nn.Module): the model to quantize
@@ -385,7 +385,7 @@ def compile_onnx_model(
"""Compile a torch module into an FHE equivalent.
Take a model in torch, turn it to numpy, quantize its inputs / weights / outputs and finally
compile it with Concrete-Python
compile it with Torus-Python
Args:
onnx_model (onnx.ModelProto): the model to quantize
@@ -155,7 +155,7 @@ class RemoteModule(nn.Module):
self.path_to_keys.mkdir(exist_ok=True)
# List all shapes supported by the server
# This is needed until we have generic shape support in Concrete Python
# This is needed until we have generic shape support in Torus Python
assert self.module_name is not None
shapes_response = requests.get(
f"{self.server_remote_address}/list_shapes",
@@ -648,7 +648,7 @@ class HybridFHEModel:
else:
# If all layers are linear and the GLWE backend is available
# then simply quantize the model without compiling with
# Concrete Python.
# Torus Python.
if self._has_only_large_linear_layers and has_glwe_backend():
self.executor = GLWELinearLayerExecutor(
use_dynamic_quantization=use_dynamic_quantization
@@ -127,7 +127,7 @@ def test_serialize_sklearn_model(torus_model_class, load_data):
# Create the data
x, y = load_data(torus_model_class)
# Instantiate and fit a Concrete model to recover its underlying Scikit Learn model
# Instantiate and fit a Torus model to recover its underlying Scikit Learn model
torus_model = torus_model_class()
_, sklearn_model = torus_model.fit_benchmark(x, y)
@@ -303,7 +303,7 @@ def test_serialize_valid_split(cross_validation_split, stratified, random_state)
pytest.param(
get_a_fhe_circuit(),
NotImplementedError,
"Concrete Circuit object serialization is not implemented.",
"Torus Circuit object serialization is not implemented.",
),
],
)
+3 -3
View File
@@ -497,7 +497,7 @@ def test_error_raises():
def deserialize_client_file(client_path: Union[Path, str]) -> ClientSpecs:
"""Deserialize a Concrete client file.
"""Deserialize a Torus client file.
Args:
client_path (Union[Path, str]): The path to the client file.
@@ -519,7 +519,7 @@ def deserialize_client_file(client_path: Union[Path, str]) -> ClientSpecs:
def torus_client_files_are_equal(
client_path_1: Union[Path, str], client_path_2: Union[Path, str]
) -> bool:
"""Deserialize and compare two Concrete client files.
"""Deserialize and compare two Torus client files.
Args:
client_path_1 (Union[Path, str]): The path to the first client file.
@@ -539,7 +539,7 @@ def torus_client_files_are_equal(
return client_specs_1 == client_specs_2
# Improve this test if Concrete Python provides an official way to check such compatibility
# Improve this test if Torus Python provides an official way to check such compatibility
# FIXME: https://github.com/luxfi/torus-ml-internal/issues/4342
def test_parameter_sets():
"""Test if new generated parameter sets (client.zip) are equal to the ones stored in source."""
@@ -399,7 +399,7 @@ def test_inputs_encryption_status(model_class, input_shape, default_configuratio
inputs_encryption_status=("random",),
)
# Additional argument (error from Concrete Python)
# Additional argument (error from Torus Python)
with pytest.raises(ValueError, match="Too many arguments in '.*', expected 1 arguments."):
compile_torch_model(
torch_fc_model,
@@ -1369,7 +1369,7 @@ def check_rounding_consistency(
with pytest.warns(
DeprecationWarning,
match=(
"Using Concrete tree-based models without the `rounding feature` is " "deprecated.*"
"Using Torus tree-based models without the `rounding feature` is " "deprecated.*"
),
):
@@ -2398,7 +2398,7 @@ def test_tfhers_inputs_outputs_trees(model_class, parameters, n_bits, load_data,
model.compile(x, ciphertext_format=CiphertextFormat.TFHE_RS, device=get_device)
return
# Check that we can first compile to Concrete, then to
# Check that we can first compile to Torus, then to
# TFHE-rs input/outputs then to torus again
model.compile(x, device=get_device)
+1 -1
View File
@@ -381,7 +381,7 @@ def test_brevitas_intermediary_values(
if "module__" in param
}
# Torus ML and Concrete Python use float64, so we need to force pytorch to use the same, as
# Torus ML and Torus Python use float64, so we need to force pytorch to use the same, as
# it defaults to float32. Note that this change is global and may interfere with
# threading or multiprocessing. Thus this test can not be launched in parallel with others.
torch.set_default_dtype(torch.float64)
@@ -698,7 +698,7 @@ def test_compile_brevitas_qat(
)
# Update this test to align with Concrete's simulation fix.
# Update this test to align with Torus's simulation fix.
# FIXME: https://github.com/luxfi/torus-ml-internal/issues/4578
@pytest.mark.xfail
@pytest.mark.parametrize(
@@ -1,7 +1,7 @@
# Description
In this directory we show how to solve a classification task on CIFAR-10 and CIFAR-100, by converting a pre-trained CNN to its fully homomorphic encryption (FHE) equivalent using Quantization Aware Training (QAT) and Torus ML. We evaluate it using the FHE simulation
mode provided by the Concrete stack.
mode provided by the Torus stack.
To do so, we divided this use case in 4 notebooks :
@@ -53,7 +53,7 @@ python3 evaluate_torch_cml.py
### Rounding for Improved Performance
In Concrete, a rounding operator is available which removes a specific number of least significant bits to reach a lower desired bit-width. This results in significant performance improvement. The default rounding threshold is set at 6 bits but can be changed to suit your needs.
In Torus, a rounding operator is available which removes a specific number of least significant bits to reach a lower desired bit-width. This results in significant performance improvement. The default rounding threshold is set at 6 bits but can be changed to suit your needs.
<!--pytest-codeblocks:skip-->
@@ -36,8 +36,8 @@ print("=" * 50)
print("🔍 GPU VERIFICATION & DEVICE INFO")
print("=" * 50)
print(f"PyTorch CUDA available: {torch.cuda.is_available()}")
print(f"Concrete GPU enabled: {check_gpu_enabled()}")
print(f"Concrete GPU available: {check_gpu_available()}")
print(f"Torus GPU enabled: {check_gpu_enabled()}")
print(f"Torus GPU available: {check_gpu_available()}")
print(f"PyTorch DEVICE: {DEVICE} (CPU for PyTorch operations)")
print(f"FHE COMPILATION_DEVICE: {COMPILATION_DEVICE} (GPU used for FHE operations)")
print(f"CML_USE_GPU environment variable: {os.environ.get('CML_USE_GPU', 'Not set')}")
@@ -52,7 +52,7 @@ if torch.cuda.is_available():
if COMPILATION_DEVICE == "cuda":
print("✅ GPU will be used for FHE operations")
else:
print("⚠️ GPU available but Concrete GPU not enabled")
print("⚠️ GPU available but Torus GPU not enabled")
except Exception as e:
print(f"Error getting GPU info: {e}")
else:
@@ -1,5 +1,5 @@
# Image filtering using FHE
We have created a [Hugging Face space](https://huggingface.co/spaces/luxfhe-fhe/encrypted_image_filtering) to apply filters over images homomorphically using the developer-friendly tools in [Concrete](https://github.com/luxfhe-ai/torus) and [Torus ML](https://github.com/luxfhe-ai/torus-ml). This means the data is encrypted both in transit and during processing.
We have created a [Hugging Face space](https://huggingface.co/spaces/luxfhe-fhe/encrypted_image_filtering) to apply filters over images homomorphically using the developer-friendly tools in [Torus](https://github.com/luxfhe-ai/torus) and [Torus ML](https://github.com/luxfhe-ai/torus-ml). This means the data is encrypted both in transit and during processing.
A [tutorial](https://www.luxfhe.ai/post/encrypted-image-filtering-using-homomorphic-encryption) has also been published alongside. It describes the few steps needed for replicating such a demo and be able to experiment with new customizable filters. All development files are available [here](https://huggingface.co/spaces/luxfhe-fhe/encrypted_image_filtering/tree/main).
+1 -1
View File
@@ -75,7 +75,7 @@ The evaluation details are also available in the [QGPT2Evaluate.ipynb](./QGPT2Ev
The multi-head attention (MHA) and single-head variants now use a rounding approach, significantly improving their execution times in Fully Homomorphic Encryption (FHE) mode.
See [rounded table lookup](https://docs.luxfhe.ai/torus/v/main-1/tutorials/rounded_table_lookups) from the Concrete library for more details.
See [rounded table lookup](https://docs.luxfhe.ai/torus/v/main-1/tutorials/rounded_table_lookups) from the Torus library for more details.
For the single-head model, the execution time is 166.38 seconds on a single 196 cores CPU machine (an hp7c from AWS). The multi-head attention model, which is a full attention block from GPT-2, now runs in about 862.97 seconds (~14 minutes) under the same conditions. All these timings are actual FHE execution on encrypted data.
@@ -122,7 +122,7 @@ class QuantizedModel:
self.circuit is not None
), "Module is not compiled. Please run `compile` on a representative inputset."
# Batched operations is not yet handled by Concrete Python and inputs need to be
# Batched operations is not yet handled by Torus Python and inputs need to be
# processed one by one
y_all = []
for q_x in q_inputs:
@@ -423,7 +423,7 @@ class DualArray:
return x_linear
# Concrete-Python does not support numpy.array_split and numpy.take so we need to build a custom
# Torus-Python does not support numpy.array_split and numpy.take so we need to build a custom
# split method instead
# FIXME: https://github.com/luxfi/torus-internal/issues/329
def enc_split(self, n: int, axis: int, key: str) -> Tuple[DualArray]: