在 Obsidian Copilot 中串接 MiniMax 與本機 Embedding:安裝、配置與 Failed to Fetch 排錯紀錄
在 Obsidian Copilot 中串接 MiniMax 與本機 Embedding:安裝、配置與 Failed to Fetch 排錯紀錄
日期:2026-05-08
環境:macOS、Obsidian、Obsidian Copilot、MiniMax 中國區 API、本機 embedding server
這篇文章整理一次實際把 Obsidian 變得更 AI 化的設定流程:在 Obsidian 安裝 Copilot 外掛,將聊天模型串接到 MiniMax 中國區 API,並用本機 embedding 模型建立語意搜尋能力。過程中也遇到了 Copilot 顯示 Connection error. more message: Failed to fetch 的問題,最後透過本機 proxy 與 CORS 修正排除。
目標架構
最後完成的架構如下:
Obsidian Copilot
├─ Chat / 推理
│ └─ http://127.0.0.1:3839/v1
│ └─ 本機 MiniMax OpenAI-compatible proxy
│ └─ https://api.minimaxi.com/v1
│ └─ MiniMax-M2.7 / MiniMax-M2.7-highspeed
│
└─ Embedding / 語意索引
└─ http://127.0.0.1:3828/v1
└─ 本機 OpenAI-compatible embedding server
└─ Xenova/multilingual-e5-small
這樣做有幾個好處:
- Obsidian Copilot 只需要面向 OpenAI-compatible API。
- MiniMax 中國區 key 不需要直接暴露在 Copilot 前端請求中。
- 聊天推理只走 MiniMax。
- embedding 使用本機模型,不依賴 OpenAI、Gemini、Qwen 或其他雲端 embedding 服務。
- 遇到 Copilot 前端
fetch問題時,可以在本機 proxy 層加 log 與 CORS 控制。
1. 在 Obsidian 安裝 Copilot
Obsidian 的 Copilot 是社羣外掛,所以第一步是確認社羣外掛可用。
在 Obsidian 中:
- 開啟
Settings - 進入
Community plugins - 關閉 Restricted mode
- 搜尋並安裝
Copilot - 啟用 Copilot
如果是手動安裝,外掛目錄會位於 vault 底下:
<你的 Vault>/.obsidian/plugins/copilot/
正式可用的 Copilot 外掛資料夾通常至少會有:
main.js
manifest.json
styles.css
data.json
這次實作的 vault 位置是:
/Users/bbb/Documents/PE-Knowledge-Base
Copilot 設定檔位置是:
/Users/bbb/Documents/PE-Knowledge-Base/.obsidian/plugins/copilot/data.json
2. AI 服務與 Embedding 模型設定
Chat 模型:MiniMax 中國區
MiniMax 中國區 API key 已放在:
/Users/bbb/.hermes/.env
環境變數名稱:
MINIMAX_CN_API_KEY
MiniMax 的 OpenAI-compatible endpoint 使用:
https://api.minimaxi.com/v1
可用聊天模型包含:
MiniMax-M2.7
MiniMax-M2.7-highspeed
一開始可以直接把 Copilot 設為:
Provider: 3rd party (openai-format)
Base URL: https://api.minimaxi.com/v1
Model: MiniMax-M2.7
但實際使用時,Obsidian/Copilot 前端直接呼叫 MiniMax 可能會遇到連線與 CORS 類問題。最後採用更穩定的方式:建立本機 MiniMax proxy。
本機 MiniMax Proxy
本機 proxy 的用途是讓 Copilot 只呼叫本機:
http://127.0.0.1:3839/v1
proxy 再轉發到 MiniMax:
https://api.minimaxi.com/v1
Copilot 中 chat 模型最後設定成:
Provider: 3rd party (openai-format)
Model: MiniMax-M2.7
Base URL: http://127.0.0.1:3839/v1
API Key: local-minimax-proxy
Stream: false
第二個模型:
Provider: 3rd party (openai-format)
Model: MiniMax-M2.7-highspeed
Base URL: http://127.0.0.1:3839/v1
API Key: local-minimax-proxy
Stream: false
注意:這裡的 local-minimax-proxy 不是 MiniMax 真正的 key,只是讓 Copilot 設定欄位有值。真正的 MiniMax key 由本機 proxy 從 ~/.hermes/.env 讀取。
Embedding 模型:本機 multilingual-e5-small
MiniMax 的 embedding endpoint 雖然存在,但實測時帳戶回應餘額不足,而且 Copilot 偏好 OpenAI-compatible input 格式,MiniMax embedding 原生格式不完全相同。因此這次 embedding 採用本機模型。
最後使用:
Xenova/multilingual-e5-small
本機 embedding server 提供 OpenAI-compatible endpoint:
http://127.0.0.1:3828/v1/embeddings
Copilot embedding 設定:
Provider: 3rd party (openai-format)
Model: local-multilingual-e5-small
Base URL: http://127.0.0.1:3828/v1
API Key: local-only
Dimensions: 384
最後 Copilot 中只啟用:
Chat:
- MiniMax-M2.7
- MiniMax-M2.7-highspeed
Embedding:
- local-multilingual-e5-small
其他內建模型,例如 OpenAI、Gemini、Copilot Plus、Qwen embedding 等,都停用,避免 Copilot 在某些功能中誤選非預期供應商。
3. 實際遇到的問題與排錯方式
問題一:Copilot 顯示 Failed to Fetch
實際畫面中的錯誤是:
Error occurred
Connection error.
more message: Failed to fetch
這個錯誤不一定代表 API key 錯,也不一定代表 MiniMax 掛了。Failed to fetch 常常是瀏覽器或 Electron 前端在請求還沒有送成功前就被擋下,例如:
- CORS 預檢失敗
- localhost/private network request 被擋
- header 沒被允許
- endpoint 格式不符
- 串流回應格式讓前端解析失敗
- Copilot 實際讀到的設定不是我們以為的設定
排錯一:先確認服務本身可用
先不要從 Obsidian 測,直接用終端機測 MiniMax:
curl -sS https://api.minimaxi.com/v1/chat/completions \
-H "Authorization: Bearer $MINIMAX_CN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "MiniMax-M2.7",
"messages": [{"role": "user", "content": "請只回覆 OK"}],
"max_tokens": 20
}'
確認 MiniMax API 可用後,再測本機 proxy:
curl -sS http://127.0.0.1:3839/health
預期:
{
"ok": true,
"upstreamBaseUrl": "https://api.minimaxi.com/v1",
"hasMiniMaxKey": true
}
再測本機 embedding:
curl -sS http://127.0.0.1:3828/health
預期:
{
"ok": true,
"model": "Xenova/multilingual-e5-small"
}
排錯二:確認 Copilot 有沒有真的打到本機服務
一開始 Copilot 報錯時,不確定它到底有沒有打到本機 proxy。於是在 proxy 與 embedding server 中加入 request log。
觀察 log 後發現:
Obsidian -> 127.0.0.1:3839
代表 Copilot 確實有連到本機 proxy。問題不是「設定完全沒有生效」,而是前端請求或 CORS 流程仍然有東西被擋。
排錯三:修正 Embedding Server 的 OPTIONS 預檢
本機 embedding server 一開始只處理:
POST /v1/embeddings
GET /health
但瀏覽器或 Electron 前端在跨來源請求時,會先送:
OPTIONS /v1/embeddings
原本 server 對 OPTIONS 回 404,這會讓 Copilot 直接顯示 Failed to fetch。
修正後,embedding server 對 OPTIONS 回:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,OPTIONS
Access-Control-Allow-Headers: authorization,content-type,accept,x-requested-with
Access-Control-Expose-Headers: *
排錯四:補上 Private Network Access Header
即使一般 CORS 通了,Obsidian/Electron 從:
app://obsidian.md
呼叫:
http://127.0.0.1:3839
http://127.0.0.1:3828
仍可能觸發 Chromium 的 Private Network Access 檢查。
因此本機 proxy 與 embedding server 都補上:
Access-Control-Allow-Private-Network: true
並讓 Access-Control-Allow-Headers 動態回應瀏覽器實際要求的 headers,例如:
authorization
content-type
x-stainless-lang
x-stainless-package-version
這點是最後讓 Copilot 成功的關鍵之一。
排錯五:關閉 Streaming
MiniMax 支援 streaming,但 Copilot、OpenAI-compatible wrapper、Electron fetch、SSE 回應格式之間可能會有解析差異。
為了先追求穩定,最後將 Copilot 中 MiniMax 模型的 streaming 關閉:
stream: false
成功穩定後,未來若需要再嘗試開啟 streaming。
排錯六:Obsidian 重啟後 Copilot 會補回內建模型
Copilot 啟動後有時會自動把內建模型清單補回 data.json,例如:
OpenAI
Gemini
Copilot Plus
Qwen
這不代表那些服務真的有 API key,也不代表它們一定會被使用。但為了確保所有 AI 服務都只走 MiniMax 或本機 embedding,最後做法是:
- 保留 Copilot 自動補回的內建清單
- 但把非 MiniMax chat 模型設為 disabled
- 把非本機 embedding 模型設為 disabled
- 確認
defaultModelKey指向MiniMax-M2.7 - 確認
embeddingModelKey指向local-multilingual-e5-small
最後驗證
最後在終端機驗證:
curl -sS http://127.0.0.1:3839/health
curl -sS http://127.0.0.1:3828/health
並確認 CORS 預檢:
curl -i -X OPTIONS http://127.0.0.1:3839/v1/chat/completions \
-H "Origin: app://obsidian.md" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Private-Network: true" \
-H "Access-Control-Request-Headers: authorization, content-type, x-stainless-lang"
以及:
curl -i -X OPTIONS http://127.0.0.1:3828/v1/embeddings \
-H "Origin: app://obsidian.md" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Private-Network: true" \
-H "Access-Control-Request-Headers: authorization, content-type, x-stainless-lang"
兩者都應回:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: *
Access-Control-Allow-Private-Network: true
最後回到 Obsidian Copilot 測試一般問題,例如:
If a lead ball and a feather are dropped simultaneously from the same height, which will reach the ground first?
成功取得回覆後,代表 Copilot、MiniMax proxy、本機 embedding server、CORS、Obsidian 外掛設定都已串通。
小結
這次真正的重點不是單純「填 API key」,而是讓 Obsidian Copilot、MiniMax 中國區 API、本機 embedding 模型三者之間形成一個穩定的 OpenAI-compatible 架構。
最後成功的關鍵包括:
- Copilot chat 不直接打 MiniMax,而是打本機 MiniMax proxy。
- MiniMax key 留在本機 proxy,不直接放在前端請求中。
- embedding 使用本機
Xenova/multilingual-e5-small。 - 本機服務同時支援
POST與OPTIONS。 - CORS headers 動態允許 Copilot/OpenAI SDK 實際送出的 headers。
- 補上
Access-Control-Allow-Private-Network: true。 - Copilot 中停用非 MiniMax、非本機 embedding 的模型。
這樣 Obsidian 就能在保留本機知識庫工作流的同時,透過 MiniMax 提供聊天推理,並用本機 embedding 支援語意搜尋與相關筆記功能。
留言
張貼留言
歡迎留下您的心靈足跡👍