Qwen3.5-Plus - 企业级部署案例实操
在本地设备上运行新的 Qwen3.5 LLM,包括 Qwen3.5-397B-A17B!
Qwen3.5 是阿里巴巴的新一代模型家族,包括 Qwen3.5-397B-A17B,一款具有 397B 参数(17B 活跃)的多模态推理模型,其性能可与 Gemini 3 Pro、Claude Opus 4.5 和 GPT-5.2 相媲美。它支持 256K 上下文(可扩展至 1M)覆盖 201 种语言,提供思考与非思考模式,并在编码、视觉、代理、对话和长上下文任务中表现出色。
完整的 Qwen3.5-397B-A17B 模型大小为 ~807GB 在磁盘上,你可以在 192GB Mac / RAM 设备上运行 3-bit,或在 256GB Mac : 上运行 4-bit MXFP4 的 Qwen3.5-397B-A17B GGUF
所有上传均使用 Unsloth Dynamic 2.0 以实现最先进的量化性能 ------ 因此 4-bit 的重要层会提升为 8 或 16 位。感谢 Qwen 在第一天就为 Unsloth 提供访问权限。

⚙️ 使用指南
Unsloth 的 4-bit 动态量化 UD-Q4_K_XL 使用 214GB 磁盘空间 ------ 这可以直接适配到一台 256GB M3 Ultra ,并且在 1x24GB 卡和 256GB 内存 配合 MoE 卸载时,能够达到 25+ tokens/s。3**-bit**量化可以在 192GB 内存上运行,而 8-bit 需要 512GB 的内存/显存。
为获得最佳性能,请确保您的总可用内存(显存 + 系统内存)超过您正在下载的量化模型文件的大小。如果不满足,llama.cpp 仍可通过 SSD/HDD 卸载运行,但推理会更慢。
推荐设置
由于 Qwen3.5 是混合推理模型,思考和非思考模式需要不同的设置:
思考模式
非思考模式
temperature = 0.6
temperature = 0.7
top_p = 0.95
top_p = 0.8
tok_k = 20
tok_k = 20
min_p = 0
min_p = 0
repeat penalty = disabled or 1.0
repeat penalty = disabled or 1.0
-
最大上下文窗口:
262,144 -
presence_penalty = 0.0 到 2.0默认此项为关闭,但若要减少重复可使用此项,然而使用更高的值可能会导致性能略有下降 -
思考:
temperature=0.6,top_p=0.95,top_k=20,min_p=0 -
非思考:
temperature=0.7,top_p=0.8,top_k=20,min_p=0 -
适当的输出长度 :
32,768适用于大多数查询的 tokens 数量
Qwen3.5-397B-A17B 教程:
在本指南中我们将使用 Dynamic MXFP4_MOE 其在 256GB 内存 / Mac 设备上非常适合用于快速推理:
✨ 在 llama.cpp 中运行
获取最新的 llama.cpp 在 此处的 GitHub。你也可以按照下面的构建说明。将 -DGGML_CUDA=ON 改为 -DGGML_CUDA=OFF 如果你没有 GPU 或仅想使用 CPU 推理。
复制
apt-get update
apt-get install pciutils build-essential cmake curl libcurl4-openssl-dev -y
git clone https://github.com/ggml-org/llama.cpp
cmake llama.cpp -B llama.cpp/build \
-DBUILD_SHARED_LIBS=OFF -DGGML_CUDA=ON
cmake --build llama.cpp/build --config Release -j --clean-first --target llama-cli llama-mtmd-cli llama-server llama-gguf-split
cp llama.cpp/build/bin/llama-* llama.cpp
如果你想直接使用 llama.cpp 来加载模型,你可以如下操作:(:Q3_K_XL)是量化类型。你也可以通过 Hugging Face(第 3 点)下载。这类似于 ollama run 。使用 export LLAMA_CACHE="folder" 来强制 llama.cpp 保存到指定位置。请记住模型的最大上下文长度只有 200K。
按照以下方式进入 思考 模式:
复制
export LLAMA_CACHE="unsloth/Qwen3.5-397B-A17B-GGUF"
./llama.cpp/llama-cli \
-hf unsloth/Qwen3.5-397B-A17B-GGUF:MXFP4_MOE \
--ctx-size 16384 \
--temp 0.6 \
--top-p 0.95 \
--top-k 20 \
--min-p 0.00
按照以下方式进入 非思考 模式:
复制
export LLAMA_CACHE="unsloth/Qwen3.5-397B-A17B-GGUF"
./llama.cpp/llama-cli \
-hf unsloth/Qwen3.5-397B-A17B-GGUF:MXFP4_MOE \
--ctx-size 16384 \
--temp 0.7 \
--top-p 0.8 \
--top-k 20 \
--min-p 0.00 \
--chat-template-kwargs "{\"enable_thinking\": false}"
通过以下方式下载模型(在安装之后) pip install huggingface_hub hf_transfer )。你可以选择 MXFP4_MOE (动态 4bit)或其他量化版本例如 UD-Q4_K_XL 。我们建议至少使用 2-bit 动态量化 UD-Q2_K_XL 以平衡大小与精度。如果下载卡住,请查看: Hugging Face Hub、XET 调试
复制
hf download unsloth/Qwen3.5-397B-A17B-GGUF \
--local-dir unsloth/Qwen3.5-397B-A17B-GGUF \
--include "*MXFP4_MOE*" # 对于 Dynamic 2bit 使用 "*UD-Q2_K_XL*"
你可以编辑 --threads 32 来设置 CPU 线程数, --ctx-size 16384 来设置上下文长度, --n-gpu-layers 2 来设置要进行 GPU 卸载的层数。如果你的 GPU 内存不足可以调整该值;如果仅使用 CPU 推理则移除该选项。
复制
./llama.cpp/llama-cli \
--model unsloth/Qwen3.5-397B-A17B-GGUF/MXFP4_MOE/Qwen3.5-397B-A17B-MXFP4_MOE-00001-of-00006.gguf \
--ctx-size 16384 \
--temp 0.6 \
--top-p 0.95 \
--top-k 20 \
--min-p 0.00
--seed 3407
要禁用思考/推理功能,请使用 --chat-template-kwargs "{\"enable_thinking\": false}"
🦙 Llama-server 服务 & OpenAI 的 completion 库
为了将 Qwen3.5-397B-A17B 部署到生产环境,我们使用 llama-server 在一个新终端(例如使用 tmux)中,通过以下命令部署模型:
复制
./llama.cpp/llama-server \
--model unsloth/Qwen3.5-397B-A17B-GGUF/MXFP4_MOE/Qwen3.5-397B-A17B-MXFP4_MOE-00001-of-00006.gguf \
--alias "unsloth/Qwen3.5-397B-A17B" \
--temp 0.6 \
--top-p 0.95 \
--ctx-size 16384 \
--top-k 20 \
--min-p 0.00 \
--port 8001
然后在另一个新终端,在执行 pip install openai之后,执行:
复制
from openai import OpenAI
import json
openai_client = OpenAI(
base_url = "http://127.0.0.1:8001/v1",
api_key = "sk-no-key-required",
)
completion = openai_client.chat.completions.create(
model = "unsloth/Qwen3.5-397B-A17B",
messages = [{"role": "user", "content": "Create a Snake game."},],
)
print(completion.choices[0].message.content)
要禁用思考/推理功能,请使用 --chat-template-kwargs "{\"enable_thinking\": false}"
🔨与 Qwen3.5 的工具调用
参见 Tool Calling Guide 以获取有关如何进行工具调用的更多细节。在新终端中(若使用 tmux,使用 CTRL+B+D),我们创建一些工具,例如相加两个数字、执行 Python 代码、执行 Linux 功能等:
复制
import json, subprocess, random
from typing import Any
def add_number(a: float | str, b: float | str) -> float:
return float(a) + float(b)
def multiply_number(a: float | str, b: float | str) -> float:
return float(a) * float(b)
def substract_number(a: float | str, b: float | str) -> float:
return float(a) - float(b)
def write_a_story() -> str:
return random.choice([
"很久以前在一个遥远的星系......",
"有两个喜欢树懒和代码的朋友......",
"世界正在终结,因为每只树懒都进化出了超人的智慧......",
"在一个朋友不知道的情况下,另一个朋友意外编写了一个让树懒进化的程序......",
])
def terminal(command: str) -> str:
if "rm" in command or "sudo" in command or "dd" in command or "chmod" in command:
msg = "无法执行 'rm, sudo, dd, chmod' 命令,因为它们具有危险性"
print(msg); return msg
print(f"正在执行终端命令 `{command}`")
try:
return str(subprocess.run(command, capture_output = True, text = True, shell = True, check = True).stdout)
except subprocess.CalledProcessError as e:
return f"命令失败:{e.stderr}"
def python(code: str) -> str:
data = {}
exec(code, data)
del data["__builtins__"]
return str(data)
MAP_FN = {
"add_number": add_number,
"multiply_number": multiply_number,
"substract_number": substract_number,
"write_a_story": write_a_story,
"terminal": terminal,
"python": python,
}
tools = [
{
"type": "function",
"function": {
"name": "add_number",
"description": "将两个数字相加。",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "第一个数字。",
},
"b": {
"type": "string",
"description": "第二个数字。",
},
},
"required": ["a", "b"],
},
},
},
{
"type": "function",
"function": {
"name": "multiply_number",
"description": "将两个数字相乘。",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "第一个数字。",
},
"b": {
"type": "string",
"description": "第二个数字。",
},
},
"required": ["a", "b"],
},
},
},
{
"type": "function",
"function": {
"name": "substract_number",
"description": "将两个数字相减。",
"parameters": {
"type": "object",
"properties": {
"a": {
"type": "string",
"description": "第一个数字。",
},
"b": {
"type": "string",
"description": "第二个数字。",
},
},
"required": ["a", "b"],
},
},
},
{
"type": "function",
"function": {
"name": "write_a_story",
"description": "写一则随机故事。",
"parameters": {
"type": "object",
"properties": {},
"required": [],
},
},
},
{
"type": "function",
"function": {
"name": "terminal",
"description": "在终端执行操作。",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "你希望执行的命令,例如 `ls`, `rm`, ...",
},
},
"required": ["command"],
},
},
},
{
"type": "function",
"function": {
"name": "python",
"description": "调用 Python 解释器运行一些 Python 代码。",
"parameters": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "要运行的 Python 代码",
},
},
"required": ["code"],
},
},
},
]
显示全部 148 行
然后我们使用下面的函数(复制粘贴并执行),它们将自动解析函数调用并为任何模型调用 OpenAI 端点:
复制
from openai import OpenAI
def unsloth_inference(
messages,
temperature = 0.6,
top_p = 0.95,
top_k = 20,
min_p = 0.00,
repetition_penalty = 1.0,
):
messages = messages.copy()
openai_client = OpenAI(
base_url = "http://127.0.0.1:8001/v1",
api_key = "sk-no-key-required",
)
model_name = next(iter(openai_client.models.list())).id
print(f"使用模型 = {model_name}")
has_tool_calls = True
original_messages_len = len(messages)
while has_tool_calls:
print(f"当前消息 = {messages}")
response = openai_client.chat.completions.create(
model = model_name,
messages = messages,
temperature = temperature,
top_p = top_p,
tools = tools if tools else None,
tool_choice = "auto" if tools else None,
extra_body = {"top_k": top_k, "min_p": min_p, "repetition_penalty" :repetition_penalty,}
)
tool_calls = response.choices[0].message.tool_calls or []
content = response.choices[0].message.content or ""
tool_calls_dict = [tc.to_dict() for tc in tool_calls] if tool_calls else tool_calls
messages.append({"role": "assistant", "tool_calls": tool_calls_dict, "content": content,})
for tool_call in tool_calls:
fx, args, _id = tool_call.function.name, tool_call.function.arguments, tool_call.id
out = MAP_FN[fx](**json.loads(args))
messages.append({"role": "tool", "tool_call_id": _id, "name": fx, "content": str(out),})
else:
has_tool_calls = False
return messages
显示全部 40 行
在通过 llama-server 启动 Qwen3.5 之后, Qwen3.5 像在 Tool Calling Guide 或参见