|
8 | 8 | import asyncio |
9 | 9 | import tiktoken |
10 | 10 | import wandb |
| 11 | +import argparse |
| 12 | +import json |
| 13 | +from pathlib import Path |
11 | 14 | from aiopslab.orchestrator import Orchestrator |
12 | 15 | from aiopslab.orchestrator.problems.registry import ProblemRegistry |
13 | 16 | from clients.utils.llm import OpenRouterClient |
@@ -107,33 +110,112 @@ def _filter_dict(self, dictionary, filter_func): |
107 | 110 | return {k: v for k, v in dictionary.items() if filter_func(k, v)} |
108 | 111 |
|
109 | 112 |
|
| 113 | +def get_completed_problems(results_dir: Path, agent_name: str, model: str) -> set: |
| 114 | + """Get set of completed problem IDs from existing result files.""" |
| 115 | + completed = set() |
| 116 | + |
| 117 | + # Look in organized directory structure first |
| 118 | + organized_dir = results_dir / agent_name / model.replace("/", "_") |
| 119 | + if organized_dir.exists(): |
| 120 | + for result_file in organized_dir.glob("*.json"): |
| 121 | + try: |
| 122 | + with open(result_file, 'r') as f: |
| 123 | + data = json.load(f) |
| 124 | + if 'problem_id' in data: |
| 125 | + completed.add(data['problem_id']) |
| 126 | + except (json.JSONDecodeError, IOError): |
| 127 | + continue |
| 128 | + |
| 129 | + # Also check legacy flat structure |
| 130 | + for result_file in results_dir.glob("*.json"): |
| 131 | + try: |
| 132 | + with open(result_file, 'r') as f: |
| 133 | + data = json.load(f) |
| 134 | + if ('problem_id' in data and |
| 135 | + data.get('agent') == agent_name and |
| 136 | + model.split('/')[-1] in str(result_file)): |
| 137 | + completed.add(data['problem_id']) |
| 138 | + except (json.JSONDecodeError, IOError): |
| 139 | + continue |
| 140 | + |
| 141 | + return completed |
| 142 | + |
| 143 | +def setup_results_directory(model: str, agent_name: str = "openrouter") -> Path: |
| 144 | + """Setup organized results directory structure.""" |
| 145 | + results_base = Path("aiopslab/data/results") |
| 146 | + |
| 147 | + # Create organized structure: results/{agent}/{model_safe}/ |
| 148 | + model_safe = model.replace("/", "_") |
| 149 | + results_dir = results_base / agent_name / model_safe |
| 150 | + results_dir.mkdir(parents=True, exist_ok=True) |
| 151 | + |
| 152 | + return results_dir |
| 153 | + |
110 | 154 | if __name__ == "__main__": |
| 155 | + parser = argparse.ArgumentParser(description='Run OpenRouter agent on AIOpsLab problems') |
| 156 | + parser.add_argument('--skip-completed', action='store_true', |
| 157 | + help='Skip problems that have already been completed') |
| 158 | + parser.add_argument('--problem-ids', nargs='+', |
| 159 | + help='Run only specific problem IDs') |
| 160 | + parser.add_argument('--max-steps', type=int, default=30, |
| 161 | + help='Maximum steps per problem (default: 30)') |
| 162 | + parser.add_argument('--model', type=str, |
| 163 | + default=os.getenv("OPENROUTER_MODEL", "openai/gpt-4o-mini"), |
| 164 | + help='OpenRouter model to use') |
| 165 | + |
| 166 | + args = parser.parse_args() |
| 167 | + |
111 | 168 | # Load use_wandb from environment variable with a default of False |
112 | 169 | use_wandb = os.getenv("USE_WANDB", "false").lower() == "true" |
113 | 170 |
|
114 | 171 | if use_wandb: |
115 | 172 | # Initialize wandb running |
116 | 173 | wandb.init(project="AIOpsLab", entity="AIOpsLab") |
117 | 174 |
|
118 | | - # You can specify different models supported by OpenRouter |
119 | | - # Popular models: |
120 | | - # - "anthropic/claude-3.5-sonnet" |
121 | | - # - "openai/gpt-4-turbo" |
122 | | - # - "meta-llama/llama-3.1-8b-instruct" |
123 | | - # - "google/gemini-pro" |
124 | | - # - "mistralai/mixtral-8x7b-instruct" |
125 | | - model = os.getenv("OPENROUTER_MODEL", "openai/gpt-4o-mini") |
| 175 | + model = args.model |
| 176 | + agent_name = "openrouter" |
126 | 177 |
|
| 178 | + # Setup organized results directory |
| 179 | + results_dir = setup_results_directory(model, agent_name) |
| 180 | + print(f"Results will be saved to: {results_dir}") |
| 181 | + |
| 182 | + # Get all problems |
127 | 183 | problems = ProblemRegistry().PROBLEM_REGISTRY |
| 184 | + |
| 185 | + # Filter problems if specific IDs requested |
| 186 | + if args.problem_ids: |
| 187 | + problems = {pid: problems[pid] for pid in args.problem_ids if pid in problems} |
| 188 | + if not problems: |
| 189 | + print("No valid problem IDs found") |
| 190 | + exit(1) |
| 191 | + |
| 192 | + # Skip completed problems if requested |
| 193 | + if args.skip_completed: |
| 194 | + completed_problems = get_completed_problems( |
| 195 | + Path("aiopslab/data/results"), agent_name, model |
| 196 | + ) |
| 197 | + problems = {pid: prob for pid, prob in problems.items() |
| 198 | + if pid not in completed_problems} |
| 199 | + |
| 200 | + print(f"Found {len(completed_problems)} completed problems") |
| 201 | + print(f"Running {len(problems)} remaining problems") |
| 202 | + |
| 203 | + if not problems: |
| 204 | + print("All problems have been completed!") |
| 205 | + exit(0) |
| 206 | + |
| 207 | + print(f"Running {len(problems)} problems with model: {model}") |
| 208 | + |
128 | 209 | for pid in problems: |
| 210 | + print(f"\n=== Starting problem: {pid} ===") |
129 | 211 | agent = OpenRouterAgent(model=model) |
130 | 212 |
|
131 | | - orchestrator = Orchestrator() |
132 | | - orchestrator.register_agent(agent, name="openrouter") |
| 213 | + orchestrator = Orchestrator(results_dir=results_dir) |
| 214 | + orchestrator.register_agent(agent, name=agent_name) |
133 | 215 |
|
134 | 216 | problem_desc, instructs, apis = orchestrator.init_problem(pid) |
135 | 217 | agent.init_context(problem_desc, instructs, apis) |
136 | | - asyncio.run(orchestrator.start_problem(max_steps=30)) |
| 218 | + asyncio.run(orchestrator.start_problem(max_steps=args.max_steps)) |
137 | 219 |
|
138 | 220 | if use_wandb: |
139 | 221 | # Finish the wandb run |
|
0 commit comments