guidellm 0.4.0a18__py3-none-any.whl → 0.4.0a155__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of guidellm might be problematic. Click here for more details.

Files changed (116) hide show
  1. guidellm/__init__.py +5 -2
  2. guidellm/__main__.py +451 -252
  3. guidellm/backends/__init__.py +33 -0
  4. guidellm/backends/backend.py +110 -0
  5. guidellm/backends/openai.py +355 -0
  6. guidellm/backends/response_handlers.py +455 -0
  7. guidellm/benchmark/__init__.py +53 -39
  8. guidellm/benchmark/benchmarker.py +148 -317
  9. guidellm/benchmark/entrypoints.py +466 -128
  10. guidellm/benchmark/output.py +517 -771
  11. guidellm/benchmark/profile.py +580 -280
  12. guidellm/benchmark/progress.py +568 -549
  13. guidellm/benchmark/scenarios/__init__.py +40 -0
  14. guidellm/benchmark/scenarios/chat.json +6 -0
  15. guidellm/benchmark/scenarios/rag.json +6 -0
  16. guidellm/benchmark/schemas.py +2085 -0
  17. guidellm/data/__init__.py +28 -4
  18. guidellm/data/collators.py +16 -0
  19. guidellm/data/deserializers/__init__.py +53 -0
  20. guidellm/data/deserializers/deserializer.py +109 -0
  21. guidellm/data/deserializers/file.py +222 -0
  22. guidellm/data/deserializers/huggingface.py +94 -0
  23. guidellm/data/deserializers/memory.py +192 -0
  24. guidellm/data/deserializers/synthetic.py +346 -0
  25. guidellm/data/loaders.py +145 -0
  26. guidellm/data/preprocessors/__init__.py +25 -0
  27. guidellm/data/preprocessors/formatters.py +412 -0
  28. guidellm/data/preprocessors/mappers.py +198 -0
  29. guidellm/data/preprocessors/preprocessor.py +29 -0
  30. guidellm/data/processor.py +30 -0
  31. guidellm/data/schemas.py +13 -0
  32. guidellm/data/utils/__init__.py +10 -0
  33. guidellm/data/utils/dataset.py +94 -0
  34. guidellm/data/utils/functions.py +18 -0
  35. guidellm/extras/__init__.py +4 -0
  36. guidellm/extras/audio.py +215 -0
  37. guidellm/extras/vision.py +242 -0
  38. guidellm/logger.py +2 -2
  39. guidellm/mock_server/__init__.py +8 -0
  40. guidellm/mock_server/config.py +84 -0
  41. guidellm/mock_server/handlers/__init__.py +17 -0
  42. guidellm/mock_server/handlers/chat_completions.py +280 -0
  43. guidellm/mock_server/handlers/completions.py +280 -0
  44. guidellm/mock_server/handlers/tokenizer.py +142 -0
  45. guidellm/mock_server/models.py +510 -0
  46. guidellm/mock_server/server.py +168 -0
  47. guidellm/mock_server/utils.py +302 -0
  48. guidellm/preprocess/dataset.py +23 -26
  49. guidellm/presentation/builder.py +2 -2
  50. guidellm/presentation/data_models.py +25 -21
  51. guidellm/presentation/injector.py +2 -3
  52. guidellm/scheduler/__init__.py +65 -26
  53. guidellm/scheduler/constraints.py +1035 -0
  54. guidellm/scheduler/environments.py +252 -0
  55. guidellm/scheduler/scheduler.py +140 -368
  56. guidellm/scheduler/schemas.py +272 -0
  57. guidellm/scheduler/strategies.py +519 -0
  58. guidellm/scheduler/worker.py +391 -420
  59. guidellm/scheduler/worker_group.py +707 -0
  60. guidellm/schemas/__init__.py +31 -0
  61. guidellm/schemas/info.py +159 -0
  62. guidellm/schemas/request.py +216 -0
  63. guidellm/schemas/response.py +119 -0
  64. guidellm/schemas/stats.py +228 -0
  65. guidellm/{config.py → settings.py} +32 -21
  66. guidellm/utils/__init__.py +95 -8
  67. guidellm/utils/auto_importer.py +98 -0
  68. guidellm/utils/cli.py +46 -2
  69. guidellm/utils/console.py +183 -0
  70. guidellm/utils/encoding.py +778 -0
  71. guidellm/utils/functions.py +134 -0
  72. guidellm/utils/hf_datasets.py +1 -2
  73. guidellm/utils/hf_transformers.py +4 -4
  74. guidellm/utils/imports.py +9 -0
  75. guidellm/utils/messaging.py +1118 -0
  76. guidellm/utils/mixins.py +115 -0
  77. guidellm/utils/pydantic_utils.py +411 -0
  78. guidellm/utils/random.py +3 -4
  79. guidellm/utils/registry.py +220 -0
  80. guidellm/utils/singleton.py +133 -0
  81. guidellm/{objects → utils}/statistics.py +341 -247
  82. guidellm/utils/synchronous.py +159 -0
  83. guidellm/utils/text.py +163 -50
  84. guidellm/utils/typing.py +41 -0
  85. guidellm/version.py +1 -1
  86. {guidellm-0.4.0a18.dist-info → guidellm-0.4.0a155.dist-info}/METADATA +33 -10
  87. guidellm-0.4.0a155.dist-info/RECORD +96 -0
  88. guidellm/backend/__init__.py +0 -23
  89. guidellm/backend/backend.py +0 -259
  90. guidellm/backend/openai.py +0 -705
  91. guidellm/backend/response.py +0 -136
  92. guidellm/benchmark/aggregator.py +0 -760
  93. guidellm/benchmark/benchmark.py +0 -837
  94. guidellm/benchmark/scenario.py +0 -104
  95. guidellm/data/prideandprejudice.txt.gz +0 -0
  96. guidellm/dataset/__init__.py +0 -22
  97. guidellm/dataset/creator.py +0 -213
  98. guidellm/dataset/entrypoints.py +0 -42
  99. guidellm/dataset/file.py +0 -92
  100. guidellm/dataset/hf_datasets.py +0 -62
  101. guidellm/dataset/in_memory.py +0 -132
  102. guidellm/dataset/synthetic.py +0 -287
  103. guidellm/objects/__init__.py +0 -18
  104. guidellm/objects/pydantic.py +0 -89
  105. guidellm/request/__init__.py +0 -18
  106. guidellm/request/loader.py +0 -284
  107. guidellm/request/request.py +0 -79
  108. guidellm/request/types.py +0 -10
  109. guidellm/scheduler/queues.py +0 -25
  110. guidellm/scheduler/result.py +0 -155
  111. guidellm/scheduler/strategy.py +0 -495
  112. guidellm-0.4.0a18.dist-info/RECORD +0 -62
  113. {guidellm-0.4.0a18.dist-info → guidellm-0.4.0a155.dist-info}/WHEEL +0 -0
  114. {guidellm-0.4.0a18.dist-info → guidellm-0.4.0a155.dist-info}/entry_points.txt +0 -0
  115. {guidellm-0.4.0a18.dist-info → guidellm-0.4.0a155.dist-info}/licenses/LICENSE +0 -0
  116. {guidellm-0.4.0a18.dist-info → guidellm-0.4.0a155.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,159 @@
1
+ """
2
+ Async utilities for waiting on synchronization objects.
3
+
4
+ This module provides async-compatible wrappers for threading and multiprocessing
5
+ synchronization primitives (Events and Barriers). These utilities enable async code
6
+ to wait for synchronization objects without blocking the event loop, essential for
7
+ coordinating between async and sync code or between processes in the guidellm system.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import asyncio
13
+ import contextlib
14
+ import time
15
+ from multiprocessing.synchronize import Barrier as ProcessingBarrier
16
+ from multiprocessing.synchronize import Event as ProcessingEvent
17
+ from threading import Barrier as ThreadingBarrier
18
+ from threading import Event as ThreadingEvent
19
+
20
+ __all__ = [
21
+ "SyncObjectTypesAlias",
22
+ "wait_for_sync_barrier",
23
+ "wait_for_sync_event",
24
+ "wait_for_sync_objects",
25
+ ]
26
+
27
+
28
+ # Type alias for threading and multiprocessing synchronization object types
29
+ SyncObjectTypesAlias = (
30
+ ThreadingEvent | ProcessingEvent | ThreadingBarrier | ProcessingBarrier
31
+ )
32
+
33
+
34
+ async def wait_for_sync_event(
35
+ event: ThreadingEvent | ProcessingEvent,
36
+ poll_interval: float,
37
+ ) -> None:
38
+ """
39
+ Asynchronously wait for a threading or multiprocessing Event to be set.
40
+
41
+ This function polls the event at regular intervals without blocking the async
42
+ event loop, allowing other async tasks to continue executing while waiting.
43
+
44
+ :param event: The Event object to wait for (threading or multiprocessing)
45
+ :param poll_interval: Time in seconds between polling checks
46
+ :raises asyncio.CancelledError: If the async task is cancelled
47
+ """
48
+ stop = ThreadingEvent()
49
+
50
+ def _watch():
51
+ try:
52
+ while not stop.is_set():
53
+ if event.wait(timeout=poll_interval):
54
+ return
55
+ except Exception as err: # noqa: BLE001
56
+ if stop.is_set():
57
+ return # Ignore error if we should have stopped
58
+ raise err
59
+
60
+ try:
61
+ await asyncio.to_thread(_watch)
62
+ except asyncio.CancelledError:
63
+ stop.set()
64
+ raise
65
+
66
+
67
+ async def wait_for_sync_barrier(
68
+ barrier: ThreadingBarrier | ProcessingBarrier,
69
+ poll_interval: float,
70
+ ) -> None:
71
+ """
72
+ Asynchronously wait for a threading or multiprocessing Barrier to be reached.
73
+
74
+ This function polls the barrier at regular intervals without blocking the async
75
+ event loop, allowing other async tasks to continue executing while waiting.
76
+
77
+ :param barrier: The Barrier object to wait for (threading or multiprocessing)
78
+ :param poll_interval: Time in seconds between polling checks
79
+ :raises asyncio.CancelledError: If the async task is cancelled
80
+ """
81
+ stop = ThreadingEvent()
82
+ barrier_broken = ThreadingEvent()
83
+
84
+ def _wait_indefinite():
85
+ try:
86
+ # wait forever, count on barrier broken event to exit
87
+ barrier.wait()
88
+ barrier_broken.set()
89
+ except Exception as err:
90
+ if stop.is_set():
91
+ return # Ignore error if we should have stopped
92
+ raise err
93
+
94
+ def _watch():
95
+ while not barrier_broken.is_set():
96
+ if stop.is_set():
97
+ with contextlib.suppress(Exception):
98
+ if not barrier.broken:
99
+ barrier.abort()
100
+ break
101
+ time.sleep(poll_interval)
102
+
103
+ try:
104
+ await asyncio.gather(
105
+ asyncio.to_thread(_wait_indefinite),
106
+ asyncio.to_thread(_watch),
107
+ )
108
+ except asyncio.CancelledError:
109
+ stop.set()
110
+ raise
111
+
112
+
113
+ async def wait_for_sync_objects(
114
+ objects: SyncObjectTypesAlias
115
+ | list[SyncObjectTypesAlias]
116
+ | dict[str, SyncObjectTypesAlias],
117
+ poll_interval: float = 0.1,
118
+ ) -> int | str:
119
+ """
120
+ Asynchronously wait for the first synchronization object to complete.
121
+
122
+ This function waits for the first Event to be set or Barrier to be reached
123
+ from a collection of synchronization objects. It returns immediately when
124
+ any object completes and cancels waiting on the remaining objects.
125
+
126
+ :param objects: Single sync object, list of objects, or dict mapping names
127
+ to objects
128
+ :param poll_interval: Time in seconds between polling checks for each object
129
+ :return: Index (for list/single) or key name (for dict) of the first
130
+ completed object
131
+ :raises asyncio.CancelledError: If the async task is canceled
132
+ """
133
+ keys: list[int | str]
134
+ if isinstance(objects, dict):
135
+ keys = list(objects.keys())
136
+ objects = list(objects.values())
137
+ elif isinstance(objects, list):
138
+ keys = list(range(len(objects)))
139
+ else:
140
+ keys = [0]
141
+ objects = [objects]
142
+
143
+ tasks = [
144
+ asyncio.create_task(
145
+ wait_for_sync_barrier(obj, poll_interval)
146
+ if isinstance(obj, ThreadingBarrier | ProcessingBarrier)
147
+ else wait_for_sync_event(obj, poll_interval)
148
+ )
149
+ for obj in objects
150
+ ]
151
+
152
+ done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
153
+
154
+ # Cancel the remaining pending tasks
155
+ for pend in pending:
156
+ pend.cancel()
157
+ await asyncio.gather(*pending, return_exceptions=True)
158
+
159
+ return keys[tasks.index(list(done)[0])]
guidellm/utils/text.py CHANGED
@@ -1,46 +1,107 @@
1
+ """
2
+ Text processing utilities for content manipulation and formatting operations.
3
+
4
+ Provides comprehensive text processing capabilities including cleaning, filtering,
5
+ splitting, loading from various sources, and formatting utilities. Supports loading
6
+ text from URLs, compressed files, package resources, and local files with automatic
7
+ encoding detection. Includes specialized formatting for display values and text
8
+ wrapping operations for consistent presentation across the system.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
1
13
  import gzip
2
14
  import re
3
15
  import textwrap
4
- from importlib.resources import as_file, files # type: ignore[attr-defined]
5
16
  from pathlib import Path
6
- from typing import Any, Optional, Union
17
+ from typing import Any
7
18
 
8
19
  import ftfy
9
20
  import httpx
10
21
  from loguru import logger
11
22
 
12
- from guidellm import data as package_data
13
- from guidellm.config import settings
23
+ from guidellm.settings import settings
24
+ from guidellm.utils.console import Colors
14
25
 
15
26
  __all__ = [
27
+ "MAX_PATH_LENGTH",
16
28
  "EndlessTextCreator",
17
29
  "camelize_str",
18
30
  "clean_text",
19
31
  "filter_text",
20
- "is_puncutation",
32
+ "format_value_display",
33
+ "is_punctuation",
21
34
  "load_text",
22
35
  "split_text",
23
36
  "split_text_list_by_length",
24
37
  ]
25
38
 
26
- MAX_PATH_LENGTH = 4096
39
+ MAX_PATH_LENGTH: int = 4096
40
+
41
+
42
+ def format_value_display(
43
+ value: float,
44
+ label: str,
45
+ units: str = "",
46
+ total_characters: int | None = None,
47
+ digits_places: int | None = None,
48
+ decimal_places: int | None = None,
49
+ ) -> str:
50
+ """
51
+ Format a numeric value with units and label for consistent display output.
52
+
53
+ Creates standardized display strings for metrics and measurements with
54
+ configurable precision, width, and color formatting. Supports both
55
+ fixed-width and variable-width output for tabular displays.
56
+
57
+ :param value: Numeric value to format and display
58
+ :param label: Descriptive label for the value
59
+ :param units: Units string to append after the value
60
+ :param total_characters: Total width for right-aligned output formatting
61
+ :param digits_places: Total number of digits for numeric formatting
62
+ :param decimal_places: Number of decimal places for numeric precision
63
+ :return: Formatted string with value, units, and colored label
64
+ """
65
+ if decimal_places is None and digits_places is None:
66
+ formatted_number = f"{value:.0f}"
67
+ elif digits_places is None:
68
+ formatted_number = f"{value:.{decimal_places}f}"
69
+ elif decimal_places is None:
70
+ formatted_number = f"{value:>{digits_places}f}"
71
+ else:
72
+ formatted_number = f"{value:>{digits_places}.{decimal_places}f}"
73
+
74
+ result = f"{formatted_number}{units} [{Colors.info}]{label}[/{Colors.info}]"
75
+
76
+ if total_characters is not None:
77
+ total_characters += len(Colors.info) * 2 + 5
78
+
79
+ if len(result) < total_characters:
80
+ result = result.rjust(total_characters)
81
+
82
+ return result
27
83
 
28
84
 
29
85
  def split_text_list_by_length(
30
86
  text_list: list[Any],
31
- max_characters: Union[int, list[int]],
87
+ max_characters: int | list[int],
32
88
  pad_horizontal: bool = True,
33
89
  pad_vertical: bool = True,
34
90
  ) -> list[list[str]]:
35
91
  """
36
- Split a list of strings into a list of strings,
37
- each with a maximum length of max_characters
38
-
39
- :param text_list: the list of strings to split
40
- :param max_characters: the maximum length of each string
41
- :param pad_horizontal: whether to pad the strings horizontally, defaults to True
42
- :param pad_vertical: whether to pad the strings vertically, defaults to True
43
- :return: a list of strings
92
+ Split text strings into wrapped lines with specified maximum character limits.
93
+
94
+ Processes each string in the input list by wrapping text to fit within character
95
+ limits, with optional padding for consistent formatting in tabular displays.
96
+ Supports different character limits per string and uniform padding across results.
97
+
98
+ :param text_list: List of strings to process and wrap
99
+ :param max_characters: Maximum characters per line, either single value or
100
+ per-string limits
101
+ :param pad_horizontal: Right-align lines within their character limits
102
+ :param pad_vertical: Pad shorter results to match the longest wrapped result
103
+ :return: List of wrapped line lists, one per input string
104
+ :raises ValueError: If max_characters list length doesn't match text_list length
44
105
  """
45
106
  if not isinstance(max_characters, list):
46
107
  max_characters = [max_characters] * len(text_list)
@@ -76,16 +137,21 @@ def split_text_list_by_length(
76
137
 
77
138
  def filter_text(
78
139
  text: str,
79
- filter_start: Optional[Union[str, int]] = None,
80
- filter_end: Optional[Union[str, int]] = None,
140
+ filter_start: str | int | None = None,
141
+ filter_end: str | int | None = None,
81
142
  ) -> str:
82
143
  """
83
- Filter text by start and end strings or indices
144
+ Extract text substring using start and end markers or indices.
84
145
 
85
- :param text: the text to filter
86
- :param filter_start: the start string or index to filter from
87
- :param filter_end: the end string or index to filter to
88
- :return: the filtered text
146
+ Filters text content by locating string markers or using numeric indices
147
+ to extract specific portions. Supports flexible filtering for content
148
+ extraction and preprocessing operations.
149
+
150
+ :param text: Source text to filter and extract from
151
+ :param filter_start: Starting marker string or index position
152
+ :param filter_end: Ending marker string or index position
153
+ :return: Filtered text substring between specified boundaries
154
+ :raises ValueError: If filter indices are invalid or markers not found
89
155
  """
90
156
  filter_start_index = -1
91
157
  filter_end_index = -1
@@ -113,10 +179,29 @@ def filter_text(
113
179
 
114
180
 
115
181
  def clean_text(text: str) -> str:
182
+ """
183
+ Normalize text by fixing encoding issues and standardizing whitespace.
184
+
185
+ Applies Unicode normalization and whitespace standardization for consistent
186
+ text processing. Removes excessive whitespace and fixes common encoding problems.
187
+
188
+ :param text: Raw text string to clean and normalize
189
+ :return: Cleaned text with normalized encoding and whitespace
190
+ """
116
191
  return re.sub(r"\s+", " ", ftfy.fix_text(text)).strip()
117
192
 
118
193
 
119
194
  def split_text(text: str, split_punctuation: bool = False) -> list[str]:
195
+ """
196
+ Split text into tokens with optional punctuation separation.
197
+
198
+ Tokenizes text into words and optionally separates punctuation marks
199
+ for detailed text analysis and processing operations.
200
+
201
+ :param text: Text string to tokenize and split
202
+ :param split_punctuation: Separate punctuation marks as individual tokens
203
+ :return: List of text tokens
204
+ """
120
205
  text = clean_text(text)
121
206
 
122
207
  if split_punctuation:
@@ -125,16 +210,20 @@ def split_text(text: str, split_punctuation: bool = False) -> list[str]:
125
210
  return text.split()
126
211
 
127
212
 
128
- def load_text(data: Union[str, Path], encoding: Optional[str] = None) -> str:
213
+ def load_text(data: str | Path, encoding: str | None = None) -> str:
129
214
  """
130
- Load an HTML file from a path or URL
131
-
132
- :param data: the path or URL to load the HTML file from
133
- :type data: Union[str, Path]
134
- :param encoding: the encoding to use when reading the file
135
- :type encoding: str
136
- :return: the HTML content
137
- :rtype: str
215
+ Load text content from various sources including URLs, files, and package data.
216
+
217
+ Supports loading from HTTP/FTP URLs, local files, compressed archives, package
218
+ resources, and raw text strings. Automatically detects source type and applies
219
+ appropriate loading strategy with encoding support.
220
+
221
+ :param data: Source location or raw text - URL, file path, package resource
222
+ identifier, or text content
223
+ :param encoding: Character encoding for file reading operations
224
+ :return: Loaded text content as string
225
+ :raises FileNotFoundError: If local file path does not exist
226
+ :raises httpx.HTTPStatusError: If URL request fails
138
227
  """
139
228
  logger.debug("Loading text: {}", data)
140
229
 
@@ -148,15 +237,6 @@ def load_text(data: Union[str, Path], encoding: Optional[str] = None) -> str:
148
237
  response.raise_for_status()
149
238
  return response.text
150
239
 
151
- # check package data
152
- if isinstance(data, str) and data.startswith("data:"):
153
- resource_path = files(package_data).joinpath(data[5:])
154
- with (
155
- as_file(resource_path) as resource_file,
156
- gzip.open(resource_file, "rt", encoding=encoding) as file,
157
- ):
158
- return file.read()
159
-
160
240
  # check gzipped files
161
241
  if isinstance(data, str) and data.endswith(".gz"):
162
242
  with gzip.open(data, "rt", encoding=encoding) as file:
@@ -178,14 +258,15 @@ def load_text(data: Union[str, Path], encoding: Optional[str] = None) -> str:
178
258
  return data.read_text(encoding=encoding)
179
259
 
180
260
 
181
- def is_puncutation(text: str) -> bool:
261
+ def is_punctuation(text: str) -> bool:
182
262
  """
183
- Check if the text is a punctuation
263
+ Check if a single character is a punctuation mark.
264
+
265
+ Identifies punctuation characters by excluding alphanumeric characters
266
+ and whitespace from single-character strings.
184
267
 
185
- :param text: the text to check
186
- :type text: str
187
- :return: True if the text is a punctuation, False otherwise
188
- :rtype: bool
268
+ :param text: Single character string to test
269
+ :return: True if the character is punctuation, False otherwise
189
270
  """
190
271
  return len(text) == 1 and not text.isalnum() and not text.isspace()
191
272
 
@@ -197,25 +278,57 @@ def camelize_str(snake_case_string: str) -> str:
197
278
 
198
279
 
199
280
  class EndlessTextCreator:
281
+ """
282
+ Infinite text generator for load testing and content creation operations.
283
+
284
+ Provides deterministic text generation by cycling through preprocessed word
285
+ tokens from source content. Supports filtering and punctuation handling for
286
+ realistic text patterns in benchmarking scenarios.
287
+
288
+ Example:
289
+ ::
290
+ creator = EndlessTextCreator("path/to/source.txt")
291
+ generated = creator.create_text(start=0, length=100)
292
+ more_text = creator.create_text(start=50, length=200)
293
+ """
294
+
200
295
  def __init__(
201
296
  self,
202
- data: Union[str, Path],
203
- filter_start: Optional[Union[str, int]] = None,
204
- filter_end: Optional[Union[str, int]] = None,
297
+ data: str | Path,
298
+ filter_start: str | int | None = None,
299
+ filter_end: str | int | None = None,
205
300
  ):
301
+ """
302
+ Initialize text creator with source content and optional filtering.
303
+
304
+ :param data: Source text location or content - file path, URL, or raw text
305
+ :param filter_start: Starting marker or index for content filtering
306
+ :param filter_end: Ending marker or index for content filtering
307
+ """
206
308
  self.data = data
207
309
  self.text = load_text(data)
208
310
  self.filtered_text = filter_text(self.text, filter_start, filter_end)
209
311
  self.words = split_text(self.filtered_text, split_punctuation=True)
210
312
 
211
313
  def create_text(self, start: int, length: int) -> str:
314
+ """
315
+ Generate text by cycling through word tokens from the specified position.
316
+
317
+ Creates deterministic text sequences by selecting consecutive tokens from
318
+ the preprocessed word list, wrapping around when reaching the end.
319
+ Maintains proper spacing and punctuation formatting.
320
+
321
+ :param start: Starting position in the token sequence
322
+ :param length: Number of tokens to include in generated text
323
+ :return: Generated text string with proper spacing and punctuation
324
+ """
212
325
  text = ""
213
326
 
214
327
  for counter in range(length):
215
328
  index = (start + counter) % len(self.words)
216
329
  add_word = self.words[index]
217
330
 
218
- if counter != 0 and not is_puncutation(add_word):
331
+ if counter != 0 and not is_punctuation(add_word):
219
332
  text += " "
220
333
 
221
334
  text += add_word
@@ -0,0 +1,41 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterator
4
+ from types import UnionType
5
+ from typing import Annotated, Literal, Union, get_args, get_origin
6
+
7
+ # Backwards compatibility for Python <3.12
8
+ try:
9
+ from typing import TypeAliasType # type: ignore[attr-defined]
10
+ except ImportError:
11
+ from typing_extensions import TypeAliasType
12
+
13
+
14
+ __all__ = ["get_literal_vals"]
15
+
16
+
17
+ def get_literal_vals(alias) -> frozenset[str]:
18
+ """Extract all literal values from a (possibly nested) type alias."""
19
+
20
+ def resolve(alias) -> Iterator[str]:
21
+ origin = get_origin(alias)
22
+
23
+ # Base case: Literal types
24
+ if origin is Literal:
25
+ for literal_val in get_args(alias):
26
+ yield str(literal_val)
27
+ # Unwrap Annotated type
28
+ elif origin is Annotated:
29
+ yield from resolve(get_args(alias)[0])
30
+ # Unwrap TypeAliasTypes
31
+ elif isinstance(alias, TypeAliasType):
32
+ yield from resolve(alias.__value__)
33
+ # Iterate over unions
34
+ elif origin in (Union, UnionType):
35
+ for arg in get_args(alias):
36
+ yield from resolve(arg)
37
+ # Fallback
38
+ else:
39
+ yield str(alias)
40
+
41
+ return frozenset(resolve(alias))
guidellm/version.py CHANGED
@@ -1,4 +1,4 @@
1
- version = "0.1.0a0"
1
+ version = "0.4.0a0"
2
2
  build_type = "nightly"
3
3
  build_iteration = "0"
4
4
  git_commit = "None"
@@ -1,34 +1,57 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: guidellm
3
- Version: 0.4.0a18
3
+ Version: 0.4.0a155
4
4
  Summary: Guidance platform for deploying and managing large language models.
5
5
  Author: Red Hat
6
- License-Expression: Apache-2.0
6
+ License: Apache-2.0
7
7
  Project-URL: homepage, https://github.com/vllm-project/guidellm
8
8
  Project-URL: source, https://github.com/vllm-project/guidellm
9
9
  Project-URL: issues, https://github.com/vllm-project/guidellm/issues
10
10
  Project-URL: docs, https://github.com/vllm-project/guidellm/tree/main/docs
11
11
  Keywords: ai,benchmarking,deep-learning,deployment,evaluation,guidance,inference,language-models,large-language-model,llm,machine-learning,model-benchmark,model-evaluation,nlp,performance,vllm
12
- Requires-Python: <4.0,>=3.9.0
12
+ Requires-Python: <4.0,>=3.10.0
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: click<8.2.0,>=8.0.0
16
+ Requires-Dist: culsans~=0.9.0
16
17
  Requires-Dist: datasets
18
+ Requires-Dist: eval_type_backport
19
+ Requires-Dist: faker
17
20
  Requires-Dist: ftfy>=6.0.0
18
21
  Requires-Dist: httpx[http2]<1.0.0
19
22
  Requires-Dist: loguru
20
- Requires-Dist: numpy
21
- Requires-Dist: pillow
23
+ Requires-Dist: msgpack
24
+ Requires-Dist: numpy>=2.0.0
22
25
  Requires-Dist: protobuf
23
26
  Requires-Dist: pydantic>=2.11.7
24
27
  Requires-Dist: pydantic-settings>=2.0.0
25
28
  Requires-Dist: pyyaml>=6.0.0
26
29
  Requires-Dist: rich
30
+ Requires-Dist: sanic
27
31
  Requires-Dist: transformers
32
+ Requires-Dist: uvloop>=0.18
33
+ Requires-Dist: torch
34
+ Provides-Extra: all
35
+ Requires-Dist: guidellm[audio,openai,perf,vision]; extra == "all"
28
36
  Provides-Extra: recommended
29
- Requires-Dist: tiktoken>=0.11.0; extra == "recommended"
30
- Requires-Dist: blobfile>=3.1.0; extra == "recommended"
37
+ Requires-Dist: guidellm[openai,perf]; extra == "recommended"
38
+ Provides-Extra: perf
39
+ Requires-Dist: orjson; extra == "perf"
40
+ Requires-Dist: msgpack; extra == "perf"
41
+ Requires-Dist: msgspec; extra == "perf"
42
+ Requires-Dist: uvloop; extra == "perf"
43
+ Provides-Extra: openai
44
+ Requires-Dist: tiktoken>=0.11.0; extra == "openai"
45
+ Requires-Dist: blobfile>=3.1.0; extra == "openai"
46
+ Provides-Extra: audio
47
+ Requires-Dist: datasets[audio]>=4.1.0; extra == "audio"
48
+ Requires-Dist: torch==2.9.*; extra == "audio"
49
+ Requires-Dist: torchcodec==0.8; extra == "audio"
50
+ Provides-Extra: vision
51
+ Requires-Dist: datasets[vision]; extra == "vision"
52
+ Requires-Dist: pillow; extra == "vision"
31
53
  Provides-Extra: dev
54
+ Requires-Dist: guidellm[all]; extra == "dev"
32
55
  Requires-Dist: build>=1.0.0; extra == "dev"
33
56
  Requires-Dist: setuptools>=61.0; extra == "dev"
34
57
  Requires-Dist: setuptools-git-versioning<3,>=2.0; extra == "dev"
@@ -38,7 +61,7 @@ Requires-Dist: sphinx~=7.1.2; extra == "dev"
38
61
  Requires-Dist: tox~=4.16.0; extra == "dev"
39
62
  Requires-Dist: lorem~=0.1.1; extra == "dev"
40
63
  Requires-Dist: pytest~=8.2.2; extra == "dev"
41
- Requires-Dist: pytest-asyncio~=0.23.8; extra == "dev"
64
+ Requires-Dist: pytest-asyncio~=1.1.0; extra == "dev"
42
65
  Requires-Dist: pytest-cov~=5.0.0; extra == "dev"
43
66
  Requires-Dist: pytest-mock~=3.14.0; extra == "dev"
44
67
  Requires-Dist: pytest-rerunfailures~=14.0; extra == "dev"
@@ -66,7 +89,7 @@ Dynamic: license-file
66
89
  Scale Efficiently: Evaluate and Optimize Your LLM Deployments for Real-World Inference
67
90
  </h3>
68
91
 
69
- [![GitHub Release](https://img.shields.io/github/release/vllm-project/guidellm.svg?label=Version)](https://github.com/vllm-project/guidellm/releases) [![Documentation](https://img.shields.io/badge/Documentation-8A2BE2?logo=read-the-docs&logoColor=%23ffffff&color=%231BC070)](https://github.com/vllm-project/guidellm/tree/main/docs) [![License](https://img.shields.io/github/license/vllm-project/guidellm.svg)](https://github.com/vllm-project/guidellm/blob/main/LICENSE) [![PyPI Release](https://img.shields.io/pypi/v/guidellm.svg?label=PyPI%20Release)](https://pypi.python.org/pypi/guidellm) [![Python Versions](https://img.shields.io/badge/Python-3.9--3.13-orange)](https://pypi.python.org/pypi/guidellm) [![Nightly Build](https://img.shields.io/github/actions/workflow/status/vllm-project/guidellm/nightly.yml?branch=main&label=Nightly%20Build)](https://github.com/vllm-project/guidellm/actions/workflows/nightly.yml)
92
+ [![GitHub Release](https://img.shields.io/github/release/vllm-project/guidellm.svg?label=Version)](https://github.com/vllm-project/guidellm/releases) [![Documentation](https://img.shields.io/badge/Documentation-8A2BE2?logo=read-the-docs&logoColor=%23ffffff&color=%231BC070)](https://github.com/vllm-project/guidellm/tree/main/docs) [![License](https://img.shields.io/github/license/vllm-project/guidellm.svg)](https://github.com/vllm-project/guidellm/blob/main/LICENSE) [![PyPI Release](https://img.shields.io/pypi/v/guidellm.svg?label=PyPI%20Release)](https://pypi.python.org/pypi/guidellm) [![Python Versions](https://img.shields.io/badge/Python-3.10--3.13-orange)](https://pypi.python.org/pypi/guidellm) [![Nightly Build](https://img.shields.io/github/actions/workflow/status/vllm-project/guidellm/nightly.yml?branch=main&label=Nightly%20Build)](https://github.com/vllm-project/guidellm/actions/workflows/nightly.yml)
70
93
 
71
94
  ## Overview
72
95
 
@@ -93,7 +116,7 @@ Scale Efficiently: Evaluate and Optimize Your LLM Deployments for Real-World Inf
93
116
  Before installing, ensure you have the following prerequisites:
94
117
 
95
118
  - OS: Linux or MacOS
96
- - Python: 3.9 – 3.13
119
+ - Python: 3.10 – 3.13
97
120
 
98
121
  The latest GuideLLM release can be installed using pip:
99
122