fix(ai): SuggestedAction enum 擴充 + Pydantic fallback 防護
根本原因: NemoTron 輸出 "investigate" → Pydantic 只接受 4 個值 → 爆炸 → openclaw_analysis_parse_failed → analysis_result=None → 全部 fallback 卡片顯示「待分析」 修復: 1. SuggestedAction enum 新增 INVESTIGATE/OBSERVE/APPLY_HPA/TUNE_RESOURCES (prompt.py 列了 6 個,enum 只有 4 個,prompt/model 不同步是根源) 2. normalize_suggested_action validator: uppercase + 別名映射 + 未知值 fallback NO_ACTION 確保任何 LLM 輸出都不會讓 Pydantic 爆炸導致 analysis_result = None Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -19,11 +19,19 @@ class SuggestedAction(str, Enum):
|
|||||||
AI 建議操作類型
|
AI 建議操作類型
|
||||||
|
|
||||||
必須與 executor.OperationType 對應
|
必須與 executor.OperationType 對應
|
||||||
|
|
||||||
|
2026-04-17 ogt + Claude Sonnet 4.6: 新增 INVESTIGATE/APPLY_HPA/TUNE_RESOURCES
|
||||||
|
根本原因: prompts.py 列了 6 個值,但 enum 只有 4 個
|
||||||
|
→ NemoTron 輸出 "investigate" → Pydantic 爆炸 → analysis_result = None → 全部 fallback
|
||||||
"""
|
"""
|
||||||
RESTART_DEPLOYMENT = "RESTART_DEPLOYMENT"
|
RESTART_DEPLOYMENT = "RESTART_DEPLOYMENT"
|
||||||
DELETE_POD = "DELETE_POD"
|
DELETE_POD = "DELETE_POD"
|
||||||
SCALE_DEPLOYMENT = "SCALE_DEPLOYMENT"
|
SCALE_DEPLOYMENT = "SCALE_DEPLOYMENT"
|
||||||
NO_ACTION = "NO_ACTION" # 無需處理
|
APPLY_HPA = "APPLY_HPA"
|
||||||
|
TUNE_RESOURCES = "TUNE_RESOURCES"
|
||||||
|
INVESTIGATE = "INVESTIGATE" # 調查診斷,不下執行指令
|
||||||
|
OBSERVE = "OBSERVE" # 觀察等待
|
||||||
|
NO_ACTION = "NO_ACTION" # 無需處理
|
||||||
|
|
||||||
|
|
||||||
class AIRiskLevel(str, Enum):
|
class AIRiskLevel(str, Enum):
|
||||||
@@ -86,6 +94,7 @@ class OpenClawDecision(BaseModel):
|
|||||||
...,
|
...,
|
||||||
description="建議執行的操作類型",
|
description="建議執行的操作類型",
|
||||||
)
|
)
|
||||||
|
|
||||||
target_resource: str = Field(
|
target_resource: str = Field(
|
||||||
...,
|
...,
|
||||||
description="目標資源名稱 (e.g., 'harbor', 'grafana')",
|
description="目標資源名稱 (e.g., 'harbor', 'grafana')",
|
||||||
@@ -192,9 +201,31 @@ class OpenClawDecision(BaseModel):
|
|||||||
@field_validator("suggested_action", mode="before")
|
@field_validator("suggested_action", mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def normalize_suggested_action(cls, v):
|
def normalize_suggested_action(cls, v):
|
||||||
"""正規化 suggested_action"""
|
"""
|
||||||
|
正規化 suggested_action:大小寫 + 別名映射 + 未知值 fallback
|
||||||
|
|
||||||
|
2026-04-17 ogt + Claude Sonnet 4.6(亞太):
|
||||||
|
根本原因: NemoTron 輸出 "investigate"(小寫) → Pydantic 拒絕 → analysis_result = None
|
||||||
|
舊版只做 uppercase,未知值仍爆 → 修復為: 先 uppercase,再別名映射,最後 fallback NO_ACTION
|
||||||
|
"""
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
return v.upper().replace("-", "_").replace(" ", "_")
|
normalized = v.upper().replace("-", "_").replace(" ", "_")
|
||||||
|
# 別名映射 (LLM 可能輸出非正式名稱)
|
||||||
|
alias_map = {
|
||||||
|
"DIAGNOSE": "INVESTIGATE",
|
||||||
|
"DEBUG": "INVESTIGATE",
|
||||||
|
"MONITOR": "OBSERVE",
|
||||||
|
"WATCH": "OBSERVE",
|
||||||
|
"TUNE": "TUNE_RESOURCES",
|
||||||
|
"HPA": "APPLY_HPA",
|
||||||
|
}
|
||||||
|
normalized = alias_map.get(normalized, normalized)
|
||||||
|
# 未知值 fallback NO_ACTION,絕不讓 Pydantic 爆炸導致 analysis_result = None
|
||||||
|
try:
|
||||||
|
SuggestedAction(normalized)
|
||||||
|
return normalized
|
||||||
|
except ValueError:
|
||||||
|
return "NO_ACTION"
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user