feat(chat): NemoClaw→Claude Haiku API + 告警只由 OpenClaw 分析
All checks were successful
CD Pipeline / build-and-deploy (push) Successful in 7m20s

老闆指示 (2026-04-03):
1. NemoClaw 改接 Claude API (claude-haiku-4-5),快速中文對話
2. 群組告警分析只觸發 OpenClaw,NemoClaw 不分析告警
3. OpenClaw/NemoClaw 雙向自然語言對話維持

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-03 19:19:56 +08:00
parent 10ad2a67c7
commit 781a6dac3e
2 changed files with 36 additions and 47 deletions

View File

@@ -144,23 +144,39 @@ class ChatManager:
async def _call_nemotron(self, system_prompt: str, user_message: str) -> str | None:
"""
呼叫 NemoClaw 對話 — NVIDIA NIM nemotron-mini-4b
呼叫 NemoClaw 對話 — Claude API (claude-haiku-4-5)
2026-04-03 ogt: Ollama 188 主機負載高常超時,暫時維持 NIM
老闆可接受慢速timeout=120s
2026-04-03 ogt: 老闆指示改接 Claude API快速且中文能力強
用 haiku 降低費用
"""
from src.services.nvidia_provider import get_nvidia_provider
nvidia = get_nvidia_provider()
try:
full_prompt = f"{system_prompt}\n\n用戶訊息: {user_message}"
response, success, _, _ = await nvidia.chat(
prompt=full_prompt,
model="nvidia/nemotron-mini-4b-instruct",
max_tokens=300,
)
if success and response and "not configured" not in response and "Circuit Breaker" not in response:
return response.strip()
import httpx
from src.core.config import get_settings
settings = get_settings()
api_key = getattr(settings, 'CLAUDE_API_KEY', None)
if not api_key:
logger.warning("nemotron_chat_failed", error="CLAUDE_API_KEY not configured")
return None
try:
async with httpx.AsyncClient(timeout=30.0) as client:
resp = await client.post(
"https://api.anthropic.com/v1/messages",
headers={
"x-api-key": api_key,
"anthropic-version": "2023-06-01",
"content-type": "application/json",
},
json={
"model": "claude-haiku-4-5-20251001",
"max_tokens": 300,
"system": system_prompt,
"messages": [{"role": "user", "content": user_message}],
},
)
resp.raise_for_status()
data = resp.json()
return data["content"][0]["text"].strip()
except Exception as e:
logger.warning("nemotron_chat_failed", error=str(e))
return None

View File

@@ -2684,36 +2684,19 @@ class TelegramGateway:
try:
chat_mgr = ChatManager()
# 2026-04-03 ogt: 老闆指示 — 告警分析只由 OpenClaw 負責NemoClaw 不分析告警
openclaw_prompt = (
f"你是 OpenClawAWOOOI SRE 戰情室首席 AI精通 K8s、Prometheus、告警分析。\n"
f"以下是一則基礎設施告警,請進行 RCA 根因分析並給出 3 點具體建議行動\n\n"
f"{alert_summary}"
)
nemo_prompt = (
f"你是 NemoClawAWOOOI SRE 戰情室 AI 參謀,由 NVIDIA Nemotron 驅動。\n"
f"以下是一則基礎設施告警,請從風險評估角度分析,指出潛在的連鎖失效點:\n\n"
f"以下是一則基礎設施告警,請進行 RCA 根因分析並給出 3 點具體建議行動\n"
f"繁體中文回應,不超過 300 字:\n\n"
f"{alert_summary}"
)
# 2026-04-03 ogt: 並行執行,兩個 AI 同時分析,不互相影響(更客觀)
openclaw_task = asyncio.create_task(
chat_mgr._call_openclaw(
system_prompt="你是 OpenClawAWOOOI SRE 戰情室首席 AI。",
user_message=openclaw_prompt,
)
)
nemo_task = asyncio.create_task(
chat_mgr._call_nemotron(
system_prompt="你是 NemoClawAWOOOI SRE 戰情室 AI 參謀。",
user_message=nemo_prompt,
)
openclaw_analysis = await chat_mgr._call_openclaw(
system_prompt="你是 OpenClawAWOOOI SRE 戰情室首席 AI。稱呼用戶為「老闆」。",
user_message=openclaw_prompt,
)
openclaw_analysis, nemo_analysis = await asyncio.gather(
openclaw_task, nemo_task, return_exceptions=True
)
# OpenClaw 發到群組
if openclaw_analysis and not isinstance(openclaw_analysis, Exception):
await self.send_as_openclaw(
text=f"🦞 <b>OpenClaw 分析</b>\n\n{openclaw_analysis}",
@@ -2723,16 +2706,6 @@ class TelegramGateway:
else:
logger.warning("trigger_group_ai_discussion_openclaw_empty")
# NemoClaw 發到群組(同樣 reply 告警訊息,並排出現)
if nemo_analysis and not isinstance(nemo_analysis, Exception):
await self.send_as_nemotron(
text=f"🤖 <b>NemoClaw 分析</b>\n\n{nemo_analysis}",
reply_to_message_id=alert_message_id,
)
logger.info("group_ai_discussion_nemo_sent")
else:
logger.warning("trigger_group_ai_discussion_nemo_empty")
logger.info("group_ai_discussion_completed", alert_message_id=alert_message_id)
except Exception as e: