From 53e1ae7ad70a99a0a29104497838fd62973ef3b3 Mon Sep 17 00:00:00 2001 From: OG T Date: Sun, 5 Apr 2026 12:11:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(phase25):=20I2=20NIM=20system=20prompt=20+?= =?UTF-8?q?=20I4=20field=5Fpath=20=E6=AD=A3=E5=89=87=E5=8C=B9=E9=85=8D?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../api/src/services/ai_providers/nemotron.py | 14 +++++++- apps/api/src/services/drift_detector.py | 34 +++++++++++++------ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/apps/api/src/services/ai_providers/nemotron.py b/apps/api/src/services/ai_providers/nemotron.py index b3744b5a..013db91a 100644 --- a/apps/api/src/services/ai_providers/nemotron.py +++ b/apps/api/src/services/ai_providers/nemotron.py @@ -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, diff --git a/apps/api/src/services/drift_detector.py b/apps/api/src/services/drift_detector.py index c873ecc1..39c622ef 100644 --- a/apps/api/src/services/drift_detector.py +++ b/apps/api/src/services/drift_detector.py @@ -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) # =============================================================================