在 NVIDIA Jetson Orin AGX 上編譯 llama.cpp 與部署 AI 應用

簡介
由於工作的緣故,需要將 llama.cpp 作為 WASI-NN 的後端所使用,來讓 WebAssembly 能具備使用 AI 模型的能力,也因此需要在各種平台上編譯 llama.cpp 作為我們的相依性函式庫。
而 NVIDIA Jetson Orin AGX 64GB 的版本,作為提供相對大的 VRAM 與支援 CUDA 的平台,自然是我們花許多力氣在上面進行測試與最佳化的目標。
本文將詳細記錄如何在 NVIDIA Jetson Orin AGX (JetPack 6.2) 上成功編譯 llama.cpp、將大型語言模型轉換成 GGUF 格式、進行模型量化以及最終部署 AI 應用的完整流程。
升級至 JetPack 6.2
不論你使用的是 NVIDIA Jetson Orin AGX 或者 Jetson Orin Nano,都強烈建議你升級到 JetPack 6.2 以上的版本,以確保你能夠使用最新的 CUDA 與與解鎖後的效能,同時這個版本提供了 Ubuntu 22.04 與 CUDA 12.6 的環境,具備更好的支援性。
至於怎麼安裝,根據不同的型號,操作可能有所差異,請參考 NVIDIA 官方文件,以取得最新的安裝方式,這裡不再贅述。
編譯 llama.cpp
安裝相依性套件
若升級到 JetPack 6.2 以上,CUDA 12.6 的工具鏈已經預先安裝在系統中,不過還是需要安裝一些相依性套件,以確保編譯 llama.cpp 時不會遇到問題。
build-essential
: 安裝編譯工具鏈,如: GCC/G++cmake
: 安裝 CMake 編譯工具,目前 llama.cpp 已經改為使用 CMake 進行編譯git
: 安裝 Git 版本控制工具,用來下載 llama.cpp 的原始碼
1 | sudo apt update # 更新套件清單 |
下載 llama.cpp
如果你以前下載過 llama.cpp 的 repo ,他的位置已經從 https://github.com/ggerganov/llama.cpp.git
轉移到 https://github.com/ggml-org/llama.cpp.git
囉,請記得更新你的連結。
1 | git clone https://github.com/ggml-org/llama.cpp.git |
編譯 llama.cpp
1 | cmake -B build -DGGML_CUDA=ON # 在 build 目錄下產生編譯檔案 |
以我的 Jetson Orin AGX 為例,編譯 llama.cpp 大約需要 30 分鐘左右,視機器效能而定。
1 | cmake --build build --parallel 9873.06s user 246.00s system 645% cpu 26:07.55 total |
編譯完成後,在 build/bin
中會產生 llama.cpp 的所有可執行檔案。
若發生 CUDA 相關的編譯錯誤
如下:
1 | -- Found CUDAToolkit: /usr/local/cuda/include (found version "12.6.68") |
這是因為 CUDA 12.6 的編譯器路徑不正確,需要手動設定 CUDA 編譯器路徑,請執行以下指令:
1 | export PATH=/usr/local/cuda-12.6/bin${PATH:+:${PATH}} |
接著重新執行上述的編譯指令即可解決。
模型轉換為 GGUF 格式
多數的模型並不是以 GGUF 的格式進行發布的,因此在使用 llama.cpp 執行之前,需要先將模型轉換成 GGUF 格式才能夠正確載入。
當然在 Hugging Face 上已經有不少人轉換好的 GGUF 模型,如果你是下載那些已經轉換的檔案就可以跳過此步驟。
下載原始模型
此處以 DeepSeek-R1-Distill-Llama-8B 為例,你可以換成任何你喜歡的模型。
使用 huggingface-cli 下載
由於下載需要不少時間,建議使用 huggingface-cli 來下載模型。
1 | huggingface-cli download deepseek-ai/DeepSeek-R1-Distill-Llama-8B --local-dir ds-r1-distill-llama-8b |
安裝轉換模型用的相依性函式庫
1 | # 在 llama.cpp 的根目錄下執行 |
轉換模型
1 | python convert_hf_to_gguf.py --outfile ./ds-r1-distill-llama-8b ./ds-r1-distill-llama-8b |
以下為執行的 log 僅供參考:
1 | INFO:hf-to-gguf:Loading model: ds-r1-distill-llama-8b |
在轉換後我們可以初步看到模型的大小關係,基本上沒有太大的變化:
1 | # 轉換前的模型大小 (8.1G + 6.9G = 15G) |
模型量化
由於眾所周知的原因(大家都很窮),部署完整版(F16)的多數模型實在過於龐大,除了因為大小的緣故很難被放入消費級的硬體外,還容易因為硬體效能限制導致推理速度不理想。這時候我們就會需要透過量化,雖然降低精度,卻也能保證模型被縮小到可以較容易部署的大小,並能獲得更高的推理速度,達到更好的可用性。
1 | # 在 llama.cpp 的根目錄下執行 |
僅供參考的 log:
1 | main: build = 4845 (d6c95b07) |
在進行完量化後,模型大小差異如下:
1 | 原本為 15GB,量化後為 4.4GB |
部署 AI 應用
透過 llama-cli 進行推論
直接使用 Chat CLI 來與模型進行互動,透過以下指令來進行推論:
1 | ./build/bin/llama-cli -m ./ds-r1-distill-llama-8b/ds-r1-distill-llama-8B-Q4_0.gguf |
然後你會馬上發現,似乎 GPU 沒有被使用到,那就對了,這時會在 log 中發現以下資訊:
1 | load_tensors: loading model tensors, this can take a while... (mmap = true) |
告訴你他只使用了 CPU 的部分,並沒有將模型放到 GPU 上來進行加速。
你需要指定 -ngl 層數
來指定要放到 GPU 上的層數,例如:
1 | ./build/bin/llama-cli -m ./ds-r1-distill-llama-8b/ds-r1-distill-llama-8B-Q4_0.gguf -ngl 33 |
這時就會看見 GPU 被使用到了:
1 | load_tensors: loading model tensors, this can take a while... (mmap = true) |
透過 llama-server 啟動 OpenAI 相容的 API 伺服器
透過以下指令來啟動 llama-server:
1 | ./build/bin/llama-server -m ./ds-r1-distill-llama-8b/ds-r1-distill-llama-8B-Q4_0.gguf -ngl 33 |
原則上就是把上面的 cli
換成 server
就可以囉!
如何與之互動
請查詢 OpenAI API 該如何使用,你可以直接將任何支援 OpenAI API endpoint 的工具與服務換成 llama-server 啟動的伺服器。
以下只是示範如何使用 curl
來發送請求,並使用 jq
來渲染輸出結果
1 | curl -X POST http://localhost:8080/v1/chat/completions \ |
結語
本文以 llama.cpp b4845 (d6c95b07)
做教學,由於 llama.cpp 是非常活躍的專案,因此上述的工具參數可能有所修改,如發現該指令無法正確執行,請使用 --help
或者 -h
來查看最新的參數應該如何使用。
希望本文能讓想使用 NVIDIA Jetson 系列開發版的開發者們,能夠輕鬆上手 llama.cpp,並更快速地部署 AI 應用。