#!/usr/bin/env python3 """ OmniRoute 周度评估报告 — 汇总观测数据,输出评估结论 每周日由 cron 触发,输出可读报告(非静默,始终输出) 评估维度:可用性 / 延迟 / 成本 / 路由一致性 / cron 运行状态 """ import json import os import statistics from datetime import datetime, timezone, timedelta STATE_DIR = os.path.expanduser("~/.hermes/omniroute-observe") LOG = os.path.join(STATE_DIR, "observations.jsonl") # 评估阈值 LATENCY_WARN_MS = 15000 # 平均延迟超 15s 警告 SUCCESS_RATE_MIN = 0.90 # 成功率低于 90% 警告 def load_observations(days=7): if not os.path.exists(LOG): return [] cutoff = datetime.now(timezone.utc) - timedelta(days=days) obs = [] with open(LOG) as f: for line in f: try: d = json.loads(line) ts = datetime.fromisoformat(d["ts"]) if ts >= cutoff: obs.append(d) except Exception: continue return obs def main(): obs = load_observations(7) n = len(obs) # 汇总 total_tests = sum(o["total_tests"] for o in obs) total_ok = sum(o["success_count"] for o in obs) success_rate = total_ok / total_tests if total_tests else 1.0 latencies = [] routed_models = {} total_cost = 0.0 service_ok = 0 for o in obs: if o["service"] == "active": service_ok += 1 for t in o["tests"]: latencies.append(t["latency_ms"]) routed_models[t["routed_to"]] = routed_models.get(t["routed_to"], 0) + 1 try: total_cost += float(t["cost"]) except Exception: pass avg_lat = statistics.mean(latencies) if latencies else 0 p95_lat = sorted(latencies)[int(len(latencies) * 0.95) - 1] if latencies else 0 # cron 状态 cron_ok = 0 cron_total = 0 for o in obs: for name, st in (o.get("cron_status") or {}).items(): cron_total += 1 if st.get("has_output"): cron_ok += 1 print(f"# 📊 OmniRoute 周度评估报告({datetime.now().strftime('%Y-%m-%d')})") print(f"\n## 观测样本:{n} 次采集(7 天内)") print(f"- 服务可用性: {service_ok}/{n} 次 active({service_ok/n*100:.0f}%)" if n else "- 无数据") print(f"- API 测试: {total_ok}/{total_tests} 成功(成功率 {success_rate*100:.1f}%)") print(f"- 平均延迟: {avg_lat:.0f}ms | P95: {p95_lat:.0f}ms") print(f"- 累计成本: ${total_cost:.6f}") print(f"- 路由模型分布: {json.dumps(routed_models, ensure_ascii=False)}") print(f"- 已切换 cron 运行: {cron_ok}/{cron_total} 次有输出") # 结论 print("\n## 评估结论") issues = [] if service_ok < n: issues.append(f"⚠️ 服务可用性 {service_ok}/{n},有宕机记录") if success_rate < SUCCESS_RATE_MIN: issues.append(f"⚠️ 成功率 {success_rate*100:.1f}% < 阈值 {SUCCESS_RATE_MIN*100:.0f}%") if avg_lat > LATENCY_WARN_MS: issues.append(f"⚠️ 平均延迟 {avg_lat:.0f}ms > 阈值 {LATENCY_WARN_MS}ms") if not issues: print("✅ **OmniRoute 运行稳定,可以继续扩大切换范围**") print("- 建议:可再将 skill-curator-weekly / 牵挂提醒 / 股票矛盾分析周报切到 omniroute-local") else: print("❌ **存在问题,建议暂停扩大切换**") for i in issues: print(f"- {i}") print("- 建议:回滚异常任务到 newapi-local,检查 omniroute.service 日志") if __name__ == "__main__": main()