mirror of
https://github.com/luxfhe/ml-sdk.git
synced 2026-11-02 12:32:08 +00:00
Brand-only sweep. Touches READMEs, docs, package metadata, comments,
notebook markdown, requirements.txt files; does NOT yet touch Python
`concrete.*` imports (those are module-level dependencies requiring the
phase-2 Python module port from `concrete` → `torus`).
Substitutions applied:
Concrete ML → TorusML
concrete-ml → torus-ml
Concrete-ML → Torus-ML
concrete_ml → torus_ml
zama-ai/concrete-ml → luxfhe/ml-sdk
zama-ai/concrete → luxfhe/torus
github.com/zama-ai → github.com/luxfhe
docs.zama.ai/concrete-ml → docs.luxfhe.com/ml-sdk
docs.zama.ai/concrete → docs.luxfhe.com/torus
Zama Concrete ML → Lux TorusML
Zama Concrete → Lux Torus
Zama tfhe-rs / Zama TFHE-rs → Lux-FHE
tfhe-rs / TFHE-rs → Lux-FHE
Zama fhEVM / fhEVM → TorusEVM
Concrete framework → Torus framework
Concrete compiler → Torus compiler
Concrete by Zama → Torus by Lux
the Zama team → the Lux Industries team
Zama's → Lux Industries'
(Zama) → (Lux)
CoFHE / Fhenix → (removed)
LICENSE: original Zama copyright RETAINED per BSD-3-Clause-Clear §1-§2
requirements; Lux Industries modifications copyright added. Per §3 no
name of ZAMA used to endorse the derived work — product marketed
exclusively as TorusML.
README image URLs migrated to github.com/luxfhe/ml-sdk/assets to break
the dependency on Zama's CDN.
Hit count: 350 → 295. Residual hits are Python `from concrete.fhe import`
imports referencing the upstream Zama `concrete` PyPI package; these
require module-level port (phase 2):
Phase 2 plan:
1. Fork zama-ai/concrete (the Python compiler) to luxfhe/torus
2. Rename Python module `concrete` → `torus`; PyPI publish as `torus-fhe`
3. Update ml-sdk imports from `concrete.fhe` → `torus.fhe`, etc.
4. Wire `torus.compiler` GPU dispatch through `luxcpp/gpu` vtbl
(lux-private/gpu-kernels for CUDA/Metal/WebGPU/FPGA targets)
5. Port concrete-cuda + concrete-mlir kernels to
lux-private/gpu-kernels/{cuda,metal,wgsl}/ckks/ (matrix-vector
mul, rescale, rotate, bootstrap for TorusML inference)
Phase 3 plan (kernels):
- CKKS/BGV/BFV GPU kernels in lux-private/gpu-kernels/
(currently only TFHE PBS / keyswitch / blind-rotate exist)
- FPGA bitstreams in lux-private/fpga/ (currently scaffold only)
Phase 1 = docs/branding sweep. PR not opened; user reviews and merges.
340 KiB
340 KiB
In [1]:
import warnings
import concrete.compiler
import torch
from cifar_utils import (
fhe_compatibility,
fhe_simulation_inference,
get_dataloader,
plot_dataset,
torch_inference,
)
from models import QuantVGG11
from torchvision import datasets
warnings.filterwarnings("ignore", category=UserWarning)In [2]:
bit = 5
seed = 42
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Device Type: {device}")Device Type: cpu
In [3]:
compilation_device = "cuda" if concrete.compiler.check_gpu_available() else "cpu"
print(f"Is GPU enabled: {concrete.compiler.check_gpu_enabled()}")
print(f"Is GPU available: {concrete.compiler.check_gpu_available()}")Is GPU enabled: False Is GPU available: False
In [3]:
param_c10 = {
"output_size": 10,
"batch_size": 128,
"dataset_name": "CIFAR_10",
"dataset": datasets.CIFAR10,
"std": [0.247, 0.243, 0.261],
"mean": [0.4914, 0.4822, 0.4465],
"dir": "./checkpoints/CIFAR_10",
"pre_trained_path": "quant/CIFAR_10_quant_state_dict.pt",
"seed": 42,
}In [4]:
# Load CIFAR-10 data-set.
train_loader_c10, test_loader_c10 = get_dataloader(param=param_c10)
# Let’s visualize `n` images from CIFAR-10 data-set.
plot_dataset(test_loader_c10, param_c10)Files already downloaded and verified Files already downloaded and verified
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
In [5]:
# Loading the pre-trained quantized model.
quant_vgg_c10 = QuantVGG11(bit=bit, output_size=param_c10["output_size"])
checkpoint = torch.load(f"{param_c10['dir']}/{param_c10['pre_trained_path']}", map_location=device)
quant_vgg_c10.load_state_dict(checkpoint)Out [5]:
<All keys matched successfully>
In [6]:
# The user can either provide the entire train data-set or a smaller but representative subset.
# As each batch is shuffled and contains 128 samples, it's a potential subset.
data_calibration, _ = next(iter(train_loader_c10))
qmodel_c10 = fhe_compatibility(quant_vgg_c10, data_calibration, device=compilation_device)
print(
f"Maximum bit-width in the circuit: {qmodel_c10.fhe_circuit.graph.maximum_integer_bit_width()}"
)Maximum bit-width in the circuit: 14
In [7]:
# Evaluation with the FHE simulation for CIFAR-10.
acc_fhe_c10 = fhe_simulation_inference(qmodel_c10, test_loader_c10, True)100%|██████████| 78/78 [48:57<00:00, 37.66s/it]
In [8]:
# Evaluation with Brevitas torch for CIFAR-10.
acc_torch_c10 = torch_inference(quant_vgg_c10, test_loader_c10, device=device)In [9]:
print(f"Top-1 acc in Brevitas torch: {acc_torch_c10 * 100 :2.2f}%")
print(f"Top-1 acc with TorusML : {acc_fhe_c10 * 100 :2.2f}%")Top-1 acc in Brevitas torch: 83.80% Top-1 acc with TorusML : 82.98%
In [10]:
param_c100 = {
"output_size": 100,
"batch_size": 128,
"dataset_name": "CIFAR_100",
"dataset": datasets.CIFAR100,
"std": [0.229, 0.224, 0.225],
"mean": [0.485, 0.456, 0.406],
"dir": "./checkpoints/CIFAR_100",
"pre_trained_path": "quant/CIFAR_100_quant_state_dict.pt",
"seed": 42,
}In [11]:
# Load CIFAR-100 data-set.
train_loader_c100, test_loader_c100 = get_dataloader(param=param_c100)
# Let’s visualize `n` images from CIFAR-100 data-set.
plot_dataset(test_loader_c100, param_c100)Files already downloaded and verified Files already downloaded and verified
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
In [12]:
# Loading the pre-trained quantized model.
quant_vgg_c100 = QuantVGG11(bit=bit, output_size=param_c100["output_size"])
checkpoint = torch.load(
f"{param_c100['dir']}/{param_c100['pre_trained_path']}", map_location=device
)
quant_vgg_c100.load_state_dict(checkpoint)Out [12]:
<All keys matched successfully>
In [13]:
# The user can either provide the entire train data-set or a smaller but representative subset.
data_calibration, _ = next(iter(train_loader_c100))
qmodel_c100 = fhe_compatibility(quant_vgg_c100, data_calibration, device=compilation_device)
print(
f"Maximum bit-width in the circuit: {qmodel_c100.fhe_circuit.graph.maximum_integer_bit_width()}"
)Maximum bit-width in the circuit: 13
In [14]:
# Evaluation with Brevitas torch for CIFAR-100.
acc_torch_c100 = torch_inference(quant_vgg_c100, test_loader_c100, device=device)In [15]:
# Evaluation with the FHE simulation for CIFAR-100.
acc_fhe_c100 = fhe_simulation_inference(qmodel_c100, test_loader_c100, True)100%|██████████| 78/78 [49:43<00:00, 38.25s/it]
In [16]:
# FIME
print(f"Top-1 acc in Brevitas torch : {acc_torch_c100 * 100 :2.2f}%")
print(f"Top-1 acc with TorusML : {acc_fhe_c100 * 100 :2.2f}%")
# There is a small between the results of Brevitas and the FHE simulation.
# This may be due to the conversion of the Brevitas model into TorusML.Top-1 acc in Brevitas torch : 68.79% Top-1 acc with TorusML : 68.74%