周红伟:Qwen3.5-Plus - 企业级部署案例实操,Qwen3.5 LLM,包括 Qwen3.5-397B-A17B

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 或参见

相关推荐
balmtv7 分钟前
Grok 3技术深度拆解:20万卡集群、思维链推理与DeepSearch的架构实现
人工智能·架构
毅航17 分钟前
告别 AI 名词焦虑:一文读懂从 LLM 到 Agent Skill的演进
人工智能·后端
秦ぅ时1 小时前
Grok-3-Fast-Beta 完整解析:xAI 低延迟大模型 + 可直接运行调用代码
人工智能·gpt·microsoft
聚客AI1 小时前
✅自托管AI网关的正确姿势:OpenClaw远程访问与安全配置
人工智能·agent·掘金·日新计划
brave and determined1 小时前
工程设计类学习(DAY25):高频PCB设计:射频布局与屏蔽腔体规范
人工智能·emc·电磁兼容·emi·屏蔽罩·电磁屏蔽·层叠设计
AI专业测评2 小时前
2026年AI写作软件底层逻辑横评:长篇网文如何破局“上下文遗忘”与“AI消痕”?
人工智能·自然语言处理·ai写作
霖大侠2 小时前
CPAL: Cross-Prompting Adapter With LoRAs forRGB+X Semantic Segmentation
人工智能·深度学习·算法·机器学习·transformer
火山引擎开发者社区2 小时前
火山 AI 生态新玩法:ArkClaw 一键生成漫剧,效率直接拉满
人工智能
一起来学吧3 小时前
【OpenClaw系列教程】第一篇:OpenClaw 完整介绍——开源 AI 智能体平台
人工智能·ai·openclaw·养龙虾
飞Link3 小时前
工业级时序异常检测利器:USAD 算法深度解析与实战
人工智能·深度学习·机器学习