本人環境:macOS 15.5?(Sonoma) - Apple M1 / 16 G
目標:在 mac m1 16G 上 完全離線 的本地模型目錄上,跑通官方?ChatGLM3-6B
目錄
-
背景 & 踩坑記錄
-
準備工作
-
新建 Conda 環境并安裝依賴
-
關鍵環境變量
-
運行 composite_demo
-
常見報錯與解決方案
-
運行效果截圖
-
結語 & 參考鏈接
1 背景 & 踩坑記錄
ChatGLM3-6B 出來后,很多小伙伴(包括我🙋?♂?)直接 git clone + pip install -r requirements.txt 結果一路紅 ?:
報錯 | 根因 |
---|---|
ModuleNotFoundError: huggingface_hub.inference._text_generation | hub≥0.30 路徑改動 |
ImportError: Using low_cpu_mem_usage=True ... requires Accelerate | accelerate 版本過低 / 未裝 |
NotImplementedError: aten::isin ... on MPS | PyTorch MPS 后端缺少算子 |
RuntimeError: torch.classes ... __path__._path | Streamlit 熱重載探測 torch.classes |
因此本文一步到位給出一套「官方 issue 實測可行」的版本組合,并解釋 為什么 這樣配才最穩。
2 準備工作
-
硬件:Apple M1 (16 GB 內存起步,建議 32 GB 更穩)
-
軟件:
-
Conda ≥ 23.x(本文用 miniforge)
-
Git & Homebrew
-
-
模型文件:
~/models/chatglm3-6b/
├── config.json
├── pytorch_model-00001-of-00007.bin
├── ...
└── tokenizer.model
# 下載模型文件和權重文件?
cd models/
# 下載模型文件
git clone https://github.com/THUDM/ChatGLM3.git# 下載權重文件
# 1. 先下載小文件
GIT_LFS_SKIP_SMUDGE=1 git clone https://hf-mirror.com/THUDM/chatglm3-6b.git
# 2. 進入目錄
cd chatglm3-6b
# 3. 下載大文件(分兩步是方便看進度,因為權重50G,一步到位的下載看不到進度)
#git lfs pull 等價于先 git lfs fetch(只抓當前分支對應的對象)再 git lfs checkout(將指針替換為大文件)。
git lfs pull
也可以 git lfs clone https://huggingface.co/THUDM/chatglm3-6b,或從同事處拷貝離線權重。我這里是用的是代理方式下載。
3 新建 Conda 環境并安裝依賴
為什么固定這些版本?
transformers 4.40.0 :ChatGLM3 官方示例鎖的版本,兼容 hub<0.30
huggingface_hub 0.19.4 :仍包含舊私有路徑 _text_generation
torch 2.2.2 :MPS 穩定版,兼容 peft/cpm_kernels
accelerate 0.26.0 :device_map="auto" 需要的最低版本
streamlit 1.45.1 :避免熱重載新 BUG
其余庫滿足 GLM3 推理 + 內核 + Notebook 需求?
?新建conda 環境和下載依賴包
# 0)推薦單獨新建,避免污染原有 Python
conda create -n glm3-demo python=3.10 -y && conda activate glm3-demo# 1)一次性安裝“老三件”+ 其他依賴
pip install "torch==2.2.2" \"transformers==4.40.0" \"huggingface_hub==0.19.4" \"accelerate==0.26.0" \"peft==0.10.0" \"streamlit==1.45.1" \"cpm_kernels>=1.0.11" \"sentencepiece>=0.2.0" \"jupyter_client>=8.6.0"
?? 注意
絕對不要 pip install -U transformers 或 pip install huggingface_hub>=0.30,否則又會踩回“私有路徑丟失”坑。
如果你想體驗最新功能,需手改源碼 → 見第 6 節“升級方案”。?
4 關鍵環境變量
變量 | 作用 | 必須放在 import torch 之前 |
---|---|---|
STREAMLIT_SERVER_ENABLE_FILE_WATCHER=false | 關閉 Streamlit 熱重載,繞開 torch.classes 路徑報錯 | ? |
PYTORCH_ENABLE_MPS_FALLBACK=1 | MPS 不支持算子時自動回退 CPU,避免 isin 報錯 | ? |
設置方式:(推薦)
export STREAMLIT_SERVER_ENABLE_FILE_WATCHER=false
export PYTORCH_ENABLE_MPS_FALLBACK=1
或者在 composite_demo/main.py 頂部寫:(我沒有這么干)
import os, torch
os.environ["STREAMLIT_SERVER_ENABLE_FILE_WATCHER"] = "false"
os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
torch.classes.__path__ = [] # 再保險
5 運行?composite_demo
cd /path/to/ChatGLM3 # 倉庫根目錄
streamlit run composite_demo/main.py --server.fileWatcherType none
瀏覽器自動打開 http://localhost:8501,就能看到下圖界面👇
6 常見報錯與解決方案
報錯關鍵詞 | 可能原因 | 解決辦法 |
---|---|---|
_text_generation Not found | hub ≥ 0.30 改路徑 | 固定 hub==0.19.4 或改 client.py 引入 |
low_cpu_mem_usage=True requires Accelerate | accelerate 未裝 / 版本<0.26 | pip install -U accelerate>=0.26.0 |
aten::isin ... MPS | MPS 缺算子 | export PYTORCH_ENABLE_MPS_FALLBACK=1 或安裝 PyTorch Nightly |
torch.classes __path__._path | Streamlit 熱重載 | export STREAMLIT_SERVER_ENABLE_FILE_WATCHER=false |
OOM / swap 爆掉 | 模型全精度占內存 13 GB+ | 加 4-bit int 模型或 CPU+FP32 |
升級到最新版 transformers?
想要 4.52.x + hub 0.32.x,需要:
# client.py 舊寫法
from huggingface_hub.inference._text_generation import TextGenerationStreamResult
# 改成
from huggingface_hub.inference._generated.types.text_generation import (TextGenerationStreamResult,
)
再升級庫即可。
7 運行效果截圖
下側參數欄 = top_p / temperature / repetition_penalty / max_new_tokens
到此,Mac M1 完全離線跑 ChatGLM3-6B 的流程就梳理完畢。核心思想只有三點:
-
鎖定 “老三件”(transformers 4.40 + hub 0.19 + accelerate 0.26)
-
關閉 Streamlit 熱重載,同時 開啟 MPS Fallback
-
缺什么補什么,不輕易亂升級
-
下面講一講這個頁面的參數設置
參數設置解釋:
下面用更口語化、簡單易懂的話來解釋這四個參數,讓你一看就明白它們對生成效果的影響。
1. top_p(核采樣概率)
-
干什么的?
控制“候選詞”的范圍。模型每一步會給出很多可能的詞,并給出它們的“可能性”高低。top_p 就是說:我只要把概率累加到某個百分比,就把這些最有希望出現的詞留下來,其他概率特別低的詞就不考慮,最后在留住的那批詞中隨機選一個出來。
-
怎么影響結果?
-
如果 top_p=1.0,就意味著“全盤考慮”,所有詞都有機會被選。(這跟不做 top_p 過濾等價)
-
如果 top_p=0.8,就只在概率最前面累加到 80% 的那部分詞里挑,剩下20%低概率的詞被直接扔掉。這樣能保證輸出不會太“離譜”,也還保留了一點隨機。
-
-
簡單說:
-
把這個數字調小(比如 0.5),候選范圍就更小,句子更“保守”、更容易生成常見表達。
-
調到接近 1.0(比如 0.95),候選更多,生成會更“活躍”、“多樣”,但也有可能出現一些冷門、奇怪的詞。
-
2. 溫度(temperature)
-
干什么的?
控制“隨機性”的強弱。模型給每個詞一個得分,接著做 Softmax 變成概率。這個概率之前會先除以溫度 T:
-
把分數 ÷ T,然后再做歸一化
-
-
當 T < 1 時,分數差距會被“放大”,高分詞更容易被選,隨機性降低,句子更“確定”。
-
當 T > 1 時,分數差距會被“壓平”,低分詞的機會增大,隨機性變高,句子更“花樣”,可能有點“天馬行空”。
-
-
怎么影響結果?
-
T = 0.5(低溫度):輸出很穩定,幾乎總是挑幾率最大的詞,適合希望答案很靠譜、不愛跑偏的場景。
-
T = 1.0:默認的“正常隨機度”。
-
T = 1.3(高溫度):輸出比較活躍,可能會冒出一些有創意、沒那么常見的詞,但也容易跑題。
-
-
簡單說:
溫度越低(0.2~0.5),句子越“板正”、越不會出意外;溫度越高(1.0~1.5),句子越“活潑”、“有新意”,但風險是可能會出現不太靠譜的表達。
3. 重復懲罰(repetition_penalty)
-
干什么的?
防止模型不停地重復同一句話或同一個詞。每次模型想輸出一個已經在對話里出現過的詞,就給它打點折扣,讓它這次不要總選同一個。
-
怎么影響結果?
-
repetition_penalty = 1.0:不做懲罰(相當于關閉),模型可能出現“我我我……”“哈哈哈……”“再見再見……”這種重復。
-
repetition_penalty = 1.1:輕度懲罰,出現過一次的詞,下次出現的可能性會被除以 1.1,能稍微抑制重復。
-
repetition_penalty = 1.3 甚至更高:懲罰力度更大,模型幾乎不會重復之前那一串字。但如果懲罰過強,也可能把一些該出現的關聯詞也給壓下去,造成句子稍微奇怪。
-
-
簡單說:
想讓輸出更“豐富”、不要老是同樣幾句話循環,就把這個數字調高一點(1.1~1.2);
想讓輸出更“流暢”,沒什么重復煩惱,就留在 1.0~1.1。
4. 輸出長度(max_new_tokens 或 max_output_length)
-
干什么的?
控制“最多能多說多少字”。默認是讓模型在看到你的提問后,最多生成這么多個 token(token 通常相當于一個漢字或一個單詞的一部分)的回答。到了上限就不再往下說了。
-
怎么影響結果?
-
輸出長度 = 20~50:短小精悍的回答,就像一句話或兩句話,適合問個小問題拿個結論。
-
輸出長度 = 256~512:回答會很長,像一段段故事、長文檔、代碼示例之類,適合寫文章、寫長段解釋。
-
如果你設置得太短,模型可能回答得過于簡略;設置太長,容易讓模型“嘮叨”或跑題。
-
-
簡單說:
這就像給模型“說話時間”的最大限制——給多少就說多少。
5. 重試 & 清除歷史
-
重試:點一次“重試”就再用當前這套參數(top_p、temperature、重復懲罰、輸出長度)重新生成一個答案,通常會和上一次稍有不同,因為其中有隨機采樣的成分。
-
清除歷史:清掉當前對話框里已經生成過的所有問答內容,下次提問就好像從零開始,沒有上下文,比較適合換話題。
簡單的調參思路
-
想要穩定靠譜:
-
溫度(temperature)調低到 0.7~0.9;
-
top_p 調到 0.8 左右;
-
重復懲罰(repetition_penalty)設 1.0~1.1;
-
輸出長度控制在 128~256 之間。
這樣,生成的大部分句子都比較常規、不離譜,也不會亂跑題。
-
-
想要更“有趣”或“發散”:
-
溫度提高到 1.1~1.3;
-
top_p 增加到 0.9~0.95;
-
重復懲罰設 1.1~1.2;
-
輸出長度可以 256 起跳、甚至 512。
此時會出現一些比較新奇的表達或意想不到的句子,但也要小心有時會跑偏、語義不太連貫。
-
-
只想要一句話回答:
-
輸出長度設得小一些(如 20~50);
-
溫度 0.5~0.7;
-
top_p 0.8;
-
重復懲罰 1.0~1.1。
這樣回答簡短干脆,不會多說。
-
-
出現老是重復同一句話的情況:
-
把重復懲罰從 1.0 調到 1.2~1.3 看看;
-
也可以稍微調低溫度或調低 top_p,減少隨機性有時也有幫助。
-
總結
-
top_p(核采樣):控制候選詞的“范圍”——去掉那部分“太低概率”的詞。
-
溫度(temperature):控制隨機性——溫度低.outputs 更確定;溫度高.outputs 更隨機。
-
重復懲罰(repetition_penalty):防止循環重復——值越大越抑制重復。
-
輸出長度(max_new_tokens):規定最多能多“說”多少字,就到上限停下。
只要搞清楚它們各自的作用,就可以根據自己的需求(“要穩”還是“要酷”或“要短”)去調參,讓模型輸出符合預期。
8 結語 & 參考鏈接
-
ChatGLM3 官方 Repo
-
PyTorch GitHub Issue #77764
-
HuggingFace Hub 路徑遷移 PR #2199
建議本地部署使用量化版本,因為 m1 電腦版本還是太低了,沒有cuda,mps 目前還不支持,只靠cpu ,推理特別的慢,本次只是能用,建議換個好點的GPU啥的也行。
如果本文對你有幫助,不妨 點贊 / 收藏 / 關注,后續我會持續更新 深度學習,和大模型相關的知識 在 Apple Silicon 上的部署踩坑記錄。
Happy Hacking! 🎉