26
26
from guidellm .benchmark .benchmarker import Benchmarker
27
27
from guidellm .benchmark .objects import GenerativeBenchmark , GenerativeBenchmarksReport
28
28
from guidellm .benchmark .output import (
29
- GenerativeBenchmarkerConsole ,
30
29
GenerativeBenchmarkerOutput ,
31
30
)
32
31
from guidellm .benchmark .profile import Profile , ProfileType
53
52
_CURRENT_WORKING_DIR = Path .cwd ()
54
53
55
54
55
+ # Data types
56
+
57
+ DataType = (
58
+ Iterable [str ]
59
+ | Iterable [dict [str , Any ]]
60
+ | Dataset
61
+ | DatasetDict
62
+ | IterableDataset
63
+ | IterableDatasetDict
64
+ | str
65
+ | Path
66
+ )
67
+
68
+ OutputFormatType = (
69
+ tuple [str , ...]
70
+ | list [str ]
71
+ | dict [str , str | dict [str , Any ] | GenerativeBenchmarkerOutput ]
72
+ | None
73
+ )
74
+
75
+
76
+ # Helper functions
77
+
78
+ async def initialize_backend (
79
+ backend : BackendType | Backend ,
80
+ target : str ,
81
+ model : str | None ,
82
+ backend_kwargs : dict [str , Any ] | None ,
83
+ ) -> Backend :
84
+ backend = (
85
+ Backend .create (
86
+ backend , target = target , model = model , ** (backend_kwargs or {})
87
+ )
88
+ if not isinstance (backend , Backend )
89
+ else backend
90
+ )
91
+ await backend .process_startup ()
92
+ await backend .validate ()
93
+ return backend
94
+
95
+
96
+ async def resolve_profile (
97
+ constraint_inputs : dict [str , int | float ],
98
+ profile : Profile | str | None ,
99
+ rate : list [float ] | None ,
100
+ random_seed : int ,
101
+ constraints : dict [str , ConstraintInitializer | Any ],
102
+ ):
103
+ for key , val in constraint_inputs .items ():
104
+ if val is not None :
105
+ constraints [key ] = val
106
+ if not isinstance (profile , Profile ):
107
+ if isinstance (profile , str ):
108
+ profile = Profile .create (
109
+ rate_type = profile ,
110
+ rate = rate ,
111
+ random_seed = random_seed ,
112
+ constraints = {** constraints },
113
+ )
114
+ else :
115
+ raise ValueError (f"Expected string for profile; got { type (profile )} " )
116
+
117
+ elif constraints :
118
+ raise ValueError (
119
+ "Constraints must be empty when providing a Profile instance. "
120
+ f"Provided constraints: { constraints } ; provided profile: { profile } "
121
+ )
122
+ return profile
123
+
124
+ async def resolve_output_formats (
125
+ output_formats : OutputFormatType ,
126
+ output_path : str | Path | None ,
127
+ ) -> dict [str , GenerativeBenchmarkerOutput ]:
128
+ output_formats = GenerativeBenchmarkerOutput .resolve (
129
+ output_formats = (output_formats or {}), output_path = output_path
130
+ )
131
+ return output_formats
132
+
133
+ async def finalize_outputs (
134
+ report : GenerativeBenchmarksReport ,
135
+ resolved_output_formats : dict [str , GenerativeBenchmarkerOutput ]
136
+ ):
137
+ output_format_results = {}
138
+ for key , output in resolved_output_formats .items ():
139
+ output_result = await output .finalize (report )
140
+ output_format_results [key ] = output_result
141
+ return output_format_results
142
+
143
+
144
+ # Complete entrypoints
145
+
56
146
async def benchmark_with_scenario (scenario : Scenario , ** kwargs ):
57
147
"""
58
148
Run a benchmark using a scenario and specify any extra arguments
@@ -67,16 +157,7 @@ async def benchmark_with_scenario(scenario: Scenario, **kwargs):
67
157
# @validate_call(config={"arbitrary_types_allowed": True})
68
158
async def benchmark_generative_text ( # noqa: C901
69
159
target : str ,
70
- data : (
71
- Iterable [str ]
72
- | Iterable [dict [str , Any ]]
73
- | Dataset
74
- | DatasetDict
75
- | IterableDataset
76
- | IterableDatasetDict
77
- | str
78
- | Path
79
- ),
160
+ data : DataType ,
80
161
profile : StrategyType | ProfileType | Profile ,
81
162
rate : float | list [float ] | None = None ,
82
163
random_seed : int = 42 ,
@@ -91,12 +172,7 @@ async def benchmark_generative_text( # noqa: C901
91
172
data_sampler : Literal ["random" ] | None = None ,
92
173
# Output configuration
93
174
output_path : str | Path | None = _CURRENT_WORKING_DIR ,
94
- output_formats : (
95
- tuple [str , ...]
96
- | list [str ]
97
- | dict [str , str | dict [str , Any ] | GenerativeBenchmarkerOutput ]
98
- | None
99
- ) = ("console" , "json" , "html" , "csv" ),
175
+ output_formats : OutputFormatType = ("console" , "json" , "html" , "csv" ),
100
176
# Updates configuration
101
177
progress : tuple [str , ...] | list [str ] | list [BenchmarkerProgress ] | None = None ,
102
178
print_updates : bool = False ,
@@ -120,16 +196,7 @@ async def benchmark_generative_text( # noqa: C901
120
196
with console .print_update_step (
121
197
title = f"Initializing backend { backend } "
122
198
) as console_step :
123
- backend = (
124
- Backend .create (
125
- backend , target = target , model = model , ** (backend_kwargs or {})
126
- )
127
- if not isinstance (backend , Backend )
128
- else backend
129
- )
130
- console_step .update (f"{ backend .__class__ .__name__ } backend initialized" )
131
- await backend .process_startup ()
132
- await backend .validate ()
199
+ backend = await initialize_backend (backend , target , model , backend_kwargs )
133
200
console_step .finish (
134
201
title = f"{ backend .__class__ .__name__ } backend initialized" ,
135
202
details = backend .info ,
@@ -190,27 +257,19 @@ async def benchmark_generative_text( # noqa: C901
190
257
with console .print_update_step (
191
258
title = f"Resolving profile { profile } "
192
259
) as console_step :
193
- for key , val in {
194
- "max_seconds" : max_seconds ,
195
- "max_requests" : max_requests ,
196
- "max_errors" : max_errors ,
197
- "max_error_rate" : max_error_rate ,
198
- "max_global_error_rate" : max_global_error_rate ,
199
- }.items ():
200
- if val is not None :
201
- constraints [key ] = val
202
- if not isinstance (profile , Profile ):
203
- profile = Profile .create (
204
- rate_type = profile ,
205
- rate = rate ,
206
- random_seed = random_seed ,
207
- constraints = {** constraints },
208
- )
209
- elif constraints :
210
- raise ValueError (
211
- "Constraints must be empty when providing a Profile instance. "
212
- f"Provided constraints: { constraints } ; provided profile: { profile } "
213
- )
260
+ profile = await resolve_profile (
261
+ {
262
+ "max_seconds" : max_seconds ,
263
+ "max_requests" : max_requests ,
264
+ "max_errors" : max_errors ,
265
+ "max_error_rate" : max_error_rate ,
266
+ "max_global_error_rate" : max_global_error_rate ,
267
+ },
268
+ profile ,
269
+ rate ,
270
+ random_seed ,
271
+ constraints ,
272
+ )
214
273
console_step .finish (
215
274
title = f"{ profile .__class__ .__name__ } profile resolved" ,
216
275
details = InfoMixin .extract_from_obj (profile ),
@@ -237,12 +296,10 @@ async def benchmark_generative_text( # noqa: C901
237
296
)
238
297
239
298
with console .print_update_step (title = "Resolving output formats" ) as console_step :
240
- output_formats = GenerativeBenchmarkerOutput .resolve (
241
- output_formats = (output_formats or {}), output_path = output_path
242
- )
299
+ resolved_output_formats = await resolve_output_formats (output_formats , output_path )
243
300
console_step .finish (
244
301
title = "Output formats resolved" ,
245
- details = {key : str (val ) for key , val in output_formats .items ()},
302
+ details = {key : str (val ) for key , val in resolved_output_formats .items ()},
246
303
status_level = "success" ,
247
304
)
248
305
@@ -278,14 +335,11 @@ async def benchmark_generative_text( # noqa: C901
278
335
if benchmark :
279
336
report .benchmarks .append (benchmark )
280
337
281
- output_format_results = {}
282
- for key , output in output_formats .items ():
283
- output_result = await output .finalize (report )
284
- output_format_results [key ] = output_result
338
+ output_format_results = await finalize_outputs (report , resolved_output_formats )
285
339
286
340
console .print ("\n \n " )
287
341
console .print_update (
288
- title = f"Benchmarking complete, generated { len (report .benchmarks )} benchmark(s)" ,
342
+ title = f"Benchmarking complete; generated { len (report .benchmarks )} benchmark(s)" ,
289
343
status = "success" ,
290
344
)
291
345
for key , value in output_format_results .items ():
@@ -294,20 +348,34 @@ async def benchmark_generative_text( # noqa: C901
294
348
return report , output_format_results
295
349
296
350
297
- def reimport_benchmarks_report (file : Path , output_path : Path | None ) -> None :
351
+ async def reimport_benchmarks_report (
352
+ file : Path ,
353
+ output_path : Path | None ,
354
+ output_formats : OutputFormatType = ("console" , "json" , "html" , "csv" ),
355
+ ) -> tuple [GenerativeBenchmarksReport , dict [str , Any ]]:
298
356
"""
299
357
The command-line entry point for re-importing and displaying an
300
- existing benchmarks report. Can also specify
358
+ existing benchmarks report. Can also specify an output format.
301
359
Assumes the file provided exists.
302
360
"""
303
- report = GenerativeBenchmarksReport .load_file (file )
304
- console_output = GenerativeBenchmarkerConsole ()
305
- console_output .finalize (report )
306
361
console = Console ()
362
+ with console .print_update_step (
363
+ title = f"Loading benchmarks from { file } "
364
+ ) as console_step :
365
+ report = GenerativeBenchmarksReport .load_file (file )
366
+ console_step .finish (f"Import of old benchmarks complete; loaded { len (report .benchmarks )} benchmark(s)" )
367
+
368
+ with console .print_update_step (title = "Resolving output formats" ) as console_step :
369
+ resolved_output_formats = await resolve_output_formats (output_formats , output_path )
370
+ console_step .finish (
371
+ title = "Output formats resolved" ,
372
+ details = {key : str (val ) for key , val in resolved_output_formats .items ()},
373
+ status_level = "success" ,
374
+ )
307
375
308
- if output_path :
309
- with console . print_update_step (
310
- title = f"Saving benchmarks report to { output_path } ..."
311
- ) as console_step :
312
- saved_path = report . save_file ( output_path )
313
- console_step . finish ( title = f"Benchmarks report saved to { saved_path } " )
376
+ output_format_results = await finalize_outputs ( report , resolved_output_formats )
377
+
378
+ for key , value in output_format_results . items ():
379
+ console . print_update ( title = f" { key :<8 } : { value } " , status = "debug" )
380
+
381
+ return report , output_format_results
0 commit comments