feat(ai): 委派 Incident RCA 給 OpenClaw (Nemo) — 架構鐵律修正
架構鐵律: OpenClaw = AI 大腦,AWOOOI API 透過 HTTP 委派仲裁 修改: - openclaw.py: 加入 _call_openclaw_analyze(),在 LLM fallback 前先呼叫 OpenClaw - 04-configmap.yaml: OPENCLAW_URL 修正為 :8088 (新容器 port) - AI_FALLBACK_ORDER 改為 ["ollama","claude"] (移除 Gemini 付費 API) OpenClaw /api/v1/analyze/incident → qwen2.5:7b 本機 Ollama (Nemo) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -255,6 +255,82 @@ class OpenClawService:
|
||||
}
|
||||
|
||||
# =========================================================================
|
||||
# =========================================================================
|
||||
# OpenClaw (Nemo) 委派仲裁 — 架構鐵律
|
||||
# 2026-04-01 ogt: AWOOOI API 不直接打 LLM,委派給 OpenClaw (192.168.0.188:8089)
|
||||
# =========================================================================
|
||||
|
||||
async def _call_openclaw_analyze(
|
||||
self,
|
||||
incident_id: str,
|
||||
severity: str,
|
||||
signals: list[dict],
|
||||
affected_services: list[str],
|
||||
expert_context: dict | None = None,
|
||||
) -> dict | None:
|
||||
"""
|
||||
委派 Incident RCA 給 OpenClaw (Nemo) API
|
||||
|
||||
Returns:
|
||||
proposal_dict if success, None if failed (fallback to direct LLM)
|
||||
"""
|
||||
try:
|
||||
client = await self._get_client()
|
||||
payload = {
|
||||
"incident_id": incident_id,
|
||||
"severity": severity,
|
||||
"signals": signals[:5],
|
||||
"affected_services": affected_services,
|
||||
"expert_context": expert_context,
|
||||
}
|
||||
resp = await client.post(
|
||||
f"{settings.OPENCLAW_URL}/api/v1/analyze/incident",
|
||||
json=payload,
|
||||
timeout=httpx.Timeout(130.0, connect=5.0),
|
||||
)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
|
||||
# 驗證必要欄位
|
||||
if not data.get("action_title") or not data.get("risk_level"):
|
||||
logger.warning("openclaw_analyze_invalid_response", incident_id=incident_id)
|
||||
return None
|
||||
|
||||
logger.info(
|
||||
"openclaw_analyze_success",
|
||||
incident_id=incident_id,
|
||||
confidence=data.get("confidence", 0),
|
||||
risk_level=data.get("risk_level"),
|
||||
)
|
||||
|
||||
# 轉換為 AWOOOI API proposal dict 格式
|
||||
return {
|
||||
"action": data.get("action_title", "AI 分析"),
|
||||
"description": data.get("description", ""),
|
||||
"kubectl_command": data.get("kubectl_command") or "",
|
||||
"target_resource": data.get("target_resource", "unknown"),
|
||||
"namespace": data.get("namespace", "awoooi-prod"),
|
||||
"risk_level": data.get("risk_level", "medium"),
|
||||
"reasoning": data.get("reasoning", ""),
|
||||
"confidence": data.get("confidence", 0.8),
|
||||
"primary_responsibility": data.get("primary_responsibility", "INFRA"),
|
||||
"optimization_suggestions": data.get("optimization_suggestions", []),
|
||||
"signoz_correlation": data.get("signoz_correlation", ""),
|
||||
"from_cache": False,
|
||||
"provider": "openclaw_nemo",
|
||||
"ai_tokens": 0,
|
||||
"ai_cost": 0.0,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(
|
||||
"openclaw_analyze_failed",
|
||||
incident_id=incident_id,
|
||||
error=str(e),
|
||||
reason="fallback to direct LLM",
|
||||
)
|
||||
return None
|
||||
|
||||
# AI Provider Implementations - Enhanced with Structured Output
|
||||
# =========================================================================
|
||||
|
||||
@@ -1312,6 +1388,14 @@ Focus on:
|
||||
signoz_available=signoz_metrics is not None,
|
||||
)
|
||||
|
||||
# 2026-04-01 ogt: 架構鐵律 — OpenClaw (Nemo) 是 AI 大腦,優先委派仲裁
|
||||
# AWOOOI K8s Pod 不直接打 Ollama/NVIDIA,避免並發逾時
|
||||
openclaw_result = await self._call_openclaw_analyze(
|
||||
incident_id, severity, signals, affected_services, expert_context
|
||||
)
|
||||
if openclaw_result is not None:
|
||||
return openclaw_result, "openclaw_nemo", True
|
||||
|
||||
# 使用快取呼叫 LLM
|
||||
alert_context = {
|
||||
"incident_id": incident_id,
|
||||
|
||||
Reference in New Issue
Block a user