Inference Framework Deployment Guide

Deployment and usage guides for HLIECpp / HLIELLama / HLIEvLLM / HLIEPython

C++ inference service framework (Windows) providing aggregated text, multimodal, image generation, and speech inference capabilities.

1. Basic Information

1.1 Version History

VersionDateDescription
v2.1.0-PreviewJune 2026Based on HLIELLama, supports the following features:
- Speculative decoding (Draft Model/MTP) [experimental]
- Inference optimization for the full Qwen3.6/Qwen3.5 model family
- CoPaw-series model support
- Gamma4-series model support
- Qwen3 Embedding and Reranker model support
- GLM-OCR model support
- Qwen3-asr and GLM-asr speech model support
v2.0.0May 2026- Supports TTS model inference channels and TTS interface protocols (cosyvoice3)
- Supports WebSocket protocol output for speech models (whisper)
- Supports the think parameter for GPT OSS models
- Supports inference for Qwen3.5-series text and multimodal models
- Supports --list-devices and --dev card binding
- Supports qwen3-embedding, qwen3-rerank, and qwen3.5 models
v1.7.0March 2026- Version v1.0.0 update
- Supports speech recognition interface protocols
- Supports bge model inference
- Supports Lora models
- Integrates HLIEWhisperCpp for whisper speech models
- Supports running multiple cards and models simultaneously with load distribution
v1.6.0January 2026- Version v0.0.7 update
- Supports KV cache reuse in single-user multi-turn conversations
- Supports automatic VL model matching
- Updates the default model loading configuration
v1.6.0-alphaDecember 2025- Supports Qwen3-30B-A3B [M50]
- Supports Qwen3-Coder-30B-A3B [M50]
- Supports Qwen3 VL 4B [M30][M50]
- Supports Qwen3 VL 8B [M50]
- Supports the MinP and presence_penalty parameters
v1.5.0October 13, 2025- Adds a configuration and management UI, integrated with HLAWModel; supports model inference scheduling and NPU status queries
- Multi-batch support
- Supports running with no model loaded; models can be dynamically loaded and unloaded through RESTful API requests; supports multi-instance scenarios
- Fixes legacy Jira bugs
- Updates the chain-of-thought switch
v1.4.0August 20, 2025- Switches dependencies to a customized llama.cpp
- Supports text + text-to-image (Xh2+SD3)
- Supports text + text-to-image in a single process
- Supports multi-process (multi-instance) startup for load balancing
- Independent request logs
- Supports Qwen2.5VL
- Supports configuring the tcim log level from the hi.cpp configuration file
v1.3.0June 30, 2025- Windows installer supports HiBalancer multi-card deployment
- Windows service boot log feature
- Request log optimization
v1.3.0-daily-20250625-m50June 12, 2025Supports sampling switch configuration
v1.3.0-daily-20250618-m50June 12, 2025M50 test version; adds performance data logging
v1.3.0-daily-20250612-m50June 12, 2025M50 test version
v1.3.0-daily-20250606June 6, 2025Supports running the hi.cpp inference service as a Linux background service with OpenAI API capabilities; provides the corresponding Kylin OS SDK; supports Kylin OS v10; models include qwen3 8b and deepseek 7b
v1.3.0-daily-20250530May 30, 2025Supports 4cores_8k qwen3-8b-1batch
1.2.0May 30, 2025Implements Windows service installation; compatible with more OpenAI interface parameters; adds port, log level, and log path configuration
1.1.0April 11, 2024Official version
1.1.0July 19, 2024Software version update
1.0.0July 10, 2024Official version

1.2 Document Purpose

This document helps you quickly connect to and start the HLIECpp inference service.

2. Inference Service Installation

2.1 Deployment Requirements

Hardware Requirements (Minimum)

  • CPU architecture: x86_64

  • Disk: 200G

Software Requirements

  • Operating system: Windows 11/10

2.2 Installation Process

Note

  • Make sure the inference AI card is already installed before installing this system.

Starting from version 2.1.0, HLIECpp installation is integrated into the AI Assistant app market.

Download the installer from the inference framework section of the Beelink AI website (https://llm.bee-link.cn/frameworks.php), then double-click HLAWUtility-Setup-1.4.0-win-x64.exe to start the installation to start the installation. After the preparation screen, you can choose the installation directory.

HLAWUtility provides many features to help users get started quickly, including

Card status monitoring, Model management (local and cloud), Configuration management, Inference scheduling, Driver management, and Firmware (card) management.

Switch to App Market, find HLIECpp, and click install. Click Yes in the pop-up dialog. After a few seconds, the installation will be complete.

3. Using the Inference Service

3.1 Model Configuration

3.1.1 Supported Model Deployment Packages

The full package name format is: HiModel_<target>_<model_type>[-vl]_<param_size>_p256_<context_size>_<batch_size>_<core_num>_<device_size>_<sys_version>_<build_time>.gguf

  • target indicates the hardware platform, such as xh1 or xh2.

  • model_type indicates the model type.

    • deepseek: the deployment package is a DeepSeek-r1 model.

    • qwen2.5: the deployment package is a QWen2.5 model.

    • qwen3: the deployment package is a QWen3 model.

    • Other model types...

  • [-vl] indicates multimodal.

  • param_size indicates the model parameters, such as 4b.

  • context_size indicates the context size, such as 2K.

  • batch_size indicates the batch inference capability, such as 1b or 2b.

  • core_num indicates the number of IPU cores the model is built for, such as 2core.

  • device_size indicates how many AI chips are needed to load and run the model, such as 1chip or 2chips (legacy format: 1d, 2d).

  • sys_version indicates the hardware version the model was compiled against, such as v0.7.0.

  • build_time indicates the build time, such as 20260105154602.

Example: HiModel_xh2_qwen3_32b_256_32k_b1_4chips_2cores_v0.7.0_20251228.gguf

Please keep the model file name intact when using the service.

3.1.2 Model Download

Method 1:

Users can download models from the designated model website: https://llm.bee-link.cn/

Method 2 (Recommended):

Use the model management feature of the HLAWUtility tool to download models directly to the local model directory:

Enter model management as shown below. In the model list, a disk icon on the far left means the model is available locally, while a cloud icon means it is a cloud model that has not been downloaded. Find the desired model and click View Details in the Operation column, or download it directly. The download task is passed to the task center for downloading.

3.1.3 Manually Configuring SD3 Models (Skip If Not Needed)

Due to the current characteristics of SD3 models, they can only be configured by manually downloading them and creating a JSON information file.

Example SD3 image generation model directory:

models/
$ tree
.
├── SD3
│ ├── clip.hmm
│ ├── clip_l.hmm
│ ├── mmdit.hmm
│ ├── t5.hmm
│ └── vae.hmm
└── sd3.json
...

Create a JSON file to describe the SD3 model information:

{
"ModelType" : "Sd3",
"XHVersion" : 2,
"ClipModel" : "./SD3/clip.hmm",
"ClipLModel" : "./SD3/clip_l.hmm",
"T5Model" : "./SD3/t5.hmm",
"MMDitModel" : "./SD3/mmdit.hmm",
"VaeModel" : "./SD3/vae.hmm"
}

Save it as a json file containing the sd3 keyword in the configured model directory.

3.2 Service Configuration

3.2.1 Manual Configuration

The configuration file is located in the config directory of the installation directory (default: C:\Program Files\AI\HLIECpp), named sys.cfg.

[server]
port=7901
# 设备ID, 以数字表示,默认只有0,多个设备用逗号隔开, 如 0,1
devices=0
# 实例副本数量,会启动多个进程,端口会递增+1, 用于负载均衡,多个设备同时运行同一种模型
replicas=1
# 用于多实例场景下节省内存使用,true时多实例的模型加载会有一定时间等待,达成串行效果
memory_saving=false [log]
# debug, info, warn, info
level=info # 4-debug, 3-warn, 2-error 1-info
tcim_level=2 # max files to keep
max_files=7
location=C:\ProgramData\AI\HLIECpp\logs\ [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja=
--reasoning-format=none
#--reasoning_budget = 0 [model]
# 模型目录
cur_model=D:\models
# 默认LLM/WHISPER模型,不带格式后缀
default=
default_mmproj=
# 是否默认加载SD3
enable_sd3=true
# 针对LLM配置为true时,相关Completions/Embeddings会根据接口中的model参数去自动加载模型
auto_load=true
# LLM模型懒加载
llm_lazy_mode=false

After modifying the configuration, restart the HLIECpp Service. Open Windows Services, find HLIECpp Service, right-click it, and restart.

3.2.2 Configuration with the Tool

After opening the application, switch to the service configuration item, modify the required configuration, click Save and Confirm, and restart the service.

3.3 Inference Scheduling with the API

Currently, the backend API default port is 7901 and can be changed through configuration (the service must be restarted).

In multi-instance scenarios, the port increments by 1 for each instance; for example, 4 instances use ports 7901, 7902, 7903, 7904.

Currently, the service supports running with no default model configured, and models can be loaded and unloaded dynamically.

3.3.1 Dynamically Loading a Model

*###start
POST*http://localhost:7901/models/load
Content-Type:application/json {
"model": "HiModel_xh2_qwen3_32b_256_32k_b1_4chips_2cores_v0.7.0_20251228"
}

Note that port 7901 mainly uses the default main process configuration. The following scenarios apply:

1) In a multi-card scenario, to dynamically create multiple process instances, you can continue sending requests to this port. The main process forks slave processes to load models.

2) If an LLM model is already running and you want to start sd3 text-to-image, you can also

*###startSD
POST*http://localhost:7901/models/load
Content-Type:application/json {
"devices": "1",
"model_type": "sd",
"params": {
"vae_model": "D:/workspace/models/SD3/vae.hmm",
"t5_model": "D:/workspace/models/SD3/t5.hmm",
"clip_model": "D:/workspace/models/SD3/clip.hmm",
"clip_l_model": "D:/workspace/models/SD3/clip_l.hmm",
"mmdit_model": "D:/workspace/models/SD3/mmdit.hmm",
}
}

The devices field above specifies card 1. If you do not want to specify it manually, configure "devices": "undefined", and the service automatically allocates from the existing devices.

3.3.2 Unloading a Model

*POST*http://10.65.35.16:7901/models/unload
Content-Type:application/json {
"model_type": "llm"
}

Note that port 7901 is configured according to each inference service process instance.

3.3.3 Stopping Service Instance Processes

*###stop
POST*http://localhost:7901/hlie/v1/stop
Content-Type:application/json {
"instance_id": 0,
"process_id": 0
}

If instance_id is 0, all models of the main process are stopped and unloaded.

If instance_id > 0 and process_id > 0, the main process finds the child process and kills it.

Note that the interface does not kill the main process; it only unloads all models of the main process. The main process stays resident.

3.3.4 Getting Information for All Service Instances

*###status
GET*http://localhost:7901/hlie/v1/status
Content-Type:application/json

3.4 Inference Scheduling with HLAWUtility

As shown below, in the inference scheduling item, you can drag a downloaded local model from the left list into the LLM box on the right to load the model into the inference service.

Switch to the inference scheduling item, refresh, and drag the corresponding model from the model list to Drop model here on the right. When the indication appears, the model has been loaded. The yellow button can unload the model. (7901 indicates the port.)

3.5 Auto-Loading Models

The auto_load configuration exists in the model area of the sys.cfg configuration file and defaults to true. When it is enabled, Completions/Embeddings automatically load the model according to the model parameter in the request and respond to the corresponding request.

[model]
cur_model=D:\workspace\models\
default = HiModel_xh2_qwen3_8b_256_16k_b4_1chip_2cores_v0.7.0_20251228
default_mmproj=
# 是否默认加载SD3
enable_sd3=true
# 针对LLM配置为true时,相关Completions/Embeddings会根据接口中的model参数去自动加载模型
auto_load=true
# LLM模型懒加载
llm_lazy_mode=false

3.6 Logs

The inference service provides real-time log information in the terminal. If errors occur during service startup, view the related log information for simple troubleshooting. Request and response data pairs are also written to log files for later review and troubleshooting; logs are stored in the log folder with the .log extension.

The log file path defaults to C:\ProgramData\AI\HLIECpp\logs\

You can also go directly to it via the Log Directory button on the HLAWUtility home page.

Log files are named [type]-[instance-id]-[YYYY-MM-DD].log

type is currently divided into access and -llm

access is the HTTP request log

-llm is the business log

4. Practical Scenarios

4.1 Starting Text + Text-to-Image in a Single Instance

sys.cfg

[server]
port=7901
# 设备ID, 以数字表示,多个设备用逗号隔开
devices=0, 1
# 实例副本数量,会启动多个进程,端口会递增+1, 用于负载均衡,多个设备同时运行同一种模型
replicas=1 [log]
# debug, info, warn, info
level=info # 4-debug, 3-warn, 2-error 1-info
tcim_level=2 # max files to keep
max_files=7
location=C:\ProgramData\AI\HLIECpp\logs\ [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja=
--reasoning-format=none
#--reasoning_budget = 0 [model]
cur_model=D:\workspace\models\
default = HiModel_xh2_qwen3_8b_256_16k_b4_1chip_2cores_v0.7.0_20251228
default_mmproj=
# 是否默认加载SD3
enable_sd3=true
# 针对LLM配置为true时,相关Completions/Embeddings会根据接口中的model参数去自动加载模型
auto_load=true
# LLM模型懒加载
llm_lazy_mode=false

Model directory D:\workspace\models\

{
"ModelType" : "SD3",
"MMDitModel" : "SD3/mmdit.hmm",
"ClipModel" : "SD3/clip.hmm",
"ClipLModel" : "SD3/clip_l.hmm",
"T5Model" : "SD3/t5.hmm",
"VaeModel" : "SD3/vae.hmm"
}

With the above configuration, text and text-to-image models can be loaded on two cards and inferenced at the same time.

The default_mmproj in the configuration file can be left empty because the service automatically matches the corresponding mmproj file by name. If multiple mmproj files with the same version and build time but different resolutions exist, you need to specify the exact mmproj name.

At this point, you only need to configure the corresponding model Provider on HLChatDesktop to chat with text and text-to-image at the same time.

4.2 Load Balancing Mode (Same Model)

sys.cfg

replicas = 2 below means starting two processes that load the same model.

On machines with limited memory, you can configure memory_saving = true for testing.

[server]
port=7901
# 设备ID, 以数字表示,多个设备用逗号隔开
devices=0, 1
# 实例副本数量,会启动多个进程,端口会递增+1, 用于负载均衡,多个设备同时运行同一种模型
replicas=2
# 用于多实例场景下节省内存使用,true时多实例的模型加载会有一定时间等待,达成串行效果
memory_saving=true [log]
# debug, info, warn, info
level=info # 4-debug, 3-warn, 2-error 1-info
tcim_level=2 # max files to keep
max_files=7
location=C:\ProgramData\AI\HLIECpp\logs\ [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja=
--reasoning-format=none
#--reasoning_budget = 0 [model]
# 模型目录
cur_model=D:\workspace\models\
# 默认LLM/WHISPER模型,不带格式后缀
default=HiModel_xh2_qwen3_8b_256_16k_b4_1chip_2cores_v0.7.0_20251228
default_mmproj=
# 是否默认加载SD3
enable_sd3=false
# 针对LLM配置为true时,相关Completions/Embeddings会根据接口中的model参数去自动加载模型
auto_load=true
# LLM模型懒加载
llm_lazy_mode=false

Currently, multi-instance requires an even distribution of devices. For example, with 2 cards and 2 instances, each instance can only get one card.

*// 每个实例获取的NPU数量, 因为每个实例可以同时运行生文和生图
int *acquires_count = device_count / replicas;

4.3 Embedding

Embedding models are currently loaded in the same way as LLMs. Supported model types include bge and gte, for example

HiModel_xh2_bge-m3_1.1b_512_512_b10_1chip_2cores_v0.7.0_20251231.gguf

HiModel_xh2_gte_1.5b_256_1chip_2cores_v0.7.0_20251228.gguf

Usage:

Modify the default model in the sys.cfg configuration file as shown below to use HiModel_xh2_gte_1.5b_256_1chip_2cores_v0.7.0_20251228

You can also load it in HLAWUtility inference scheduling.

The model name must contain the bge or gte field.

[model]
cur_model=D:\workspace\models\
default = HiModel_xh2_gte_1.5b_256_1chip_2cores_v0.7.0_20251228
default_mmproj=
# 是否默认加载SD3
enable_sd3=false
# 针对LLM配置为true时,相关Completions/Embeddings会根据接口中的model参数去自动加载模型
auto_load=true
# LLM模型懒加载
llm_lazy_mode=false

Supported endpoints: /embeddings, /v1/embeddings (OpenAI compatible)

POST example:

POSThttp://localhost:7901/v1/embeddings
Content-Type:application/json {
"model": "HiModel_xh2_gte_1.5b_256_1chip_2cores_v0.7.0_20251228",
"input": "这是一段测试的文本",
"n_tokens": 5
}

4.4 Specifying Devices for a Model (Default Single-Instance Scenario)

### start
POSThttp://localhost:7901/hlie/v1/start
Content-Type:application/json {
"devices": "1",
"model": "HiModel_xh2_qwen3-vl_4b_256_32k_b1_1chip_2cores_v0.7.0_20251220",
}

The above scenario requires the corresponding card configuration in the HLIECpp sys.cfg:

[server]
port=7901
# 设备ID, 以数字表示,多个设备用逗号隔开
devices=0,1
# 实例副本数量,会启动多个进程,端口会递增+1, 用于负载均衡,多个设备同时运行同一种模型 ### 其他配置
### ......

4.6 llama Parameter Tuning

According to the service configuration file described in section 2.2, the llm_params section can add llama-related parameter configurations.

Such as --repeat-penalty, --presence-penalty, --frequency-penalty, --repeat-last-n, --top-k, --top-p, --temp, and so on.

sys.cfg

#之前的配置 [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja=
--reasoning-format=none
#--reasoning_budget = 0 #继续之后的内容

4.6.1 Deep Thinking Configuration

You can add parameters in the llm_params area of the configuration file.

Setting --reasoning_budget = 0 avoids deep thinking.

#之前的配置 [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja=
--reasoning-format=none
--reasoning_budget=0 #继续之后的内容

4.6.2 Key llama.cpp Sampling Parameters

ParameterMeaningMechanismCommon RangeEffect
--repeat-penaltyRepetition penaltyLowers the probability of tokens the model repeats1.0 \~ 1.5Higher values avoid repetition more, but too high may cause broken output or strange words
--presence-penaltyPresence penaltyLowers the probability of a token that has already appeared0.0 \~ 2.0Increases topic coverage and reduces repetition, but may deviate from the topic
--frequency-penaltyFrequency penaltyPenalizes a token by how many times it appears0.0 \~ 2.0Controls repeated words and avoids redundancy
--repeat-last-nRepetition detection rangeApplies the repetition penalty within the last N tokens0 \~ 4096Larger values prevent repetition more globally; too large increases the penalty and affects fluency
--top-kTop-K samplingSelects the next token only from the K highest-probability candidates20 \~ 100Limits the selection space; too large can be verbose, too small can be rigid
--top-pTop-P (nucleus sampling)Keeps candidates whose cumulative probability is ≤ P, then samples randomly0.7 \~ 0.95Larger is more diverse, smaller is more deterministic
--tempTemperatureControls the smoothness of the probability distribution0.2 \~ 1.5Larger is more random, smaller is more conservative

4.6.3 Recommended Configurations for Different Scenarios

  1. Meeting minutes (stable, concise)

[llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja =
--reasoning-format = none
--reasoning_budget = 0
--repeat-penalty = 1. 2
--presence-penalty = 0. 2
--frequency-penalty = 0. 2
--repeat-last-n = 256
--top-k = 40
--top-p = 0. 9
--temp = 0. 5
  1. Writing drafts (creative and diverse)

[llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja =
--reasoning-format = none
--reasoning_budget = 0
--repeat-penalty = 1. 05
--presence-penalty = 0. 8
--frequency-penalty = 0. 5
--repeat-last-n = 512
--top-k = 80
--top-p = 0. 95
--temp = 0. 8
  1. Chatbot (natural, interactive)

[llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja =
--reasoning-format = none
--repeat-penalty = 1. 1
--presence-penalty = 0. 6
--frequency-penalty = 0. 3
--repeat-last-n = 256
--top-k = 50
--top-p = 0. 9
--temp = 0. 7

4.7 ASR Support

Whisper-Medium and Whisper-Large-v3-Turbo models are now supported.

You can download the corresponding models from model management, for example

4.7.1 Model Loading

  • Curl command:

curl -X POST "http://localhost:7901/hlie/v1/start" \
-H "Content-Type: application/json" \
-d '{ "model_type": "whisper", "model": "HiModel_xh2_whisper-medium_1.5b_256_1chip_2cores_v1.0.0_20260228" }'
  • AI Assistant:

4.7.2 HTTP Inference

curl-XPOST "http://127.0.0.1:7901/v1/audio/transcriptions" \
-H "Content-Type: multipart/form-data" \
-F"file=@E:/test_data/audio/long_2.wav"

4.7.3 WebSocket Inference

You can use a related script or service to connect to "ws://127.0.0.1:7999".

Then send the audio as a float32 byte stream in order and end with the string EOS for inference.

Reference Python script:

#!/usr/bin/env python3 # -*- coding: utf-8 -*- *"""*
* Whisper.cpp / miniaudio Compatible WebSocket Audio Stream Client* *功能:*
* 1. 读取 wav 音频*
* 2. 转 mono*
* 3. 重采样到 16k*
* 4. 转 float32 PCM [-1,1]*
* 5. websocket 流式发送* * 目标:*
* 与 whisper.cpp 中 miniaudio 的行为尽可能一致* * 数据格式:*
* float32 PCM*
* 16000Hz*
* mono* *发送协议:*
* binary:*
* float32 PCM bytes* * text:*
* EOS*
* """* import asyncio
import time
from pathlib import Path import numpy as np
import soundfile as sf
import websockets
from loguru import logger
from scipy import signal # ============================================================================= # Config # ============================================================================= TARGET_SAMPLE_RATE = 16000 # 1000ms chunk
CHUNK_DURATION_MS = 1000 # websocket uri
WS_URI = "ws://10.65.32.191:7999" # audio file
AUDIO_FILE = "D:/workspace/wtt//llm/hi.cpp/samples/zero_shot_prompt.wav" # ============================================================================= # Logger # ============================================================================= logger. remove () logger. add ( sink=lambda msg : print (msg, end=""), level="INFO", format=( "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | " "<level>{level: </level> | " "{message}" ),) logger. add ( "asr_websocket_test.log", level="DEBUG", rotation="10 MB", retention=5, encoding="utf-8",) # ============================================================================= # Audio Process # ============================================================================= def load_audio (file_path : str) -> np. ndarray : *"""*
* 加载音频并转换成:* * float32*
* mono*
* 16000Hz*
* [-1,1]* * 尽量模拟 miniaudio 行为*
* """* * *logger. info (f"Loading audio:{file_path}") # soundfile: # int16 wav -> int16 # float wav -> float data, sample_rate = sf. read (file_path) logger. info ( f"Original audio info: " f"sample_rate={sample_rate}, " f"shape={data.shape}, " f"dtype={data.dtype}" ) # ========================================================================= # Convert to mono # ========================================================================= if data. ndim > 1 : logger. info ( f"Convert multi-channel -> mono " f"(channels={data.shape[1]})" ) # IMPORTANT: # whisper.cpp/miniaudio: # left + right # # NOT: # (left + right) / 2 # # 这里使用 sum 更接近 whisper.cpp data = np. sum (data, axis=1) # ========================================================================= # Resample to 16k # ========================================================================= if sample_rate != TARGET_SAMPLE_RATE : logger. info ( f"Resample audio: " f"{sample_rate}Hz ->{TARGET_SAMPLE_RATE}Hz" ) num_samples = int ( len (data) * TARGET_SAMPLE_RATE / sample_rate ) data = signal. resample ( data, num_samples,) sample_rate = TARGET_SAMPLE_RATE # ========================================================================= # Convert to float32 # ========================================================================= if data. dtype == np. int16 : logger. info ("Convert int16 -> float32") data = data. astype (np. float32) / 32768.0 elif data. dtype == np. int32 : logger. info ("Convert int32 -> float32") data = data. astype (np. float32) / 2147483648.0 elif data. dtype != np. float32 : logger. info (f"Convert{data.dtype} -> float32") data = data. astype (np. float32) # ========================================================================= # Clip # ========================================================================= # 防止 stereo 相加后超过 [-1,1] data = np. clip (data, -1.0, 1.0) duration = len (data) / TARGET_SAMPLE_RATE logger. success ( f"Audio ready: " f"samples={len(data)}, " f"duration={duration:.2f}s, " f"dtype={data.dtype}" ) return data # ============================================================================= # WebSocket Stream # ============================================================================= async def stream_audio ( websocket, pcmf32 : np. ndarray,): *"""*
* websocket 流式发送 float32 PCM*
* """* * *chunk_size = int ( TARGET_SAMPLE_RATE * CHUNK_DURATION_MS / 1000 ) total_chunks = ( len (pcmf32) + chunk_size - 1 ) // chunk_size logger. info ( f"Start streaming: " f"chunk_duration={CHUNK_DURATION_MS}ms, " f"chunk_size={chunk_size}, " f"total_chunks={total_chunks}" ) start_time = time. time () for chunk_index, start in enumerate ( range (0, len (pcmf32), chunk_size), start=1,): end = start + chunk_size chunk = pcmf32 [start : end] # binary float32 pcm binary = chunk. astype (np. float32). tobytes () await websocket. send (binary) chunk_duration = ( len (chunk) / TARGET_SAMPLE_RATE ) logger. info ( f"[Chunk{chunk_index}/{total_chunks}] " f"samples={len(chunk)}, " f"bytes={len(binary)}, " f"duration={chunk_duration:.3f}s" ) # 模拟真实实时发送 await asyncio. sleep (chunk_duration) elapsed = time. time () - start_time logger. success ( f"Audio stream completed (elapsed={elapsed:.2f}s)" ) # ============================================================================= # Main # ============================================================================= async def simulate_frontend_stream ( file_path : str, uri : str,): if not Path (file_path). exists (): logger. error ( f"Audio file not found:{file_path}" ) return # load audio pcmf32 = load_audio (file_path) logger. info (f"Connecting websocket:{uri}") try : async with websockets. connect ( uri, max_size=20 * 1024 * 1024, ping_interval=20, ping_timeout=20,) as websocket : logger. success ("WebSocket connected") # stream audio await stream_audio ( websocket, pcmf32,) # EOS logger. info ("Sending EOS") await websocket. send ("EOS") # wait result logger. info ("Waiting ASR result...") result = await asyncio. wait_for ( websocket. recv (), timeout=30.0,) logger. success ( f"ASR Result:\n{result}" ) except asyncio. TimeoutError : logger. error ( "Timeout waiting ASR result" ) except websockets. ConnectionClosed as e : logger. error ( f"WebSocket closed: " f"code={e.code}, " f"reason={e.reason}" ) except Exception as e : logger. exception ( f"Unexpected error:{e}" ) finally : logger. info ("Test finished") # ============================================================================= # Entry # ============================================================================= if __name__ == "__main__" : asyncio. run ( simulate_frontend_stream ( AUDIO_FILE, WS_URI,) )

4.8 TTS Support

TTS currently only supports the CosyVoice3 model.

4.8.1 Model Loading

  • Curl command:

curl -X POST "http://localhost:7901/hlie/v1/start" \
-H "Content-Type: application/json" \
-d '{ "model_type": "cosyvoice", "model": "HiModel_xh2_cosyvoice3_0.5b_1chip_2cores_v1.1.0-20260409" }'
  • AI Assistant:

4.8.2 HTTP Inference

curl -X POST "http://localhost:7901/v1/audio/speech" \
-H "Content-Type: application/json" \
--max-time 600 \
-d '{ "input": "君不见,黄河之水天上来,奔流到海不复回。君不见,高堂明镜悲白发,朝如青丝暮成雪!人生得意须尽欢,莫使金樽空对月。天生我材必有用,千金散尽还复来。烹羊宰牛且为乐,会须一饮三百杯。岑夫子,丹丘生,将进酒,杯莫停。与君歌一曲,请君为我倾耳听。钟鼓馔玉不足贵,但愿长醉不复醒。古来圣贤皆寂寞,惟有饮者留其名。陈王昔时宴平乐,斗酒十千恣欢谑。主人何为言少钱,径须沽取对君酌。五花马、千金裘,呼儿将出换美酒,与尔同销万古愁!", "prompt_wav_path": "E:/test_data/tts/zero_shot_0.wav", "prompt_text": "八百标兵奔北坡,北坡炮兵并排跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。" }'

Among the above parameters, the audio of prompt_wav_path must be aligned one-to-one with the text of prompt_text. Of course, both parameters can also be omitted, for example:

In the following way, the system's built-in default prompt is used during inference.

curl -X POST "http://localhost:7901/v1/audio/speech" \
-H "Content-Type: application/json" \
--max-time 600 \
-d '{ "input": "君不见,黄河之水天上来,奔流到海不复回。君不见,高堂明镜悲白发,朝如青丝暮成雪!人生得意须尽欢,莫使金樽空对月。天生我材必有用,千金散尽还复来。烹羊宰牛且为乐,会须一饮三百杯。岑夫子,丹丘生,将进酒,杯莫停。与君歌一曲,请君为我倾耳听。钟鼓馔玉不足贵,但愿长醉不复醒。古来圣贤皆寂寞,惟有饮者留其名。陈王昔时宴平乐,斗酒十千恣欢谑。主人何为言少钱,径须沽取对君酌。五花马、千金裘,呼儿将出换美酒,与尔同销万古愁!" }'

5. Service Troubleshooting

  1. Installation failure: check the current user's operation permission on the C drive and make sure new files can be created by default.

  2. Startup failure:

    1. Check the corresponding logs.

    The default service log path is: C:\ProgramData\AI\HLIECpp\logs\

    The default system log path is: C:\Program Files\AI\HLIECpp\bin\boot_log

    1. Debug Console

    Open a command prompt, navigate to the bin directory of the installation directory, and run debug.bat

    C:\Program Files\AI\HLIECpp\bin\debug.bat

    After running it, check whether there are unexpected errors.

  3. API failure: check the returned message and system logs.

  4. For other problems that cannot be located, contact support.

C++ inference service framework (Linux) aggregating multiple inference components with standardized OpenAI interfaces and high-performance serving.

1. Basic Information

1.1 Version History

VersionDateDescription
v2.1.0-PreviewJune 2026Based on HLIELLama, supports the following features:
- Speculative decoding (Draft Model/MTP) [experimental]
- Inference optimization for the full Qwen3.6/Qwen3.5 model family
- CoPaw-series model support
- Gamma4-series model support
- Qwen3 Embedding and Reranker model support
- GLM-OCR model support
- Qwen3-asr and GLM-asr speech model support
v2.0.0May 2026- Supports TTS model inference channels and TTS interface protocols (cosyvoice3)
- Supports WebSocket protocol output for speech models (whisper)
- Supports the think parameter for GPT OSS models
- Supports inference for Qwen3.5-series text and multimodal models
- Supports --list-devices and --dev card binding
- Supports qwen3-embedding, qwen3-rerank, and qwen3.5 models
v1.7.0March 2026- Version v1.0.0 update
- Supports speech recognition interface protocols
- Supports bge model inference
- Supports Lora models
- Integrates HLIEWhisperCpp for whisper speech models
- Supports running multiple cards and models simultaneously with load distribution
v1.6.0January 2026- Supports KV cache reuse in single-user multi-turn conversations
- Supports automatic VL model matching
- Updates the default model loading configuration
v1.6.0-alphaDecember 2025- Supports Qwen3-30B-A3B [M50]
- Supports Qwen3-Coder-30B-A3B [M50]
- Supports Qwen3 VL 4B [M30][M50]
- Supports Qwen3 VL 8B [M50]
- Supports the MinP and presence_penalty parameters
1.5.020251013- Adds a configuration and management UI, integrated with HLAWModel; supports model inference scheduling and NPU status queries
- Multi-batch support
- Supports running with no model loaded; models can be dynamically loaded and unloaded through RESTful API requests; supports multi-instance scenarios
- Fixes legacy Jira bugs
- Updates the chain-of-thought switch
1.4.020250815- Switches dependencies to a customized llama.cpp
- Supports text + text-to-image (Xh2+SD3)
- Supports multi-instance deployment
- Independent request logs
- Supports Qwen2.5VL
- Supports configuring the tcim log level from the hi.cpp configuration file
1.3.020250606The run package supports ubuntu2004 and Kylin v10 sp1; adds demo examples and instructions

1.2 Document Purpose

This document helps you quickly connect to and start the inference service on Linux.

2. Supported Model Deployment Packages

2.1 Supported Model Deployment Packages

The full package name format is: HiModel-<model_type>[-vl]-<param_size>-p256-<context_size>-<batch_size>-<core_num>-<device_size>-<target>-<sys_version>-<build_time>.gguf

  • model_type indicates the model type.

    • DeepSeek: the deployment package is a DeepSeek-r1 model.

    • Qwen2.5: the deployment package is a QWen2.5 model.

    • Qwen3: the deployment package is a QWen3 model.

  • [-vl] indicates multimodal.

  • param_size indicates the model parameters, such as 4b.

  • context_size indicates the context size, such as 2K.

  • batch_size indicates the batch inference capability, such as 1b or 2b.

  • core_num indicates the number of IPU cores the model is built for, such as 2core.

  • device_size indicates how many AI chips are needed to load and run the model, such as 1d or 2d.

  • target indicates the hardware platform, such as xh1 or xh2.

  • sys_version indicates the hardware version the model was compiled against, such as v0.7.0.

  • build_time indicates the build time, such as 20260105154602.

Example: HiModel-Qwen3-vl-4b-p256-2K-b1-2core-1d-xh2-v0.7.0-20260105154602.gguf

Please keep the model file name intact when using the service.

2.2 Model Download

Users can download models from the designated model website: https://llm.bee-link.cn/

2.3 Model Package Adaptation

HLIECpp model packages are currently based on llama-cpp models and use the GGUF format.

models/
$ tree
.
|-- HiModel-Qwen3-8b-p256-2K-b1-2core-1d-xh2-v0.7.0-20260105154602.gguf

Manually configuring SD3 models (skip if not needed)

Due to the current characteristics of SD3 models, they can only be configured by manually downloading them and creating a JSON information file.

Example SD3 image generation model directory:

models/
$ tree
.
├── SD3
│ ├── clip.hmm
│ ├── clip_l.hmm
│ ├── mmdit.hmm
│ ├── t5.hmm
│ └── vae.hmm
└── sd3.json
...

Create a JSON file to describe the SD3 model information:

{
"ModelType" : "Sd3",
"XHVersion" : 2,
"ClipModel" : "./SD3/clip.hmm",
"ClipLModel" : "./SD3/clip_l.hmm",
"T5Model" : "./SD3/t5.hmm",
"MMDitModel" : "./SD3/mmdit.hmm",
"VaeModel" : "./SD3/vae.hmm"
}

Save it as a json file containing the sd3 keyword in the configured model directory.

2.4 Configuring the Default Inference Model

The model loading path is specified through the configuration file. To change it, modify the cur_model value in the sys.cfg file at the path below:

/opt/HLIECpp/config/sys.cfg

[server]
port=7901
# 设备ID, 以数字表示,默认只有0,多个设备用逗号隔开, 如 0,1
devices=0
# 实例副本数量,会启动多个进程,端口会递增+1, 用于负载均衡,多个设备同时运行同一种模型
replicas=1
# 用于多实例场景下节省内存使用,true时多实例的模型加载会有一定时间等待,达成串行效果
memory_saving=false [log]
# debug, info, warn, info
level=info # 4-debug, 3-warn, 2-error 1-info
tcim_level=2
# max files to keep
max_files=7
# Just for Windows Mode, Linux Service use fixed path: /var/log//HLIECpp
location=/var/log//HLIECpp # SDK & Demo using
open_console_window=true [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja=
--reasoning-format=none
#--reasoning_budget = 0 [model]
# 模型目录
cur_model=/opt//models
# 默认LLM/WHISPER模型,不带格式后缀
default=HiModel-Qwen3-vl-4b-p256-2K-b1-2core-1d-xh2-v0.7.0-20260105154602
default_mmproj=
# 是否默认加载SD3
enable_sd3=false
# 针对LLM配置为true时,相关Completions/Embeddings会根据接口中的model参数去自动加载模型
auto_load=true
# LLM模型懒加载
llm_lazy_mode=false

The default_mmproj in the configuration file can be left empty because the service automatically matches the corresponding mmproj file by name. If multiple mmproj files with the same version and build time but different resolutions exist, you need to specify the exact mmproj name.

After the modification, restart the HLIECpp service:

sudo systemctl daemon-reload

sudo systemctl restart HLIECpp.service

3. Installation

Download the run installer for your platform from the inference framework section of the Beelink AI website (https://llm.bee-link.cn/frameworks.php). For Linux x86_64:

sudo ./houmo-HLIECpp_xh2_2_1_0_linux_x86_64.run

After installation, the inference service starts automatically. Run the following command to check whether the service started normally:

sudo systemctl status HLIECpp

Note: Make sure the models folder path and content in Section 2 are correct; otherwise the command above may fail with a loadmodel error.

4. Managing the Service

sudo systemctl start HLIECpp      # Start the service (already started after installing the run package, no need to start again)
sudo systemctl stop HLIECpp       # Stop the service
sudo systemctl restart HLIECpp    # Restart the service
sudo systemctl status HLIECpp     # Check the status

5. Uninstallation

sudo systemctl stop HLIECpp
sudo systemctl disable HLIECpp
sudo rm /etc/systemd/system/HLIECpp.service
sudo systemctl daemon-reload

Whether to run the following command depends on your situation. Note that the model files are large; do not delete them casually:

sudo rm -rf /opt/HLIECpp

6. Using the Service

  • API access address: http://ip:7901

Currently, the backend API default port is 7901 and can be changed through the configuration file (the service must be restarted).

In multi-instance scenarios, the port increments by 1 for each instance; for example, 4 instances use ports 7901, 7902, 7903, 7904.

Currently, the service supports running with no default model configured, and models can be loaded and unloaded dynamically.

6.1 Dynamically Loading a Model

*POSThttp://localhost:7901/models/load
Content-Type:application/json {
"model": "HiModel-Qwen3-vl-4b-p256-2K-b1-2core-1d-xh2-v0.7.0-20260105154602"
}*

Note that port 7901 mainly uses the default main process configuration. The following scenarios apply:

1) In a multi-card scenario, to dynamically create multiple process instances, you can continue sending requests to this port. The main process forks slave processes to load models.

2) If an LLM model is already running and you want to start sd3 text-to-image, you can also

*POSThttp://localhost:7901/models/load
Content-Type:application/json {
"devices": "1",
"model_type": "sd",
"params": {
"vae_model": "SD3/vae.hmm",
"t5_model": "SD3/t5.hmm",
"clip_model": "SD3/clip.hmm",
"clip_l_model": "SD3/clip_l.hmm",
"mmdit_model": "SD3/mmdit.hmm",
}
}*

The devices field above specifies card 1. If you do not want to specify it manually, configure "devices": "undefined" or omit this parameter, and the service automatically allocates from the existing devices.

6.2 Dynamically Unloading a Model

*POSThttp://localhost:7901/hlie/v1/unload_model
Content-Type:application/json {
"model_type": "llm"
}*
curl-XPOSThttp://*localhost*:7901/hlie/v1/unload_model-H "Content-Type: application/json"-d '{"model_type": "llm"}'

Note that port 7901 is configured according to each inference service process instance.

6.3 Stopping Service Instance Processes

*POST*http://localhost:7901/hlie/v1/stop
Content-Type:application/json {
"instance_id": 0,
"process_id": 0
}

If instance_id is 0, all models of the main process are stopped and unloaded.

If instance_id > 0 and process_id > 0, the main process finds the child process and kills it.

Note that the interface does not kill the process; it only unloads all models of the main process.

6.4 Getting Information for All Service Instances

*GET*http://localhost:7901/hlie/v1/status
Content-Type:application/json

7. Practical Scenarios

7.1 Starting Text + Text-to-Image in a Single Instance

sys.cfg

[server]
port=7901
# 设备ID, 以数字表示,默认只有0,多个设备用逗号隔开, 如 0,1
devices=0,1
# 实例副本数量,会启动多个进程,端口会递增+1, 用于负载均衡,多个设备同时运行同一种模型
replicas=1
# 用于多实例场景下节省内存使用,true时多实例的模型加载会有一定时间等待,达成串行效果
memory_saving=false [log]
# debug, info, warn, info
level=info # 4-debug, 3-warn, 2-error 1-info
tcim_level=2
# max files to keep
max_files=7
# Just for Windows Mode, Linux Service use fixed path: /var/log//HLIECpp
location=/var/log//HLIECpp # SDK & Demo using
open_console_window=true [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja=
--reasoning-format=none
#--reasoning_budget = 0 [model]
cur_model=/opt//models
default=HiModel_xh2_qwen3_8b_256_16k_b4_1chip_2cores_v0.7.0_20251228
default_mmproj=
# 是否默认加载SD3
enable_sd3=true
# 针对LLM配置为true时,相关Completions/Embeddings会根据接口中的model参数去自动加载模型
auto_load=true
# LLM模型懒加载
llm_lazy_mode=false

The model directory /opt/HLIECpp/models must contain HiModel_xh2_qwen3_8b_256_16k_b4_1chip_2cores_v0.7.0_20251228.gguf.

sd3_model.json

{
"ModelType" : "SD3",
"MMDitModel" : "SD3/mmdit.hmm",
"ClipModel" : "SD3/clip.hmm",
"ClipLModel" : "SD3/clip_l.hmm",
"T5Model" : "SD3/t5.hmm",
"VaeModel" : "SD3/vae.hmm"
}

At this point, you only need to configure the corresponding model Provider on HLChatDesktop to chat with text and text-to-image at the same time.

7.2 Starting Multiple Instances

sys.cfg

replicas = 2 below means starting two processes that load the same model.

On machines with limited memory, you can configure memory_saving = true for testing.

[server]
port=7901
# 设备ID, 以数字表示,默认只有0,多个设备用逗号隔开, 如 0,1
devices=0,1
# 实例副本数量,会启动多个进程,端口会递增+1, 用于负载均衡,多个设备同时运行同一种模型
replicas=2
# 用于多实例场景下节省内存使用,true时多实例的模型加载会有一定时间等待,达成串行效果
memory_saving=false [log]
# debug, info, warn, info
level=info # 4-debug, 3-warn, 2-error 1-info
tcim_level=2
# max files to keep
max_files=7
# Just for Windows Mode, Linux Service use fixed path: /var/log//HLIECpp
location=/var/log//HLIECpp # SDK & Demo using
open_console_window=true [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja=
--reasoning-format=none
#--reasoning_budget = 0 [model]
cur_model=/opt//models
# 默认LLM/WHISPER模型,不带格式后缀
default=HiModel_xh2_qwen3_8b_256_16k_b4_1chip_2cores_v0.7.0_20251228
# 是否默认加载SD3
default_mmproj=
enable_sd3=false
# 针对LLM配置为true时,相关Completions/Embeddings会根据接口中的model参数去自动加载模型
auto_load=true
# LLM模型懒加载
llm_lazy_mode=false

Currently, multi-instance requires an even distribution of devices. For example, with 2 cards and 2 instances, each instance can only get one card.

*// 每个实例获取的NPU数量, 因为每个实例可以同时运行生文和生图
int *acquires_count = device_count / replicas;

7.3 Multimodal Scenarios

Download the corresponding model to the specified model directory:

For example, /opt/HLIECpp/models contains:

HiModel_xh2_qwen3-vl_4b_256_32k_b1_1chip_2cores_v0.7.0_20251228.gguf

mmproj_xh2_qwen3-vl_4b_2cores_vit_448x448_v0.7.0_20251228.gguf

To start with the service by default, change the default field under [model] in sys.cfg to the corresponding main model name.

[model]
cur_model=/opt//models
default=HiModel_xh2_qwen3-vl_4b_256_32k_b1_1chip_2cores_v0.7.0_20251228
default_mmproj=
enable_sd3=false

The default_mmproj in the configuration file can be left empty because the service automatically matches the corresponding mmproj file by name. If multiple mmproj files with the same version and build time but different resolutions exist, you need to specify the exact mmproj name.

7.4 Embedding

Embedding models are currently loaded in the same way as LLMs. Supported model types include bge and gte, for example

HiModel_xh2_bge-m3_1.1b_512_512_b10_1chip_2cores_v0.7.0_20251231.gguf

HiModel_xh2_gte_1.5b_256_1chip_2cores_v0.7.0_20251228.gguf

Usage:

Modify the default model in the sys.cfg configuration file as shown below to use HiModel_xh2_gte_1.5b_256_1chip_2cores_v0.7.0_20251228

You can also load it in HLAWUtility inference scheduling.

The model name must contain the bge or gte field.

[model]
cur_model=/opt//models
default=HiModel_xh2_gte_1.5b_256_1chip_2cores_v0.7.0_20251228
default_mmproj=
# 是否默认加载SD3
enable_sd3=false
# 针对LLM配置为true时,相关Completions/Embeddings会根据接口中的model参数去自动加载模型
auto_load=true
# LLM模型懒加载
llm_lazy_mode=false

Then restart the HLIECpp service.

Supported endpoints: /embeddings, /v1/embeddings (OpenAI compatible)

POST example:

POSThttp://localhost:7901/v1/embeddings
Content-Type:application/json {
"model": "HiModel_xh2_gte_1.5b_256_1chip_2cores_v0.7.0_20251228",
"input": "这是一段测试的文本",
"n_tokens": 5
}

7.5 Specifying Devices for a Model (Default Single-Instance Scenario)

### start
POST http://localhost:7901/hlie/v1/start
Content-Type: application/json { "devices": "1", "model": "HiModel_xh2_qwen3-vl_4b_256_32k_b1_1chip_2cores_v0.7.0_20251220",
}

You can also rely on the service configuration and only configure devices = 1.

Service Configuration

The above scenario requires the corresponding card configuration in the HLIECpp sys.cfg:

[server]
port=7901
# 设备ID, 以数字表示,多个设备用逗号隔开
devices=0, 1
# 实例副本数量,会启动多个进程,端口会递增+1, 用于负载均衡,多个设备同时运行同一种模型 ### 其他配置
### ......

7.6 llama Parameter Tuning

The service configuration file has a llm_params section where llama-related parameter configurations can be added.

Such as --repeat-penalty, --presence-penalty, --frequency-penalty, --repeat-last-n, --top-k, --top-p, --temp, and so on.

sys.cfg

#之前的配置 [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
#--jinja =
#--reasoning_budget = 0 #继续之后的内容

7.6.1 Deep Thinking Configuration

sys.cfg

#之前的配置 [llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
#--jinja =
#--reasoning_budget = 0 #继续之后的内容

7.6.2 Key llama.cpp Sampling Parameters

ParameterMeaningMechanismCommon RangeEffect
--repeat-penaltyRepetition penaltyLowers the probability of tokens the model repeats1.0 \~ 1.5Higher values avoid repetition more, but too high may cause broken output or strange words
--presence-penaltyPresence penaltyLowers the probability of a token that has already appeared0.0 \~ 2.0Increases topic coverage and reduces repetition, but may deviate from the topic
--frequency-penaltyFrequency penaltyPenalizes a token by how many times it appears0.0 \~ 2.0Controls repeated words and avoids redundancy
--repeat-last-nRepetition detection rangeApplies the repetition penalty within the last N tokens0 \~ 4096Larger values prevent repetition more globally; too large increases the penalty and affects fluency
--top-kTop-K samplingSelects the next token only from the K highest-probability candidates20 \~ 100Limits the selection space; too large can be verbose, too small can be rigid
--top-pTop-P (nucleus sampling)Keeps candidates whose cumulative probability is ≤ P, then samples randomly0.7 \~ 0.95Larger is more diverse, smaller is more deterministic
--tempTemperatureControls the smoothness of the probability distribution0.2 \~ 1.5Larger is more random, smaller is more conservative

7.6.3 Recommended Configurations for Different Scenarios

  1. Meeting minutes (stable, concise)

[llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja =
--reasoning-format = none
--reasoning_budget = 0
--repeat-penalty = 1. 2
--presence-penalty = 0. 2
--frequency-penalty = 0. 2
--repeat-last-n = 256
--top-k = 40
--top-p = 0. 9
--temp = 0. 5
  1. Writing drafts (creative and diverse)

[llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja =
--reasoning-format = none
--reasoning_budget = 0
--repeat-penalty 1. 05
--presence-penalty 0. 8
--frequency-penalty 0. 5
--repeat-last-n 512
--top-k 80
--top-p 0. 95
--temp 0. 8
  1. Chatbot (natural, interactive)

[llm_params]
#llama-server的参数透传,请参考下面或者llamacpp的设置, 请使用完整option: --xxx = xx, 没有值的请留空
--jinja =
--reasoning-format = none
--repeat-penalty 1. 1
--presence-penalty 0. 6
--frequency-penalty 0. 3
--repeat-last-n 256
--top-k 50
--top-p 0. 9
--temp 0. 7

7.7 ASR Support

Whisper-Medium and Whisper-Large-v3-Turbo models are now supported.

You can download the corresponding models from model management, for example

7.7.1 Model Loading

  • Curl command:

curl -X POST "http://localhost:7901/hlie/v1/start" \
-H "Content-Type: application/json" \
-d '{ "model_type": "whisper", "model": "HiModel_xh2_whisper-medium_1.5b_256_1chip_2cores_v1.0.0_20260228" }'
  • AI Assistant:

7.7.2 HTTP Inference

curl-XPOST "http://127.0.0.1:7901/v1/audio/transcriptions" \
-H "Content-Type: multipart/form-data" \
-F"file=@E:/test_data/audio/long_2.wav"

7.7.3 WebSocket Inference

You can use a related script or service to connect to "ws://127.0.0.1:7999".

Then send the audio as a float32 byte stream in order and end with the string EOS for inference.

Reference Python script:

#!/usr/bin/env python3 # -*- coding: utf-8 -*- *"""*
* Whisper.cpp / miniaudio Compatible WebSocket Audio Stream Client* *功能:*
* 1. 读取 wav 音频*
* 2. 转 mono*
* 3. 重采样到 16k*
* 4. 转 float32 PCM [-1,1]*
* 5. websocket 流式发送* * 目标:*
* 与 whisper.cpp 中 miniaudio 的行为尽可能一致* * 数据格式:*
* float32 PCM*
* 16000Hz*
* mono* *发送协议:*
* binary:*
* float32 PCM bytes* * text:*
* EOS*
* """* import asyncio
import time
from pathlib import Path import numpy as np
import soundfile as sf
import websockets
from loguru import logger
from scipy import signal # ============================================================================= # Config # ============================================================================= TARGET_SAMPLE_RATE = 16000 # 1000ms chunk
CHUNK_DURATION_MS = 1000 # websocket uri
WS_URI = "ws://10.65.32.191:7999" # audio file
AUDIO_FILE = "D:/workspace/wtt//llm/hi.cpp/samples/zero_shot_prompt.wav" # ============================================================================= # Logger # ============================================================================= logger. remove () logger. add ( sink=lambda msg : print (msg, end=""), level="INFO", format=( "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | " "<level>{level: </level> | " "{message}" ),) logger. add ( "asr_websocket_test.log", level="DEBUG", rotation="10 MB", retention=5, encoding="utf-8",) # ============================================================================= # Audio Process # ============================================================================= def load_audio (file_path : str) -> np. ndarray : *"""*
* 加载音频并转换成:* * float32*
* mono*
* 16000Hz*
* [-1,1]* * 尽量模拟 miniaudio 行为*
* """* * *logger. info (f"Loading audio:{file_path}") # soundfile: # int16 wav -> int16 # float wav -> float data, sample_rate = sf. read (file_path) logger. info ( f"Original audio info: " f"sample_rate={sample_rate}, " f"shape={data.shape}, " f"dtype={data.dtype}" ) # ========================================================================= # Convert to mono # ========================================================================= if data. ndim > 1 : logger. info ( f"Convert multi-channel -> mono " f"(channels={data.shape[1]})" ) # IMPORTANT: # whisper.cpp/miniaudio: # left + right # # NOT: # (left + right) / 2 # # 这里使用 sum 更接近 whisper.cpp data = np. sum (data, axis=1) # ========================================================================= # Resample to 16k # ========================================================================= if sample_rate != TARGET_SAMPLE_RATE : logger. info ( f"Resample audio: " f"{sample_rate}Hz ->{TARGET_SAMPLE_RATE}Hz" ) num_samples = int ( len (data) * TARGET_SAMPLE_RATE / sample_rate ) data = signal. resample ( data, num_samples,) sample_rate = TARGET_SAMPLE_RATE # ========================================================================= # Convert to float32 # ========================================================================= if data. dtype == np. int16 : logger. info ("Convert int16 -> float32") data = data. astype (np. float32) / 32768.0 elif data. dtype == np. int32 : logger. info ("Convert int32 -> float32") data = data. astype (np. float32) / 2147483648.0 elif data. dtype != np. float32 : logger. info (f"Convert{data.dtype} -> float32") data = data. astype (np. float32) # ========================================================================= # Clip # ========================================================================= # 防止 stereo 相加后超过 [-1,1] data = np. clip (data, -1.0, 1.0) duration = len (data) / TARGET_SAMPLE_RATE logger. success ( f"Audio ready: " f"samples={len(data)}, " f"duration={duration:.2f}s, " f"dtype={data.dtype}" ) return data # ============================================================================= # WebSocket Stream # ============================================================================= async def stream_audio ( websocket, pcmf32 : np. ndarray,): *"""*
* websocket 流式发送 float32 PCM*
* """* * *chunk_size = int ( TARGET_SAMPLE_RATE * CHUNK_DURATION_MS / 1000 ) total_chunks = ( len (pcmf32) + chunk_size - 1 ) // chunk_size logger. info ( f"Start streaming: " f"chunk_duration={CHUNK_DURATION_MS}ms, " f"chunk_size={chunk_size}, " f"total_chunks={total_chunks}" ) start_time = time. time () for chunk_index, start in enumerate ( range (0, len (pcmf32), chunk_size), start=1,): end = start + chunk_size chunk = pcmf32 [start : end] # binary float32 pcm binary = chunk. astype (np. float32). tobytes () await websocket. send (binary) chunk_duration = ( len (chunk) / TARGET_SAMPLE_RATE ) logger. info ( f"[Chunk{chunk_index}/{total_chunks}] " f"samples={len(chunk)}, " f"bytes={len(binary)}, " f"duration={chunk_duration:.3f}s" ) # 模拟真实实时发送 await asyncio. sleep (chunk_duration) elapsed = time. time () - start_time logger. success ( f"Audio stream completed (elapsed={elapsed:.2f}s)" ) # ============================================================================= # Main # ============================================================================= async def simulate_frontend_stream ( file_path : str, uri : str,): if not Path (file_path). exists (): logger. error ( f"Audio file not found:{file_path}" ) return # load audio pcmf32 = load_audio (file_path) logger. info (f"Connecting websocket:{uri}") try : async with websockets. connect ( uri, max_size=20 * 1024 * 1024, ping_interval=20, ping_timeout=20,) as websocket : logger. success ("WebSocket connected") # stream audio await stream_audio ( websocket, pcmf32,) # EOS logger. info ("Sending EOS") await websocket. send ("EOS") # wait result logger. info ("Waiting ASR result...") result = await asyncio. wait_for ( websocket. recv (), timeout=30.0,) logger. success ( f"ASR Result:\n{result}" ) except asyncio. TimeoutError : logger. error ( "Timeout waiting ASR result" ) except websockets. ConnectionClosed as e : logger. error ( f"WebSocket closed: " f"code={e.code}, " f"reason={e.reason}" ) except Exception as e : logger. exception ( f"Unexpected error:{e}" ) finally : logger. info ("Test finished") # ============================================================================= # Entry # ============================================================================= if __name__ == "__main__" : asyncio. run ( simulate_frontend_stream ( AUDIO_FILE, WS_URI,) )

7.8 TTS Support

TTS currently only supports the CosyVoice3 model.

7.8.1 Model Loading

  • Curl command:

curl -X POST "http://localhost:7901/hlie/v1/start" \
-H "Content-Type: application/json" \
-d '{ "model_type": "cosyvoice", "model": "HiModel_xh2_cosyvoice3_0.5b_1chip_2cores_v1.1.0-20260409" }'
  • AI Assistant:

7.8.2 HTTP Inference

curl -X POST "http://localhost:7901/v1/audio/speech" \
-H "Content-Type: application/json" \
--max-time 600 \
-d '{ "input": "君不见,黄河之水天上来,奔流到海不复回。君不见,高堂明镜悲白发,朝如青丝暮成雪!人生得意须尽欢,莫使金樽空对月。天生我材必有用,千金散尽还复来。烹羊宰牛且为乐,会须一饮三百杯。岑夫子,丹丘生,将进酒,杯莫停。与君歌一曲,请君为我倾耳听。钟鼓馔玉不足贵,但愿长醉不复醒。古来圣贤皆寂寞,惟有饮者留其名。陈王昔时宴平乐,斗酒十千恣欢谑。主人何为言少钱,径须沽取对君酌。五花马、千金裘,呼儿将出换美酒,与尔同销万古愁!", "prompt_wav_path": "E:/test_data/tts/zero_shot_0.wav", "prompt_text": "八百标兵奔北坡,北坡炮兵并排跑,炮兵怕把标兵碰,标兵怕碰炮兵炮。" }'

Among the above parameters, the audio of prompt_wav_path must be aligned one-to-one with the text of prompt_text. Of course, both parameters can also be omitted, for example:

In the following way, the system's built-in default prompt is used during inference.

curl -X POST "http://localhost:7901/v1/audio/speech" \
-H "Content-Type: application/json" \
--max-time 600 \
-d '{ "input": "君不见,黄河之水天上来,奔流到海不复回。君不见,高堂明镜悲白发,朝如青丝暮成雪!人生得意须尽欢,莫使金樽空对月。天生我材必有用,千金散尽还复来。烹羊宰牛且为乐,会须一饮三百杯。岑夫子,丹丘生,将进酒,杯莫停。与君歌一曲,请君为我倾耳听。钟鼓馔玉不足贵,但愿长醉不复醒。古来圣贤皆寂寞,惟有饮者留其名。陈王昔时宴平乐,斗酒十千恣欢谑。主人何为言少钱,径须沽取对君酌。五花马、千金裘,呼儿将出换美酒,与尔同销万古愁!" }'

8. Common Questions and Tips

8.1 Kylin OS: Disable the Security Center before installing the driver

On Kylin systems, disable the system Security Center before installing the driver; otherwise the driver installation will fail.

8.2 Journal Log Size

During the current debugging phase, the HLIECpp.service generates journal logs. To limit the log size, configure it as follows:

Set SystemMaxUse=500M in /etc/systemd/journald.conf

To make the new configuration take effect:

sudo systemctl daemon-reexec
Adapted and customized from the llama.cpp community ecosystem for efficient on-device inference.

1. Basic Information

1.1 Version History

VersionDateDescription
1.0.0July 10, 2024Official version
1.1.0July 25, 20251. Supports multimodal interfaces; supports running qwenvl2.5 7b/3b models on M30.
2. Supports disabling the think capability of Qwen3.
3. Reduces the libc version dependency; supports Ubuntu 20.04.
1.1.1August 15, 20251. Supports deepseek and qwen3; supports qwen2.5 Coder.
2. Supports dual-card 14B.
1.1.2September 2, 2025Updates the usage of run_llama-server.sh
1.2.0September 29, 20251. Supports m50 qwen2.5vl.
2. Supports multi-batch models.
3. Upgrades llama-server and webui.
1.3.0November 26, 20251. Supports statistics message interpretation.
2. Supports startup information interpretation.
1.3.2December 28, 20251. Not compatible with models from previous versions.
2. Supports dynamic model loading and unloading in llama-server.
3. Supports running llama-server as a service.
4. Releases the model-cli tool, supporting model download and local model management.
5. The 1.3.2 documentation uses the HLIELLama Deployment and Usage Guide.
1.4.0February 28, 20261. Only supports 1.0.0-version models.
2. Supports cache-prompt.
3. Upgrades the hlaw_ollama tool.
4. Supports qwen3-vl-30b-a3b models.
5. Upgrades hlaw_ollama to support openclaw configuration, etc.
6. Supports the abort callback of the llama_decode interface.
7. Supports models with lora_mask and dynamic lora switching.
8. The 1.4.0 documentation uses the HLIELLama Deployment and Usage Guide.
2.0.0March 30, 20261. Upgraded to 1.1.0.
2. Supports Qwen3.5 9B and 30B-A3B.
3. hlaw_ollama upgraded to a customized version with built-in gguf model download and automatic openclaw configuration.
4. Supports qwen3-embedding and qwen3-rerank models.
5. Version 1.5.0 no longer supports M30.
6. reasoning-format defaults to auto.
7. Supports think level settings.
8. llama-gguf can view basic model information.
9. llama-server webui supports MCP configuration.
10. The 2.0.0 documentation uses the HLIELLama Deployment and Usage Guide.
2.0.1April 22, 20261. Fixes legacy 2.0.0 bugs: fixes the garbled output when np>1 and fixes llama-bench errors.
2. Upgrades the model_cli tool to verify the integrity of downloaded models.
3. Upgrades the llama-gguf tool to view gguf information.
4. Supports qwen3.5/3.6 multimodal.
5. Supports qwen3 speculative decoding (cpu+npu).
6. Adds VL model usage recommendations.
7. Currently qwen3.5/3.6 with np>1 may cause insufficient NPU memory. Not supported yet; will be optimized in the next version.
2.1.0May 9, 20261. Upgrades llama to e43431b3811543efdad896e93a992551cc72ab5a to support more model architectures.
2. Removes the enable thinking control switch from webui to stay consistent with the community; for qwen-series models, use -rea off to disable thinking.
3. Based on 1.3.0 runtime.
4. Gemma4 support.
5. Qwen3.5/3.6 dual-card support.
6. Qwen3.5/3.6 MTP support (VIT currently not supported).
7. Qwen3-ASR and GLM-ASR support.
8. Qwen3-ASR-Force-Aligner support.
9. VIT supports video frame interfaces; qwen systems default to 2 frames.
10. AArch64 release components are page-aligned to 64K (done).
11. GLM-OCR model support (done).
12. Supports qwen3 speculative decoding npu+npu (done).
13. Further performance optimization.
2.1.1 (in development)May 18, 2026

1.2 Document Purpose

HLIELLama is an inference framework integrated based on the open-source llama.cpp. This document describes how to deploy the customized llama.cpp.

1.3 Supported Model List

PlatformModelSource
M50Qwen3 4Bhttps://modelscope.cn/models/Qwen/Qwen3-4B-Instruct-2507
Qwen3 8Bhttps://modelscope.cn/models/Qwen/Qwen3-8B
Qwen3 14Bhttps://www.modelscope.cn/models/Qwen/Qwen3-14B
Qwen3 32Bhttps://www.modelscope.cn/models/Qwen/Qwen3-32B
Qwen3 VL 4Bhttps://modelscope.cn/models/Qwen/Qwen3-VL-4B-Instruct
Qwen3 VL 8Bhttps://modelscope.cn/models/Qwen/Qwen3-VL-8B-Instruct
Qwen2.5 VL 7Bhttps://modelscope.cn/models/Qwen/Qwen2.5-VL-7B-Instruct
Qwen3 30B A3Bhttps://www.modelscope.cn/models/Qwen/Qwen3-30B-A3B
Qwen3-2507 30B A3Bhttps://www.modelscope.cn/models/Qwen/Qwen3-30B-A3B-Instruct-2507
Qwen 2.5 7Bhttps://modelscope.cn/models/Qwen/Qwen2.5-7B-Instruct
DeepSeek 8Bhttps://modelscope.cn/models/deepseek-ai/DeepSeek-R1-0528-Qwen3-8B
bge-m3https://www.modelscope.cn/models/BAAI/bge-m3
gte-qwen2 1.5bhttps://www.modelscope.cn/models/iic/gte_Qwen2-1.5B-instruct
Qwen3 coder 30B A3B 32khttps://www.modelscope.cn/models/Qwen/Qwen3-Coder-30B-A3B-Instruct
Qwen3-VL 30B A3B 8khttps://modelscope.cn/models/Qwen/Qwen3-VL-30B-A3B-Instruct
gpt-oss-20b 32khttps://www.modelscope.cn/models/openai-mirror/gpt-oss-20b
Qwen3-Reranker-8Bhttps://modelscope.cn/models/Qwen/Qwen3-Reranker-8B
Qwen3-Embedding-8Bhttps://www.modelscope.cn/models/Qwen/Qwen3-Embedding-8B
minicpmo2.6 (supports vision)https://www.modelscope.cn/models/OpenBMB/MiniCPM-o-2_6
qwen3.5 2b 4b 9b 27Bhttps://modelscope.cn/models/Qwen/Qwen3.5-4B
https://modelscope.cn/models/Qwen/Qwen3.5-9B
https://modelscope.cn/models/Qwen/Qwen3.5-27B
qwen3.5 35b-a3bhttps://www.modelscope.cn/models/Qwen/Qwen3.5-35B-A3B
qwen3.6 35b-a3bhttps://modelscope.cn/models/Qwen/Qwen3.6-35B-A3B
gemma4https://modelscope.cn/models/google/gemma-4-26B-A4B-it
Cowpawhttps://modelscope.cn/models/AgentScope/CoPaw-Flash-9B

2. Inference Service Deployment

2.1 Deployment Requirements

Hardware Requirements (Minimum)

  • CPU architecture: x86_64 / aarch64

  • Disk: 200G

  • AI hardware: M50

Software Requirements

  • Operating system: Ubuntu 20.04

  • Driver version:

    • M50-v1.0.0

2.2 Directory Structure

An example of the complete directory structure of the inference service deployment package is shown below. First confirm that you have downloaded the correct version. M30 and M50 use different packages; check whether the file name contains xh1 (M30) or xh2 (M50). You can download it from the model section of the Beelink AI website: https://llm.bee-link.cn/.

.
├── bin
├── include
├── lib
├── models
├── scripts
├── service
└── version.txt

The bin directory contains some binaries shipped with llama.cpp for self-testing, of which llama-server is the main one.

bin
├──hlaw_ollama//ollama实现,处于实验阶段
├──llama-bench//bench工具
├──llama-cli//命令行交互工具
├──llama-gguf//gguf工具支持rn命令
├──llama-gguf-split//支持将gguf文件切分为多个gguf文件
├──llama-server//提供webapi,openai兼容接口
├──model-cli//model-cli支持简单模型管理

The include directory contains the llama.cpp header files for secondary development based on llama.cpp.

The lib directory contains the libraries generated by llama.cpp and its dependent libraries (SDK).

The scripts directory contains model packaging scripts for converting models to the GGUF format.

scripts
├── convert_hm_to_gguf.py // 转换脚本,讲hmm打包成gguf
├── gguf-py // 转换脚本依赖的gguf库
├── readhmm // 可以查看hmm模型基本信息工具
└── requirements-convert_hm_to_gguf.txt //依赖

2.3 Converting Models Yourself [Optional]

If you have fine-tuned a model, it must finally be converted to GGUF format for loading. If you are only evaluating open-source models, skip this step. The conversion scripts are in the scripts directory.

For model compilation and quantization, refer to the related documentation. After quantization and compilation, it is recommended to use the hmmstrip tool to strip the weights shared between prefill and decode.

The tool is located in the compilation container at /usr/local/HLIECpp/bin/hmmstrip; see the --help instructions for usage.

Example:

After execution, the decode model is only a few hundred MB. Use the compressed decode model directly:

/usr/local/HLIECpp/bin/hmmstrip --strip -o decoder.hmm -i qwen3-prefill.hmm qwen3-decode.hmm

2.3.1 Installing Dependencies

A Python 3 environment of >= 3.10 is recommended, preferably 3.10 or 3.12.

pip3install-rscripts/requirements-convert_hm_to_gguf.txt

2.3.2 Compiling and Quantizing Models

For model compilation and quantization, refer to the related documentation. The document download path is in the documentation center (Model Resource Center/doc).

2.3.3 Running the Conversion Script

  1. Download the official configuration files.

For example, download from ModelScope to your_local_dir (in the same folder as the hmm files).

modelscopedownload--modeldeepseek-ai/DeepSeek-R1-0528-Qwen3-8B--exclude '*.safetensors'--local_diryour_local_dir
  1. Run the conversion. (For qwen2.5, qwen3, and similar models; for qwenvl and deepseek, refer to steps 3 and 4.)

python3convert_hm_to_gguf.pyyour_local_dir/
  1. qwen2.5-vl conversion

Text model conversion

# 文本模型指定vit 模型的width & height
python3convert_hm_to_gguf.pyyour_local_dir/

Vision model conversion

python3convert_hm_to_gguf.pyyour_local_dir/--mmproj--outfileyour_local_dir/mmproj.gguf
  1. bge-m3 / bge-reranker-v2-ms model conversion

Rename the hmm file to embedding.hmm. The rest of the process is the same as above.

modelscopedownload--modelBAAI/bge-m3--exclude '*.safetensors'--local_dirbge-m3
# 将hmm文件重命名为embedding.hmm
python3convert_hm_to_gguf.pybge-m3
  1. deepseek conversion

Currently, the deepseek-qwen3 conversion reports an error:

convert_hm_to_gguf.py ", line 1029, in get_vocab_base_pre
 raise NotImplementedError(
 NotImplementedError: BPE pre-tokenizer was not recognized - update get_vocab_base_pre()

You can solve it by updating the tokenizer.json file as follows:

from transformers import AutoTokenizer * # 替换成你目标模型的正确 HuggingFace 模型名称,比如:*
model_name = "deepseek-ai/[DeepSeek-R1-0528-Qwen3-8B](https://huggingface.co/deepseek-ai/DeepSeek-R1-0528-Qwen3-8B)" * # 请确认这个名称是否正确!* * # 下载到本地缓存 ~/.cache/huggingface...*
tokenizer = AutoTokenizer. from_pretrained (model_name) # 执行下面命令将*.json 保存到your_local_dir
tokenizer. save_pretrained (your_local_dir)

2.4 Model Download (model-cli)

New in v1.3.2.

Use model-cli in the bin directory to download models. The downloaded models are quantized and compiled from open-source models. The usage is as follows:

Usage:./model-cli [options]<command> [args] Options:
-hoststring
TargetserverIP/Host (default "127.0.0.1")
-model-pathstring
Custommodelsdirectory (overridesenvanddefault)
-portint
TargetserverPort (default 17701) Commands:
query [k=v...]Queryremote (auto-detectstarget,default: open_type=cloud&format=gguf)
pull<ids|urls>DownloadbyIDorURL.examplepull 123 124
listList localmodels
psListloadedmodels
run<name>Loadamodel
stop<name>Unloadamodel
rm<name>Delete localmodel

2.4.1 Querying the Reference Model List Published in the Cloud

Filters such as size, batch, device, and target are supported, for example: target=xh2.

CTX: the maximum context length of the model.

BATCH: whether it is a multi-batch model.

DEVICE: whether it is a single-card or multi-card model. For example, 2 means a dual-card model that needs to run on DM.2 or a multi-chip PCIe card.

FILES: how many gguf files; multi-card models usually have 2.

BUILD: which toolchain version was used to compile the model.

user@user-System-Product-Name:~/dev/tools$./model-cliquery
Auto-detectedtarget:xh2
Fetchingfrom:https://llm.bee-link.cn//models?build_version=1.0.0&format=gguf&open_type=cloud&target=xh2 Found 23models:
IDNAMESIZEBUILDCTXBATCHDEVICETARGETCORESFILES
----------------------------------------------
1767880490946qwen3-vl4b 1.0.0 16384 1 1xh2 2 2
1767880490947qwen314b 1.0.0 32768 1 2xh2 2 1
1767880490948qwen332b 1.0.0 32768 1 4xh2 2 1
1767880490949qwen2.57b 1.0.0 8192 1 1xh2 2 1
1767880490950qwen2.57b 1.0.0 32768 1 1xh2 2 1
1767880490951deepseek8b 1.0.0 32768 1 1xh2 2 1
1767880490952gpt20b 1.0.0 65536 1 1xh2 2 1
1767880490955gte 1.5b 1.0.0 2048 1 1xh2 2 1
1767880490956bge 0.5b 1.0.0 32768 1 1xh2 2 1
1767880490957bge-reranker-v2-m3 0.5b 1.0.0 32768 1 1xh2 2 1
1767880490958qwen34b 1.0.0 32768 1 1xh2 2 1
1767880490959qwen38b 1.0.0 32768 1 1xh2 2 1
1767880490960qwen38b 1.0.0 16384 4 1xh2 2 1
1767880490961qwen314b 1.0.0 16384 1 1xh2 2 1
1767880490962qwen3-vl4b 1.0.0 32768 1 1xh2 2 2
1767880490963qwen3-vl8b 1.0.0 32768 1 1xh2 2 2
1767880490964qwen2.5-vl7b 1.0.0 8192 1 1xh2 2 2
1767880490965qwen330b-a3b 1.0.0 32768 1 1xh2 2 1
1767880490966qwen3-vl30b-a3b 1.0.0 8192 1 1xh2 2 2
1772188146032qwen3-250730b-a3b 1.0.0 32768 1 1xh2 2 1
1772188325612qwen3-250730b-a3b 1.0.0 32768 1 2xh2 2 1
1772799664016gpt20b 1.0.0 65536 1 2xh2 2 1
1772878235701gpt20b 1.0.0 131072 1 1xh2 2 1 Todownload:./model-clipull<ID>

The default model download path is the ../models directory relative to model-cli.

You can also specify the download path with --model-path.

2.4.2 Local Model Management

Requires llama-server to be started with --models-dir.

  • list: lists the models that have been scanned/loaded.

  • run: loads a model.

Loading takes time; the actual return only means the load command was received. Use ps to check the loading result.

  • ps: views loaded models.

  • stop: unloads a loaded model.

2.5 Running llama-server

Notes:

  1. It is recommended to run llama-server directly. It also supports installation and running as a background service. New versions no longer recommend using the run_llama-server.sh script, and it will be removed in future versions.

  2. For long-term stability tests, it is recommended to add --cache-ram 0; otherwise, the prompt of each session is cached, causing slow memory growth (max cache 8G). This feature will be disabled by default in the next version.

# 首先进到压缩包目录
cd-application-software-llama.cpp-xh2
# 查看支持的命令
./bin/llama-server--help

2.5.1 Running Modes

Preloading a Model

Specify the model at startup to preload it for testing.

# model_name 为gguf模型文件绝对路径
./bin/llama-server-mmodel_name.gguf
# 加载多模态
./bin/llama-server-mmodel_name.gguf--mmprojmmproj.gguf

Dynamically Loading Models

Do not load a model at startup; specify the model directory. Models are loaded dynamically according to user requests. If memory is sufficient, multiple models can be loaded at the same time. The current version does not support dynamically updating the model list; it only scans the directory specified by --models-dir at startup.

With dynamic loading, each request must carry the correct model name.

./bin/llama-server--models-dirmodels
  • The bin/model-cli tool can be used to load and unload models.

./bin/model-clilist # 列出llama-server 启动时扫描到的模型
./bin/model-clirunmodelname # 加载模型
./bin/model-clistopmodelname # 卸载模型
  • Models can be loaded/unloaded dynamically through webui.

  • Or through the web API:

    /models/load
    {model: "qwen3-vl_4b_32769_1_1"} /models/unload
    {model: "qwen3-vl_4b_32769_1_1"}
  • For the first request after loading, the model in the request must be set to the correct value.

Running as a Background Service

Install_llama-server.sh and uninstall_llama-server.sh scripts exist in the service directory.

Running llama-server as described in "Dynamically Loading Models" (2.5.1.2) means it runs as a background service; models are loaded/unloaded dynamically through model-cli or the UI.

# 安装指令
sudobashservice/install_llama-server.sh
# 服务管理
sudosystemctlstatusllama-server.service # 查看服务状态
sudosystemctlstartllama-server.service # 启动服务
sudosystemctlstopllama-server.service # 停止服务
sudosystemctlrestartllama-server.service # 重启服务
sudojournalctl-ullama-server.service-f # 实时查看服务日志 # 服务卸载
sudobashservice/uninstall_llama-server.sh

2.5.2 Common Runtime Parameters

For specific usage parameters, refer to the llama-server binary. To support concurrent access at the same time, you can use --np 4 (currently limited to a maximum of 4; only multi-batch models are truly concurrent, while single-batch models execute alternately).

Running with Dynamic Model Loading

./bin/llama-server--models-dirmodles

Running Embedding Models

The parameters for running embedding models are slightly different from LLM/vLLM. Take gte as an example.

Currently, -b and -ub must be greater than or equal to the context length. (Since v2.0.1, the default values of -b and -ub are automatically adjusted according to the context.)

./bin/llama-server-m../models/gte_Qwen2-1.5B-Q4_0.gguf--embedding--poolinglast-b 8096-ub 8096

Running Rerank Models

./bin/llama-server-m../models/Qwen3-Reranker-8B-Q4_0.gguf--rerank

Binding Cards in a Multi-Card Environment

Single-card models run on DEVICE_ID 0 by default; multi-card models run on DEVICE_ID 0,1 by default.

drv_DEVICE_ID has the highest priority.

export drv_DEVICE_ID=0或者双卡export drv_DEVICE_ID=0,1

--list-devices lists the card status

--device 0 means running on card 0

user@user-System-Product-Name:~$./dev/llama.cpp/release/xh2/x86_64/bin/llama-server--list-devices
[NPU]LoadingNPUSDK...
[NPU]Tryingtoload:/usr/local/-sdk/hal/lib/libhal_xh2a.so
[NPU]Successfullyloaded:/usr/local/-sdk/hal/lib/libhal_xh2a.so
[NPU]hm_sys_get_device_inforeturned: 1devices
[NPU]Device 0: device_id=0
[NPU]get_mem_inforeturned: 0, mem_total=24448, mem_used=0, mem_avail=24448
[NPU]Finaldevicememory: total=24448MB, free=24448MB
[NPU]Initializationcomplete, 1devicesavailable
Availabledevices:
0:NPULQ50 (ID: 0) (24448MiB, 24448MiBfree)

Specifying the Port

./bin/llama-server-mmodel_name--port 18080

Disabling the Think Mechanism of Qwen3 by Default (Including Qwen3, Qwen3.5, Qwen3.6)

./bin/llama-server-mmodel_name--reasoning-budget 0【2.1.0之前接口】 ./bin/llama-server-mmodel_name-reaoff【2.1.0版本接口,qwen3.5等需要使用这个参数】

Note: After think is disabled on the inference side, whether think actually takes effect is controlled by the request parameters of the application side. See 2.5.2.9 for details.

Forcibly Disabling the Think Mechanism of Qwen3/Deepseek (Qwen3.5 and Qwen3.6 Not Supported)

./bin/llama-server-mmodel_name--jinja--chat-template-filebin/qwen3_nonthinking.jinja

Setting the Log Level

--log-file写日志到文件
--log-timestamps为打印uptime的时间,
--verbosity控制等级
- 0:genericoutput
- 1:error
- 2:warning
- 3:info
- 4:debug example
--log-file/home/useradmin/test.log--log-prefix--log-timestamps--verbosity 2

Dynamically Enabling/Disabling qwen3 think through the OpenAI-Compatible API

In the request body:

{
"temperature" : 0.8,
"top_p" : 0.9,
"repetition_penalty" : 1.1,
"chat_template_kwargs" : {"enable_thinking" : false}
}

Setting the Think Level: none, low, medium, high

Setting it to none disables think. For example, gpt-oss supports the low, medium, and high levels.

{
"temperature" : 0.8,
"top_p" : 0.9,
"repetition_penalty" : 1.1,
"reasoning" :{"effort" : "low"}
}

Setting a Model Alias

After setting an alias, the model name is more concise.

-a,--aliasSTRING set alias formodelname (tobeusedbyRESTAPI)

Enabling/Disabling cache_prompt (Enabled by Default since 1.4.0)

For large model inference, reuse the KV cache to reduce TTFT time.

  1. In multi-turn conversations, carry the history each time to avoid resending the history to the model for inference; reuse the previously computed KV cache.

  2. Long system prompt scenarios.

Loading Models by Tensor

On systems with limited memory, direct loading may cause OutOfMemory. Add the --no-mmap startup parameter in this case. Note that this makes loading slower.

Environment Variables for qwen3.5/3.6

The cache_prompt implementation of qwen3.5/3.6 occupies some NPU or HOST memory.

  1. Single-card models keep at most 40 groups of cache, stored on the NPU by default (occupying 1G+).

  2. Dual-card models keep at most 80 groups of cache, stored on the Host by default; currently only Host is supported (occupying 2G+).

You can change the storage location and size through environment variables.

export LLAMA_CHECKPOINT_STORAGE=1
#表示存在device上,0 表示host上
#日志信息:set checkpoint_storage_ to kDevice from env LLAMA_CHECKPOINT_STORAGE export LLAMA_CHECKPOINT_INTERVAL=1024
#表示每隔多少个tokens 保存一次,默认1024, 最大40960

reasoning-format

reasoning-format=none means the think part is placed in the "message.content" field.

reasoning-format=auto means the think part is placed in the "message.reasoning_content" field.

New applications are compatible with the reasoning_content format. It is not recommended to change the default setting; the current default is auto.

For gpt-oss models, add --reasoning-format auto; otherwise the output message format is not parsed.

qwen3.6 MTP

--spec-type draft-mtp --spec-draft-n-max 4

2.1.0 only supports the text part, without the vision part.

./bin/llama-server-m~/dev/models/HiModel_xh2_qwen3.6_27b_mtp_256_128k_1chip_2cores_v1.3.0_20260603.gguf--spec-typedraft-mtp--spec-draft-n-max 4

Running Qwen3-ASR Models

HTTP inference

curl-XPOST "http://127.0.0.1:17701/v1/audio/transcriptions" \
-H "Content-Type: multipart/form-data" \
-F"model=Qwen3-ASR" \
-F"file=@E:/test_data/audio/test.wav"

Running Qwen3-ASR-Force-Aligner Models

HTTP inference

curl-XPOST "http://127.0.0.1:17701/v1/audio/transcriptions" \
-F"file=@E:/test_data/audio/test.wav;type=audio/wav" \
-F"model=Qwen3-ForcedAligner-0.6B" \
-F"response_format=json" \
-F"asr_force_align=true" \
-F"text=HE BEGAN A CONFUSED COMPLAINT AGAINST THE WIZARD WHO HAD VANISHED BEHIND THE CURTAIN ON THE LEFT" \
-F"language=English"

Note the following about these parameters:

The text parameter must correspond one-to-one with the audio;

The language parameter must match the main language of this audio.

2.5.3 Console Statistics

Startup Information

FieldDescription
n_ctx_lengthThe maximum context length supported by the model
n_layerThe number of model layers (model-related)
n_embdThe embedding length of the model
model_descModel description; Q4_0 is displayed because large models mainly use w4a8 quantization
allow_imageWhether image input is supported
allow_audioWhether audio input is supported
vision-width, vision-heightThe resolution after image resize
VmPeakPeak virtual memory usage
VmSizeVirtual memory usage after startup
VmHWMPeak physical memory usage
VmRSSPhysical memory usage after loading

Performance Statistics

Llama-server enables cache-prompt by default, so the prefill token count excludes the prefix part. Using --no-cache-prompt shows information that is easier to understand.

The figure below shows the display system for VL models.

MetricDescription
Image eval timeThe vision model time, e.g. 154ms; each image is encoded into 196 tokens
Prefill eval timeThe prefill model time, processing a total of 209 tokens (including the 196 image tokens)
Decoder eval timeThe decode time
Total eval timeThe end-to-end latency
TTFTTime to first token (vision + prefill)
TOPTInterval between tokens
E2E LatencyEnd-to-end latency
E2E TPSOverall throughput

2.5.4 Testing

Built-in WebUI Test

Access http://ip:17701 in a browser; ip is the IP of the deployment host, or 127.0.0.1 for local access. 17701 is the default port.

Statistics message description:

  • Context: 194/65536 means the maximum context of this model is 65536 and 194 tokens have been used.

  • Output: 124 means this request output 101 tokens.

  • 28.1 t/s means the average decode speed of this request.

Click the red arrow to display the statistics:

  • 70 indicates the number of prompt tokens sent to the model.

  • 0.3s indicates the time to first token; currently only one decimal place is displayed.

  • 277.32 tokens/s indicates the prefill speed.

MCP Test

In Settings, on the MCP configuration page, you can configure an MCP Server. The example below configures a public GitMCP and a custom local-file-mcp-server.

Access through the OpenAI API

Tools such as chatbox, hichat, and dify can access the service through the OpenAI API. Refer to the figure below for configuration.

Multi-Turn Conversation Cache

Multi-User Concurrency

Add the -np 2 startup parameter (maximum 4) for multiple users.

2.6 Other Usage Notes

The llama.cpp release package ships multiple tools. Besides model-cli, it also includes hlaw_ollama, llama-cli, llama-gguf-split, and other tools. These tools are mainly experimental and may have some issues.

2.6.1 hlaw_ollama

This tool is a customized version of ollama. You can use the install script in the service directory to install it as a service. See the HLAWOllama Deployment and Usage guide for details. This tool is only provided as a demo.

2.6.2 llama-gguf

llama-gguf xx.gguf r is similar to the gguf-dump capability.

2.6.3 llama-gguf-split

This tool can split prefill.hmm and decoder.hmm from customized models. Currently, it only supports pd-classified models such as qwenvl. Combined with the readhmm tool shipped with the toolchain, model information can be read. This tool is mainly used for model tracing and problem location.

It can also be used to quickly test and verify models with different contexts based on compiled models without converting to gguf. Take the qwen3_8b model as an example; the split model has three parts:

  1. qwen3_8b_00001-of-00003.gguf: contains vocab + embedding.

  2. qwen3_8b_00002-of-00003.gguf: the prefill.hmm.

  3. qwen3_8b_00003-of-00003.gguf: the decoder.hmm.

When compiling models with different contexts, vocab + embedding are shared; only the last two parts change. Overwrite 00002 and 00003 with the new prefill and decode models respectively. To load the model, only specify qwen3_8b_00001-of-00003.gguf with -m.

2.6.4 llama-cli

The command line version; basic functions are the same as the open-source version.

2.6.5 VL Model Usage Notes

Read this section before using VL models.

  1. Currently, the VIT model only supports fixed resolutions. For example, the default provides 448x448 resolution, so all images sent to llama-server are resized to 448x448.

    When calling the OpenAI-compatible API, it is recommended that the caller performs the resize. This has two advantages:

    1. Reduces HTTP transfer overhead.

    2. The resize in llama.cpp is executed on the CPU by default and may not be the most efficient.

  2. Currently, the resize logic in llama is proportional compression followed by padding, pasted to the top-left corner, with the remainder filled with (114,114,114). For inspection-box tasks, the returned boxes are relative to the resized image and need to be converted back. In addition, the bbox returned by object detection is usually between 0-1 or in 0-1000 resolution.

2.6.6 Recommendations for qwen3.5-Series Models

  1. A 24G card can run qwen3.5 35B-A3B with np=1.

  2. It is recommended to add --presence_penalty 1.5 to the startup parameters of qwen3.5-series models.

Official recommendations:

Model
Qwen/Qwen3.5-35B-A3B
Qwen/Qwen3.5-4B
Adapted and customized from the vLLM community ecosystem for stable high-concurrency large model serving.

1. Version Information

VersionDocument DateChange Description
1.4.0-Preview20260527Key features and changes:
1) The vllm baseline is upgraded to v0.21.0rc1.
Community vllm commit id:
18f6bf5a214fd51d0cb08fcf1b59edc5629e7c19
2) Added gemma4 (including VL models) support.
3) Added copawflash 9B support.
4) Added qwen3 draft model speculative decoding support.
5) Added qwen3.5 MTP speculative decoding support.
6) Added qwen3 asr, forcealigner, and other speech models.
7) Supports Docker deployment and provides a Dockerfile.
8) Due to licensing risk, Anaconda downloads are not provided externally; please download from the Anaconda official website or other public addresses.
9) Optimized the qwen3.5 inference pipeline.
10) Added qwen3-reranker and glm-ocr models.
1.3.0202604231) The vllm baseline is switched to v0.18.1rc1.
2) Added qwen3.5/qwen3.6 (including 448x448 VL models) support.
3) Added gpt-oss 20b model support.
4) Added qwen3-8b-embedding model support.
5) Optimized multi-batch related logic.
6) promptcache reuse changed to token-level reuse logic.
7) HLIEvLLM 1.3.0 supports qwen3.5 vl-series vision-language models, but does not yet support qwen3 vl-series models. To test qwen3vl-related models, download HLIEvLLM 1.2.0.
1.2.020260327Changed internal network addresses to external addresses.
1.2.0 rc0202603091) Added TTS and ASR features, corresponding to minicpmo tts and Whisper models.
2) Added the qwen3_vl 30b moe model.
3) Supports ARM Linux deployment.
4) Supports enabling and disabling cache prompt; disabled by default.
Historical Version DocumentsVersion Information
1.1.0 release20260113
1.1.0a420260104
v1.0.0 release20251108

2. Environment Deployment

2.1 Creating a Python 3.11 Virtual Environment

Install Anaconda and create a Python 3.11 virtual environment. Miniconda cannot be used.

First install Anaconda. For internal testing, you can download the Anaconda installer from the following URLs:

Linux installer

x86 platform:

http://10.10.1.53:8082/artifactory/application_software/open-source/Anaconda3-2025.12-2-Linux-x86_64.sh

ARM64 platform:

http://10.10.1.53:8082/artifactory/application_software/open-source/Anaconda3-2025.12-2-Linux-aarch64.sh

After downloading, run the following commands to install Anaconda3:

sudochmod 777Anaconda3--Linux-x86_64.sh
./Anaconda3--Linux-x86_64.sh

Due to licensing risk, external customers should download the latest installer from the Anaconda official website or other public addresses.

Anaconda official download URL: https://www.anaconda.com/download

2.1.1 Creating a Python 3.11 Environment on Ubuntu

Use conda to create a Python 3.11 virtual environment; specify the virtual environment name after -n:

condacreate-nvllm_env python=3.11-y

Activate the virtual environment:

condaactivatevllm_env

2.2 Installing HLIEvLLM

Make sure the host has the corresponding M50 driver version installed and that hm_smi output is normal.

Download the two packages released by HLIEvLLM from the inference framework section of the Beelink AI website (https://llm.bee-link.cn/frameworks.php):

HLIEvLLM-1.x.zip and hlievllmplugin-1.x-py3-none-any.whl

2.2.1 Step 0: Confirm the tcim runtime is installed and the firmware version of the inference card matches

If tcim_runtime is not installed, download the matching runtime from the following link (select the version matching your driver): https://dr.bee-link.cn/download/dXBsb2Fkcy9MTE0vUnVudGltZS1TREsvaG91bW9fdGNpbV9ydW50aW1lX3hoMl9saW51eF94ODZfNjQtMV80XzBfdGFyLmd6/h/ca681089f70cbf5962aedfd56d866ba1 Install the tcim runtime v1.x package following the steps below. Also make sure the firmware version on the inference card matches the driver version. (If the runtime is already installed and the firmware version on the inference card is confirmed to match, this step can be skipped.)

First enter the Python virtual environment created above and make sure the operating system has gcc and g++ installed, with C++11 support; otherwise, the tcim runtime installation will fail.

If not installed, run the following command:

sudoaptinstallg++

Then run the following command to install the tcim runtime package:

Linux系统:注意根据cpu架构,选择对应版本
x86平台:
1.3.0的runtime包
pipinstallhttp://10.10.1.53:8082/artifactory/drv_software/release_xh2_v1.3.0/2026/05/19/0015/ubuntu2004/drv_tcim_runtime_xh2_linux_x86_64-1.3.0.tar.gz-ihttps://mirrors.aliyun.com/pypi/simple/ arm平台:
1.3.0的runtime包
pipinstalldrv_tcim_runtime_xh2_linux_aarch64-1..0.tar.gz-ihttps://mirrors.aliyun.com/pypi/simple/

2.2.2 Step 1: Install vLLM and Set Related Variables

Note: HLIEvLLM must be installed first, and then HLIEvLLMPlugin. This step installs the software packages that HLIEvLLM depends on and takes some time. It normally takes about 10-20 minutes to finish.

a. Install HLIEvLLM on Linux.

Starting from HLIEvLLM 1.3.0, the tcmalloc-minimal and omp libraries recommended by vllm are used first. According to the official instructions, install the following dependencies first:

依赖项1:
sudoapt-getinstalllibnuma-dev 依赖项2:
sudoapt-getinstall-y--no-install-recommendslibtcmalloc-minimal4
sudofind/usr-namelibtcmalloc_minimal*so
返回的路径要用到下面的环境变量设置中 依赖项3:
sudoapt-getinstalllibomp5libomp-dev
sudofind/usr-namelibomp*so* 设置下面的环境变量,以便找到相关的库
export IOMP_PATH=/上面findomp命令返回的路径/libomp.so.5
export TC_PATH=/上面findtcmalloc命令返回的路径/libtcmalloc_minimal.so.4
export LD_PRELOAD="$TC_PATH:$IOMP_PATH:$LD_PRELOAD"
echo $LD_PRELOAD
x86平台LD_PRELOAD变量输出示例如下:
/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4:/usr/lib/x86_64-linux-gnu/libomp.so.5: arm平台LD_PRELOAD变量输出示例如下:
/usr/lib/aarch64-linux-gnu/libtcmalloc_minimal.so.4:/usr/lib/aarch64-linux-gnu/libomp.so.5:

b. Download the vllm version.

Extract the archive and enter the extracted folder, for example "HLIEvLLM-1.3.0". Run the following command to install vllm (it takes about 10 minutes because dependencies are downloaded):

On Ubuntu 22.04 and earlier, the default gcc version is lower than 12.3 and must be upgraded; otherwise, vllm compilation reports an error. Upgrade it as follows (if gcc is greater than or equal to 12.3, no upgrade is needed):

# 1. 添加官方源(针对 Ubuntu 20.04/22.04)
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
sudo apt update # 2. 安装 gcc-13 和 g++-13,如果下载较慢,ctrl—c终止,然后重新下载试试,速度不低于200KB/s就行。速度如果一直较慢,请设置clash 翻墙代理,正常不到10分钟可以安装完成
sudo apt install -y gcc-13 g++-13 # 3. 设置为系统默认版本(关键)
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 100
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 100 # 4. 验证版本(输出应为 13.+)
gcc --version
g++ --version

First confirm that the gcc and g++ versions are greater than or equal to 12.3. Then enter the extracted folder, for example "HLIEvLLM-1.3.0", and run the following command to install vllm: After installing the v1.4.0 preview version, remember to downgrade fastapi to 0.136.3 or 0.136.1; the official version will fix this problem. After the preview release, the fastapi version was upgraded, and the latest fastapi is not compatible. See section 3.1 of chapter 3.

VLLM_TARGET_DEVICE=cpupipinstall-e.--extra-index-urlhttps://download.pytorch.org/whl/cpu-ihttps://mirrors.aliyun.com/pypi/simple/

If you need to run audio-related models, such as the Whisper models below, install the additional dependencies. Enter the extracted folder, for example "HLIEvLLM-1.3.0", and run the following command:

VLLM_TARGET_DEVICE=cpupipinstall-e ".[audio]"--extra-index-urlhttps://download.pytorch.org/whl/cpu-ihttps://mirrors.aliyun.com/pypi/simple/

2.2.3 Step 2: Install the vllm Inference Plugin Package

Note: If an old whl plugin package is installed, be sure to uninstall it first by running pip uninstall HLIEvLLMPlugin.

If the installation encounters an unsupported instruction vpdpbusd' error, set the following two environment variables before installing:

export CFLAGS="-mno-avx"

export CXXFLAGS="-mno-avx"

The whl package installation command is as follows:

VLLM_TARGET_DEVICE=pipinstallhlievllmplugin-1.-py3-none-any.whl--no-build-isolation--extra-index-urlhttps://download.pytorch.org/whl/cpu-ihttps://mirrors.aliyun.com/pypi/simple/

After installation, view the installation location and source path through the Location: value in the output of the following command:

pip show HLIEvLLMPlugin

Example path: /home/useradmin/anaconda3/envs/vllm_env_120rc0/lib/python3.11/site-packages/vllm_/

2.3 Docker Deployment

# 解压安装包并进入目录
tarzxvf-Python-xh2_3.0.0_linux_x86_64.tar.gz
cd-Python-xh2_3.0.0_linux_x86_64 # 执行初始化脚本加载镜像
bashinit.sh # 将GGUF 模型以目录格式存放到 models/ 目录,例如:
mkdirmodels/Qwen3.5_35B
wget-Pmodels/Qwen3.5_35Bhttp://xxx/Qwen3.5_35B.gguf # 修改docker-compose.hlievllm.yaml 中的启动命令
vimdocker-compose.hlievllm.yaml # 启动 hliepython 服务
dockercompose-fscripts/docker-compose.hlievllm.yamlup-d # 查看服务启动日志
dockercompose-fscripts/docker-compose.hlievllm.yamllogs--tail 100-fhlievllm # 下线 hliepython 服务
dockercompose-fscripts/docker-compose.hlievllm.yamldown

Note

The model directory in the startup command field of docker-compose.hlievllm.yaml should use the model directory mounted in the container, which is mounted to /opt/hlievllm/models by default.

3. Startup Test

Before testing, read the following notes a) to h):

a) HLIEvLLM contains a lot of info logging for debugging and problem location. For debugging, you can lower the log level; for performance mode, you can disable info. Set one environment variable as follows:

Performance mode (default mode): reduces debug output and makes decode output faster. Set VLLM_LOGGING_LEVEL to the following value:

export VLLM_LOGGING_LEVEL=WARNING

Debug mode: set VLLM_LOGGING_LEVEL to the following value to print a lot of logs:

export VLLM_LOGGING_LEVEL=DEBUG

b) Time statistics and printing for key paths:

This version includes time statistics for key paths in the vllm inference flow for performance analysis. They are not executed by default. To view the related time statistics, set the following environment variable. The time statistics are not controlled by VLLM_LOGGING_LEVEL:

export ENABLE_TIMING=1

c) Download links for the gguf model files corresponding to this HLIEvLLM version:

https://llm.bee-link.cn/, and select the model corresponding to version 1.2.0 in the version column.

Note: for qwen3.5/qwen3.6 35B MOE models, select the model corresponding to 1.3.0 or 1.4.0 in the version column, or contact FAE colleagues for the related model version.

If the link cannot be opened, contact FAE colleagues.

d) If the following error occurs during startup testing: ImportError: /lib/x86_64-linux-gnu/libstdc++.so.6: version `CXXABI_1.3.15' not found

Solution: modify the LD_LIBRARY_PATH environment variable to load conda's libstdc++ first.

To locate the problem, run: strings /lib/x86_64-linux-gnu/libstdc++.so.6 | grep CXXABI. If 1.3.15 is not in the output, the system's built-in libstdc++ is too old, and conda's own libstdc++.so.6 must be used. Set the variable as follows (change to the directory corresponding to your conda virtual environment):

export LD_LIBRARY_PATH=/home/useradmin/anaconda3/envs/vllm_env/lib:$LD_LIBRARY_PATH

e) To reduce CPU utilization, set the following environment variable. CPU utilization can be significantly reduced, but note that the decode rate also decreases; choose a balance.

export OMP_NUM_THREADS=1

Reason: preprocessing uses torchvision. If this environment variable is not set, torch does not limit the number of threads of a single instance, causing high CPU utilization.

f) For multi-card models, remember to add the following parameter when starting vllm to specify the cards on which the model is loaded:

--additional-config='{"device_ids":[0,1]}'

g) Starting from hlievllm 1.3.0, libtcmalloc_minimal.so.4 is enabled by default according to official recommendations. Before running the tests below, make sure the LD_PRELOAD variable in the current terminal env includes the paths of tcmalloc-minimal and omp. Section 1.2 of this document describes the related instructions and setting methods.

h) vllm has many startup parameters. Refer to http://docs.vllm.ai/en/latest/cli/ or https://www.psvmc.cn/article/2026-03-10-ai-vllm-prop.html to understand the meaning of the related parameters.

3.1 Offline Inference Test

The test code is in the drv_examples/ folder of the extracted HLIEvLLM-1.* package:

Change the model folder in the test code to the folder of your downloaded model. Note: the specified model folder can contain only one gguf file starting with HiModel. Put different HiModel*.gguf files in different folders.

Modify the "model_name" variable in the LLM_*.py test code to point to the folder containing your downloaded gguf file.

For VL models, also modify:

additional_config={"visual_model_path": point to the absolute path of your mmproj*.gguf file}

Starting a Text Offline Inference Test

(vllm_env_szj_v110a4)user@PC:/HLIEvLLM-1.*.* $**python3drv_examples/LLM_example_chat.py

Starting a Multimodal Offline Inference Test

(vllm_env_szj_v110a4)user@PC:~/szj_project/HLIEvLLM-1.*.*$python3drv_examples/LLM_qwen35_vl_example.py

Speech-Text Forced Alignment Model

Use the following command to run the Qwen3-ForcedAligner-0.6B model for speech and text alignment, mapping each text token to the corresponding time segment of the audio. The reference text can be obtained through the speech model.

Note: the qwen-asr library must be installed in the hlievllm environment. The qwen-asr library downgrades transformers to 4.57.6. After using the example, manually upgrade the transformers library to avoid affecting other models.

pythondrv_examples/qwen3_forcealigner_offline.py--model-dir/path/to/Qwen3-ForcedAligner-0.6B--audio/path/to/test.mp3--text "参考文本"--pretty

3.2 Online Inference Test: OpenAI API Server

Before starting the test, please read and note the following points again:

*) For multi-card models or models that need to run on a specified card, add the following parameter when starting vllm online inference to specify the cards. The --additional-config example below is for a dual-chip model, meaning the model runs on 2 inference cards with card ids 0 and 1; the corresponding model must be a dual-card model.

--additional-config='{"device_ids":[0,1]}'

*) Different model categories have different tool-call-parsers. Refer to the examples for settings. If you change to another parser, make sure you understand the parser and confirm that its performance is better than the recommended configuration.

*) vllm does not enable prompt cache reuse by default. To enable it, add the following parameter when starting vllm:

--additional-config='{"enable_cacheprompt":"True"}'

*) vllm has many startup parameters. Refer to http://docs.vllm.ai/en/latest/cli/ or https://www.psvmc.cn/article/2026-03-10-ai-vllm-prop.html to understand the meaning of the related parameters.

Text Models

Start the OpenAI server with an API key.

qwen3.5/qwen3.6 Series (Multi-Chip Models + Cache Reuse Supported)

Take the qwen3.5 35B A3B 256K context model as an example: --max-num-batched-tokens and --max-model-len must be set to the model's maximum context length; --max-num-seqs must be set to the model's actual batch number. To disable the chain of thought, add --default-chat-template-kwargs '{"enable_thinking": false}' when starting vllm.

vllmserve/home/user/szj_project/models/v1.2.0/qwen3.5_35B_a3b/--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-nameqwen35--max-num-batched-tokens 262144--max-num-seqs 1--max-model-len 262144--enable-auto-tool-choice--tool-call-parserqwen3_coder--additional-config='{"device_ids":[0]}'

qwen3 Series

Startup command: take qwen3 30b a3b 32K context as an example. Note the toolparser is different from qwen3.5:

vllmserve/home/user/szj_project/models/qwen3_30b_a3b_v1.2.0--port 12321--host 0.0.0.0--no-enable-prefix-caching--max-num-seqs 1--served-model-nameqwen3_30b_a3b--enable-auto-tool-choice--tool-call-parserhermes--max-num-batched-tokens 32768--max-model-len 32768

qwen3 8b Multi-Batch

Note the value of max-num-seqs must match the actual batch of the model.

vllmserve/home/user/szj_project/models/v1.2.0/qwen3_8b_16k_4batch--port 12321--host 0.0.0.0--no-enable-prefix-caching--max-num-seqs 4--served-model-nameqwen3_8b_b4--enable-auto-tool-choice--tool-call-parserhermes--max-num-batched-tokens 16384--max-model-len 16384

deepseek-8b

The startup command is as follows:

vllmserve/home/user/szj_project/models/v1.2.0/deepseek_8b--port 12321--host 0.0.0.0--no-enable-prefix-caching--max-num-seqs 1--served-model-namedeepseek_8b--enable-auto-tool-choice--tool-call-parserhermes--max-num-batched-tokens 32768--max-model-len 32768

Multimodal qwen3.5/qwen3.6 VL Series (Multiple Images Supported)

The M50 24G card supports qwen3.5/qwen3.6 35B-A3B vision-language models.

Note: visual_model_path is not the same gguf file as the language model. It is usually named with the mmproj prefix. This file path cannot use relative paths or the ~ symbol for the working directory. Use a complete absolute path, as shown below:

a)单chip模型启动示例:
vllmserve/home/user/szj_project/models/v1.3.0/qwen35_35b_a3b/--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-nameqwen35_vl--max-num-batched-tokens 262144--max-num-seqs 1--max-model-len 262144--enable-auto-tool-choice--tool-call-parserqwen3_coder--additional-config='{"enable_cacheprompt":"False","visual_model_path":"/home/user/szj_project/models/v1.3.0/qwen35_35b_a3b/mmproj-qwen3.5-35b-a3b-p256-256K-b1-2core-1d-xh2-v1.3.0-20260420210756.gguf"}' b)多chip模型启动示例-以4chip语言模型+1chip视觉模型启动为例:
vllmserve/home/lenovo/release/models/130/qwen3.6_27b_128k_4chip--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-nameqwen36_vl--max-num-batched-tokens 131072--max-num-seqs 1--max-model-len 131072--enable-auto-tool-choice--tool-call-parserqwen3_coder--additional-config='{"enable_cacheprompt":"True","visual_model_path":"/home/lenovo/release/models/130/qwen3.6_27b_128k_4chip/mmproj_xh2_qwen3.6_27b_2cores_vit_448x448_v1.3.0_20260603.gguf","device_ids":[0,1,2,3],"vl_device_ids":[3]}' 其中:
"device_ids": [0,1,2,3],指定语言模型跑在哪些卡上,示例是4chip语言模型,跑在devid 0/1/2/3这4张卡
"vl_device_ids": [3],指定视觉模型跑在哪些卡上,示例是1chipvit模型,跑在devid 3这张卡上
注意:卡的数量,要跟模型实际chip数一致。

For testing, you can attach images through chatbox or use the curl command as shown below, where "url" should be replaced with your local image or the corresponding base64 data, "model" name and key should be replaced with your own values, and the final EOF must be included.

curl-XPOST [http://127.0.0.1:12321/v1/chat/completions](http://127.0.0.1:7801/v1/chat/completions)-H "Authorization: Bearer sk-123"-H "Content-Type: application/json"-d@- <<EOF
{
 "model": "qwen35_vl",
 "messages": [
 {"role": "system", "content": "你是一个智能助理"},
 {
 "role": "user",
 "content": [
 {
 "type": "image_url",
 "image_url": {
  "url": "data:image/jpeg;base64,$(base64 -w 0 /home/user/szj_project/-examples-xh2/models/llm/qwen3.5/image_dir/frame85.jpg)"
 },
 "detail":"high"
 },
 {
 "type": "text",
 "text": "请描述图片内容。"
 }
 ]
 }
 ],
 "stream": true
}
EOF

Multimodal gemma4 Model

Startup command: divided into single-chip and multi-chip models.

Note: to enable thinking mode, add parameters at startup; see the example below.

单芯模型启动示例:
vllmserve/home/user/szj_project/models/v1.4.0/gemmar4/gemma-4-26B-A4B-it--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-namegemma4--max-num-batched-tokens 32768--max-num-seqs 1--max-model-len 32768--enable-auto-tool-choice--tool-call-parsergemma4--additional-config='{"enable_cacheprompt":"False","visual_model_path":"/home/user/szj_project/models/v1.4.0/gemmar4/gemma-4-26B-A4B-it/gemma-mmproj.gguf","device_ids":[0]}' 多芯模型启动示例:语言模型双芯,vit视觉模型单芯
vllmserve/home/user/vllm_v140_release_teset/models/gemma4_mutlichip/--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-namegemma4--max-num-batched-tokens 32768--max-num-seqs 1--max-model-len 32768--enable-auto-tool-choice--tool-call-parsergemma4--additional-config='{"enable_cacheprompt":"True","visual_model_path":"/home/user/vllm_v140_release_teset/models/gemma4_mutlichip/mmproj_xh2_gemma4-26b-a4b_2cores_vit_448x448_v1.4.0_20260609.gguf","device_ids":[0,1],"vl_device_ids":[3]}' 开启Thinking模式
vllmserve/home/user/szj_project/models/v1.4.0/gemmar4/gemma-4-26B-A4B-it--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-namegemma4--max-num-batched-tokens 32768--max-num-seqs 1--max-model-len 32768--enable-auto-tool-choice--tool-call-parsergemma4--reasoning-parsergemma4--default-chat-template-kwargs '{"enable_thinking": true}'--additional-config='{"enable_cacheprompt":"False","visual_model_path":"/home/user/szj_project/models/v1.4.0/gemmar4/gemma-4-26B-A4B-it/gemma-mmproj.gguf","device_ids":[0]}'--chat-templateexamples/tool_chat_template_gemma4.jinja

Speculative Decoding Test

1) qwen3 Draft Model Speculative Decoding

Startup command:

vllmserve/home/user/szj_project/models/v1.4.0/qwen3_14b_speculate--host 0.0.0.0--port 12321--no-enable-prefix-caching--max-num-seqs 1--served-model-nameqwen3_14b--enable-auto-tool-choice--tool-call-parserhermes--max-num-batched-tokens 32768--max-model-len 32768--additional-config='{"enable_cacheprompt":"True"}'--speculative-config '{"model": "/home/user/szj_project/models/v1.4.0/qwen3_0.6B_speculate", "num_speculative_tokens": 5, "method": "draft_model"}'

Description:

  • Verify main model: /home/user/szj_project/models/v1.4.0/qwen3_14b_speculate

  • --speculative-config '{"model": "/home/user/szj_project/models/v1.4.0/qwen3_0.6B_speculate"' points to the folder containing the draft model gguf file. The folder can contain only one gguf file starting with HiModel.

2) qwen3.5 9B MTP Speculative Decoding

Startup command:

vllmserve/home/user/szj_project/models/v1.3.0/qwen35_9b_mtp/gguf_main_verify_model/--max-model-len 262144--speculative-config '{"model":"/home/user/szj_project/models/v1.3.0/qwen35_9b_mtp/gguf_draft_model","method": "mtp", "num_speculative_tokens": 5}'--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-nameqwen35--max-num-batched-tokens 262144--max-num-seqs 1--max-model-len 262144--enable-auto-tool-choice--tool-call-parserqwen3_coder

3) qwen3.5 27B MTP Speculative Decoding

vllmserve/home/user/szj_project/models/v1.3.0/qwen36_27b_mtp--max-model-len 262144--speculative-config '{"model":"/home/user/szj_project/models/v1.3.0/qwen36_27b_mtp","method": "mtp", "num_speculative_tokens": 5}'--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-nameqwen35--max-num-batched-tokens 262144--max-num-seqs 1--max-model-len 262144--enable-auto-tool-choice--tool-call-parserqwen3_coder

gpt_oss 20B

Startup command:

VLLM_ALLOW_LONG_MAX_MODEL_LEN=1vllmserve/home/user/szj_project/models/v1.0.0/gpt_oss_20b_64K--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-namegpt_oss--max-num-batched-tokens 65536--max-num-seqs 1--max-model-len 65536--enable-auto-tool-choice--tool-call-parseropenai

If the following error occurs: openai_harmony.HarmonyError: error downloading or loading vocab file: failed to download or load vocab file, solve it as follows: (In our self-test, x86 did not encounter this error, but ARM did. gpt-oss needs the following files; the default URL may fail to download and then report an error. The following method can solve it.)

mkdir-ptiktoken_encodings
curl-L-otiktoken_encodings/o200k_base.tiktoken "https://openaipublic.blob.core.windows.net/encodings/o200k_base.tiktoken"
curl-L-otiktoken_encodings/cl100k_base.tiktoken "https://openaipublic.blob.core.windows.net/encodings/cl100k_base.tiktoken"
export TIKTOKEN_ENCODINGS_BASE=${PWD}/tiktoken_encodings

ASR Models

Model Support Overview

Model NameSupport Status
whisper-mediumSupported
whisper-turboSupported
Qwen3-ASR-0.6BSupported
GLM-ASR-Nano-2512Supported

Service Startup

vllmserve/path/to/ASR-Model \
--served-model-nameasr-model \
--no-enable-prefix-caching \
--load-formatdummy \
--additional-config='{"visual_model_path": "/path/to/ASR-Model/mmproj-asr-model.gguf"}'

Note: whisper-medium and whisper-turbo have only one main model, so the --additional-config parameter is not needed to specify an extra model.

Request Command

  • /v1/audio/transcriptions

curlhttp://127.0.0.1:8000/v1/audio/transcriptions-H "Content-Type: multipart/form-data"-F"file=@test.wav"-F"model=asr-model"-F"language=zh"-F"response_format=json"-F stream=false

Embedding Models

Startup command:

vllmserve/home/user/szj_project/models/v1.1.0/qwen3_embedding--port 12321--host 0.0.0.0--no-enable-prefix-caching--served-model-nameqwen3_embed--max-num-batched-tokens 8192--max-num-seqs 1--max-model-len 8192

Corresponding curl test command:

curlhttp://127.0.0.1:12321/v1/embeddings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-123" \
-d '{"input": "Your text string goes here",
 "model":"qwen3_embed"}'

Rerank Models

Service Startup

vllmserve/data/useradmin/models/v1.2.0/qwen3-reranker--served-model-nameqwen3-reranker-8b--max-model-len 8192--host 0.0.0.0--port 7804--api-keysk-123--hf-overrides='{"architectures": ["Qwen3ForSequenceClassification"], "classifier_from_token": ["no", "yes"], "is_original_qwen3_reranker": true}'

/v1/score request

# 单个查询对单个文档
curl-X 'POST' 'http://127.0.0.1:7804/v1/score'-H 'accept: application/json'-H 'Content-Type: application/json'-H "Authorization: Bearer sk-123"-d '{
 "model": "qwen3-reranker-8b",
 "queries": "What is the capital of France?",
 "documents": "The capital of France is Paris."
}' # 单个查询对多个文档
curl-X 'POST' 'http://127.0.0.1:7804/score'-H 'accept: application/json'-H 'Content-Type: application/json'-d '{
 "model": "qwen3-reranker-8b",
 "queries": "What is the capital of France?",
 "documents": [
 "The capital of Brazil is Brasilia.",
 "The capital of France is Paris."
 ]
}'

/v1/rerank request

curl-X 'POST' 'http://127.0.0.1:7804/v1/rerank'-H 'accept: application/json'-H 'Content-Type: application/json'-H "Authorization: Bearer sk-123"-d '{
 "model": "qwen3-reranker-8b",
 "query": "What is the capital of France?",
 "documents": [
 "The capital of Brazil is Brasilia.",
 "The capital of France is Paris.",
 "Horses and cows are both animals"
 ]
}'

Alignment Models

Model Support Overview

Model NameSupport StatusIntroduction
Qwen/Qwen3-ForcedAligner-0.6BSupportedQwen3ASRForcedAlignerForTokenClassification is a multimodal model with input type T + A+ = text + audio

Service Startup

vllmserve/path/to/Qwen3-ForcedAligner-0.6B \
--served-model-name-model \
--host 0.0.0.0 \
--port 12325 \
--api-keysk-123 \
--runnerpooling \
--enforce-eager \
--hf-overrides '{"architectures": ["Qwen3ASRForcedAlignerForTokenClassification"]}' \
--max-model-len 411 \
--load-formatdummy \
--trust-request-chat-template \
--additional-config '{"visual_model_path": "/path/to/Qwen3-ForcedAligner-0.6B/mmproj-Qwen3-ForcedAligner-Q4_0.gguf"}'

Request Command

PROMPT='参考文本' curl-s-XPOSThttp://localhost:7803/v1/audio/transcriptions \
-H "Authorization: Bearer sk-123" \
-F"file=@/path/to/test.mp3" \
-F"model=asr-model" \
-F"prompt=${PROMPT}" \
-F"language=chinese" \
-F"response_format=verbose_json"

OCR Models

Startup command:

vllmserve/home/user/models/glm_ocr--host 0.0.0.0--port 12321--no-enable-prefix-caching--served-model-nameglm-ocr--max-num-batched-tokens 2048--max-num-seqs 1--max-model-len 2048--additional-config '{"visual_model_path":"/home/user/models/glm_ocr/mmproj_xh2_glm-ocr_0.8b_2cores_v1.3.0_20260519.gguf"}'

Corresponding curl test command:

curl--location--requestPOST 'http://127.0.0.1:12321/v1/chat/completions'--header 'Content-Type: application/json'--data-raw '{"model":"glm-ocr","messages":[{"role":"user","content":[{"type":"image_url","image_url":{"url":"https://cdn.bigmodel.cn/markdown/1770033643596image.png?attname=image.png"}},{"type":"text","text":"请识别图片中的所有文字。"}]}],"temperature":0,"max_tokens":256}'

Local image test command:

curl-XPOSThttp://127.0.0.1:12321/v1/chat/completions-H "Authorization: Bearer sk-123"-H "Content-Type: application/json"-d@- <<EOF
{
 "model": "glm-ocr",
 "messages": [
 {
 "role": "user",
 "content": [
 {
 "type": "image_url",
 "image_url": {
 "url": "data:image/jpeg;base64,$(base64 -w 0 /tmp/glm_ocr_test.jpg)"
 }
 },
 {
 "type": "text",
 "text": "请识别图片中的所有文字。"
 }
 ]
 }
 ]
}
EOF

3.3 PromptCache Reuse Test

Prompt cache reuse caches the input and output of the model. When a user question carries history information, the model skips the repeated part of the history and optimizes the TTFT metric. vllm does not enable prompt cache reuse by default. To enable it, refer to the example below and add the following parameter when starting vllm:

--additional-config='{"enable_cacheprompt":"True"}'

Currently, qwen3, qwen3.5, qwen3.6, gpt-oss, and gemma4 all support promptcache reuse.

Enabling promptcache reuse can significantly reduce the TTFT response time in long-context and multi-turn scenarios that carry history messages, and reduce unnecessary repeated computation. Choose according to the usage scenario. When starting vllm, if enable_cacheprompt is not set or is set to "enable_cacheprompt":"False", promptcache reuse is disabled. In addition, put "True" or "False" in double quotes.

Reference command:

vllm serve /home/user/szj_project/models/v1.0.0/gpt_oss_20b_64K --port 12321 --host 0.0.0.0 --no-enable-prefix-caching --served-model-name gpt_oss --max-num-batched-tokens 65536 --max-num-seqs 1 --max-model-len 65536 --enable-auto-tool-choice --tool-call-parser openai --additional-config='{"enable_cacheprompt":"True"}'

Test process:

  • In AI chat tools such as HLChat, HLChatDeskTop, or chatbox, set the number of history messages to a value greater than 1.

  • Copy a long text (for example, longer than 2k) and ask the model to summarize it.

  • Check the TTFT time of the first model reply.

  • Enter the same question again and check the model TTFT time; it should be much lower than the first round and should not slow down significantly as the number of messages increases.

  • Repeat the same question several times and check the model reply TTFT time.

  • Ask a question related to a previous question and check whether the reply time and content are related to the history, and whether the TTFT value is not greater than the first long-text reply time.

4. FAQ

4.1 fastapi Version Issue

During the development and testing of HLIEvLLM v1.4.0 preview, fastapi was still version 0.136.1 and all tests were normal. After the release, the latest fastapi version was upgraded to 0.137.x, which is incompatible with HLIEvLLM v1.4.0 preview.

The highest fastapi version compatible with HLIEvLLM v1.4.0 preview is:

fastapi 0.136.3

If the version is higher, downgrade to 0.136.3 or below. 0.136.3 and 0.136.1 have been verified to work normally. These two versions are recommended.

Python inference service framework aggregating vLLM, Transformers, Diffusers, and other components with standard OpenAI interfaces and comprehensive inference services.

1. Basic Information

1.1 Version History

VersionDateDescription
3.0.1June 16, 2026- Supports speculative decoding.
- More model support, such as Qwen3-ASR, Gamma 4, CoPaw, Qwen3.6/3.5, and Qwen3-ForcedAligner.
3.0.0April 15, 2026- Supports TTS model inference channels and TTS-related interface protocols.
- Adds streaming output support for speech models (based on WebSocket).
- Deployment supports whl package installation.
- Supports dynamic model loading.
2.8.0March 13, 2026- ASR interface support; whisper model support.
2.7.0January 5, 2026- Embedding interface and inference support.
- The inference backend of text, multimodal, and embedding models switches to vLLM.
2.6.0October 10, 2025- Supports gguf models.
- Reduces model configuration and optimizes application deployment.
2.5.0August 6, 2025- Adds support for multimodal models qwen2.5-vl 3b and 7b, and the /chat/completions interface.
- Optimizes the base image compilation method for flexible toolchain version switching.
2.4.0July 2, 2025- Optimizes and fixes the request and response parameters of the OpenAI API /chat/completions and /images/generations interfaces.
- Adds image generation model support and qwen3-8b model support; reduces support for 14B models.
- Supports configuring whether to load the t5 model to the AI card through config.yaml, as well as related global configuration parameters.
2.3.0May 9, 2025- Adds an inference service deployment method: Kubernetes (manual yaml deployment, helm deployment).
2.2.0April 25, 2025- Supports single-batch, multi-batch, and 14B models; adds newly supported models such as 14B and 4batch models.
- Supports request service waiting and timeout handling.
2.1.0March 14, 2025- Decouples the application deployment package from the model deployment package, and the deployment package is platform-independent.
- Adds, optimizes, and updates supported models.
- Adds dynamic configuration parameters and a non-streaming retry mechanism to the inference service.
- Adds a health check interface, multi-card configuration, and configurable backend service model, port, device, and other settings.
2.0.0January 22, 2025- Compatible with some OpenAI interface parameters; adds support for multiple models and multiple features; resolves some known issues; multiple detail optimizations.
1.0.0July 10, 2024- Official version.

1.2 Document Purpose

This document helps you quickly connect to and start the inference service, and provides a brief introduction to log troubleshooting.

1.3 Related Access Methods

The inference service can currently be accessed in 4 ways: front-end application system version, command line version, HTTP version, and OpenAI version. Choose the access method according to the introduction below.

  • Front-end system version: Three application systems are provided as front ends. After configuring the corresponding parameters, they provide external interfaces based on the inference service, accessible and operable through a browser. This method provides an intuitive user interface and is suitable for general users; no technical knowledge is required to interact with the inference service.

  • Command line version: Interact through the terminal with command line commands; suitable for developers or technical staff. Users can send requests and view results by entering commands; debugging, HTTP client operations, and other functions are supported.

  • HTTP version: Provides RESTful API interfaces based on the HTTP protocol, allowing users to access through HTTP clients (such as curl, Postman, etc.) or integrate them into other systems.

    • Usage: users need to send HTTP requests to the specified server address, usually POST or GET, with the necessary request body parameters (such as model name and conversation content).

    • Applicable scenarios: suitable for scenarios that require code integration or integration into other business systems, with high flexibility and easy expansion.

  • OpenAI version: Access the ChatBot system through OpenAI-compatible interfaces, allowing users to reuse existing OpenAI client tools (such as the openai Python SDK) or third-party applications based on OpenAI standards.

    • Usage: users configure the provided base_url (and API key [optional]) to call it in an OpenAI-style SDK manner, for example using the chat.completions.create() method to send requests.

    • Applicable scenarios: suitable for developers with OpenAI API experience or users who want to quickly get started with the inference service, reducing the learning cost and keeping a consistent development experience.

Each access method is suitable for different user groups and application scenarios. Users can choose the appropriate access method according to their needs. For details on the four methods above, see section 4 of this document, "System Usage".

2. Inference Service Deployment

2.1 Deployment Requirements

Hardware Requirements (Minimum)

  • CPU architecture: x86_64, aarch64

  • Disk: 200G

  • AI hardware: M50

Software Requirements

  • Operating system: Ubuntu 20.04+

  • Driver version:

    • M50-v1.3.0

2.2 System Deployment Process

Note

  • Before installing this system, make sure the inference accelerator card is installed, and the driver and firmware are upgraded to the specified versions.

  • If a large model inference system of the same type is already running, take it offline first to ensure the normal operation of this service.

  • Make sure the complete installation packages (such as the application or service package and the model package) have been obtained.

2.2.1 Directory Structure

An example of the directory structure of the inference service installation package is shown below.

.
├── hliepython
│ ├── config
│ │ ├── app_config.py
│ │ └── __init__.py
│ ├── config.yaml
│ ├── __init__.py
│ ├── main.py
│ ├── model_server
│ │ ├── engines
│ │ │ ├── asr_engine.py
│ │ │ ├── base_engine.py
│ │ │ ├── embedding_engine.py
│ │ │ ├── files
│ │ │ ├── image_engine.py
│ │ │ ├── __init__.py
│ │ │ ├── protocol
│ │ │ ├── text_engine.py
│ │ │ ├── tts_engine.py
│ │ │ └── utils.py
│ │ ├── inference_adapter.py
│ │ ├── utils
│ │ │ ├── convert_gguf_to_hmm.py
│ │ │ ├── gguf_view.py
│ │ │ ├── read_gguf.py
│ │ │ └── test.py
│ │ └── worker.py
│ └── utils
├── PKG-INFO
├── pyproject.toml
└── setup.cfg

2.2.2 Service Deployment

HLIEPython depends on the HLIEvLLM service. Install HLIEvLLM before installing HLIEPython.

Refer to the HLIEvLLM Deployment and Usage Guide to install HLIEvLLM.

(1) Download the HLIEPython installation package from the inference framework section of the Beelink AI website (https://llm.bee-link.cn/frameworks.php), and extract it

Extract the archive and enter the extracted folder, for example "HLIEPython-3.0.0". Run the following command to install HLIEPython:

pipinstall-e.

(2) Modify the startup configuration

Modify the config.yaml configuration file to configure the models to be started statically.

vim hliepython/config.yaml

Note

  • [Required] Set the --max-num-batched-tokens and --max-model-len parameters to be consistent with the maximum length supported by the model.

  • Static loading and dynamic loading cannot be used at the same time in the current version; otherwise, static and dynamic model ID conflicts occur.

  • The YAML file format is strict. If startup fails with config.yaml-related errors, check whether the config.yaml format is correct, for example: indentation, spaces, and so on.

# 服务运行配置
server:
main_port: 7800
log_level: "info"
model_root_dir: "/home/useradmin/workspaces/models/v1.2.0" # 模型配置
models:
# Qwen3.5-9B 模型
-name: "Qwen3.5-9B"
instances:
-port: 7801
model_path: "qwen3.5_9B"
model_type: "text" # text、embedding、image、asr、tts
vllm_config:
max-model-len: 65536
max-num-seqs: 1
no-enable-prefix-caching: true
max-num-batched-tokens: 65536
additional_config:
device_ids: [0]
enable_cacheprompt: "False" # # Qwen3.5_VL-35B 模型
# - name: "Qwen3.5-VL_35B"
# instances:
# - port: 7802
# model_path: "qwen3.5_35b"
# model_type: "text"
# vllm_config:
# max-model-len: 262144
# max-num-seqs: 1
# no-enable-prefix-caching: true
# max-num-batched-tokens: 262144
# enable_mm_embeds: true
# additional_config:
# device_ids: [0]
# enable_cacheprompt: "False"
# "vit_model_name": "mmproj-qwen3.5-35b-a3b-p256-256K-b1-2core-1d-xh2-v1.3.0-20260420210756.gguf" # # whisper-medium 模型
# - name: "whisper-medium"
# instances:
# - port: 7803
# model_path: "whisper-medium"
# model_type: "asr"
# additional_config:
# device_ids: [0]
# enable_cacheprompt: ""

Configuration field description:

server: configures the startup items of the server side

  • main_port: the main process port number

  • log_level: the log level (cannot be modified in this version)

  • vllm_log_level: the log level of the underlying hlievllm

  • model_root_dir: the root directory for storing models

models: configures the models started statically

  • name: the model name used in requests, consistent with the model ID returned by the /v1/models interface

  • instances: model instances

    • port: the child process port number

    • model_path: the gguf model directory relative to model_root_dir; each model needs an independent directory for its gguf file

    • model_type: the model type; this version supports text, embedding, asr, tts

    • device_ids: device ids

    • vllm_config: configures the core inference engine parameters of the underlying vllm startup (Note: the vLLM parameter allowlist is not maintained here; whatever is configured is passed through. If a parameter is not supported by the AsyncEngineArgs of the current vLLM version, the underlying vLLM reports an error according to its own logic.)

    • additional_config: additional configuration for hliepython and vllm

      • device_ids: configures the device id used at startup

      • enable_cacheprompt: determines whether KV cache reuse is enabled

      • vit_model_name: adds a multimodal VIT model

Core parameters supported by the vLLM inference engine:

CategoryParameterDescription
Model configuration parameterstokenizerTokenizer path
dtypeData type (auto, half, float16, bfloat16, float32)
quantizationQuantization method
max_model_lenMaximum model length
trust_remote_codeWhether to trust remote code
Parallel configuration parameterstensor_parallel_sizeTensor parallel size
pipeline_parallel_sizePipeline parallel size
data_parallel_sizeData parallel size
distributed_executor_backendDistributed executor backend
Cache and memory parametersgpu_memory_utilizationGPU memory utilization (0-1)
kv_cache_memory_bytesKV cache memory bytes
enable_prefix_cachingEnable prefix caching
block_sizeKV cache block size
Scheduling configuration parametersmax_num_seqsMaximum number of sequences
max_num_batched_tokensMaximum number of batched tokens
max_num_partial_prefillsMaximum number of partial prefills
Other parametersenforce_eagerForce eager execution
disable_log_statsDisable statistics logging
seedRandom seed

2.2.3 Service Startup

python-mhliepython.main

3. Service Usage

Main port: 7800

3.1 Checking the Service Status

Checking the Server Status

curl-XGEThttp://0.0.0.0:7800/hlie/v1/status

Checking the Model Startup Status

curl-XGEThttp://0.0.0.0:7800/hlie/v1/models

Response parameter description:

  • data: the model information list

  • id: the model id, displayed consistently with the local model directory name

  • port: the port occupied by the current model; 0 if not loaded

  • status: whether the current model is loaded; 0 if not loaded, 1 if loaded

  • object: the fixed value "model"

  • owned_by: the owning inference engine, fixed value "HLIEPython"

  • created: the creation time of the model information

  • aliases: model aliases (not enabled in this version)

  • tags: model tags (not enabled in this version)

Dynamic Loading Example

Loading a model

Load the corresponding model according to the startup configuration parameters.

curl-XPOSThttp://0.0.0.0:7800/hlie/v1/models-H "Content-Type: application/json"-d '{ "model_name": "Qwen3-0.6B", "server_config": {"device_ids": [0], "model_type" : "text", "vllm_config": {"max-model-len": 16384, "max-num-seqs": 4, "max-num-batched-tokens": 16384}, "additional_config": {"enable_cacheprompt":"True"}}}'

Sending an inference request

curl-XPOSThttp://0.0.0.0:7801/v1/chat/completions-H "Authorization: Bearer sk-123"-H "Content-Type: application/json"-d '{"model": "Qwen3-0.6B", "messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "讲个笑话"}], "stream": true}'

Unloading a model

curl-XDELETEhttp://0.0.0.0:7800/hlie/v1/models/Qwen3-0.6B

3.2 Sending Client Requests from the Command Line

Construct the request headers and configure the specified parameters in the request body, then send the request to the server. The terminal displays the server reply. The interface parameters below are compatible with OpenAI API parameters. To add other parameters, refer to the OpenAI API parameter documentation and add them as needed. Command line request examples:

LLM

curl-XPOSThttp://0.0.0.0:7801/v1/chat/completions-H "Authorization: Bearer sk-123"-H "Content-Type: application/json"-d '{"model": "Qwen3.5-9B", "messages": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "讲个笑话"}], "stream": false}'

VLM

Compare local images and network images

curl-XPOSThttp://0.0.0.0:7802/v1/chat/completions-H "Authorization: Bearer sk-123"-H "Content-Type: application/json"-d '{
 "model": "Qwen3.5-VL_4B",
 "messages": [
 {
 "role": "user",
 "content": [
 {
 "type": "image_url",
 "image_url": {
 "url": "file:///path/to/images/test.jpg"
 }
 },
 {
 "type": "image_url",
 "image_url": {
 "url": "https://ask.qcloudimg.com/http-save/yehe-6503436/l8m9wq9ivy.jpeg"
 }
 },
 {
 "type": "text",
 "text": "请描述这两张图片的内容。"
 }
 ]
 }
 ],
 "stream": false
}'

ASR

curl-XPOSThttp://0.0.0.0:7803/v1/audio/transcriptions-H "Authorization: Bearer sk-123"-H "Content-Type: multipart/form-data"-F"model=whisper-medium"-F"language=zh"-F"response_format=json"-F"file=@test.wav"-F"stream=false"

WebSocket streaming interface:

Test the WebSocket interface demo program: [demo.py]

recv: {"type":"ready","model":"Qwen3-ASR-1.7B","port":7804,"message":"WebSocket ASR 已连接"}
recv: {"type":"ack","message":"配置已更新","language":"zh"} === 模式1:一次性发送整段音频 ===
[FULL] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask not what your country can do for you. Ask what you can do for your country.","chunk_index":1,"final":false} === 模式2:分片实时发送 ===
[CHUNK] recv: {"type":"ack","message":"音频缓冲已清空"}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, and so.","chunk_index":1,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans.","chunk_index":2,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans.","chunk_index":3,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask.","chunk_index":4,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask not.","chunk_index":5,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask not what your country can do for you—ask what you can do for your country.","chunk_index":6,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask not what your country can do for you—ask what you can do for your country.","chunk_index":7,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask not what your country can do for you.","chunk_index":8,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask not what your country can do for you. Ask what you can do for your country.","chunk_index":9,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask not what your country can do for you. Ask what you can do for your country.","chunk_index":10,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask not what your country can do for you. Ask what you can do for your country.","chunk_index":11,"final":false}
[CHUNK] recv: {"type":"transcript","text":"languageAnd so, my fellow Americans, ask not what your country can do for you. Ask what you can do for your country.","chunk_index":12,"final":false}
recv: {"type":"done","text":"languageAnd so, my fellow Americans, ask not what your country can do for you. Ask what you can do for your country.","final":true}

Note: the response data of the current interface is incremental and does not return only the independent result of the current small chunk. This is because ASR strongly depends on context; single-chunk results have large jitter, severe word segmentation problems, and poor punctuation.

The ws implementation is:

  1. When a chunk is received, append it to the server-side buffer.

  2. Re-transcribe using the complete audio accumulated up to the current point.

  3. Return the current complete hypothesis text.

You can return different modes by setting the return_type field of the request to full or delta.

TTS

curl-XPOSThttp://0.0.0.0:7804/v1/audio/speech \
-H "Authorization: Bearer sk-123" \
-H "Content-Type: application/json" \
-d '{
 "model": "Fun-CosyVoice3-0.5B",
 "input": "你好呀!的同学们。",
 "voice": "default",
 "response_format": "wav"
 }' \
--outputspeech.wav

Embedding

curlhttp://0.0.0.0:7805/v1/embeddings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer sk-123" \
-d '{
 "input": "Your text string goes here",
 "model":"qwen3_embed"
 }'

3.3 Calling through HTTP

import requests
import json
import os local_ip = "0.0.0.0"
API_URL = f"http://{local_ip}:7801/v1/chat/completions" # 设置请求头
headers = { "Content-Type" : "application/json",
} # 设置请求体
data = { "model" : "QWen2.5-7b", "messages" : [ { "role" : "system", "content" : "You are a helpful assistant." }, { "role" : "user", "content" : "讲一个笑话" } ]
} # 发送请求
response = requests. post (API_URL, headers=headers, data=json. dumps (data), stream=True) # 处理流式响应
if response. status_code == 200 : for chunk in response. iter_content (chunk_size=None): if chunk : print (chunk. decode ('utf-8'))
else : print (f"Error:{response.status_code},{response.text}")

3.4 Accessing through the OpenAI SDK

The current application software provides an OpenAI SDK-compatible implementation. You can run the following Demo program to access the backend service. Note that if the calling machine and the backend machine are not the same, modify local_ip in the program to the ip of the backend machine.

Program Requirements

  • Software requirements: the program is compatible with Python 3.7 and later. Make sure an appropriate Python version is installed to run the code.

  • Dependency libraries: the program requires the following Python libraries:

    • openai: used to access the OpenAI API for inference calls.

Install the required dependencies with the following command:

pip install openai

Configuration Modification

The current inference service is compatible with the OpenAI SDK. You can run the following Demo program to access the inference service. Note: modify base_url in the program to the ip of the machine where the inference service runs.

Example Program

import os
from openai import OpenAI base_url = "0.0.0.0:7801" def create_chat_completion (messages, use_stream=False): client = OpenAI ( base_url=f"http://{base_url}/v1", api_key="sk-xxx",) response = client. chat. completions. create ( model="QWen2.5-7b", messages=messages, stream=use_stream, max_completion_tokens=100, top_p=0.8, frequency_penalty=1.4,) if use_stream : print ("Streaming response:") for chunk in response : print (chunk. choices [0]. delta. content or "", end="", flush=True) print () else : print ("Non-streaming response:") print (response. choices [0]. message. content) def function_chat (): chat_messages = [ { "role" : "system", "content" : "You are a helpful assistant.", }, { "role" : "user", "content" : "讲一个笑话", } ] create_chat_completion (messages=chat_messages, use_stream=False) if __name__ == "__main__" : function_chat ()

Run the script:

python3 openai_sdk.py

Adapted from the official inference framework documentation for reference.