本文以Qwen2-1.5B-Instruct模型、GPU類型為A10卡為例,示範如何在ACK中使用Triton推理服務 + TensorRT-LLM部署通義千問模型推理服務。模型部署過程中使用Fluid Dataflow完成模型準備工作,並使用Fluid提升模型載入速度。
背景資訊
Qwen2-1.5B-Instruct
Qwen2-1.5B-Instruct是基於Transformer的大語言模型,在超大規模的預訓練資料上進行訓練得到的15億參數規模的模型。預訓練資料類型多樣,覆蓋廣泛,包括大量網路文本、專業書籍、代碼等。
更多模型資訊,請參見Qwen2 Github程式碼程式庫。
Triton(Triton Inference Server)
Triton Inference Server是NVIDIA開源的推理服務架構,可以協助您快速搭建AI推理應用。Triton支援多種不同的機器學習架構作為它的運行時後端,包括TensorRT、TensorFlow、PyTorch、ONNX、vLLM等。Triton面向即時推理、批量推理以及音視頻流式推理情境進行了許多最佳化,以在推理時獲得更好的效能。
更多關於Triton推理服務架構的資訊,請參見Triton Inference Server GitHub程式碼程式庫。
TensorRT-LLM
TensorRT-LLM 是NVIDIA開源的LLM(Large Language Model)模型最佳化引擎,用於定義LLM模型並將模型構建為TensorRT引擎,以提升服務在NVIDIA GPU上的推理效率。TensorRT-LLM還可以與Triton架構結合,作為Triton推理架構的一種後端TensorRT-LLM Backend。TensorRT-LLM構建的模型可以在單個或多個GPU上運行,支援Tensor Parallelism及Pipeline Parallelism。
更多關於TensorRT-LLM的資訊,請參見TensorRT-LLM Github程式碼程式庫。
前提條件
已建立包含A10卡GPU的ACK叢集Pro版,且叢集版本為1.22及以上。具體操作,請參見建立ACK託管叢集。
建議GPU節點使用525版本驅動,您可以通過為GPU節點池添加標籤
ack.aliyun.com/nvidia-driver-version:525.105.17
指定驅動版本為525.105.17。具體操作,請參見通過指定版本號碼自訂節點GPU驅動版本。已安裝雲原生AI套件並部署ack-fluid組件。
重要若您已安裝開源Fluid,請卸載後再部署ack-fluid組件。
未安裝雲原生AI套件:安裝時開啟Fluid資料加速。具體操作,請參見安裝雲原生AI套件。
已安裝雲原生AI套件:在Container Service管理主控台的雲原生AI套件頁面部署ack-fluid。
已安裝最新版Arena用戶端。具體操作,請參見配置Arena用戶端。
已開通阿里雲Object Storage Service服務,並建立儲存空間。具體操作,請參見開通OSS服務、建立儲存空間。
步驟一:建立Dataset和JindoRuntime
Dataset可以高效地組織和處理資料,而整合JindoRuntime可以通過資料緩衝策略進一步加速資料訪問,兩者結合可以大幅提升資料處理和模型服務的效能。
執行以下命令,建立用於儲存OSS的訪問憑證的Secret。
kubectl apply -f-<<EOF apiVersion: v1 kind: Secret metadata: name: fluid-oss-secret stringData: fs.oss.accessKeyId: <YourAccessKey ID> fs.oss.accessKeySecret: <YourAccessKey Secret> EOF
其中,
fs.oss.accessKeyId
和fs.oss.accessKeySecret
是用來訪問OSS的AccessKey ID(AK)和AccessKey Secret(SK)。關於如何擷取AK和SK,請參見擷取AccessKey。預期輸出:
secret/fluid-oss-secret created
建立並拷貝以下內容到dataset.yaml檔案中,用於建立一個Dataset和一個JindoRuntime來提供快取服務。關於Dataset及JindoRuntime的詳細配置資訊,請參見JindoFS加速OSS檔案訪問。
# 建立一個Dataset,描述遠端儲存資料集和UFS的資訊。 apiVersion: data.fluid.io/v1alpha1 kind: Dataset metadata: name: qwen2-oss spec: mounts: - mountPoint: oss://<oss_bucket>/qwen2-1.5b # 請替換為實際的模型儲存地址。 name: qwen2 path: / options: fs.oss.endpoint: <oss_endpoint> # 請替換為實際的OSS endpoint地址。 encryptOptions: - name: fs.oss.accessKeyId valueFrom: secretKeyRef: name: fluid-oss-secret key: fs.oss.accessKeyId - name: fs.oss.accessKeySecret valueFrom: secretKeyRef: name: fluid-oss-secret key: fs.oss.accessKeySecret accessModes: - ReadWriteMany # 建立一個JindoRuntime,啟動一個JindoFS的叢集來提供快取服務。 --- apiVersion: data.fluid.io/v1alpha1 kind: JindoRuntime metadata: name: qwen2-oss spec: replicas: 2 tieredstore: levels: - mediumtype: MEM volumeType: emptyDir path: /dev/shm quota: 20Gi high: "0.95" low: "0.7" fuse: properties: fs.oss.read.buffer.size: "8388608" # 8M fs.oss.download.thread.concurrency: "200" fs.oss.read.readahead.max.buffer.count: "200" fs.oss.read.sequence.ambiguity.range: "2147483647" args: - -oauto_cache - -oattr_timeout=1 - -oentry_timeout=1 - -onegative_timeout=1
執行以下命令,建立JindoRuntime和Dataset。
kubectl apply -f dataset.yaml
預期輸出:
dataset.data.fluid.io/qwen2-oss created jindoruntime.data.fluid.io/qwen2-oss created
輸出結果表明Dataset資源和JindoRuntime資源已被成功建立。
執行以下命令,查看Dataset的部署情況。
kubectl get dataset qwen2-oss
預期輸出:
NAME UFS TOTAL SIZE CACHED CACHE CAPACITY CACHED PERCENTAGE PHASE AGE qwen2-oss 0.00B 0.00B 20.00GiB 0.0% Bound 57s
步驟二:建立Dataflow
要使用TensorRT-LLM加速模型推理,首先需要下載模型檔案,然後進行模型檔案格式轉換,構建TensorRT Engine,修改設定檔等操作。本文通過使用Fluid Dataflow完成上述步驟。
建立並拷貝以下內容到dataflow.yaml檔案中,用於建立一個Dataflow,包含以下三個步驟:
從ModelScope下載Qwen2-1.5B-Instruct模型。
使用TensorRT-LLM工具完成模型格式轉換,構建Engine。
使用Dataload更新Dataset資料。
# 從ModelScope平台下載Qwen2-1.5B-Instruct模型到指定的儲存路徑。 apiVersion: data.fluid.io/v1alpha1 kind: DataProcess metadata: name: step1-download-model spec: dataset: name: qwen2-oss namespace: default mountPath: /mnt/models/ processor: script: image: ac2-registry.cn-hangzhou.cr.aliyuncs.com/ac2/base imageTag: ubuntu22.04 imagePullPolicy: IfNotPresent restartPolicy: OnFailure command: - bash source: | #!/bin/bash echo "download model..." if [ -d "${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct" ]; then echo "directory ${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct exists, skip download model" else apt update && apt install -y git git-lfs git clone https://www.modelscope.cn/qwen/Qwen2-1.5B-Instruct.git Qwen2-1.5B-Instruct mv Qwen2-1.5B-Instruct ${MODEL_MOUNT_PATH} fi env: - name: MODEL_MOUNT_PATH value: "/mnt/models" # 將下載的模型轉換為TensorRT-LLM所需的格式,並構建推理引擎。 --- apiVersion: data.fluid.io/v1alpha1 kind: DataProcess metadata: name: step2-trtllm-convert spec: runAfter: kind: DataProcess name: step1-download-model namespace: default dataset: name: qwen2-oss namespace: default mountPath: /mnt/models/ processor: script: image: kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/tritonserver-build imageTag: 24.07-trtllm-python-py3 imagePullPolicy: IfNotPresent restartPolicy: OnFailure command: - bash source: | #!/bin/bash set -ex cd /tensorrtllm_backend/tensorrt_llm/examples/qwen if [ -d "${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-ckpt" ]; then echo "directory ${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-ckpt exists, skip convert checkpoint" else echo "covert checkpoint..." python3 convert_checkpoint.py --model_dir ${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct --output_dir /root/Qwen2-1.5B-Instruct-ckpt --dtype float16 echo "Writing trtllm model ckpt to OSS Bucket..." mv /root/Qwen2-1.5B-Instruct-ckpt ${MODEL_MOUNT_PATH} fi sleep 2 if [ -d "${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-engine" ]; then echo "directory $OUTPUT_DIR/Qwen2-1.5B-Instruct-engine exists, skip build engine" else echo "build trtllm engine..." trtllm-build --checkpoint_dir ${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-ckpt \ --gemm_plugin float16 \ --paged_kv_cache enable \ --output_dir /root/Qwen2-1.5B-Instruct-engine echo "Writing trtllm engine to OSS Bucket..." mv /root/Qwen2-1.5B-Instruct-engine ${MODEL_MOUNT_PATH} fi if [ -d "${MODEL_MOUNT_PATH}/tensorrtllm_backend" ]; then echo "directory $OUTPUT_DIR/tensorrtllm_backend exists, skip config tensorrtllm_backend" else echo "config model..." cd /tensorrtllm_backend cp all_models/inflight_batcher_llm/ qwen2_ifb -r export QWEN2_MODEL=${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct export ENGINE_PATH=${MODEL_MOUNT_PATH}/Qwen2-1.5B-Instruct-engine python3 tools/fill_template.py -i qwen2_ifb/preprocessing/config.pbtxt tokenizer_dir:${QWEN2_MODEL},triton_max_batch_size:8,preprocessing_instance_count:1 python3 tools/fill_template.py -i qwen2_ifb/postprocessing/config.pbtxt tokenizer_dir:${QWEN2_MODEL},triton_max_batch_size:8,postprocessing_instance_count:1 python3 tools/fill_template.py -i qwen2_ifb/tensorrt_llm_bls/config.pbtxt triton_max_batch_size:8,decoupled_mode:False,bls_instance_count:1,accumulate_tokens:False python3 tools/fill_template.py -i qwen2_ifb/ensemble/config.pbtxt triton_max_batch_size:8 python3 tools/fill_template.py -i qwen2_ifb/tensorrt_llm/config.pbtxt triton_backend:tensorrtllm,triton_max_batch_size:8,decoupled_mode:False,max_beam_width:1,engine_dir:${ENGINE_PATH},max_tokens_in_paged_kv_cache:1280,max_attention_window_size:1280,kv_cache_free_gpu_mem_fraction:0.5,exclude_input_in_output:True,enable_kv_cache_reuse:False,batching_strategy:inflight_fused_batching,max_queue_delay_microseconds:0 echo "Writing trtllm config to OSS Bucket..." mkdir -p ${MODEL_MOUNT_PATH}/tensorrtllm_backend mv /tensorrtllm_backend/qwen2_ifb ${MODEL_MOUNT_PATH}/tensorrtllm_backend fi env: - name: MODEL_MOUNT_PATH value: "/mnt/models" resources: requests: cpu: 2 memory: 10Gi nvidia.com/gpu: 1 limits: cpu: 12 memory: 30Gi nvidia.com/gpu: 1 # 載入轉換並最佳化後的模型及配置到記憶體中,以實現快速響應的推理服務。 --- apiVersion: data.fluid.io/v1alpha1 kind: DataLoad metadata: name: step3-warmup-cahce spec: runAfter: kind: DataProcess name: step2-trtllm-convert namespace: default dataset: name: qwen2-oss namespace: default loadMetadata: true target: - path: /Qwen2-1.5B-Instruct-engine - path: /tensorrtllm_backend
以上代碼的三個步驟共同構成了一個完整的模型部署流程,從原始模型的下載、轉換、最佳化到最終的緩衝預先載入,實現了自動化、可擴充的模型部署。
執行以下命令,建立Dataflow。
kubectl create -f dataflow.yaml
預期輸出:
dataprocess.data.fluid.io/step1-download-model created dataprocess.data.fluid.io/step2-trtllm-convert created dataload.data.fluid.io/step3-warmup-cahce created
輸出結果表明已成功地根據
dataflow.yaml
檔案中的定義建立了相應的自訂資來源物件。執行以下命令,查看Dataflow執行情況,等待任務執行完成。
kubectl get dataprocess
預期輸出:
NAME DATASET PHASE AGE DURATION step1-download-model qwen2-oss Complete 23m 3m2s step2-trtllm-convert qwen2-oss Complete 23m 19m58s
輸出結果表明叢集中與資料集
qwen2-oss
相關的兩個資料處理任務(下載模型和轉換模型至trtllm
格式)都已經成功完成。
步驟三:部署推理服務
執行以下命令,通過Arena命令部署一個Custom類型的Serve服務。
該服務名稱為qwen2-chat,version為v1,需要使用一個GPU,副本數為1,並且配置了就緒檢測。模型是一種特殊類型的資料,因此採用
--data
參數將Fluid建立的模型PVCqwen2-oss
掛載到了容器中的/mnt/models
目錄下。arena serve custom \ --name=qwen2-chat \ --version=v1 \ --gpus=1 \ --replicas=1 \ --restful-port=8000 \ --readiness-probe-action="tcpSocket" \ --readiness-probe-action-option="port: 8000" \ --readiness-probe-option="initialDelaySeconds: 30" \ --readiness-probe-option="periodSeconds: 30" \ --image=kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/tritonserver:24.07-trtllm-python-py3 \ --data=qwen2-oss:/mnt/models \ "tritonserver --model-repository=/mnt/models/tensorrtllm_backend/qwen2_ifb --http-port=8000 --grpc-port=8001 --metrics-port=8002 --disable-auto-complete-config --backend-config=python,shm-region-prefix-name=prefix0_"
參數說明如下:
參數
說明
--name
指定推理服務名稱。
--version
指定推理服務版本。
--gpus
指定單個推理服務副本需要使用的GPU卡數。
--replicas
指定推理服務副本數。
--restful-port
指定推理服務對外暴露的連接埠。
--readiness-probe-action
指定就緒探針連線類型,支援HttpGet、Exec、gRPC、TCPSocket。
--readiness-probe-action-option
指定就緒探針串連方式。
--readiness-probe-option
指定就緒探針配置。
--data
掛載共用儲存卷PVC到運行環境中。它由兩部分組成,通過英文冒號(:)分割。冒號左側是您已經準備好的PVC名稱。您可以通過命令
arena data list
查看當前叢集可用的PVC列表;冒號右側是您想將PVC掛載到運行環境中的路徑,也是您訓練代碼要讀取資料或模型的本地路徑。這樣通過掛載的方式,您的代碼就可以訪問PVC中的資料或模型。--image
指定推理服務的鏡像地址。
預期輸出:
service/qwen2-chat-v1 created deployment.apps/qwen2-chat-v1-custom-serving created INFO[0003] The Job qwen2-chat has been submitted successfully INFO[0003] You can run `arena serve get qwen2-chat --type custom-serving -n default` to check the job status
輸出結果表明推理服務已成功部署。
執行下列命令,查看推理服務詳細資料,等待服務就緒。
arena serve get qwen2-chat
預期輸出:
Name: qwen2-chat Namespace: default Type: Custom Version: v1 Desired: 1 Available: 1 Age: 1m Address: 192.XX.XX.XX Port: RESTFUL:8000 GPU: 1 Instances: NAME STATUS AGE READY RESTARTS GPU NODE ---- ------ --- ----- -------- --- ---- qwen2-chat-v1-custom-serving-657869c698-hl665 Running 1m 1/1 0 1 ap-southeast-1.192.XX.XX.XX
輸出結果表明該推理服務的一個Pod(qwen2-chat-v1-custom-serving-657869c698-hl665)正在穩定運行,且已準備好提供服務。
步驟四:驗證推理服務
執行以下命令,在推理服務與本地環境之間建立連接埠轉寄。
重要請注意kubectl port-forward建立的連接埠轉寄不具備生產層級的可靠性、安全性和擴充性,因此僅適用於開發和調試目的,不適合在生產環境使用。更多關於Kubernetes叢集內生產可用的網路方案的資訊,請參見Ingress概述。
kubectl port-forward svc/qwen2-chat-v1 8000:8000
預期輸出:
Forwarding from 127.0.0.1:8000 -> 8000 Forwarding from [::1]:8000 -> 8000
執行以下命令,發送模型推理請求。
curl -X POST localhost:8000/v2/models/ensemble/generate -d '{"text_input": "什麼是機器學習?", "max_tokens": 20, "bad_words": "", "stop_words": "", "pad_id": 2, "end_id": 2}'
預期輸出:
{"context_logits":0.0,"cum_log_probs":0.0,"generation_logits":0.0,"model_name":"ensemble","model_version":"1","output_log_probs":[0.0,0.0,0.0,0.0],"sequence_end":false,"sequence_id":0,"sequence_start":false,"text_output":" 機器學習是一種人工智慧技術,它使電腦系統能夠從資料中學習,而無需明確的編程。"}
輸出結果表明模型可以根據給定的輸入產生相應的回複。
(可選)步驟五:清理環境
如果不再使用已部署的模型推理服務,請執行以下命令,刪除服務。
arena serve delete qwen2-chat