首页>其他>正文

无GPU也能跑大模型:HuggingFace转GGUF量化部署全流程

Feng 25 阅读 其他

纯CPU、无CUDA的机器上跑大模型,核心就两步:把HuggingFace权重转成GGUF容器,再量化压缩。下面以Qwen2-0.5B-Instruct为例,在Ubuntu上走完整条链路。

先给内存留条退路:Swap配置

模型加载、格式转换、权重量化三个阶段都会吃大量内存,物理内存不够时进程会被OOM Killer直接干掉。提前挂一块磁盘Swap,本次给8G。



root@localhost:~/# sudo fallocate -l 8G /swapfile
root@localhost:~/# sudo chmod 600 /swapfile
root@localhost:~/# sudo mkswap /swapfile
root@localhost:~/# sudo swapon /swapfile
root@localhost:~/# echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Swap只是兜底,不是性能优化。转换和量化阶段如果频繁触发Swap,速度会掉到难以忍受,能加物理内存就别指望Swap。

编译依赖与llama.cpp源码构建

编译工具链、运行库、Python虚拟环境工具先装齐,后面llama.cpp编译和转换脚本都靠它们。



root@localhost:~/# sudo apt update
root@localhost:~/# sudo apt install -y git build-essential cmake python3 python3-pip python3-full python3-venv tmux

拉取官方仓库并编译,make跑完后根目录会生成转换脚本。



root@localhost:~/# cd llama.cpp

root@localhost:~/# mkdir build
root@localhost:~/# cd build
root@localhost:~/# cmake ..
root@localhost:~/# make -j2

[100%] Building CXX object app/CMakeFiles/llama-app.dir/llama.cpp.o
[100%] Building CXX object app/CMakeFiles/llama-app.dir/download.cpp.o
[100%] Building CXX object app/CMakeFiles/llama-app.dir/__/license.cpp.o
[100%] Linking CXX executable ../bin/llama
[100%] Built target llama-app
[100%] Building CXX object tools/cli/CMakeFiles/llama-cli.dir/main.cpp.o
[100%] Linking CXX executable ../../bin/llama-cli
[100%] Built target llama-cli
[100%] Linking CXX executable ../bin/test-chat
[100%] Built target test-chat

root@localhost:~/# cd ..
root@localhost:~/# ls -lh convert*
-rwxr-xr-x 1 root root 13K Aug 27 16:19 convert_hf_to_gguf.py
-rwxr-xr-x 1 root root 28K Aug 27 16:19 convert_hf_to_gguf_update.py
-rwxr-xr-x 1 root root 19K Aug 27 16:19 convert_llama_ggml_to_gguf.py
-rwxr-xr-x 1 root root 23K Aug 27 16:19 convert_lora_to_gguf.py

这里有个坑:llama.cpp的构建方式近几年从纯make转向CMake为主,新版本里部分工具(比如llama-quantize、llama-cli)的可执行文件位置和命名跟老教程不一致,编译前先看仓库根目录的README确认当前构建方式,别照着旧文章硬套。

隔离Python环境,避免污染系统

转换脚本依赖一堆Python包,用独立虚拟环境跑,别往系统全局Python里装。低配内存机器上顺手关掉pip缓存写入,省磁盘也省内存。



root@localhost:~/# python3 -m venv ~/myvenv
root@localhost:~/# source ~/myvenv/bin/activate

(myvenv) root@localhost:~/llama.cpp# export TMPDIR=$HOME/tmp
(myvenv) root@localhost:~/llama.cpp# mkdir -p "$TMPDIR"
(myvenv) root@localhost:~/llama.cpp# pip install --upgrade pip
(myvenv) root@localhost:~/llama.cpp# pip install --no-cache-dir torch transformers sentencepiece protobuf safetensors huggingface_hub modelscope
(myvenv) root@localhost:~/llama.cpp# pip list

Package                Version
---------------------- ---------
annotated-doc          0.0.5
anyio                  4.14.2
certifi                2026.7.22
charset-normalizer     3.5.1
click                  8.4.2
cuda-bindings          13.3.1
cuda-pathfinder        1.7.0
cuda-toolkit           13.0.3.0
filelock               3.32.4
fsspec                 2026.7.0
h11                    0.16.0
hf-xet                 1.6.0
httpcore               1.0.9
httpx                  0.28.1
huggingface_hub        1.28.0
idna                   3.19
Jinja2                 3.1.6
markdown-it-py         4.2.0
MarkupSafe             3.0.3
mdurl                  0.1.2
modelscope             1.39.1
modelscope-hub         0.2.0
mpmath                 1.3.0
networkx               3.6.1
numpy                  2.5.2
nvidia-cublas          13.1.1.3
nvidia-cuda-cupti      13.0.85
nvidia-cuda-nvrtc      13.0.88
nvidia-cuda-runtime    13.0.96
nvidia-cudnn-cu13      9.20.0.48
nvidia-cufft           12.0.0.61
nvidia-cufile          1.15.1.6
nvidia-curand          10.4.0.35
nvidia-cusolver        12.0.4.66
nvidia-cusparse        12.6.3.3
nvidia-cusparselt-cu13 0.8.1
nvidia-nccl-cu13       2.29.7
nvidia-nvjitlink       13.3.33
nvidia-nvshmem-cu13    3.4.5
nvidia-nvtx            13.0.85
packaging              26.3
pip                    26.2.1
protobuf               7.36.0
Pygments               2.21.0
PyYAML                 6.0.3
regex                  2026.7.19
requests               2.34.2
rich                   15.0.0
safetensors            0.8.0
sentencepiece          0.2.2
setuptools             84.0.0
shellingham            1.5.4
sympy                  1.14.0
tokenizers             0.22.2
torch                  2.13.0
tqdm                   4.70.0
transformers           5.15.1
triton                 3.7.1
typer                  0.27.1
typing_extensions      4.16.0
urllib3                2.7.0

拉取原始HF模型

直接从魔搭社区拉Qwen2-0.5B-Instruct。目录里必须有config.json、model.safetensors、tokenizer.json、tokenizer_config.json,缺任何一个都说明下载不完整,重跑下载命令。



(myvenv) root@localhost:~/llama.cpp# modelscope download --model Qwen/Qwen2-0.5B-Instruct --local_dir ./Qwen2-0.5B-Instruct
(myvenv) root@localhost:~/llama.cpp# (myvenv) root@wintcp:~/llama.cpp/Qwen2-0.5B-Instruct# ls -lhA
total 954M
-rw-r--r-- 1 root root 1.5K Aug 27 16:58 .gitattributes
-rw-r--r-- 1 root root  12K Aug 27 16:58 LICENSE
-rw-r--r-- 1 root root 3.5K Aug 27 16:58 README.md
-rw-r--r-- 1 root root  659 Aug 27 16:58 config.json
-rw-r--r-- 1 root root   48 Aug 27 16:58 configuration.json
-rw-r--r-- 1 root root  242 Aug 27 16:58 generation_config.json
-rw-r--r-- 1 root root 1.6M Aug 27 16:58 merges.txt
-rw-r--r-- 1 root root 943M Aug 27 16:59 model.safetensors
-rw-r--r-- 1 root root 6.8M Aug 27 16:58 tokenizer.json
-rw-r--r-- 1 root root 1.3K Aug 27 16:58 tokenizer_config.json
-rw-r--r-- 1 root root 2.7M Aug 27 16:58 vocab.json

格式转换和量化,别混为一谈

新手最容易在这里翻车,把两件事当成一件。

HF转GGUF(convert_hf_to_gguf.py):只做格式翻译,不压缩、不掉精度。把HuggingFace的safetensors权重塞进llama.cpp专属的GGUF容器,输出f16.gguf是FP16全精度,体积大、内存占用高,只是中间过渡文件。

GGUF量化(llama-quantize):真正的权重压缩。把FP16权重压到4bit/5bit,体积和内存大幅下降。

一句话:GGUF是容器格式,不是量化格式。同一个GGUF容器里既能装f16全精度,也能装Q4_K_M量化权重。

转换完成得到Qwen2-0.5B-Instruct-f16.gguf。



(myvenv) root@localhost:~/llama.cpp# mkdir -p ./models
(myvenv) root@localhost:~/llama.cpp# python convert_hf_to_gguf.py ./Qwen2-0.5B-Instruct \
  --outtype f16 \
  --outfile ./models/Qwen2-0.5B-Instruct-f16.gguf \
  --no-lazy

再用llama-quantize对f16.gguf做Q4_K_M量化,这是4bit方案,最终产出可用模型。



(myvenv) root@localhost:~/llama.cpp# ./build/bin/llama-quantize
  ./models/Qwen2-0.5B-Instruct-f16.gguf \
  ./models/Qwen2-0.5B-Instruct-Q4_K_M.gguf \
  Q4_K_M

怎么验证转换和量化没出问题

光看文件生成不够,得实际校验。转换后可以用llama.cpp自带的推理工具加载f16.gguf跑一句中文对话,确认输出连贯、tokenizer没坏。量化后再加载Q4_K_M版本跑同样输入,对比输出是否明显劣化。

判定标准很直接:f16版本输出正常、量化版本输出语义基本一致,就说明链路通了。如果量化后输出乱码或胡言乱语,多半是转换阶段tokenizer或config没对齐,回去检查原始HF模型文件是否完整。

适用场景与风险

这套流程适合无GPU的开发机、边缘设备做模型验证和轻量推理。Q4_K_M在0.5B这种小模型上精度损失有限,但模型越大、量化等级越低,掉点越明显,生产环境上量化前务必用真实业务数据做对比测试。

另外,纯CPU推理吞吐远低于GPU,0.5B模型还能接受,7B以上建议先评估延迟是否满足业务要求,别盲目上生产。

Feng
这位作者很神秘,还没有填写简介。