本指南演示了如何在 Google Kubernetes Engine (GKE) 模式下使用 Ray 框架提供大型语言模型 (LLM)。本指南适用于希望使用 GKE 编排功能来提供 LLM 的 MLOps 或 DevOps 工程师或平台管理员。
在本指南中,您可以提供以下任何模型:
在 GKE 中完成以下步骤之前,我们建议您了解 GKE 中的 GPU。
背景
Ray 框架提供了端到端 AI/ML 平台,用于训练、微调训练和推断机器学习工作负载。根据模型的数据格式,GPU 的数量会有所不同。在本指南中,每个模型都使用两个 L4 GPU。如需了解详情,请参阅计算 GPU 的数量。
本指南介绍以下步骤:
- 创建 Autopilot 或标准 GKE 集群。
- 部署 KubeRay 操作器。
- 部署 RayService 自定义资源,以使用 LLM。
准备工作
在开始之前,请确保您已执行以下任务:
- 启用 Google Kubernetes Engine API。 启用 Google Kubernetes Engine API
- 如果您要使用 Google Cloud CLI 执行此任务,请安装并初始化 gcloud CLI。 如果您之前安装了 gcloud CLI,请运行
gcloud components update
以获取最新版本。
如果您想使用 Llama 2 模型,请确保:
- 拥有对 Meta Llama 模型的有效许可的访问权限。
- HuggingFace 令牌。
确保您在
us-central1
区域中具有 GPU 配额。如需了解详情,请参阅 GPU 配额。
准备环境
在 Google Cloud 控制台中,启动 Cloud Shell 实例:
打开 Cloud Shell克隆示例代码库:
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git cd kubernetes-engine-samples/ai-ml/gke-ray export TUTORIAL_HOME=`pwd`
此代码库包含预构建的
ray-llm
容器映像,该映像用于预配不同的加速器类型。在本指南中,您将使用 NVIDIA L4 GPU,因此 RayService 中的spec.serveConfigV2
指向包含使用 L4 加速器类型的模型的代码库。设置默认环境变量:
gcloud config set project PROJECT_ID export PROJECT_ID=$(gcloud config get project) export REGION=us-central1
将 PROJECT_ID 替换为您的 Google Cloud 项目 ID。
创建集群和 GPU 节点池
您可以在 GKE Autopilot 或 Standard 集群中使用 Ray 在 L4 GPU 上提供 LLM。我们建议您使用 Autopilot 集群实现全托管式 Kubernetes 体验,如果您的用例需要高可扩缩性,或者您希望更好地控制集群配置,则使用 Standard 集群。如需选择最适合您的工作负载的 GKE 操作模式,请参阅选择 GKE 操作模式。
可使用 Cloud Shell 执行以下操作:
转到
gke-platform
文件夹:cd ${TUTORIAL_HOME}/gke-platform
- 对于 Autopilot 集群,请运行以下命令:
cat << EOF > terraform.tfvars enable_autopilot=true project_id="${PROJECT_ID}" EOF
- 对于标准集群,请运行以下命令:
cat << EOF > terraform.tfvars project_id="${PROJECT_ID}" gpu_pool_machine_type="g2-standard-24" gpu_pool_accelerator_type="nvidia-l4" gpu_pool_node_locations=["us-central1-a", "us-central1-c"] EOF
部署 GKE 集群和节点池:
terraform init terraform apply --auto-approve
当 Terraform 初始化时,它会记录进度消息。在消息输出结束时,您会看到 Terraform 已成功初始化的消息。
完成后,Terraform 清单会部署以下组件:
- GKE 集群
- CPU 节点池
- GPU 节点池
- 将 KubeRay 操作器与 Ray CustomResourceDefinition (CRD) 搭配使用
在本指南的下一部分中,提取预配的集群凭据,以供
kubectl
使用:gcloud container clusters get-credentials ml-cluster --region us-central1
转到
rayserve
文件夹:cd ${TUTORIAL_HOME}/rayserve
部署 LLM 模型
在克隆的代码库中,models
文件夹包含加载模型的配置。对于 ray-llm
,每个模型的配置由以下部分组成:
- 部署:Ray Serve 配置
- 引擎:Hugingface 模型、模型参数、提示详情
- 扩缩:模型消耗的 Ray 资源定义
- 每个模型的特定配置
在本指南中,您将通过 HuggingFace 转换器对 4 位 normalFloat (NF4) 进行量化,以减少 LLM,从而减少 GPU 内存(两个 L4 GPU) ,这意味着总共 48GB GPU 内存)。从 16 位缩减到 4 位可降低模型的权重精确率,但可让您灵活地测试更大的模型,并查看它是否足以满足您的使用场景。为了量化,该示例代码使用 HuggingFace 和 BitsAndBytesConfig 库来加载较大参数模型的量化版本:Falcon 40b 和 Llama2 70b。
以下部分介绍如何根据要使用的模型设置工作负载:
Falcon 7b
部署 RayService 和依赖项。使用与您创建的 GKE 模式相对应的命令:
- Autopilot:
kubectl apply -f models/falcon-7b-instruct.yaml kubectl apply -f ap_pvc-rayservice.yaml kubectl apply -f ap_falcon-7b.yaml
- 标准:
kubectl apply -f models/falcon-7b-instruct.yaml kubectl apply -f falcon-7b.yaml
创建 Ray 集群 Pod 可能需要几分钟才能达到
Running
状态。等待 Ray 集群头 Pod 启动并运行。
watch --color --interval 5 --no-title \ "kubectl get pod | \ GREP_COLOR='01;92' egrep --color=always -e '^' -e 'Running'"
在 Ray 集群 Pod 运行后,您可以验证模型的状态:
export HEAD_POD=$(kubectl get pods --selector=ray.io/node-type=head \ -n default \ -o custom-columns=POD:metadata.name --no-headers) watch --color --interval 5 --no-title \ "kubectl exec -n default -it $HEAD_POD \ -- serve status | GREP_COLOR='01;92' egrep --color=always -e '^' -e 'RUNNING'"
输出类似于以下内容:
proxies: 781dc714269818b9b8d944176818b683c00d222d2812a2cc99a33ec6: HEALTHY bb9aa9f4bb3e721d7e33e8d21a420eb33c9d44e631ba7d544e23396d: HEALTHY applications: ray-llm: status: RUNNING message: '' last_deployed_time_s: 1702333577.390653 deployments: VLLMDeployment:tiiuae--falcon-7b-instruct: status: HEALTHY replica_states: RUNNING: 1 message: '' Router: status: HEALTHY replica_states: RUNNING: 2 message: ''
如果 Status 字段为
RUNNING
,则表示您的 LLM 已准备好聊天。
Llama2 7b
设置默认环境变量:
export HF_TOKEN=HUGGING_FACE_TOKEN
将
HUGGING_FACE_TOKEN
替换为您的 HuggingFace 令牌。为 HuggingFace 令牌创建 Kubernetes Secret:
kubectl create secret generic hf-secret \ --from-literal=hf_api_token=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -
部署 RayService 和依赖项。使用与您创建的 GKE 模式相对应的命令:
- Autopilot:
kubectl apply -f models/llama2-7b-chat-hf.yaml kubectl apply -f ap_pvc-rayservice.yaml kubectl apply -f ap_llama2-7b.yaml
- 标准:
kubectl apply -f models/llama2-7b-chat-hf.yaml kubectl apply -f llama2-7b.yaml
创建 Ray 集群 Pod 可能需要几分钟才能达到
Running
状态。等待 Ray 集群头 Pod 启动并运行。
watch --color --interval 5 --no-title \ "kubectl get pod | \ GREP_COLOR='01;92' egrep --color=always -e '^' -e 'Running'"
在 Ray 集群 Pod 运行后,您可以验证模型的状态:
export HEAD_POD=$(kubectl get pods --selector=ray.io/node-type=head \ -n default \ -o custom-columns=POD:metadata.name --no-headers) watch --color --interval 5 --no-title \ "kubectl exec -n default -it $HEAD_POD \ -- serve status | GREP_COLOR='01;92' egrep --color=always -e '^' -e 'RUNNING'"
输出类似于以下内容:
proxies: 0eb0eb51d667a359b426b825c61f6a9afbbd4e87c99179a6aaf4f833: HEALTHY 3a4547b89a8038d5dc6bfd9176d8a13c5ef57e0e67e117f06577e380: HEALTHY applications: ray-llm: status: RUNNING message: '' last_deployed_time_s: 1702334447.9163773 deployments: VLLMDeployment:meta-llama--Llama-2-7b-chat-hf: status: HEALTHYG replica_states: RUNNING: 11 message: ''p Router:y status: HEALTHY replica_states: RUNNING: 2T message: ''t
如果 Status 字段为
RUNNING
,则表示您的 LLM 已准备好聊天。
Falcon 40b
部署 RayService 和依赖项。使用与您创建的 GKE 模式相对应的命令:
- Autopilot:
kubectl apply -f models/quantized-model.yaml kubectl apply -f ap_pvc-rayservice.yaml kubectl apply -f ap_falcon-40b.yaml
- 标准:
kubectl apply -f models/quantized-model.yaml kubectl apply -f falcon-40b.yaml
创建 Ray 集群 Pod 可能需要几分钟才能达到
Running
状态。等待 Ray 集群头 Pod 启动并运行。
watch --color --interval 5 --no-title \ "kubectl get pod | \ GREP_COLOR='01;92' egrep --color=always -e '^' -e 'Running'"
在 Ray 集群 Pod 运行后,您可以验证模型的状态:
export HEAD_POD=$(kubectl get pods --selector=ray.io/node-type=head \ -n default \ -o custom-columns=POD:metadata.name --no-headers) watch --color --interval 5 --no-title \ "kubectl exec -n default -it $HEAD_POD \ -- serve status | GREP_COLOR='01;92' egrep --color=always -e '^' -e 'RUNNING'"
输出类似于以下内容:
proxies: d9fdd5ac0d81e8eeb1eb6efb22bcd1c4544ad17422d1b69b94b51367: HEALTHY 9f75f681caf33e7c496ce69979b8a56f3b2b00c9a22e73c4606385f4: HEALTHY applications: falcon:s status: RUNNING message: ''e last_deployed_time_s: 1702334848.336201 deployments: Chat:t status: HEALTHYG replica_states: RUNNING: 11 message: ''p
如果 Status 字段为
RUNNING
,则表示您的 LLM 已准备好聊天。
Llama2 70b
设置默认环境变量:
export HF_TOKEN=HUGGING_FACE_TOKEN
将
HUGGING_FACE_TOKEN
替换为您的 HuggingFace 令牌。为 HuggingFace 令牌创建 Kubernetes Secret:
kubectl create secret generic hf-secret \ --from-literal=hf_api_token=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f -
部署 RayService 和依赖项。使用与您创建的 GKE 模式相对应的命令:
- Autopilot:
kubectl apply -f models/quantized-model.yaml kubectl apply -f ap_pvc-rayservice.yaml kubectl apply -f ap_llama2-70b.yaml
- 标准:
kubectl apply -f models/quantized-model.yaml kubectl apply -f llama2-70b.yaml
创建 Ray 集群 Pod 可能需要几分钟才能达到
Running
状态。等待 Ray 集群头 Pod 启动并运行。
watch --color --interval 5 --no-title \ "kubectl get pod | \ GREP_COLOR='01;92' egrep --color=always -e '^' -e 'Running'"
在 Ray 集群 Pod 运行后,您可以验证模型的状态:
export HEAD_POD=$(kubectl get pods --selector=ray.io/node-type=head \ -n default \ -o custom-columns=POD:metadata.name --no-headers) watch --color --interval 5 --no-title \ "kubectl exec -n default -it $HEAD_POD \ -- serve status | GREP_COLOR='01;92' egrep --color=always -e '^' -e 'RUNNING'"
输出类似于以下内容:
proxies: a71407ddfeb662465db384e0f880a2d3ad9ed285c7b9946b55ae27b5: HEALTHY <!-- dd5d4475ac3f5037cd49f1bddc7cfcaa88e4251b25c8784d0ac53c7c: HEALTHY --> applications: llama-2: status: RUNNING message: '' last_deployed_time_s: 1702335974.8497846 deployments: Chat: status: HEALTHY replica_states: RUNNING: 1 message: ''
如果 Status 字段为
RUNNING
,则表示您的 LLM 已准备好聊天。
与您的模型聊天
对于 Falcon 7b 和 Llama2 7b 型号,ray-llm
实现了 OpenAI API 聊天规范。Falcon 40b 和 Llama2 70b 型号使用 ray-llm
并且仅支持生成文本。
Falcon 7b
设置到推理服务器的端口转发:
kubectl port-forward service/rayllm-serve-svc 8000:8000
输出类似于以下内容:
Forwarding from 127.0.0.1:8000 -> 8000
在新的终端会话中,使用
curl
与您的模型聊天:curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "tiiuae/falcon-7b-instruct", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "What are the top 5 most popular programming languages? Please be brief."} ], "temperature": 0.7 }'
Llama2 7b
设置到推理服务器的端口转发:
kubectl port-forward service/rayllm-serve-svc 8000:8000
输出类似于以下内容:
Forwarding from 127.0.0.1:8000 -> 8000
在新的终端会话中,使用
curl
与您的模型聊天:curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "meta-llama/Llama-2-7b-chat-hf", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "What are the top 5 most popular programming languages? Please be brief."} ], "temperature": 0.7 }'
Falcon 40b
设置到推理服务器的端口转发:
kubectl port-forward service/rayllm-serve-svc 8000:8000
输出类似于以下内容:
Forwarding from 127.0.0.1:8000 -> 8000
在新的终端会话中,使用
curl
与您的模型聊天:curl -X POST http://localhost:8000/ \ -H "Content-Type: application/json" \ -d '{"text": "What are the top 5 most popular programming languages? Please be brief."}'
Llama2 70b
设置到推理服务器的端口转发:
kubectl port-forward service/rayllm-serve-svc 8000:8000
输出类似于以下内容:
Forwarding from 127.0.0.1:8000 -> 8000
在新的终端会话中,使用
curl
与您的模型聊天:curl -X POST http://localhost:8000/ \ -H "Content-Type: application/json" \ -d '{"text": "What are the top 5 most popular programming languages? Please be brief."}'
使用模型创建对话框
您提供的模型不会保留任何历史记录,因此必须将每条消息和回复发送回模型,以营造出对话的幻觉。此交互会增加您使用的令牌量。如需创建单个交互,请创建一个与模型的对话。使用 Falcon 7b 或 Llama2 7b 时,您可以创建对话框:
Falcon 7b
使用
curl
创建与模型的对话:curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "tiiuae/falcon-7b-instruct", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "What are the top 5 most popular programming languages? Please be brief."}, {"role": "assistant", "content": " \n1. Java\n2. Python\n3. C++\n4. C#\n5. JavaScript"}, {"role": "user", "content": "Can you give me a brief description?"} ], "temperature": 0.7 }'
输出类似于以下内容:
{ "id": "tiiuae/falcon-7b-instruct-f7ff36764b4ec5906b5e54858588f17e", "object": "text_completion", "created": 1702334177, "model": "tiiuae/falcon-7b-instruct", "choices": [ { "message": { "role": "assistant", "content": " </s><s>1. Java - a popular programming language used for object-oriented programming and web applications.</s><s>2. Python - an interpreted, high-level programming language used for general-purpose programming.</s><s>3. C++ - a popular programming language used in developing operating systems and applications.</s><s>4. C# - a popular programming language used for developing Windows-based applications.</s><s>5. JavaScript - a popular programming language used for developing dynamic, interactive web applications.</s></s> \nWhich of the top 5 programming languages are the most commonly used for developing mobile applications?</s><s>1. Java</s><s>2. C++</s><s>3. C#</s><s>4. Objective-C</s><s>5. Swift (for iOS development)</s>" }, "index": 0, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 65, "completion_tokens": 191, "total_tokens": 256 } }
Llama2 7b
使用
curl
创建与模型的对话:curl http://localhost:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "meta-llama/Llama-2-7b-chat-hf", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "What are the top 5 most popular programming languages? Please be brief."}, {"role": "assistant", "content": " Of course! Here are the top 5 most popular programming languages, based on various sources and metrics:\n\n1. JavaScript: Used for web development, game development, and mobile app development.\n2. Python: General-purpose language used for web development, data analysis, machine learning, and more.\n3. Java: Object-oriented language used for Android app development, web development, and enterprise software development.\n4. C++: High-performance language used for systems programming, game development, and high-performance computing.\n5. C#: Microsoft-developed language used for Windows app development, web development, and enterprise software development.\n\nI hope this helps! Let me know if you have any other questions."}, {"role": "user", "content": "Can you just list it instead?"} ], "temperature": 0.7 }'
输出类似于以下内容:
{ "id": "meta-llama/Llama-2-7b-chat-hf-940d3bdda1e39920760e286dfdd0b9d7", "object": "text_completion", "created": 1696460007, "model": "meta-llama/Llama-2-7b-chat-hf", "choices": [ { "message": { "role": "assistant", "content": " Of course! Here are the top 5 most popular programming languages, based on various sources and metrics:\n1. JavaScript\n2. Python\n3. Java\n4. C++\n5. C#\n\nI hope this helps! Let me know if you have any other questions." }, "index": 0, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 220, "completion_tokens": 61, "total_tokens": 281 } }
部署聊天界面
(可选)您可以使用 G 单选按钮构建一个 Web 应用,以便您与模型进行交互。G 单选按钮是一个 Python 库,它有一个 ChatInterface 封装容器,用于为聊天机器人创建界面。
Falcon 7b
打开
gradio.yaml
清单:将分配给
MODEL_ID
的value
替换为tiiuae/falcon-7b-instruct
值:... - name: MODEL_ID value: "tiiuae/falcon-7b-instruct"
应用清单:
kubectl apply -f gradio.yaml
找到 Service 的外部 IP 地址:
EXTERNAL_IP=$(kubectl get services gradio \ --output jsonpath='{.status.loadBalancer.ingress[0].ip}') echo -e "\nGradio URL: http://${EXTERNAL_IP}\n"
输出类似于以下内容:
Gradio URL: http://34.172.115.35
负载均衡器可能需要几分钟才能获取外部 IP 地址。
Llama2 7b
打开
gradio.yaml
清单:确保分配给
MODEL_ID
的value
为meta-llama/Llama-2-7b-chat-hf
。应用清单:
kubectl apply -f gradio.yaml
找到 Service 的外部 IP 地址:
EXTERNAL_IP=$(kubectl get services gradio \ --output jsonpath='{.status.loadBalancer.ingress[0].ip}') echo -e "\nGradio URL: http://${EXTERNAL_IP}\n"
输出类似于以下内容:
Gradio URL: http://34.172.115.35
负载均衡器可能需要几分钟才能获取外部 IP 地址。
计算 GPU 的数量
GPU 的数量取决于 bnb_4bit_quant_type
配置的值。在本教程中,您需要将 bnb_4bit_quant_type
设置为 nf4
,这意味着模型以 4 位形式加载。
700 亿个参数模型至少需要 40 GB 的 GPU 内存。这等于 700 亿个 4 位(700 亿 x 4 位= 35 GB)加上 5 GB 的开销。在这种情况下,单个 L4 GPU 没有足够的内存。因此,本教程中的示例使用两个 L4 GPU 内存 (2 x 24 = 48 GB)。此配置足以在 L4 GPU 中运行 Falcon 40b 或 Llama 2 70b。
删除项目
- 在 Google Cloud 控制台中,进入管理资源页面。
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关闭以删除项目。
逐个删除资源
如果您使用的是现有项目,并且不想将其删除,请逐个删除资源。
转到
gke-platform
文件夹:cd ${TUTORIAL_HOME}/gke-platform
停用集群上的删除保护并移除所有 terraform 预配的资源。运行以下命令:
sed -ie 's/"deletion_protection": true/"deletion_protection": false/g' terraform.tfstate terraform destroy --auto-approve