Phase 1 A4 — 13 個呼叫點接 ai_call_logger(覆蓋率 11.8% → 預估 50%+)
- TOP-1 nemoton_dispatcher: nemotron_dispatch caller (NIM 配額追蹤)
- TOP-2 openclaw_strategist: 4 reports (daily/weekly/monthly/meta) + qa caller
- TOP-3 hermes_analyst: hermes_analyst + hermes_intent (順修 commit 00591c5 殘留 bug)
- TOP-4 code_review_pipeline: code_review_hermes/openclaw/elephant 三鏈 (request_id 串)
- TOP-5 openclaw_bot_routes: openclaw_bot_main/gemini/nim 三層 fallback
Phase 3 A7 — OpenClaw Q&A → qwen3:14b(feature flag OFF)
- OPENCLAW_QA_OLLAMA_FIRST 灰度開關
- 繁中強制 system prompt + Gemini fallback chain
- _is_low_quality_response 品質守門(簡體字檢測 + 拒答訊號 + 結構分數)
- 黃金集 A/B 對照測試框架(10 樣本去 PII)
Phase 3 A8 — OpenClaw 日報 → Hermes 模板(feature flag OFF)
- OPENCLAW_DAILY_HERMES_TEMPLATE 灰度開關
- _compute_daily_kpi 純 SQL + Hermes 規則引擎
- _compute_gemini_insight 精簡 200 字洞察 prompt
- templates/daily_report_v2.j2 + _SafeUndefined 缺欄位優雅降級
- scripts/compare_daily_report_versions.py 雙版本盲測
Phase 3 A9 — Nemotron NIM → qwen3:14b(feature flag OFF)
- NEMOTRON_OLLAMA_FIRST 灰度開關(A2 紅燈:deepseek-r1 假支援,改 qwen3)
- _call_qwen3_dispatch + 既有 NIM tool_calls 解析共用
- 保留 ADR-004「🟡 [降級模式]」Hermes 規則引擎兜底
H6 PII fix — chat_id 進 ai_calls.meta 改 SHA1[:8](4 處 Bot Q&A)
Code Review pipeline — N3 動態 provider tag(gcp/secondary/111)+ A4 logger 三鏈
37 unit tests 全綠(routing 15 + golden 5 + qwen3 8 + daily template 8 + nemotron 1)
Operation Ollama-First v5.0 / Phase 1 A4 + Phase 3 A7+A8+A9
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
102 lines
3.6 KiB
Python
102 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
scripts/compare_daily_report_versions.py
|
||
─────────────────────────────────────────────────────────────────
|
||
Operation Ollama-First v5.0 / Phase 3 / A8 — 日報雙版本盲測腳本
|
||
|
||
用途:
|
||
跑同一天的「舊版 Gemini 全文」vs「新版 Hermes 模板」
|
||
輸出兩份檔案到 reports/,供統帥盲測選擇預設模式。
|
||
|
||
使用:
|
||
python3 scripts/compare_daily_report_versions.py --date 2026-05-03
|
||
python3 scripts/compare_daily_report_versions.py # 預設昨日
|
||
|
||
紀律:
|
||
- 不寫入 ai_insights(避免污染 production 資料)
|
||
- 不發 Telegram(純 dry-run)
|
||
- 兩版本皆獨立執行,互不干擾
|
||
- 失敗時報錯但不刪舊檔
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
import argparse
|
||
from datetime import date, timedelta, datetime
|
||
from pathlib import Path
|
||
|
||
# 確保可 import 本專案 services
|
||
ROOT = Path(__file__).resolve().parent.parent
|
||
sys.path.insert(0, str(ROOT))
|
||
|
||
|
||
def _ensure_reports_dir() -> Path:
|
||
reports_dir = ROOT / 'reports'
|
||
reports_dir.mkdir(exist_ok=True)
|
||
return reports_dir
|
||
|
||
|
||
def _run_legacy(target_date: date) -> str:
|
||
"""跑舊版(_legacy_full_gemini_daily_report)"""
|
||
os.environ['OPENCLAW_DAILY_HERMES_TEMPLATE'] = 'false'
|
||
# 強制 reload module(避免 cache)
|
||
import importlib
|
||
import services.openclaw_strategist_service as svc
|
||
importlib.reload(svc)
|
||
print(f"[legacy] 開始跑 Gemini 全文版日報 target_date={target_date}")
|
||
result = svc._legacy_full_gemini_daily_report()
|
||
return result.get('content', '') or result.get('report_content', '') or str(result)
|
||
|
||
|
||
def _run_hermes_template(target_date: date) -> str:
|
||
"""跑新版(_generate_daily_report_hermes_template)"""
|
||
os.environ['OPENCLAW_DAILY_HERMES_TEMPLATE'] = 'true'
|
||
import importlib
|
||
import services.openclaw_strategist_service as svc
|
||
importlib.reload(svc)
|
||
print(f"[hermes] 開始跑 Hermes 模板版日報 target_date={target_date}")
|
||
result = svc._generate_daily_report_hermes_template()
|
||
return result.get('content', '') or result.get('report_content', '') or str(result)
|
||
|
||
|
||
def main():
|
||
parser = argparse.ArgumentParser(description='OpenClaw 日報雙版本盲測')
|
||
parser.add_argument('--date', help='YYYY-MM-DD(預設昨日)')
|
||
args = parser.parse_args()
|
||
|
||
if args.date:
|
||
target_date = datetime.strptime(args.date, '%Y-%m-%d').date()
|
||
else:
|
||
target_date = date.today() - timedelta(days=1)
|
||
|
||
reports_dir = _ensure_reports_dir()
|
||
date_tag = target_date.strftime('%Y%m%d')
|
||
|
||
legacy_file = reports_dir / f'daily_report_legacy_{date_tag}.md'
|
||
hermes_file = reports_dir / f'daily_report_v2_{date_tag}.md'
|
||
|
||
# 跑舊版
|
||
try:
|
||
legacy_content = _run_legacy(target_date)
|
||
legacy_file.write_text(legacy_content, encoding='utf-8')
|
||
print(f"✅ legacy 版輸出:{legacy_file}")
|
||
except Exception as e:
|
||
print(f"❌ legacy 版失敗:{e}", file=sys.stderr)
|
||
|
||
# 跑新版
|
||
try:
|
||
hermes_content = _run_hermes_template(target_date)
|
||
hermes_file.write_text(hermes_content, encoding='utf-8')
|
||
print(f"✅ hermes 模板版輸出:{hermes_file}")
|
||
except Exception as e:
|
||
print(f"❌ hermes 版失敗:{e}", file=sys.stderr)
|
||
|
||
print(f"\n盲測檢查(建議):")
|
||
print(f" diff <(head -50 {legacy_file}) <(head -50 {hermes_file})")
|
||
print(f" wc -w {legacy_file} {hermes_file}")
|
||
print(f" # 統帥盲測時可遮 caller 名稱避免偏見")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|