struct.error: unpack requires a buffer of 4 bytes when loading Qwen3Moe GGUF file with ktransformers
检查清单
- [x] 1. 我已经搜索过相关问题,但未能获得预期的帮助
- [x] 2. 该问题在最新版本中尚未修复
- [x] 3. 请注意,如果您提交的BUG相关 issue 缺少对应环境信息和最小可复现示例,我们将难以复现和定位问题,降低获得反馈的可能性
- [x] 4. 如果您提出的不是bug而是问题,请在讨论区发起讨论 https://github.com/kvcache-ai/ktransformers/discussions。否则该 issue 将被关闭
- [x] 5. 为方便社区交流,我将使用中文/英文或附上中文/英文翻译(如使用其他语言)。未附带翻译的非中文/英语内容可能会被关闭
问题描述
在使用 ktransformers 加载 Qwen3-30B-A3B的 GGUF 量化文件时,出现 struct.error: unpack requires a buffer of 4 bytes 错误,导致模型无法加载。该 GGUF 文件已验证文件头为合法的 GGUF 格式,哈希值与网站上的文件相同,但 ktransformers 的 GGUFLoader 解析时始终失败。
复现步骤
1、使用了ModelScope内unsloth/Qwen3-30B-A3B-GGUF的两个版本(Q4_0,Q8_0) 2、命令 2-1.(base) nh@CHS:~/ktransformers$ conda activate kt-LLM 2-2.(kt-LLM) nh@CHS:~/ktransformers$ python ktransformers/server/main.py --model_path /home/nh/LLM-Model/Qwen3-30B-A3B --gguf_path /home/nh/LLM-Model/Qwen3-30B-A3B-GGUF/ --optimize_config_path ktransformers/optimize/optimize_rules/Qwen3Moe-serve.yaml
环境信息
操作系统:Ubuntu 22.04 Python 版本:3.11.5 ktransformers 版本:已经为最新 依赖库版本: torch:2.8.0+cu128 llama-cpp-python:0.1.50 flashinfer:0.2.0 GPU:NVIDIA RTX 5080 CUDA 版本:12.8
降到tag为v0.3.2重新编译试一下?
短结论:这是典型的 GGUF 头部或偏移读错位。常见三类原因
- 文件不完整或被代理改写。分片未合并、断点续传截断、下载到 HTML 页面。
- GGUF 版本或格式不兼容,文件版本高于当前 ktransformers 的 GGUFLoader 支持。
- Qwen3-MoE 的 GGUF 需要 loader 具备 MoE 支持,旧版本解析器会在读取 header 或 tensors 索引时触发
unpack requires a buffer of 4 bytes。
快速自检(5 分钟能确定原因)
-
验证文件本体
sha256sum <model.gguf>对照发布页校验wc -c <model.gguf>看字节数是否和官方一致- 若是分片
*.gguf.*记得先cat part* > model.gguf合并 - 确认不是下载到重定向 HTML,
file <model.gguf>或head -c 8 <model.gguf>应该出现GGUF魔数
-
用独立工具校验 GGUF
llama-cli --print-gguf <model.gguf>或等价脚本- 能打印出 header 和 tensors 列表,说明文件本体 OK。如果这里也报错,就是文件或版本问题
-
对齐 loader 与 MoE 支持
- 升到 ktransformers 最新 master 或 nightly,确保包含 GGUF 的 MoE 解析支持
- 若最新仍失败,先用非 MoE 的 Qwen GGUF 验证一遍,排除模型侧因素
- 作为对照,用 llama.cpp 加载同一 GGUF。如果 llama.cpp 正常而 ktransformers 失败,基本就是 GGUFLoader 兼容性
常见修复
- 重新下载,用
aria2c -c -x16之类并比对校验和,避免代理对 Range 响应做压缩或改写 - 合并分片后再加载
- 升级到包含 MoE GGUF 支持的 ktransformers 版本。无法升级时,临时改用非 MoE GGUF 或用 llama.cpp 推理做验证
如果你能贴出:sha256sum、llama-cli --print-gguf 的前 30 行、以及你当前的 ktransformers 版本号,我可以帮你断点定位到底是文件问题还是 loader 兼容问题。
降到tag为v0.3.2重新编译试一下?
使用pip show ktransformers,version为0.3.2+cu128torchavx2
看起来这不是你代码的问题,而是 GGUF 文件和 loader 版本/能力不匹配。常见排查步骤:
- 先校验 GGUF 文件完整性,
sha256sum对照官方值,再用 gguf 工具打印 header 和 tensors 列表,确认能正常读。 - 你用的是 Qwen3 MoE 变体,ktransformers 老版本对 MoE-GGUF 支持不完整,建议先试最新 nightly 版本;也可以交叉用 llama.cpp 打开同一个文件,如果能读说明就是 loader 差异。
- 检查 config 里的参数(n_ctx, heads 等)是否和 GGUF meta 信息一致,不一致也会触发越界报错。
如果是文件损坏,用 aria2c -x16 重新下载一遍;如果 llama.cpp 正常、ktransformers 报错,那就是 MoE 支持还没完全补上。
这种情况在我们的 ProblemMap 里对应 No.14(Bootstrap Ordering / 加载顺序问题),有完整 checklist 可以参考:
https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md
看起来这不是你代码的问题,而是 GGUF 文件和 loader 版本/能力不匹配。常见排查步骤:
- 先校验 GGUF 文件完整性,
sha256sum对照官方值,再用 gguf 工具打印 header 和 tensors 列表,确认能正常读。- 你用的是 Qwen3 MoE 变体,ktransformers 老版本对 MoE-GGUF 支持不完整,建议先试最新 nightly 版本;也可以交叉用 llama.cpp 打开同一个文件,如果能读说明就是 loader 差异。
- 检查 config 里的参数(n_ctx, heads 等)是否和 GGUF meta 信息一致,不一致也会触发越界报错。
如果是文件损坏,用
aria2c -x16重新下载一遍;如果 llama.cpp 正常、ktransformers 报错,那就是 MoE 支持还没完全补上。这种情况在我们的 ProblemMap 里对应 No.14(Bootstrap Ordering / 加载顺序问题),有完整 checklist 可以参考: https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md
使用llama.cpp可以正常进行部署,这说明gguf文件没有问题,现在KT版本是0.3.2了,还是出现问题
(kt-LLM) nh@CHS:~/ktransformers$ python ktransformers/server/main.py --port 10002 --model_path /home/nh/LLM-Model/Qwen3-30B-A3B --gguf_path /home/nh/LLM-Model/Qwen3-30B-A3B-GGUF/Qwen3-30B-A3B-Q4_K_M.gguf --optimize_config_path ktransformers/optimize/optimize_rules/Qwen3Moe-serve.yaml --max_new_tokens 1024 --cache_lens 32768 --chunk_size 256 --max_batch_size 4
2025-08-26 10:45:01,368 - INFO - flashinfer.jit: Prebuilt kernels not found, using JIT backend
found flashinfer
found flash_attn
set start method
Connected to server at tcp://localhost:51637
2025-08-26 10:45:03,626 - INFO - flashinfer.jit: Prebuilt kernels not found, using JIT backend
found flashinfer
found flash_attn
start method already set to spawn
Connected to server at tcp://localhost:51637
args.architectures: Qwen3MoeForCausalLM
The argument trust_remote_code is to be used with Auto classes. It has no effect here and is ignored.
Process SpawnProcess-1:
Traceback (most recent call last):
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/multiprocessing/process.py", line 314, in _bootstrap
self.run()
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/site-packages/ktransformers/server/backend/interfaces/balance_serve.py", line 300, in run_engine
engine = Engine(args, token_queue, broadcast_endpoint, kvcache_event)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/site-packages/ktransformers/server/backend/interfaces/balance_serve.py", line 204, in init
optimize_and_load_gguf(self.model, optimize_config_path, gguf_path, config)
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/site-packages/ktransformers/optimize/optimize.py", line 126, in optimize_and_load_gguf
weights_loader = ModelLoaderFactory.create_loader(gguf_path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/site-packages/ktransformers/util/custom_loader.py", line 536, in create_loader
return GGUFLoader(path)
^^^^^^^^^^^^^^^^
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/site-packages/ktransformers/util/custom_loader.py", line 295, in init
self.load_gguf(f)
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/site-packages/ktransformers/util/custom_loader.py", line 315, in load_gguf
info[name] = read_value(f, data_type)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/site-packages/ktransformers/util/custom_gguf.py", line 210, in read_value
return [read_value(f, elem_type) for _ in range(count)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/nh/anaconda3/envs/kt-LLM/lib/python3.11/site-packages/ktransformers/util/custom_gguf.py", line 210, in
下面我用AI輔助幫忙回應 (使用我的WFGY辦法),希望別介意
===
先說結論:你這條仍然是 GGUF 與 loader 版本/路由不匹配,屬於 ProblemMap No.14 的範圍。從你新貼的 log 看,模型本身多數機率是好的,崩在 loader 解 header / tensors 的位置。建議直接做下面最短四步,把「是不是檔案壞」跟「是不是 loader 不支援」切開:
A. 驗證檔案本體
- 檢查分片與總檔校驗
sha256sum model*.gguf
wc -c model*.gguf
比對和來源提供的校驗與大小是否一致。
- 讀 header 3 個關鍵欄位(用 gguf 套件)
python - <<'PY'
import sys, gguf
r = gguf.GGUFReader(sys.argv[1])
print("arch=", r.get_meta("general.architecture"))
print("file_type=", r.get_meta("general.file_type"))
print("tensor_count=", r.get_tensor_count())
PY
./your_model.gguf
把這三行輸出貼回來即可。若這裡能讀,檔案本體沒壞。
B. 用 baseline 驗證 loader 3) 用 llama.cpp 先試讀一次,確定檔案可被 baseline loader 接上
./main -m ./your_model.gguf -t 1 -n 1 --verbose
能起就代表檔案 OK,問題在 ktransformers 的 GGUF loader 支援度。
C. 針對 ktransformers
4) 先固定一版可讀 GGUF 的 nightly 或明確版本,再試。Qwen3-MoE 這類模型常需要較新的 loader 路由。若你是 ar/ax 類 kvcache,先退回一般路徑。
若仍錯,收斂成最小重現:單卡、關混合精度、關 offload,把 heads/kv_rank 這類 MoE 關鍵 meta 一併貼出。
這樣做的目的很簡單:
- A 能排除「檔案壞/分片不齊」
- B 能切出「檔案好,但某個 loader 不支援」
- C 才是對症下 loader 的修復或版本釘選
如果你想更快一點,也可以用我前面給的 ProblemMap 檢查表走一次,或下載 TXTOS,直接問任一 LLM:「use WFGY,幫我把這個 GGUF 載入錯誤歸類並給 No.」。通常一分鐘就能得到同樣的 No.14 結果與對應步驟。
先跑 A、B 兩步,貼三行 header 與一行 llama.cpp 是否能啟動,我再幫你把 ktransformers 該固定的版本與參數對掉。
降到tag为v0.3.2重新编译试一下?
使用pip show ktransformers,version为0.3.2+cu128torchavx2
checkout到tag为v0.3.2分支,使用多流的编译,USE_BALANCE_SERVE=1 bash ./install.sh。编完后,version应该是v0.3.1