在本地部署Qwen大語言模型全過程總結(jié)
1. 理論計(jì)算
大語言模型要進(jìn)行本地部署,先得選擇一個(gè)與本地環(huán)境適配的模型。比如筆者這里選擇的是Qwen1.5-7B-Chat,那么可以計(jì)算一下需要的存儲(chǔ)空間大小:
- 這里的
7B代表7-billion,也就是7×10?參數(shù)。 - 每個(gè)參數(shù)是
4字節(jié)浮點(diǎn)型。 - 一次性加載所有參數(shù)需要
7×10?×4 Bytes的存儲(chǔ)空間 7×10?×4 Bytes約等于28GB
入門消費(fèi)級(jí)的顯卡的顯存是很少能滿足這個(gè)存儲(chǔ)要求的,比如筆者這里用的Nvidia GeForce RTX 4060 laptop只有8GB顯存。為了能在這臺(tái)機(jī)器上使用Qwen1.5-7B-Chat,就要進(jìn)行量化。“量化”是個(gè)很專業(yè)的詞匯,但其實(shí)沒那么難理解,簡單來說就是“壓縮精度”,或者“降低分辨率”的意思。比如全精度的模型參數(shù)是4字節(jié)浮點(diǎn)型,將其重新映射到8位整型:
| 原始值(FP32) | 量化后(INT8) |
|---|---|
| 0.123 | 15 |
| -0.456 | -58 |
| 0.999 | 127 |
實(shí)現(xiàn)原理很簡單,就是把一個(gè)浮點(diǎn)范圍(比如-1.0到+1.0)劃分成256個(gè)離散的等級(jí)(因?yàn)?8-bit可以表示2?=256個(gè)值),然后每個(gè)原始值“四舍五入”到最近的那個(gè)等級(jí)。這種處理辦法在信號(hào)處理或者數(shù)字圖形處理中也非常常見。
如果使用8-bit量化,那么7B模型大概只需要7GB顯存,理論是可以在8GB顯存的機(jī)器上部署的。不過實(shí)際上大模型運(yùn)行不是只有模型權(quán)重參數(shù)這么簡單,實(shí)際的顯存占用=模型權(quán)重+中間緩存+ 優(yōu)化器狀態(tài)+輸入輸出等,所以最好還是使用4-bit量化。
2. 下載模型
一般開源的大模型都是托管在Hugging Face上,這里使用的Qwen1.5-7B-Chat也不例外。不過Hugging Face在國內(nèi)因?yàn)榫W(wǎng)絡(luò)問題連接不上,因此可以使用鏡像站HF-Mirror。Hugging Face上的大模型數(shù)據(jù)可以使用git工具來下載,不過大模型的單個(gè)文件可能比較大,需要開啟git lfs,使用起來還是有點(diǎn)麻煩。感覺git還是不太適合管理非代碼項(xiàng)目,因此還是推薦使用Hugging Face 官方提供的命令行工具h(yuǎn)uggingface-cli來下載大模型。
首先是安裝依賴:
pip install -U huggingface_hub
然后設(shè)置環(huán)境變量:
export HF_ENDPOINT=https://hf-mirror.com
最后下載模型:
huggingface-cli download --resume-download Qwen/Qwen1.5-7B-Chat --local-dir Qwen1.5-7B-Chat
3. 環(huán)境配置
需要說明的是因?yàn)椴渴鸫竽P托枰惭b非常多的依賴包,它們之間的依賴關(guān)系可能不一致,所以有的時(shí)候會(huì)因?yàn)榘姹緵_突安裝不上。而且依賴庫的源也一直在更新,現(xiàn)在不行說不定以后就可以了,只能講講大概的配置思路。
筆者這里使用的操作系統(tǒng)是Ubuntu Desktop 24.04 LTS,其實(shí)版本有點(diǎn)太新了,會(huì)導(dǎo)致低版本的CUDA或者PyTorch安裝找不到相應(yīng)的安裝包。Linux的兼容性不像Windows那么強(qiáng),有時(shí)候安裝不上就只能重編譯了。推薦使用Ubuntu 22.04版本可能會(huì)更好。
3.1 顯卡驅(qū)動(dòng)
安裝顯卡驅(qū)動(dòng):
sudo ubuntu-drivers autoinstall
筆者使用的是筆記本電腦,為了避免切換顯卡的麻煩就在Ubuntu桌面的顯卡設(shè)置中設(shè)置成獨(dú)立顯卡獨(dú)占的模式。輸入如下指令:
nvidia-smi
就會(huì)輸出NVIDIA GPU的詳細(xì)信息,包括使用的驅(qū)動(dòng)版本、GPU溫度、顯存使用情況、功率消耗以及正在運(yùn)行的進(jìn)程等:
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.163.01 Driver Version: 550.163.01 CUDA Version: 12.4 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 4060 ... Off | 00000000:01:00.0 Off | N/A |
| N/A 37C P8 3W / 55W | 189MiB / 8188MiB | 0% Default |
| | | N/A |
+-----------------------------------------+------------------------+----------------------+
+-----------------------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=========================================================================================|
| 0 N/A N/A 2699 G /usr/lib/xorg/Xorg 138MiB |
| 0 N/A N/A 3043 G /usr/bin/gnome-shell 40MiB |
| 0 N/A N/A 3227 G /opt/freedownloadmanager/fdm 2MiB |
+-----------------------------------------------------------------------------------------+
3.2 CUDA
安裝CUDA除了要跟操作系統(tǒng)適配,還有個(gè)麻煩的地方就是不同的依賴包對(duì)CUDA版本的要求不一致。依賴包的沖突可以通過虛擬環(huán)境解決,但是CUDA版本沖突就有點(diǎn)麻煩;這里就介紹一下筆者的辦法。
首先正常安裝CUDA的某個(gè)版本,比如筆者先安裝的是12.9。這時(shí)輸入指令:
nvcc --version
可以檢查是否安裝好12.9的版本。然后輸入指令:
which nvcc
這個(gè)指令是用來查詢cuda在操作系統(tǒng)的具體路徑。筆者顯示的是:
/usr/local/cuda-12.9/bin/nvcc
那么操作系統(tǒng)是怎么找到這個(gè)路徑地址的呢,一般是在安裝CUDA的時(shí)候添加到~/.bashrc這個(gè)文件來實(shí)現(xiàn)的。~/.bashrc是Linux中一個(gè)非常重要的用戶級(jí)shell配置文件,會(huì)在每次打開一個(gè)新的Bash終端時(shí)自動(dòng)執(zhí)行。打開這個(gè)文件夾,找到:
export PATH=/usr/local/cuda-12.9/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-12.9/lib64:$LD_LIBRARY_PATH
這部分配置,將其修改成:
export PATH=/usr/local/cuda/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
/usr/local/cuda是個(gè)軟鏈接,會(huì)指向/usr/local/cuda-12.9這個(gè)文件夾。我們的目標(biāo)就是根據(jù)需要修改這個(gè)軟鏈接,達(dá)到切換CUDA版本的目的。
接著安裝CUDA的第二個(gè)版本,筆者這里安裝的是CUDA 12.6。不太確定第二次安裝是否會(huì)將軟鏈接覆蓋了,但是沒有關(guān)系。安裝好兩個(gè)版本之后,如果要切換12.9版本:
sudo rm -f /usr/local/cuda
sudo ln -s /usr/local/cuda-12.9 /usr/local/cuda
如果要切換12.6版本:
sudo rm -f /usr/local/cuda
sudo ln -s /usr/local/cuda-12.6 /usr/local/cuda
切換完成之后可以通過指令nvcc --version查看是否修改成功:
charlee@charlee-pc:~$ nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2024 NVIDIA Corporation
Built on Fri_Jun_14_16:34:21_PDT_2024
Cuda compilation tools, release 12.6, V12.6.20
Build cuda_12.6.r12.6/compiler.34431801_0
3.3 庫包
安裝Anaconda的過程這里就不介紹了,使用Anaconda主要是為了配置Python虛擬環(huán)境,解決依賴庫地獄的問題。安裝完成后使用如下指令安裝虛擬環(huán)境:
conda create --name llm python=3.11
然后激活虛擬環(huán)境:
conda activate llm
接下來就是安裝開源深度學(xué)習(xí)框架PyTorch,這個(gè)包非常重要,并且一般不通過Python默認(rèn)pip地址獲取,在其官方網(wǎng)站提供了具體的下載指令。比如筆者使用的基于CUDA12.6的PyTorch 2.7.1版本:
pip install torch==2.7.1 torchvision==0.22.1 torchaudio==2.7.1 --index-url https://download.pytorch.org/whl/cu126
最后安裝部署大模型需要的依賴包:
pip install bitsandbytes transformers accelerate
其中bitsandbytes是優(yōu)化LLM推理和訓(xùn)練的開源工具庫,這里用來進(jìn)行4-bit量化。除了bitsandbytes,auto-gptq也可以4-bit量化,不過筆者第一次的環(huán)境中安裝auto-gptq總是安裝不上,就轉(zhuǎn)成使用bitsandbytes了。應(yīng)該是Python、顯卡驅(qū)動(dòng)或者CUDA的版本太高了不兼容。
4 進(jìn)行對(duì)話
最后一步就是啟動(dòng)大語言模型與其對(duì)話了。其實(shí)可以使用像Ollama這樣的工具來一鍵部署,或者使用Gradio來實(shí)現(xiàn)圖形界面。不過這里這里還是簡單的實(shí)現(xiàn)一輪對(duì)話的例子,因?yàn)楣P者想以此來了解一點(diǎn)底層的東西。畢竟如果為了實(shí)現(xiàn)大模型對(duì)話,直接使用官方在線部署的大模型就可以了。具體的Python腳本如下所示:
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch
# 修改為你的本地模型路徑
model_id = "/home/charlee/work/Qwen1.5-7B-Chat"
# 配置量化(可選)
quant_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.float16
)
# 從本地路徑加載模型和分詞器
model = AutoModelForCausalLM.from_pretrained(
model_id,
quantization_config=quant_config,
device_map="auto",
trust_remote_code=True
)
tokenizer = AutoTokenizer.from_pretrained(
model_id,
trust_remote_code=True
)
# 設(shè)置 pad_token
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
tokenizer.pad_token_id = tokenizer.eos_token_id
# 構(gòu)造對(duì)話輸入
messages = [{"role": "user", "content": "用 Python 寫一個(gè)快速排序"}]
inputs = tokenizer.apply_chat_template(
messages,
return_tensors="pt",
add_generation_prompt=True
).to("cuda")
# 生成 attention_mask
attention_mask = (inputs != tokenizer.pad_token_id).long()
# 生成輸出
outputs = model.generate(
input_ids=inputs,
attention_mask=attention_mask,
max_new_tokens=512,
temperature=0.6,
top_p=0.9,
do_sample=True,
pad_token_id=tokenizer.eos_token_id,
eos_token_id=tokenizer.eos_token_id
)
# 只解碼生成的部分
generated_ids = outputs[0][inputs.shape[-1]:]
response = tokenizer.decode(generated_ids, skip_special_tokens=True)
print(response)
最終運(yùn)行的結(jié)果如下所示:


浙公網(wǎng)安備 33010602011771號(hào)