mirror of
https://github.com/zama-ai/concrete.git
synced 2026-01-09 12:57:55 -05:00
docs(frontend): add documentation for fhe modules
This commit is contained in:
committed by
Quentin Bourgerie
parent
c838b7fdb6
commit
2eae0710ed
@@ -32,6 +32,7 @@
|
||||
* [Reuse arguments](compilation/reuse_arguments.md)
|
||||
* [Multi precision](compilation/multi_precision.md)
|
||||
* [Multi parameters](compilation/multi_parameters.md)
|
||||
* [Modules](compilation/modules.md)
|
||||
* [Decorator](compilation/decorator.md)
|
||||
* [Direct circuits](compilation/direct_circuits.md)
|
||||
|
||||
|
||||
51
docs/compilation/modules.md
Normal file
51
docs/compilation/modules.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Modules
|
||||
|
||||
{% hint style="warning" %}
|
||||
Modules are still experimental. They are only compatible with [composition](../compilation/composition.md), which means the outputs of every functions can be used directly as inputs for other functions. The crypto-parameters used in this mode are large and thus, the execution is likely to slow.
|
||||
{% endhint %}
|
||||
|
||||
In some cases, deploying a server that can execute different functions is useful. *Concrete* can compile FHE _modules_, that can contain many different functions to execute at once. All the functions are compiled in a single step and can be [deployed with the same artifacts](../guides/deploy.md#deployment-of-modules). Here is an example:
|
||||
|
||||
```python
|
||||
from concrete import fhe
|
||||
|
||||
@fhe.module()
|
||||
class MyModule:
|
||||
@fhe.function({"x": "encrypted"})
|
||||
def inc(x):
|
||||
return x + 1 % 20
|
||||
|
||||
@fhe.function({"x": "encrypted"})
|
||||
def dec(x):
|
||||
return x - 1 % 20
|
||||
```
|
||||
|
||||
You can compile the FHE module `MyModule` using the `compile` method. To do that, you need to provide a dictionnary of input sets for every function:
|
||||
|
||||
```python
|
||||
inputset = list(range(20))
|
||||
my_module = MyModule.compile({"inc": inputset, "dec": inputset})
|
||||
```
|
||||
|
||||
{% hint style="warning" %}
|
||||
Note that here we can see a current limitation of modules: The configuration must use the `parameter_selection_strategy` of `v0`, and activate the `composable` flag.
|
||||
{% endhint %}
|
||||
|
||||
After the module has been compiled, we can encrypt and call the different functions in the following way:
|
||||
|
||||
```python
|
||||
x = 5
|
||||
x_enc = my_module.inc.encrypt(x)
|
||||
x_inc_enc = my_module.inc.run(x_enc)
|
||||
x_inc = my_module.inc.decrypt(x_inc_enc)
|
||||
assert x_inc == 6
|
||||
|
||||
x_inc_dec_enc = my_module.dec.run(x_inc_enc)
|
||||
x_inc_dec = my_module.dec.decrypt(x_inc_dec_enc)
|
||||
assert x_inc_dec == 5
|
||||
|
||||
for _ in range(10):
|
||||
x_enc = my_module.inc.run(x_enc)
|
||||
x_dec = my_module.inc.decrypt(x_enc)
|
||||
assert x_dec == 15
|
||||
```
|
||||
@@ -131,3 +131,58 @@ Then, decrypt the result:
|
||||
decrypted_result = client.decrypt(deserialized_result)
|
||||
assert decrypted_result == 49
|
||||
```
|
||||
|
||||
# Deployment of modules
|
||||
|
||||
Deploying a [module](../compilation/modules.md#modules) follows the same logic as the deployment of circuits. Assuming a module compiled in the following way:
|
||||
|
||||
<!--pytest-codeblocks:skip-->
|
||||
```python
|
||||
from concrete import fhe
|
||||
|
||||
@fhe.module()
|
||||
class MyModule:
|
||||
@fhe.function({"x": "encrypted"})
|
||||
def inc(x):
|
||||
return x + 1
|
||||
|
||||
@fhe.function({"x": "encrypted"})
|
||||
def dec(x):
|
||||
return x - 1
|
||||
|
||||
inputset = list(range(20))
|
||||
my_module = MyModule.compile({"inc": inputset, "dec": inputset})
|
||||
)
|
||||
```
|
||||
|
||||
You can extract the server from the module and save it in a file:
|
||||
|
||||
<!--pytest-codeblocks:skip-->
|
||||
```python
|
||||
my_module.server.save("server.zip")
|
||||
```
|
||||
|
||||
The only noticeable difference between the deployment of modules and the deployment of circuits is that the methods `Client::encrypt`, `Client::decrypt` and `Server::run` must contain an extra `function_name` argument specifying the name of the targeted function.
|
||||
|
||||
The encryption of an argument for the `inc` function of the module would be:
|
||||
|
||||
<!--pytest-codeblocks:skip-->
|
||||
```python
|
||||
arg = client.encrypt(7, function_name="inc")
|
||||
serialized_arg = arg.serialize()
|
||||
```
|
||||
|
||||
The execution of the `inc` function would be :
|
||||
|
||||
<!--pytest-codeblocks:skip-->
|
||||
```python
|
||||
result = server.run(deserialized_arg, evaluation_keys=deserialized_evaluation_keys, function_name="inc")
|
||||
serialized_result = result.serialize()
|
||||
```
|
||||
|
||||
Finally, decrypting a result from the execution of `dec` would be:
|
||||
|
||||
<!--pytest-codeblocks:skip-->
|
||||
```python
|
||||
decrypted_result = client.decrypt(deserialized_result, function_name="dec")
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user