Skip to content

Commit 75286fa

Browse files
committed
feat: parallelize runs over multiple ports
2 parents de5222d + 6b4a515 commit 75286fa

4 files changed

Lines changed: 319 additions & 218 deletions

File tree

CLAUDE.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,31 @@ litellm --config config/litellm.yaml
2626
### Running the Application
2727

2828
```
29-
usage: balatrollm [-h] [--model MODEL] [--list-models] [--strategy STRATEGY] [--base-url BASE_URL] [--api-key API_KEY] [--config CONFIG] [--runs-dir RUNS_DIR] [--runs RUNS] {benchmark} ...
29+
usage: balatrollm [-h] [-m MODEL] [-l] [-s STRATEGY] [-u BASE_URL] [-k API_KEY] [-c CONFIG]
30+
[-d RUNS_DIR] [-r RUNS] [-p PORT]
31+
{benchmark} ...
3032
3133
LLM-powered Balatro bot using LiteLLM proxy
3234
3335
positional arguments:
34-
{benchmark} Available commands
35-
benchmark Analyze runs and generate leaderboards
36+
{benchmark} Available commands
37+
benchmark Analyze runs and generate leaderboards
3638
3739
options:
38-
-h, --help show this help message and exit
39-
--model MODEL Model name to use from LiteLLM proxy (default: openai/gpt-oss-20b)
40-
--list-models List available models from the proxy and exit
41-
--strategy STRATEGY Name of the strategy to use (default: default)
42-
--base-url BASE_URL LiteLLM base URL (default: http://localhost:4000)
43-
--api-key API_KEY LiteLLM proxy API key (default: sk-balatrollm-proxy-key)
44-
--config CONFIG Load configuration from a previous run's config.json file
45-
--runs-dir RUNS_DIR Base directory for storing run data (default: current directory)
46-
--runs RUNS Number of times to run the bot with the same configuration (default: 1)
40+
-h, --help show this help message and exit
41+
-m, --model MODEL Model name to use from LiteLLM proxy (default: openai/gpt-oss-20b)
42+
-l, --list-models List available models from the proxy and exit
43+
-s, --strategy STRATEGY
44+
Name of the strategy to use (default: default)
45+
-u, --base-url BASE_URL
46+
LiteLLM base URL (default: http://localhost:4000)
47+
-k, --api-key API_KEY
48+
LiteLLM proxy API key (default: sk-balatrollm-proxy-key)
49+
-c, --config CONFIG Load configuration from a previous run's config.json file
50+
-d, --runs-dir RUNS_DIR
51+
Base directory for storing run data (default: current directory)
52+
-r, --runs RUNS Number of times to run the bot with the same configuration (default: 1)
53+
-p, --port PORT Port for BalatroBot client connection (can specify multiple, default: 12346)
4754
```
4855

4956
### Development

README.md

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -90,26 +90,31 @@ balatrollm --help
9090
```
9191

9292
```
93-
usage: balatrollm [-h] [--model MODEL] [--list-models] [--strategy STRATEGY] [--base-url BASE_URL]
94-
[--api-key API_KEY] [--config CONFIG] [--runs-dir RUNS_DIR] [--runs RUNS]
93+
usage: balatrollm [-h] [-m MODEL] [-l] [-s STRATEGY] [-u BASE_URL] [-k API_KEY] [-c CONFIG]
94+
[-d RUNS_DIR] [-r RUNS] [-p PORT]
9595
{benchmark} ...
9696
9797
LLM-powered Balatro bot using LiteLLM proxy
9898
9999
positional arguments:
100-
{benchmark} Available commands
101-
benchmark Analyze runs and generate leaderboards
100+
{benchmark} Available commands
101+
benchmark Analyze runs and generate leaderboards
102102
103103
options:
104-
-h, --help show this help message and exit
105-
--model MODEL Model name to use from LiteLLM proxy (default: openai/gpt-oss-20b)
106-
--list-models List available models from the proxy and exit
107-
--strategy STRATEGY Name of the strategy to use (default: default)
108-
--base-url BASE_URL LiteLLM base URL (default: http://localhost:4000)
109-
--api-key API_KEY LiteLLM proxy API key (default: sk-balatrollm-proxy-key)
110-
--config CONFIG Load configuration from a previous run's config.json file
111-
--runs-dir RUNS_DIR Base directory for storing run data (default: current directory)
112-
--runs RUNS Number of times to run the bot with the same configuration (default: 1)
104+
-h, --help show this help message and exit
105+
-m, --model MODEL Model name to use from LiteLLM proxy (default: openai/gpt-oss-20b)
106+
-l, --list-models List available models from the proxy and exit
107+
-s, --strategy STRATEGY
108+
Name of the strategy to use (default: default)
109+
-u, --base-url BASE_URL
110+
LiteLLM base URL (default: http://localhost:4000)
111+
-k, --api-key API_KEY
112+
LiteLLM proxy API key (default: sk-balatrollm-proxy-key)
113+
-c, --config CONFIG Load configuration from a previous run's config.json file
114+
-d, --runs-dir RUNS_DIR
115+
Base directory for storing run data (default: current directory)
116+
-r, --runs RUNS Number of times to run the bot with the same configuration (default: 1)
117+
-p, --port PORT Port for BalatroBot client connection (can specify multiple, default: 12346)
113118
```
114119

115120
#### `Makefile` - Development Workflow

src/balatrollm/__init__.py

Lines changed: 2 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -2,197 +2,6 @@
22

33
__version__ = "0.6.0"
44

5-
import argparse
6-
import asyncio
7-
import sys
8-
from pathlib import Path
5+
from .cli import main
96

10-
from .benchmark import run_benchmark_analysis
11-
from .bot import LLMBot, setup_logging
12-
from .config import Config
13-
14-
15-
def main() -> None:
16-
"""Main CLI entry point for balatrollm.
17-
18-
Parses command line arguments and executes the appropriate command.
19-
Supports both the main balatrollm command and benchmark subcommand.
20-
"""
21-
parser = _create_argument_parser()
22-
args = parser.parse_args()
23-
24-
setup_logging()
25-
26-
match args.command:
27-
case "benchmark":
28-
cmd_benchmark(args)
29-
case None:
30-
asyncio.run(cmd_balatrollm(args))
31-
case _:
32-
print(f"Unknown command: {args.command}")
33-
sys.exit(1)
34-
35-
36-
async def cmd_balatrollm(args) -> None:
37-
"""Run the balatrollm command.
38-
39-
Creates a bot configuration and runs the main game loop.
40-
41-
Args:
42-
args: Parsed command line arguments containing model, strategy,
43-
base_url, api_key, config file path, runs count, and other options.
44-
"""
45-
# Validate runs argument
46-
if args.runs < 1:
47-
print("Error: --runs must be at least 1")
48-
sys.exit(1)
49-
50-
if args.config:
51-
config = Config.from_config_file(args.config)
52-
else:
53-
config = Config(
54-
model=args.model,
55-
strategy=args.strategy,
56-
)
57-
58-
bot = LLMBot(config, base_url=args.base_url, api_key=args.api_key, port=args.port)
59-
60-
if args.list_models:
61-
models = await bot.list_available_models()
62-
for model in models:
63-
print(model)
64-
return
65-
66-
# Run the bot multiple times
67-
for run_number in range(1, args.runs + 1):
68-
if args.runs > 1:
69-
print(f"\n=== Run {run_number}/{args.runs} ===")
70-
71-
try:
72-
with bot:
73-
await bot.play_game(runs_dir=args.runs_dir)
74-
except KeyboardInterrupt:
75-
print(f"\nInterrupted after {run_number - 1} completed runs")
76-
break
77-
except Exception as e:
78-
print(f"Run {run_number} failed: {e}")
79-
if args.runs > 1:
80-
print("Continuing to next run...")
81-
else:
82-
raise
83-
84-
# Sleep between runs to prevent errors
85-
if run_number < args.runs:
86-
print("Waiting 3 seconds before next run...")
87-
await asyncio.sleep(3)
88-
89-
90-
def cmd_benchmark(args) -> None:
91-
"""Run the benchmark command.
92-
93-
Analyzes run data and generates comprehensive leaderboards.
94-
95-
Args:
96-
args: Parsed command line arguments containing runs_dir and output_dir.
97-
98-
Raises:
99-
FileNotFoundError: If the runs directory doesn't exist.
100-
Exception: If benchmark analysis fails for any other reason.
101-
"""
102-
try:
103-
run_benchmark_analysis(args.runs_dir, args.output_dir)
104-
except FileNotFoundError as e:
105-
print(f"Error: {e}")
106-
sys.exit(1)
107-
except Exception as e:
108-
print(f"Benchmark analysis failed: {e}")
109-
sys.exit(1)
110-
111-
112-
def _create_argument_parser() -> argparse.ArgumentParser:
113-
"""Create and configure argument parser.
114-
115-
Sets up command line argument parsing for both the main balatrollm
116-
command and the benchmark subcommand.
117-
118-
Returns:
119-
Configured ArgumentParser instance with all commands and options.
120-
"""
121-
parser = argparse.ArgumentParser(
122-
description="LLM-powered Balatro bot using LiteLLM proxy",
123-
formatter_class=argparse.RawDescriptionHelpFormatter,
124-
)
125-
126-
# Add subcommands
127-
subparsers = parser.add_subparsers(dest="command", help="Available commands")
128-
129-
# Default command (play game) - no subcommand needed, just use main parser
130-
parser.add_argument(
131-
"--model",
132-
default="openai/gpt-oss-20b",
133-
help="Model name to use from LiteLLM proxy (default: openai/gpt-oss-20b)",
134-
)
135-
parser.add_argument(
136-
"--list-models",
137-
action="store_true",
138-
help="List available models from the proxy and exit",
139-
)
140-
parser.add_argument(
141-
"--strategy",
142-
default="default",
143-
type=str,
144-
help="Name of the strategy to use (default: default)",
145-
)
146-
parser.add_argument(
147-
"--base-url",
148-
default="http://localhost:4000",
149-
help="LiteLLM base URL (default: http://localhost:4000)",
150-
)
151-
parser.add_argument(
152-
"--api-key",
153-
default="sk-balatrollm-proxy-key",
154-
help="LiteLLM proxy API key (default: sk-balatrollm-proxy-key)",
155-
)
156-
parser.add_argument(
157-
"--config",
158-
help="Load configuration from a previous run's config.json file",
159-
)
160-
parser.add_argument(
161-
"--runs-dir",
162-
type=lambda p: Path(p).resolve(),
163-
default=Path.cwd().resolve(),
164-
help="Base directory for storing run data (default: current directory)",
165-
)
166-
parser.add_argument(
167-
"--runs",
168-
type=int,
169-
default=1,
170-
help="Number of times to run the bot with the same configuration (default: 1)",
171-
)
172-
parser.add_argument(
173-
"--port",
174-
type=int,
175-
default=12346,
176-
help="Port for BalatroBot client connection (default: 12346)",
177-
)
178-
179-
# Benchmark subcommand
180-
benchmark_parser = subparsers.add_parser(
181-
"benchmark",
182-
help="Analyze runs and generate leaderboards",
183-
description="Analyze BalatroLLM runs and generate comprehensive leaderboards",
184-
)
185-
benchmark_parser.add_argument(
186-
"--runs-dir",
187-
type=lambda p: Path(p).resolve(),
188-
default=Path("runs").resolve(),
189-
help="Directory containing run data (default: runs)",
190-
)
191-
benchmark_parser.add_argument(
192-
"--output-dir",
193-
type=Path,
194-
default=Path("benchmarks"),
195-
help="Output directory for benchmark results (default: benchmarks)",
196-
)
197-
198-
return parser
7+
__all__ = ["main"]

0 commit comments

Comments
 (0)