Extend Inference Runtimes

Introduction

本文档将逐步指导您如何添加新的推理服务运行时,用于服务大语言模型(LLM)或其他模型类型,如“图像分类”、“目标检测”、“文本分类”等。

Alauda AI 内置了“vLLM”推理引擎,通过“自定义推理运行时”,您可以引入更多推理引擎,例如 Seldon MLServerTriton inference server 等。

通过引入自定义运行时,您可以扩展平台对更多模型类型和 GPU 类型的支持,并针对特定场景优化性能,以满足更广泛的业务需求。

本节将演示如何通过自定义 XInfernece 推理运行时扩展当前 AI 平台,实现 LLM 部署并提供“OpenAI 兼容 API”。

Scenarios

当您遇到以下任一情况时,建议扩展 AI 平台推理服务运行时:

  • 支持新模型类型:您的模型当前默认推理运行时 vLLM 不支持。
  • 兼容其他类型 GPU:需要在配备 AMD 或华为 Ascend 等 GPU 的硬件上执行 LLM 推理。
  • 特定场景性能优化:某些推理场景下,新运行时(如 Xinference)可能比现有运行时提供更优的性能或资源利用率。
  • 自定义推理逻辑:需要引入自定义推理逻辑或依赖库,现有默认运行时难以实现。

Prerequisites

开始前,请确保满足以下条件:

  1. 您的 ACP 集群已部署且正常运行
  2. AI 平台版本为1.3 或更高
  3. 已准备好所需的推理运行时镜像。例如,Xinference 运行时镜像可能为 xprobe/xinference:v1.2.2(GPU)或 xprobe/xinference:v1.2.2-cpu(CPU)。
  4. 拥有集群管理员权限(用于创建 CRD 实例)。

Standard Workflow (Example: Xinference)

按照以下步骤扩展平台。我们以 Xinference 为基线示例,演示标准流程。

创建推理运行时资源

根据目标硬件环境(GPU/CPU/NPU),创建对应的推理运行时 ClusterServingRuntime 资源。

  1. 准备运行时 YAML 配置

    根据您要添加的运行时类型(如 Xinference)及目标硬件环境,准备相应的 YAML 配置文件。以下是 Xinference 运行时在不同硬件环境下的示例:

  • GPU 运行时示例
    # Xinference GPU 运行时示例 YAML
    apiVersion: serving.kserve.io/v1alpha1
    kind: ClusterServingRuntime
    metadata:
      name: aml-xinference-cuda-12.1 # 运行时资源名称
      labels:
        cpaas.io/runtime-class: xinference # 必需的运行时类型标签
        cpaas.io/accelerator-type: "nvidia"
        cpaas.io/cuda-version: "12.1"
      annotations:
        cpaas.io/display-name: xinference-cuda-12.1 # UI 中显示名称
    spec:
      containers:
      - name: kserve-container
        image: xprobe/xinference:v1.2.2  # 替换为您实际准备的 GPU 运行时镜像
        env:
        # 所有运行时均需,模型目录路径
        - name: MODEL_PATH
          value: /mnt/models/{{ index .Annotations "aml-model-repo" }}
        # 其他运行时可选的 MODEL_UID 参数
        - name: MODEL_UID 
          value: '{{ index .Annotations "aml-model-repo" }}'
        # Xinference 运行时必需的 MODEL_ENGINE 参数,其他运行时可省略
        - name: MODEL_ENGINE 
          value: "transformers"
        # xinference 运行时必需参数,请根据模型家族设置,示例值:"llama"(如 "llama"、"chatglm" 等)
        - name: MODEL_FAMILY 
          value: ""
        command:
        - bash
        - -c
        - |
            set +e
            if [ "${MODEL_PATH}" == "" ]; then
                echo "Need to set MODEL_PATH!"
                exit 1
            fi
            if [ "${MODEL_ENGINE}" == "" ]; then
                echo "Need to set MODEL_ENGINE!"
                exit 1
            fi
            if [ "${MODEL_UID}" == "" ]; then
                echo "Need to set MODEL_UID!"
                exit 1
            fi
            if [ "${MODEL_FAMILY}" == "" ]; then
                echo "Need to set MODEL_FAMILY!"
                exit 1
            fi
    
            xinference-local --host 0.0.0.0 --port 8080 &
            PID=$!
            while [ true ];
            do
                curl http://127.0.0.1:8080/docs
                if [ $? -eq 0 ]; then
                    break
                else
                    echo "waiting xinference-local server to become ready..."
                    sleep 1
                fi
            done
    
            set -e
            xinference launch --model_path ${MODEL_PATH} --model-engine ${MODEL_ENGINE} -u ${MODEL_UID} -n ${MODEL_FAMILY} -e http://127.0.0.1:8080 $@
            xinference list -e http://127.0.0.1:8080
            echo "model load succeeded, waiting server process: ${PID}..."
            wait ${PID}
        # 添加此行以支持脚本中的 $@ 参数:
        # 参考:https://unix.stackexchange.com/questions/144514/add-arguments-to-bash-c
        - bash
        resources:
          limits:
            cpu: 2
            memory: 6Gi
          requests:
            cpu: 2
            memory: 6Gi
        startupProbe:
          httpGet:
            path: /docs
            port: 8080
            scheme: HTTP
          failureThreshold: 60 
          periodSeconds: 10
          timeoutSeconds: 10
      supportedModelFormats:
        - name: transformers # 运行时支持的模型格式
          version: "1"
    
    • 提示:请务必将 image 字段替换为您实际准备的运行时镜像路径。您也可以修改 annotations.cpaas.io/display-name 字段,自定义 AI 平台 UI 中运行时的显示名称。
  1. 应用 YAML 文件创建资源

    在拥有集群管理员权限的终端执行以下命令,应用 YAML 文件创建推理运行时资源:

    kubectl apply -f your-xinference-runtime.yaml
    TIP
    • 重要提示:请**根据您的实际环境和推理需求,参考上述示例创建/配置运行时。**示例仅供参考,您需调整镜像、资源 limitsrequests 等参数,确保运行时与模型及硬件环境兼容且高效运行。
    • 注意:只有在运行时资源创建成功后,才能在推理服务发布页面使用该自定义运行时!

发布 Xinference 推理服务并选择运行时

Xinference 推理运行时资源创建成功后,您可在 AI 平台发布 LLM 推理服务时选择并配置该运行时。

  1. 配置模型推理框架

    确保在即将发布的模型仓库模型详情页,通过“文件管理”元数据编辑功能选择了合适的框架。此处选择的框架参数值必须与创建推理服务运行时时 supportedModelFormats 字段中包含的值一致。请确保模型框架参数值在推理运行时的 supportedModelFormats 列表中

  2. 进入推理服务发布页面

    登录 AI 平台,进入“推理服务”或“模型部署”模块,点击“发布推理服务”。

  3. 选择 Xinference 运行时

    在推理服务创建向导中,找到“运行时”或“推理框架”选项,从下拉菜单或列表中选择第 1 步创建的 Xinference 运行时(如“Xinference CPU 运行时”或“Xinference GPU 运行时(CUDA)”)。

  4. 设置环境变量: Xinference 运行时需要特定环境变量才能正常工作。在推理服务配置页面,找到“环境变量”或“更多设置”部分,添加以下环境变量:

    • 环境变量参数说明

      参数名称说明
      MODEL_FAMILY必填。指定您部署的 LLM 模型家族类型。Xinference 通过该参数识别并加载对应的推理逻辑。例如,部署 Llama 3 模型时设置为 llama;部署 ChatGLM 模型时设置为 chatglm。请根据模型实际家族设置。
    • 示例

      • 变量名MODEL_FAMILY
      • 变量值llama(如果使用 Llama 系列模型,详见文档。也可运行 xinference registrations -t LLM 列出所有支持的模型家族。)

Specific Runtime Examples

了解标准流程后,请参考以下示例,了解其他运行时的具体配置。

MLServer

MLServer 运行时灵活,可用于 NVIDIA GPU 和 CPU。

kind: ClusterServingRuntime
apiVersion: serving.kserve.io/v1alpha1
metadata:
  annotations:
    cpaas.io/display-name: mlserver-cuda11.6-x86-arm
  creationTimestamp: 2026-01-05T07:02:33Z
  generation: 1
  labels:
    cpaas.io/accelerator-type: nvidia
    cpaas.io/cuda-version: "11.6"
    cpaas.io/runtime-class: mlserver
  name: aml-mlserver-cuda-11.6
spec:
  containers:
    - command:
        - /bin/bash
        - -lc
        - |
          if [ "$MODEL_TYPE" = "text-to-image" ]; then
            MODEL_IMPL="mlserver_diffusers.StableDiffusionRuntime"
          else
            MODEL_IMPL="mlserver_huggingface.HuggingFaceRuntime"
          fi            

          MODEL_DIR="${MLSERVER_MODEL_URI}/${MLSERVER_MODEL_NAME}"
          # a. 使用 git lfs 存储初始化器,模型位于 /mnt/models/<model_name>
          # b. 使用 hf 存储初始化器,模型位于 /mnt/models
          if [ ! -d "${MODEL_DIR}" ]; then
              MODEL_DIR="${MLSERVER_MODEL_URI}"
              echo "[WARNING] Model directory ${MODEL_DIR}/${MLSERVER_MODEL_NAME} not found, using ${MODEL_DIR} instead"
          fi

          export MLSERVER_MODEL_IMPLEMENTATION=${MODEL_IMPL}
          export MLSERVER_MODEL_EXTRA="{\"task\":\"${MODEL_TYPE}\",\"pretrained_model\":\"${MODEL_DIR}\"}"            

          mlserver start $MLSERVER_MODEL_URI $@
        - bash
      env:
        - name: MLSERVER_MODEL_URI
          value: /mnt/models
        - name: MLSERVER_MODEL_NAME
          value: '{{ index .Annotations "aml-model-repo" }}'
        - name: MODEL_TYPE
          value: '{{ index .Annotations "aml-pipeline-tag" }}'
      image: alaudadockerhub/seldon-mlserver:1.6.0-cu116-v1.3.1
      name: kserve-container
      resources:
        limits:
          cpu: 2
          memory: 6Gi
        requests:
          cpu: 2
          memory: 6Gi
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop:
            - ALL
        privileged: false
        runAsNonRoot: true
        runAsUser: 1000
      startupProbe:
        failureThreshold: 60
        httpGet:
          path: /v2/models/{{ index .Annotations "aml-model-repo" }}/ready
          port: 8080
          scheme: HTTP
        periodSeconds: 10
        timeoutSeconds: 10
  labels:
    modelClass: mlserver_sklearn.SKLearnModel
  supportedModelFormats:
    - name: mlflow
      version: "1"
    - name: transformers
      version: "1"

MindIE (Ascend NPU 310P)

MindIE 专为华为 Ascend 硬件设计,其配置在资源管理和元数据方面有显著差异。

1.ClusterServingRuntime

# Ascend NPU 运行时示例 YAML
kind: ClusterServingRuntime
apiVersion: serving.kserve.io/v1alpha1
metadata:
  annotations:
    cpaas.io/display-name: mindie-2.2RC1
  labels:
    cpaas.io/accelerator-type: npu
    cpaas.io/cann-version: 8.3.0
    cpaas.io/runtime-class: mindie
  name: mindie-2.2rc1-310p
spec:
  containers:
    - command:
        - bash
        - -c
        - |
          REAL_SCRIPT=$(echo "$RAW_SCRIPT" | sed 's/__LT__/\x3c/g')
          echo "$REAL_SCRIPT" > /tmp/startup.sh
          chmod +x /tmp/startup.sh

          CONFIG_FILE="${MODEL_PATH}/config.json"
          echo "Checking for file: ${CONFIG_FILE}"

          ls -ld "${MODEL_PATH}"
          chmod -R 755 "${MODEL_PATH}"
          echo "Fixing MODEL_PATH permission..."
          ls -ld "${MODEL_PATH}"

          /tmp/startup.sh --model-name "${MODEL_NAME}" --model-path "${MODEL_PATH}" --ip "${MY_POD_IP}"
      env:
        - name: RAW_SCRIPT
          value: |
            #!/bin/bash
            #
            #  Copyright 2024 Huawei Technologies Co., Ltd
            #
            #  Licensed under the Apache License, Version 2.0 (the "License");
            #  you may not use this file except in compliance with the License.
            #  You may obtain a copy of the License at
            #
            #  http://www.apache.org/licenses/LICENSE-2.0
            #
            #  Unless required by applicable law or agreed to in writing, software
            #  distributed under the License is distributed on an "AS IS" BASIS,
            #  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
            #  See the License for the specific language governing permissions and
            #  limitations under the License.
            #  ============================================================================
            #

            ##
            # 脚本说明
            ##
            ### 名称:
            ### run_mindie.sh - 用于启动 MindIE 服务,指定模型
            ###
            ### 用法:
            ###   bash run_mindie.sh --model-name xxx --model-path /path/to/model
            ###
            ### 必填参数:
            ###   --model-name             :指定模型名称,用于识别 MindIE 服务。
            ###   --model-path             :指定模型路径,包含 yaml/conf.json/tokenizer/vocab 等必要文件。
            ### 可选参数:
            ###   --help                   :显示帮助信息。
            ###   --ip                     :绑定 MindIE 服务业务面 RESTful 接口的 IP,默认值:127.0.0.1。
            ###   --port                   :绑定 MindIE 服务业务面 RESTful 接口的端口,默认值:1025。
            ###   --management-ip          :绑定 MindIE 服务管理面 RESTful 接口的 IP,默认值:127.0.0.2。
            ###   --management-port        :绑定 MindIE 服务管理面 RESTful 接口的端口,默认值:1026。
            ###   --metrics-port           :性能指标监控接口端口,默认值:1027。
            ###   --max-seq-len            :最大序列长度,默认值:2560。
            ###   --max-iter-times         :模型全局最大输出长度,默认值:512。
            ###   --max-input-token-len    :Token id 最大长度,默认值:2048。
            ###   --max-prefill-tokens     :每次预填充时当前批次输入 token 总数,默认值:8192。
            ###   --truncation             :是否执行参数合理性检查截断,默认值:false。
            ###   --template-type          :推理类型,默认值:"Standard"。
            ###   --max-preempt-count      :每批最大可抢占请求数上限,默认值:0。
            ###   --support-select-batch   :批次选择策略,默认值:false。
            ###   --npu-mem-size           :NPU 中 KV Cache 大小上限申请,默认值:8。
            ###   --max-prefill-batch-size :最大预填充批次大小,默认值:50。
            ###   --world-size             :启用多卡推理。
            ###                             1. 未设置时,默认读取 YAML 文件中的并行配置,设置 worldsize = dp*mp*pp。
            ###                             2. 设置时,修改 YAML 并行配置为 dp:1 mp:worldSize pp:1。
            ###   --ms-sched-host          :MS Scheduler IP,默认值:127.0.0.1。
            ###   --ms-sched-port          :MS Scheduler 端口,默认值:8119。
            ### 更多配置说明请参考 MindIE 主页:https://www.hiascend.com/document/detail/zh/mindie/10RC3/mindiellm/llmdev/mindie_llm0004.html
            help() {
              awk -F'### ' '/^###/ { print $2 }' "$0"
            }

            if [[ $# == 0 ]] || [[ "$1" == "--help" ]]; then
              help
              exit 1
            fi

            ##
            # 获取设备信息
            ##
            total_count=$(npu-smi info -l | grep "Total Count" | awk -F ':' '{print $2}' | xargs)

            if [[ -z "$total_count" ]]; then
                echo "Error: Unable to retrieve device info. Please check if npu-smi is available for current user (id 1001), or if you are specifying an occupied device."
                exit 1
            fi

            echo "$total_count device(s) detected!"

            ##
            # 设置工具包环境变量
            ##
            echo "Setting toolkit envs..."
            if [[ -f "/usr/local/Ascend/ascend-toolkit/set_env.sh" ]];then
                            source /usr/local/Ascend/ascend-toolkit/set_env.sh
                    else
                            echo "ascend-toolkit package is incomplete please check it."
                            exit 1
                    fi
            echo "Toolkit envs set succeeded!"

            ##
            # 设置 MindIE 环境变量
            ##
            echo "Setting MindIE envs..."
            if [[ -f "/usr/local/Ascend/mindie/set_env.sh" ]];then
                            source /usr/local/Ascend/mindie/set_env.sh
                    else
                            echo "mindie package is incomplete please check it."
                            exit 1
                    fi
            echo "MindIE envs set succeeded!"

            ##
            # 默认 MS 环境变量
            ##

            # 设置 PYTHONPATH
            MF_SCRIPTS_ROOT=$(realpath "$(dirname "$0")")
            export PYTHONPATH=$MF_SCRIPTS_ROOT/../:$PYTHONPATH

            ##
            # 接收参数并修改 config.json
            ##
            export MIES_INSTALL_PATH=/usr/local/Ascend/mindie/latest/mindie-service
            CONFIG_FILE=${MIES_INSTALL_PATH}/conf/config.json
            echo "MindIE Service config path:$CONFIG_FILE"
            # 默认配置
            BACKEND_TYPE="atb"
            MAX_SEQ_LEN=2560
            MAX_PREFILL_TOKENS=8192
            MAX_ITER_TIMES=512
            MAX_INPUT_TOKEN_LEN=2048
            TRUNCATION=false
            HTTPS_ENABLED=false
            MULTI_NODES_INFER_ENABLED=false
            NPU_MEM_SIZE=8
            MAX_PREFILL_BATCH_SIZE=50
            TEMPLATE_TYPE="Standard"
            MAX_PREEMPT_COUNT=0
            SUPPORT_SELECT_BATCH=false
            IP_ADDRESS="127.0.0.1"
            PORT=8080
            MANAGEMENT_IP_ADDRESS="127.0.0.2"
            MANAGEMENT_PORT=1026
            METRICS_PORT=1027

            # 修改配置
            while [[ "$#" -gt 0 ]]; do
                case $1 in
                    --model-path) MODEL_WEIGHT_PATH="$2"; shift ;;
                    --model-name) MODEL_NAME="$2"; shift ;;
                    --max-seq-len) MAX_SEQ_LEN="$2"; shift ;;
                    --max-iter-times) MAX_ITER_TIMES="$2"; shift ;;
                    --max-input-token-len) MAX_INPUT_TOKEN_LEN="$2"; shift ;;
                    --max-prefill-tokens) MAX_PREFILL_TOKENS="$2"; shift ;;
                    --truncation) TRUNCATION="$2"; shift ;;
                    --world-size) WORLD_SIZE="$2"; shift ;;
                    --template-type) TEMPLATE_TYPE="$2"; shift ;;
                    --max-preempt-count) MAX_PREEMPT_COUNT="$2"; shift ;;
                    --support-select-batch) SUPPORT_SELECT_BATCH="$2"; shift ;;
                    --npu-mem-size) NPU_MEM_SIZE="$2"; shift ;;
                    --max-prefill-batch-size) MAX_PREFILL_BATCH_SIZE="$2"; shift ;;
                    --ip) IP_ADDRESS="$2"; shift ;;
                    --port) PORT="$2"; shift ;;
                    --management-ip) MANAGEMENT_IP_ADDRESS="$2"; shift ;;
                    --management-port) MANAGEMENT_PORT="$2"; shift ;;
                    --metrics-port) METRICS_PORT="$2"; shift ;;
                    --ms-sched-host) ENV_MS_SCHED_HOST="$2"; shift ;;
                    --ms-sched-port) ENV_MS_SCHED_PORT="$2"; shift ;;
                    *)
                        echo "Unknown parameter: $1"
                        echo "Please check your inputs."
                        exit 1
                        ;;
                esac
                shift
            done

            if [ -z "$MODEL_WEIGHT_PATH" ] || [ -z "$MODEL_NAME" ]; then
                echo "Error: Both --model-path and --model-name are required."
                exit 1
            fi
            MODEL_NAME=${MODEL_NAME:-$(basename "$MODEL_WEIGHT_PATH")}
            echo "MODEL_NAME is set to: $MODEL_NAME"

            WORLD_SIZE=$total_count
            NPU_DEVICE_IDS=$(seq -s, 0 $(($WORLD_SIZE - 1)))

            # 验证配置
            if [[ "$BACKEND_TYPE" != "atb" ]]; then
                echo "Error: BACKEND must be 'atb'. Current value: $BACKEND_TYPE"
                exit 1
            fi

            if [[ ! "$IP_ADDRESS" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] ||
              [[ ! "$MANAGEMENT_IP_ADDRESS" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
                echo "Error: IP_ADDRESS and MANAGEMENT_IP_ADDRESS must be valid IP addresses. Current values: IP_ADDRESS=$IP_ADDRESS, MANAGEMENT_IP_ADDRESS=$MANAGEMENT_IP_ADDRESS"
                exit 1
            fi

            if [[ ! "$PORT" =~ ^[0-9]+$ ]] || (( PORT __LT__ 1025 || PORT > 65535 )) ||
              [[ ! "$MANAGEMENT_PORT" =~ ^[0-9]+$ ]] || (( MANAGEMENT_PORT __LT__ 1025 || MANAGEMENT_PORT > 65535 )); then
                echo "Error: PORT and MANAGEMENT_PORT must be integers between 1025 and 65535. Current values: PORT=$PORT, MANAGEMENT_PORT=$MANAGEMENT_PORT"
                exit 1
            fi

            if [ "$MAX_PREFILL_TOKENS" -lt "$MAX_SEQ_LEN" ]; then
                MAX_PREFILL_TOKENS=$MAX_SEQ_LEN
                echo "MAX_PREFILL_TOKENS was less than MAX_SEQ_LEN. Setting MAX_PREFILL_TOKENS to $MAX_SEQ_LEN"
            fi

            MODEL_CONFIG_FILE="${MODEL_WEIGHT_PATH}/config.json"
            if [ ! -f "$MODEL_CONFIG_FILE" ]; then
                echo "Error: config.json file not found in $MODEL_WEIGHT_PATH."
                exit 1
            fi
            chmod 600 "$MODEL_CONFIG_FILE"
            # 更新配置文件
            chmod u+w ${MIES_INSTALL_PATH}/conf/
            sed -i "s/\"backendType\"\s*:\s*\"[^\"]*\"/\"backendType\": \"$BACKEND_TYPE\"/" $CONFIG_FILE
            sed -i "s/\"modelName\"\s*:\s*\"[^\"]*\"/\"modelName\": \"$MODEL_NAME\"/" $CONFIG_FILE
            sed -i "s|\"modelWeightPath\"\s*:\s*\"[^\"]*\"|\"modelWeightPath\": \"$MODEL_WEIGHT_PATH\"|" $CONFIG_FILE
            sed -i "s/\"maxSeqLen\"\s*:\s*[0-9]*/\"maxSeqLen\": $MAX_SEQ_LEN/" "$CONFIG_FILE"
            sed -i "s/\"maxPrefillTokens\"\s*:\s*[0-9]*/\"maxPrefillTokens\": $MAX_PREFILL_TOKENS/" "$CONFIG_FILE"
            sed -i "s/\"maxIterTimes\"\s*:\s*[0-9]*/\"maxIterTimes\": $MAX_ITER_TIMES/" "$CONFIG_FILE"
            sed -i "s/\"maxInputTokenLen\"\s*:\s*[0-9]*/\"maxInputTokenLen\": $MAX_INPUT_TOKEN_LEN/" "$CONFIG_FILE"
            sed -i "s/\"truncation\"\s*:\s*[a-z]*/\"truncation\": $TRUNCATION/" "$CONFIG_FILE"
            sed -i "s|\(\"npuDeviceIds\"\s*:\s*\[\[\)[^]]*\(]]\)|\1$NPU_DEVICE_IDS\2|" "$CONFIG_FILE"
            sed -i "s/\"worldSize\"\s*:\s*[0-9]*/\"worldSize\": $WORLD_SIZE/" "$CONFIG_FILE"
            sed -i "s/\"httpsEnabled\"\s*:\s*[a-z]*/\"httpsEnabled\": $HTTPS_ENABLED/" "$CONFIG_FILE"
            sed -i "s/\"templateType\"\s*:\s*\"[^\"]*\"/\"templateType\": \"$TEMPLATE_TYPE\"/" $CONFIG_FILE
            sed -i "s/\"maxPreemptCount\"\s*:\s*[0-9]*/\"maxPreemptCount\": $MAX_PREEMPT_COUNT/" "$CONFIG_FILE"
            sed -i "s/\"supportSelectBatch\"\s*:\s*[a-z]*/\"supportSelectBatch\": $SUPPORT_SELECT_BATCH/" "$CONFIG_FILE"
            sed -i "s/\"multiNodesInferEnabled\"\s*:\s*[a-z]*/\"multiNodesInferEnabled\": $MULTI_NODES_INFER_ENABLED/" "$CONFIG_FILE"
            sed -i "s/\"maxPrefillBatchSize\"\s*:\s*[0-9]*/\"maxPrefillBatchSize\": $MAX_PREFILL_BATCH_SIZE/" "$CONFIG_FILE"
            sed -i "s/\"ipAddress\"\s*:\s*\"[^\"]*\"/\"ipAddress\": \"$IP_ADDRESS\"/" "$CONFIG_FILE"
            sed -i "s/\"port\"\s*:\s*[0-9]*/\"port\": $PORT/" "$CONFIG_FILE"
            sed -i "s/\"managementIpAddress\"\s*:\s*\"[^\"]*\"/\"managementIpAddress\": \"$MANAGEMENT_IP_ADDRESS\"/" "$CONFIG_FILE"
            sed -i "s/\"managementPort\"\s*:\s*[0-9]*/\"managementPort\": $MANAGEMENT_PORT/" "$CONFIG_FILE"
            sed -i "s/\"metricsPort\"\s*:\s*[0-9]*/\"metricsPort\": $METRICS_PORT/" $CONFIG_FILE
            sed -i "s/\"npuMemSize\"\s*:\s*-*[0-9]*/\"npuMemSize\": $NPU_MEM_SIZE/" "$CONFIG_FILE"

            ##
            # 启动服务
            ##
            echo "当前配置如下:"
            cat $CONFIG_FILE
            npu-smi info -m > ~/device_info

            ${MIES_INSTALL_PATH}/bin/mindieservice_daemon
        - name: MODEL_NAME
          value: '{{ index .Annotations "aml-model-repo" }}'
        - name: MODEL_PATH
          value: /mnt/models/{{ index .Annotations "aml-model-repo" }}
        - name: MY_POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
      image: swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:2.2.RC1-300I-Duo-py311-openeuler24.03-lts
      name: kserve-container
      resources:
        limits:
          cpu: 2
          memory: 6Gi
        requests:
          cpu: 2
          memory: 6Gi
      volumeMounts:
        - mountPath: /dev/shm
          name: dshm
      startupProbe:
        failureThreshold: 60
        httpGet:
          path: /v1/models
          port: 8080
          scheme: HTTP
        periodSeconds: 10
        timeoutSeconds: 180
  supportedModelFormats:
    - name: transformers
      version: "1"
  volumes:
    - emptyDir:
        medium: Memory
        sizeLimit: 8Gi
      name: dshm
      

2. 推理服务必须添加的注解

与其他运行时不同,MindIE 在最终发布推理服务时,必须InferenceService 元数据中添加注解,确保平台调度器正确绑定 NPU 硬件到服务。

配置键作用
storage.kserve.io/readonly"false"启用模型存储卷的写权限。

3. 用户权限(Root 访问)

由于 Ascend 驱动和硬件抽象层要求,MindIE 镜像必须以 root 用户身份运行。请确保您的 ClusterServingRuntimeInferenceService 安全上下文配置正确:

注意:上述 MindIE ClusterServingRuntime YAML 示例未指定 securityContext,意味着容器使用镜像默认设置(通常为 root)。与 MLServer 显式设置 runAsNonRoot: truerunAsUser: 1000 不同,MindIE 需要 root 权限访问 NPU 硬件。

Comparison of Runtime Configurations

开始前,请参考下表,了解不同运行时的具体要求:

运行时目标硬件支持框架特殊要求
XinferenceCPU / NVIDIA GPUtransformers, pytorch必须设置 MODEL_FAMILY 环境变量
MLServerCPU / NVIDIA GPUsklearn, xgboost, mlflow标准配置
MindIE华为 Ascend NPUmindspore, transformers必须在 InferenceService 添加 NPU 必需注解