在 Hugging Face 端點上執行隱私保護推理

釋出於 2024 年 4 月 16 日
在 GitHub 上更新

這是 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 平臺上的其他任何模型一樣,選擇 部署,然後選擇 推理端點(專用)

Inference Endpoint (dedicated) 推理端點(專用)

接下來,選擇端點名稱或區域,最重要的是,選擇 CPU(Concrete ML 模型目前不使用 GPU;我們正在努力解決這個問題)以及可用的最佳機器——在下面的示例中,我們選擇了八個 vCPU。現在點選 建立端點 並等待初始化完成。

Create Endpoint 建立端點

幾秒鐘後,端點部署完畢,您的隱私保護模型即可執行。

Endpoint is created 端點已建立

:當您不再使用端點時,不要忘記刪除它(或至少暫停它),否則費用會超出預期。

使用端點

安裝客戶端

目標不僅是部署您的端點,還要讓您的使用者使用它。為此,他們需要在自己的計算機上克隆倉庫。這可以透過在下拉選單中選擇 克隆倉庫 來完成。

Clone Repository 克隆倉庫

他們將獲得一個簡短的命令列,可以在終端中執行。

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.zipserver.zipversions.json)。如文件中所述,這些檔案包含您的預編譯模型。如果您有任何問題,可以在 fhe.org discord 上獲得支援。

最後一步是修改 play_with_endpoint.py,使其也處理與 creating_models.py 中相同的 ML 任務:相應地設定資料集。

現在,您可以將此目錄以及 compiled_model 目錄和檔案,以及您在 creating_models.pyplay_with_endpoint.py 中所做的修改儲存到 Hugging Face 模型中。當然,您需要執行一些測試並進行微調才能使其正常工作。不要忘記新增 concrete-mlFHE 標籤,以便您的預編譯模型能夠輕鬆地在搜尋中顯示。

目前可用的預編譯模型

目前,我們已經準備了一些預編譯模型作為示例,希望社群能儘快擴充套件。可以透過搜尋 concrete-mlFHE 標籤來找到預編譯模型。

模型型別 資料集 在 HF 端點上的執行時間
邏輯迴歸 合成 0.4 秒
決策樹 垃圾郵件 2.0 秒
QNN 鳶尾花 3.7 秒
CNN MNIST 24 秒

請記住,Hugging Face 為 CPU 支援的端點提供的配置選項有限(目前最多 8 個 vCPU 和 16 GB RAM)。根據您的生產需求和模型特性,在更強大的雲實例上執行時間可能會更快。希望 Hugging Face 端點很快能提供更強大的機器來改善這些時間。

額外資源

結論和下一步

在這篇部落格文章中,我們展示了自定義端點非常容易且功能強大。我們在 Concrete ML 中所做的工作與機器學習從業者的常規工作流程截然不同,但我們仍然能夠適應自定義端點來滿足我們大部分需求。向 Hugging Face 工程師開發如此通用的解決方案致敬。

我們解釋瞭如何

  • 開發人員可以建立自己的預編譯模型並將其釋出到 Hugging Face 模型上。
  • 公司可以部署開發人員的預編譯模型,並透過 HF 端點提供給使用者。
  • 終端使用者可以使用這些端點對加密資料執行機器學習任務。

為了進一步發展,在 Hugging Face 端點上提供更強大的機器以加快推理速度將非常有益。此外,我們可以設想 Concrete ML 更好地整合到 Hugging Face 的介面中,並提供一個“隱私保護推理端點”按鈕,從而進一步簡化開發人員的工作。最後,為了在多個伺服器機器中進行整合,如果有一種方法可以在機器之間共享狀態並保持此狀態非易失(FHE 推理金鑰將儲存在此處),那將非常有幫助。

社群

註冊登入以評論

© . This site is unofficial and not affiliated with Hugging Face, Inc.