Text Generation
llama-cpp-python
GGUF
llama.cpp
Mixture of Experts
ssd-offload
smallthinker
expert-paging
low-ram
Instructions to use HelloSun/SmallThinker4b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- llama-cpp-python
How to use HelloSun/SmallThinker4b with llama-cpp-python:
# !pip install llama-cpp-python from llama_cpp import Llama llm = Llama.from_pretrained( repo_id="HelloSun/SmallThinker4b", filename="{{GGUF_FILE}}", )output = llm( "Once upon a time,", max_tokens=512, echo=True ) print(output)
- Notebooks
- Google Colab
- Kaggle
File size: 4,591 Bytes
1e54449 370fce7 f279c31 370fce7 1e54449 370fce7 1e54449 370fce7 1e54449 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | # AGENTS.md — 續作指引
**這個檔案的存在理由:本機很不穩,agent 可能隨時崩潰。**
無論你(人或 agent)從哪裡開始,只要 clone 這個 repo 並讀完本檔,就能接著做。
```bash
git clone https://huggingface.co/HelloSun/SmallThinker4b
cd SmallThinker4b
cat STATUS.md # 進度真相來源,先讀這個
cat AGENTS.md # 本檔
```
## 專案一句話
SmallThinker-4B-A0.6B-Instruct(Q4_K_M,2508 MiB,MoE 32 層 × 32 experts)
在 llama.cpp 上跑,**熱的 expert 權重留在 RAM,冷的丟回 SSD**。
## 最重要原則(聽到沒)
**只要到能跑、能驗證的階段,就立刻上傳。後面每改到程式並編譯過,也要上傳。**
本機十分不穩,你必須保存工作成果,並且假設 agent 崩潰後要能指定 repo 繼續工作。
```bash
./sync.sh "改了什麼"
```
`git clone https://huggingface.co/HelloSun/SmallThinker4b` 就能接著做。
## 硬約束
1. 行程**總 RSS**(含 file-backed mmap 的權重頁)要受 RAM 預算約束。
只驗證匿名記憶體是不成立的 —— 權重頁會算進 RSS 且真的佔用系統 RAM。
2. **VmSwap = 0**。
3. **輸出必須與上游逐字相同**。分頁只該影響「權重住哪裡」,
不該影響任何一個 token 的數值。
實測成果(`validate/ab-test.json`,`all_passed: true`):
peak RSS 從上游的 **2.565 GiB** 降到 **0.596 GiB**(預算 256 MiB,−76.8%),
swap 全程 0,冷權重真的從 SSD 重讀 2.3 GiB,輸出四種設定逐字相同。
## 已知的坑(不要重蹈)
完整清單在 `STATUS.md` 的「踩過的坑」表格,每一條都有實測證據。
最容易再犯的三個:
1. **`-DGGML_CPU_REPACK=OFF` 是硬性要求**。開著時 ggml 把權重放進匿名緩衝區,
`madvise` 會把它**歸零**,輸出變亂碼但行程看起來正常。
2. **`init_mappings(!st::will_page(arch))` 這個 `!` 不能拿掉**。
它是整個機制裡最容易寫反的一行 —— 寫反的話 peak RSS 會變成 2.6 GiB,
但分頁統計看起來完全正常(sweep 有跑、帳面 resident 也對),
所以**光看分頁統計抓不到**。
3. **`fscanf` 讀 `/proc/self/io` 開頭要空格**,否則 `read_bytes` 永遠是 0。
4. **`will_page()` 只能看 arch,不能看 `enabled()`** ——
`init_mappings()` 在權重載入之前跑,那時 `register_model()` 還沒被呼叫。
## 環境
本機(開發/驗證用):16 vCPU、MemTotal 約 2 TB、cgroup `memory.max` = 104 GB、
無 GPU。SSD 是 **overlayfs**。
**換機器一定要用 `tools/io_probe.py` 重測讀取能力**,tok/s 會跟著全變。
## 常用指令
```bash
# 完整流程
ST_HOME=~/.cache/smallthinker4b ./llama_server.sh --verify
# 只看參數
./llama_server.sh --plan
# A/B 驗證
python3 tools/ab_test.py --bin <llama-cli> --model <gguf> \
--budget 1024 --budget 512 --out validate/ab-test.json
# 對照組(關分頁)
ST_PAGER=0 ./llama_server.sh
# 上傳
./sync.sh "改了什麼"
```
## 下一步(可選,非必要)
1. **I/O 預取**:目前是 demand paging(第一次碰到缺頁才讀 SSD)。
可以在 sweep 裡對「下一個 token 極可能用到、但現在是冷的」expert 發
`MADV_WILLNEED`,讓 SSD 讀取與計算重疊。參考 sddqwen35a3b_v01 的結論:
它實測預取命中率 0%(相鄰 token 的 top-k 重疊率已達 70%,LRU 本來就留著),
所以不確定這邊有沒有價值 —— 要先量路由重疊率。
2. **KV cache 也放 SSD**:ctx 拉到 32768 時 KV 是 128 MiB(f16),
目前是留在 RAM 的。要更省可以加 KV 檔案 mmap(llama.cpp 有 `--kv-unified`
與部分 lazy load 的機制可利用)。
3. **prefill 的工作集**:prefill 會一次摸遍幾乎所有 expert,所以 prefill 階段
的峰值必然接近整個模型。要壓低只能限制 prefill 批次大小(`-ub`),
分批送 prompt。
## 常數(改模型就要改)
`llama_server.sh` 頂部。這些是模型事實,不是可調參數:
```
N_LAYER=32 N_EMBD=1536 N_EXPERT=32 N_EXPERT_USED=4 EXPERT_FFN=768
N_HEAD=12 N_HEAD_KV=2 KEY_LEN=128 VAL_LEN=128 MODEL_MAX_CTX=32768
MODEL_REPO=Tiiny/SmallThinker-4BA0.6B-Instruct-GGUF
MODEL_FILE=SmallThinker-4B-A0.6B-Instruct.Q4_K.gguf
MODEL_SIZE=2630212704
LLAMA_COMMIT=b9acf138a1e28ce1fc23b5a4fc4b12444b50f7ea
```
⚠️ `EXPERT_BYTES` 只是**粗估**(0.6 B/elem),因為 `down_exps` 逐層量化型別不同。
真正精確的數字由 `st_pager.cpp` 在載入時從 GGUF metadata 算出來並印出。 |