diff --git a/services/elephant_alpha_autonomous_engine.py b/services/elephant_alpha_autonomous_engine.py index d6300bf..6618c40 100644 --- a/services/elephant_alpha_autonomous_engine.py +++ b/services/elephant_alpha_autonomous_engine.py @@ -534,6 +534,49 @@ class ElephantAlphaAutonomousEngine: return default async def _execute_autonomous_decision(self, trigger: AutonomousTrigger) -> None: + # ─── Operation Ollama-First v5.0 修補(2026-05-03)─── + # 統帥反饋:每個 EA trigger 都先跑 Gemini orchestrate(燒錢)才 prefetch Hermes, + # 結果 Hermes 0 threats 時送出空泛幻覺訊息 + Gemini 帳單照付。 + # 修法:價格類 trigger Hermes-first short-circuit + # 1. 先跑 Hermes(5s timeout,免費 Ollama) + # 2. 0 threats → 直接 return(**不燒 Gemini**) + # 3. 有 threats → 才走原 Gemini orchestration + # 預期:>70% 的 trigger 在 Hermes 階段就被攔截,月省 Gemini ~3-5M tokens + if trigger.trigger_type in _PRICE_RELATED_TRIGGERS: + try: + hermes_threats = await self._fetch_hermes_threats_summary(top_n=5) + except Exception as e: + self._log.warning("Hermes pre-flight check 失敗 (non-blocking): %s", e) + hermes_threats = None + + if not hermes_threats: + # 0 threats 或 prefetch timeout → 直接 drop trigger,不燒 Gemini + self._log.info( + "EA short-circuit: trigger=%s 無 Hermes 實證 threats," + "跳過 Gemini orchestration 省成本", + trigger.trigger_type + ) + # 紀錄 short-circuit 事件供 token report 統計(不影響主流程) + try: + from services.ai_call_logger import log_ai_call + with log_ai_call( + caller='ea_engine', + provider='gcp_ollama', # 只跑了 Hermes,沒燒 Gemini + model='hermes3:latest', + meta={'short_circuit': True, 'trigger': trigger.trigger_type, + 'reason': 'no_hermes_threats'}, + ) as ctx: + ctx.set_tokens(input=0, output=0) # Hermes 已自己記 + ctx.status = 'cache_only' # 不算 ok 也不算 error + except Exception: + pass # logger 失敗不影響主流程 + return + + # Hermes 有實證 threats → 把它存進 trigger.conditions 給 orchestrator 用 + # 避免 orchestrator 又自己編 SKU 數字 + trigger.conditions = trigger.conditions or {} + trigger.conditions['_prefetched_hermes_threats'] = hermes_threats + context = await self._build_trigger_context(trigger) try: decision = await self._run_with_timeout( @@ -881,32 +924,62 @@ class ElephantAlphaAutonomousEngine: self._log.warning("Pre-fetch threats raised (non-blocking): %s", e) concrete_actions = None + # ─── Operation Ollama-First v5.0 修補:消除空泛幻覺訊息 ─── + # 統帥反饋(2026-05-03):fallback 路徑帶 OpenClaw Gemini plan 文字 + + # decision.reasoning 全是「312 SKU / 23% / 14 項任務」幻覺數字,無 DB 鉤住, + # 嚴重誤導決策。修法:concrete=Hermes 實證 vs concrete=None 兩條路徑徹底分離。 + # - 有實證 → 完整訊息(含 SKU 流失金額) + # - 無實證 → 極簡訊息「Hermes 即時數據不可用」+ 不再灌 LLM 幻覺 + + from services.telegram_templates import triaged_alert, _send_telegram_raw + if concrete_actions: + # 有實證數據路徑:保留完整訊息 ai_actions_payload = concrete_actions + ai_summary_text = (decision.reasoning or "")[:300] + ai_cause_text = ( + f"觸發類型:{_zh_trigger(trigger.trigger_type)} | " + f"信心度:{decision.confidence:.2f} | " + f"參與模組:{', '.join(_AGENT_LABEL.get(a.lower(), a) for a in decision.agents_required)}" + ) else: + # 無實證數據路徑:極簡訊息,明確標註無數據 + self._log.warning( + "EA escalation 落入 no-concrete-data fallback (trigger=%s);" + "送極簡訊息避免 LLM 幻覺數字誤導統帥", + trigger.trigger_type + ) ai_actions_payload = [ - f"步驟 {s.get('step', i+1)}:{_zh_step(s)}" - for i, s in enumerate(decision.execution_plan[:3]) - ] or ["無具體執行計畫"] + "⚠️ Hermes 即時威脅清單不可用(5s timeout 或無 SKU 命中)", + "📋 建議:手動下 SQL 查詢過去 24h competitor_price_history 確認狀況", + "🔧 或:SSH 188 跑 docker exec momo-pro-system python -c " + "'from services.hermes_analyst_service import HermesAnalystService;" + " print(HermesAnalystService().run().threats[:5])'", + ] + ai_summary_text = ( + f"⚠️ 本訊息為**無實證**告警:Hermes pre-fetch 失敗," + f"以下原始決策內容含 LLM 自由發揮數字(非 DB 數據),請審慎參考。" + ) + ai_cause_text = ( + f"觸發類型:{_zh_trigger(trigger.trigger_type)} | " + f"信心度:{decision.confidence:.2f} | " + f"⚠️ 無 Hermes SKU 數據(不顯示 LLM 幻覺 plan 文字)" + ) try: - from services.telegram_templates import triaged_alert, _send_telegram_raw msg, keyboard = triaged_alert( base_event={ "event_type": "ea_escalation", "title": f"🐘 EA 升級審核 · {_zh_trigger(trigger.trigger_type)}", "summary": ( f"自主決策信心度 {decision.confidence:.2f} 低於門檻,需人工批准" + + ("" if concrete_actions else "(⚠️ 無實證數據)") ), "id": f"ea_review_{int(datetime.now().timestamp())}", }, tier_label="🐘 Elephant Alpha · L3 HITL", - ai_summary=(decision.reasoning or "")[:300], - ai_cause=( - f"觸發類型:{_zh_trigger(trigger.trigger_type)} | " - f"信心度:{decision.confidence:.2f} | " - f"參與模組:{', '.join(_AGENT_LABEL.get(a.lower(), a) for a in decision.agents_required)}" - ), + ai_summary=ai_summary_text, + ai_cause=ai_cause_text, ai_actions=ai_actions_payload, ) await self._run_with_timeout(_send_telegram_raw, msg, timeout=10, reply_markup=keyboard)