Select Page

Nvidia DGX Spark 安裝 Holo-3.1

原本我在 Nvidia 都搭配 vLLM 啟動,這條路理論上可以發揮 NVFP4 權重的優勢,但在 DGX Spark 的 GB10 平台上,實際遇到 CUDA Kernel 與 Marlin repack 相容性問題。

最後我改採:

Hcompany/Holo-3.1-35B-A3B-GGUF

搭配 llama.cpp CUDA Build,成功啟動模型並提供 API 服務。

這篇文章記錄完整流程,也保留幾個重要的踩坑經驗。


環境

本次環境如下:

硬體:NVIDIA DGX SparkGPU:NVIDIA GB10系統:Ubuntu Linux模型儲存位置:/mnt/ai-models推論框架:llama.cpp模型格式:GGUF量化版本:Q4_K_M

DGX Spark 使用統一記憶體架構,因此 CPU、GPU 與系統服務會共用記憶體。這點對 vLLM 與 llama.cpp 都很重要。


為什麼放棄 NVFP4 + vLLM

一開始使用 vLLM 載入:

Hcompany/Holo-3.1-35B-A3B-NVFP4

後,權重其實已經完整載入:

Loading safetensors checkpoint shards: 100% Completed | 3/3Loading weights took 142.78 seconds

但載入完成後,仍然在 Marlin FP4 重新整理階段失敗:

NotImplementedError:Could not run '_C::gptq_marlin_repack'with arguments from the 'CUDA' backend

這代表模型檔案本身沒有問題,真正卡住的是 vLLM 的 CUDA Extension 在 DGX Spark GB10 上沒有完整提供所需的 Marlin CUDA Operator。

如果只是想先把 Holo 3.1 跑起來,不一定要繼續投入時間處理 NVFP4 相容性。改用 GGUF + llama.cpp 是更快、更穩定的選擇。


移除 NVFP4 模型快取

vLLM 下載的 Hugging Face 模型通常會放在:

/mnt/ai-models/huggingface/hub/

先確認路徑:

find /mnt/ai-models/huggingface \  -maxdepth 3 \  -type d \  -name 'models--Hcompany--Holo-3.1-35B-A3B-NVFP4' \  -print

確認容量:

du -sh \  /mnt/ai-models/huggingface/hub/models--Hcompany--Holo-3.1-35B-A3B-NVFP4

確認無誤後刪除:

rm -rf \  /mnt/ai-models/huggingface/hub/models--Hcompany--Holo-3.1-35B-A3B-NVFP4

安裝 llama.cpp

1. 安裝編譯工具

sudo apt update
sudo apt install -y \  git \  build-essential \  cmake \  ninja-build \  libcurl4-openssl-dev \  pkg-config

2. 確認 CUDA Toolkit

export CUDA_HOME=/usr/local/cudaexport PATH="${CUDA_HOME}/bin:${PATH}"
export LD_LIBRARY_PATH="${CUDA_HOME}/lib64:${LD_LIBRARY_PATH:-}"
nvcc --versionnvidia-smi

nvcc --version 必須能正常回傳 CUDA 版本。

3. Clone llama.cpp

mkdir -p /mnt/ai-models/srccd /mnt/ai-models/srcgit 
clone https://github.com/ggml-org/llama.cpp.gitcd 
llama.cpp

如果之前已經下載過:

cd /mnt/ai-models/src/llama.cpp
git fetch origingit switch master
git pull --ff-only origin master

4. 編譯 CUDA 版本

cd /mnt/ai-models/src/llama.cpp
rm -rf buildcmake -B build \  -DGGML_CUDA=ON \  -DCMAKE_BUILD_TYPE=Releasecmake --build build \  --config Release \  -j 4 \  --target llama-server llama-cli

確認:

./build/bin/llama-server --version
./build/bin/llama-cli --version

下載 Holo 3.1 GGUF 模型

建立模型目錄:

mkdir -p \  /mnt/ai-models/llama-models/Holo-3.1-35B-A3B-GGUF

下載主模型、視覺投影模型與 Chat Template:

hf download \  Hcompany/Holo-3.1-35B-A3B-GGUF \  q4_k_m.gguf \  mmproj.f16.gguf \  chat_template.jinja \  --local-dir \  /mnt/ai-models/llama-models/Holo-3.1-35B-A3B-GGUF

確認:

ls -lh \  /mnt/ai-models/llama-models/Holo-3.1-35B-A3B-GGUF

應該看到:

q4_k_m.ggufmmproj.f16.ggufchat_template.jinja

單模型模式啟動

先用最簡單的單模型方式確認服務能運作:

cd /mnt/ai-models/src/llama.cpp
./build/bin/llama-server \  -m /mnt/ai-models/llama-models/Holo-3.1-35B-A3B-GGUF/q4_k_m.gguf \  --mmproj /mnt/ai-models/llama-models/Holo-3.1-35B-A3B-GGUF/mmproj.f16.gguf \  --jinja \  --host 0.0.0.0 \  --port 8080 \  -c 8192 \  -np 1 \  -ngl 999

參數說明:

--mmproj     指定視覺投影模型
--jinja      使用模型附帶的 Chat Template
-c 8192      Context Length
-np 1        同時處理 1 個請求
-ngl 999     儘可能將模型層放到 GPU

測試文字 API

curl -s http://192.168.0.240:8080/v1/chat/completions \  -H "Content-Type: application/json" \  -d '{    "model": "Holo-3.1-35B-A3B-GGUF",    "messages": [      {        "role": "user",        "content": "請使用繁體中文介紹你的 UI 畫面分析能力。"      }    ],    "max_tokens": 256,    "temperature": 0.2  }' | python3 -m json.tool

在這台 DGX Spark 上,實測文字生成速度約為:

82 tokens/s

測試圖片分析 API

curl -s http://127.0.0.1:8080/v1/chat/completions \  -H "Content-Type: application/json" \  -d '{    "model": "q4_k_m.gguf",    "messages": [      {        "role": "user",        "content": [          {            "type": "text",            "text": "Describe this image in one concise English sentence."          },          {            "type": "image_url",            "image_url": {              "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg"            }          }        ]      }    ],    "thinking_budget_tokens": 64,    "max_tokens": 1024,    "temperature": 0.1  }' | python3 -m json.tool

已知問題:中文多模態輸出偶爾觸發解析錯誤

圖片推論本身可以成功,但在某些中文輸出中,llama-server 可能回傳:

Failed to parse input at pos ...

例如:

自由女神像、火炬、基座、城市天際線、高樓、水面、島嶼、樹木、旗�、船。

其中 是 UTF-8 無效字元替代符號。

實務上的處理方式:

1. 降低 temperature,例如 0.12. 限制輸出為簡短句子3. 提高 max_tokens,避免輸出被截斷4. Client 端遇到 500 時自動 Retry 一次5. 優先更新至最新版 llama.cpp

Router Mode:支援多模型切換

確認單模型模式正常後,可以啟用 Router Mode:

cd /mnt/ai-models/src/llama.cpp
./build/bin/llama-server \  --models-dir /mnt/ai-models/llama-models \  --models-max 1 \  --models-autoload \  --jinja \  --host 0.0.0.0 \  --port 8080 \  -c 8192 \  -np 1 \  -ngl 999

啟動後會看到:

Loaded 1 local model presets from /mnt/ai-models/llama-modelsAvailable models (1)    Holo-3.1-35B-A3B-GGUFstarting router server, no model will be loaded in this processrouter server is listening on http://0.0.0.0:8080

Router 會在 Client 第一次呼叫時才載入模型。

查看模型清單:

curl -s \  'http://127.0.0.1:8080/models?reload=1' | \  python3 -m json.tool

指定模型:

curl -s http://127.0.0.1:8080/v1/chat/completions \  -H "Content-Type: application/json" \  -d '{    "model": "Holo-3.1-35B-A3B-GGUF",    "messages": [      {        "role": "user",        "content": "請使用繁體中文簡短介紹你的功能。"      }    ],    "max_tokens": 512,    "temperature": 0.2  }' | python3 -m json.tool

Router Mode 的記憶體策略

我使用:

--models-max 1

意思是:

可以讓 Client 選擇多個模型但同一時間只保留一個模型在記憶體中

這很適合 DGX Spark。因為 Holo 35B、KV Cache、圖片 Token 與系統服務都會共用統一記憶體。

如果要同時提供 Holo 與另一個 Tool Calling 模型,建議:

Holo 35B:Context 8192 或 16384用途:UI 截圖與視覺分析較小的文字 Tool Calling 模型:Context 65536用途:Hermes Agent 預設模型

不同模型需要不同 Context Length 時,可使用 models.ini

version = 1

[*]
jinja = true
n-gpu-layers = 999
parallel = 1

[Holo-3.1-35B-A3B-GGUF]
model = /mnt/ai-models/llama-models/Holo-3.1-35B-A3B-GGUF/q4_k_m.gguf
mmproj = /mnt/ai-models/llama-models/Holo-3.1-35B-A3B-GGUF/mmproj.f16.gguf
ctx-size = 8192

[qwen-coder]
model = /mnt/ai-models/llama-models/qwen-coder-14b-q4_k_m.gguf
ctx-size = 65536

啟動:

./build/bin/llama-server \  --models-preset /mnt/ai-models/llama-models/models.ini \  --models-max 1 \  --models-autoload \  --host 0.0.0.0 \  --port 8080

讓 llama.cpp 開機就執行

一、確認執行檔路徑

先執行:

ls -lh /mnt/ai-models/src/llama.cpp/build/bin/llama-server

再確認模型目錄:

ls -lah /mnt/ai-models/llama-models

測試版本:

/mnt/ai-models/src/llama.cpp/build/bin/llama-server --version

如果這三個指令正常,就可以建立服務。


二、建立 systemd 服務

建立服務檔:

sudo nano /etc/systemd/system/llama-router.service

貼上:

[Unit]
Description=llama.cpp Router Server
Documentation=https://github.com/ggml-org/llama.cpp
After=network-online.target local-fs.target
Wants=network-online.target
RequiresMountsFor=/mnt/ai-models

[Service]
Type=simple
User=gwoyju
Group=gwoyju
WorkingDirectory=/mnt/ai-models/src/llama.cpp

Environment="LD_LIBRARY_PATH=/usr/local/cuda/lib64"
Environment="CUDA_HOME=/usr/local/cuda"

ExecStartPre=/usr/bin/test -x /mnt/ai-models/src/llama.cpp/build/bin/llama-server
ExecStartPre=/usr/bin/test -d /mnt/ai-models/llama-models

ExecStart=/mnt/ai-models/src/llama.cpp/build/bin/llama-server \
  --models-dir /mnt/ai-models/llama-models \
  --models-max 1 \
  --models-autoload \
  --jinja \
  --host 0.0.0.0 \
  --port 8080 \
  -c 8192 \
  -np 1 \
  -ngl 999

Restart=on-failure
RestartSec=10
TimeoutStopSec=30
KillSignal=SIGTERM
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

儲存後離開:

Ctrl + O
Enter
Ctrl + X

WantedBy=multi-user.target 讓服務可以隨一般多使用者開機流程啟動;Restart=on-failure 會在程式異常退出時重新啟動服務。

為什麼需要 RequiresMountsFor

你的模型與程式都放在:

/mnt/ai-models

如果外接 SSD 尚未掛載完成,直接啟動 llama-server 會失敗。

這一行:

RequiresMountsFor=/mnt/ai-models

會要求 systemd 先準備好該掛載點,再啟動 Router。


三、啟用開機自動執行

重新讀取服務設定:

sudo systemctl daemon-reload

設定開機自動啟動,並立即啟動:

sudo systemctl enable --now llama-router

查看服務狀態:

systemctl status llama-router --no-pager

正常情況應該看到:

Active: active (running)

以及:

router server is listening on http://0.0.0.0:8080

四、查看即時日誌

查看最近 100 行日誌:

journalctl -u llama-router -n 100 --no-pager

持續追蹤日誌:

journalctl -u llama-router -f

離開即時日誌:

Ctrl + C

五、測試 Router API

確認 Router 已啟動:

curl -s http://127.0.0.1:8080/health

查看模型清單:

curl -s \  'http://127.0.0.1:8080/models?reload=1' | \  python3 -m json.tool

測試 Holo 3.1:

curl -s http://127.0.0.1:8080/v1/chat/completions \  -H "Content-Type: application/json" \  -d '{    "model": "Holo-3.1-35B-A3B-GGUF",    "messages": [      {        "role": "user",        "content": "請使用繁體中文簡短介紹你的功能。"      }    ],    "max_tokens": 256,    "temperature": 0.2  }' | python3 -m json.tool

第一次呼叫時會需要等待模型載入。後續請求會比較快。


六、常用管理指令

啟動服務

sudo systemctl start llama-router

停止服務

sudo systemctl stop llama-router

重新啟動

sudo systemctl restart llama-router

查看狀態

systemctl status llama-router --no-pager

取消開機自動啟動

sudo systemctl disable --now llama-router

七、確認開機後是否真的自動啟動

重新開機:

sudo reboot

重新 SSH 登入後執行:

systemctl status llama-router --no-pager

確認 Port:

ss -ltnp | grep :8080

測試模型清單:

curl -s http://127.0.0.1:8080/models | \  python3 -m json.tool

八、改用 models.ini

準備讓不同模型有不同 Context Length:

Holo 35B:8192Hermes 預設 Tool Calling 模型:65536

這種情況建議不要在服務中使用:

--models-dir-c 8192

而是改用:

--models-preset

假設設定檔位於:

/mnt/ai-models/llama-models/models.ini

服務中的 ExecStart 改成:

ExecStart=/mnt/ai-models/src/llama.cpp/build/bin/llama-server \
  --models-preset /mnt/ai-models/llama-models/models.ini \
  --models-max 1 \
  --models-autoload \
  --host 0.0.0.0 \
  --port 8080

改完後重新載入設定:

sudo systemctl daemon-reload
sudo systemctl restart llama-router

查看日誌:

journalctl -u llama-router -f

九、避免 Ollama 開機後搶占記憶體

你之前遇過記憶體不足。如果目前 DGX Spark 主要改用 llama.cpp,建議停用 Ollama 的開機自動啟動:

sudo systemctl disable --now ollama

確認:

systemctl status ollama --no-pager

未來需要恢復:

sudo systemctl enable --now ollama

十、限制只允許內網連線

目前使用:

--host 0.0.0.0

代表區域網路內其他裝置可以存取 API。Router Mode 目前仍屬於實驗性功能;llama.cpp 啟動日誌也提醒,不建議直接暴露在不受信任的網路環境。

假設區域網路是:

192.168.0.0/24

可以設定 UFW:

sudo ufw allow from 192.168.0.0/24 \  to any port 8080 proto tcp

查看規則:

sudo ufw status numbered

不要直接把 Port 8080 暴露到公網。


建議你現在直接執行的版本

建立 /etc/systemd/system/llama-router.service 後,執行:

sudo systemctl daemon-reload
sudo systemctl enable --now llama-router
systemctl status llama-router --no-pagerjournalctl -u llama-router -n 50 --no-pager

這樣 DGX Spark 每次重新開機後,llama.cpp Router Server 就會自動啟動,並等待 Hermes Agent 或其他 Client 指定要載入的模型。

參考資料

https://huggingface.co/collections/Hcompany/holo31

https://build.nvidia.com/spark/llama-cpp/instructions

ChatTTS-完整使用指南

ChatTTS-完整使用指南

免費且超強大的 AI TTS,文字轉語音模型+工具,有許多語氣的控制,也可以很精準的寫程式控制效果,是RD眼中好用的Local端開源的TTS

特色說明

1.大規模的數據:10萬小時的訓練資料,現在開源的是4小時的版本

2.專用設計:專門對於對話情境、視頻介紹的情境所設計的模型

3.開源特性:可以很簡單的整合到你的WEB中

4.支持語氣:oral, laugh, break

安裝前準備

python 3.10

CUDA

GIT

gradio

安裝說明

github 複製

git clone https://github.com/2noise/ChatTTS
cd ChatTTS

安裝依賴

pip install --upgrade -r requirements.txt

執行 webui

python examples/web/webui.py

利用 CLI

python examples/cmd/run.py "Your text 1." "Your text 2."

要整合在 python 程式碼中,可以安裝 PyPI

pip install ChatTTS
pip install git+https://github.com/2noise/ChatTTS
pip install -e .

整合程式碼

###################################
# Sample a speaker from Gaussian.

rand_spk = chat.sample_random_speaker()
print(rand_spk) # save it for later timbre recovery

params_infer_code = ChatTTS.Chat.InferCodeParams(
    spk_emb = rand_spk, # add sampled speaker 
    temperature = .3,   # using custom temperature
    top_P = 0.7,        # top P decode
    top_K = 20,         # top K decode
)

###################################
# For sentence level manual control.

# use oral_(0-9), laugh_(0-2), break_(0-7) 
# to generate special token in text to synthesize.
params_refine_text = ChatTTS.Chat.RefineTextParams(
    prompt='[oral_2][laugh_0][break_6]',
)

wavs = chat.infer(
    texts,
    params_refine_text=params_refine_text,
    params_infer_code=params_infer_code,
)

###################################
# For word level manual control.

text = 'What is [uv_break]your favorite english food?[laugh][lbreak]'
wavs = chat.infer(text, skip_refine_text=True, params_refine_text=params_refine_text,  params_infer_code=params_infer_code)
"""
In some versions of torchaudio, the first line works but in other versions, so does the second line.
"""
try:
    torchaudio.save("word_level_output.wav", torch.from_numpy(wavs[0]).unsqueeze(0), 24000)
except:
    torchaudio.save("word_level_output.wav", torch.from_numpy(wavs[0]), 24000)

V3版本

音色庫

https://www.modelscope.cn/studios/ttwwwaa/chattts_speaker

注意事項

1.是否要使用CUDA,需要的話,記得安裝依賴

2.要用CUDA,怎選擇 Linux 平台,相容性比較好

3.Python最好用3.10版本,並且用conda

直接使用

https://chattts.com

colab

modalScope

參考資源

ChatTTS Github

ChatTTS官網

Chat TTS UI

Chat TTS 翻譯

MediaFire一件安裝包

Lobe Chat UI-有plugin,多模態的AI CHAT UI – 雨 (rain.tips)

AI Tools – AI工具大全(總整理) – 雨 (rain.tips)

搭配 Free AI 產圖Flux

WordPress站長必學:Windows環境下利用FFmpeg壓縮WebP/WebM格式檔案提升效能

WordPress站長必學:Windows環境下利用FFmpeg壓縮WebP/WebM格式檔案提升效能

隨著網絡速度的提升和視覺內容的普及,高效的多媒體處理成為了網站管理的重要環節。對於WordPress網站來說,使用高效的圖片和視頻格式,如WebP和WebM,可以顯著提高頁面加載速度,改善用戶體驗。FFmpeg是一款強大的開源工具,它可以讓你在Windows環境下輕鬆地進行多媒體文件的轉換和壓縮。本文將引導您完成在Windows下安裝FFmpeg的過程,並教您如何壓縮WebP和WebM格式的檔案。

步驟1:下載FFmpeg

  1. 首先,前往FFmpeg的官方網站(ffmpeg.org)。
  2. 想要找編譯好的可以直接到https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z
  3. 下載 Windows 對應的版本。
FFMPEG在github鐘的最新編譯版本
FFMPEG在github鐘的最新編譯版本

步驟2:安裝FFmpeg

  1. 下載完成後,解壓縮zip文件到您希望存放FFmpeg的文件夾,例如 C:\FFmpeg
  2. 將FFmpeg添加到系統環境變量,便於命令行使用:
    • 右鍵點擊“我的電腦”或“此電腦”,選擇“屬性”。
    • 點擊“高級系統設置”,然後點擊“環境變量”。
    • 在“系統變量”下,找到“Path”變量,選擇“編輯”。
    • 點擊“新建”,添加FFmpeg的bin目錄路徑,例如 C:\FFmpeg\bin
    • 確認後關閉所有對話框。

步驟3:檢查FFmpeg是否安裝成功

  1. 打開命令提示符(cmd)。
  2. 輸入 ffmpeg -version 並按回車,如果安裝正確,它將顯示FFmpeg的版本信息。
ffmpeg -version

步驟4:使用FFmpeg壓縮WebP格式圖片

  1. 使用命令提示符,導航到包含您圖片的文件夾。
  2. 輸入以下命令來壓縮圖片為WebP格式:
ffmpeg -i input.jpg -compression_level 60 output.webp

步驟5:使用FFmpeg壓縮WebM格式視頻

  1. 在命令提示符中,定位到包含您視頻的文件夾。
  2. 壓縮視頻為WebM格式,輸入以下命令:
ffmpeg -i input.mp4 -c:v libvpx -b:v 1M -c:a libvorbis output.webm

以下是命令中的參數解釋:

  • -i input.mp4:這是輸入文件的名稱(MP4檔案名)。
  • -c:v libvpx:這個參數選擇了WebM視頻編解碼器libvpx。
  • -b:v 1M:這個參數設置了視頻比特率為1 Mbps。

執行此命令後,FFmpeg將開始轉換MP4文件,並將其儲存為WebM格式。你可以根據需要自定義命令以滿足特定的要求,例如更改視頻比特率、解析度等。

採用 Nvida CUDA 來加速

如果你有 Nvida 的顯卡,可以加入 -hwaccel cuda 來提供編碼速度,但因為目前 Nvida 還沒支援 webm 的編碼器,指令只能加速一小段,等以後有支援就可以享受顯卡加速的快樂

ffmpeg -hwaccel cuda -i input.mp4 -c:v libvpx -b:v 1M -c:a libvorbis output.webm

批次轉換

如果你跟我一樣有大量轉換需求,那你可用我編寫的 .bat 檔案,一次性大量轉換

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION

:: 設置FFmpeg的路徑,假設FFmpeg已經加到了系統環境變量,否則你需要指定完整的路徑,如 C:\path\to\ffmpeg\bin\ffmpeg.exe
SET "ffmpeg_path=C:\ffmpeg\bin\ffmpeg.exe"

:: 設置目錄路徑,這裡用 . 代表當前目錄
SET "source_dir=."

:: 設置輸出目錄,這裡也用 . 代表當前目錄,你可以修改為任何你想要的目錄
SET "output_dir=."

:: 轉換目錄下的所有.mp4檔案為.webm
FOR %%A IN ("%source_dir%\*.mp4") DO (
    SET "filename=%%~nA"
    SET "output_file=!filename!.webm"
    ECHO 正在轉換: "%%A"
    "!ffmpeg_path!" -hwaccel cuda -i "%%A" -c:v libvpx -b:v 1M -c:a libvorbis "%output_dir%\!output_file!"
    ECHO 轉換完成: "!output_file!"
)

ECHO 所有檔案轉換完成!
PAUSE

直接下載

將上述代碼保存為 .bat 文件,然後將這個批次檔放在含有你想要轉換的 .mp4 文件的目錄中,雙擊運行即可開始轉換過程。轉換後的 .webm 文件將會保存在設定的輸出目錄中。

注意事項:

  • 請根據你的情況替換ffmpeg_pathsource_dir,和output_dir變量。
  • -c:v libvpx -c:a libvorbis 是指定使用 VP8/Vorbis 編碼器進行視頻和音頻的轉碼。你可以根據需要修改這些參數,例如使用 VP9 編碼器則是 -c:v libvpx-vp9
  • 如果你在執行過程中遇到問題,請檢查FFmpeg是否正確安裝並添加到了系統環境變量中,或者在批次檔案中指定了正確的FFmpeg路徑。
  • -b:v 1M 是代表編碼率是1M,這參數可以不用有,有的話是可以更精確的指定畫質以及檔案大小

延伸閱讀