為什麼要自架 DeepWiki?
最近經常看到有開源專案使用 deepwiki.org 產生的互動式文件,覺得這個工具非常實用 — 丟一個 repo 進去就能自動產生結構化的技術文件和對話式查詢介面。
但問題是:deepwiki.org 需要上傳你的程式碼。對於私有專案或公司內部程式碼來說,這不太方便。
於是找到了 MIT 授權的 DeepWiki-Open,可以完全在本機自架。不過裝起來之後才發現,Embedding 需要 API key — 這又延伸出了後面搭配 Ollama 的一連串踩坑過程。
環境概述
- macOS host:repo 在本機資料夾(例如
/Users/yourname/Projects/...) - DeepWiki-Open:Docker 容器
- Ollama:本機運行(
http://host.docker.internal:11434),提供 cloud models + local embedding - LLM:選擇
minimax-m2:cloud— 最近在 Artificial Analysis 開源模型排名中拿下第一,230B 總參數但僅 10B 活躍(MoE 架構),推理速度快且擅長 coding 任務 - Embedding:選擇
nomic-embed-text— 輕量免費,本機 CPU 跑得動不會吃太多資源
前置準備
在開始之前,確保你的環境已具備:
- Docker 環境(我用的是 OrbStack,比 Docker Desktop 更輕量;當然用 Docker Desktop 也行)
- Ollama(安裝頁面)— 裝完後確認跑得起來:
ollama serve
先把需要的模型拉下來:
# LLM(MoE 架構,cloud 模式走 Ollama 代理)ollama pull minimax-m2:cloud
# Embedding(輕量,CPU 就跑得動)ollama pull nomic-embed-text安裝 DeepWiki-Open
git clone https://github.com/AsyncFuncAI/deepwiki-open.gitcd deepwiki-open接下來修改 docker-compose.yaml,這是整個設定的核心。
docker-compose 重點
核心就是「把本機 repo mount 進容器」+「讓容器能連到 Ollama」。
services: deepwiki: build: context: . dockerfile: Dockerfile ports: - "8001:8001" # API - "3000:3000" # UI (Next.js) environment: - DEEPWIKI_AUTH_MODE=false - OLLAMA_HOST=http://host.docker.internal:11434 - DEEPWIKI_EMBEDDER_TYPE=ollama - DEEPWIKI_GENERATOR_TYPE=ollama - EMBEDDING_MODEL=nomic-embed-text - LLM_MODEL=minimax-m2:cloud # 有些版本仍會硬檢查 OpenAI key(下文會講) - OPENAI_API_KEY=sk-fake-dummy - OPENAI_BASE_URL=http://host.docker.internal:11434/v1 volumes: - ~/.adalflow:/root/.adalflow - /Users/yourname/Projects:/mnt/local-repos:rw - ./api/config:/app/api/config:ro啟動:
docker compose up -d踩坑 1:Local repository 404 / Directory not found
症狀
UI 填本機路徑會噴:
Local repository API error (404): {"error":"Directory not found: /Users/yourname/Projects/"}原因
DeepWiki 後端跑在容器內,容器看不到 host 的 /Users/...,所以必定 404。這是 常見的 local repo 掛載問題。
解法
把 host 路徑 mount 到容器內,並在 UI 改用容器路徑:
- Host:
/Users/yourname/Projects - Container:
/mnt/local-repos
UI 輸入:
/mnt/local-repos/my-project踩坑 2:docker-compose 驗證錯誤
症狀
改 compose 時遇到:
services.deepwiki additional properties 'services' not allowed原因
YAML 結構錯,把 services: 又寫到 services.deepwiki: 底下(巢狀 services)。這是 Docker Compose 常見的 schema 驗證錯誤。
解法
把 services: 放回頂層,確保縮排正確,用以下指令檢查:
docker compose config踩坑 3:Failed to validate the authorization code
症狀
UI 顯示:
Failed to validate the authorization code原因
服務啟用了 auth 模式,UI 需要 auth code 才能產生文件。
解法
本地自用直接關掉:
- DEEPWIKI_AUTH_MODE=false踩坑 4:明明選 Ollama,卻一直要 OPENAI_API_KEY
這是整個安裝過程中最讓人困惑的問題。
症狀 A(初始階段)
OPENAI_API_KEY environment variable is not set...症狀 B(更關鍵)
後端 log 在 retriever 階段直接掛掉:
ValueError preparing retriever: Environment variable OPENAI_API_KEY must be set為什麼會這樣
某些版本的 DeepWiki-Open / 其底層依賴(常見是 OpenAI SDK 相容層)會在建立 embedding/retriever 時先硬檢查 OpenAI key,即使你要用的是 Ollama。這是 issue 上常見的抱怨。
我一開始還想說「那就填一個過期的真實 OpenAI key 吧」— 結果一樣驗證失敗。因為有些檢查不只看 key 有沒有設,還會實際打 OpenAI API 驗證,過期 key 自然過不了。這才逼出了後面整套改用 Ollama 相容端點的做法。
最終處理方式
用「OpenAI 相容模式」— 讓 DeepWiki 以為自己在呼叫 OpenAI,但其實全部打到 Ollama 的 /v1 相容端點:
# 設一個假的 key,只為了通過檢查- OPENAI_API_KEY=sk-fake-dummy# 把 base URL 指向 Ollama 的 OpenAI 相容端點- OPENAI_BASE_URL=http://host.docker.internal:11434/v1Ollama 的 OpenAI 相容端點是已知可用的解法,很多 OpenAI-only 的 client 都靠這招跑起來。
如果設了環境變數還是報錯
有些版本光靠環境變數不夠,embedding 仍然會走錯 client。這時候需要建立 api/config/embedder.json,直接強制指定用 OllamaClient:
{ "embedder": { "client_class": "OllamaClient", "model_kwargs": { "model": "nomic-embed-text" } }}這個設定檔會覆蓋底層的 client 選擇邏輯,確保 embedding 一定走 Ollama 而不是 OpenAI。
踩坑 5:模型不存在 → 連帶出現 “No valid XML found in response”
症狀
跑到最後一刻才爆:
POST http://host.docker.internal:11434/api/chat "HTTP/1.1 404 Not Found"Error: model 'qwen3:1.7b' not found (status code: 404)No valid XML found in response原因
DeepWiki 的模型名稱可以在三個地方指定:api/config/generator.json 設定檔、docker-compose 環境變數(LLM_MODEL)、以及 UI 前端的模型選擇器。不管在哪裡設定,模型名稱都必須跟 Ollama 裡實際 pull 過的完全一致,否則 Ollama 找不到模型就會回 404。
後端拿不到預期的回應格式時,前端會顯示 “No valid XML found…” — 這個錯誤訊息很誤導,容易讓人以為是 repo 格式問題,實際上只是模型不存在。
解法
確保你要用的模型已下載,名稱要和設定完全一樣:
# 例如你想用 qwen3:1.7bollama pull qwen3:1.7b
# 或者用本文的 minimax-m2:cloudollama pull minimax-m2:cloud然後在 docker-compose 中固定指定:
- LLM_MODEL=minimax-m2:cloudUI 的模型選擇器也能切換模型,但如果環境變數已經設定了
LLM_MODEL,實際行為以 server config 為準。建議統一在 docker-compose 管理,避免混淆。
踩坑 6:Embedding 遇到超大檔(context length exceeded)
症狀
nomic-embed-text embedding 時,log 會出現一堆:
Failed to get embedding for document '...babel-polyfill.min.js', skippingFailed to get embedding for document '...vuetify.min.js', skippingFailed to get embedding for document '...firebase-app.js', skipping或 Ollama 回 500:
the input length exceeds the context length (status code: 500)第一次看到 log 裡整片 Failed to get embedding 會很緊張,但其實不影響最終結果 — DeepWiki 會自動跳過這些檔案,其餘正常的原始碼照樣能被 index。
原因
minified/vendor 檔案 token 數超大,embedding 模型的 context length 不夠就會爆。DeepWiki 會自動跳過或 backoff retry。
處理方式
DeepWiki 預設的 api/config/repo.json 已經排除了 node_modules/、*.min.js、dist/ 等常見目錄。但如果你的專案有其他大型 vendor 檔案(例如直接放在 src/ 裡的第三方 JS),可以手動編輯 repo.json 加入排除規則:
{ "excluded_dirs": ["node_modules/", "vendor/", "dist/", "build/"], "excluded_files": ["*.min.js", "*.min.css", "*.bundle.js"]}建議在第一次跑之前就先確認排除清單,讓 ingestion 更乾淨、速度更快。
踩坑 7:讀檔編碼不是 UTF-8(UnicodeDecodeError)
症狀
換另一個老專案後,大量出現:
'utf-8' codec can't decode byte 0xa5 ... invalid start byte原因
那些 .js 檔不是 UTF-8(可能是 Big5、CP950 或 Windows-1252),DeepWiki ingestion 用 UTF-8 讀取就會失敗。
處理方式
兩種策略:
- 轉碼成 UTF-8(最佳做法)
- 直接排除這些歷史檔案路徑(如果本來就不重要)
全流程確認清單
正式跑之前,照這個順序快速確認一輪:
ollama list確認有nomic-embed-text(和你要用的 LLM 模型)- docker-compose 有設假的
OPENAI_API_KEY=sk-fake-dummy - UI 路徑用容器內路徑,例如
/mnt/local-repos/my-project - 按下生成,觀察 log 出現 “Embedding documents (X/Y)” 進度條代表正在跑
如果 embedding 階段還是報錯,再建 api/config/embedder.json 強制指定 OllamaClient(見踩坑 4)。
看 Log 判斷「已完成」還是「仍在跑」
DeepWiki 的 UI 文案很容易讓人誤判進度,但後端 log 才是真的。
RAG/索引已完成的關鍵 log
看到以下代表 embeddings + retriever 完成:
Loaded XXX documents from existing databaseEmbedding validation complete: XXX/XXXIndex built with XXX chunksFAISS retriever created successfullyRetriever prepared for /mnt/local-repos/...UI 卡在「驗證 Wiki 結構…」怎麼辦
這通常是前端狀態沒有更新,或快取/專案列表顯示邏輯的問題。最務實的做法是:
- 先確認後端
Retriever prepared有出現 - 再確保 LLM model 真的存在、可呼叫
- 必要時用 OpenAI 相容模式(fake key + base_url)讓流程不會卡在 retriever 初始化
最終穩定設定
| 項目 | 設定值 |
|---|---|
| Embedding | nomic-embed-text(免費、快速) |
| LLM | minimax-m2:cloud |
| 相容性 | OPENAI_API_KEY=sk-fake-dummy + OPENAI_BASE_URL=http://host.docker.internal:11434/v1 |
| 路徑 | 永遠用容器路徑 /mnt/local-repos/...(避免 host path 404) |
參考資源
回報錯字、失效連結,或告訴我你想看的延伸主題。