Skip to content

Commit

Permalink
chore: generate keys implicitely when getting the keys
Browse files Browse the repository at this point in the history
  • Loading branch information
jfrery committed May 7, 2024
1 parent d1d2126 commit 671045c
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 34 deletions.
5 changes: 1 addition & 4 deletions docs/advanced_examples/ClientServer.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,7 @@
"fhemodel_client = FHEModelClient(network.client_dir.name, key_dir=network.client_dir.name)\n",
"\n",
"# The client first need to create the private and evaluation keys.\n",
"fhemodel_client.generate_private_and_evaluation_keys()\n",
"\n",
"# Get the serialized evaluation keys\n",
"serialized_evaluation_keys = fhemodel_client.get_serialized_evaluation_keys()"
"serialized_evaluation_keys = fhemodel_client.generate_private_and_evaluation_keys()"
]
},
{
Expand Down
46 changes: 31 additions & 15 deletions docs/guides/client_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,51 @@ The `FHEModelDev`, `FHEModelClient`, and `FHEModelServer` classes in the `concre

### Example Usage

<!--pytest-codeblocks:skip-->

```python
# Development machine
dev = FHEModelDev(path_dir='path/to/save', model=my_trained_model)
from concrete.ml.sklearn import DecisionTreeClassifier
from concrete.ml.deployment import FHEModelDev, FHEModelClient, FHEModelServer
import numpy as np

# Define the directory for FHE client/server files
fhe_directory = '/tmp/fhe_client_server_files/'

# Initialize the Decision Tree model
model = DecisionTreeClassifier()

# Generate some random data for training
X = np.random.rand(100, 20)
y = np.random.randint(0, 2, size=100)

# Train and compile the model
model.fit(X, y)
model.compile(X)

# Setup the development environment
dev = FHEModelDev(path_dir=fhe_directory, model=model)
dev.save()

# Client machine
client = FHEModelClient(path_dir='path/to/client/zip', key_dir='path/to/keys')
client.generate_private_and_evaluation_keys()
# Setup the client
client = FHEModelClient(path_dir=fhe_directory, key_dir="/tmp/keys_client")
serialized_evaluation_keys = client.get_serialized_evaluation_keys()
# The client encrypts the data to be sent to the server for processing.
encrypted_data = client.quantize_encrypt_serialize(my_data)

# Server machine
server = FHEModelServer(path_dir='path/to/server/zip')
# Client pre-processes new data
X_new = np.random.rand(1, 20)
encrypted_data = client.quantize_encrypt_serialize(X_new)

# Setup the server
server = FHEModelServer(path_dir=fhe_directory)
server.load()

# Run the FHE execution on the encrypted data.
# Server processes the encrypted data
encrypted_result = server.run(encrypted_data, serialized_evaluation_keys)

# Back to Client machine
# The client decrypts the result.
# Client decrypts the result
result = client.deserialize_decrypt_dequantize(encrypted_result)
```

> **Data Transfer Overview:**
>
> - **From Client to Server:** `serialized_evaluation_keys`, `encrypted_data`.
> - **From Client to Server:** `serialized_evaluation_keys` (once), `encrypted_data`.
> - **From Server to Client:** `encrypted_result`.
These objects are serialized into bytes to streamline the data transfer between the client and server.
Expand Down
3 changes: 3 additions & 0 deletions src/concrete/ml/deployment/fhe_client_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ def get_serialized_evaluation_keys(self) -> bytes:
Returns:
bytes: the evaluation keys
"""
# Generate private and evaluation keys if not already generated
self.generate_private_and_evaluation_keys(force=False)

return self.client.evaluation_keys.serialize()

def quantize_encrypt_serialize(self, x: numpy.ndarray) -> bytes:
Expand Down
3 changes: 1 addition & 2 deletions src/concrete/ml/torch/hybrid_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,8 @@ def init_fhe_client(
path_dir=str(path_to_client.resolve()), key_dir=str(self.path_to_keys.resolve())
)
# The client first need to create the private and evaluation keys.
client.generate_private_and_evaluation_keys()
# Get the serialized evaluation keys
serialized_evaluation_keys = client.get_serialized_evaluation_keys()

if self.verbose:
print(f"Evaluation keys size: {len(serialized_evaluation_keys) / (10**6):.2f} MB")
assert isinstance(serialized_evaluation_keys, bytes)
Expand Down
1 change: 0 additions & 1 deletion tests/deployment/test_client_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ def check_client_server_execution(
fhe_model_server.load()

# Client side : Generate all keys and serialize the evaluation keys for the server
fhe_model_client.generate_private_and_evaluation_keys()
evaluation_keys = fhe_model_client.get_serialized_evaluation_keys()

# Client side : Encrypt the data
Expand Down
4 changes: 1 addition & 3 deletions tests/deployment/test_deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,8 @@ def test_deploy(load_data, tmp_path): # pylint: disable=too-many-locals,too-man
client = FHEModelClient(path_dir=tmp_path, key_dir=tmp_path / "keys")

# The client first need to create the private and evaluation keys.
client.generate_private_and_evaluation_keys()

# Get the serialized evaluation keys
serialized_evaluation_keys = client.get_serialized_evaluation_keys()

assert isinstance(serialized_evaluation_keys, bytes)

# Evaluation keys can be quite large files but only have to be shared once with the server.
Expand Down
4 changes: 1 addition & 3 deletions use_case_examples/deployment/breast_cancer_builtin/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,8 @@
client = FHEModelClient(path_dir=str(ROOT.resolve()), key_dir=str((ROOT / "keys").resolve()))

# The client first need to create the private and evaluation keys.
client.generate_private_and_evaluation_keys()

# Get the serialized evaluation keys
serialized_evaluation_keys = client.get_serialized_evaluation_keys()

assert isinstance(serialized_evaluation_keys, bytes)

# Evaluation keys can be quite large files but only have to be shared once with the server.
Expand Down
4 changes: 1 addition & 3 deletions use_case_examples/deployment/cifar/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,8 @@ def main():
client = FHEModelClient(path_dir="./", key_dir="./keys")

# The client first need to create the private and evaluation keys.
client.generate_private_and_evaluation_keys()

# Get the serialized evaluation keys
serialized_evaluation_keys = client.get_serialized_evaluation_keys()

assert isinstance(serialized_evaluation_keys, bytes)

# Evaluation keys can be quite large files but only have to be shared once with the server.
Expand Down
4 changes: 1 addition & 3 deletions use_case_examples/deployment/sentiment_analysis/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,8 @@ def main():
client = FHEModelClient(path_dir="./", key_dir="./keys")

# The client first need to create the private and evaluation keys.
client.generate_private_and_evaluation_keys()

# Get the serialized evaluation keys
serialized_evaluation_keys = client.get_serialized_evaluation_keys()

assert isinstance(serialized_evaluation_keys, bytes)
# Evaluation keys can be quite large files but only have to be shared once with the server.
# Check the size of the evaluation keys (in MB)
Expand Down

0 comments on commit 671045c

Please sign in to comment.