Files
ewoooc/docs/AI_INTELLIGENCE_MODULE_SOT.md
OoO 40ddf4eee0
All checks were successful
CD Pipeline / deploy (push) Successful in 1m3s
強化 PChome legacy 配對重驗證
2026-05-19 22:18:32 +08:00

34 KiB
Raw Blame History

MOMO PRO — AI 競價情報模組 Single Source of Truth

最後更新: 2026-05-19 (台北時間) 狀態: 🟢 四 AI Agent 自動化閉環已落地LLM 路由紅線升級為 Ollama-first 三主機級聯Gemini 僅備援 / 鎖定場景 適用版本: V10.281


零、LLM 路由紅線2026-05-12

  • 所有 AI Agent、LLM 推理與 embedding 預設必須走 Ollama 三主機級聯GCP-A 34.143.170.20:11434 → GCP-B 34.21.145.224:11434 → 111 192.168.0.111:11434
  • services/ollama_service.resolve_ollama_host() 是主機解析契約;OLLAMA_HOSTHERMES_URLEMBEDDING_HOSTOLLAMA_API_BASE 只接受 GCP-A / GCP-B / 111 或 110 的核准轉發端口。
  • Gemini 只能作為 Ollama 主路徑失敗後的備援,或 ADR-028 明確鎖定的 MCP Grounding、PPT/vision、週/月報、Code Review、EA HITL、複雜 SKU 升級等低頻場景。
  • 188 192.168.0.188 僅是 App / DB / scheduler / Telegram bot 容器宿主與 AutoHeal target不可作為 Ollama 節點。
  • 通用 AI 文案、關鍵字、商品洞察與 Telegram Q&A 第一響應不得 Gemini-first。
  • Hermes intent / analyst 路徑不得手刻 /api/generate 或只 resolve 單次 host必須走 OllamaService,讓同一請求可依序 retry GCP-A → GCP-B → 111。
  • NemoTron qwen3 dispatch 的 /api/chat tool-calling 路徑也必須同一請求最多嘗試三台 Ollama第一台失敗要 mark_unhealthy() 後再試下一台,最後才 fallback NIM。
  • PPT vision、PPT 文案 final fallback、MCP 離線 final fallback 等特殊 Ollama 路徑也不得只打單一 host如需 /api/generate,一律透過 OllamaService.generate()
  • Code Review pipeline 也必須 Ollama-firstHermes scan 與 OpenClaw assessment 都走 OllamaService 三主機 retryGemini telemetry 只能以 code_review_openclaw_gemini 出現,表示 Ollama/可選 Claude 備援都失敗後才啟用。
  • Code Review 的 OpenClaw assessment 預設使用 qwen2.5-coder:7b 與 45s/host timeoutHermes scan 只送 compact snippet預設 3 檔、每檔 2500 字)並使用 35s/host timeout避免三主機各卡 120s 後把正常 code review 推進 Gemini 備援。
  • Code Review OpenClaw assessment 保持主機順序 GCP-A → GCP-B → 111但可使用主機適配本地模型GCP-A qwen2.5-coder:7b、GCP-B gemma3:4b、111 hermes3:latest;三段本地 Ollama 全失敗後才允許雲端備援。
  • OpenClaw Telegram Q&A 主路徑也不得綁單一 host_call_qwen3_qa() 必須透過 OllamaService 跑 GCP-A → GCP-B → 111並把實際落點寫入 ai_calls.provider
  • OpenClaw Telegram 圖片商品辨識也必須 Ollama-first_identify_product_name_with_ollama_vision() 透過 OllamaService 嘗試 GCP-A → GCP-B → 111Gemini 只允許以 openclaw_bot_image_gemini caller 作為失敗後備援。

一、四 AI Agent 路由架構

SQL漏斗(~300筆)
     ↓
[Hermes 3 8B] — 分析師 (Ollama 三主機級聯, 零成本)
  模型: hermes3:latest @ GCP-A → GCP-B → 111
  任務: 競價威脅分類 → TOP 20 HIGH/MED/LOW
     ↓
[NemoTron / qwen3] — 派發器
  主路徑: qwen3:14b @ Ollama 三主機級聯
  備援: NVIDIA NIM meta/llama-3.1-8b-instruct
  任務: Tool Calling → Telegram 告警 / DB 寫入
     ↓
[OpenClaw] — 策略師 (Ollama-firstGemini 僅備援 / 鎖定場景)
  任務: 週策略報告、洞察報告、L3 HITL 建議
     ↓
[ElephantAlpha] — 編排者 (L3 Orchestrator)
  任務: 跨 Agent orchestration、HITL、AutoHeal bridge、受控 log scan

1.1 PChome 挑品 Agent2026-05-01

services/ai_product_pick_agent.py 新增 PChome 銷售用挑品 Agent

  • 只讀真實資料表:productsprice_recordscompetitor_pricescompetitor_price_history,若 daily_sales_snapshot 可用則納入近 7 天銷售額、數量、毛利或成本推算毛利率。
  • 將 PChome 比 MOMO 有價格優勢、比對信心足夠、且有歷史快照或銷售動能的品項寫入 ai_price_recommendations。信心度不以固定倍率灌高,而是由商機分數與證據完整度共同決定,證據包含 PChome match score、歷史快照、銷售/毛利、PChome 商品 ID/名稱、抓取時間與促銷/評價/庫存標籤。每次重算只保留最新 50 品為 status='pending',未進榜舊品標為 superseded,避免統計與清單超量。
  • 寫入策略使用 strategy='product_pick',保留在既有 AI 決策表,不新增假頁面或暫存 JSON。
  • 後台入口:POST /api/ai/product-picks/generate/ai_intelligence 可手動產生清單。
  • 配對來源仍以 PChome crawler 真實搜尋結果為準;無競品資料時不生成挑品。
  • 比對覆蓋率補強入口:POST /api/ai/pchome-match/backfill,優先補抓仍無有效 PChome 配對的高價 ACTIVE 商品,完成後自動重算 AI 挑品清單。
  • 排程閉環:run_pchome_match_backfill_task 每日 10:30 執行,補抓 PChome 待比對商品、寫入歷史價格,再重算 strategy='product_pick' 清單。
  • PChome / MOMO 競價摘要出口 services/competitor_intel_repository.py 使用 30 分鐘共享快取(COMPETITOR_INTEL_CACHE_TTL_SECONDS 可調),避免 /growth_analysis/daily_sales、PPT/AI 報表每次請求重跑昂貴覆蓋率與價差趨勢查詢;run_competitor_price_feeder_task 與 PChome backfill 完成後會主動清除快取。快取只包摘要輸出,不改 matcher 的高信心門檻與 identity_v2 準確性規則。
  • 商品看板第一屏:/ 的 V2 看板直接以 productsprice_recordscompetitor_pricesai_price_recommendations 顯示比對覆蓋率、PChome 優勢、MOMO 威脅、AI 挑品與待比對優先清單;filter=ai_picks 可查看 50 品 AI 挑品列表,並在列表上方顯示平均信心、平均價差、最大價差與估算總價差空間,列表列內顯示 AI 排名與建議理由,且可透過 /api/export/excel/ai-picks 匯出 50 品 Excel 操作清單。商品看板深度快取同時寫入 data/dashboard_full_cache.pkl,供多個 Gunicorn worker 共用,避免部署後各 worker 重複重建 7,000+ 商品統計造成開頁變慢;所有資料異動與 AI 挑品重算都透過 clear_dashboard_cache() 同步清除記憶體與共享快取,手動重算 API 會立即預熱商品看板快取,避免第一位使用者承擔重建成本。
角色 模型 主機 成本 每日限額
Hermes 分析師 hermes3:latest / bge-m3 GCP-A → GCP-B → 111 Ollama 無限
NemoTron 派發器 qwen3:14bNIM fallback GCP-A → GCP-B → 111NVIDIA NIM 備援 Ollama 零NIM 配額內免費 NIM 80
OpenClaw 策略師 qwen3:14b / Gemini 鎖定場景 Ollama-firstGemini 備援 Ollama 零Gemini 需控管
ElephantAlpha 編排者 ElephantAlpha 依部署環境 受控 HITL / 任務制

一之一、AI 自動化閉環實況2026-04-29

事件 / 排程失敗 / code review finding
  → EventRouter 分流、去重、降級
  → Hermes L1 摘要或 NemoTron L2 tool calling
  → L2 SAFE_ACTIONS / AutoHeal / OpenClaw memory
  → Telegram 通知,失敗則 file queue成功後 replay
  → ai_insights + embedding_retry_queue
  → OpenClaw / ElephantAlpha 後續策略與 HITL

硬性邊界:

  • EventRouter 是告警與 L2 safe action 的入口。
  • AutoHeal 是自癒副作用入口。
  • momo-db / momo-postgres 不可被 AI 自動 restart / stop / recreate。
  • raw ai_insights insert 必須接 enqueue_insight_embedding() 或可被 backfill。
  • ElephantAlpha 只做編排與 bridge不可繞過 ADR-011 / ADR-012 / ADR-013。
  • ElephantAlpha / NemoTron 不可直接執行商品價格調整;execute_price_adjustmentadjust_price 等動作必須攔截並寫入 human_review,等待人工核准。

可觀測性:

  • /metrics 匯出 momo_ai_event_router_dispatch_total
  • /metrics 匯出 momo_ai_event_router_latency_ms_count/sum/max
  • /metrics 匯出 momo_ai_event_router_safe_action_total
  • /metrics 匯出 momo_ai_event_router_replay_total
  • /metrics 匯出 momo_ai_autoheal_action_totalmomo_ai_autoheal_duration_ms_count/sum/max
  • /metrics 在尚無事件時仍輸出 momo_ai_* zero-baseline series讓 Prometheus/Grafana 重啟後可立即看到 metric names。
  • /ai_automation_smoke 提供登入後 smoke dashboard。
  • /api/ai-automation/smoke 提供 read-only JSON 狀態,不做外部網路呼叫。
  • Smoke API 會將最近快檢結果保存到 JSONLdashboard 顯示最近狀態趨勢。
  • Smoke history 支援 JSONL 匯出、清理與每日 OK / Warning / Critical 摘要。
  • Smoke 每日摘要支援手動 Telegram 推播,並由 momo-scheduler 每日 09:10 呼叫 run_ai_smoke_daily_summary_task()
  • Grafana provisioning 新增 docker/grafana/provisioning/dashboards/json/ai-automation-overview.json,觀測 EventRouter dispatch/latency、safe action、Telegram replay 與 AutoHeal action/duration。
  • Active monitoring stack 使用 monitoring/prometheus.ymlmomo-app job scrape momo-pro-system:80/metricsPrometheus container 需加入 momo-network
  • Active Blackbox HTTP targets 必須探測 /health188 stack 目前 https://mo.wooo.work/healthhttp://momo-pro-system:80/health110 gateway stack 目前 https://mo.wooo.work/health),不可探測 Dashboard 首頁 /,避免監控流量觸發重型 DB 查詢。
  • /metricsrealtime_sales_monthly 只用 raw SELECT COUNT(*) 取得總筆數,避免 ORM schema drift 讓 Prometheus scrape 產生 warning。
  • momo-app 必須 bind mount ./gunicorn.conf.py:/app/gunicorn.conf.py:ro,讓 CD sync/rebuild 後的 Gunicorn runtime 設定與 repo 保持一致。
  • Gunicorn runtime 預設 worker_class = gthreadGUNICORN_THREADS=4preload_app = False;此組合讓 HUP 熱重載可用,也避免 Dashboard 長查詢完全阻塞 /health
  • CD rebuild 模式必須先 build image 成功,再短暫 stop/rm/recreate 三應用容器,避免 no-cache build 造成長時間 502。
  • ElephantAlpha 使用 NVIDIA NIM hosted APIproduction 預設模型為 nvidia/llama-3.3-nemotron-super-49b-v1.5ELEPHANT_ALPHA_FALLBACK_MODELS 需保留至少一個可呼叫備援403/404、408/409/425/429、5xx、timeout 與 connection error 必須嘗試下一個模型。
  • ElephantAlpha L3 HITL 只允許發送有實證、可審核、可行動的升級告警;價格類 trigger 無 Hermes 具體威脅時,只記錄 suppressed escalation telemetry 與 cooldown不寫 pending human_review,不發 Telegram 空告警。
  • ElephantAlpha 價格類 trigger 的 HITL / 決策 prefetch 必須先使用觸發 SQL 與 competitor_prices / price_records 的 DB 實證生成 SKU、MOMO / PChome 價差與建議 action lines完整 Hermes LLM prefetch 預設關閉(ELEPHANT_ALPHA_HERMES_LLM_PREFETCH_ENABLED=false),避免 5s timeout 後落入無實證摘要或雲端備援。若無 DB 實證,只記錄 suppressed telemetry / cooldown不發 Telegram 空告警。
  • resource_optimization 不再交給 LLM 生成「預期效益 / 已執行」敘事。此 trigger 必須先由程式量測 action_plans backlog、P1/P2 數、pending_review、逾時項目與 CPU load只有 CPU 達門檻、P1/P2 積壓或逾時積壓才發 Telegram「資源壓力告警」。單純 queue 大但 CPU 正常只記錄 telemetry不派發 Hermes/NemoTron、不宣稱 48 小時效益。
  • resource_optimization 會先執行 ActionPlanHygieneService 清理過期噪音:只關閉超過 72 小時的 code_review_fix / openclaw_recommendation 類 advisory action_plans以及 NemoTron direct_response/reply_simple 舊聊天回覆計畫;將狀態改為 auto_disabledrejected 並寫入 metadata_json.hygiene_history。不刪資料,也不碰 NemoTron human_review / pricing / tool action 類業務行動。
  • momo-scheduler 每 6 小時固定執行 run_action_plan_hygiene_task(),讓過期 advisory action_plans 的關閉不再依賴 resource_optimization 告警觸發;排程失敗會經 EventRouter 發送 action_plan_hygiene_failure
  • action_plans 產生端必須防重Code Review 同一檔案已有 active code_review_fix 時不重建OpenClaw recommendation 會寫入文字 fingerprint 並跳過同一建議AIOrchestrator 不再把 NemoTron direct_response/reply_simple 聊天回覆存成 action plan真正需工具、審核或執行的 NemoTron action 才能進 queue。
  • OpenClaw/Hermes embedding 優先呼叫 Ollama /api/embed,只在舊節點不支援時 fallback /api/embeddingstimeout 由 EMBEDDING_TIMEOUT / OLLAMA_EMBED_TIMEOUT 控制。
  • PPT 自動產線由 momo-scheduler 依節奏執行 run_ppt_auto_generation_task(schedule_kind):每日 20:30 產日報、週一 20:40 產週報/市場情報、每月 1 日 20:50 產月報與管理型簡報、季初 21:00 產季報、半年初 21:10 產半年報、年初 21:20 產年報,再交給 22:00 ppt_vision_audit 做視覺審核;每次嘗試會寫入 ppt_generation_runs/observability/ppt_audit_history 以精準參數檢查目標版本是否已產生,並可用 /observability/ppt_audit/generate_missing 手動補齊缺漏,總開關為 PPT_AUTO_GENERATION_ENABLED。PPT vision 需 PPT_VISION_ENABLED=true 與容器內 LibreOffice/observability/ppt_audit_file/<filename> 會把 PPTX 轉成 PDF 快取供站內線上預覽,原始 PPTX 仍保留下載。

二、真實資料庫 Schema已校對確認

2.1 productsSQLAlchemy ORMSQLite/PostgreSQL 通用)

欄位 型別 說明
id Integer PK 主鍵
i_code String(50) UNIQUE MOMO 商品代碼(爬蟲來源,即商品 SKU
name String(255) 商品名稱
url String(500) MOMO 商品頁 URL
image_url Text 商品圖片 URL
category String(100) 分類名稱(直接欄位)
status String(20) 預設 'ACTIVE'
created_at DateTime 建立時間
updated_at DateTime 更新時間
category_id Integer FK → categories.id 分類關聯(可選)

重要: i_code = MOMO 網站上的商品 ID例如 I132467614

2.2 price_records

欄位 型別 說明
id Integer PK 主鍵
product_id Integer FK → products.id 商品關聯
price Float MOMO 自家售價(爬蟲抓取)
timestamp DateTime indexed 抓取時間戳

⚠️ 架構限制: price_records 只存 MOMO 自家售價,無 source 欄位無競品PChome價格。 PChome 比價資料必須由外部爬蟲即時抓取,以 pchome_prices: dict 形式注入 HermesAnalystService.run()

2.3 daily_sales_snapshot 表(動態表,從 Excel 匯入)

重要: 此表由 import_service.py 使用 df.to_sql() 動態建立。 欄位名稱完全繼承自匯入的 MOMO Excel 報表原始欄位,加上程式碼追加的 snapshot_date

已確認的關鍵欄位(實際 MOMO 報表欄位名稱)

欄位 型別 說明 備注
snapshot_date Date 資料所屬日期(程式追加) import_service.py 從「日期」欄位解析
商品ID VARCHAR 商品識別碼= products.i_code ⚠️商品編號
商品名稱 TEXT 商品名稱
銷售金額 NUMERIC 銷售業績金額 系統以 find_col 模糊比對,優先 銷售金額
數量 NUMERIC 銷售數量
總成本 NUMERIC 成本
廠商名稱 VARCHAR 廠商名稱
商品館 / 館別 VARCHAR 分類

欄位自動偵測邏輯(find_col

系統使用 keyword 模糊比對,不要求欄位名完全固定

SKU/商品ID   = find_col(['商品ID', 'Product ID', 'ID', 'i_code', 'Item Code'])
商品名稱     = find_col(['商品名稱', '品名', 'Name', 'Product'])
銷售金額     = find_col(['銷售金額', '業績', '金額', 'Amount', 'Sales', 'Total'])
成本         = find_col(['成本', 'Cost', '進價', '總成本'])
數量         = find_col(['銷售數量', '銷量', '數量', 'Qty', 'Quantity'])
日期         = find_col(['日期', '訂單日期', '交易日期', 'Date'])
分類         = find_col(['商品館', '館別', '分類', 'Category'])

2.4 competitor_pricesMigration 004 — 已建立)

競品價格快取表,由 competitor_price_feeder.py Worker 寫入AI Pipeline LEFT JOIN 消費。

欄位 型別 說明
id SERIAL PK 主鍵
sku VARCHAR(50) MOMO 商品代碼(= products.i_code
source VARCHAR(30) 競品來源:'pchome'(預留 shopee 等)
price NUMERIC(10,2) 競品售價
original_price NUMERIC(10,2) 競品原價
discount_pct INTEGER 折扣 %NULL=未折扣)
competitor_product_id VARCHAR(100) PChome 商品 ID
competitor_product_name TEXT PChome 商品名稱(核對用)
match_score NUMERIC(4,3) 商品身份比對分數0~1< 0.76 不寫入正式快取
tags JSONB 語意標籤,如 ["on_sale","discount_20pct"]
crawled_at TIMESTAMP 爬取時間
expires_at TIMESTAMP TTL = crawled_at + 6h過期後 Hermes 忽略

UNIQUE: (sku, source) — 同一 SKU+來源只有一筆ON CONFLICT UPDATE

語意標籤字典

標籤 觸發條件
on_sale PChome is_on_sale = True
discount_10pct 折扣 10-19%
discount_20pct 折扣 20-29%
discount_30pct 折扣 ≥ 30%
low_stock 庫存 < 10
high_rating 評分 ≥ 4.5

2.5 ai_price_recommendationsMigration 003 — 已建立)

此表需執行 migrations/003_ai_price_recommendations.sql 才能完整寫入 DB

CREATE TABLE IF NOT EXISTS ai_price_recommendations (
    id          SERIAL PRIMARY KEY,
    sku         VARCHAR(50) UNIQUE NOT NULL,
    name        TEXT NOT NULL,
    reason      TEXT,
    status      VARCHAR(20) DEFAULT 'pending',  -- pending / approved / rejected
    created_at  TIMESTAMP DEFAULT NOW(),
    updated_at  TIMESTAMP DEFAULT NOW()
);

現狀: nemoton_dispatcher_service.py_exec_add_to_recommendation() 在 engine 注入且表存在時才寫入,否則只發 Telegram 通知,不會 crash。


三、SQL 漏斗設計(已修正欄位名稱)

hermes_analyst_service.pyfetch_candidates() 的核心 SQL

WITH latest_momo_price AS (
    -- 從爬蟲商品庫取最新 MOMO 售價
    SELECT
        p.i_code      AS sku,      -- MOMO 商品代碼
        p.name,
        p.category,
        pr.price      AS momo_price,
        ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY pr.timestamp DESC) AS rn
    FROM products p
    JOIN price_records pr ON pr.product_id = p.id
    WHERE p.status = 'ACTIVE'
),
recent_sales AS (
    -- 從每日業績快照計算近7天 vs 前7天銷售額
    SELECT
        "商品ID"     AS sku,      -- ⚠️ 實際欄位名為「商品ID」(非「商品編號」)
        SUM(CASE WHEN snapshot_date >= CURRENT_DATE - 7
                 THEN COALESCE("銷售金額"::numeric, 0) ELSE 0 END) AS sales_7d_curr,
        SUM(CASE WHEN snapshot_date >= CURRENT_DATE - 14
                  AND snapshot_date < CURRENT_DATE - 7
                 THEN COALESCE("銷售金額"::numeric, 0) ELSE 0 END) AS sales_7d_prev
    FROM daily_sales_snapshot
    GROUP BY "商品ID"
)
SELECT lmp.sku, lmp.name, lmp.category, lmp.momo_price,
       rs.sales_7d_curr, rs.sales_7d_prev
FROM latest_momo_price lmp
JOIN recent_sales rs ON rs.sku = lmp.sku
WHERE lmp.rn = 1
  AND rs.sales_7d_prev > 0
  AND (rs.sales_7d_curr - rs.sales_7d_prev) / rs.sales_7d_prev < -0.10
ORDER BY (rs.sales_7d_curr - rs.sales_7d_prev) / rs.sales_7d_prev ASC
LIMIT 300

漏斗效果: 226萬筆 price_records → ~300 筆近7天銷量跌幅 > 10% 的活躍商品)

JOIN 邏輯:

  • products.i_codedaily_sales_snapshot."商品ID" — 均為 MOMO 商品代碼,格式相同

四、競品價格補給線架構(已實裝)

生產者-消費者解耦設計

[competitor_price_feeder.py Worker]  ←← 每 4 小時獨立運行
  ↓ 搜尋 PChomesearch_products
  ↓ 商品身份比對marketplace_product_matcher.py
  ↓ 提取語意標籤
  ↓ UPSERT competitor_pricesTTL 6h
                ↓
[HermesAnalystService.fetch_candidates()]  ←← AI Pipeline 消費端
  ↓ LEFT JOIN competitor_prices零網路等待
  ↓ 有效期內expires_at > NOW()+ match_score ≥ 0.76 + tags 含 identity_v2 才 JOIN
  ↓ pchome_price + competitor_tags 一起傳給 Hermes

關鍵設計決策

決策 選擇 原因
解耦方式 DB 表快取(非 Redis PostgreSQL 已是核心,無需額外依賴;支援 JOIN
TTL 6 小時 與 AI Pipeline 排程週期對齊
比對算法 品牌 + 核心 token + 容量/重量/包數 + 品類 + 價格 sanity check marketplace_product_matcher.py 統一供 feeder、legacy crawler、AI/PPT 鏈路使用
最低比對門檻 0.76 核心比價寧可待審,不允許低信心錯配影響 AI 決策
已有不同 PChome 商品覆蓋門檻 0.84 新候選與既有正式配對不同時,除非超高信心,否則寫入 needs_review attempt 不覆蓋
語意標籤 JSONB 陣列 傳給 Hermes 提升情境感知品質

競品比對邏輯(competitor_price_feeder.py

MOMO 商品名稱
  → marketplace_product_matcher.build_search_terms()
  → PChomeCrawler.search_products(keyword, limit=12)
  → marketplace_product_matcher.score_marketplace_match()
    → 品牌衝突 / 容量衝突 / 包數衝突 hard veto
    → 同款高信心 score ≥ 0.76 才進 competitor_prices
    → 低信心、規格衝突、既有配對衝突寫入 competitor_match_attempts

fetch_candidates() v2 漏斗(已更新)

LEFT JOIN competitor_prices cp
       ON cp.sku = lmp.sku
      AND cp.source = 'pchome'
      AND cp.expires_at > NOW()
      AND cp.match_score >= 0.76
      AND COALESCE(cp.tags, '[]'::jsonb) ? 'identity_v2'

→ 無競品資料的商品仍回傳,pchome_price=NULL_batch_analyze 自動跳過

下游消費規範2026-05-19 更新)

  • Dashboard、AI pick、Hermes、Excel export、daily/growth 圖表與 competitor PPT 必須以 competitor_prices + competitor_price_history + competitor_match_attempts 為短期唯一生產真相源,且只消費 identity_v2 matcher 驗證過的配對;舊版僅靠 match_score 的快取不可直接進入決策或簡報。
  • pchome_matches 與 live pchome_batch() 僅保留 legacy compatibility不得作為新簡報或 AI 決策主來源。
  • services/competitor_intel_repository.py 是下游頁面、圖表、簡報的共用查詢出口;新增消費端不得各自硬寫不同 match threshold。
  • services/competitor_identity_revalidator.py 可對既有 competitor_prices legacy row 離線重跑 identity_v2:只有新版 matcher 分數 >= 0.76 且無 hard veto 才補 identity_v2 / legacy_revalidated tags預設不刷新 expires_at,避免過期價格進入決策。
  • Dashboard 必須把「待比對」拆成可診斷狀態:價格過期待刷新舊版配對待重驗低分配對待審身份否決找不到同款抓取異常尚未搜尋。不可再用單一「待比對」掩蓋資料品質原因。

執行方式

# 手動觸發一輪抓取
python3 services/competitor_price_feeder.py

# 預覽 legacy PChome 快取 identity_v2 重驗證(不寫入)
python3 -m services.competitor_identity_revalidator --limit 500

# 寫入安全通過的 identity_v2 tag不刷新過期價格
python3 -m services.competitor_identity_revalidator --limit 500 --apply

# 未來整合為 K3s CronJob每 4 小時)
# k8s/jobs/competitor-price-feeder-cronjob.yaml

五、Telegram 語意化訊息規範ChatOps 標準)

5.1 核心原則

  1. 語意化排版 (Semantic Formatting) — Emoji 作為視覺標籤0.5 秒判斷嚴重性
  2. 倒金字塔結構 — 結論先行 → 核心數據 → AI 洞察 → 建議行動 → 運算足跡
  3. 收斂行動呼籲 (Call to Action) — 每則訊息只有一個明確的 👉 建議行動
  4. 底部運算足跡 — FinOps + Observability用分隔線隔開主訊息

5.2 語意化 Emoji 字典

類別 Emoji 語意
身份識別 ⚡ NemoTron 派發器 Dispatcher 身份
身份識別 🔍 Hermes 3 8B Analyst 身份(僅出現在足跡)
風險級別 🚨 高危險,立即行動
風險級別 ⚠️ 中風險,人工覆核
風險級別 💡 低風險,策略建議
例行報告 📊 核心數據區塊標頭
業務屬性 💰 價格/毛利
業務屬性 📦 庫存/銷量
業務屬性 🏆 競品情報
AI 洞察 🧠 AI 分析結果
運算足跡 ⚙️ FinOps 底部區塊

5.3 三大類訊息模板(標準格式)

類別一:緊急告警(trigger_price_alert 觸發)

🚨 [⚡ NemoTron 派發器] 競價高危險預警

⚠️ 核心問題:[A003 舒特膚 AD 乳液] 價格大幅落後競品,訂單流失中!

📊 關鍵數據:
• 我方價格:$1,200
• 競品價格:$980 (價差 22.4%)
• 銷量變化:近七天銷量 -35.0%

🧠 AI 洞察 (信心度 85%)
價差已突破 20% 警戒線,且伴隨實質銷量下滑,高度判定為競品大力促銷攔截。

👉 建議行動:建議立即降價至 $1,000 迎戰,或發放 $200 專屬折價券

─────────────────────
⚙️ 運算足跡:
• 🔍 分析: Hermes 3 8B (GCP-A/GCP-B/111 Ollama) | 耗時: 34.2s | Tokens: 512 | $0 成本
• ⚡ 決策: NemoTron NIM | 185 Tokens | $0 (配額內 2/80)

類別二:人工覆核(flag_for_human_review 觸發)

⚠️ [⚡ NemoTron 派發器] 異常波動需人工覆核

🔍 待查商品:[A001 玻尿酸面膜10片裝]

📊 矛盾數據:
• 價格狀態:無明顯價差 (與競品齊平)
• 異常現象:過去 3 天銷量突然掛零 (平日日均 15 件)
• 庫存狀態:目前庫存充足 (500+ 件)

🧠 AI 洞察 (信心度 45%)
數據出現矛盾訊號AI 信心不足以自主決策,需人工走查確認。

👉 建議行動:請營運人員立即進行人工走查。

─────────────────────
⚙️ 運算足跡:
• 🔍 分析: Hermes 3 8B (GCP-A/GCP-B/111 Ollama) | 耗時: 34.2s | Tokens: 512 | $0 成本
• ⚡ 決策: NemoTron NIM | 185 Tokens | $0 (配額內 2/80)

類別三:策略執行通知(add_to_recommendation 觸發)

💡 [⚡ NemoTron 派發器] 潛力商品自動佈署

🏆 推薦品項:[A009 美白化妝水150ml] 已自動加入「首頁推薦區塊」

📊 決策依據:
我方價格低於市場 20%近7天銷量回升具備流量轉換潛力

🧠 AI 洞察 (信心度 82%)
具備價格競爭優勢NemoTron 主動提升曝光量以最大化業績。

👉 執行狀態:✅ 系統已自動寫入 ai_price_recommendations 推薦表

─────────────────────
⚙️ 運算足跡:
• 🔍 分析: Hermes 3 8B (GCP-A/GCP-B/111 Ollama) | 耗時: 34.2s | Tokens: 512 | $0 成本
• ⚡ 決策: NemoTron NIM | 185 Tokens | $0 (配額內 2/80)

類別四Gemini 備援 / 鎖定場景推理週報

... (前文省略) ...
─────────────────────
⚙️ 運算足跡:
• 🔍 彙整: Hermes 3 8B (GCP-A/GCP-B/111 Ollama) | 耗時: 12s | $0 成本
• 🧠 備援/鎖定場景: Gemini 2.5 Flash | 8,420 Tokens | 費用: 約 $0.003 USD

5.4 運算足跡資料來源

模型 API Response 欄位 說明
Hermes (Ollama) eval_count, total_duration 生成 tokens 數 + 推理耗時 (ns→s)
NemoTron (NIM) usage.total_tokens (OpenAI 格式) prompt + completion tokens 合計
Gemini usageMetadata.totalTokenCount 乘費率算 USD

程式碼位置: nemoton_dispatcher_service.py_build_footprint_block(hermes_stats, nim_stats)

5.5 Inline Keyboard 按鈕Level 2 互動,待實裝)

當收到類別一緊急告警時訊息底部附帶互動按鈕Telegram Bot API inline_keyboard

[ ✅ 批准降價 ]  [ ❌ 拒絕並忽略 ]  [ 🔗 查看報表 ]
  • ✅ 批准降價 → 呼叫 MOMO PRO 後台 API 改價 + 決策寫入知識庫
  • ❌ 拒絕並忽略 → 決策寫入知識庫(訓練未來在此品類保守點)
  • 🔗 查看報表 → 跳轉至 MOMO PRO 該商品數據分析頁

現狀: 尚未實裝Inline Keyboard 需搭配 Telegram Webhook + callback_query handler


六、Telegram 告警架構

告警群組

  • 群組: 小龍蝦 (業務情報專用,非 SRE 維運)
  • Chat ID: -1003940688311
  • Bot: 8610496165:AAFOlcWV4oRUSC2TI-fYux7JV97fjNzsYR8

單 Bot 多身份策略One Bot, Multiple Headers

模組 Telegram 標頭
Hermes 分析師 [Hermes 分析師]
NemoTron 派發器 [NemoTron 派發器]
Gemini 備援 [Gemini 備援](僅 Ollama 失敗或 ADR-028 鎖定場景)

三種告警類型

Tool 觸發條件 Telegram 格式
trigger_price_alert HIGH 風險 (gap>15% + 銷量跌>20%) 🔴/🟡 競價威脅告警
add_to_recommendation 我方價格低於競品且銷量正成長 推薦商品候選
flag_for_human_review 信心 < 0.6 或情況複雜 ⚠️ 需要人工審核

六、已驗證的服務參數

Hermes 分析師

參數
模型 hermes3:latest
Ollama URL GCP-A http://34.143.170.20:11434 → GCP-B http://34.21.145.224:11434 → 111 http://192.168.0.111:11434
Timeout 120s
Temperature 0.1
實測推理時間 19.3s3筆實彈 2026-04-17
TOP_N 20每次最多輸出威脅數

NemoTron 派發器

參數
模型 meta/llama-3.1-8b-instruct
NIM API URL https://integrate.api.nvidia.com/v1
Timeout 60s
每日配額上限 80留 20 給 AWOOOI
配額耗盡 fallback 直接派發 HIGH 風險告警,跳過 NIM
實測 token 消耗 1206 tokens/輪(實彈 2026-04-17

七、已知技術債與待辦

優先 項目 說明
Migration 003 + 004 competitor_prices + ai_price_recommendations 已在 188 momo_analytics 執行
188 生產容器實彈驗證 Hermes + NIM + PostgreSQL + Telegram 全通 (2026-04-17)
momo-app port 5001→5002 docker-registry 佔用 5001docker-compose.yml 改為 127.0.0.1:5002:80,已 Up healthy
momo-app 雙網路連線 同時連 momo-network + momo-pro_default(後者含 momo-db alias momo-postgres
P1 PChome Feeder CronJob competitor_price_feeder.py 每 4 小時排程 (Scheduler 整合)
P1 告警去重 TTL 同一 SKU 短期內重複告警未防範
P1 daily_sales_snapshot 欄位防禦 若 Excel 欄位名變更JOIN 條件會靜默失效
P2 Scheduler 整合 每6小時自動觸發 Hermes→NIM→Telegram 管線
P2 Gemini 備援治理 僅保留 ADR-028 鎖定場景與 Ollama 失敗備援,新增 caller 必須走 ADR

八、部署拓撲2026-04-17 確認)

實體機器對應

服務 主機 容器名 說明
PostgreSQL 192.168.0.188 momo-db pgvector/pgvector:pg14含所有 AI 相關表
momo-app 192.168.0.188 momo-pro-system Up healthyport 5002:805001 被 docker-registry 佔用,已改 5002
momo-scheduler 192.168.0.188 momo-scheduler 常駐排程容器
Ollama Primary 34.143.170.20 Ollama 原生 GCP-AAI/LLM/embedding 主路徑
Ollama Secondary 34.21.145.224 Ollama 原生 GCP-B同等備援
Ollama Fallback 192.168.0.111 Ollama 原生 最後一道本地防線
E2E 驗證容器 192.168.0.188 momo-e2e-test 臨時容器,含新服務模組

188 /home/ollama/momo-pro/.env 正確設定

TELEGRAM_BOT_TOKEN=8610496165:AAFOlcWV4oRUSC2TI-fYux7JV97fjNzsYR8  # ← 唯一正確 token
TELEGRAM_CHAT_IDS=["-1003940688311"]  # 小龍蝦群組
NVIDIA_API_KEY=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
USE_POSTGRESQL=true
POSTGRES_HOST=momo-db
# POSTGRES_DB / USER / PASSWORD 使用 docker-compose.yml 預設值

⚠️ Split-brain 陷阱188 容器環境曾存在舊 bot token 8569720657(不同 bot不在小龍蝦群組 已於 2026-04-17 深夜修正為正確 token 8610496165


九、校對歷程

日期 問題 修正
2026-04-17 fetch_candidates() SQL 使用 "商品編號" 修正為 "商品ID"(與 MOMO Excel 實際欄位名一致)
2026-04-17 Hermes gap_pct 由 LLM 計算 → 誤差大 改為 Python 預算 (momo-pchome)/pchome*100
2026-04-17 推理時間 52s 預算 gap_pct 後降至 19.3s (3筆)
2026-04-17 model_footprint DB 欄位寫入 {} 分離 footprint_textTelegram 顯示)與 footprint_dataDB JSON
2026-04-17 SQLite 語法 NOW() / datetime('now') / ::jsonb 全部改為 CURRENT_TIMESTAMP / Python 計算(跨 DB 相容)
2026-04-17 本機 SQLite 測試通過但 188 未同步任何檔案 rsync 推送 6 核心檔案 + 全站 dry-run 對帳 + migrations 跑通
2026-04-17 188 容器無 volume mountdocker cp 臨時解 重建 imageCOPY . . bake 進新代碼port 5001 衝突記錄為技術債
2026-04-17 188 .env Telegram token 不正確split-brain 修正為 8610496165188→Telegram message_id=282 確認
2026-04-17 NIM Tool Calling E2E 真實 NVIDIA_API_KEY 驗證dispatched=3, errors=[]