在 GKE 上从 GCS 部署 Qwen2 7B 和 TGI DLC
Qwen2 是阿里云构建的新一代 Qwen 大型语言模型 (LLM) 系列,包含基础和指令微调的语言模型,参数量从 5 亿到 720 亿不等,包括一个混合专家模型;在 Hugging Face 的 Open LLM 排行榜上,7B 版本在 7B 参数量范围内排名第二,72B 版本在所有参数量范围内排名第一。文本生成推理 (TGI) 是 Hugging Face 开发的一个工具包,用于部署和服务 LLM,并提供高性能文本生成。此外,Google Kubernetes Engine (GKE) 是 Google Cloud 中一个完全托管的 Kubernetes 服务,可用于使用 GCP 的基础设施大规模部署和运行容器化应用程序。
此示例展示了如何在 Google Cloud Storage (GCS) 存储桶上部署 LLM,该存储桶位于运行专用容器的 GKE 集群上,以在安全且受管理的环境中使用 Hugging Face 的 TGI DLC 部署 LLM。
设置/配置
首先,您需要在本地机器上安装 gcloud
和 kubectl
,它们分别是 Google Cloud 和 Kubernetes 的命令行工具,用于与 GCP 和 GKE 集群交互。
- 要安装
gcloud
,请按照Cloud SDK 文档 - 安装 gcloud CLI中的说明进行操作。 - 要安装
kubectl
,请按照Kubernetes 文档 - 安装工具中的说明进行操作。
可选地,为了简化本教程中命令的使用,您需要为 GCP 设置以下环境变量
export PROJECT_ID=your-project-id
export LOCATION=your-location
export CLUSTER_NAME=your-cluster-name
export BUCKET_NAME=your-bucket-name
然后,您需要登录到您的 GCP 帐户并将项目 ID 设置为您要用于部署 GKE 集群的项目 ID。
gcloud auth login
gcloud auth application-default login # For local development
gcloud config set project $PROJECT_ID
登录后,您需要在 GCP 中启用必要的服务 API,例如 Google Kubernetes Engine API、Google Container Registry API 和 Google Container File System API,这些 API 对于部署 GKE 集群和 Hugging Face 的 TGI DLC 是必需的。
gcloud services enable container.googleapis.com
gcloud services enable containerregistry.googleapis.com
gcloud services enable containerfilesystem.googleapis.com
此外,要将 kubectl
与 GKE 集群凭据一起使用,您还需要安装 gke-gcloud-auth-plugin
,可以使用 gcloud
如下安装
gcloud components install gke-gcloud-auth-plugin
安装 gke-gcloud-auth-plugin
不需要专门通过 gcloud
安装,要了解有关替代安装方法的更多信息,请访问https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl#install_plugin。
创建 GKE 集群
一切设置完成后,您可以继续创建 GKE 集群和节点池,在本例中将是一个单个 GPU 节点,以便使用 GPU 加速器进行高性能推理,同时遵循 TGI 基于其内部 GPU 优化提供的建议。
为了部署 GKE 集群,将使用“Autopilot”模式,因为它是大多数工作负载的推荐模式,因为底层基础设施由 Google 管理。或者,您也可以使用“Standard”模式。
在创建 GKE Autopilot 集群之前,请务必查看GKE 文档 - 通过选择机器系列优化 Autopilot Pod 性能,因为并非所有版本都支持 GPU 加速器,例如 nvidia-l4
在 GKE 集群版本 1.28.3 或更低版本中不受支持。
gcloud container clusters create-auto $CLUSTER_NAME \
--project=$PROJECT_ID \
--location=$LOCATION \
--release-channel=stable \
--cluster-version=1.28 \
--no-autoprovisioning-enable-insecure-kubelet-readonly-port
要选择您所在位置的 GKE 集群的特定版本,您可以运行以下命令
gcloud container get-server-config \
--flatten="channels" \
--filter="channels.channel=STABLE" \
--format="yaml(channels.channel,channels.defaultVersion)" \
--location=$LOCATION
有关更多信息,请访问https://cloud.google.com/kubernetes-engine/versioning#specifying_cluster_version。
创建 GKE 集群后,您可以使用以下命令获取通过 kubectl
访问它的凭据
gcloud container clusters get-credentials $CLUSTER_NAME --location=$LOCATION
可选:将模型从 Hugging Face Hub 上传到 GCS
这是本教程中的一个可选步骤,因为您可能希望重用 GCS 存储桶上的现有模型,如果是这种情况,请随意跳到本教程的下一步,了解如何配置 GCS 的 IAM,以便您可以从 GKE 集群中的 Pod 访问存储桶。
否则,要将模型从 Hugging Face Hub 上传到 GCS 存储桶,您可以使用脚本scripts/upload_model_to_gcs.sh,它将从 Hugging Face Hub 下载模型并将其上传到 GCS 存储桶(如果存储桶不存在则创建存储桶)。
应通过 gcloud
安装 gsutil
组件,并安装 Python 包 huggingface_hub
(包含 hf_transfer
扩展)和 crcmod
包。
gcloud components install gsutil
pip install --upgrade --quiet "huggingface_hub[hf_transfer]" crcmod
然后,您可以运行脚本从 Hugging Face Hub 下载模型,然后将其上传到 GCS 存储桶。
确保设置正确的权限以运行脚本,例如:chmod +x scripts/upload_model_to_gcs.sh
。
./scripts/upload_model_to_gcs.sh --model-id Qwen/Qwen2-7B-Instruct --gcs gs://$BUCKET_NAME/Qwen2-7B-Instruct
配置 GCS 的 IAM
在继续在 GKE 集群上部署用于 TGI 的 Hugging Face DLC 之前,您需要为 GCS 存储桶设置 IAM 权限,以便 GKE 集群中的 Pod 可以访问该存储桶。为此,您需要在 GKE 集群中创建命名空间和服务账户,然后为包含模型的 GCS 存储桶设置 IAM 权限(无论是从 Hugging Face Hub 上传的还是已经存在于 GCS 存储桶中的)。
为方便起见,由于将在后续步骤中使用命名空间和服务账户的引用,因此将设置环境变量 NAMESPACE
和 SERVICE_ACCOUNT
。
export NAMESPACE=hf-gke-namespace
export SERVICE_ACCOUNT=hf-gke-service-account
然后,您可以在 GKE 集群中创建命名空间和服务账户,从而启用为该命名空间中的 Pod 创建 IAM 权限,以便在使用该服务账户时访问 GCS 存储桶。
kubectl create namespace $NAMESPACE
kubectl create serviceaccount $SERVICE_ACCOUNT --namespace $NAMESPACE
然后,您需要按如下方式将 IAM 策略绑定添加到存储桶
gcloud storage buckets add-iam-policy-binding \
gs://$BUCKET_NAME \
--member "principal://iam.googleapis.com/projects/$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/$NAMESPACE/sa/$SERVICE_ACCOUNT" \
--role "roles/storage.objectUser"
部署 TGI
现在,您可以继续进行用于 TGI 的 Hugging Face DLC 的 Kubernetes 部署,该部署将提供 Qwen/Qwen2-7B-Instruct
模型,该模型来自挂载在 /data
中的卷,并从模型所在的 GCS 存储桶复制而来。
要探索可以通过 TGI 提供服务的所有模型,您可以在 Hub 中探索标记为 text-generation-inference
的模型,网址为 https://huggingface.co/models?other=text-generation-inference。
用于 TGI 的 Hugging Face DLC 将通过 kubectl
部署,来自 config/
目录中的配置文件。
deployment.yaml
:包含 Pod 的部署详细信息,包括对用于 TGI 的 Hugging Face DLC 的引用,将MODEL_ID
设置为卷挂载中的模型路径,在本例中为/data/Qwen2-7B-Instruct
。service.yaml
:包含 Pod 的服务详细信息,为 TGI 服务公开端口 8080。storageclass.yaml
:包含 Pod 的存储类详细信息,定义卷挂载的存储类。- (可选)
ingress.yaml
:包含 Pod 的 Ingress 详情,将服务暴露到外部世界,以便可以通过 Ingress IP 访问。
kubectl apply -f config/
Kubernetes 部署可能需要几分钟才能准备就绪,因此您可以使用以下命令检查部署的状态
kubectl get pods --namespace $NAMESPACE
或者,您可以只等待部署准备就绪,使用以下命令
kubectl wait --for=condition=Available --timeout=700s --namespace $NAMESPACE deployment/tgi-deployment
使用 TGI 进行推理
要对已部署的 TGI 服务运行推理,您可以:
将已部署的 TGI 服务端口转发到端口 8080,以便通过
localhost
访问,使用以下命令:kubectl port-forward --namespace $NAMESPACE service/tgi-service 8080:8080
通过 Ingress 的外部 IP 访问 TGI 服务,这是此处的默认方案,因为您已在
config/ingress.yaml
文件中定义了 Ingress 配置(但可以跳过它,而选择端口转发),可以使用以下命令检索:kubectl get ingress --namespace $NAMESPACE tgi-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
通过 cURL
要使用 cURL
向 TGI 服务发送 POST 请求,您可以运行以下命令:
curl http://localhost:8080/generate \
-X POST \
-d '{"inputs":"<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\nWhat is 2+2?<|im_end|>\n<|im_start|>assistant\n","parameters":{"temperature":0.7, "top_p": 0.95, "max_new_tokens": 128}}' \
-H 'Content-Type: application/json'
或者向 Ingress IP 发送 POST 请求:
curl http://$(kubectl get ingress --namespace $NAMESPACE tgi-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')/generate \
-X POST \
-d '{"inputs":"<|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\nWhat is 2+2?<|im_end|>\n<|im_start|>assistant\n","parameters":{"temperature":0.7, "top_p": 0.95, "max_new_tokens": 128}}' \
-H 'Content-Type: application/json'
这将产生以下输出:
{"generated_text":"2 + 2 equals 4."}
要使用预期的聊天模板格式生成 inputs
,您可以使用以下代码片段:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-7B-Instruct")
tokenizer.apply_chat_template(
[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"},
],
tokenize=False,
add_generation_prompt=True,
)
通过 Python
要使用 Python 运行推理,您可以使用 openai
Python SDK(请参阅 https://platform.openai.com/docs/quickstart 中的安装说明),将 localhost 或 Ingress IP 设置为客户端的 base_url
,然后运行以下代码:
from huggingface_hub import get_token
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8080/v1/",
api_key=get_token() or "-",
)
chat_completion = client.chat.completions.create(
model="tgi",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is 2+2?"},
],
max_tokens=128,
)
这将产生以下输出:
ChatCompletion(id='', choices=[Choice(finish_reason='eos_token', index=0, message=ChatCompletionMessage(content='2 + 2 equals 4.', role='assistant', function_call=None, tool_calls=None), logprobs=None)], created=1719996359, model='/data/Qwen2-7B-Instruct', object='chat.completion', system_fingerprint='2.1.0-native', usage=CompletionUsage(completion_tokens=9, prompt_tokens=26, total_tokens=35))
删除 GKE 集群
最后,在您完成在 GKE 集群上使用 TGI 后,可以安全地删除 GKE 集群以避免产生不必要的费用。
gcloud container clusters delete $CLUSTER_NAME --location=$LOCATION
或者,如果您想保留集群,也可以将已部署 Pod 的副本数量缩减到 0,因为使用 GKE 自动驾驶仪模式部署的默认 GKE 集群仅运行一个 e2-small
实例。
kubectl scale --replicas=0 --namespace $NAMESPACE deployment/tgi-deployment
📍 在 GitHub 上查看完整示例 此处!