Skip to content

Commit 2ad9bc5

Browse files
committed
Add serialization and deserialization classes and methods with pydantic
1 parent 663b3e7 commit 2ad9bc5

File tree

10 files changed

+331
-628
lines changed

10 files changed

+331
-628
lines changed

src/guidellm/core/distribution.py

Lines changed: 28 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -3,135 +3,99 @@
33
import numpy as np
44
from loguru import logger
55

6+
from guidellm.core.serializable import Serializable
7+
68
__all__ = ["Distribution"]
79

810

9-
class Distribution:
11+
class Distribution(Serializable):
1012
"""
11-
A class to represent a statistical distribution and perform various statistical
12-
analyses.
13-
14-
:param data: List of numerical data points (int or float) to initialize the
15-
distribution.
16-
:type data: List[Union[int, float]], optional
13+
A class to represent a statistical distribution and perform various
14+
statistical analyses.
1715
"""
1816

19-
def __init__(self, data: Optional[Union[List[int], List[float]]] = None):
20-
"""
21-
Initialize the Distribution with optional data.
22-
23-
:param data: List of numerical data points to initialize the distribution,
24-
defaults to None.
25-
:type data: List[Union[int, float]], optional
26-
"""
27-
self._data = list(data) if data else []
28-
logger.debug(f"Initialized Distribution with data: {self._data}")
17+
def __init__(self, **data):
18+
super().__init__(**data)
19+
logger.debug(f"Initialized Distribution with data: {self.data}")
2920

3021
def __str__(self) -> str:
3122
"""
3223
Return a string representation of the Distribution.
33-
34-
:return: String representation of the Distribution.
35-
:rtype: str
3624
"""
3725
return (
3826
f"Distribution(mean={self.mean:.2f}, median={self.median:.2f}, "
39-
f"min={self.min}, max={self.max}, count={len(self._data)})"
27+
f"min={self.min}, max={self.max}, count={len(self.data)})"
4028
)
4129

4230
def __repr__(self) -> str:
4331
"""
4432
Return an unambiguous string representation of the Distribution for debugging.
45-
46-
:return: Unambiguous string representation of the Distribution.
47-
:rtype: str
48-
"""
49-
return f"Distribution(data={self._data})"
50-
51-
@property
52-
def data(self) -> List[Union[int, float]]:
53-
"""
54-
Return the data points of the distribution.
55-
56-
:return: The data points of the distribution.
57-
:rtype: List[Union[int, float]]
5833
"""
59-
return self._data
34+
return f"Distribution(data={self.data})"
6035

6136
@property
6237
def mean(self) -> float:
6338
"""
6439
Calculate and return the mean of the distribution.
65-
6640
:return: The mean of the distribution.
67-
:rtype: float
6841
"""
69-
if not self._data:
42+
if not self.data:
7043
logger.warning("No data points available to calculate mean.")
7144
return 0.0
7245

73-
mean_value = np.mean(self._data).item()
46+
mean_value = np.mean(self.data).item()
7447
logger.debug(f"Calculated mean: {mean_value}")
7548
return mean_value
7649

7750
@property
7851
def median(self) -> float:
7952
"""
8053
Calculate and return the median of the distribution.
81-
8254
:return: The median of the distribution.
83-
:rtype: float
8455
"""
85-
if not self._data:
56+
if not self.data:
8657
logger.warning("No data points available to calculate median.")
8758
return 0.0
8859

89-
median_value = np.median(self._data).item()
60+
median_value = np.median(self.data).item()
9061
logger.debug(f"Calculated median: {median_value}")
9162
return median_value
9263

9364
@property
9465
def variance(self) -> float:
9566
"""
9667
Calculate and return the variance of the distribution.
97-
9868
:return: The variance of the distribution.
99-
:rtype: float
10069
"""
101-
if not self._data:
70+
if not self.data:
10271
logger.warning("No data points available to calculate variance.")
10372
return 0.0
10473

105-
variance_value = np.var(self._data).item()
74+
variance_value = np.var(self.data).item()
10675
logger.debug(f"Calculated variance: {variance_value}")
10776
return variance_value
10877

10978
@property
11079
def std_deviation(self) -> float:
11180
"""
11281
Calculate and return the standard deviation of the distribution.
113-
11482
:return: The standard deviation of the distribution.
115-
:rtype: float
11683
"""
117-
if not self._data:
84+
if not self.data:
11885
logger.warning("No data points available to calculate standard deviation.")
11986
return 0.0
12087

121-
std_deviation_value = np.std(self._data).item()
88+
std_deviation_value = np.std(self.data).item()
12289
logger.debug(f"Calculated standard deviation: {std_deviation_value}")
12390
return std_deviation_value
12491

12592
def percentile(self, percentile: float) -> float:
12693
"""
12794
Calculate and return the specified percentile of the distribution.
128-
12995
:param percentile: The desired percentile to calculate (0-100).
130-
:type percentile: float
13196
:return: The specified percentile of the distribution.
132-
:rtype: float
13397
"""
134-
if not self._data:
98+
if not self.data:
13599
logger.warning("No data points available to calculate percentile.")
136100
return 0.0
137101

@@ -142,61 +106,52 @@ def percentile(self, percentile: float) -> float:
142106
def percentiles(self, percentiles: List[float]) -> List[float]:
143107
"""
144108
Calculate and return the specified percentiles of the distribution.
145-
146109
:param percentiles: A list of desired percentiles to calculate (0-100).
147-
:type percentiles: List[float]
148110
:return: A list of the specified percentiles of the distribution.
149-
:rtype: List[float]
150111
"""
151-
if not self._data:
112+
if not self.data:
152113
logger.warning("No data points available to calculate percentiles.")
153114
return [0.0] * len(percentiles)
154115

155-
percentiles_values = np.percentile(self._data, percentiles).tolist()
116+
percentiles_values = np.percentile(self.data, percentiles).tolist()
156117
logger.debug(f"Calculated percentiles {percentiles}: {percentiles_values}")
157118
return percentiles_values
158119

159120
@property
160121
def min(self) -> float:
161122
"""
162123
Return the minimum value of the distribution.
163-
164124
:return: The minimum value of the distribution.
165-
:rtype: float
166125
"""
167-
if not self._data:
126+
if not self.data:
168127
logger.warning("No data points available to calculate minimum.")
169128
return 0.0
170129

171-
min_value = np.min(self._data)
130+
min_value = np.min(self.data)
172131
logger.debug(f"Calculated min: {min_value}")
173132
return min_value
174133

175134
@property
176135
def max(self) -> float:
177136
"""
178137
Return the maximum value of the distribution.
179-
180138
:return: The maximum value of the distribution.
181-
:rtype: float
182139
"""
183-
if not self._data:
140+
if not self.data:
184141
logger.warning("No data points available to calculate maximum.")
185142
return 0.0
186143

187-
max_value = np.max(self._data)
144+
max_value = np.max(self.data)
188145
logger.debug(f"Calculated max: {max_value}")
189146
return max_value
190147

191148
@property
192149
def range(self) -> float:
193150
"""
194151
Calculate and return the range of the distribution (max - min).
195-
196152
:return: The range of the distribution.
197-
:rtype: float
198153
"""
199-
if not self._data:
154+
if not self.data:
200155
logger.warning("No data points available to calculate range.")
201156
return 0.0
202157

@@ -207,9 +162,7 @@ def range(self) -> float:
207162
def describe(self) -> dict:
208163
"""
209164
Return a dictionary describing various statistics of the distribution.
210-
211165
:return: A dictionary with statistical summaries of the distribution.
212-
:rtype: dict
213166
"""
214167
description = {
215168
"mean": self.mean,
@@ -230,19 +183,15 @@ def describe(self) -> dict:
230183
def add_data(self, new_data: Union[List[int], List[float]]):
231184
"""
232185
Add new data points to the distribution.
233-
234186
:param new_data: A list of new numerical data points to add.
235-
:type new_data: List[Union[int, float]]
236187
"""
237-
self._data.extend(new_data)
188+
self.data.extend(new_data)
238189
logger.debug(f"Added new data: {new_data}")
239190

240191
def remove_data(self, remove_data: Union[List[int], List[float]]):
241192
"""
242193
Remove specified data points from the distribution.
243-
244194
:param remove_data: A list of numerical data points to remove.
245-
:type remove_data: List[Union[int, float]]
246195
"""
247-
self._data = [item for item in self._data if item not in remove_data]
196+
self.data = [item for item in self.data if item not in remove_data]
248197
logger.debug(f"Removed data: {remove_data}")

src/guidellm/core/request.py

Lines changed: 22 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,32 @@
11
import uuid
2-
from dataclasses import dataclass, field
3-
from typing import Dict, Optional
2+
from typing import Dict, Optional, Any
43

5-
from loguru import logger
4+
from guidellm.core.serializable import Serializable
65

76

8-
@dataclass(frozen=True)
9-
class TextGenerationRequest:
7+
class TextGenerationRequest(Serializable):
108
"""
119
A class to represent a text generation request for generative AI workloads.
12-
13-
:param prompt: The input prompt for the text generation request.
14-
:type prompt: str
15-
:param prompt_token_count: The number of tokens in the prompt, defaults to None.
16-
:type prompt_token_count: Optional[int]
17-
:param generated_token_count: The number of tokens to generate, defaults to None.
18-
:type generated_token_count: Optional[int]
19-
:param params: Optional parameters for the text generation request,
20-
defaults to None.
21-
:type params: Optional[Dict[str, Any]]
2210
"""
2311

12+
id: str
2413
prompt: str
25-
id: uuid.UUID = field(default_factory=uuid.uuid4)
26-
prompt_token_count: Optional[int] = None
27-
generated_token_count: Optional[int] = None
28-
params: Dict = field(default_factory=dict)
29-
30-
def __post_init__(self) -> None:
31-
"""
32-
Log the initialization of the TextGenerationRequest instance.
33-
"""
34-
35-
logger.debug(
36-
f"Initialized TextGenerationRequest with id={self.id}, "
37-
f"prompt={self.prompt}, prompt_token_count={self.prompt_token_count}, "
38-
f"generated_token_count={self.generated_token_count}, params={self.params}"
39-
)
40-
41-
def __repr__(self) -> str:
42-
"""
43-
Return a string representation of the TextGenerationRequest.
44-
45-
:return: String representation of the TextGenerationRequest.
46-
:rtype: str
47-
"""
48-
49-
return (
50-
f"TextGenerationRequest("
51-
f"id={self.id}, "
52-
f"prompt={self.prompt}, "
53-
f"prompt_token_count={self.prompt_token_count}, "
54-
f"generated_token_count={self.generated_token_count}, "
55-
f"params={self.params})"
14+
prompt_token_count: Optional[int]
15+
generated_token_count: Optional[int]
16+
params: Dict[str, Any]
17+
18+
def __init__(
19+
self,
20+
prompt: str,
21+
prompt_token_count: Optional[int] = None,
22+
generated_token_count: Optional[int] = None,
23+
params: Optional[Dict[str, Any]] = None,
24+
id: Optional[str] = None,
25+
):
26+
super().__init__(
27+
id=str(uuid.uuid4()) if id is None else id,
28+
prompt=prompt,
29+
prompt_token_count=prompt_token_count,
30+
generated_token_count=generated_token_count,
31+
params=params or {},
5632
)

0 commit comments

Comments
 (0)