需求
之前參考零度博客的文章,成功能在 llama UI 使用本地模型,但我想要的不只是聊天,而是一套可以長時間工作的本地 AI:能執行指令、修改程式、搜尋網路,也能從 Discord 接收任務。
最後採用的組合是:
- llama.cpp:載入模型,提供 OpenAI 相容 API
- Hermes Agent:主要 AI 助理,負責工具、記憶、工作階段與 Discord
- OpenHands:處理比較完整的程式開發工作
- SearXNG:提供免費、自架的網路搜尋後端
- n8n:負責排程、Webhook 與自動化流程
這篇主要分享它們怎麼接在一起,不會逐條展開所有安裝選項。只要先理解每個服務負責什麼,實際設定就沒有看起來那麼複雜。
整體架構
這套架構的核心只有一個:所有 Agent 共用同一個 llama.cpp 模型 API。
┌─ SearXNG(網路搜尋)
Discord ─ Hermes ────┤
│ └─ Docker 工具環境
│
├───────── llama.cpp ─ Qwen 本地模型
│
OpenHands ────┘
n8n ── 排程 / Webhook / HTTP API ── llama.cpp、Hermes 或其他服務
我的電腦是 Windows,llama.cpp 與 Hermes Agent 直接執行在 Windows;OpenHands、SearXNG、n8n 和 PostgreSQL 則放在 Docker Desktop。
這樣做的好處是 llama.cpp 可以直接使用顯示卡,不必在容器裡另外處理 CUDA;需要隔離環境的 OpenHands 與自動化服務則交給 Docker 管理。
1. 用 llama.cpp 提供共用模型 API
模型使用 Qwen3.6-35B-A3B 的 IQ2_M GGUF 量化版本,由 llama-server 啟動:
llama-server.exe `
-m .\models\Qwen3.6-35B-A3B-IQ2_M.gguf `
--alias qwen3.6-35b-a3b-iq2 `
-ngl 999 `
-c 65536 `
-np 1 `
-ctk q4_0 `
-ctv q4_0 `
--flash-attn on `
--api-key YOUR_API_KEY `
--host 0.0.0.0 `
--port 8080
啟動後就會得到一個 OpenAI 相容 API:
http://127.0.0.1:8080/v1
-c 65536 是 64K context;-np 1 代表只保留一個完整的推論 slot。因為這台電腦只有一張顯示卡,與其同時跑多個縮水的工作,不如讓 Hermes、OpenHands 和 n8n 排隊共用完整 context。
我也把 KV cache 設成 Q4,降低長 context 佔用的顯示記憶體。這組設定在 RTX 5070 Ti 16GB 上大約使用 13.8GB VRAM,實際能接受的 context 還是要依模型、量化和顯示卡調整。
2. 串接 OpenHands
OpenHands 放在 Docker 裡,設定重點是讓容器找到 Windows 上的 llama.cpp:
environment:
LLM_MODEL: openai/qwen3.6-35b-a3b-iq2
LLM_BASE_URL: http://host.docker.internal:8080/v1
LLM_API_KEY: ${LLAMA_API_KEY}
LLM_MAX_INPUT_TOKENS: 61440
LLM_MAX_OUTPUT_TOKENS: 4096
這裡不能填 127.0.0.1:8080,因為對 Docker 容器來說,127.0.0.1 是容器自己;要用 host.docker.internal 才能連回 Windows 主機。
模型有 65,536 tokens,但 OpenHands 的輸入上限設成 61,440,預留一部分給模型輸出和通訊格式,避免工作做到最後才因 context 滿掉而失敗。
OpenHands 可以執行指令與修改檔案,所以我只掛載一個專用資料夾:
environment:
SANDBOX_VOLUMES: /run/desktop/mnt/host/c/projects/myAI/workspace:/workspace/project:rw
不要直接掛載整個系統碟或使用者目錄。需要 AI 處理的專案先放進 workspace,權限範圍比較清楚,也不容易誤改其他檔案。
3. 用 SearXNG 提供網路搜尋
本地模型本身不知道即時資訊,llama.cpp 也不會憑空多出搜尋能力,所以另外架一個 SearXNG。
SearXNG 是聚合搜尋引擎,可以查詢多個公開搜尋來源,並用 JSON 回傳結果。Docker 啟動後,我把它限制在本機的 8888 port:
services:
searxng:
image: searxng/searxng:latest
ports:
- "127.0.0.1:8888:8080"
測試網址如下:
http://127.0.0.1:8888/search?q=test&format=json
在 SearXNG 的 settings.yml 還要開放 JSON 格式:
search:
formats:
- html
- json
我一開始使用 DDGS,偶爾會遇到空結果或搜尋錯誤。改成自架 SearXNG 後,Open WebUI 與 Hermes 都共用同一個搜尋後端,狀況穩定許多,也不需要另外申請搜尋 API key。
4. 串接 Hermes Agent
Hermes 是這套系統的主要入口。它負責維持工作階段、呼叫工具、壓縮長對話,還能透過 Discord 接收訊息。
模型設定指向 llama.cpp:
model:
default: qwen3.6-35b-a3b-iq2
provider: custom:local-llama
context_length: 65536
providers:
local-llama:
api: http://127.0.0.1:8080/v1
key_env: LLAMA_API_KEY
transport: chat_completions
Hermes 執行在 Windows 上,所以這裡使用 127.0.0.1。搜尋則指向剛才建立的 SearXNG:
web:
search_backend: searxng
SEARXNG_URL=http://127.0.0.1:8888
長時間工作很容易用滿 context,因此我也開啟 Hermes 的對話壓縮:
compression:
enabled: true
threshold: 0.55
target_ratio: 0.20
protect_last_n: 16
當內容累積到一定程度,Hermes 會把較舊的內容整理成摘要,同時保留最近的訊息。這不能保證任務永遠不會失去細節,但比單純等到 context 爆掉可靠很多。
Hermes 的終端工具同樣放進 Docker,並限制在同一個 workspace。即使 Discord Bot 收到不適當的指令,能碰到的檔案範圍仍然有限。
例如我把 Apple Health 匯出的資料放進 workspace,再從 Discord 請 Hermes 檢查資料夾。它能先辨識大型 XML 與其他資料,再分段執行後續分析,不需要直接把整個檔案塞進一次對話。
需要即時資料時,Hermes 會呼叫 SearXNG 搜尋。例如請它查看部落格現有文章,搜尋與整理結果都會直接回傳到 Discord。
5. n8n 負責排程與自動化
Hermes 適合接收自然語言任務,n8n 則適合處理固定流程,例如:
- 每天固定時間整理資料
- 收到 Webhook 後呼叫本地模型分類內容
- 搜尋新聞後交給模型摘要
- 任務完成後傳送 Discord 通知
n8n 可以用 HTTP Request 節點呼叫 llama.cpp:
POST http://host.docker.internal:8080/v1/chat/completions
Authorization: Bearer YOUR_API_KEY
如果要從 n8n 搜尋網路,因為它和 SearXNG 在同一個 Docker network,可以直接使用服務名稱:
GET http://searxng:8080/search?q={{ $json.keyword }}&format=json
n8n 的資料不要只放在容器裡。我使用 PostgreSQL 保存設定與執行資料,並替 n8n 的 volume、資料庫和加密金鑰做備份,這樣容器更新或重建後,工作流程不會一起消失。
6. 最容易弄錯的連線位置
這次串接花最多時間的地方,其實不是模型,而是分清楚「誰正在呼叫誰」。
| 呼叫端 | 目標 | 使用的網址 |
|---|---|---|
| Windows 上的 Hermes | llama.cpp | http://127.0.0.1:8080/v1 |
| Docker 裡的 OpenHands / n8n | llama.cpp | http://host.docker.internal:8080/v1 |
| Windows 上的 Hermes | SearXNG | http://127.0.0.1:8888 |
| Docker 裡的 n8n | SearXNG | http://searxng:8080 |
同樣一個服務,從 Windows 和 Docker 連線時可能要使用不同網址。先畫清楚服務的位置,通常就能解決大部分的「明明有啟動,卻連不上」問題。
啟動與停止
服務變多後,我沒有再逐個手動啟動,而是做成三個指令:
start-myAI.bat
status-myAI.bat
stop-myAI.bat
啟動順序是:
- 先啟動 llama.cpp,等待模型 API 可以連線
- 啟動 SearXNG、n8n、PostgreSQL 與 OpenHands
- 確認 llama.cpp 的 context 至少有 64K,再啟動 Hermes
停止時除了關閉 Docker 容器,也要結束 llama-server。只執行 docker compose down 不會卸載 Windows 上的模型,VRAM 當然還是會被佔用。
使用上的限制
這套架構目前使用一個 llama.cpp slot,所以不適合同時讓多個 Agent 大量輸出。Hermes、OpenHands 和 n8n 可以一起開著,但最好一次只讓一個主要任務生成,其他請求會排隊等待。
另外,我只把一般操作介面綁定在 127.0.0.1。Hermes API 具有終端和檔案工具,不要直接把 port 開到公網。若要從外部使用,可以透過 Discord,或另外使用有身分驗證的 VPN。
結果
完成後,這台電腦上的同一個 Qwen 模型可以:
- 在 Hermes 裡持續處理任務與搜尋網路
- 從 Discord 接收指令並回覆
- 交給 OpenHands 執行較完整的程式工作
- 由 n8n 定時啟動固定流程
- 所有可寫入的工具都限制在專用 workspace
這套組合不是把五個服務硬塞在一起,而是把工作分清楚:llama.cpp 專心推論、SearXNG 提供搜尋、Hermes 負責互動、OpenHands 負責程式工作、n8n 負責固定流程。理解這個分工後,後續更換模型或增加新的工具也比較容易。