Try   HackMD

Llama 3.2 Instruct Model 移植 iOS

  • 移植到 Executorch CoreML Backend 對話會重複輸入文字,在 iPhone 16 pro 上無法輸入較長 >100 文字,記憶體不足。
  • 虛擬機 iPhone 大約用掉 6.9 GB,會重複輸入文字。
  • 使用 Executorch Llama 編譯程式可以正常執行在 Macbook Air M1 16 GB 上
  • 可轉換成 CoreML 格式在 Macbook 或 iOS 上正常執行。

聯發科於 2025 年初釋出他們調整過的 Llama 3.2 模型,上傳至 huggingface。MediaTek 提供部分必要的檔案,.ptetokenizer.bin 檔案。
Meta 的 llama 提供更多檔案,例如 safetensor,並且 MLX-Example 已經提供 llama 轉換格式的程式碼、MLX-Swift-Example 移植到 iOS 平台上,可以使用 mlx-swift-example repository,搭配 Apple Silcon 一次支援 M1 與 iOS 系統。
pte 檔案可以使用 Executorch 跟它提供的專案,移植到 iOS 上使用。

練習目標

  1. 移植到 iOS 與 Apple M 系列的電腦上
  2. 提高 token 生成速度並學會相關技巧、論文與方法

使用 Executorch 移植

這裡參考聯發科使用的 Executorch,Executorch 是專門移植到手機與邊緣裝置使用的框架。目前有穩定的版本(stable 0.5 分支),但是如果要移植到 iOS 與 Android 等裝置,需要使用最新的分支(main 0.6 分支)。

文件內容等等都蠻混亂的,很多重複的步驟散亂在個文件中,從 Google 搜尋會給你 main 分支上的文件,其中幾個 iOS App 連結已經被移除,只在 stable 分支才有。

步驟

這裡使用的操作電腦為 Macbook Air M1 16GB,並以 main 分支連結。

  1. 從來源安裝 Executorch
  2. 依據範例編譯 Llama 工具、下載 Llama 3.2 並轉檔,最終會有 *.ptetokenizer.bintokenizer.model
  3. 使用 Executorch 中的 iOS llama 範例專案或在電腦上執行 llama

因為很混亂所以這裡提供過程:

# 安裝 cmake
brew install --cask cmake
sudo /Applications/CMake.app/Contents/bin/cmake-gui --install

# 部署 Python 虛擬環境
conda create -n executorch python=3.10.0
conda activate executorch

# 下載並安裝 Executorch (預設 main branch)
git clone --depth 1 https://github.com/pytorch/executorch.git

# 到該 executorch 目錄下
cd executorch
git submodule sync
git submodule update --init

# 不知為何使用以下指令才會拉 submodule 下來
git submodule update --init --recursive

# 安裝 CoreML 與 MPS Backend
./install_executorch.sh --pybind coreml mps xnnpack
./backends/apple/coreml/scripts/install_requirements.sh
./backends/apple/mps/install_requirements.sh

# 安裝 LLama 工具
./examples/models/llama/install_requirements.sh

# 編譯工具 會創建 cmake-out 目錄
cmake -DPYTHON_EXECUTABLE=python \
    -DCMAKE_INSTALL_PREFIX=cmake-out \
    -DEXECUTORCH_ENABLE_LOGGING=1 \
    -DCMAKE_BUILD_TYPE=Release \
    -DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
    -DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
    -DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
    -DEXECUTORCH_BUILD_COREML=ON \
    -DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
    -DEXECUTORCH_BUILD_KERNELS_OPTIMIZED=ON \
    -DEXECUTORCH_BUILD_KERNELS_CUSTOM=ON \
    -Bcmake-out .

cmake --build cmake-out -j16 --target install --config Release

git submodule update --init --recursive

cmake -DPYTHON_EXECUTABLE=python \
    -DCMAKE_INSTALL_PREFIX=cmake-out \
    -DCMAKE_BUILD_TYPE=Release \
    -DEXECUTORCH_BUILD_KERNELS_CUSTOM=ON \
    -DEXECUTORCH_BUILD_KERNELS_OPTIMIZED=ON \
    -DEXECUTORCH_BUILD_COREML=ON \
    -DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
    -Bcmake-out/examples/models/llama \
    examples/models/llama

cmake --build cmake-out/examples/models/llama -j16 --config Release

# 將 Meta llama 3.2 檔案輸出成 *.pte
# 聯發科 Llama 已經提供 *.pte 檔案,可以跳過轉檔步驟
python -m examples.models.llama.export_llama --model "llama3_2" --checkpoint llama323B/consolidated.00.pth --params llama323B/params.json -kv --use_sdpa_with_kv_cache -X -d bf16 --metadata '{"get_bos_id":128000, "get_eos_ids":[128009, 128001]}' --output_name="llama3_2_bf16.pte"

在電腦上執行 Llama

# 同一虛擬環境下
conda acticate executorch
cd executorch

# 執行 Llama
cmake-out/examples/models/llama/llama_main --model_path=<model pte file> --tokenizer_path=<tokenizer.model> --prompt=<prompt>

# 範例
cmake-out/examples/models/llama/llama_main --model_path="llama3_2_bf16.pte" --tokenizer_path="tokenizer.model" --prompt="What's PyTorch?"

我自己電腦的聯發科 Llama 輸出:

cmake-out/examples/models/llama/llama_main --model_path="/Users/yangdunfu/Documents/mlx_project/Llama3.2-3B-Instruct-mobile/llama3_2.pte" --tokenizer_path="/Users/yangdunfu/Documents/mlx_project/Llama-3.2-3B-Instruct/original/tokenizer.model" --prompt="撰寫台灣統治全世界的文章來看看,其中以經濟制霸的角度和方法去描述"
撰寫台灣統治全世界的文章來看看,其中以經濟制霸的角度和方法去描述台灣在亞洲的影響力,臺灣在國際上的影響力主要是經濟制?,臺灣的經濟實力是亞洲第一,經濟發展是亞洲第一,亞洲其他國家都在追隨臺灣的經濟發展。所以臺灣的經濟實力是亞洲第一,在亞洲的影響力是非常大。
第二,臺灣在亞洲的影響力主要是教育制?,臺灣的教育是亞洲第一,臺灣的教育
PyTorchObserver {"prompt_tokens":25,"generated_tokens":102,"model_load_start_ms":1742969142119,"model_load_end_ms":1742969144796,"inference_start_ms":1742969144796,"inference_end_ms":1742969166178,"prompt_eval_end_ms":1742969146508,"first_token_ms":1742969146508,"aggregate_sampling_time_ms":132,"SCALING_FACTOR_UNITS_PER_SECOND":1000}

我自己電腦的 meta Llama 輸出:

cmake-out/examples/models/llama/llama_main --model_path="llama3_2_bf16_test.pte" --tokenizer_path="/Users/yangdunfu/Documents/mlx_project/Llama-3.2-3B-Instruct/original/tokenizer.model" --prompt="撰寫台灣統治全世界的文章來看看,其中以經濟制霸的角度和方法去描"
撰寫台灣統治全世界的文章來看看,其中以經濟制霸的角度和方法去描?台灣的統治形態》. 
. 

*   「臺灣社會發展史-中華民國史與臺灣史」(1994)- 本書是由台大教育局所出版的,?在作為學生與教師的參考書。它的內容分為五章,第一章是介紹台大的成立與發展的歷史,第二章是中華民國的建立與發展,第三章是台北地方法
PyTorchObserver {"prompt_tokens":25,"generated_tokens":102,"model_load_start_ms":1742969188460,"model_load_end_ms":1742969190524,"inference_start_ms":1742969190524,"inference_end_ms":1742969204241,"prompt_eval_end_ms":1742969191839,"first_token_ms":1742969191839,"aggregate_sampling_time_ms":153,"SCALING_FACTOR_UNITS_PER_SECOND":1000}

說實話看不出來差在哪裡,輸出文字有夠短的,我記得有說有改成繁體中文與台灣用詞的東西。

執行 iOS llama 專案

iOS 專案底下的 LLaMARunner,會連結到部分 gitsubmodule,只按照 iOS 文件的步驟很容易會漏掉。前面的 llama 工具執行過程會產生 iOS 需要的檔案。
另外,因為 xcode 專案目錄管理自成一套,編譯過程會發現其他維護者的檔案路徑,造成編譯錯誤。

# 有幾包目錄檔案要下載下來
git submodule update --init --recursive

# 在 executorch 目錄下,打開 iOS 範例專案
open ./executorch/examples/demo-apps/apple_ios/LLaMA/LLaMA.xcodeproj

最後的執行結果非常糟糕,模型完全無法正常反應,而且還蠻詭異的,看起來有存取到不正確的記憶體位置。在 iPhone 16 pro 上跑會因為記憶體限制關係強制關閉,模擬器可以跑出來。

心得

安裝過程蠻折騰人的,文件本身很多地方要改, issue 中有表示效果不好或回覆有問題。iOS 的範例專案有包含到其他維護者的電腦目錄路徑,導致檔案找不到。
coremltools 不支援 onnx 檔案格式,coremltools 跟 Apple 有一套自己的 llama 跟 transofmer fusion 的方法,如果可以移植,還是使用 safetensor 去移植比較有用。Apple WWDC 有一堆開發者影片展示如何轉換。

對於聯發科來說,量測或改進生 token 的速度才是最重要的事情,感覺我還有一大段路要走!

Executorch 很多文件沒有補齊,是個可以貢獻開源的好機會!

使用 CoreML 移植

CoreML 與 mlmodelc 是蘋果的模型格式,早於 gguf 的模型格式,透過 coremltools 轉換現有 Pytorch 模型 pth 檔案,透過 Pytorch jit 技術追蹤模型網路組成,輸出蘋果支援格式。

CoreML 移植比較簡單,在 LLM 模型推出之後,huggingface 便推出 swift-transformer 等實作來使用,swift-transformer 本身使用 Swift 程式語言實作,提供類似 huggingface-cli 的模型下載跟使用的功能。

步驟

以下的 llama-to-coreml 專案跟 Swift-Chat 專案有使用到 huggingface 提供的套件,如果不是使用自製的語言模型,可以直接參考程式碼使用現有模型,套件會幫你自動下載。專案本身都沒有教學怎麼手動使用自己的模型。

  1. 使用 Python 專案 llama-to-coreml,這套件使用 huffingface 的 transformer 去讀取並下載模型。這個專案固定會從 huggingface 下載模型。轉換過程中會用到約 28 GB 記憶體,但是我的 16 GB 的電腦還是轉得過沒問題。
  2. 從 huggingface meta 頁面下載 tokenizer_config.jsontokenizer.json
  3. 使用我的 Swift XCode 專案,這程式碼多數從 LanguageModelWithStatefulKVCache 內容複製,程式碼目前主在 preview 分支。
  4. 修改 LlamaCoreml.swift 的每個路徑。
  5. 執行

輸出

<|begin_of_text|>介紹你自己
==========================

### 關鍵技能

*   **Python**: Python是目前最受歡迎的程式語言,尤其是在開源和數據科學領域的應用。
*   **JavaScript**: JavaScript是目前最受歡迎的程式語言,尤其是在網路和互動式網頁應用。
*   **SQL**: SQL是目前最受歡迎的程式語言,尤其是在資料庫和數據分析的應用。
*   **HTML/CSS**: HTML/CSS是目前最受歡迎的程式語言,尤其是在網頁設計和前端開發的應用。
*   **Git**: Git是目前最受歡迎的程式語言,尤其是在版本控制和開源的應用。

### 作品

*   **Python**: Python的作品包括了許多開源程式語言的應用,例如:數據科學、機器學習、網路等。
*   **JavaScript**: JavaScript的作品包括了許多網路和互動式網頁的應用,例如:網路應用、互動式
Program ended with exit code: 0

我沒要求輸出 MarkDown 格式,它自己就輸出了。

心得

想比 Executorch 設定環境,使用 CoreML 工具要為簡單很多,模型轉換後的檔案大小從 4.62 GB 降為 1.8 GB,CoreML 儲存不同精度。
執行過程中,在記憶體佔用上相比使用 Executorch 要少很多,在 Maxbook 上測試執行過程中約 4 GB ,執行過程中緩慢上升。