MiniMax-M3¶
1 简介¶
MiniMax-M3 是一个支持文本、图像和视频输入的多模态大型语言模型。在 Ascend 上,它支持 A2/A3 上的 BF16 和 W8A8、Atlas 800 A3(BF16)和 950DT 产品(MXFP8)上的 Prefill-Decode 分离、思考模式、推理解析、工具调用解析以及多模态输入。
本文档涵盖支持的特性、环境和模型准备、单节点部署、多节点部署、PD 分离、思考与解析器配置、功能验证、精度评估和故障排查。
本文档基于 vLLM-Ascend v0.27.1 版本编写。该模型在此版本中受支持。
2 支持特性¶
模型支持矩阵请参考 支持特性列表。
功能配置说明请参考 特性指南。
3 前提条件¶
3.1 模型权重¶
MiniMax-M3(BF16):需要 16 颗 64 GB NPU 芯片。Prefill-Decode 分离使用 2 台 Atlas 800 A3(64GB × 16)。下载模型权重。MiniMax-M3-w8a8(W8A8):至少需要 8 颗 64 GB NPU 芯片。推荐用于 Atlas 800 A3(64GB × 16)和 Atlas 800 A2(64GB × 8)。下载模型权重。MiniMax-M3-MXFP8(MXFP8):用于 950DT 产品(96GB × 8)的 PD 分离(2 节点,1P1D)。下载模型权重。MiniMax-M3-EAGLE3-GQA:EAGLE3 草稿模型,用作投机解码(eagle3 方法)的草稿模型以加速生成。与原始MiniMax-M3-EAGLE3相比,该草稿模型采用分组查询注意力(GQA)以提高推理效率并兼容目标模型。下载模型权重。
建议将模型权重放置在共享缓存目录中。
3.2 验证多节点通信(可选)¶
对于多节点部署,请按照 验证多节点通信环境 验证通信环境。
4 安装¶
4.1 Docker 镜像安装¶
您可以使用官方一体化 Docker 镜像。有关可用的镜像标签和已发布版本,请参考 使用 Docker。
步骤 1: 下载最新的 Docker 镜像
步骤 2: 启动 Docker 容器
根据您的硬件平台选择对应的 docker run 命令:
# Set the vLLM Ascend image name.
export IMAGE=quay.io/ascend/vllm-ascend:{tag}
export NAME=minimax-m3-dev
# Start the container with the variables defined above.
docker run --rm \
--name $NAME \
--net=host \
--shm-size=100g \
--device /dev/davinci0 \
--device /dev/davinci1 \
--device /dev/davinci2 \
--device /dev/davinci3 \
--device /dev/davinci4 \
--device /dev/davinci5 \
--device /dev/davinci6 \
--device /dev/davinci7 \
--device /dev/davinci8 \
--device /dev/davinci9 \
--device /dev/davinci10 \
--device /dev/davinci11 \
--device /dev/davinci12 \
--device /dev/davinci13 \
--device /dev/davinci14 \
--device /dev/davinci15 \
--device /dev/davinci_manager \
--device /dev/devmm_svm \
--device /dev/hisi_hdc \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/Ascend/driver/tools/hccn_tool:/usr/local/Ascend/driver/tools/hccn_tool \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/ \
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /root/.cache:/root/.cache \
-it $IMAGE bash
# Set the vLLM Ascend image name.
export IMAGE=quay.io/ascend/vllm-ascend:{tag}
export NAME=minimax-m3-dev
# 950DT products have 8 NPUs and use Device UB.
docker run --rm \
--name $NAME \
--net=host \
--privileged=true \
--shm-size=60g \
--device /dev/davinci_manager \
--device /dev/hisi_hdc \
--device /dev/ummu \
--device /dev/uburma \
--device /dev/davinci0 \
--device /dev/davinci1 \
--device /dev/davinci2 \
--device /dev/davinci3 \
--device /dev/davinci4 \
--device /dev/davinci5 \
--device /dev/davinci6 \
--device /dev/davinci7 \
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
-v /usr/local/Ascend/firmware:/usr/local/Ascend/firmware \
-v /usr/local/dcmi:/usr/local/dcmi \
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \
-v /etc/ascend_install.info:/etc/ascend_install.info \
-v /etc/hixlep:/etc/hixlep \
-v /etc/hccn.conf:/etc/hccn.conf \
-v /var/log/npu/:/usr/slog \
-v /root/.cache:/root/.cache \
-it $IMAGE bash
请根据您的环境调整数据卷挂载(例如模型权重和数据集)。在 950DT 产品上,不要添加主机上不存在的 Atlas A3 挂载,例如 /dev/devmm_svm。
预期结果:容器以 Up 状态列出。您还可以在容器内验证 vllm-ascend 版本:
预期结果:显示版本信息,与所拉取镜像的版本一致。
5 在线服务部署¶
使用以下命令启动在线服务:
有关部署示例中使用的标准 vllm serve 参数说明,请参考 vLLM 服务参数文档。有关通过 --additional-config 传入的 Ascend 专用选项,请参考 附加配置。有关 Ascend 专用的环境变量,请参考 环境变量。
5.1 单节点部署¶
单节点部署在同一节点内同时完成 Prefill 和 Decode。MiniMax-M3(BF16)模型可部署在 1 台 Atlas 800 A3(64GB × 16)上,但对于 A3 系列上的 BF16,建议使用双节点部署;不建议单节点部署。MiniMax-M3-w8a8(W8A8)量化模型建议在 1 台 Atlas 800 A3(64GB × 16)或 1 台 Atlas 800 A2(64GB × 8)上进行单节点部署。MiniMax-M3-MXFP8(MXFP8)量化模型可部署在 1 台 950DT 产品(96GB × 8)上。
Note
--quantization 参数仅对量化权重需要,并且必须与权重变体匹配:
- BF16 权重(
MiniMax-M3):不要添加--quantization;模型将以浮点格式加载。 - W8A8 权重(
MiniMax-M3-w8a8,ModelSlim 格式):使用--quantization ascend。vLLM Ascend 可以从检查点文件自动检测该配置,但为清晰起见,建议显式指定。 - MXFP8 权重(
MiniMax-M3-MXFP8):使用--quantization mxfp8。
添加错误的 --quantization 值(或将其添加到 BF16 权重)会导致检查点被错误解释并加载失败。
export HCCL_OP_EXPANSION_MODE="AIV"
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
vllm serve ${WEIGHT_PATH} \
--host 0.0.0.0 \
--port 11223 \
--served-model-name minimax-m3 \
--trust-remote-code \
--max-model-len 43008 \
--tensor-parallel-size 16 \
--enable-expert-parallel \
--max-num-seqs 16 \
--distributed_executor_backend "mp" \
--gpu-memory-utilization 0.92 \
--reasoning-parser minimax_m3 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--enable-chunked-prefill \
--enable-prefix-caching \
--additional-config '{
"enable_cpu_binding": true,
"enable_flashcomm1": true,
"ascend_compilation_config": {
"fuse_norm_quant": false
},
"multistream_overlap_shared_expert": true,
"weight_nz_mode": 2
}' > ${LOG_PATH} 2>&1 &
export HCCL_OP_EXPANSION_MODE="AIV"
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
vllm serve ${WEIGHT_PATH} \
--host 0.0.0.0 \
--port 11223 \
--served-model-name minimax-m3 \
--trust-remote-code \
--quantization ascend \
--max-model-len 131072 \
--tensor-parallel-size 4 \
--data-parallel-size 4 \
--api-server-count 1 \
--max-num-batched-tokens 32768 \
--long-prefill-token-threshold 4096 \
--enable-expert-parallel \
--max-num-seqs 32 \
--distributed_executor_backend "mp" \
--gpu-memory-utilization 0.92 \
--reasoning-parser minimax_m3 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--enable-chunked-prefill \
--enable-prefix-caching \
--speculative-config '{"model":"${EAGLE3_WEIGHT_PATH}", "method":"eagle3", "num_speculative_tokens":3}' \
--additional-config '{
"enable_cpu_binding": true,
"enable_flashcomm1": true,
"ascend_compilation_config": {
"fuse_norm_quant": false
},
"multistream_overlap_shared_expert": true,
"enable_shared_expert_dp": true,
"weight_nz_mode": 2
}' > ${LOG_PATH} 2>&1 &
nic_name="xxxx" # NIC corresponding to local_ip
export GLOO_SOCKET_IFNAME=$nic_name
export HCCL_SOCKET_IFNAME=$nic_name
export HCCL_OP_EXPANSION_MODE="AIV"
export LD_LIBRARY_PATH=/usr/local/Ascend/cann-9.1.0/opp/vendors/experimental_950_transformer/op_api/lib/:${LD_LIBRARY_PATH}
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
vllm serve ${WEIGHT_PATH} \
--host 0.0.0.0 \
--port 11223 \
--served-model-name minimax-m3 \
--trust-remote-code \
--distributed-executor-backend mp \
--tensor-parallel-size 4 \
--data-parallel-size 2 \
--enable-expert-parallel \
--dtype bfloat16 \
--quantization mxfp8 \
--max-model-len 140000 \
--max-num-batched-tokens 16384 \
--kv-cache-dtype fp8 \
--max-num-seqs 500 \
--enable-chunked-prefill \
--enable-prefix-caching \
--async-scheduling \
--reasoning-parser minimax_m3 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--gpu-memory-utilization 0.92 \
--additional-config '{"enable_cpu_binding":true,"ascend_compilation_config":{"fuse_qknorm_rope":false,"fuse_norm_quant":false},"multistream_overlap_shared_expert":true,"enable_shared_expert_dp":true,"enable_flashcomm1":true}' \
--speculative-config '{"method":"eagle3","model":"${EAGLE3_WEIGHT_PATH}","num_speculative_tokens":3,"kv_cache_dtype": "bfloat16"}' \
--safetensors-load-strategy prefetch > ${LOG_PATH} 2>&1 &
注意:在上述脚本中,max-num-seqs 表示调度器在单次迭代中可处理的最大序列数。请根据实际业务动态调整 max-num-seqs 参数。
对于纯文本部署,可以省略 --limit-mm-per-prompt。对于多模态部署,请根据实际请求形态配置该参数。例如,对于双图像请求,使用 --limit-mm-per-prompt '{"image":2,"video":0}';对于单视频请求,使用 --limit-mm-per-prompt '{"image":0,"video":1}'。
5.2 多节点部署¶
在 Ascend A2 服务器上部署浮点模型至少需要两个节点。不建议在 A3 服务器上执行未进行 Prefill–Decode 分离的多节点部署。请根据实际环境更新 WEIGHT_PATH、EAGLE3_WEIGHT_PATH、LOG_PATH、local_ip、node0_ip 和 IFNAME。
在节点 0 上运行以下命令:
local_ip="${NODE0_IP}"
node0_ip="${NODE0_IP}"
export HCCL_IF_IP=$local_ip
export IFNAME="${NETWORK_INTERFACE}"
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_SOCKET_IFNAME="$IFNAME"
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
export GLOO_SOCKET_IFNAME="$IFNAME"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
vllm serve ${WEIGHT_PATH} \
--host 0.0.0.0 \
--port 11223 \
--served-model-name minimax-m3 \
--trust-remote-code \
--max-model-len 65920 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--max-num-seqs 32 \
--data-parallel-size 4 \
--data-parallel-size-local 2 \
--data-parallel-start-rank 0 \
--data-parallel-address $node0_ip \
--distributed_executor_backend "mp" \
--gpu-memory-utilization 0.92 \
--reasoning-parser minimax_m3 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--speculative-config '{"model":"${EAGLE3_WEIGHT_PATH}","method":"eagle3","num_speculative_tokens":3}' \
--enable-chunked-prefill \
--enable-prefix-caching \
--additional-config '{"enable_cpu_binding":true, "ascend_compilation_config":{"fuse_norm_quant":false}, "enable_shared_expert_dp":true,"multistream_overlap_shared_expert": true, "weight_nz_mode": 2,"enable_flashcomm1":true}' > ${LOG_PATH} 2>&1 &
```
在节点 1 上运行以下命令:
```bash
local_ip="${NODE1_IP}"
node0_ip="${NODE0_IP}"
export HCCL_IF_IP=$local_ip
export IFNAME="${NETWORK_INTERFACE}"
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_SOCKET_IFNAME="$IFNAME"
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
export GLOO_SOCKET_IFNAME="$IFNAME"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
vllm serve ${WEIGHT_PATH} \
--host 0.0.0.0 \
--port 11223 \
--served-model-name minimax-m3 \
--trust-remote-code \
--headless \
--max-model-len 65920 \
--tensor-parallel-size 8 \
--enable-expert-parallel \
--max-num-seqs 32 \
--data-parallel-size 4 \
--data-parallel-size-local 2 \
--data-parallel-start-rank 2 \
--data-parallel-address $node0_ip \
--distributed_executor_backend "mp" \
--gpu-memory-utilization 0.92 \
--reasoning-parser minimax_m3 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--speculative-config '{"model":"${EAGLE3_WEIGHT_PATH}","method":"eagle3","num_speculative_tokens":3}' \
--enable-chunked-prefill \
--enable-prefix-caching \
--additional-config '{"enable_cpu_binding":true, "ascend_compilation_config":{"fuse_norm_quant":false}, "enable_shared_expert_dp":true,"multistream_overlap_shared_expert": true, "weight_nz_mode": 2,"enable_flashcomm1":true}' > ${LOG_PATH} 2>&1 &
```
=== "A3 series(W8A8)"
在节点 0 上运行以下命令:
```bash
local_ip="${NODE0_IP}"
node0_ip="${NODE0_IP}"
export HCCL_IF_IP=$local_ip
export IFNAME="${NETWORK_INTERFACE}"
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_SOCKET_IFNAME="$IFNAME"
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
export GLOO_SOCKET_IFNAME="$IFNAME"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
vllm serve ${WEIGHT_PATH} \
--host 0.0.0.0 \
--port 11223 \
--served-model-name minimax-m3 \
--trust-remote-code \
--quantization ascend \
--max-model-len 131072 \
--tensor-parallel-size 4 \
--enable-expert-parallel \
--max-num-seqs 32 \
--data-parallel-size 8 \
--data-parallel-size-local 4 \
--data-parallel-start-rank 0 \
--data-parallel-address $node0_ip \
--distributed_executor_backend "mp" \
--gpu-memory-utilization 0.92 \
--reasoning-parser minimax_m3 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--speculative-config '{"model":"${EAGLE3_WEIGHT_PATH}", "method":"eagle3", "num_speculative_tokens":3}' \
--enable-chunked-prefill \
--enable-prefix-caching \
--additional-config '{"enable_cpu_binding":true, "ascend_compilation_config":{"fuse_norm_quant":false}, "enable_shared_expert_dp":true,"multistream_overlap_shared_expert": true, "weight_nz_mode": 2,"enable_flashcomm1":true}' > ${LOG_PATH} 2>&1 &
```
在节点 1 上运行以下命令:
```bash
local_ip="${NODE1_IP}"
node0_ip="${NODE0_IP}"
export HCCL_IF_IP=$local_ip
export IFNAME="${NETWORK_INTERFACE}"
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_SOCKET_IFNAME="$IFNAME"
export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2:$LD_PRELOAD
export GLOO_SOCKET_IFNAME="$IFNAME"
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
vllm serve ${WEIGHT_PATH} \
--host 0.0.0.0 \
--port 11223 \
--served-model-name minimax-m3 \
--trust-remote-code \
--quantization ascend \
--headless \
--max-model-len 131072 \
--tensor-parallel-size 4 \
--enable-expert-parallel \
--max-num-seqs 32 \
--data-parallel-size 8 \
--data-parallel-size-local 4 \
--data-parallel-start-rank 4 \
--data-parallel-address $node0_ip \
--distributed_executor_backend "mp" \
--gpu-memory-utilization 0.92 \
--reasoning-parser minimax_m3 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--speculative-config '{"model":"${EAGLE3_WEIGHT_PATH}", "method":"eagle3", "num_speculative_tokens":3}' \
--enable-chunked-prefill \
--enable-prefix-caching \
--additional-config '{"enable_cpu_binding":true, "ascend_compilation_config":{"fuse_norm_quant":false}, "enable_shared_expert_dp":true,"multistream_overlap_shared_expert": true, "weight_nz_mode": 2,"enable_flashcomm1":true}' > ${LOG_PATH} 2>&1 &
```
### 5.3 预填充-解码分离 {#5.3-prefill-decode-disaggregation}
下面将展示 MiniMax-M3 在 1P1D 多节点环境下的部署指南,以获得更好的性能。
PD 分离将 Prefill 和 Decode 拆分到不同的服务组。Prefill 节点处理大型 prompt 块,Decode 节点负责 token 生成,代理在两者之间转发请求。使用 Mooncake 进行 KV 缓存传输。有关通用 PD 分离工作流,请参阅 [Mooncake](../features/pd_disaggregation_mooncake_multi_node.md)。
启动方式为:在每个节点上准备 `launch_online_dp.py` 和按角色区分的 `run_dp_template.sh`,然后在每个引擎打印 `Application startup complete` 后启动负载均衡代理。下面的启动器在仓库示例基础上扩展了 `--pp-size`:在 A3 上,Prefill 使用流水线并行(`PP=2`),将 60 个 transformer 层按 `30,30` 划分;而 950DT 产品的 MXFP8 启动在两个角色上均使用 `PP=1` 和 `DP=2`。每个 DP rank 占用 `tp_size * pp_size` 个 NPU。
**常见问题提示:** 对于 PD 分离问题(例如 KV 传输超时或 Mooncake 连接错误),请参阅 [公共常见问题](../../faqs.md)。对于 MiniMax 特有问题,请参阅 [第 10 章常见问题](#10-faq)。
开始之前,请在每个节点上准备脚本 `launch_online_dp.py`:
```python
import argparse
import multiprocessing
import os
import subprocess
import sys
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument(
"--dp-size",
type=int,
required=True,
help="Data parallel size."
)
parser.add_argument(
"--tp-size",
type=int,
default=1,
help="Tensor parallel size."
)
parser.add_argument(
"--pp-size",
type=int,
default=1,
help="Pipeline parallel size."
)
parser.add_argument(
"--dp-size-local",
type=int,
default=-1,
help="Local data parallel size."
)
parser.add_argument(
"--dp-rank-start",
type=int,
default=0,
help="Starting rank for data parallel."
)
parser.add_argument(
"--dp-address",
type=str,
required=True,
help="IP address for data parallel master node."
)
parser.add_argument(
"--dp-rpc-port",
type=str,
default="12321",
help="Port for data parallel master node."
)
parser.add_argument(
"--vllm-start-port",
type=int,
default=8000,
help="Starting port for the engine."
)
return parser.parse_args()
args = parse_args()
dp_size = args.dp_size
tp_size = args.tp_size
pp_size = args.pp_size
dp_size_local = args.dp_size_local
if dp_size_local == -1:
dp_size_local = dp_size
dp_rank_start = args.dp_rank_start
dp_address = args.dp_address
dp_rpc_port = args.dp_rpc_port
vllm_start_port = args.vllm_start_port
gpus_per_dp_rank = tp_size * pp_size
def run_command(visible_devices, dp_rank, vllm_engine_port):
command = [
"bash",
"./run_dp_template.sh",
visible_devices,
str(vllm_engine_port),
str(dp_size),
str(dp_rank),
dp_address,
dp_rpc_port,
str(tp_size),
str(pp_size),
]
subprocess.run(command, check=True)
if __name__ == "__main__":
template_path = "./run_dp_template.sh"
if not os.path.exists(template_path):
print(f"Template file {template_path} does not exist.")
sys.exit(1)
processes = []
for i in range(dp_size_local):
dp_rank = dp_rank_start + i
vllm_engine_port = vllm_start_port + i
visible_devices = ",".join(
str(x) for x in range(i * gpus_per_dp_rank, (i + 1) * gpus_per_dp_rank)
)
process = multiprocessing.Process(
target=run_command,
args=(visible_devices, dp_rank, vllm_engine_port),
)
processes.append(process)
process.start()
for process in processes:
process.join()
launch_online_dp.py 会将可见设备、端口、DP 规模、DP rank、DP 地址、DP RPC 端口、TP 规模和 PP 规模作为 $1 到 $8 传递。
然后在每个节点上准备 run_dp_template.sh 并启动引擎。
Prefill-Decode 分离可部署在 2 台 Atlas 800 A3(64GB × 16)上,用于 MiniMax-M3-w8a8(W8A8),并搭配 MiniMax-M3-EAGLE3-GQA。
显式声明该限制(--limit-mm-per-prompt '{"image":1,"video":0}')可改善调度器侧内存规划和端到端吞吐量。请根据实际请求形态调整(例如,双图像请求使用 {"image":2,"video":0},单视频请求使用 {"image":0,"video":1});对于纯文本部署,可以省略该参数。
- Prefill 节点
unset http_proxy https_proxy ftp_proxy
nic_name="xxxx" # NIC corresponding to local_ip
local_ip="xxxx" # Prefill node IP
model_path="xxxx" # MiniMax-M3 model path
EAGLE3_WEIGHT_PATH="xxxx" # MiniMax-M3-EAGLE3-GQA path
export VLLM_PP_LAYER_PARTITION="30,30"
export HCCL_BUFFSIZE=1024
export HCCL_IF_IP=$local_ip
export HCCL_OP_EXPANSION_MODE="AIV"
export ASCEND_RT_VISIBLE_DEVICES=$1
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
# If Mooncake is installed in a non-standard path, set this before startup.
if [ -n "${MOONCAKE_LIB_DIRS:-}" ]; then
export LD_LIBRARY_PATH="${MOONCAKE_LIB_DIRS}:${LD_LIBRARY_PATH:-}"
fi
vllm serve "$model_path" \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--pipeline-parallel-size $8 \
--enforce-eager \
--distributed-executor-backend mp \
--served-model-name minimax-m3 \
--enable-expert-parallel \
--seed 1024 \
--max-model-len 133000 \
--max-num-seqs 32 \
--max-num-batched-tokens 32768 \
--long-prefill-token-threshold 2048 \
--enable-chunked-prefill \
--enable-prefix-caching \
--trust-remote-code \
--quantization ascend \
--gpu-memory-utilization 0.92 \
--limit-mm-per-prompt '{"image":1,"video":0}' \
--reasoning-parser minimax_m3 \
--additional-config '{"enable_cpu_binding":true,"ascend_compilation_config":{"fuse_norm_quant":false},"multistream_overlap_shared_expert":true,"weight_nz_mode":2,"enable_shared_expert_dp":true,"enable_flashcomm1":true}' \
--speculative-config '{"method":"eagle3","model":"${EAGLE3_WEIGHT_PATH}","num_speculative_tokens":3}' \
--kv-transfer-config \
'{
"kv_connector":"MooncakeConnectorV1",
"kv_role":"kv_producer",
"kv_port":"36000",
"engine_id":"0",
"kv_connector_extra_config":{
"use_ascend_direct":true,
"prefill":{"dp_size":2,"tp_size":4,"pp_size":2,"pp_layer_partition":"30,30"},
"decode":{"dp_size":4,"tp_size":4,"pp_size":1}
}
}'
-
解码节点
unset http_proxy https_proxy ftp_proxy nic_name="xxxx" # NIC corresponding to local_ip local_ip="xxxx" # Decode node IP model_path="xxxx" # MiniMax-M3 model path EAGLE3_WEIGHT_PATH="xxxx" # MiniMax-M3-EAGLE3-GQA path export HCCL_BUFFSIZE=2048 export HCCL_IF_IP=$local_ip export HCCL_OP_EXPANSION_MODE="AIV" export ASCEND_RT_VISIBLE_DEVICES=$1 export HCCL_SOCKET_IFNAME=$nic_name export GLOO_SOCKET_IFNAME=$nic_name export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True # If Mooncake is installed in a non-standard path, set this before startup. if [ -n "${MOONCAKE_LIB_DIRS:-}" ]; then export LD_LIBRARY_PATH="${MOONCAKE_LIB_DIRS}:${LD_LIBRARY_PATH:-}" fi vllm serve "$model_path" \ --host 0.0.0.0 \ --port $2 \ --data-parallel-size $3 \ --data-parallel-rank $4 \ --data-parallel-address $5 \ --data-parallel-rpc-port $6 \ --tensor-parallel-size $7 \ --pipeline-parallel-size $8 \ --enable-expert-parallel \ --seed 1024 \ --served-model-name minimax-m3 \ --reasoning-parser minimax_m3 \ --distributed-executor-backend mp \ --max-model-len 133000 \ --max-num-batched-tokens 32768 \ --trust-remote-code \ --quantization ascend \ --max-num-seqs 64 \ --gpu-memory-utilization 0.92 \ --limit-mm-per-prompt '{"image":1,"video":0}' \ --additional-config '{"enable_cpu_binding":true,"ascend_compilation_config":{"fuse_norm_quant":false},"multistream_overlap_shared_expert":true,"weight_nz_mode":2,"enable_shared_expert_dp":true}' \ --speculative-config '{"method":"eagle3","model":"${EAGLE3_WEIGHT_PATH}","num_speculative_tokens":3}' \ --kv-transfer-config \ '{ "kv_connector":"MooncakeConnectorV1", "kv_role":"kv_consumer", "kv_port":"36100", "engine_id":"1", "kv_connector_extra_config":{ "use_ascend_direct":true, "prefill":{"dp_size":2,"tp_size":4,"pp_size":2,"pp_layer_partition":"30,30"}, "decode":{"dp_size":4,"tp_size":4,"pp_size":1} } }'准备工作完成后,在每个节点上使用以下命令启动服务器:
- 预填充节点
python launch_online_dp.py \ --dp-size 2 --tp-size 4 --pp-size 2 \ --dp-size-local 2 --dp-rank-start 0 \ --dp-address $node_p_ip --dp-rpc-port 6884 \ --vllm-start-port 31050这将在端口
31050和31051上启动两个预填充 API 服务器。等待两个 rank 都打印Application startup complete。- 解码节点
python launch_online_dp.py \ --dp-size 4 --tp-size 4 --pp-size 1 \ --dp-size-local 4 --dp-rank-start 0 \ --dp-address $node_d_ip --dp-rpc-port 5964 \ --vllm-start-port 31060这将在端口
31060到31063上启动四个解码 API 服务器。要设置请求转发,请在能够访问所有预填充和解码 API 端口的节点上运行以下脚本。你可以从仓库的示例中获取代理程序:load_balance_proxy_server_example.py。对于 A3 1P1D,代理会将请求转发到 2 个预填充 rank 和 4 个解码 rank。
unset http_proxy unset https_proxy unset ftp_proxy python load_balance_proxy_server_example.py \ --port 8009 \ --host $node_p_ip \ --prefiller-hosts \ $node_p_ip $node_p_ip \ --prefiller-ports \ 31050 31051 \ --decoder-hosts \ $node_d_ip $node_d_ip $node_d_ip $node_d_ip \ --decoder-ports \ 31060 31061 31062 31063然后服务可通过
<proxy_ip>:8009访问。对于 PD 分离,请在第 7 节中使用此代理端点。
=== "950DT 产品" {#950dt-products}
对于 `MiniMax-M3-MXFP8` 配合 `MiniMax-M3-EAGLE3-GQA`,预填充-解码分离可以部署在 2 个 950DT 产品(96GB × 8)上。在容器中挂载 `/etc/hixlep/`,用于 UBOE / Ascend 直接 KV 传输。
1. 预填充节点
```bash
unset ftp_proxy https_proxy http_proxy all_proxy
unset FTP_PROXY HTTPS_PROXY HTTP_PROXY ALL_PROXY
nic_name="xxxx" # NIC corresponding to local_ip
local_ip="xxxx" # Prefill node IP
model_path="xxxx" # MiniMax-M3-MXFP8 model path
EAGLE3_WEIGHT_PATH="xxxx" # MiniMax-M3-EAGLE3-GQA path
export HCCL_BUFFSIZE=256
export HCCL_IF_IP=$local_ip
export HCCL_OP_EXPANSION_MODE="AIV"
export ASCEND_RT_VISIBLE_DEVICES=$1
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/mooncake:$LD_LIBRARY_PATH
vllm serve "$model_path" \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--pipeline-parallel-size $8 \
--served-model-name minimax-m3 \
--trust-remote-code \
--dtype bfloat16 \
--max-num-seqs 128 \
--max-num-batched-tokens 32768 \
--max-model-len 133000 \
--enable-expert-parallel \
--quantization mxfp8 \
--gpu-memory-utilization 0.92 \
--distributed-executor-backend mp \
--kv-cache-dtype fp8 \
--reasoning-parser minimax_m3 \
--safetensors-load-strategy prefetch \
--speculative-config '{"method":"eagle3","model":"${EAGLE3_WEIGHT_PATH}","num_speculative_tokens":3,"kv_cache_dtype":"bfloat16"}' \
--enforce-eager \
--enable-chunked-prefill \
--enable-prefix-caching \
--additional-config '{"enable_cpu_binding":true,"ascend_compilation_config":{"fuse_qknorm_rope":true,"fuse_norm_quant":true},"multistream_overlap_shared_expert":true,"enable_shared_expert_dp":true,"enable_flashcomm1":true}' \
--kv-transfer-config \
'{
"kv_connector":"MooncakeConnectorV1",
"kv_role":"kv_producer",
"kv_port":"30000",
"engine_id":"0",
"kv_connector_extra_config":{
"use_ascend_direct":true,
"ascend_local_comm_res_path":"/etc/hixlep",
"prefill":{"dp_size":2,"tp_size":4,"pp_size":1},
"decode":{"dp_size":2,"tp_size":4,"pp_size":1}
}
}'
```
-
Decode 节点
unset ftp_proxy https_proxy http_proxy all_proxy unset FTP_PROXY HTTPS_PROXY HTTP_PROXY ALL_PROXY nic_name="xxxx" # NIC corresponding to local_ip local_ip="xxxx" # Decode node IP model_path="xxxx" # MiniMax-M3-MXFP8 model path EAGLE3_WEIGHT_PATH="xxxx" # MiniMax-M3-EAGLE3-GQA path export HCCL_BUFFSIZE=2048 export HCCL_IF_IP=$local_ip export HCCL_OP_EXPANSION_MODE="AIV" export HCCL_SOCKET_IFNAME=$nic_name export GLOO_SOCKET_IFNAME=$nic_name export ASCEND_RT_VISIBLE_DEVICES=$1 export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/mooncake:$LD_LIBRARY_PATH export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True vllm serve "$model_path" \ --host 0.0.0.0 \ --port $2 \ --data-parallel-size $3 \ --data-parallel-rank $4 \ --data-parallel-address $5 \ --data-parallel-rpc-port $6 \ --tensor-parallel-size $7 \ --pipeline-parallel-size $8 \ --enable-expert-parallel \ --seed 1024 \ --served-model-name minimax-m3 \ --reasoning-parser minimax_m3 \ --distributed-executor-backend mp \ --max-model-len 133000 \ --max-num-batched-tokens 32768 \ --trust-remote-code \ --max-num-seqs 256 \ --gpu-memory-utilization 0.92 \ --dtype bfloat16 \ --quantization mxfp8 \ --kv-cache-dtype fp8 \ --speculative-config '{"method":"eagle3","model":"${EAGLE3_WEIGHT_PATH}","num_speculative_tokens":3,"kv_cache_dtype":"bfloat16"}' \ --additional-config '{"enable_cpu_binding":true,"ascend_compilation_config":{"fuse_norm_quant":false},"multistream_overlap_shared_expert":true,"enable_shared_expert_dp":true}' \ --kv-transfer-config \ '{ "kv_connector":"MooncakeConnectorV1", "kv_role":"kv_consumer", "kv_port":"26900", "engine_id":"1", "kv_connector_extra_config":{ "use_ascend_direct":true, "ascend_local_comm_res_path":"/etc/hixlep", "prefill":{"dp_size":2,"tp_size":4,"pp_size":1}, "decode":{"dp_size":2,"tp_size":4,"pp_size":1} } }'准备工作完成后,在每个节点上使用以下命令启动服务器:
- Prefill 节点
python launch_online_dp.py \ --dp-size 2 --tp-size 4 --pp-size 1 \ --dp-size-local 2 --dp-rank-start 0 \ --dp-address $node_p_ip --dp-rpc-port 6884 \ --vllm-start-port 31050这将启动两个 Prefill API 服务器,端口为
31050和31051。等待两个 rank 都打印Application startup complete。- Decode 节点
python launch_online_dp.py \ --dp-size 2 --tp-size 4 --pp-size 1 \ --dp-size-local 2 --dp-rank-start 0 \ --dp-address $node_d_ip --dp-rpc-port 5964 \ --vllm-start-port 31060这将启动两个 Decode API 服务器,端口为
31060和31061。要设置请求转发,请在一个能够访问所有 Prefill 和 Decode API 端口的节点上运行以下脚本。你可以在仓库的 examples 中获取代理程序:load_balance_proxy_server_example.py。对于 950DT 产品 1P1D,代理会将请求转发到 2 个 Prefill rank 和 2 个 Decode rank。
unset ftp_proxy unset https_proxy unset http_proxy python load_balance_proxy_server_example.py \ --port 8009 \ --host $node_p_ip \ --prefiller-hosts \ $node_p_ip $node_p_ip \ --prefiller-ports \ 31050 31051 \ --decoder-hosts \ $node_d_ip $node_d_ip \ --decoder-ports \ 31060 31061之后,服务可通过
<proxy_ip>:8009访问。对于 PD 分离,请在第 7 节中使用此代理端点。
关键参数说明:
launch_online_dp.py 参数:
| 参数 | 类型 | 是否必填 | 默认值 | 描述 |
|---|---|---|---|---|
--dp-size |
int | 是 | - | 数据并行大小(所有节点上 DP rank 的总数)。 |
--tp-size |
int | 否 | 1 | 每个 DP rank 内的张量并行大小。 |
--pp-size |
int | 否 | 1 | 每个 DP rank 内的流水线并行大小。每个 rank 占用 tp_size * pp_size 个 NPU。 |
--dp-size-local |
int | 否 | (与 --dp-size 相同) |
当前节点上的 DP rank 数量。 |
--dp-rank-start |
int | 否 | 0 | 本节点上数据并行 rank 的起始 rank 偏移。 |
--dp-address |
str | 是 | - | 数据并行主节点的 IP 地址。 |
--dp-rpc-port |
str | 否 | 12321 | 数据并行主通信的 RPC 端口。 |
--vllm-start-port |
int | 否 | 8000 | 本节点上每个 vLLM 引擎实例的起始端口。每个 DP rank 的引擎端口 = vllm_start_port + 本地 rank 索引。 |
Prefill 节点特定配置:
--pipeline-parallel-size(A3 Prefill:2):将 MiniMax-M3 的 60 层分配到两个流水线阶段。A3 会设置VLLM_PP_LAYER_PARTITION=30,30,并将pp_layer_partition写入 Mooncake 额外配置。950DT 产品启动在 Prefill 和 Decode 上都使用--pp-size 1(不使用流水线并行),因此无需层分区。--enforce-eager:Prefill 节点不捕获 CUDA/ACL 图。--speculative-config '{"method":"eagle3", ...}':启用MiniMax-M3-EAGLE3-GQA草稿模型。不要将其替换为 GLM MTP 选项。
Decode 节点特定配置:
--max-num-seqs 256:经验证的 950DT 产品 1P1D 启动所使用的 Decode 并发数。A3 使用64。
Mooncake KV 传输配置(--kv-transfer-config):
"kv_connector": "MooncakeConnectorV1":使用 Mooncake 作为 prefill 节点和 decode 节点之间的 KV 缓存传输连接器。"kv_role": "kv_producer"/"kv_consumer":prefill 节点使用kv_producer,decode 节点使用kv_consumer。"kv_port":Mooncake KV 传输端口。prefill 和 decode 需使用不同端口。经验证的值为 A336000/36100,950DT 产品30000/26900。"use_ascend_direct": true:为 KV 缓存启用 Ascend 直接传输。"ascend_local_comm_res_path": "/etc/hixlep"(仅限 950DT 产品):950DT 产品上 UBOE / Ascend 直接通信所需。"prefill"/"decode"部分:dp_size、tp_size和pp_size必须与两个节点上的实际全局布局一致。A3 使用prefill: dp2 tp4 pp2和decode: dp4 tp4 pp1。950DT 产品使用prefill: dp2 tp4 pp1和decode: dp2 tp4 pp1。
请求转发(代理):
- 在启动代理之前,请等待所有 Prefill 和 Decode rank 打印
Application startup complete。 - 代理将每个 prefill 引擎端点和每个 decode 引擎端点映射到端口
8009上的单一入口点。 - 如果请求到达代理但没有返回输出,请检查代理主机列表是否包含所有健康的 Prefill 和 Decode 端口,并且在上一次运行后两个节点仍有空闲 NPU 内存。
有关上述环境变量的进一步说明和限制,请参阅 envs.py。
5.4 Prefill-Decode 分离与 KV Cache 池¶
本节基于 第 5.3 节。复用相同的拓扑、launch_online_dp.py、代理映射以及 MiniMax vllm serve 标志。Prefill 和 Decode 切换到 MultiConnector,以便实时 P→D KV 传输和 Mooncake KV Cache 池协同工作:
MooncakeConnectorV1实时将 KV 从 Prefill 传输到 Decode(与第 5.3 节中的角色相同)。AscendStoreConnector将 KV 存储在 Mooncake KV Cache 池中,以便后续具有相同前缀的 Prefill 可以命中池,而无需重新计算。- 默认情况下,Prefill 节点执行池查找、加载和写入。
有关后端选择、mooncake.json、Mooncake Master、驱逐和租户选项,请参阅 KV Cache 池部署指南。有关池化所需的硬件/通信环境变量,请参阅 环境变量说明。有关 MiniMax 特定问题,请参阅 第 10 章常见问题。
与第 5.3 节中的普通 PD 相比,请注意以下仅适用于池化的要求:
| 项目 | 普通 PD(5.3) | 池化 PD(本节) |
|---|---|---|
| 连接器 | 单个 MooncakeConnectorV1 |
MultiConnector 封装 MooncakeConnectorV1 + AscendStoreConnector |
| Mooncake Master | 不需要 | 必须在 Decode / Prefill 之前启动 mooncake_master |
mooncake.json |
不需要 | 每个 rank 都需要;Prefill 提供内存,Decode 设置 global_segment_size=0 |
engine_id / lookup_rpc_port |
固定示例 ID 可以 | 必须每个 DP rank 唯一(37000/37100 + DP_RANK),以避免端口 / 引擎冲突 |
| 额外环境变量 | 仅第 5.3 节的 HCCL_* |
保留 5.3 环境变量,然后添加来自 kv_pool.md §5.1 的池 fabric/UB 导出 |
| 容器挂载 | 950DT 需要 /etc/hixlep/ |
还需挂载 /etc/hccn.conf;在 950DT 上保留 /etc/hixlep/ |
| 启动顺序 | Decode → Prefill → 代理 | Mooncake Master → Decode → Prefill → 代理 |
| 验证 | 仅 P→D KV 传输 | 在重复前缀预热后,还需检查 Prefill 池 lookup/get/put 命中 |
5.4.1 先决条件¶
将主机 HCCN 配置挂载到每个参与池化的容器中:
在 950DT 产品上,还需保留第 5.3 节中的 /etc/hixlep/ 挂载,用于 Ascend 直接 KV 传输。
在每个节点上,将 mooncake.json 放在 run_dp_template.sh 旁边。Prefill 提供池内存;Decode 不提供。将 xxxx 替换为运行 Mooncake Master 的 Prefill 节点 IP。非零的 global_segment_size 必须对齐到 1GB。
A3 Prefill mooncake.json:
{
"metadata_server": "P2PHANDSHAKE",
"protocol": "ascend",
"device_name": "",
"master_server_address": "xxxx:50088",
"global_segment_size": "64GB",
"preferred_segment": true,
"prefer_alloc_in_same_node": true,
"enable_ssd_offload": false,
"tenant_id": "default"
}
950DT Prefill mooncake.json:
{
"metadata_server": "P2PHANDSHAKE",
"protocol": "ascend",
"device_name": "",
"master_server_address": "xxxx:50088",
"global_segment_size": "128GB",
"preferred_segment": true,
"prefer_alloc_in_same_node": true,
"enable_ssd_offload": false,
"tenant_id": "default"
}
两个平台上的 Decode mooncake.json(相同 Master 和 tenant_id,无捐赠段):
{
"metadata_server": "P2PHANDSHAKE",
"protocol": "ascend",
"device_name": "",
"master_server_address": "xxxx:50088",
"global_segment_size": 0,
"preferred_segment": true,
"prefer_alloc_in_same_node": true,
"enable_ssd_offload": false,
"tenant_id": "default"
}
5.4.2 环境变量¶
从第 5.3 节的环境变量块(HCCL_IF_IP、HCCL/GLOO/TP socket IFNAME、HCCL_BUFFSIZE、HCCL_OP_EXPANSION_MODE、PYTORCH_NPU_ALLOC_CONF、ASCEND_RT_VISIBLE_DEVICES,以及 A3 Prefill VLLM_PP_LAYER_PARTITION="30,30")开始。然后添加以下池化所需变量。根据你的机器和链路类型,从 环境变量说明 中选择硬件/通信导出。
每个 Prefill 和 Decode rank 上通用的池化导出:
export PYTHONHASHSEED=0
export MOONCAKE_CONFIG_PATH=./mooncake.json
# Optional: only if Mooncake is installed in a non-standard path (same as Section 5.3).
if [ -n "${MOONCAKE_LIB_DIRS:-}" ]; then
export LD_LIBRARY_PATH="${MOONCAKE_LIB_DIRS}:${LD_LIBRARY_PATH:-}"
fi
| 硬件 | 依赖项 | 必需的池化导出 | 说明 |
|---|---|---|---|
| 800I/T A3(HCCS,推荐) | HDK >= 26.0,或 HDK >= 25.5 且 mooncake >= v0.3.11;CANN >= 9.0.0 | export ACL_OP_INIT_MODE=1 和 export ASCEND_ENABLE_USE_FABRIC_MEM=1 |
保留第 5.3 节的 HCCL_IF_IP / socket IFNAME 导出。 |
| 800I/T A3(RoCE)或 800I/T A2 | A2:推荐 HDK >= 25.5 | export HCCL_INTRA_ROCE_ENABLE=1,外加 HCCL_IF_IP / socket IFNAME,以及 nr_hugepages=200000 |
使用 KV Cache 池指南中的 RoCE 路径。 |
| 950PR/DT(Device UB) | HDK >= 25.6 且 mooncake >= v0.3.11;CANN >= 9.1.0 | export ASCEND_LOCAL_COMM_RES_PATH=/etc/hixlep/ 和 export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}';unset ASCEND_GLOBAL_RESOURCE_CONFIG |
挂载 /etc/hixlep/。若改用 UBOE,请按 KV Cache 池指南中的说明使用 ASCEND_GLOBAL_RESOURCE_CONFIG。 |
| 硬件 | 依赖项 | 必需的池化导出项 | 备注 |
|---|---|---|---|
5.4.3 预填充 / 解码脚本¶
复用第 5.3 节的 launch_online_dp.py。将每个角色的 run_dp_template.sh 替换为下面的池化版本。保持第 5.3 节 vllm serve 的参数风格;仅 --kv-transfer-config 切换为 MultiConnector。根据 $4(DP rank)展开 engine_id 和 lookup_rpc_port — 不要在不同 rank 中硬编码相同值。
在 2 台 Atlas 800 A3(64GB × 16)上,针对 MiniMax-M3-w8a8(W8A8)并使用 MiniMax-M3-EAGLE3-GQA,实现带 KV 缓存池的预填充-解码分离。
- 预填充节点
unset http_proxy https_proxy ftp_proxy
nic_name="xxxx" # NIC corresponding to local_ip
local_ip="xxxx" # Prefill node IP
model_path="xxxx" # MiniMax-M3 model path
EAGLE3_WEIGHT_PATH="xxxx" # MiniMax-M3-EAGLE3-GQA path
export VLLM_PP_LAYER_PARTITION="30,30"
export HCCL_BUFFSIZE=1024
export HCCL_IF_IP=$local_ip
export HCCL_OP_EXPANSION_MODE="AIV"
export ASCEND_RT_VISIBLE_DEVICES=$1
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export PYTHONHASHSEED=0
# Pooling extras on top of Section 5.3 (kv_pool.md §5.1, A3 HCCS)
export ACL_OP_INIT_MODE=1
export ASCEND_ENABLE_USE_FABRIC_MEM=1
export MOONCAKE_CONFIG_PATH=./mooncake.json
if [ -n "${MOONCAKE_LIB_DIRS:-}" ]; then
export LD_LIBRARY_PATH="${MOONCAKE_LIB_DIRS}:${LD_LIBRARY_PATH:-}"
fi
vllm serve "$model_path" \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--pipeline-parallel-size $8 \
--enforce-eager \
--distributed-executor-backend mp \
--served-model-name minimax-m3 \
--enable-expert-parallel \
--seed 1024 \
--max-model-len 133000 \
--max-num-seqs 32 \
--max-num-batched-tokens 32768 \
--long-prefill-token-threshold 2048 \
--enable-chunked-prefill \
--enable-prefix-caching \
--trust-remote-code \
--quantization ascend \
--gpu-memory-utilization 0.92 \
--reasoning-parser minimax_m3 \
--additional-config '{"enable_cpu_binding":true,"ascend_compilation_config":{"fuse_norm_quant":false},"multistream_overlap_shared_expert":true,"weight_nz_mode":2,"enable_shared_expert_dp":true,"enable_flashcomm1":true}' \
--speculative-config '{"method":"eagle3","model":"${EAGLE3_WEIGHT_PATH}","num_speculative_tokens":3}' \
--kv-transfer-config \
'{
"kv_connector":"MultiConnector",
"kv_role":"kv_producer",
"engine_id":"minimax-m3-prefill-dp'"$4"'",
"kv_connector_extra_config":{
"connectors":[
{
"kv_connector":"MooncakeConnectorV1",
"kv_buffer_device":"npu",
"kv_role":"kv_producer",
"kv_port":"36000",
"kv_connector_extra_config":{
"use_ascend_direct":true,
"prefill":{"dp_size":2,"tp_size":4,"pp_size":2,"pp_layer_partition":"30,30"},
"decode":{"dp_size":4,"tp_size":4,"pp_size":1}
}
},
{
"kv_connector":"AscendStoreConnector",
"kv_role":"kv_producer",
"kv_connector_extra_config":{
"backend":"mooncake",
"lookup_rpc_port":'$((37000 + $4))'
}
}
]
}
}'
- 解码节点
unset http_proxy https_proxy ftp_proxy
nic_name="xxxx" # NIC corresponding to local_ip
local_ip="xxxx" # Decode node IP
model_path="xxxx" # MiniMax-M3 model path
EAGLE3_WEIGHT_PATH="xxxx" # MiniMax-M3-EAGLE3-GQA path
export HCCL_BUFFSIZE=2048
export HCCL_IF_IP=$local_ip
export HCCL_OP_EXPANSION_MODE="AIV"
export ASCEND_RT_VISIBLE_DEVICES=$1
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export PYTHONHASHSEED=0
# Pooling extras on top of Section 5.3 (kv_pool.md §5.1, A3 HCCS)
export ACL_OP_INIT_MODE=1
export ASCEND_ENABLE_USE_FABRIC_MEM=1
export MOONCAKE_CONFIG_PATH=./mooncake.json
if [ -n "${MOONCAKE_LIB_DIRS:-}" ]; then
export LD_LIBRARY_PATH="${MOONCAKE_LIB_DIRS}:${LD_LIBRARY_PATH:-}"
fi
vllm serve "$model_path" \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--pipeline-parallel-size $8 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name minimax-m3 \
--reasoning-parser minimax_m3 \
--distributed-executor-backend mp \
--max-model-len 133000 \
--max-num-batched-tokens 32768 \
--trust-remote-code \
--quantization ascend \
--max-num-seqs 64 \
--gpu-memory-utilization 0.92 \
--additional-config '{"enable_cpu_binding":true,"ascend_compilation_config":{"fuse_norm_quant":false},"multistream_overlap_shared_expert":true,"weight_nz_mode":2,"enable_shared_expert_dp":true}' \
--speculative-config '{"method":"eagle3","model":"${EAGLE3_WEIGHT_PATH}","num_speculative_tokens":3}' \
--kv-transfer-config \
'{
"kv_connector":"MultiConnector",
"kv_role":"kv_consumer",
"engine_id":"minimax-m3-decode-dp'"$4"'",
"kv_connector_extra_config":{
"connectors":[
{
"kv_connector":"MooncakeConnectorV1",
"kv_buffer_device":"npu",
"kv_role":"kv_consumer",
"kv_port":"36100",
"kv_connector_extra_config":{
"use_ascend_direct":true,
"prefill":{"dp_size":2,"tp_size":4,"pp_size":2,"pp_layer_partition":"30,30"},
"decode":{"dp_size":4,"tp_size":4,"pp_size":1}
}
},
{
"kv_connector":"AscendStoreConnector",
"kv_role":"kv_consumer",
"kv_connector_extra_config":{
"backend":"mooncake",
"lookup_rpc_port":'$((37100 + $4))'
}
}
]
}
}'
A3 上的启动顺序:Mooncake Master → Decode → Prefill → Proxy。使用与 5.3 节 A3 相同的 launch_online_dp.py 和 proxy 命令(--vllm-start-port 31050 / 31060,proxy 位于 8009)。
在 2 个 950DT 产品(96GB × 8)上,为 MiniMax-M3-MXFP8 搭配 MiniMax-M3-EAGLE3-GQA 实现带 KV Cache Pool 的 Prefill-Decode 分离。挂载 /etc/hixlep/ 和 /etc/hccn.conf。将 5.4.1 节中的 Prefill / Decode mooncake.json 放置在 run_dp_template.sh 旁边(Prefill 上的 global_segment_size 为 128GB,Decode 上为 0)。将 master_server_address 设置为 Prefill Mooncake Master,例如 xxxx:50088。
- Prefill 节点
unset ftp_proxy https_proxy http_proxy all_proxy
unset FTP_PROXY HTTPS_PROXY HTTP_PROXY ALL_PROXY
nic_name="xxxx" # NIC corresponding to local_ip
local_ip="xxxx" # Prefill node IP
model_path="xxxx" # MiniMax-M3-MXFP8 model path
EAGLE3_WEIGHT_PATH="xxxx" # MiniMax-M3-EAGLE3-GQA path
export HCCL_BUFFSIZE=256
export HCCL_IF_IP=$local_ip
export HCCL_OP_EXPANSION_MODE="AIV"
export ASCEND_RT_VISIBLE_DEVICES=$1
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export PYTHONHASHSEED=0
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/mooncake:$LD_LIBRARY_PATH
# Pooling extras on top of Section 5.3 (kv_pool.md §5.1, Device UB)
export MOONCAKE_CONFIG_PATH=./mooncake.json
export ASCEND_LOCAL_COMM_RES_PATH=/etc/hixlep/
export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}'
unset ASCEND_GLOBAL_RESOURCE_CONFIG
vllm serve "$model_path" \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--pipeline-parallel-size $8 \
--served-model-name minimax-m3 \
--trust-remote-code \
--dtype bfloat16 \
--max-num-seqs 128 \
--max-num-batched-tokens 32768 \
--max-model-len 133000 \
--enable-expert-parallel \
--quantization mxfp8 \
--gpu-memory-utilization 0.92 \
--distributed-executor-backend mp \
--kv-cache-dtype fp8 \
--reasoning-parser minimax_m3 \
--safetensors-load-strategy prefetch \
--speculative-config '{"method":"eagle3","model":"${EAGLE3_WEIGHT_PATH}","num_speculative_tokens":3,"kv_cache_dtype":"bfloat16"}' \
--enforce-eager \
--enable-chunked-prefill \
--enable-prefix-caching \
--additional-config '{"enable_cpu_binding":true,"ascend_compilation_config":{"fuse_qknorm_rope":true,"fuse_norm_quant":true},"multistream_overlap_shared_expert":true,"enable_shared_expert_dp":true,"enable_flashcomm1":true}' \
--kv-transfer-config \
'{
"kv_connector":"MultiConnector",
"kv_role":"kv_producer",
"engine_id":"minimax-m3-prefill-dp'"$4"'",
"kv_connector_extra_config":{
"connectors":[
{
"kv_connector":"MooncakeConnectorV1",
"kv_buffer_device":"npu",
"kv_role":"kv_producer",
"kv_port":"30000",
"kv_connector_extra_config":{
"use_ascend_direct":true,
"ascend_local_comm_res_path":"/etc/hixlep",
"prefill":{"dp_size":2,"tp_size":4,"pp_size":1},
"decode":{"dp_size":2,"tp_size":4,"pp_size":1}
}
},
{
"kv_connector":"AscendStoreConnector",
"kv_role":"kv_producer",
"kv_connector_extra_config":{
"backend":"mooncake",
"lookup_rpc_port":'$((37000 + $4))'
}
}
]
}
}'
- Decode 节点
unset ftp_proxy https_proxy http_proxy all_proxy
unset FTP_PROXY HTTPS_PROXY HTTP_PROXY ALL_PROXY
nic_name="xxxx" # NIC corresponding to local_ip
local_ip="xxxx" # Decode node IP
model_path="xxxx" # MiniMax-M3-MXFP8 model path
EAGLE3_WEIGHT_PATH="xxxx" # MiniMax-M3-EAGLE3-GQA path
export HCCL_BUFFSIZE=2048
export HCCL_IF_IP=$local_ip
export HCCL_OP_EXPANSION_MODE="AIV"
export HCCL_SOCKET_IFNAME=$nic_name
export GLOO_SOCKET_IFNAME=$nic_name
export ASCEND_RT_VISIBLE_DEVICES=$1
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/lib64:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/mooncake:$LD_LIBRARY_PATH
export PYTORCH_NPU_ALLOC_CONF=expandable_segments:True
export PYTHONHASHSEED=0
# Pooling extras on top of Section 5.3 (kv_pool.md §5.1, Device UB)
export MOONCAKE_CONFIG_PATH=./mooncake.json
export ASCEND_LOCAL_COMM_RES_PATH=/etc/hixlep/
export ASCEND_LOCAL_COMM_RES='{"version":"1.3"}'
unset ASCEND_GLOBAL_RESOURCE_CONFIG
vllm serve "$model_path" \
--host 0.0.0.0 \
--port $2 \
--data-parallel-size $3 \
--data-parallel-rank $4 \
--data-parallel-address $5 \
--data-parallel-rpc-port $6 \
--tensor-parallel-size $7 \
--pipeline-parallel-size $8 \
--enable-expert-parallel \
--seed 1024 \
--served-model-name minimax-m3 \
--reasoning-parser minimax_m3 \
--distributed-executor-backend mp \
--max-model-len 133000 \
--max-num-batched-tokens 32768 \
--trust-remote-code \
--max-num-seqs 256 \
--gpu-memory-utilization 0.92 \
--dtype bfloat16 \
--quantization mxfp8 \
--kv-cache-dtype fp8 \
--speculative-config '{"method":"eagle3","model":"${EAGLE3_WEIGHT_PATH}","num_speculative_tokens":3,"kv_cache_dtype":"bfloat16"}' \
--additional-config '{"enable_cpu_binding":true,"ascend_compilation_config":{"fuse_norm_quant":false},"multistream_overlap_shared_expert":true,"enable_shared_expert_dp":true}' \
--kv-transfer-config \
'{
"kv_connector":"MultiConnector",
"kv_role":"kv_consumer",
"engine_id":"minimax-m3-decode-dp'"$4"'",
"kv_connector_extra_config":{
"connectors":[
{
"kv_connector":"MooncakeConnectorV1",
"kv_buffer_device":"npu",
"kv_role":"kv_consumer",
"kv_port":"26900",
"kv_connector_extra_config":{
"use_ascend_direct":true,
"ascend_local_comm_res_path":"/etc/hixlep",
"prefill":{"dp_size":2,"tp_size":4,"pp_size":1},
"decode":{"dp_size":2,"tp_size":4,"pp_size":1}
}
},
{
"kv_connector":"AscendStoreConnector",
"kv_role":"kv_consumer",
"kv_connector_extra_config":{
"backend":"mooncake",
"lookup_rpc_port":'$((37100 + $4))'
}
}
]
}
}'
950DT 上的启动顺序:Mooncake Master → Decode → Prefill → Proxy。请使用与第 5.3 节 950DT 相同的 launch_online_dp.py 和代理命令(两个角色均使用 DP2,代理使用 8009)。
5.4.4 启动服务¶
在每个平台上按以下顺序启动:
- 在 Prefill 节点上启动
mooncake_master,并确认端口50088可访问:
mooncake_master \
--port 50088 \
--eviction_high_watermark_ratio 0.9 \
--eviction_ratio 0.1 \
--default_kv_lease_ttl 11000 \
--enable_offload=false \
--client_ttl=120
-
使用第 5.3 节中适用于你平台的
launch_online_dp.py命令启动 Decode。等待每个 Decode rank 打印Application startup complete。 -
以相同方式启动 Prefill。等待每个 Prefill rank 打印
Application startup complete。 -
启动第 5.3 节的代理。此时服务可通过
<proxy_ip>:8009访问。在第 7 节中使用此代理端点。
5.4.5 验证¶
- 确认 Mooncake Master 端口
50088可访问。 - 确认每个 Decode 引擎端口就绪,然后确认每个 Prefill 引擎端口就绪。
- 仅向端口
8009上的代理发送请求。 - 使用重复前缀请求进行预热,然后再次发送请求,并检查 Prefill 日志中的 KV Pool 查找/获取/写入及命中信息。
- 确认 Decode 日志仍显示正常的 Mooncake P→D KV 传输。
5.5 多模态与 ViT DP(可选)¶
MiniMax-M3 在 Ascend 上支持图像和视频输入。上述部署示例将 --limit-mm-per-prompt '{"image":1,"video":0}' 保留为默认的多模态容量假设,因为其他服务参数是针对单图像路径调优的。
MiniMax-M3 的图像和视频输入共享同一个 Vision Tower。如果服务只需要一种模态,请显式将未使用的模态设置为 0;例如,仅图像服务使用 {"image":1,"video":0},仅视频服务使用 {"image":0,"video":1}。只要图像或视频中任意一种保持启用,共享的 Vision Tower 就会保留。将未使用的模态设置为 0 比省略它更清晰,因为被省略的模态仍可能参与多模态容量和 profiling 规划。
对于 ViT / 多模态编码器部分,支持数据并行执行,并可通过以下方式启用:
默认部署示例未启用该选项,因为它可能增加单卡内存使用。启用 ViT DP 时,请针对目标工作负载重新评估内存相关参数,例如 --max-model-len、--max-num-seqs 和 --gpu-memory-utilization。
对于视频或图像-视频混合请求,请根据实际请求形态调整多模态限制,而不是盲目修改默认模板:
# one video
--limit-mm-per-prompt '{"image":0,"video":1}'
# one image and one video
--limit-mm-per-prompt '{"image":1,"video":1}'
在请求中使用本地媒体路径(例如 file:///path/to/video.mp4)时,请添加显式允许列表路径:
如果未指定采样的视频帧数,vLLM 会使用其默认视频采样策略,默认采样 32 帧。对于快速功能冒烟测试,可以在请求或评估配置中设置更小的帧数,例如 8 或 16。对于基准测试运行,请遵循数据集协议。
在 MiniMax-M3 服务中,不应同时启用 FLASHCOMM1 和仅语言模型模式。FLASHCOMM1 通过 additional_config.enable_flashcomm1 启用,而仅语言模型模式通过 --language-model-only 启用。
# Enable FLASHCOMM1.
--additional-config '{"enable_flashcomm1": true}'
# Enable language-model-only mode.
--language-model-only
VLLM_ASCEND_ENABLE_FLASHCOMM1=1 仅为兼容性保留,但推荐使用 additional_config.enable_flashcomm1。
6 思考与解析器配置¶
6.1 思考模式¶
MiniMax-M3 支持三种思考模式,通过 chat_template_kwargs 中的 thinking_mode 控制:
| 模式 | 行为 | 使用场景 |
|---|---|---|
enabled |
模型在每次响应前都会思考,包括在工具结果之后 | 复杂推理、智能体 |
disabled |
不思考;模型直接回答 | 对延迟敏感的轮次 |
adaptive |
模型根据任务决定是否思考(未设置时的默认值) | 通用场景 |
6.1.1 请求示例¶
禁用思考(curl):
curl http://{ip}:{port}/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "minimax-m3",
"messages": [{"role": "user", "content": "who are you?"}],
"max_tokens": 100,
"stream": false,
"top_p": 0.95,
"top_k": 40,
"temperature": 1.0,
"chat_template_kwargs": {"thinking_mode": "disabled"}
}'
根据需要,将 "thinking_mode" 更改为 "enabled" 或 "adaptive"。已弃用的 enable_thinking 参数(等同于 thinking_mode: "enabled")也受到支持。
启用思考(Python SDK):
from openai import OpenAI
client = OpenAI(api_key="EMPTY", base_url="http://localhost:8000/v1")
response = client.chat.completions.create(
model="minimax-m3",
messages=[{"role": "user", "content": "Prove there are infinitely many primes."}],
extra_body={"chat_template_kwargs": {"thinking_mode": "enabled"}},
)
msg = response.choices[0].message
print(getattr(msg, "reasoning", None)) # the <mm:think> block
print(msg.content) # the final answer
6.2 推理解析器¶
MiniMax-M3 推理解析器(--reasoning-parser minimax_m3)会从模型输出中提取思考块 <mm:think>...</mm:think>,并将其作为 reasoning 字段暴露。其余文本作为 content 返回。
6.2.1 服务器配置¶
--reasoning-parser minimax_m3 标志启用 MiniMax-M3 推理解析器,该解析器使用 <mm:think>...</mm:think> 分隔符将模型输出拆分为推理和正文:
6.2.2 输出格式¶
MiniMax-M3 使用显式的思考分隔符:
6.2.3 解析器行为¶
thinking_mode="enabled":聊天模板会在提示词中预填<mm:think>。生成的文本从推理块内部开始,并在</mm:think>之后过渡到内容。thinking_mode="disabled"或默认:模型输出被视为纯内容。如果出现<mm:think>,解析器会按分隔符进行拆分。- 流式输出:推理和内容通过
DeltaMessage.reasoning和DeltaMessage.content逐 token 增量流式传输。 - Token 计数:
<mm:think>块内的推理 token 会被正确计数。
6.3 工具调用解析器¶
MiniMax-M3 使用命名空间分隔的 XML 格式进行工具调用。通过 --tool-parser minimax_m3 启用。
6.3.1 服务端配置¶
当同时指定 --reasoning-parser minimax_m3 和 --tool-call-parser minimax_m3 时,解析器会自动协同工作,以处理同时包含推理块和工具调用的响应:
vllm serve ${WEIGHT_PATH} \
--reasoning-parser minimax_m3 \
--enable-auto-tool-choice \
--tool-call-parser minimax_m3 \
...
6.3.2 工具调用格式¶
每个结构标签前面都有 ]<]minimax[>[ 命名空间标记:
]<]minimax[>[<tool_call>
]<]minimax[>[<invoke name="create_order">
]<]minimax[>[<user_id>42]<]minimax[>[</user_id>
]<]minimax[>[<shipping>
]<]minimax[>[<city>Singapore]<]minimax[>[</city>
]<]minimax[>[<zip>018956]<]minimax[>[</zip>
]<]minimax[>[</shipping>
]<]minimax[>[</invoke>
]<]minimax[>[</tool_call>
6.3.3 主要特性¶
- 递归参数解析:支持嵌套对象和数组(例如,包含
city/zip的shipping)。 - Schema 感知的类型强制转换:根据函数的 JSON Schema 定义,字符串参数值会自动转换为正确的类型(整数、布尔值、对象、数组)。
- 多次调用:单个
<tool_call>块可以包含多个<invoke>块。 - 流式输出:随着
<invoke>块的接收,工具名称和参数片段会增量流式传输。
6.3.4 请求示例(curl)¶
curl http://{ip}:{port}/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "minimax-m3",
"messages": [{"role": "user", "content": "What'\''s the weather like in Shanghai?"}],
"max_tokens": 300,
"stream": false,
"tool_choice": "auto",
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City or country name"
}
},
"required": ["location"],
"additionalProperties": false
}
}
}
],
"chat_template_kwargs": {"thinking_mode": "disabled"}
}'
7 功能验证¶
7.1 文本¶
curl http://{ip}:{port}/v1/chat/completions \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"model": "minimax-m3",
"messages": [
{
"role": "user",
"content": "Answer the following multiple choice question. The last line of your response should be of the following format: 'Answer: LETTER' (without quotes) where LETTER is one of ABCD. Think step by step before answering.\n\nA student regrets that he fell asleep during a lecture in electrochemistry, facing the following incomplete statement in a test:\nThermodynamically, oxygen is a …oxidant in basic solutions. Kinetically, oxygen reacts …in acidic solutions.\nWhich combination of weaker/stronger and faster/slower is correct?\n\nA) weaker —faster\nB) stronger —faster\nC) weaker - slower\nD) stronger —slower"
}
],
"max_tokens": 8000,
"temperature": 1.0
}
EOF
预期结果:答案为 C。
7.2 单张图片¶
以启用图片输入的方式启动服务,例如 --limit-mm-per-prompt '{"image":1,"video":0}'。在客户端将 ${IMAGE_PATH} 替换为本地图片路径。
IMAGE_PATH=/path/to/image.jpg
IMAGE_BASE64="$(base64 -w 0 "${IMAGE_PATH}")"
curl http://{ip}:{port}/v1/chat/completions \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"model": "minimax-m3",
"messages": [
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,${IMAGE_BASE64}"}},
{"type": "text", "text": "Briefly describe this image."}
]
}
],
"max_tokens": 512,
"temperature": 0
}
EOF
预期结果:HTTP 200 响应,JSON 响应体包含非空的 choices 以及描述图片的生成文本。
7.3 单个视频¶
以启用视频输入的方式启动服务,例如 --limit-mm-per-prompt '{"image":0,"video":1}'。如果请求使用 file:// 本地视频路径,还需添加 --allowed-local-media-path / 或更受限的允许目录。如果未指定 media_io_kwargs.video.num_frames,vLLM 默认采样 32 帧。
curl http://{ip}:{port}/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "minimax-m3",
"messages": [
{
"role": "user",
"content": [
{
"type": "video_url",
"video_url": {
"url": "file:///path/to/video.mp4"
}
},
{
"type": "text",
"text": "Briefly describe the main content of this video."
}
]
}
],
"max_tokens": 512,
"temperature": 0
}'
Expected result: HTTP 200 response with a JSON body containing non-empty choices and generated text describing the video content.
7.4 混合图像和视频请求¶
启动服务时同时启用图像和视频输入。对于以下请求,使用 --limit-mm-per-prompt '{"image":1,"video":1}'。如果请求使用 file:// 本地视频路径,还需添加 --allowed-local-media-path / 或更窄的允许目录。
IMAGE_BASE64="$(base64 -w 0 /path/to/image.jpg)"
curl http://{ip}:{port}/v1/chat/completions \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"model": "minimax-m3",
"messages": [
{
"role": "user",
"content": [
{"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,${IMAGE_BASE64}"}},
{"type": "video_url", "video_url": {"url": "file:///path/to/video.mp4"}},
{"type": "text", "text": "Describe the image and video separately, and explain whether they are related."}
]
}
],
"max_tokens": 512,
"temperature": 0
}
EOF
预期结果:HTTP 200 响应,JSON 响应体中包含非空的 choices 以及分别描述图像和视频并解释它们是否相关的生成文本。
8 准确性评估¶
8.1 使用 AISBench¶
有关详细说明,请参阅 使用 AISBench 进行准确性评估。
8.2 文本评估¶
| 数据集 | 硬件 | 分数 | max-model-len | max-num-seqs | max_out_len | batch_size | generation_kwargs |
|---|---|---|---|---|---|---|---|
| GSM8K | 8 H20 (96G × 8) | 96.72 | 65536 | 16 | 49152 | 16 | temperature=1.0, top_p=0.95 |
| GSM8K | 8 Atlas 800 A3 (64GB × 16) | 96.36 | 10240 | 16 | 9500 | 20 | temperature=1.0, top_p=0.95 |
| AIME2025 | 8 H20 (96G × 8) | 95@repeat4 | - | - | - | - | - |
| AIME2025 | 8 Atlas 800 A3 (64GB × 16) | 93.3@repeat2 | 131072 | 32 | 65536 | 8 | temperature=1.0, top_p=0.95 |
| GPQA-Diamond | 8 H20 (96G × 8) | 92.42 | 81920 | 64 | 75776 | 8 | temperature=0.6, top_p=0.95 |
| GPQA-Diamond | 8 Atlas 800 A3 (64GB × 16) | 92.42 | 131072 | 32 | 65536 | 8 | temperature=0.6, top_p=0.95 |
| GPQA-Diamond | 8 950DT 产品 (96GB × 8) | 92.9 | 133000 | 128 | 131072 | 128 | temperature=0.6, top_p=0.95 |
| MMMU-pro | 8 950DT 产品 (96GB × 8) | 78.9 | 133000 | 128 | 131072 | 50 | temperature=0.6, top_p=0.95 |
8.3 多模态评估¶
MiniMax-M3 的多模态准确性使用 AISBench 进行评估。ViT DP 路径是可选的,可以通过在服务命令中添加 --mm-encoder-tp-mode data 来启用,但并非所有多模态准确性运行都需要它。对于视频评估,如果请求或评估配置中未指定帧数,vLLM 默认采样 32 帧。
下面的 Video-MME 结果是在 chunk1 和 chunk2 上测量的,而不是完整数据集。
对于 Video-MME 评估,请运行启用视频输入的 vLLM OpenAI 兼容服务,并使用 AISBench 发送 Video-MME 请求。官方 AISBench 指南可能未将 Video-MME 列为内置示例,因此此处使用的关键 MiniMax-M3 设置如下:
- 使用
--limit-mm-per-prompt '{"image":0,"video":1}'提供服务; - 不要设置
media_io_kwargs.video.num_frames,以便 vLLM 使用默认的 32 个采样帧; - 使用
max-model-len=90112和max_out_len=8192; - 评估 Video-MME chunk1 和 chunk2,而不是完整数据集。
用于 Video-MME chunk1+chunk2 评估的 AISBench 命令如下:
ais_bench \
--models vllm_api_general_chat \
--datasets videomme_subset_1_2.py \
--mode all \
--dump-eval-details \
--merge-ds
videomme_subset_1_2.py 是一个本地 AISBench 数据集配置,派生自原始 Video-MME 配置,例如 videomme_gen.py。它将 path 指向根据本地可用的 chunk1/chunk2 视频从完整 Video-MME 元数据中过滤得到的 parquet 文件,并将 video_path 指向提取的 chunk1/chunk2 .mp4 目录。这可以在保持标准 Video-MME 请求和评分流程的同时,使评估更轻量。
| 数据集 | 模态 | 工具 | 硬件 | ViT DP | max-model-len | max_out_len | 输入配置 | generation_kwargs | 分数 |
|---|---|---|---|---|---|---|---|---|---|
| TextVQA | 图像 | AISBench | GPU | 禁用 | 65536 | 512 | --limit-mm-per-prompt '{"image":1,"video":0}' |
temperature=1.0, top_p=0.95 | 70.82 |
| TextVQA | 图像 | AISBench | NPU | 禁用 | 65536 | 512 | --limit-mm-per-prompt '{"image":1,"video":0}' |
temperature=1.0, top_p=0.95 | 72.75 |
| Video-MME chunk1+chunk2 | 视频 | AISBench | GPU | - | 90112 | 8192 | --limit-mm-per-prompt '{"image":0,"video":1}',默认 32 帧 |
temperature=1.0, top_p=0.95 | 73.41 |
| Video-MME chunk1+chunk2 | 视频 | AISBench | NPU | - | 90112 | 8192 | --limit-mm-per-prompt '{"image":0,"video":1}',默认 32 帧 |
temperature=1.0, top_p=0.95 | 74.21 |
9 性能调优¶
注意:以下配置已在特定测试环境中验证,仅供参考。最优配置取决于最大输入/输出长度、前缀缓存命中率、精度要求以及部署机器比例等因素。建议参考第 9.2 节,根据实际条件进行调优。
9.1 推荐配置¶
推荐配置与第 5 章“在线服务部署”中指定的配置相同。
9.2 调优指南¶
9.2.1 通用调优参考¶
有关通用调优方法,请参阅 公开性能调优文档。
有关详细功能描述,请参阅 功能矩阵。
10 常见问题¶
- 问:如何重新安装 vLLM Ascend?
答:使用以下命令重新安装 vLLM Ascend,并使用当前 Python 环境中的依赖项进行构建:
pip install -v --no-build-isolation -e . -i http://mirrors.aliyun.com/pypi/simple --trusted-host mirrors.aliyun.com
- 问:当未设置
media_io_kwargs.video.num_frames时,如果视频请求缓慢或超时,应该怎么办?
答:默认情况下,vLLM 在读取视频时会采样 32 帧。MiniMax-M3 每帧会产生大量视觉 Token,因此 32 帧视频会显著增加预填充计算。如果请求缓慢或超时,请显式将 media_io_kwargs.video.num_frames 设置为较小的值,例如 8 或 16 帧:
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 vl/vllm-ascend