このガイドでは、Google Kubernetes Engine(GKE)モードで Ray フレームワークを使用して大規模言語モデル(LLM)を提供する方法について説明します。このガイドは、LLM を提供するために GKE オーケストレーション機能を使用する MLOps または DevOps エンジニア、またはプラットフォーム管理者を対象としています。
このガイドでは、次のモデルを提供できます。
GKE で次の操作を行う前に、GKE での GPU についてを確認することをおすすめします。
背景
Ray フレームワークは、ML ワークロードのトレーニング、微調整、推論を行うエンドツーエンドの AI / ML プラットフォームを提供します。GPU の数はモデルのデータ形式によって異なります。このガイドでは、各モデルで 2 つの L4 GPU を使用します。詳細については、GPU の量の計算をご覧ください。
このガイドでは、次の手順を説明します。
- GKE の Autopilot クラスタまたは Standard クラスタを作成する。
- KubeRay オペレーターをデプロイする。
- LLM を提供する RayService カスタム リソースをデプロイする。
始める前に
始める前に、次の作業が完了していることを確認してください。
- 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 を提供できます。フルマネージドの Kubernetes 環境を実現するには、Autopilot クラスタを使用することをおすすめします。高いスケーラビリティを必要とするユースケースや、クラスタ構成をより詳細に制御する必要がある場合は、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
- Standard クラスタの場合は、次のコマンドを実行します。
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 ノードプール
- Ray CustomResourceDefinitions(CRD)を使用した KubeRay オペレーター
プロビジョニングされたクラスタの認証情報を取得します。この認証情報は、ガイドの次のセクションで
kubectl
によって使用されます。gcloud container clusters get-credentials ml-cluster --region us-central1
rayserve
フォルダに移動します。cd ${TUTORIAL_HOME}/rayserve
LLM モデルをデプロイする
クローン作成されたリポジトリでは、models
フォルダにモデルを読み込む構成が含まれています。ray-llm
の場合、各モデルの構成は次の要素で構成されます。
- Deployment: Ray Serve 構成
- エンジン: Huggingface モデル、モデル パラメータ、プロンプトの詳細
- スケーリング: モデルが使用する Ray リソースの定義
- モデルに固有の構成
このガイドでは、HuggingFace トランスフォーマーを介して 4 ビットの NormalFloat(NF4)の量子化を使用し、少ない GPU メモリ フットプリントで LLM を読み込みます(2 つの L4 GPU で、合計 48 GB の 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
- Standard:
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
- Standard:
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
- Standard:
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
- Standard:
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 } }
チャット インターフェースをデプロイする
必要に応じて、Gradio を使用して、モデルを操作できるウェブ アプリケーションを構築できます。Gradio は、chatbot のユーザー インターフェースを作成する ChatInterface ラッパーを含む Python ライブラリです。
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 億 x 4 ビット(700 億 x 4 ビット = 35 GB)に 5 GB のオーバーヘッドを加えたものです。この場合、1 つの L4 GPU ではメモリが足りません。このため、このチュートリアルの例では 2 つの L4 GPU メモリ(2 × 24 = 48 GB)を使用します。この構成は、L4 GPU で Falcon 40b または Llama 2 70b を実行するのに十分です。
プロジェクトを削除する
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
個々のリソースを削除する
既存のプロジェクトを削除しない場合は、リソースを個別に削除します。
gke-platform
フォルダに移動します。cd ${TUTORIAL_HOME}/gke-platform
クラスタの削除保護を無効にし、Terraform でプロビジョニングされたすべてのリソースを削除します。次のコマンドを実行します。
sed -ie 's/"deletion_protection": true/"deletion_protection": false/g' terraform.tfstate terraform destroy --auto-approve