文本嵌入推理文档

在 Google Cloud Run 上部署 TEI

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

在 Google Cloud Run 上部署 TEI

在 Google Cloud Platform (GCP) 上部署文本嵌入推理 (TEI) 可以利用底层 Kubernetes 技术,该技术可确保 TEI 根据需求自动扩展或缩减。

在 Google Cloud 上,有 3 个主要选项可用于部署 TEI(或任何其他 Docker 容器)

  • Cloud Run
  • Vertex AI 端点
  • GKE(Google Kubernetes Engine)。

本指南将介绍如何在 Cloud Run 上部署 TEI,Cloud Run 是 Google 提供的一项完全托管的服务。Cloud Run 是一种所谓的无服务器产品。这意味着服务器基础设施由 Google 处理,您只需提供一个 Docker 容器。这样做的好处是,您只在应用程序有需求时才为计算付费。当有需求时,Cloud Run 会自动启动服务器;当没有需求时,它会缩减到零实例。

我们将展示如何部署任何带或不带 GPU 的文本嵌入模型。

[!NOTE] 截至撰写本文时,Cloud Run 上的 GPU 支持在 4 个区域已普遍可用。如果您有兴趣使用它,请申请增加配额,用于`每个项目每个区域的总 Nvidia L4 GPU 分配`。目前,NVIDIA L4 GPU(24GiB 显存)是 Cloud Run 上唯一可用的 GPU;默认情况下,它支持自动扩展到最多 7 个实例(通过配额可以获得更多),并在没有请求时缩减到零实例。

设置/配置

本指南假设您已设置 Google Cloud 项目并已启用结算功能。您可以在 https://console.cloud.google.com/ 完成此操作。

首先,您需要在本地机器上安装 gcloud CLI。这允许以编程方式与您的 Google Cloud 项目交互。

或者,为了简化本教程中命令的使用,您需要为 GCP 设置以下环境变量

export PROJECT_ID=your-project-id
export LOCATION=europe-west1  # or any location you prefer: https://cloud.google.com/run/docs/locations
export CONTAINER_URI="gcr.io/deeplearning-platform-release/huggingface-text-embeddings-inference-cpu.1-6"
export SERVICE_NAME="text-embedding-server" # choose a name for your service
export MODEL_ID="ibm-granite/granite-embedding-278m-multilingual" # choose any embedding model

一些澄清

  • 我们根据 README 提供最新的官方 Docker 镜像 URI。
  • 我们选择部署 IBM granite 嵌入模型,因为它具有强大的多语言能力。当然,您可以从 Hub 中选择任何其他嵌入模型。建议查找标记为 `feature-extraction`、`sentence-similarity` 或 `text-ranking` 的模型。

然后您需要登录您的 Google Cloud 账户并设置您要用于部署 Cloud Run 的项目 ID。

gcloud auth login
gcloud auth application-default login  # For local development
gcloud config set project $PROJECT_ID

登录后,您需要启用 Cloud Run API,这是 Hugging Face DLC for TEI 在 Cloud Run 上部署所必需的。

gcloud services enable run.googleapis.com

在 Cloud Run 上部署 TEI

一切就绪后,您可以调用 `gcloud run deploy` 命令来部署 Docker 镜像。

该命令需要您指定以下参数

  • --image:要部署的容器镜像 URI。
  • --args:传递给容器入口点的参数,对于 Hugging Face DLC for TEI,该参数为 `text-embeddings-inference`。更多关于支持的参数,请此处阅读。
    • --model-id:要使用的模型 ID,在此例中为 ibm-granite/granite-embedding-278m-multilingual
    • --quantize:要使用的量化方法。如果未指定,它将从 `config.json` 文件中的 `quantization_config->quant_method` 中检索。
    • --max-concurrent-requests:此特定部署的最大并发请求数。设置较低的限制将拒绝客户端请求,而不是让它们等待太长时间,这通常有利于正确处理反压。设置为 64,但默认值为 128。
  • --port:容器监听的端口。
  • --cpu--memory:分配给容器的 CPU 数量和内存量。需要分别设置为 4 和 16Gi (16 GiB);因为这是使用 GPU 的最低要求。
  • --no-cpu-throttling:禁用 CPU 节流,这是使用 GPU 所必需的。
  • --gpu--gpu-type:要使用的 GPU 数量和 GPU 类型。必须分别设置为 1 和 `nvidia-l4`;因为在撰写本教程时,这些是 Cloud Run on GPUs 上唯一可用的选项。
  • --max-instances:要运行的最大实例数,设置为 3,但默认最大值为 7。另外,也可以设置为 1,但这最终可能导致基础设施迁移期间停机,因此建议设置为 1 以上。
  • --concurrency:每个实例的最大并发请求数,设置为 64。请注意,此值也与 TEI 中的 --max-concurrent-requests 参数一致。
  • --region:部署 Cloud Run 服务的区域。
  • --no-allow-unauthenticated:禁用对服务的未经身份验证的访问,这是一个很好的做法,因为它添加了由 Google Cloud IAM 管理的身份验证层。

[!NOTE] 可选地,您可以包含参数 `—vpc-egress=all-traffic` 和 `—subnet=default`,因为有外部流量发送到公共互联网,因此为了加快网络速度,您需要通过设置这些标志将所有流量路由到 VPC 网络。请注意,除了设置这些标志外,您还需要设置 Google Cloud NAT 才能访问公共互联网,这是一项付费产品。请在Cloud Run 文档 - 网络最佳实践中找到更多信息。

gcloud compute routers create nat-router --network=default --region=$LOCATION
gcloud compute routers nats create vm-nat --router=nat-router --region=$LOCATION --auto-allocate-nat-external-ips --nat-all-subnet-ip-ranges

最后,您可以运行 `gcloud run deploy` 命令来部署 Cloud Run 上的 TEI,如下所示:

gcloud run deploy $SERVICE_NAME \
    --image=$CONTAINER_URI \
    --args="--model-id=$MODEL_ID,--max-concurrent-requests=64" \
    --set-env-vars=HF_HUB_ENABLE_HF_TRANSFER=1 \
    --port=8080 \
    --cpu=8 \
    --memory=32Gi \
    --region=$LOCATION \
    --no-allow-unauthenticated

如果您想使用 GPU 部署,请运行以下命令

gcloud run deploy $SERVICE_NAME \
    --image=$CONTAINER_URI \
    --args="--model-id=$MODEL_ID,--max-concurrent-requests=64" \
    --set-env-vars=HF_HUB_ENABLE_HF_TRANSFER=1 \
    --port=8080 \
    --cpu=8 \
    --memory=32Gi \
    --no-cpu-throttling \
    --gpu=1 \
    --gpu-type=nvidia-l4 \
    --max-instances=3 \
    --concurrency=64 \
    --region=$LOCATION \
    --no-allow-unauthenticated

或者,如果您创建了 Cloud NAT,则按如下所示进行

gcloud beta run deploy $SERVICE_NAME \
    --image=$CONTAINER_URI \
    --args="--model-id=$MODEL_ID,--max-concurrent-requests=64" \
    --set-env-vars=HF_HUB_ENABLE_HF_TRANSFER=1 \
    --port=8080 \
    --cpu=8 \
    --memory=32Gi \
    --no-cpu-throttling \
    --gpu=1 \
    --gpu-type=nvidia-l4 \
    --max-instances=3 \
    --concurrency=64 \
    --region=$LOCATION \
    --no-allow-unauthenticated \
    --vpc-egress=all-traffic \
    --subnet=default

[!NOTE] 首次在 Cloud Run 上部署新容器大约需要 5 分钟,因为它需要从 Google Cloud Artifact Registry 导入,但在后续部署中,由于镜像已提前导入,因此所需时间会更短。

推理

部署后,您可以通过任何受支持的 TEI 端点向服务发送请求,请查看 TEI 的 OpenAPI 规范以查看所有可用的端点及其各自的参数。

所有 Cloud Run 服务默认情况下都是私有部署的,这意味着未经请求头中提供身份验证凭据,无法访问它们。这些服务受 IAM 保护,并且只能由项目所有者、项目编辑者、Cloud Run 管理员和 Cloud Run 调用者调用。

在这种情况下,将展示几种启用开发人员访问的替代方案;而其他用例超出了本示例的范围,因为它们要么由于身份验证被禁用而不安全(对于公共访问场景),要么需要额外的设置才能用于生产就绪场景(服务到服务身份验证、最终用户访问)。

[!NOTE] 下面提到的替代方案适用于开发场景,不应直接用于生产就绪场景。以下方法遵循Cloud Run 文档 - 身份验证开发人员中定义的指南;但您可以在Cloud Run 文档 - 身份验证概述中找到所有其他指南,如上所述。

通过 Cloud Run 代理

Cloud Run 代理在本地主机上运行一个服务器,该服务器将请求代理到指定的 Cloud Run 服务并附加凭据;这对于测试和实验很有用。

gcloud run services proxy $SERVICE_NAME --region $LOCATION

然后,您可以使用 https://:8080 URL 向 Cloud Run 上部署的服务发送请求,无需身份验证,如以下示例所示,由代理公开。您可以在浏览器中查看 API 文档:https://:8080/docs。

cURL

要使用 cURL 向 TEI 服务发送 POST 请求,您可以运行以下命令

curl https://:8080/embed \
    -X POST \
    -H 'Content-Type: application/json' \
    -d '{
        "model": "tei",
        "text": "What is deep learning?"
    }'

或者,也可以向兼容 OpenAI 的端点发送请求

curl https://:8080/v1/embeddings \
    -X POST \
    -H 'Content-Type: application/json' \
    -d '{
        "model": "tei",
        "text": "What is deep learning?"
    }'

Python

要使用 Python 运行推理,您可以使用 huggingface_hub Python SDK(推荐)或 openai Python SDK。

huggingface_hub

您可以通过 `pip install --upgrade --quiet huggingface_hub` 安装,然后运行

from huggingface_hub import InferenceClient

client = InferenceClient()
embedding = client.feature_extraction("What is deep learning?",
                                      model="https://:8080/embed")
print(len(embedding[0]))

OpenAI

您可以通过 `pip install --upgrade openai` 安装,然后运行

from openai import OpenAI

client = OpenAI(base_url="https://:8080/v1/embeddings", api_key="")

response = client.embeddings.create(
  model="tei",
  input="What is deep learning?"
)

print(response)

(推荐)通过 Cloud Run 服务 URL

Cloud Run 服务有一个唯一的 URL,可以用于从任何地方发送请求,使用具有 Cloud Run 调用访问权限的 Google Cloud 凭据;这是推荐的方法,因为它比使用 Cloud Run 代理更安全、更一致。

Cloud Run 服务的 URL 可以通过以下命令获取(为方便起见,分配给 SERVICE_URL 变量)

SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --region $LOCATION --format 'value(status.url)')

然后,您可以使用 `SERVICE_URL` 和任何具有 Cloud Run Invoke 访问权限的 Google Cloud 凭据向 Cloud Run 上部署的服务发送请求。设置凭据有多种方法,其中一些列在下面

使用 Google Cloud SDK 中的默认身份令牌

  • 通过 gcloud 如下所示
gcloud auth print-identity-token
  • 通过 Python 如下所示
import google.auth
from google.auth.transport.requests import Request as GoogleAuthRequest

auth_req = GoogleAuthRequest()
creds, _ = google.auth.default()
creds.refresh(auth_req)

id_token = creds.id_token
  • 使用具有 Cloud Run Invoke 访问权限的服务帐户,可以通过以下任何一种方法完成

在创建 Cloud Run 服务之前创建服务帐户,然后在创建 Cloud Run 服务时将 service-account 标志设置为服务帐户电子邮件。并且仅使用 `gcloud auth print-access-token --impersonate-service-account=SERVICE_ACCOUNT_EMAIL` 为该服务帐户使用访问令牌。 在创建 Cloud Run 服务之后创建服务帐户,然后更新 Cloud Run 服务以使用该服务帐户。并且仅使用 `gcloud auth print-access-token --impersonate-service-account=SERVICE_ACCOUNT_EMAIL` 为该服务帐户使用访问令牌。

推荐的方法是使用服务帐户 (SA),因为访问可以得到更好的控制,并且权限更精细;由于 Cloud Run 服务不是使用 SA 创建的(这是另一个不错的选择),您现在需要创建 SA,授予其必要的权限,更新 Cloud Run 服务以使用 SA,然后生成访问令牌以设置为请求中的身份验证令牌,该令牌可以在使用完毕后撤销。

  • 为了方便起见,设置 SERVICE_ACCOUNT_NAME 环境变量
export SERVICE_ACCOUNT_NAME=tei-invoker
  • 创建服务帐户
gcloud iam service-accounts create $SERVICE_ACCOUNT_NAME
  • 授予服务帐户 Cloud Run 调用者角色
gcloud run services add-iam-policy-binding $SERVICE_NAME \
    --member="serviceAccount:$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com" \
    --role="roles/run.invoker" \
    --region=$LOCATION

为服务帐户生成访问令牌

export ACCESS_TOKEN=$(gcloud auth print-access-token --impersonate-service-account=$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com)

访问令牌是短期的,默认情况下会在 1 小时后过期。如果您想将令牌的生命周期延长到默认时间之外,您必须创建组织策略并在创建令牌时使用 --lifetime 参数。请参阅访问令牌生命周期以了解更多信息。否则,您也可以通过再次运行相同的命令来生成新令牌。

现在,您已经可以深入研究向已部署的 Cloud Run 服务发送请求的不同替代方案,使用如上所述的 `SERVICE_URL` 和 `ACCESS_TOKEN`。

cURL

要使用 cURL 向 TEI 服务发送 POST 请求,您可以运行以下命令

curl $SERVICE_URL/v1/embeddigs \
    -X POST \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    -H 'Content-Type: application/json' \
    -d '{
        "model": "tei",
        "text": "What is deep learning?"
    }'

Python

要使用 Python 运行推理,您可以使用 huggingface_hub Python SDK(推荐)或 openai Python SDK。

huggingface_hub

您可以通过 `pip install --upgrade --quiet huggingface_hub` 安装,然后运行

import os
from huggingface_hub import InferenceClient

client = InferenceClient(
    base_url=os.getenv("SERVICE_URL"),
    api_key=os.getenv("ACCESS_TOKEN"),
)

embedding = client.feature_extraction("What is deep learning?",
                                      model="https://:8080/embed")
print(len(embedding[0]))

OpenAI

您可以通过 `pip install --upgrade openai` 安装,然后运行

import os
from openai import OpenAI

client = OpenAI(
    base_url=os.getenv("SERVICE_URL"),
    api_key=os.getenv("ACCESS_TOKEN"),
)

response = client.embeddings.create(
  model="tei",
  input="What is deep learning?"
)

print(response)

资源清理

最后,一旦您在 Cloud Run 服务上使用完 TEI,就可以安全地删除它,以避免产生不必要的费用,例如,如果 Cloud Run 服务在免费套餐中意外调用次数超过您的每月 Cloud Run 调用分配。

要删除 Cloud Run 服务,您可以前往 Google Cloud 控制台 https://console.cloud.google.com/run 手动删除;或者通过 gcloud 使用 Google Cloud SDK,如下所示

gcloud run services delete $SERVICE_NAME --region $LOCATION

此外,如果您按照“通过 Cloud Run 服务 URL”中的步骤操作并生成了服务帐户和访问令牌,您可以删除服务帐户,或者如果它仍然有效,只需撤销访问令牌。

  • (推荐)撤销访问令牌,如下所示:
gcloud auth revoke --impersonate-service-account=$SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com
  • (可选)删除服务帐户,如下所示:
gcloud iam service-accounts delete $SERVICE_ACCOUNT_NAME@$PROJECT_ID.iam.gserviceaccount.com

最后,如果您决定通过 Cloud NAT 启用 VPC 网络,您还可以删除 Cloud NAT(这是一个付费产品),如下所示

gcloud compute routers nats delete vm-nat --router=nat-router --region=$LOCATION
gcloud compute routers delete nat-router --region=$LOCATION

参考资料

< > 在 GitHub 上更新