Files
awoooi/docs/adr/ADR-105-revert-a2-ollama-primary.md
Your Name b1ef05fa8c
Some checks failed
Code Review / ai-code-review (push) Successful in 50s
CD Pipeline / tests (push) Failing after 1m14s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
feat(ollama): ADR-110 GCP 三層容災架構(GCP-A → GCP-B → Local → Gemini)
## 變更摘要
- Primary: http://34.143.170.20:11434 (GCP-A SSD, 9x 載速 + 2x 推理)
- Secondary: http://34.21.145.224:11434 (GCP-B SSD)
- Fallback: http://192.168.0.111:11434 (M1 Pro Local HDD,最後防線)
- 廢止 ADR-105「111 唯一鐵律」,新建 ADR-110

## 核心改動
- config.py: 新增 OLLAMA_SECONDARY_URL;validator 加 GCP IP 白名單(34.143.170.20, 34.21.145.224)
- ollama_failover_manager.py: 三層 Ollama 決策矩陣;並行健康檢查三台;health_111 → health_gcp_a
- ollama_health_monitor.py: host label 萃取改為通用版(支援 GCP 公網 IP)
- failover_alerter.py: 故障/恢復主機動態顯示,不再硬編碼「Ollama 111 (GPU)」
- ollama_auto_recovery.py: notify_recovery 改為 ollama_gcp_a;recovered_host 動態
- k8s/awoooi-prod: configmap + deployment + network-policy 同步更新(egress 加 GCP /32)
- 服務層: 10 個服務檔案硬編碼 192.168.0.111 改為讀 settings.OLLAMA_URL
- 測試: URL 常數更新,新增三層容災場景,GCP IP 白名單驗證測試

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 22:49:23 +08:00

179 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-105: 推翻 A2 鐵律 — DIAGNOSE primary 改 Ollama 本地優先
**狀態**: 已廢止Superseded by ADR-110, 2026-05-03
**Status**: Accepted (2026-04-29)
**Deciders**: ogt首席架構師+ Claude Code
**Date**: 2026-04-29
**Supersedes**: A2 (2026-04-27 INC-20260425) DIAGNOSE 永久排除 Ollama
---
## Context
### A2 鐵律的歷史背景2026-04-27 INC-20260425
INC-20260425 事件NIM timeout 後 fallback 到 Ollama deepseek-r1:14b造成二次 timeout 238sCPU-only
統帥批准 A2 補丁:
- `_intent_provider_overrides[DIAGNOSE] = OPENCLAW_NEMO`(強制走 188 NIM
- `_diagnose_fallback_chain` = `[OPENCLAW_NEMO, GEMINI, CLAUDE]`**永久排除 Ollama**
- 6 個 regression test 守門「Ollama 不在 DIAGNOSE chain」
### 2 個月後的事實基礎變化
#### 新事實 1Ollama 111 已升級為 GPU
**舊A2 假設)**CPU-only deepseek-r1:14b @ 238s 不可用
**新2026-04-29 實測)**M1 Pro Apple Silicon GPU + qwen2.5:7b-instruct
- VRAM 8.2GB 全載入ctx 32k
- `curl /api/generate` hi prompt → **0.54s 完成**
- prod 已實際 load 此 model驗證自 `curl http://192.168.0.111:11434/api/ps`
#### 新事實 2A2 的雲端 fallback 全死
**2026-04-29 prod log 證據**
```
openclaw_nemo → 500 Internal Server Errorhttp://192.168.0.188:8088/api/v1/analyze/incident
gemini → 429 Too Many Requests每日配額 1000 用爆)
claude → 404 Not Found/v1/messagesmodel claude-3-haiku-20240307 過期)
```
A2 chain `[NEMO, GEMINI, CLAUDE]` 三條全部不可用 → 100% incident `llm_failed` → AI 自動修復永遠不啟動。
#### 新事實 3統帥鐵律明確衝突
- `feedback_ai_autonomous_direction.md`: 以本地免費 LLM 為主
- `feedback_ollama_111_only.md`: Ollama 唯一主機 = 111
- 統帥 2026-04-29 親口:「主要優先用 111 主機的 Ollama」+「就算 Ollama 慢還是可以等」
A2 鐵律與「本地優先」鐵律衝突。後者優先(範圍更廣、來源更高)。
---
## Decision
**推翻 A2 鐵律**DIAGNOSE primary 從 OPENCLAW_NEMO 改為 OLLAMA。
### 配套修改4 處)
#### 1. `ai_router.py:_intent_provider_overrides`
```python
IntentType.DIAGNOSE: AIProviderEnum.OLLAMA, # 推翻 A2
```
#### 2. `ai_router.py:_diagnose_fallback_chain`
```python
self._diagnose_fallback_chain = [
(AIProviderEnum.OLLAMA, self._ollama_default), # 主:本地免費(推翻 A2
(AIProviderEnum.OPENCLAW_NEMO, self._openclaw_nemo_default), # fallback 1
(AIProviderEnum.GEMINI, self._gemini_default), # fallback 2
(AIProviderEnum.CLAUDE, self._claude_default), # fallback 3
]
```
#### 3. `openclaw.py` 注入 `task_type="diagnose"`
critic 揭示的真根因webhooks alert_context 沒注入 `task_type`
`ai_providers/ollama.py:77` 讀不到 → 走 `OPENCLAW_TIMEOUT=30s`(不夠 qwen2.5:7b 推理)。
修法:
```python
exec_context = dict(alert_context) if alert_context else {}
if decision.intent == IntentType.DIAGNOSE:
exec_context["task_type"] = "diagnose"
```
讓 Ollama 用 `OLLAMA_DIAGNOSE_TIMEOUT_SECONDS=200s`
#### 4. 6 個 regression test 同步更新
| Test 檔案 | 舊斷言 | 新斷言 |
|----------|-------|-------|
| `test_p0_diagnose_routing.py::test_diagnose_override_is_openclaw_nemo` | DIAGNOSE = OPENCLAW_NEMO | `test_diagnose_override_is_ollama` → DIAGNOSE = OLLAMA |
| `test_ai_router_diagnose_fallback.py::test_diagnose_fallback_chain_no_ollama` | OLLAMA 不在 chain | `test_diagnose_fallback_chain_ollama_primary` → OLLAMA chain[0] |
| 其他 4 個守門 test | (排除 Ollama 系列) | (Ollama primary 系列) |
每個 test docstring 記載歷史脈絡 + 推翻原因,便於後續維護者理解。
### 不動的部分(避免 blast radius
- `_full_fallback_chain`: 不動(避免影響 RESTART/SCALE/CONFIG/DELETE
- `_tool_calling_fallback_chain`: 不動NEMOTRON 仍主推理 tool_call
- `_intent_provider_overrides[DELETE]`: 仍是 CLAUDECRITICAL 風險強制最強模型)
- `complexity_map`: 4/5 寫死 gemini/claudecritic M2 留待後續 ADR
---
## Consequences
### 正面
1. **AI 自動修復鏈路恢復** — DIAGNOSE 主推理走本地 Ollama雲端只當 fallback100% `llm_failed` 應降至 < 30%
2. **遵守統帥本地優先鐵律** — 對齊 `feedback_ai_autonomous_direction.md` + `feedback_ollama_111_only.md`
3. **節省雲端成本** — Gemini/Claude 配額不再被頻繁觸發燒光
4. **隱私加強** — incident evidence 不再頻繁送雲端
### 負面
1. **DIAGNOSE 延遲變長** — 真實 incident prompt 含 evidence + RAG context估 5-30svs OPENCLAW_NEMO 2-27s
- 緩解:`OLLAMA_DIAGNOSE_TIMEOUT_SECONDS=200s` 足夠等
- 統帥指令「即使慢也可以等」
2. **Ollama 健康度成單點** — 主推理掛掉 → fallback 雲端死亡 chain
- 緩解:`ollama_failover_manager` 偵測 111 不健康自動切 188 CPU 備援
- 監控:`OllamaInstanceDown` PrometheusRule 已部署(鐵證 3
3. **INC-20260425 教訓再現風險** — 若 prod model 不知為何切回 deepseek-r1:14bCPU 跑) → 238s timeout 重演
- 緩解:`models.json:21` 暫保留 deepseek-r1:14bcritic C1 警示,留待 ADR-106 處理)
- 防線CBcircuit breaker對 Ollama 失敗 5 次後 OPEN 60s
### 已知債(後續 ADR
- **ADR-106 (待寫)**`models.json` 對齊 prod 實際 load modelqwen2.5:7b-instruct
- **ADR-107 (待寫)**`complexity_map` 4/5 寫死 gemini/claude 改為動態路由
- **ADR-108 (待寫)**OpenClaw 188 服務 500 根因 + 修復策略
- **ADR-109 (待寫)**Claude API endpoint 過期model `claude-3-haiku-20240307``claude-haiku-4-5`
---
## Validation
### 部署前
- ✅ 1635 unit tests 全綠
- ✅ 6 個 regression test 反映新鐵律
- ✅ critic + onboarder 兩位 agent 全景審查通過
### 部署後(等 CD #1119 4115ddde 通過)
- [ ] prod pod image tag 更新到 fb0c72db
- [ ] 新 incident 路由 log `provider=ollama` 而非 `provider=openclaw_nemo`
- [ ] `llm_failed` 比率從 100% 降至 < 30%
- [ ] Ollama 真實 latency p95含 evidence + RAG< 60s
- [ ] `ollama_failover_manager` 對 OLLAMA primary 行為正確(不誤切 188 CPU
---
## Rollback
env 切換(不需 redeploy
```bash
# 暫時關閉本地優先,回到 A2 鐵律
kubectl -n awoooi-prod set env deployment/awoooi-api \
AI_FALLBACK_ORDER='["openclaw_nemo","gemini","claude"]'
```
或修改 commit `fb0c72db` 推 revert
```bash
git revert fb0c72db
git push gitea main
```
---
## References
- A2 原 commit: 2026-04-27 ai_router v4.4
- INC-20260425 教訓記錄: `feedback_auto_execute_pattern_bug.md`
- 推翻 commit: `fb0c72db` (2026-04-29)
- CD 阻塞修復: `4115ddde` (setup_test_schema.sql 補欄位)
- 統帥鐵律: `feedback_ai_autonomous_direction.md` / `feedback_ollama_111_only.md`
- critic PR review: 已驗證實測 0.54s + complexity_map 4/5 留債
- onboarder LLM 路徑全景審查: 確認 7 處違反本地優先鐵律