fix(phase25): I2 NIM system prompt + I4 field_path 正則匹配修正
I2: nemotron.analyze() 補上 system role (NIM 標準 message format)
- 舊: messages=[{role:user, ...}]
- 新: messages=[{role:system, ...}, {role:user, ...}]
- 效果: K8s operator 角色定義,改善 tool calling 品質
I4: drift_detector._is_allowlisted/_is_critical 用正則取代 strip
- 舊: replace('[*]','') 後 startswith/in → 無法匹配 containers[0]
- 新: [*] → \[\d+\] 正則,正確匹配所有索引
- 修復: containers[*].image 現在能匹配 containers[0].image
This commit is contained in:
@@ -171,9 +171,21 @@ class NemotronProvider:
|
||||
timeout = getattr(settings, "NEMOTRON_TIMEOUT_SECONDS", 45)
|
||||
nvidia = self._get_nvidia()
|
||||
|
||||
# 2026-04-05 Claude Code: I2 修正 — 補上 system prompt (NIM 標準 message format)
|
||||
# NIM API 要求 system role 先定義模型角色,否則 tool calling 品質下降
|
||||
result = await asyncio.wait_for(
|
||||
nvidia.tool_call(
|
||||
messages=[{"role": "user", "content": tool_prompt}],
|
||||
messages=[
|
||||
{
|
||||
"role": "system",
|
||||
"content": (
|
||||
"你是 Kubernetes 操作專家。根據 AI 診斷結果,"
|
||||
"使用提供的工具生成精確的 kubectl 操作指令。"
|
||||
"優先選擇最安全、最小影響範圍的操作。"
|
||||
),
|
||||
},
|
||||
{"role": "user", "content": tool_prompt},
|
||||
],
|
||||
tools=_K8S_TOOLS,
|
||||
),
|
||||
timeout=timeout,
|
||||
|
||||
@@ -296,22 +296,34 @@ class DriftDetector:
|
||||
|
||||
return diffs
|
||||
|
||||
@staticmethod
|
||||
def _pattern_matches(pattern: str, field_path: str) -> bool:
|
||||
"""
|
||||
匹配 field_path 是否符合 pattern。
|
||||
|
||||
支援兩種萬用字元:
|
||||
- [*] → 任意索引 (e.g. containers[*] 匹配 containers[0], containers[1])
|
||||
- * → 任意字串段
|
||||
|
||||
2026-04-05 Claude Code: I4 修正 — 舊邏輯直接 strip [*] 導致
|
||||
containers[*].image 無法匹配 containers[0].image (首席架構師 Review I4)
|
||||
"""
|
||||
import re as _re
|
||||
|
||||
# 將 pattern 轉為正則:[*] → \[\d+\],* → [^.]+
|
||||
regex = _re.escape(pattern)
|
||||
regex = regex.replace(r"\[\*\]", r"\[\d+\]")
|
||||
regex = regex.replace(r"\*", r"[^.]+")
|
||||
# 允許 pattern 是前綴(field_path 可能更深,. 或 [ 或字串結尾均可)
|
||||
return bool(_re.match(f"^{regex}(\\.|\\[|$)", field_path))
|
||||
|
||||
def _is_allowlisted(self, field_path: str) -> bool:
|
||||
"""判斷欄位是否在白名單(靜默記錄不告警)"""
|
||||
for pattern in self._allowlist:
|
||||
# 簡單前綴匹配(*替換為粗略包含)
|
||||
clean_pattern = pattern.replace("[*]", "")
|
||||
if field_path.startswith(clean_pattern.replace("*", "")):
|
||||
return True
|
||||
return False
|
||||
return any(self._pattern_matches(p, field_path) for p in self._allowlist)
|
||||
|
||||
def _is_critical(self, field_path: str) -> bool:
|
||||
"""判斷欄位是否為關鍵欄位(HIGH 等級)"""
|
||||
for pattern in self._critical_fields:
|
||||
clean_pattern = pattern.replace("[*]", "")
|
||||
if clean_pattern.replace("*", "") in field_path:
|
||||
return True
|
||||
return False
|
||||
return any(self._pattern_matches(p, field_path) for p in self._critical_fields)
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user