93 lines
4.1 KiB
Python
93 lines
4.1 KiB
Python
import io, json, sqlite3, collections, re
|
|||
|
|
|
||
|
|
con = sqlite3.connect(r"E:/ProgramData/.workbuddy/workbuddy.db"); con.row_factory = sqlite3.Row
|
||
|
|
|
||
|
|
autos = {}
|
||
|
|
for r in con.execute("select id,name,status,schedule_type,rrule,scheduled_at,cwds,created_at from automations"):
|
||
|
|
autos[r["id"]] = dict(r)
|
||
|
|
|
||
|
|
def walk(o, acc):
|
||
|
|
"""递归收集所有 usage 对象"""
|
||
|
|
if isinstance(o, dict):
|
||
|
|
u = o.get("usage")
|
||
|
|
if isinstance(u, dict) and "inputTokens" in u:
|
||
|
|
acc.append(u)
|
||
|
|
for v in o.values(): walk(v, acc)
|
||
|
|
elif isinstance(o, list):
|
||
|
|
for v in o: walk(v, acc)
|
||
|
|
|
||
|
|
rows = []
|
||
|
|
for r in con.execute("select automation_id, thread_id, runs_json, result_success, created_at from automation_runs order by created_at"):
|
||
|
|
aid = r["automation_id"]
|
||
|
|
acc = []
|
||
|
|
try: walk(json.loads(r["runs_json"] or "[]"), acc)
|
||
|
|
except Exception: pass
|
||
|
|
n_tool = len(re.findall(r'"toolName"', r["runs_json"] or ""))
|
||
|
|
rows.append({"aid": aid, "t": r["created_at"], "usages": acc, "n_tool": n_tool,
|
||
|
|
"name": (autos.get(aid) or {}).get("name", aid)})
|
||
|
|
|
||
|
|
print("=" * 96)
|
||
|
|
print("%-34s %-8s %-8s %-9s %-8s %s" % ("自动化", "运行次", "工具次", "积分总计", "缓存命中", "请求数"))
|
||
|
|
print("=" * 96)
|
||
|
|
agg = collections.defaultdict(lambda: {"runs":0,"tools":0,"cost":0.0,"hit":0,"miss":0,"req":0,"cat":collections.Counter()})
|
||
|
|
for x in rows:
|
||
|
|
a = agg[x["aid"]]; a["runs"] += 1; a["tools"] += x["n_tool"]
|
||
|
|
for u in x["usages"]:
|
||
|
|
a["req"] += 1
|
||
|
|
c = (u.get("cost") or {}).get("amount") or 0
|
||
|
|
a["cost"] += c
|
||
|
|
d = u.get("details") or {}
|
||
|
|
a["hit"] += d.get("promptCacheHitTokens", 0) or 0
|
||
|
|
a["miss"] += d.get("promptCacheMissTokens", 0) or 0
|
||
|
|
for k, v in (u.get("byCategory") or {}).items():
|
||
|
|
if isinstance(v, (int, float)): a["cat"][k] += v
|
||
|
|
|
||
|
|
tot = {"cost":0.0,"hit":0,"miss":0,"tools":0,"req":0}
|
||
|
|
for aid, a in sorted(agg.items(), key=lambda kv: -kv[1]["cost"]):
|
||
|
|
nm = (autos.get(aid) or {}).get("name", aid)[:32]
|
||
|
|
hr = a["hit"] / max(a["hit"] + a["miss"], 1) * 100
|
||
|
|
print("%-34s %-8d %-8d %-9.2f %-8s %d" % (nm, a["runs"], a["tools"], a["cost"], "%.1f%%" % hr, a["req"]))
|
||
|
|
tot["cost"] += a["cost"]; tot["hit"] += a["hit"]; tot["miss"] += a["miss"]; tot["tools"] += a["tools"]; tot["req"] += a["req"]
|
||
|
|
print("-" * 96)
|
||
|
|
print("合计:运行 %d 次 | 工具调用 %d | 模型请求 %d | 积分 %.2f | 缓存命中率 %.1f%%"
|
||
|
|
% (sum(a["runs"] for a in agg.values()), tot["tools"], tot["req"], tot["cost"],
|
||
|
|
tot["hit"] / max(tot["hit"] + tot["miss"], 1) * 100))
|
||
|
|
|
||
|
|
print()
|
||
|
|
print("== 固定注入构成(所有自动化请求的平均,token)==")
|
||
|
|
cats = collections.Counter()
|
||
|
|
for a in agg.values(): cats.update(a["cat"])
|
||
|
|
if cats:
|
||
|
|
s = sum(v for k, v in cats.items() if k != "version")
|
||
|
|
for k, v in cats.most_common():
|
||
|
|
if k == "version": continue
|
||
|
|
print(" %-14s %8.0f (%4.1f%%)" % (k, v / max(len(rows), 1), v / max(s, 1) * 100))
|
||
|
|
print(" %-14s %8.0f" % ("合计/请求", s / max(len(rows), 1)))
|
||
|
|
|
||
|
|
print()
|
||
|
|
print("== 逐次请求明细(前 20 条:inputTokens / credit / 缓存命中率 / 工具数)==")
|
||
|
|
n = 0
|
||
|
|
for x in rows:
|
||
|
|
for u in x["usages"]:
|
||
|
|
d = u.get("details") or {}
|
||
|
|
h, m = d.get("promptCacheHitTokens", 0) or 0, d.get("promptCacheMissTokens", 0) or 0
|
||
|
|
c = (u.get("cost") or {}).get("amount") or 0
|
||
|
|
print(" %-30s in=%-8s credit=%-7s hit=%4.1f%% tools=%d [%s]"
|
||
|
|
% (x["name"][:30], u.get("inputTokens"), round(c, 3),
|
||
|
|
h / max(h + m, 1) * 100, x["n_tool"],
|
||
|
|
__import__("datetime").datetime.fromtimestamp(x["t"] / 1000).strftime("%m-%d %H:%M")))
|
||
|
|
n += 1
|
||
|
|
if n >= 20: break
|
||
|
|
if n >= 20: break
|
||
|
|
|
||
|
|
print()
|
||
|
|
print("== 仍在跑的自动化(按计划类型)==")
|
||
|
|
for aid, a in autos.items():
|
||
|
|
if a["status"] != "ACTIVE": continue
|
||
|
|
if a["rrule"]:
|
||
|
|
per_day = {"HOURLY": 24}.get("HOURLY", 0)
|
||
|
|
iv = re.search(r"INTERVAL=(\d+)", a["rrule"])
|
||
|
|
k = 24 / int(iv.group(1)) if iv else "?"
|
||
|
|
print(" [周期] %-34s %s ⇒ 约 %.0f 次/天" % (a["name"][:34], a["rrule"], k))
|
||
|
|
else:
|
||
|
|
print(" [一次] %-34s %s" % (a["name"][:34], a["scheduled_at"]))
|