batch.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import argparse
  2. import subprocess
  3. import os
  4. from pathlib import Path
  5. def main():
  6. parser = argparse.ArgumentParser(description="Spawn multi-window batch runner")
  7. parser.add_argument("--start", type=int, required=True, help="Start requirement (1-based, inclusive, e.g. 31)")
  8. parser.add_argument("--end", type=int, required=True, help="End requirement (1-based, inclusive, e.g. 50)")
  9. parser.add_argument("--workers", type=int, default=7, help="Number of physical CMD windows to spawn")
  10. parser.add_argument("--skip-research", action="store_true", help="Skip Phase 1 and use existing raw cases")
  11. parser.add_argument("--research-only", action="store_true", help="Only run research phases, skip Phase 2 and 3")
  12. parser.add_argument("--use-claude-sdk", action="store_true", help="Use pure Anthropic SDK for Phase 2/3")
  13. parser.add_argument("--platforms", type=str, default="", help="Comma-separated list of platforms to search")
  14. args = parser.parse_args()
  15. start_idx = args.start - 1
  16. end_idx = args.end - 1
  17. total_tasks = end_idx - start_idx + 1
  18. if total_tasks <= 0:
  19. print("Invalid range")
  20. return
  21. # Assign indices to workers using round-robin
  22. worker_tasks = {i: [] for i in range(args.workers)}
  23. for i, req_idx in enumerate(range(start_idx, end_idx + 1)):
  24. worker_id = i % args.workers
  25. worker_tasks[worker_id].append(req_idx)
  26. base_dir = Path(__file__).parent
  27. print(f"Spawning {args.workers} actual CMD windows to process {total_tasks} requirements...")
  28. for worker_id, indices in worker_tasks.items():
  29. if not indices:
  30. continue
  31. # Create a temporary batch file for this worker window
  32. bat_path = base_dir / f"worker_{worker_id}.bat"
  33. with open(bat_path, "w", encoding="utf-8") as f:
  34. f.write("@echo off\n")
  35. f.write("cd /d %~dp0\n")
  36. f.write("if exist ..\\..\\.venv\\Scripts\\activate.bat call ..\\..\\.venv\\Scripts\\activate.bat\n")
  37. f.write("echo Worker Group %d starting...\n" % worker_id)
  38. for idx in indices:
  39. f.write(f"echo =======================================\n")
  40. f.write(f"echo Running Requirement Index: {idx}\n")
  41. f.write(f"echo =======================================\n")
  42. cmd = f"python run_pipeline.py --index {idx}"
  43. if args.skip_research:
  44. cmd += " --skip-research"
  45. if args.research_only:
  46. cmd += " --research-only"
  47. if args.use_claude_sdk:
  48. cmd += " --use-claude-sdk"
  49. if args.platforms:
  50. cmd += f" --platforms {args.platforms}"
  51. # 第 1 遍执行
  52. f.write(f"echo [Attempt 1] {cmd}\n")
  53. f.write(f"{cmd}\n")
  54. # 第 2 遍执行(检查重试)
  55. if not args.research_only:
  56. target_file = f"output\\{(idx+1):03d}\\strategy.json"
  57. f.write(f"if not exist \"{target_file}\" (\n")
  58. f.write(f" echo =======================================\n")
  59. f.write(f" echo [Retry] target.json missing, retrying once...\n")
  60. f.write(f" echo =======================================\n")
  61. f.write(f" {cmd}\n")
  62. f.write(f") else (\n")
  63. f.write(f" echo [Verified] {target_file} generated successfully.\n")
  64. f.write(f")\n")
  65. else:
  66. # 如果是 resaerch-only 则较难在 batch 中校验几个文件,默认让它安全重试一遍
  67. f.write(f"echo [Retry For Research] Automatically trying once more to ensure completeness...\n")
  68. f.write(f"{cmd}\n")
  69. f.write("timeout /t 2 > NUL\n")
  70. f.write("echo Worker Group %d finished!\n" % worker_id)
  71. f.write("pause\n")
  72. # Open a new CMD window executing this batch file
  73. subprocess.Popen(
  74. ["cmd.exe", "/c", "start", f"Worker_{worker_id}", "cmd.exe", "/c", str(bat_path.absolute())],
  75. cwd=str(base_dir)
  76. )
  77. print(f"Launched window for Worker {worker_id} -> Indices: {indices}")
  78. if __name__ == "__main__":
  79. main()