使用 llama.cpp 运行 Qwen3.8-27B
我在 RTX 4090 24GB 上用 llama.cpp 跑了一遍 Qwen3.8-27B。模型使用 UD-Q4_K_M 量化,启动时同时加载 mmproj-F16.gguf。服务大约 11 秒完成初始化,两次文本请求都正常返回,生成速度在 49 tokens/s 左右。
这只是一次初步运行。我还没有测试长上下文、工具调用和持续运行的稳定性,所以这里只记录已经跑出来的结果。
下载模型
模型来自 ModelScope 上的 Qwen3.8-27B-GGUF。先按固定 ModelScope 缓存根目录设置 MODELSCOPE_CACHE,再下载 UD-Q4_K_M 权重和 F16 投影文件:
modelscope download unsloth/Qwen3.8-27B-GGUF \
--include "*Q4_K_M*" "*mmproj-F16*"下载完成后得到两个文件:
Qwen3.8-27B-UD-Q4_K_M.gguf 16464440224 bytes
mmproj-F16.gguf 927607488 bytes新版 ModelScope 的缓存目录是:
$MODELSCOPE_CACHE/models/unsloth--Qwen3.8-27B-GGUF/snapshots/master/启动前可以核对文件名和大小:
find "$MODELSCOPE_CACHE/models/unsloth--Qwen3.8-27B-GGUF/snapshots/master" \
-maxdepth 1 -type f -printf '%f %s bytes\n'主模型的实际文件名带有 UD,后面的启动命令也要使用完整名称 Qwen3.8-27B-UD-Q4_K_M.gguf。
启动 llama-server
./build/bin/llama-server 是从 llama.cpp 源码编译得到的。源码获取、CUDA 构建参数和版本检查见“编译 llama.cpp”一节。编译完成后,进入 llama.cpp 仓库目录运行:
export LLAMA_API_KEY='在这里填入你的实际 key'
./build/bin/llama-server --metrics --alias Qwen3.8-27B \
--model "$MODELSCOPE_CACHE/models/unsloth--Qwen3.8-27B-GGUF/snapshots/master/Qwen3.8-27B-UD-Q4_K_M.gguf" \
--mmproj "$MODELSCOPE_CACHE/models/unsloth--Qwen3.8-27B-GGUF/snapshots/master/mmproj-F16.gguf" \
--reasoning-preserve --jinja \
--host 0.0.0.0 --port 30104 --ctx-size 262144 -ngl 100 --fit off \
--cache-type-k q4_0 --cache-type-v q4_0 --parallel 1 \
--batch-size 4096 --ubatch-size 1024 --flash-attn on \
--load-mode mlock --threads $(nproc)本地文件启动时,主模型和投影文件需要分别通过 --model、--mmproj 指定。llama.cpp 的多模态说明介绍了两者的分工:主模型负责文本理解与生成,mmproj-F16.gguf 负责处理图片输入。这里保留 mmproj,但本次实测只发送了文本请求。
其余参数沿用之前运行 Qwen3.6-27B 的配置。--jinja 用于聊天模板和工具调用解析,--cache-type-k q4_0 与 --cache-type-v q4_0 用来压缩 KV Cache。--ctx-size 262144 能正常启动,不过我没有实际跑满 262K 上下文。
验证图片输入
加载 mmproj-F16.gguf 只说明图片投影器已经随服务启动,图片输入是否正常还要实际发一次请求。下面把本地图片编码成 Data URL,再交给 OpenAI 兼容的 /v1/chat/completions 接口:
IMAGE_DATA=$(base64 -w 0 ./test.png)
curl --noproxy '*' http://127.0.0.1:30104/v1/chat/completions \
-H "Authorization: Bearer $LLAMA_API_KEY" \
-H 'Content-Type: application/json' \
--data-binary @- <<JSON
{
"model": "Qwen3.8-27B",
"messages": [
{
"role": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "data:image/png;base64,$IMAGE_DATA"
}
},
{
"type": "text",
"text": "请描述这张图片,并抄出其中清晰可见的文字。"
}
]
}
]
}
JSON测试图片最好内容简单,并带有几处容易核对的文字。除了接口返回,还要看 llama-server 日志里是否出现图片编码过程。如果请求被当成纯文本,或者接口直接提示不支持图片,先检查 --mmproj 路径、投影文件是否与主模型配套,再确认当前 llama.cpp 构建是否包含多模态支持。这条图片请求还没有实际跑过,下面的性能数据来自两次文本请求。
运行结果
llama-server 大约 11 秒完成加载:
init: llama threadpool init, n_threads = 32
load_model: initializing, n_slots = 1, n_ctx_slot = 262144, kv_unified = 'false'
llama_server: model loaded
llama_server: listening on http://0.0.0.0:30104第一次请求处理了 371 个输入 token,生成 85 个 token:
prompt eval time = 322.84 ms / 371 tokens (1149.19 tokens per second)
eval time = 1704.65 ms / 85 tokens (49.28 tokens per second)
total time = 2027.49 ms / 456 tokens
truncated = 0第二次请求与已有上下文很接近,前缀相似度是 0.958。llama-server 复用了同一 slot 的缓存,只重新计算了 20 个输入 token。生成 804 个 token 时,速度是 49.38 tokens/s:
selected slot by LCP similarity, f_sim_best = 0.958
prompt eval time = 277.24 ms / 20 tokens (72.14 tokens per second)
eval time = 16262.84 ms / 804 tokens (49.38 tokens per second)
total time = 16540.09 ms / 824 tokens
truncated = 0从这两次请求看,模型已经能够正常加载和生成文本,前缀缓存也在工作。至于回复质量、长上下文表现和 Agent 工具调用,还需要另外测试。
unused tensor 警告
加载模型时出现了几条 blk.64 警告:
model has unused tensor blk.64.attn_q.weight -- ignoring
model has unused tensor blk.64.ffn_gate.weight -- ignoring
model has unused tensor blk.64.nextn.eh_proj.weight -- ignoring
model has unused tensor blk.64.nextn.shared_head_norm.weight -- ignoring其中既有 attention、FFN 权重,也有 nextn 权重。这与 llama.cpp 记录的 Qwen3.x MTP 块 unused tensor 问题一致。
这些警告没有影响本次普通文本生成,但也说明额外的 MTP/NextN 预测块没有参与这次推理。我没有测试 draft-mtp 推测解码,暂时保留这些警告,不对这部分能力下结论。