msModelSlim Quick Start¶
1. Overview¶
msModelSlim is a model compression tool for the Ascend ecosystem, covering the quantization and compression of dense LLMs, MoE, and multimodal models. This document uses Qwen3.6-27B as an example to walk you through compressing model weights into the W8A8 format through one-click quantization, and completing inference deployment verification based on vLLM-Ascend.
Experience map (core operations take about 10 minutes, excluding network transfer time such as image and model downloads)
| Step | Stage | Core Tool | Operation Time | Principle Learning |
|---|---|---|---|---|
| 1 | Container environment preparation | vLLM-Ascend container | About 1 minute (excluding image download time) | 5 minutes |
| 2 | Model file preparation | modelscope | About 1 minute (excluding model download time) | 2 minutes |
| 3 | Model quantization | msModelSlim | About 3 minutes | 5 minutes |
| 4 | Quantization result verification | vLLM-Ascend | About 5 minutes | 10 minutes |
2. Procedure¶
2.1 Environment Preparation (Required)¶
🛑 This section is mandatory! Skipping this section may cause multiple subsequent operations to fail.
This tutorial is only supported in the standardized vLLM-Ascend container and is not supported on bare metal, virtual machines, or other non-standard container environments.
2.1.1 Prerequisites¶
Before you begin, confirm that the server meets the following requirements:
| Item | Requirement | Verification Method |
|---|---|---|
| Hardware computing power | The Linux server is equipped with at least 2 NPU cards (A2 or A3 series), with drivers and firmware installed. | Run npu-smi info and confirm that the NPU card status is normal. |
| Container runtime | Docker is installed and running (recommended version ≥ 18.0). | Run docker ps; no error indicates that the service is running normally. |
| Script execution | Python 3 (any version) is installed on the host machine. | Run python3 -V on the host machine; version information output indicates that it is installed. |
| Network communication | curl (any version) is installed. | Run curl -V; version information output indicates that it is installed. |
| Disk space | At least 100 GB of free disk space (for downloading model weights). | Run df -h to check disk space usage. |
👉 After confirming that the prerequisites are met, if the environment has public network access, all commands in this chapter can be executed directly by Copy/Paste without manual input or concatenation.
2.1.2 Host Machine: Automatically Identifying and Configuring Image Environment Variables¶
Run the following commands on the host machine: reads the NPU PCI ID, matches the image version, and writes the environment variable for use in subsequent steps.
dev_id=$(lspci -n -D | grep -o '19e5:d[0-9a-f]\{3\}' | head -n1 | cut -d: -f2)
source /dev/stdin <<< "$(
case "$dev_id" in
'd802' )
echo 'export MY_STUDY_VAR_VLLM_IMAGE="quay.io/ascend/vllm-ascend:v0.18.0"'
echo 'echo -e "\e[32m[PASS] Successfully auto-selected image: $MY_STUDY_VAR_VLLM_IMAGE\e[0m"'
;;
'd803' )
echo 'export MY_STUDY_VAR_VLLM_IMAGE="quay.io/ascend/vllm-ascend:v0.18.0-a3"'
echo 'echo -e "\e[32m[PASS] Successfully auto-selected image: $MY_STUDY_VAR_VLLM_IMAGE\e[0m"'
;;
* )
echo 'unset MY_STUDY_VAR_VLLM_IMAGE'
echo 'echo -e "\033[31m[FAIL] Get device ID: '"$dev_id"'. Learning is not supported in the current environment.\033[0m" >&2'
;;
esac
)"
[!NOTE]
Command Principle
Obtain the NPU PCI ID through
lspci, automatically match the official vLLM-Ascend image, and assign the image address to the environment variableMY_STUDY_VAR_VLLM_IMAGEfor subsequent use.
All images come from the official vLLM-Ascend repository published on Quay.io. For image details, see vLLM-Ascend Official Image Repository.
If [PASS] is output, the identification succeeded; continue to the next step. If [FAIL] is output, the possible causes are as follows:
-
The hardware is not within the supported range: this tutorial supports only the Ascend A2 and A3 series. Use compatible hardware and retry.
-
Underlying environment exception:
lspciis not installed, or the current user does not have permission to runlspci -n -D. Contact the environment administrator for confirmation.
2.1.3 Host Machine: Pulling the Image¶
Run the following command on the host machine:
If the pull fails due to enterprise intranet restrictions, refer to Section 3.1.
2.1.4 Host Machine: Downloading the Container Startup Script¶
On the host machine, run:
cd ~ && curl -fLO --retry 3 https://inst.obs.cn-north-4.myhuaweicloud.com/env/ctr_in.py && chmod +x ctr_in.py
If the download fails due to network restrictions, see Section 3.2.
2.1.5 Host Machine: Starting the Container¶
Run the following command on the host machine. The terminal displays the container creation information and waits for confirmation. Press Enter to complete the creation.
Expected result:
After waiting for about 10 seconds, the terminal displays the following root shell prompt, indicating that the container has been started successfully:
If an error or the container selection interface appears, return to Section 2.1.2, confirm that [PASS] is output, and then retry.
2.1.6 Inside the Container: Installing msModelSlim¶
After entering the container, install msModelSlim and the required transformers version:
pip install -i https://repo.huaweicloud.com/repository/pypi/simple/ \
transformers==5.2.0 \
https://gitcode.com/Ascend/msmodelslim/releases/download/tag_MindStudio_26.1.0.B100_002/msmodelslim-26.1.0-py3-none-any.whl
[!NOTE]
Transformers Version Selection
The transformers version depends on the model to be quantized. The Qwen3.6-27B model used in this example must run in a Transformers 5.2.0 environment.
If the installation fails due to enterprise intranet restrictions, refer to Section 3.3.
2.1.7 Inside the Container: Verifying Environment Installation¶
After installation is complete, run the one-click verification:
python3 -c 'import torch, torch_npu; assert torch.npu.is_available(), "NPU is unavailable"; print("PyTorch:", torch.__version__)' && msmodelslim --help >/dev/null && echo -e "\e[32m[PASS] NPU environment and msmodelslim check passed.\e[0m"
If [PASS] is output, it indicates that the NPU driver, PyTorch, and msModelSlim are all ready. The environment preparation is complete, and you can proceed to the quantization stage.
2.2 Performing Quantization¶
2.2.1 Inside the Container: Preparing Model Files¶
[!NOTE]
Efficient Operation Tips
The model files are large (approximately 50 GB), and even at full gigabit bandwidth, downloading takes about 10 minutes. It is recommended that after executing the download command, you first read the subsequent sections to learn the quantization principles and deployment process, so that you can perform the subsequent operations more efficiently once the download is complete.
Run the following command to download the original Qwen3.6-27B weights from ModelScope:
2.2.2 Inside the Container: Preparing NPU Cards¶
The quantization process requires NPU compute acceleration. Ensure that at least one idle NPU card is available. Run the following command to automatically select an idle card:
free_npu=$(npu-smi info | grep -oE "No running processes found in NPU\s+[0-9]+" | head -n 1 | awk '{print $NF}')
if [ -n "$free_npu" ]; then
export ASCEND_RT_VISIBLE_DEVICES=$free_npu
echo -e "\e[32m[PASS] Successfully exported ASCEND_RT_VISIBLE_DEVICES=$free_npu\e[0m"
else
echo -e "\e[31m[FAIL] All NPUs are busy. Please release NPUs and try again.\e[0m" >&2
fi
If [PASS] is output, an idle NPU card has been successfully specified and you can proceed to the next step. If [FAIL] is output, release the NPU resources first and then retry the preceding command.
[!NOTE]
NPU Card Selection Mechanism
Function: The environment variable
ASCEND_RT_VISIBLE_DEVICESspecifies the NPU IDs visible to the current process (single or multiple), allowing device switching without modifying the code.Index Mapping Rules:
After this variable is set, the logical indexes of the visible devices are renumbered starting from 0. Subsequent operations must use the new indexes instead of the original NPU IDs.
=1: Only NPU 1 is visible, and its new index is 0.=1,2,3: NPUs 1, 2, and 3 are visible, and their new indexes are 0, 1, 2 in order.⚠️ Note: This environment variable is a trial feature and may change in later versions. Do not use it in production environments.
2.2.3 Inside the Container: Performing Model Quantization¶
Run the following command to use the one-click quantization feature. The system automatically matches the best-practice configuration for this model and completes quantization in W8A8 mode (quantizing both model weights and activations to 8-bit):
msmodelslim quant --model_path ~/qwen36_27b_base --save_path ~/qwen36_27b_w8a8 --device npu --model_type Qwen3.6-27B --quant_type w8a8 --trust_remote_code True
Quantization takes approximately 4 minutes. The following output indicates completion:
If quantization is aborted or reports an error and the preceding success indicator does not appear, troubleshoot as follows:
-
Confirm that the NPU card status is normal: run
npu-smi infoand check whether theHealthstatus of the target card isOKand whether the AI Core utilization is abnormal. If abnormal, release resources or replace the card first. -
Check the environment variable settings: run
echo ${ASCEND_RT_VISIBLE_DEVICES}to confirm that the card ID referenced by this variable actually exists and is not occupied, and that it does not contain spaces or invalid IDs. -
Troubleshoot insufficient memory (OOM): check whether the terminal error log contains a keyword similar to
Out of memory. If it does, the current card has insufficient memory. Switch to an idle NPU card and retry.
2.2.4 Inside the Container: Viewing the Quantization Output¶
1. View the quantization result files.
The output directory structure is similar to the following, where files marked "[Quantization ]" are the quantization output files, and files marked "[Original]" are the inference configuration files copied from the original model (only the main files are listed, not a complete list):
~/qwen36_27b_w8a8/
├── Qwen3.6-27B_best_practice.yaml # [Quantization] Quantization configuration protocol (full record of quantization settings, reproducible)
├── quant_model_description.json # [Quantization] Quantized weight descriptor (tensor-wise quantization types and metadata; required for inference engine loading)
├── quant_model_weights-00001-of-00009.safetensors # [Quantization] Quantized weight shard 1/9 (INT8 weights, 9 shards total)
├── ... # [Quantization] Remaining weight shards (00002–00008)
├── quant_model_weights-00009-of-00009.safetensors # [Quantization] Quantized weight shard 9/9 (INT8 weights)
├── config.json # [Original] Model configuration (architecture, layers, hidden size, etc.)
├── tokenizer_config.json # [Original] Tokenizer configuration (special tokens, vocab size, preprocessing logic)
├── tokenizer.json # [Original] Tokenizer vocabulary (token-to-ID mappings)
├── chat_template.jinja # [Original] Chat template (multi-turn prompt formatting)
└── generation_config.json # [Original] Generation configuration (temperature, Top-P, max length, sampling strategy)
2. Verify the quantization compression.
Run the following command to compare the directory sizes before and after quantization:
Expected result: the original weights are approximately 50+ GB, and after quantization approximately 30+ GB, a size reduction of about 40%, indicating that quantization significantly compresses the model size.
2.3 Quantized Model Function Verification¶
This section uses vLLM-Ascend to deploy the quantized model and complete one inference verification.
2.3.1 Inside the Container: Restoring the vLLM Runtime Environment¶
The msModelSlim quantization phase require Transformers 5.x, whereas the vLLM runtime requires Transformers 4.x. Therefore, before inference, the version must be downgraded and restored to the original version in the image.
2.3.2 Inside the Container: Preparing NPU Cards¶
The inference service requires two cards for tensor parallel. Run the following commands to automatically select two idle cards:
# 1. Obtain the IDs of up to two idle cards
free_npus_raw=$(npu-smi info | grep -oE "No running processes found in NPU\s+[0-9]+" | head -n 2 | awk '{print $NF}')
npu_count=$(echo "$free_npus_raw" | wc -w)
# 2. Check whether the requirement for two cards is met and set the control environment variable. An error is reported if only one card is available or no idle card exists
if [ "$npu_count" -eq 2 ]; then
export_val=$(echo "$free_npus_raw" | paste -s -d ',')
export ASCEND_RT_VISIBLE_DEVICES=$export_val
echo -e "\e[32m[PASS] Successfully exported ASCEND_RT_VISIBLE_DEVICES=$export_val\e[0m"
else
echo -e "\e[31m[FAIL] Insufficient free NPUs (Found $npu_count, Need 2). Please release NPUs and try again.\e[0m" >&2
fi
If [PASS] is output, idle NPU cards have been automatically selected and you can proceed to the next step. If [FAIL] is output, release the NPU resources first and then retry the preceding command.
2.3.3 Inside the Container: Starting the Service¶
Start the vLLM-Ascend online inference service (the command keeps occupying the current terminal):
vllm serve ~/qwen36_27b_w8a8 \
--port 5678 \
--served-model-name Qwen3.6-27B-W8A8 \
--quantization ascend \
--tensor-parallel-size 2 \
--max-model-len 8192 \
--compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' \
--additional-config '{"enable_cpu_binding":true}'
[!NOTE]
Knowledge point (optional reading): Description of the main vLLM startup parameters
--quantization ascend: the Ascend quantization inference backend to load the W8A8 weights generated by msModelSlim.--served-model-name: the model name exposed externally, which must be consistent with themodelfield in client requests.--tensor-parallel-size 2: the tensor parallel degree, which shards the model across 2 NPU cards.--max-model-len 8192: the maximum sequence length (number of tokens). Requests exceeding this length will be rejected.--compilation-config: Enables the FULL_DECODE_ONLY graph mode, which compiles the Decode stage into a static graph to accelerate inference.--additional-config: Enables CPU-NPU NUMA affinity binding to reduce Host-Device communication latency.
Startup takes approximately 4 to 5 minutes and produces a large amount of logs. The main time-consuming stages are as follows (the durations are measured values from a single test and are for reference only).
| No. | Stage | Duration | Description |
|---|---|---|---|
| 1 | Configuration parsing and plugin activation | About 10 seconds | Loads the vLLM-Ascend platform plugin and parses the model architecture and scheduling parameters. |
| 2 | Worker startup and HCCL handshake | About 50 seconds | Starts multi-card Worker processes, establishes communication links, and assigns TP ranks. |
| 3 | CPU-NPU affinity binding | About 10 seconds | Binds Workers to NPU-proximal CPU cores and interrupts according to the NUMA topology. |
| 4 | Model weight loading | About 30 seconds | Loads 9 safetensors shards (about 16.7 GB per card) into global memory. |
| 5 | Graph compilation and operator fusion | About 80 seconds | Performs Dynamo bytecode conversion (20s) + CANN operator compilation (48s) + fusion warm-up. |
| 6 | NPU Graph capture | About 30 seconds | Precompiles static execution paths for 22 batch sizes (1 to 152). |
When logs similar to the following appear, the service has started successfully:
(APIServer pid=6036) INFO: Started server process [6036]
(APIServer pid=6036) INFO: Waiting for application startup.
(APIServer pid=6036) INFO: Application startup complete.
Some Warning logs may appear during startup. They can be ignored as long as the preceding success log appears. For details, see FAQ 4.3.
If the service startup is aborted and the preceding success log does not appear, locate the problem based on the error message output by the terminal. Common errors and their handling methods are as follows:
-
Port occupied: The error message contains
Address already in useorbind: address already in use. Change the port using--port, or terminate the process that is using this port. -
Insufficient memory (OOM): The error message contains something like
Out of memory. You can runnpu-smi infoto check the memory usage of the target card, and useASCEND_RT_VISIBLE_DEVICESto switch to an idle card.
2.3.4 Inference Verification¶
After the service starts successfully, because the vLLM service continuously occupies the current terminal, open a new terminal on the host machine (whether to execute inside the container is optional, as the network is reachable in both cases):
Step 1: Send a warmup request.
curl -s http://localhost:5678/v1/completions \
-H "Content-Type: application/json" \
-d '{"model": "Qwen3.6-27B-W8A8", "prompt": "This is a warm-up request.", "max_tokens": 256}' \
| python3 -c "import sys, json; print(json.load(sys.stdin)['choices'][0]['text'])"
The first response may be slow or return garbled characters. Wait for the returned information; the returned content can be ignored.
[!NOTE]
Key point (optional reading): Reasons why the first request takes a long time or returns garbled characters
After the service starts, the first inference triggers several one-time initialization operations, causing the first inference to take a long time or return garbled characters:
- First execution of the NPU Graph: The static graph path only fully traverses the complete data flow during the first actual inference, and the log shows the
Replaying aclgraphprompt.- JIT compilation of Triton operators: Operators such as FlashAttention perform dynamic compilation and automatic tuning during their first execution, causing a delay of several seconds.
- Dirty data in the KV Cache: After global memory is preallocated, it is not cleared byte by byte. The first attention computation may read invalid data, resulting in garbled output.
The industry commonly adopts the "Warmup" mechanism to address such issues, that is, after the service starts, send a test request first and discard its result, and only connect formal traffic after the system completes initialization.
Step 2: Send a formal inference request.
curl -s http://localhost:5678/v1/completions \
-H "Content-Type: application/json" \
-d '{"model":"Qwen3.6-27B-W8A8", "prompt":"Write a Python function to calculate the Fibonacci sequence.", "max_tokens":256}' \
| python3 -c "import sys, json; print(json.load(sys.stdin)['choices'][0]['text'])"
Wait for the inference to complete. If the returned information includes the reasoning process for writing code or contains code output, the inference is successful.
2.4 Cleaning Up Resources¶
2.4.1 Stopping the Inference Service and Releasing NPU Card Resources¶
Press Ctrl+C in the vLLM startup terminal to stop the service and release the occupied NPU card resources. Run npu-smi info to confirm that the NPU cards are no longer abnormally occupied, and manually kill any residual processes if necessary.
2.4.2 (Optional) Deleting the Container to Free Up Disk Space¶
If the container environment in this tutorial is no longer needed, run the following command on the host machine to select and delete the target container to free up disk space:
🎉 At this point, the quick start experience is complete. You have finished the full workflow of one-click quantization with msModelSlim and inference deployment with vLLM-Ascend. To learn about more features, see advanced documents such as User Guide.
3. Appendix: Solutions for Intranet Environments Without Public Network Access¶
3.1 Obtaining Docker Images in an Isolated Intranet¶
Solution 1: Configuring a Docker Proxy for Direct Pulling
Applicable to most Linux distributions with Docker version ≥ 18.0 (compatibility is not guaranteed in all scenarios; adjust according to the actual environment if exceptions occur).
Edit the Docker service proxy configuration file /etc/systemd/system/docker.service.d/http-proxy.conf (replace the username, password, proxy address, and port according to the actual environment).
[Service]
Environment="HTTP_PROXY=http://username:password@proxy.example.com:8080"
Environment="HTTPS_PROXY=http://username:password@proxy.example.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,.example.com"
After saving, reload and restart the Docker service:
After that, docker pull can be executed normally.
Solution 2: Importing the Image Offline
If the proxy solution is not feasible, first run Section 2.1.2 on the intranet NPU server and record the complete value of MY_STUDY_VAR_VLLM_IMAGE. Then, on a relay machine that has public network access and the same CPU architecture, run:
VLLM_IMAGE='Full image address' # Replace with the value of MY_STUDY_VAR_VLLM_IMAGE
docker pull "${VLLM_IMAGE}"
docker save -o vllm-ascend.tar "${VLLM_IMAGE}"
Transfer vllm-ascend.tar to the intranet server via a USB drive or other means, and then load it:
After loading is complete, continue to Section 3.2 to transfer the startup script, and then return to Section 2.1.5 to start the container. If the host machine shell session has been switched, re-execute Section 2.1.2 to restore the environment variables.
3.2 Transferring the Container Startup Script¶
Open the following link in a browser with public network access, download the ctr_in.py script, and transfer it to the ~/ directory of the intranet server:
Run the following commands on the host machine of the intranet server:
After confirming that the file exists and has execution permissions, return to Section 2.1.5 to start the container.
3.3 Installing Python Dependencies Offline¶
Use the intranet pip source to install dependencies whenever possible. If no intranet software source is available, download the required installation packages in a relay environment that has public network access and matches the intranet NPU server in both CPU architecture and Python version, as follows:
Transfer the offline_wheels directory to the intranet server, copy it to the user home directory inside the container, and then execute the following inside the container:
After the installation is complete, return to Section 2.1.7 to run the verification command. There is no need to run the online installation command again.
4. FAQs¶
4.1 How Do I Re-enter the Container After Exiting It?¶
On the host machine, choose either of the following methods:
Method 1 (recommended): Use the container startup script.
Select the target container as prompted. If only one container is running, the script enters it automatically.
Method 2: Use the native Docker command.
Replace alice_YYMMDD_HHMMSS with the actual container name. You can run docker ps first to view it.
4.2 What Should I Do if "Permission Denied" Is Displayed When Running Docker Commands?¶
The current user may not have been added to the Docker user group. Run the following command on the host machine with root privileges:
After running the command, log out of the current session and log in again, or run newgrp docker to make the user group change take effect immediately. Then run docker ps to verify.
NOTE The Docker user group has high system privileges. Add only trusted users to this group, and avoid operating as root on a daily basis.
4.3 Is It Normal to See Warning Logs When Starting vLLM?¶
If Application startup complete is finally output, none of the WARNING logs during startup affect functionality. They mainly fall into the following categories:
-
GPU-specific parameter reset: Parameters such as
--disable-cascade-attnand--disable-flashinfer-prefillapply only to NVIDIA GPUs. In the Ascend environment, vLLM automatically resets them toFalseand ignores them. -
FULL_DECODE_ONLY graph mode risk warning: This mode is in the experimental stage, and the warning indicates that capturing too many batches may cause insufficient memory. If
Application startup completeis finally output, it means graph capture succeeded and the service can be used normally. -
CUDA Graph capture limit: The message
Capping cudagraph capture sizesindicates that the system automatically adjusted the maximum captured batch size based on the available Mamba cache blocks, which is normal adaptation behavior. -
Gloo communication fallback: The message
Unable to resolve hostnameindicates that the Gloo communication library cannot resolve the hostname and has automatically fallen back to the loopback address, which does not affect single-machine multi-card inference.