-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Serializable Functionality and GuidanceReport Class for Enhanced …
…Results Management (#22) ## Summary Introduces the `Serializable` class to provide serialization capabilities for core Pydantic classes, along with the new `GuidanceReport` class to manage multiple benchmarking reports. The additions add in native support for loading and saving to disk in json and yaml formats. ## Details - **Serializable Class**: Adds the ability to serialize and deserialize objects to/from YAML and JSON formats, and save/load from files. - Implements methods for `to_yaml`, `to_json`, `from_yaml`, `from_json`, `save_file`, and `load_file`. - Introduces `SerializableFileType` enum to handle supported file types. - Includes validation and error handling for file operations. - **GuidanceReport Class**: Manages guidance reports containing benchmarking details across multiple runs. - Inherits from `Serializable` to leverage serialization capabilities. - Contains a list of `TextGenerationBenchmarkReport` objects. - **CLI Integration**: Updates the CLI to use `GuidanceReport` for saving benchmark reports. - Adds `-save-path` option for specifying the path to save the report. - **Tests**: Adds comprehensive unit tests for the new functionality. - Tests for `Serializable` class methods. - Tests for `GuidanceReport` class, including initialization, file operations, and serialization. ## Test Plan - **Automation Testing**: - Added unit tests for `Serializable` class covering YAML and JSON serialization/deserialization, file saving/loading, and error handling. - Added unit tests for `GuidanceReport` class covering initialization and file operations.
- Loading branch information
Showing
8 changed files
with
384 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
from typing import List | ||
|
||
from pydantic import Field | ||
|
||
from guidellm.core.serializable import Serializable | ||
from guidellm.core.result import TextGenerationBenchmarkReport | ||
|
||
__all__ = [ | ||
"GuidanceReport", | ||
] | ||
|
||
|
||
class GuidanceReport(Serializable): | ||
""" | ||
A class to manage the guidance reports that include the benchmarking details, | ||
potentially across multiple runs, for saving and loading from disk. | ||
""" | ||
|
||
benchmarks: List[TextGenerationBenchmarkReport] = Field( | ||
default_factory=list, description="The list of benchmark reports." | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import os | ||
|
||
|
||
__all__ = [ | ||
"is_file_name", | ||
"is_directory_name", | ||
] | ||
|
||
|
||
def is_file_name(path: str) -> bool: | ||
""" | ||
Check if the path has an extension and is not a directory. | ||
:param path: The path to check. | ||
:type path: str | ||
:return: True if the path is a file naming convention. | ||
""" | ||
|
||
_, ext = os.path.splitext(path) | ||
|
||
return bool(ext) and not path.endswith(os.path.sep) | ||
|
||
|
||
def is_directory_name(path: str) -> bool: | ||
""" | ||
Check if the path does not have an extension and is a directory. | ||
:param path: The path to check. | ||
:type path: str | ||
:return: True if the path is a directory naming convention. | ||
""" | ||
_, ext = os.path.splitext(path) | ||
return not ext or path.endswith(os.path.sep) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import pytest | ||
import os | ||
import tempfile | ||
from guidellm.core import ( | ||
TextGenerationBenchmark, | ||
TextGenerationBenchmarkReport, | ||
TextGenerationResult, | ||
TextGenerationRequest, | ||
TextGenerationError, | ||
Distribution, | ||
GuidanceReport, | ||
) | ||
|
||
|
||
@pytest.fixture | ||
def sample_benchmark_report() -> TextGenerationBenchmarkReport: | ||
sample_request = TextGenerationRequest(prompt="sample prompt") | ||
sample_distribution = Distribution() | ||
sample_result = TextGenerationResult( | ||
request=sample_request, | ||
prompt="sample prompt", | ||
prompt_word_count=2, | ||
prompt_token_count=2, | ||
output="sample output", | ||
output_word_count=2, | ||
output_token_count=2, | ||
last_time=None, | ||
first_token_set=False, | ||
start_time=None, | ||
end_time=None, | ||
first_token_time=None, | ||
decode_times=sample_distribution, | ||
) | ||
sample_error = TextGenerationError(request=sample_request, message="sample error") | ||
sample_benchmark = TextGenerationBenchmark( | ||
mode="async", | ||
rate=1.0, | ||
results=[sample_result], | ||
errors=[sample_error], | ||
concurrencies=[], | ||
) | ||
return TextGenerationBenchmarkReport( | ||
benchmarks=[sample_benchmark], args=[{"arg1": "value1"}] | ||
) | ||
|
||
|
||
def compare_guidance_reports(report1: GuidanceReport, report2: GuidanceReport) -> bool: | ||
return report1 == report2 | ||
|
||
|
||
@pytest.mark.smoke | ||
def test_guidance_report_initialization(): | ||
report = GuidanceReport() | ||
assert report.benchmarks == [] | ||
|
||
|
||
@pytest.mark.smoke | ||
def test_guidance_report_initialization_with_params(sample_benchmark_report): | ||
report = GuidanceReport(benchmarks=[sample_benchmark_report]) | ||
assert report.benchmarks == [sample_benchmark_report] | ||
|
||
|
||
@pytest.mark.smoke | ||
def test_guidance_report_file(sample_benchmark_report): | ||
report = GuidanceReport(benchmarks=[sample_benchmark_report]) | ||
with tempfile.TemporaryDirectory() as temp_dir: | ||
file_path = os.path.join(temp_dir, "report.yaml") | ||
report.save_file(file_path) | ||
loaded_report = GuidanceReport.load_file(file_path) | ||
assert compare_guidance_reports(report, loaded_report) | ||
|
||
|
||
@pytest.mark.regression | ||
def test_guidance_report_json(sample_benchmark_report): | ||
report = GuidanceReport(benchmarks=[sample_benchmark_report]) | ||
json_str = report.to_json() | ||
loaded_report = GuidanceReport.from_json(json_str) | ||
assert compare_guidance_reports(report, loaded_report) | ||
|
||
|
||
@pytest.mark.regression | ||
def test_guidance_report_yaml(sample_benchmark_report): | ||
report = GuidanceReport(benchmarks=[sample_benchmark_report]) | ||
yaml_str = report.to_yaml() | ||
loaded_report = GuidanceReport.from_yaml(yaml_str) | ||
assert compare_guidance_reports(report, loaded_report) |
Oops, something went wrong.