# Use mirror if HuggingFace is inaccessible
export HF_ENDPOINT="https://hf-mirror.com"
# GPU (INT8)
python tools/run.py -c configs/qwen3/int8_dynamic/qwen3_8b-w8a8.yaml
# GPU (GPTQ)
python tools/run.py -c configs/opt/gptq/opt_125m-w4a16.yaml
# NPU (use device_map: npu in config)
python tools/run.py -c configs/qwen3/int8_dynamic/qwen3_8b-w8a8.yaml# GPU
bash tools/serve/deploy_vllm.sh outputs/model -d 0 -t 1
# NPU
bash tools/serve/deploy_vllm.sh outputs/model -d 0 -t 1 -qLM-Eval Harness (supports 3 backends: vllm, hf, api):
# vLLM backend (fastest, direct loading - no server needed)
bash tools/eval/run_lmeval.sh outputs/model --backend vllm --tasks wikitext -d 0
# HuggingFace backend
bash tools/eval/run_lmeval.sh outputs/model --backend hf --tasks wikitext -d 0
# API backend (requires running server)
bash tools/serve/deploy_vllm.sh outputs/model -d 0 -t 1
bash tools/eval/run_lmeval.sh outputs/model --backend api --tasks wikitextStress Test (requires running vLLM server):
# Step 1: Deploy vLLM server first
bash tools/serve/deploy_vllm.sh outputs/model -d 0 -t 1
# Step 2: Run stress test against running server
bash tools/eval/run_stress_test.sh outputs/modelNPUSlim v2 uses a streaming-first, chunk-based quantization pipeline. Instead of loading the full model into memory, it streams through checkpoint shards chunk-by-chunk via ChunkLoader, applies algorithms, and writes results incrementally via StreamingHuggingFaceSaver.
SlimEngine (core/engine.py):
- Pipeline orchestrator: creates
ResourceManagerfrom config resources, builds and executes recipe tasks - Each task receives
resource_managerfor lazy resource acquisition
Registry Pattern (core/factory.py):
- Single
Registryclass withregister(),register_lazy(),get(),create(),list()methods - 5 singleton registries:
AlgorithmRegistry,ModelRegistry,DatasetRegistry,TaskRegistry,SaverRegistry - Lazy loading: modules are imported only on first
get()/create()call
ResourceManager (core/resource_manager.py):
- Resolves
@resource_idreferences from config - Lazy model/dataset instantiation via registry lookup
BackendHandler (core/backend.py):
- Unified CPU/CUDA/NPU backend abstraction
bootstrap_from_path() (core/bootstrap.py):
- CLI bootstrap: YAML loading, config parse/validate, logging setup
- BaseAlgorithm (
algorithms/base_algo.py):process_chunk(chunk: ChunkContext) -> ChunkContextwithon_start()/on_finish()lifecycle hooks - BaseQuantizationAlgorithm (
algorithms/quantization/base_quant_algo.py): Addsset_runtime_context(),should_skip_name()for glob/regex skip matching,_mark_model_quantized() - BaseLLMModel (
models/base_model.py): Model wrapper with HF/ModelScope hub support,prepare_empty_model()for meta-device skeleton - BaseTask (
tasks/base_task.py): Lifecycle hooks (on_start,on_finish,execute) with lazy resource acquisition viaResourceManager - BaseSaver (
savers/base_saver.py): Streaming tensor writer interface - BaseDataset (
datasets/base_dataset.py): Dataset withprocessorargument,collate_fnstatic method
- compressor (
tasks/compressor/): Streaming quantization task — handles chunk loading, algorithm invocation, skip-layer resolution, and saver coordination all in one unified task
src/npuslim/
├── core/ # Core framework
│ ├── engine.py # SlimEngine orchestrator
│ ├── factory.py # Registry pattern (5 singleton registries)
│ ├── resource_manager.py # Lazy resource acquisition
│ ├── backend.py # CPU/CUDA/NPU backend handler
│ └── bootstrap.py # CLI bootstrap
├── config/ # Config parsing
│ ├── schema.py # Dataclasses (EngineConfig, ResourceConfig, etc.)
│ ├── parser.py # YAML/dict -> EngineConfig
│ ├── validator.py # Reference checking
│ └── printer.py # Pretty-printing, logging setup
├── algorithms/ # Quantization algorithms
│ ├── base_algo.py # BaseAlgorithm (process_chunk interface)
│ └── quantization/
│ ├── base_quant_algo.py # Shared runtime context + skip-matching
│ ├── gptq/ # GPTQ algorithm
│ └── int8_dynamic/ # INT8 dynamic quantization
├── models/ # Model wrappers
│ ├── base_model.py # BaseLLMModel
│ ├── qwen3/ # Qwen3 model
│ ├── opt/ # OPT model
│ └── glm5/ # GLM-5 model (GlmMoeDsa)
├── datasets/ # Calibration datasets
│ ├── base_dataset.py # BaseDataset
│ ├── c4_dataset.py # C4 dataset (streaming + local cache)
│ └── text_dataset.py # Text dataset (JSONL + Parquet)
├── tasks/ # Pipeline tasks
│ ├── base_task.py # BaseTask with lifecycle hooks
│ └── compressor/ # Streaming compressor task
│ ├── context.py # ChunkContext, LayerInfo, ModuleInfo
│ ├── loader.py # ChunkLoader (streaming safetensors reader)
│ └── task.py # CompressorTask
├── savers/ # Model savers
│ ├── base_saver.py # BaseSaver interface
│ └── hf_saver.py # StreamingHuggingFaceSaver (safetensors)
├── hooks/ # Lifecycle hook system (HookType, HookRegistry)
├── distributed/ # Distributed execution support
├── cann_ops/ # CANN-specific operators
│ ├── quant/ # Quantization primitives (PTQ, QAT tools)
│ ├── llm_ptq/ # LLM-specific PTQ utilities
│ ├── sparse/ # Sparsity utilities
│ ├── lowbit/ # Low-bit quantization
│ └── multi_modal/ # Multi-modal support
├── plugins/ # Integration plugins
│ ├── vllm/ # vLLM model executor plugins
│ │ └── model_executor/models/
│ │ ├── qwen3_moe.py
│ │ └── kimi_k2_mcore.py
│ ├── vllm_ascend/ # vLLM-Ascend quantization methods
│ └── transformers/ # HuggingFace quantizers
└── cli/ # CLI entry point (tools/run.py)
tools/
├── run.py # Main entry point
├── serve/deploy_vllm.sh # vLLM server deployment
├── eval/ # Evaluation scripts
│ ├── run_lmeval.sh # LM-Eval harness
│ └── run_stress_test.sh # Stress test pipeline
└── utils/common.sh # Shared bash utilities
metadata:
name: "Qwen3_INT8_Recipe"
description: "INT8 quantization for Qwen3"
resources:
- id: qwen3
type: Qwen3
path: Qwen/Qwen3-0.6B
model_hub: hf # or ms (ModelScope)
device_map: cuda # or cpu, npu
- id: calib_data
type: C4
num_samples: 128
max_seq_length: 2048
recipe:
- name: "INT8_Quantization"
type: compressor
model: "@qwen3" # Reference to resource
dataloader:
dataset: "@calib_data" # Reference to resource
batch_size: 1
algorithm:
type: INT8Dynamic # or GPTQ
wbits: 8
ignore_layers: [] # glob/regex patterns
execution:
mode: streaming
chunk_size: 4
saver:
type: StreamingHuggingFaceSaver
save_dir: "./outputs"- EngineConfig:
metadata+resources(list) +recipe(list of tasks) - ResourceConfig:
id,type, extra fields passed to constructor - RecipeTaskConfig:
name,type,model(@ref),dataloader,algorithm,saver,execution - Resource references use
@idsyntax (e.g.,@qwen3,@calib_data)
| Algorithm | Registry Name | Description |
|---|---|---|
| INT8Dynamic | INT8Dynamic |
Per-channel weight, per-token activation quantization |
| GPTQ | GPTQ |
Activation-aware weight quantization with Hessian statistics |
| Model | Registry Name | Description |
|---|---|---|
| Qwen3 | Qwen3 (or Qwen3Model) |
Qwen3 series |
| OPT | OPT (or OPTModel) |
Meta OPT series |
| GLM-5 | GLM5 |
GlmMoeDsa with MLA attention |
Entry points defined in pyproject.toml:
[project.entry-points."vllm.general_plugins"]
npuslim = "npuslim.plugins:register"
[project.entry-points."transformers.quantizers"]
quip = "npuslim.plugins.transformers.quantizers.quantizer_quip:QuipHfQuantizer"npuslim.plugins:register() is the main entry point that:
- Calls
plugins.vllm.register()- Core vLLM patches - Calls
plugins.transformers.register()- HuggingFace quantizers - Conditionally calls
plugins.vllm_ascend.register()- NPU-specific patches
Plugin paths MUST mirror the target framework's structure:
src/npuslim/plugins/
├── vllm/ # Patches vllm.* modules
│ └── model_executor/models/
│ ├── qwen3_moe.py # Patches vllm.model_executor.models.qwen3_moe
│ └── kimi_k2_mcore.py # Patches vllm.model_executor.models.kimi_k2_mcore
├── vllm_ascend/ # Patches vllm_ascend.* modules
│ └── quantization/
│ ├── method_adapters.py # Patches vllm_ascend.quantization.method_adapters
│ └── methods/w4a16_linear.py # Quantization scheme for vLLM-Ascend
└── transformers/ # Patches transformers.* modules
└── quantizers/quantizer_quip.py # Registers QuipHfQuantizer
Use @register_patch(target_module) decorator from npuslim.plugins.registry:
from npuslim.plugins.registry import register_patch
@register_patch("vllm_ascend.quantization.method_adapters")
def patch_process_weight(module):
original = module.AscendLinearMethod.process_weight
module.AscendLinearMethod.process_weight = patched_versionFor vLLM-Ascend quantization schemes, use their @register_scheme decorator:
from vllm_ascend.quantization.methods import register_scheme
@register_scheme("W4A16", "linear")
class MyW4A16LinearMethod(AscendLinearScheme):
...- StreamingHuggingFaceSaver: Streaming safetensors writer with auto-flush on size threshold. Writes
model.safetensors.index.json, copies auxiliary files, saves config/tokenizer. Generatesquant_model_description.jsonfor Ascend runtime when NPU mode is detected.
- CANN: Set
ASCEND_HOME_PATHenv var before installation - Python: >=3.11