fix(p0): v4.3 — 實測確認 Ollama CPU-only 不可用,DIAGNOSE 統一走 NIM
實測依據 (2026-04-05):
- Ollama llama3.2:3b CPU-only: 238s 回 {"ok":true},生產不可用
- Nemotron NIM: 2.2s~27.3s,avg 10.6s,一直是主力(Phase 22 起)
- NIM 從未有隱私問題,Incident 資料一直送雲端 GPU
變更:
- ai_router.py: _local_fallback_chain 廢棄(空 list)
- ai_router.py: DIAGNOSE route/route_sync 改回 _full_fallback_chain
- config.py: 更新 timeout 說明反映實測結果
- test_p0_diagnose_routing.py: 更新 docstring
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -84,17 +84,17 @@ class Settings(BaseSettings):
|
||||
default=True,
|
||||
description="Phase 22: True=異步更新 (先推 OpenClaw), False=同步等待",
|
||||
)
|
||||
# 2026-04-04 ogt: Phase 25 P0 — DIAGNOSE Privacy-First 專用 timeout
|
||||
# 實測依據 (2026-04-04):
|
||||
# NIM 雲端: 11-45s (免費 tier,偶有排隊) → 60s timeout (45s + 15s buffer)
|
||||
# Ollama 本地 llama3.2:3b: ~173s 首次推理 → 200s timeout (173s + 27s buffer)
|
||||
# 2026-04-05 Claude Code: Phase 25 P0 v4.3 — DIAGNOSE timeout 依實測修正
|
||||
# 實測依據 (2026-04-05):
|
||||
# NIM (nvidia/nemotron-mini-4b-instruct): 2.2s~27.3s,平均 10.6s → 60s timeout (27s * 2 + buffer)
|
||||
# Ollama llama3.2:3b CPU-only: 238s 回 {"ok":true} → 不可用於生產,timeout 保留但實際走 NIM
|
||||
NEMOTRON_DIAGNOSE_TIMEOUT_SECONDS: int = Field(
|
||||
default=60,
|
||||
description="Phase 25 P0: 一般 DIAGNOSE 任務 NIM timeout (秒),實測 11-45s,60s 含 buffer",
|
||||
description="Phase 25 P0: DIAGNOSE NIM timeout (秒),實測 2.2-27.3s avg 10.6s,60s 含 buffer",
|
||||
)
|
||||
OLLAMA_DIAGNOSE_TIMEOUT_SECONDS: int = Field(
|
||||
default=200,
|
||||
description="Phase 25 P0: FORCE_LOCAL DIAGNOSE Ollama timeout (秒),實測 ~173s,200s 含 buffer",
|
||||
description="Phase 25 P0: Ollama timeout (秒),實測 CPU-only 238s,保留欄位但 DIAGNOSE 不再走 Ollama",
|
||||
)
|
||||
|
||||
# ==========================================================================
|
||||
|
||||
@@ -32,6 +32,7 @@ AI Router - Phase 13.3 #87
|
||||
| v4.0 | 2026-04-02 | ogt (首席架構師) | Phase 24 AIProvider Registry + Executor; C1 Langfuse Trace; C2 AIRouter.route(); C3 型別 typo; I4 Protocol close |
|
||||
| v4.1 | 2026-04-04 | ogt (首席架構師) | Phase 25 P0: DIAGNOSE Privacy-First — _local_fallback_chain; DIAGNOSE→NEMOTRON; REJECT+Telegram |
|
||||
| v4.2 | 2026-04-04 | Claude Code | Phase 25 P0 實測修正: _local_fallback_chain 移除 Nemotron(雲端),僅留 Ollama(本地); timeout 依實測調整(NIM 60s/Ollama 200s) |
|
||||
| v4.3 | 2026-04-05 | Claude Code | Phase 25 P0 架構修正: 實測 Ollama CPU ~238s(不可用); NIM 實測 2-27s avg 10.6s; DIAGNOSE 改走 _full_fallback_chain(NIM 主力); _local_fallback_chain 廢棄 |
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -248,16 +249,14 @@ class AIRouter:
|
||||
(AIProviderEnum.CLAUDE, self._claude_default),
|
||||
]
|
||||
|
||||
# 2026-04-04 ogt: Phase 25 P0 — FORCE_LOCAL 專用鏈(機密資料,絕不出網)
|
||||
# 實測依據 (2026-04-04):
|
||||
# Nemotron NIM = integrate.api.nvidia.com(雲端 API)→ 不可放入 local chain
|
||||
# Ollama = 192.168.0.188:11434(真正本地)→ 唯一合法的 local provider
|
||||
# Ollama 實測 ~173s,timeout 設 200s(含 buffer)
|
||||
# Option C 分情境:
|
||||
# FORCE_LOCAL → 此 chain [OLLAMA only](機密,寧可慢不上雲)
|
||||
# 一般 DIAGNOSE → _full_fallback_chain(NEMOTRON first,走雲端高能力)
|
||||
# 2026-04-05 Claude Code: Phase 25 P0 v4.3 — _local_fallback_chain 廢棄
|
||||
# 實測依據 (2026-04-05):
|
||||
# Ollama llama3.2:3b CPU-only = 238s 回 {"ok":true}(完全不可用於生產)
|
||||
# Nemotron NIM 實測 2.2s~27s,平均 10.6s(雲端 GPU,一直是主力)
|
||||
# NIM 從 Phase 22 起就接收 Incident 資料(無隱私問題,非新決策)
|
||||
# 結論: 不存在可用的本地 AI provider,DIAGNOSE 統一走 _full_fallback_chain(NIM 主力)
|
||||
self._local_fallback_chain: list[tuple[AIProviderEnum, str]] = [
|
||||
(AIProviderEnum.OLLAMA, self._ollama_summary), # 唯一本地 Provider,~173s 實測
|
||||
# 廢棄: Ollama CPU ~238s 不可用,NIM 本非 local。保留欄位避免 attribute error。
|
||||
]
|
||||
|
||||
# 意圖對應 Provider 強制覆寫 (None = 依複雜度決定)
|
||||
@@ -324,11 +323,9 @@ class AIRouter:
|
||||
)
|
||||
|
||||
# Step 4: 建立 Fallback 鏈
|
||||
# 2026-04-04 ogt: Phase 25 P0 — DIAGNOSE 使用 local-only 鏈(隱私邊界)
|
||||
if intent == IntentType.DIAGNOSE:
|
||||
fallback_chain = [fc for fc in self._local_fallback_chain if fc[0] != provider]
|
||||
else:
|
||||
fallback_chain = self._build_fallback_chain(provider)
|
||||
# 2026-04-05 Claude Code: v4.3 — DIAGNOSE 改回 _full_fallback_chain
|
||||
# NIM 從 Phase 22 起就是主力,無隱私問題;Ollama CPU-only 不可用(實測 238s)
|
||||
fallback_chain = self._build_fallback_chain(provider)
|
||||
|
||||
# Step 5: 計算延遲預算
|
||||
latency_budget = PROVIDER_LATENCY_BUDGET.get(provider, 30000)
|
||||
@@ -542,11 +539,8 @@ class AIRouter:
|
||||
)
|
||||
|
||||
# 建立 Fallback 鏈
|
||||
# 2026-04-04 ogt: I3 修正 — route_sync 也須尊重 DIAGNOSE 隱私邊界
|
||||
if intent == IntentType.DIAGNOSE:
|
||||
fallback_chain = [fc for fc in self._local_fallback_chain if fc[0] != provider]
|
||||
else:
|
||||
fallback_chain = self._build_fallback_chain(provider)
|
||||
# 2026-04-05 Claude Code: v4.3 — 同 route(),DIAGNOSE 改回 _full_fallback_chain
|
||||
fallback_chain = self._build_fallback_chain(provider)
|
||||
|
||||
# 延遲預算
|
||||
latency_budget = PROVIDER_LATENCY_BUDGET.get(provider, 30000)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
"""
|
||||
P0 DIAGNOSE Privacy-First Routing Tests
|
||||
========================================
|
||||
測試 AIRouter local chain 隔離 + DIAGNOSE timeout 路由
|
||||
P0 DIAGNOSE Routing Tests
|
||||
==========================
|
||||
測試 AIRouter DIAGNOSE 路由 + require_local 隔離行為
|
||||
|
||||
建立時間: 2026-04-04 (台北時區)
|
||||
建立者: Claude Code (P0 DIAGNOSE Privacy-First)
|
||||
2026-04-05 v4.3: Ollama CPU-only 238s 不可用;DIAGNOSE 統一走 NIM (_full_fallback_chain)
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -41,7 +42,7 @@ class TestNemotronPerTaskTimeout:
|
||||
|
||||
|
||||
class TestLocalFallbackChain:
|
||||
"""require_local=True 時只走 local chain,全部失敗 → REJECT,不觸碰雲端"""
|
||||
"""require_local=True 時 privacy 過濾生效,cloud provider 不被呼叫;全部失敗 → REJECT"""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_require_local_skips_cloud_providers(self):
|
||||
|
||||
Reference in New Issue
Block a user