From 1717dad3d7c0c99ed0bb6461322569be99bb569f Mon Sep 17 00:00:00 2001 From: OoO Date: Sun, 24 May 2026 15:50:39 +0800 Subject: [PATCH] V10.426 deduplicate 111 proxy reject logs --- config.py | 2 +- docs/AI_INTELLIGENCE_MODULE_SOT.md | 4 ++-- docs/memory/history_logs.md | 1 + scripts/ops/ollama111_allow_proxy.py | 9 ++++++++- tests/test_ollama111_proxy_contract.py | 8 ++++++++ 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/config.py b/config.py index 94b83d4..137a96d 100644 --- a/config.py +++ b/config.py @@ -325,7 +325,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '') # ========================================== # 系統版本與路徑 # ========================================== -SYSTEM_VERSION = "V10.425" +SYSTEM_VERSION = "V10.426" LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log') public_url = PUBLIC_URL # 用於模板顯示 diff --git a/docs/AI_INTELLIGENCE_MODULE_SOT.md b/docs/AI_INTELLIGENCE_MODULE_SOT.md index c023d44..9593239 100644 --- a/docs/AI_INTELLIGENCE_MODULE_SOT.md +++ b/docs/AI_INTELLIGENCE_MODULE_SOT.md @@ -2,7 +2,7 @@ > **最後更新**: 2026-05-24 (台北時間) > **狀態**: 🟢 四 AI Agent 自動化閉環已落地;LLM 路由紅線升級為 Ollama-first 三主機級聯,Gemini 備援預設關閉 -> **適用版本**: V10.425 +> **適用版本**: V10.426 --- @@ -32,7 +32,7 @@ - ElephantAlpha prompt / agent registry 不得再把 OpenClaw 描述為 Gemini 主模型;OpenClaw 是 `qwen2.5-coder:7b` / `qwen3:14b` Ollama-first 策略師,Gemini 僅能在 guard 顯式解鎖後作 emergency fallback。 - 111 `192.168.0.111` 只是最後一道 Mac fallback,不承接 7B+、vision、long-context 模型長駐;`OllamaService.generate()` 落到 111 時會將 `qwen3`、`deepseek-r1`、`hermes3`、`qwen2.5*`、`gemma3`、`llava`、`minicpm-v` 與 7B+ 模型依 `OLLAMA_111_MODEL_DOWNGRADE_PATTERNS` 降級到 `OLLAMA_111_MODEL_FALLBACK=llama3.2:latest`,並以 `OLLAMA_111_KEEP_ALIVE=5m`、`OLLAMA_111_MAX_TIMEOUT=20`、`OLLAMA_111_NUM_CTX=4096`、`OLLAMA_111_NUM_PREDICT=512` 封頂。OpenClaw 報告型路徑的業務 keep-alive 預設 `5m`;Code Review 以 `CODE_REVIEW_ALLOW_111_FALLBACK=false`、Hermes 以 `HERMES_ALLOW_111_FALLBACK=false` 預設跳過 111,避免 16GB RAM 主機與 GCP-B 被長駐 runner、長輸出與 24h keep-alive 壓到高 load。 - Scheduler 每 15 分鐘執行 `run_ollama_111_usage_guard_check()`,只讀 `ai_calls` 統計最近視窗的 GCP-A / GCP-B / 111 呼叫量;預設 60 分鐘內 Ollama 呼叫至少 20 次、111 至少 3 次且占比 >= 5% 才推 Telegram。這是觀測護欄,不改路由、不寫 DB、不自動重啟服務。 -- 111 的 LAN 入口必須經 `scripts/ops/ollama111_allow_proxy.py` allowlist proxy:真實 Ollama 綁 `127.0.0.1:11434`,proxy 綁 `192.168.0.111:11434`,預設只允許 111 本機與 188 生產宿主;110 / 121 / 其他 LAN client 不能直接打 111,避免跨專案 CI 或 VM 繞過 momo-pro router 載入 7B+ runner。111 上以 `scripts/ops/install_ollama111_allow_proxy.sh` 安裝 user LaunchAgent,安裝器會把 proxy script 複製到 `~/.local/share/momo-pro-system/ollama111_allow_proxy.py`,讓 LaunchAgent 不依賴 iCloud repo 掛載路徑,並讓 proxy 與 `OLLAMA_HOST=127.0.0.1:11434` 在登入/重啟後自動恢復。 +- 111 的 LAN 入口必須經 `scripts/ops/ollama111_allow_proxy.py` allowlist proxy:真實 Ollama 綁 `127.0.0.1:11434`,proxy 綁 `192.168.0.111:11434`,預設只允許 111 本機與 188 生產宿主;110 / 121 / 其他 LAN client 不能直接打 111,避免跨專案 CI 或 VM 繞過 momo-pro router 載入 7B+ runner。111 上以 `scripts/ops/install_ollama111_allow_proxy.sh` 安裝 user LaunchAgent,安裝器會把 proxy script 複製到 `~/.local/share/momo-pro-system/ollama111_allow_proxy.py`,讓 LaunchAgent 不依賴 iCloud repo 掛載路徑,並讓 proxy 與 `OLLAMA_HOST=127.0.0.1:11434` 在登入/重啟後自動恢復。拒絕日誌以 `OLLAMA111_PROXY_REJECT_LOG_DEDUP_SEC=60` 去重,避免 121 這類旁路探測刷爆 111 磁碟日誌。 - ElephantAlpha 的 `price_drop_alert` / `market_opportunity` Telegram HITL 告警必須把同款證據獨立呈現,至少包含 `match_type`、`price_basis`、`alert_tier` 與 `match_score`;沒有高信心同款與總價可比證據時,不得把 PChome/MOMO 價差寫成可直接跟價建議。 ## 零之一、12 Agent 決策信封(2026-05-24) diff --git a/docs/memory/history_logs.md b/docs/memory/history_logs.md index 8e5014f..9a6be27 100644 --- a/docs/memory/history_logs.md +++ b/docs/memory/history_logs.md @@ -13,6 +13,7 @@ ## 📅 詳細更新日誌 (考古存檔) ### 2026-05-24:PChome 近門檻身份回收第二輪 +- **V10.426 111 proxy 拒絕日誌去重**: `ollama111_allow_proxy.py` 對同一來源 IP 的 reject log 預設 60 秒去重,保留 110 / 121 被擋的可觀測性,同時避免旁路 VM 持續探測時把 111 的 proxy log 與磁碟 I/O 刷高。 - **V10.425 111 fallback 使用率護欄**: Scheduler 每 15 分鐘只讀 `ai_calls` 檢查 111 Ollama fallback 使用率,預設 60 分鐘內 Ollama 呼叫 >=20、111 呼叫 >=3 且占比 >=5% 才推 Telegram,並列出 111 caller Top 5;此護欄只觀測與告警,不改路由、不寫 DB、不重啟服務,讓 111 被異常承接高負載時可即早發現。 - **V10.424 111 proxy LaunchAgent 安裝路徑穩定化**: `install_ollama111_allow_proxy.sh` 會把 proxy script 複製到 `~/.local/share/momo-pro-system/ollama111_allow_proxy.py` 後再寫入 LaunchAgent,避免 111 重啟或 iCloud repo 路徑未掛載時代理失效;同時清空舊 stderr log,讓安裝後狀態更容易判讀。 - **V10.423 12 Agent 決策信封**: `triaged_alert()` 支援 `decision_envelope` 結構化區塊,讓 Hermes / NemoTron / OpenClaw / ElephantAlpha 與後續 12 角色決策統一輸出 `severity`、`evidence`、`recommended_action`、`expected_impact`、`confidence`、`guardrails` 與 `trace`;缺證據時必須明確標記資料品質與 HITL 邊界,避免再出現空泛效益預測或不可追溯告警。 diff --git a/scripts/ops/ollama111_allow_proxy.py b/scripts/ops/ollama111_allow_proxy.py index 9fa4f32..848b61c 100755 --- a/scripts/ops/ollama111_allow_proxy.py +++ b/scripts/ops/ollama111_allow_proxy.py @@ -16,6 +16,7 @@ import logging import os import signal import sys +import time LISTEN_HOST = os.getenv("OLLAMA111_PROXY_LISTEN_HOST", "192.168.0.111") @@ -37,6 +38,8 @@ def _allowed_networks() -> tuple[ipaddress._BaseNetwork, ...]: ALLOWED_NETWORKS = _allowed_networks() +REJECT_LOG_DEDUP_SEC = float(os.getenv("OLLAMA111_PROXY_REJECT_LOG_DEDUP_SEC", "60")) +_LAST_REJECT_LOG: dict[str, float] = {} def _is_allowed(peer_ip: str) -> bool: @@ -69,7 +72,11 @@ async def _handle_client(reader: asyncio.StreamReader, writer: asyncio.StreamWri peer = writer.get_extra_info("peername") peer_ip = peer[0] if peer else "unknown" if not _is_allowed(peer_ip): - logging.warning("reject peer=%s allowed=%s", peer_ip, ",".join(ALLOWED_CIDRS)) + now = time.monotonic() + last_log = _LAST_REJECT_LOG.get(peer_ip, 0.0) + if now - last_log >= REJECT_LOG_DEDUP_SEC: + logging.warning("reject peer=%s allowed=%s", peer_ip, ",".join(ALLOWED_CIDRS)) + _LAST_REJECT_LOG[peer_ip] = now writer.close() await writer.wait_closed() return diff --git a/tests/test_ollama111_proxy_contract.py b/tests/test_ollama111_proxy_contract.py index effc970..a06c5ce 100644 --- a/tests/test_ollama111_proxy_contract.py +++ b/tests/test_ollama111_proxy_contract.py @@ -21,3 +21,11 @@ def test_ollama111_proxy_logs_to_stdout_for_launchagent_collection(): assert "import sys" in proxy_source assert "stream=sys.stdout" in proxy_source + + +def test_ollama111_proxy_reject_logs_are_deduplicated(): + proxy_source = (ROOT / "scripts/ops/ollama111_allow_proxy.py").read_text() + + assert "OLLAMA111_PROXY_REJECT_LOG_DEDUP_SEC" in proxy_source + assert "_LAST_REJECT_LOG" in proxy_source + assert "now - last_log >= REJECT_LOG_DEDUP_SEC" in proxy_source