V10.422 persist 111 Ollama proxy launch agent

This commit is contained in:
OoO
2026-05-24 15:36:16 +08:00
committed by AiderHeal Bot
parent bf88fcd48e
commit 6d22d4920e
5 changed files with 112 additions and 3 deletions

View File

@@ -325,7 +325,7 @@ YOUTUBE_API_KEY = os.getenv('YOUTUBE_API_KEY', '')
# ==========================================
# 系統版本與路徑
# ==========================================
SYSTEM_VERSION = "V10.421"
SYSTEM_VERSION = "V10.422"
LOG_FILE_PATH = os.path.join(BASE_DIR, 'logs/system.log')
public_url = PUBLIC_URL # 用於模板顯示

View File

@@ -2,7 +2,7 @@
> **最後更新**: 2026-05-24 (台北時間)
> **狀態**: 🟢 四 AI Agent 自動化閉環已落地LLM 路由紅線升級為 Ollama-first 三主機級聯Gemini 備援預設關閉
> **適用版本**: V10.420
> **適用版本**: V10.422
---
@@ -31,7 +31,7 @@
- Gemini 不可被任何狀態面板或 router 推薦為主提供者:`AIProviderService._get_recommended_provider()` 不得回傳 `gemini`,只能顯示為 fallback 狀態;`llm_model_router``ea_engine` 若收到 `gemini-*` default 必須改回 `hermes3:latest`,需要深推理時才升本地 `deepseek-r1:14b`
- 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。
- 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 的 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 與 `OLLAMA_HOST=127.0.0.1:11434` 在登入/重啟後自動恢復。
- ElephantAlpha 的 `price_drop_alert` / `market_opportunity` Telegram HITL 告警必須把同款證據獨立呈現,至少包含 `match_type``price_basis``alert_tier``match_score`;沒有高信心同款與總價可比證據時,不得把 PChome/MOMO 價差寫成可直接跟價建議。
## 一、四 AI Agent 路由架構

View File

@@ -13,6 +13,7 @@
## 📅 詳細更新日誌 (考古存檔)
### 2026-05-24PChome 近門檻身份回收第二輪
- **V10.422 111 proxy LaunchAgent 持久化**: 新增 `scripts/ops/install_ollama111_allow_proxy.sh`,在 111 以 user LaunchAgent 安裝 `com.momo.ollama111-allow-proxy`,啟動時設定 `OLLAMA_HOST=127.0.0.1:11434`、重啟 Ollama、載入 allowlist proxy避免重開機或重新登入後 111 又回到 LAN 全開狀態。
- **V10.421 Kanebo Milano / hoi 蠟燭品類防錯配**: marketplace matcher 追加 `kanebo_milano_type_conflict``hoi_candle_line_conflict`,將 Kanebo Milano Collection 蜜粉餅 vs 絕色香水、hoi 日京山風香氛蠟燭 vs hoi!LAB 實驗室香氛蠟燭經典篇列為 hard veto同品牌、同系列字樣或同容量仍不可跨品類/跨產品線直接比價。
- **V10.420 111 Ollama LAN allowlist proxy**: 追查 111 高負載時確認來源不是 momo-pro而是 110 上 `awoooi-cd` 臨時測試與 121 VMware VM 直接打 `192.168.0.111:11434`,繞過 `ai_calls` 與 momo-pro router 載入 7B runner。新增 `scripts/ops/ollama111_allow_proxy.py`,將真實 Ollama 收斂到 `127.0.0.1:11434`,由 user-space proxy 綁 `192.168.0.111:11434` 並預設只允許 111 本機與 188 生產宿主110 / 121 會被 reset111 fallback 保留給 momo production。
- **V10.419 Dr.Hsieh LabSmart 精華品線防錯配**: marketplace matcher 追加 `dr_hsieh_labsmart_line_conflict`,只針對 Dr.Hsieh/達特醫的 `LabSmart Hi-Tech` / `LabSmart Classic` 精華被拿去對 `神經醯胺多重修復保濕精華液` 的近門檻錯配做 hard veto同品牌同容量但不同產品線不再因規格相同停在 `true_low_confidence` 或被誤推進比價。

View File

@@ -0,0 +1,108 @@
#!/usr/bin/env bash
set -euo pipefail
# Install a user LaunchAgent that keeps the 111 Ollama LAN entrypoint behind
# scripts/ops/ollama111_allow_proxy.py. This avoids sudo/pfctl and keeps the
# real Ollama process bound to localhost while exposing an allowlisted LAN port.
PROJECT_DIR="${PROJECT_DIR:-$(cd "$(dirname "$0")/../.." && pwd)}"
LABEL="${OLLAMA111_PROXY_LABEL:-com.momo.ollama111-allow-proxy}"
PLIST_DIR="${HOME}/Library/LaunchAgents"
PLIST_PATH="${PLIST_DIR}/${LABEL}.plist"
LOG_DIR="${HOME}/Library/Logs"
PID_FILE="${HOME}/.ollama/ollama111-allow-proxy.pid"
PYTHON_BIN="${PYTHON_BIN:-/usr/bin/python3}"
OLLAMA_APP="${OLLAMA_APP:-/Applications/Ollama.app}"
OLLAMA_HOST_VALUE="${OLLAMA_HOST_VALUE:-127.0.0.1:11434}"
ALLOWED_CIDRS="${OLLAMA111_PROXY_ALLOWED_CIDRS:-127.0.0.1/32,192.168.0.80/32,192.168.0.111/32,192.168.0.188/32}"
GUI_DOMAIN="gui/$(id -u)"
if [[ ! -f "${PROJECT_DIR}/scripts/ops/ollama111_allow_proxy.py" ]]; then
echo "missing proxy script under PROJECT_DIR=${PROJECT_DIR}" >&2
exit 1
fi
mkdir -p "${PLIST_DIR}" "${LOG_DIR}" "${HOME}/.ollama"
launchctl setenv OLLAMA_HOST "${OLLAMA_HOST_VALUE}"
# Stop the ad-hoc nohup proxy from the initial incident response, if present.
if [[ -f "${PID_FILE}" ]]; then
old_pid="$(cat "${PID_FILE}" 2>/dev/null || true)"
if [[ -n "${old_pid}" ]]; then
kill "${old_pid}" >/dev/null 2>&1 || true
fi
rm -f "${PID_FILE}"
fi
while IFS= read -r old_proxy_pid; do
[[ -n "${old_proxy_pid}" ]] && kill "${old_proxy_pid}" >/dev/null 2>&1 || true
done < <(pgrep -f '[o]llama111_allow_proxy.py' || true)
# Restart Ollama so it observes the launchd user environment. The pgrep pattern
# intentionally avoids matching this installer command.
osascript -e 'quit app "Ollama"' >/dev/null 2>&1 || true
while IFS= read -r old_ollama_pid; do
[[ -n "${old_ollama_pid}" ]] && kill "${old_ollama_pid}" >/dev/null 2>&1 || true
done < <(pgrep -f '[o]llama serve' || true)
sleep 2
open "${OLLAMA_APP}"
for _ in $(seq 1 20); do
if curl -fsS --max-time 2 "http://${OLLAMA_HOST_VALUE}/api/version" >/dev/null 2>&1; then
break
fi
sleep 1
done
cat > "${PLIST_PATH}" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${LABEL}</string>
<key>ProgramArguments</key>
<array>
<string>${PYTHON_BIN}</string>
<string>${PROJECT_DIR}/scripts/ops/ollama111_allow_proxy.py</string>
</array>
<key>WorkingDirectory</key>
<string>${PROJECT_DIR}</string>
<key>EnvironmentVariables</key>
<dict>
<key>OLLAMA111_PROXY_ALLOWED_CIDRS</key>
<string>${ALLOWED_CIDRS}</string>
<key>OLLAMA111_PROXY_LISTEN_HOST</key>
<string>192.168.0.111</string>
<key>OLLAMA111_PROXY_LISTEN_PORT</key>
<string>11434</string>
<key>OLLAMA111_PROXY_TARGET_HOST</key>
<string>127.0.0.1</string>
<key>OLLAMA111_PROXY_TARGET_PORT</key>
<string>11434</string>
<key>PYTHONUNBUFFERED</key>
<string>1</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>${LOG_DIR}/ollama111-allow-proxy.log</string>
<key>StandardErrorPath</key>
<string>${LOG_DIR}/ollama111-allow-proxy.err.log</string>
</dict>
</plist>
PLIST
launchctl bootout "${GUI_DOMAIN}" "${PLIST_PATH}" >/dev/null 2>&1 || true
launchctl bootstrap "${GUI_DOMAIN}" "${PLIST_PATH}"
launchctl kickstart -k "${GUI_DOMAIN}/${LABEL}"
sleep 2
echo "installed ${LABEL}"
echo "plist=${PLIST_PATH}"
echo "allowed=${ALLOWED_CIDRS}"
launchctl print "${GUI_DOMAIN}/${LABEL}" | head -40 || true
tail -20 "${LOG_DIR}/ollama111-allow-proxy.log" || true

0
scripts/ops/ollama111_allow_proxy.py Normal file → Executable file
View File