在 Hugging Face 端点上运行隐私保护推理
这是 Zama 团队的客座博客文章。Zama 是一家开源密码学公司,致力于为区块链和人工智能构建最先进的 FHE 解决方案。
十八个月前,Zama 启动了 Concrete ML,这是一个隐私保护机器学习框架,与 scikit-learn、ONNX、PyTorch 和 TensorFlow 等传统机器学习框架绑定。为了确保用户数据的隐私,Zama 使用了全同态加密 (FHE),这是一种允许直接对加密数据进行计算而无需知道私钥的加密工具。
从一开始,我们就希望预编译一些 FHE 友好型网络并将它们发布到互联网上,让用户可以轻松使用它们。我们今天已经准备好了!而且不是在互联网上的某个随机位置,而是直接在 Hugging Face 上。
更准确地说,我们使用 Hugging Face 端点和 自定义推理处理器,以便能够存储我们的 Concrete ML 模型,并让用户一键部署到 Hugging Face 机器上。在本篇博客文章的末尾,您将了解如何使用预编译模型以及如何准备自己的模型。这篇博客文章也可以被视为自定义推理处理器的另一个教程。
部署预编译模型
让我们从部署一个 FHE 友好型模型开始(由 Zama 或第三方准备——有关如何准备自己的模型,请参见下面的 准备您的预编译模型 部分)。
首先,寻找您想要部署的模型:我们在 Zama 的 HF 页面上预编译了大量模型(或者您可以通过标签找到它们)。假设您选择了 concrete-ml-encrypted-decisiontree:如描述中所述,此预编译模型允许您在不查看明文消息内容的情况下检测垃圾邮件。
与 Hugging Face 平台上的其他任何模型一样,选择 部署,然后选择 推理端点(专用)。
接下来,选择端点名称或区域,最重要的是,选择 CPU(Concrete ML 模型目前不使用 GPU;我们正在努力解决这个问题)以及可用的最佳机器——在下面的示例中,我们选择了八个 vCPU。现在点击 创建端点 并等待初始化完成。
几秒钟后,端点部署完毕,您的隐私保护模型即可运行。
:当您不再使用端点时,不要忘记删除它(或至少暂停它),否则费用会超出预期。
使用端点
安装客户端
目标不仅是部署您的端点,还要让您的用户使用它。为此,他们需要在自己的计算机上克隆仓库。这可以通过在下拉菜单中选择 克隆仓库 来完成。
他们将获得一个简短的命令行,可以在终端中运行。
git clone https://huggingface.co/zama-fhe/concrete-ml-encrypted-decisiontree
命令执行完毕后,他们进入 concrete-ml-encrypted-decisiontree
目录,并用编辑器打开 play_with_endpoint.py
。在这里,他们会找到 API_URL = …
这一行,并应将其替换为上一节中创建的端点的新 URL。
API_URL = "https://vtx9w974oxrq54ff.us-east-1.aws.endpoints.huggingface.cloud"
当然,请填写*您的*入口点的 URL。此外,定义一个访问令牌并将其存储在环境变量中。
export HF_TOKEN=[your token hf_XX..XX]
最后,您的用户机器需要本地安装 Concrete ML:创建一个虚拟环境,激活它,并安装必要的依赖项。
python3.10 -m venv .venv
source .venv/bin/activate
pip install -U setuptools pip wheel
pip install -r requirements.txt
请注意,我们目前强制使用 Python 3.10(这也是 Hugging Face Endpoints 中使用的默认 Python 版本)。这是因为我们的开发文件目前依赖于 Python 版本。我们正在努力使其独立。这应该在后续版本中提供。
运行推理
现在,您的用户可以通过运行脚本在端点上执行推理。
python play_with_endpoint.py
它应该生成一些类似于以下内容的日志:
Sending 0-th piece of the key (remaining size is 71984.14 kbytes)
Storing the key in the database under uid=3307376977
Sending 1-th piece of the key (remaining size is 0.02 kbytes)
Size of the payload: 0.23 kilobytes
for 0-th input, prediction=0 with expected 0 in 3.242 seconds
for 1-th input, prediction=0 with expected 0 in 3.612 seconds
for 2-th input, prediction=0 with expected 0 in 4.765 seconds
(...)
for 688-th input, prediction=0 with expected 1 in 3.176 seconds
for 689-th input, prediction=1 with expected 1 in 4.027 seconds
for 690-th input, prediction=0 with expected 0 in 4.329 seconds
Accuracy on 691 samples is 0.8958031837916064
Total time: 2873.860 seconds
Duration per inference: 4.123 seconds
适应您的应用程序或需求
如果您编辑 play_with_endpoint.py
,您会看到我们遍历了测试数据集的不同样本,并直接在端点上运行加密推理。
for i in range(nb_samples):
# Quantize the input and encrypt it
encrypted_inputs = fhemodel_client.quantize_encrypt_serialize(X_test[i].reshape(1, -1))
# Prepare the payload
payload = {
"inputs": "fake",
"encrypted_inputs": to_json(encrypted_inputs),
"method": "inference",
"uid": uid,
}
if is_first:
print(f"Size of the payload: {sys.getsizeof(payload) / 1024:.2f} kilobytes")
is_first = False
# Run the inference on HF servers
duration -= time.time()
duration_inference = -time.time()
encrypted_prediction = query(payload)
duration += time.time()
duration_inference += time.time()
encrypted_prediction = from_json(encrypted_prediction)
# Decrypt the result and dequantize
prediction_proba = fhemodel_client.deserialize_decrypt_dequantize(encrypted_prediction)[0]
prediction = np.argmax(prediction_proba)
if verbose:
print(
f"for {i}-th input, {prediction=} with expected {Y_test[i]} in {duration_inference:.3f} seconds"
)
# Measure accuracy
nb_good += Y_test[i] == prediction
当然,这只是一个入口点使用的示例。鼓励开发人员根据自己的用例或应用程序调整此示例。
幕后工作
请注意,所有这些都得益于自定义处理程序的灵活性,我们对 Hugging Face 开发人员提供如此灵活性表示感谢。其机制在 handler.py
中定义。如 Hugging Face 文档中所述,您可以根据需要定义 EndpointHandler
的 __call__
方法:在我们的案例中,我们定义了一个 method
参数,它可以是 save_key
(用于保存 FHE 评估密钥)、append_key
(如果密钥太大无法一次性发送,则分段保存 FHE 评估密钥)以及最终的 inference
(用于运行 FHE 推理)。这些方法用于一次设置评估密钥,然后逐个运行所有推理,如 play_with_endpoint.py
中所示。
限制
然而,人们可能会发现密钥存储在端点的 RAM 中,这对于生产环境来说并不方便:每次重启,密钥都会丢失,需要重新发送。此外,当您有多台机器来处理大量流量时,这种 RAM 不会在机器之间共享。最后,可用的 CPU 机器最多只能为端点提供八个 vCPU,这对于高负载应用程序来说可能是一个限制。
准备您的预编译模型
既然您知道了部署预编译模型是多么容易,您可能想准备自己的模型。为此,您可以克隆我们准备的其中一个仓库。Concrete ML 支持的所有模型类别(线性模型、基于树的模型、内置多层感知器、PyTorch模型)都至少有一个示例,可以作为新预编译模型的模板。
然后,编辑 creating_models.py
,并将机器学习任务更改为您想要在预编译模型中处理的任务:例如,如果您从 concrete-ml-encrypted-decisiontree 开始,请更改数据集和模型类型。
如前所述,您必须安装 Concrete ML 才能准备预编译模型。请注意,您可能需要使用与 Hugging Face 默认使用的 Python 版本相同(编写本博客时为 3.10),否则您的模型可能需要人们在部署期间使用带有您的 Python 的容器。
现在您可以启动 python creating_models.py
。这将训练模型并在 compiled_model
目录中创建必要的开发文件(client.zip
、server.zip
和 versions.json
)。如文档中所述,这些文件包含您的预编译模型。如果您有任何问题,可以在 fhe.org discord 上获得支持。
最后一步是修改 play_with_endpoint.py
,使其也处理与 creating_models.py
中相同的 ML 任务:相应地设置数据集。
现在,您可以将此目录以及 compiled_model
目录和文件,以及您在 creating_models.py
和 play_with_endpoint.py
中所做的修改保存到 Hugging Face 模型中。当然,您需要运行一些测试并进行微调才能使其正常工作。不要忘记添加 concrete-ml
和 FHE
标签,以便您的预编译模型能够轻松地在搜索中显示。
目前可用的预编译模型
目前,我们已经准备了一些预编译模型作为示例,希望社区能尽快扩展。可以通过搜索 concrete-ml 或 FHE 标签来找到预编译模型。
请记住,Hugging Face 为 CPU 支持的端点提供的配置选项有限(目前最多 8 个 vCPU 和 16 GB RAM)。根据您的生产需求和模型特性,在更强大的云实例上执行时间可能会更快。希望 Hugging Face 端点很快能提供更强大的机器来改善这些时间。
额外资源
- 查看 Zama 库 Concrete 和 Concrete-ML,并开始在您自己的应用程序中使用 FHE。
- 查看 Zama 的 Hugging Face 个人资料,阅读更多博客文章并尝试实用的 FHE 演示。
- 在 Twitter 上关注 @zama_fhe,获取我们的最新更新。
结论和下一步
在这篇博客文章中,我们展示了自定义端点非常容易且功能强大。我们在 Concrete ML 中所做的工作与机器学习从业者的常规工作流程截然不同,但我们仍然能够适应自定义端点来满足我们大部分需求。向 Hugging Face 工程师开发如此通用的解决方案致敬。
我们解释了如何
- 开发人员可以创建自己的预编译模型并将其发布到 Hugging Face 模型上。
- 公司可以部署开发人员的预编译模型,并通过 HF 端点提供给用户。
- 最终用户可以使用这些端点对加密数据运行机器学习任务。
为了进一步发展,在 Hugging Face 端点上提供更强大的机器以加快推理速度将非常有益。此外,我们可以设想 Concrete ML 更好地集成到 Hugging Face 的界面中,并提供一个“隐私保护推理端点”按钮,从而进一步简化开发人员的工作。最后,为了在多个服务器机器中进行集成,如果有一种方法可以在机器之间共享状态并保持此状态非易失(FHE 推理密钥将存储在此处),那将非常有帮助。