()
| 359 | |
| 360 | |
| 361 | def main(): |
| 362 | parser = argparse.ArgumentParser(description="Token 花销统计工具") |
| 363 | parser.add_argument("--start-date", type=str, default=None, help="开始日期 YYYYMMDD") |
| 364 | parser.add_argument("--end-date", type=str, default=None, help="结束日期 YYYYMMDD") |
| 365 | parser.add_argument("--group-by", type=str, default="date", choices=["date", "task_type", "model", "user_id"]) |
| 366 | parser.add_argument("--mode", type=str, default="stats", choices=["stats", "benchmark", "compare"]) |
| 367 | parser.add_argument("--llm-model", type=str, default="qwen3.5-plus", help="LLM 模型名称") |
| 368 | parser.add_argument("--days", type=int, default=1, help="基准测试天数") |
| 369 | args = parser.parse_args() |
| 370 | |
| 371 | # 连接数据库获取论文和用户数据 |
| 372 | conn = sqlite3.connect(DB_PATH) |
| 373 | papers = conn.execute("SELECT title, abstract FROM papers").fetchall() |
| 374 | papers = [{"title": p[0], "abstract": p[1] or ""} for p in papers] |
| 375 | |
| 376 | profiles = conn.execute("SELECT user_id, profile_json FROM profiles").fetchall() |
| 377 | user_profiles = [{"user_id": p[0], **json.loads(p[1])} for p in profiles] |
| 378 | conn.close() |
| 379 | |
| 380 | print(f"Loaded {len(papers)} papers, {len(user_profiles)} users") |
| 381 | |
| 382 | if args.mode == "stats" and args.start_date and args.end_date: |
| 383 | # 统计已有日志 |
| 384 | stats = get_usage_stats(args.start_date, args.end_date, args.group_by) |
| 385 | print(f"\n=== Token Usage Stats ({args.start_date} to {args.end_date}) ===\n") |
| 386 | |
| 387 | for key, s in sorted(stats.items()): |
| 388 | print(f"[{key}]") |
| 389 | print(f" Embedding: {s['embedding_input']:,} tokens") |
| 390 | print(f" LLM: {s['llm_input'] + s['llm_output']:,} tokens") |
| 391 | print(f" Cost: ${s['cost']:.4f}") |
| 392 | print(f" Calls: {s['calls']}") |
| 393 | print() |
| 394 | |
| 395 | elif args.mode == "benchmark": |
| 396 | # 基准测试指定天数 |
| 397 | today = datetime.now() |
| 398 | for i in range(args.days): |
| 399 | test_date = (today - timedelta(days=i)).strftime("%Y-%m-%d") |
| 400 | print(f"\n{'='*60}") |
| 401 | print(f"Benchmarking {test_date} with {args.llm_model}...") |
| 402 | print(f"{'='*60}\n") |
| 403 | |
| 404 | result = benchmark_one_day(test_date, args.llm_model, papers, user_profiles) |
| 405 | |
| 406 | print(f"Date: {result['date']}") |
| 407 | print(f"LLM Model: {result['llm_model']}") |
| 408 | print(f"Embedding Model: {result['embedding_model']}") |
| 409 | print(f"\nBreakdown:") |
| 410 | for task, data in result["breakdown"].items(): |
| 411 | print(f" {task}:") |
| 412 | print(f" Count: {data.get('papers', data.get('users', data.get('reports', 0)))}") |
| 413 | print(f" Tokens: {data['total_tokens']:,} ({data['tokens_per_paper'] if 'tokens_per_paper' in data else data['tokens_per_user'] if 'tokens_per_user' in data else data['tokens_per_report']}/item)") |
| 414 | print(f"\nTotal:") |
| 415 | print(f" Embedding Tokens: {result['total']['embedding_tokens']:,}") |
| 416 | print(f" LLM Tokens: {result['total']['llm_tokens']:,}") |
| 417 | print(f" Total Tokens: {result['total']['total_tokens']:,}") |
| 418 | print(f" Estimated Cost: ${result['total']['estimated_cost_usd']:.4f}") |
no test coverage detected