Skip to content

Commit 86d9f8c

Browse files
committed
bug fix
1 parent c8fe203 commit 86d9f8c

File tree

4 files changed

+60
-53
lines changed

4 files changed

+60
-53
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "tacho"
3-
version = "0.8.7"
3+
version = "0.8.8"
44
description = "CLI tool for measuring and comparing LLM inference speeds"
55
readme = "README.md"
66
authors = [

tacho/cli.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ def version_callback(value: bool):
2121
raise typer.Exit()
2222

2323

24+
async def run_cli(models: list[str], runs: int, tokens: int):
25+
"""Run pings and benchmarks in a single event loop"""
26+
res = await run_pings(models)
27+
valid_models = [models[i] for i in range(len(models)) if res[i]]
28+
if not valid_models:
29+
return None, None
30+
bench_res = await run_benchmarks(valid_models, runs, tokens)
31+
return valid_models, bench_res
32+
33+
2434
@app.command()
2535
def cli(
2636
models: list[str] = typer.Argument(
@@ -36,11 +46,9 @@ def cli(
3646
),
3747
):
3848
"""CLI tool for measuring LLM inference speeds"""
39-
res = asyncio.run(run_pings(models))
40-
valid_models = [models[i] for i in range(len(models)) if res[i]]
41-
if not valid_models:
49+
valid_models, res = asyncio.run(run_cli(models, runs, tokens))
50+
if valid_models is None:
4251
raise typer.Exit(1)
43-
res = asyncio.run(run_benchmarks(valid_models, runs, tokens))
4452
display_results(valid_models, runs, res)
4553

4654

tests/test_cli.py

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,23 @@ def test_version_callback_not_called(self):
3232

3333
def test_bench_command_success(self, runner, mocker):
3434
"""Test successful benchmark command"""
35-
# Test the cli function directly to avoid callback issues
36-
mock_asyncio_run = mocker.patch("tacho.cli.asyncio.run")
37-
38-
# First call to run_pings
39-
mock_asyncio_run.side_effect = [
40-
[True, True], # run_pings result
41-
[
42-
(2.0, 100),
43-
(2.1, 102),
44-
(2.2, 104),
45-
(2.3, 106),
46-
(2.4, 108), # run_benchmarks results
47-
(1.5, 95),
48-
(1.6, 97),
49-
(1.7, 99),
50-
(1.8, 101),
51-
(1.9, 103),
52-
],
35+
mock_run_pings = mocker.patch("tacho.cli.run_pings", new_callable=AsyncMock)
36+
mock_run_pings.return_value = [True, True]
37+
38+
mock_run_benchmarks = mocker.patch(
39+
"tacho.cli.run_benchmarks", new_callable=AsyncMock
40+
)
41+
mock_run_benchmarks.return_value = [
42+
(2.0, 100),
43+
(2.1, 102),
44+
(2.2, 104),
45+
(2.3, 106),
46+
(2.4, 108),
47+
(1.5, 95),
48+
(1.6, 97),
49+
(1.7, 99),
50+
(1.8, 101),
51+
(1.9, 103),
5352
]
5453

5554
mock_display = mocker.patch("tacho.cli.display_results")
@@ -75,13 +74,13 @@ def test_bench_command_no_valid_models(self, runner, mocker):
7574

7675
def test_bench_command_with_options(self, runner, mocker):
7776
"""Test benchmark command with custom options"""
78-
mock_asyncio_run = mocker.patch("tacho.cli.asyncio.run")
77+
mock_run_pings = mocker.patch("tacho.cli.run_pings", new_callable=AsyncMock)
78+
mock_run_pings.return_value = [True]
7979

80-
# Configure asyncio.run mock responses
81-
mock_asyncio_run.side_effect = [
82-
[True], # run_pings result
83-
[(2.0 + i * 0.1, 100 + i) for i in range(10)], # run_benchmarks results
84-
]
80+
mock_run_benchmarks = mocker.patch(
81+
"tacho.cli.run_benchmarks", new_callable=AsyncMock
82+
)
83+
mock_run_benchmarks.return_value = [(2.0 + i * 0.1, 100 + i) for i in range(10)]
8584

8685
mock_display = mocker.patch("tacho.cli.display_results")
8786

@@ -96,18 +95,22 @@ def test_bench_command_with_options(self, runner, mocker):
9695

9796
def test_cli_with_partial_valid_models(self, runner, mocker):
9897
"""Test CLI when some models fail validation"""
99-
mock_asyncio_run = mocker.patch("tacho.cli.asyncio.run")
100-
mock_asyncio_run.side_effect = [
101-
[True, False, True], # run_pings: gpt-4 valid, invalid fails, claude-3 valid
102-
[(2.0, 100), (1.8, 95)], # run_benchmarks for valid models
103-
]
98+
mock_run_pings = mocker.patch("tacho.cli.run_pings", new_callable=AsyncMock)
99+
mock_run_pings.return_value = [True, False, True]
100+
101+
mock_run_benchmarks = mocker.patch(
102+
"tacho.cli.run_benchmarks", new_callable=AsyncMock
103+
)
104+
mock_run_benchmarks.return_value = [(2.0, 100), (1.8, 95)]
105+
104106
mock_display = mocker.patch("tacho.cli.display_results")
105107

106108
# Call cli with mixed valid/invalid models
107109
cli(["gpt-4", "invalid", "claude-3"], runs=1, tokens=250)
108110

109111
# Should not raise Exit since at least one model succeeded
110-
assert mock_asyncio_run.call_count == 2
112+
mock_run_pings.assert_called_once()
113+
mock_run_benchmarks.assert_called_once()
111114
mock_display.assert_called_once()
112115

113116
def test_cli_all_models_fail(self, runner, mocker):
@@ -147,23 +150,19 @@ def test_help_command(self, runner):
147150

148151
def test_cli_function_partial_valid_models(self, mocker):
149152
"""Test cli function filters out invalid models"""
150-
mock_asyncio_run = mocker.patch("tacho.cli.asyncio.run")
151-
152-
# Configure responses: first ping returns mixed results
153-
mock_asyncio_run.side_effect = [
154-
[
155-
True,
156-
False,
157-
True,
158-
], # run_pings: gpt-4 valid, invalid fails, claude-3 valid
159-
[
160-
(2.0, 100),
161-
(2.1, 102),
162-
(2.2, 104), # Results for gpt-4 (3 runs)
163-
(1.8, 95),
164-
(1.9, 97),
165-
(2.0, 99),
166-
], # Results for claude-3 (3 runs)
153+
mock_run_pings = mocker.patch("tacho.cli.run_pings", new_callable=AsyncMock)
154+
mock_run_pings.return_value = [True, False, True]
155+
156+
mock_run_benchmarks = mocker.patch(
157+
"tacho.cli.run_benchmarks", new_callable=AsyncMock
158+
)
159+
mock_run_benchmarks.return_value = [
160+
(2.0, 100),
161+
(2.1, 102),
162+
(2.2, 104),
163+
(1.8, 95),
164+
(1.9, 97),
165+
(2.0, 99),
167166
]
168167

169168
mock_display = mocker.patch("tacho.cli.display_results")

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)