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.
- guidellm/__init__.py +5 -2
- guidellm/__main__.py +451 -252
- guidellm/backends/__init__.py +33 -0
- guidellm/backends/backend.py +110 -0
- guidellm/backends/openai.py +355 -0
- guidellm/backends/response_handlers.py +455 -0
- guidellm/benchmark/__init__.py +53 -39
- guidellm/benchmark/benchmarker.py +148 -317
- guidellm/benchmark/entrypoints.py +466 -128
- guidellm/benchmark/output.py +517 -771
- guidellm/benchmark/profile.py +580 -280
- guidellm/benchmark/progress.py +568 -549
- guidellm/benchmark/scenarios/__init__.py +40 -0
- guidellm/benchmark/scenarios/chat.json +6 -0
- guidellm/benchmark/scenarios/rag.json +6 -0
- guidellm/benchmark/schemas.py +2085 -0
- guidellm/data/__init__.py +28 -4
- guidellm/data/collators.py +16 -0
- guidellm/data/deserializers/__init__.py +53 -0
- guidellm/data/deserializers/deserializer.py +109 -0
- guidellm/data/deserializers/file.py +222 -0
- guidellm/data/deserializers/huggingface.py +94 -0
- guidellm/data/deserializers/memory.py +192 -0
- guidellm/data/deserializers/synthetic.py +346 -0
- guidellm/data/loaders.py +145 -0
- guidellm/data/preprocessors/__init__.py +25 -0
- guidellm/data/preprocessors/formatters.py +412 -0
- guidellm/data/preprocessors/mappers.py +198 -0
- guidellm/data/preprocessors/preprocessor.py +29 -0
- guidellm/data/processor.py +30 -0
- guidellm/data/schemas.py +13 -0
- guidellm/data/utils/__init__.py +10 -0
- guidellm/data/utils/dataset.py +94 -0
- guidellm/data/utils/functions.py +18 -0
- guidellm/extras/__init__.py +4 -0
- guidellm/extras/audio.py +215 -0
- guidellm/extras/vision.py +242 -0
- guidellm/logger.py +2 -2
- guidellm/mock_server/__init__.py +8 -0
- guidellm/mock_server/config.py +84 -0
- guidellm/mock_server/handlers/__init__.py +17 -0
- guidellm/mock_server/handlers/chat_completions.py +280 -0
- guidellm/mock_server/handlers/completions.py +280 -0
- guidellm/mock_server/handlers/tokenizer.py +142 -0
- guidellm/mock_server/models.py +510 -0
- guidellm/mock_server/server.py +168 -0
- guidellm/mock_server/utils.py +302 -0
- guidellm/preprocess/dataset.py +23 -26
- guidellm/presentation/builder.py +2 -2
- guidellm/presentation/data_models.py +25 -21
- guidellm/presentation/injector.py +2 -3
- guidellm/scheduler/__init__.py +65 -26
- guidellm/scheduler/constraints.py +1035 -0
- guidellm/scheduler/environments.py +252 -0
- guidellm/scheduler/scheduler.py +140 -368
- guidellm/scheduler/schemas.py +272 -0
- guidellm/scheduler/strategies.py +519 -0
- guidellm/scheduler/worker.py +391 -420
- guidellm/scheduler/worker_group.py +707 -0
- guidellm/schemas/__init__.py +31 -0
- guidellm/schemas/info.py +159 -0
- guidellm/schemas/request.py +216 -0
- guidellm/schemas/response.py +119 -0
- guidellm/schemas/stats.py +228 -0
- guidellm/{config.py → settings.py} +32 -21
- guidellm/utils/__init__.py +95 -8
- guidellm/utils/auto_importer.py +98 -0
- guidellm/utils/cli.py +46 -2
- guidellm/utils/console.py +183 -0
- guidellm/utils/encoding.py +778 -0
- guidellm/utils/functions.py +134 -0
- guidellm/utils/hf_datasets.py +1 -2
- guidellm/utils/hf_transformers.py +4 -4
- guidellm/utils/imports.py +9 -0
- guidellm/utils/messaging.py +1118 -0
- guidellm/utils/mixins.py +115 -0
- guidellm/utils/pydantic_utils.py +411 -0
- guidellm/utils/random.py +3 -4
- guidellm/utils/registry.py +220 -0
- guidellm/utils/singleton.py +133 -0
- guidellm/{objects → utils}/statistics.py +341 -247
- guidellm/utils/synchronous.py +159 -0
- guidellm/utils/text.py +163 -50
- guidellm/utils/typing.py +41 -0
- guidellm/version.py +1 -1
- {guidellm-0.4.0a18.dist-info → guidellm-0.4.0a155.dist-info}/METADATA +33 -10
- guidellm-0.4.0a155.dist-info/RECORD +96 -0
- guidellm/backend/__init__.py +0 -23
- guidellm/backend/backend.py +0 -259
- guidellm/backend/openai.py +0 -705
- guidellm/backend/response.py +0 -136
- guidellm/benchmark/aggregator.py +0 -760
- guidellm/benchmark/benchmark.py +0 -837
- guidellm/benchmark/scenario.py +0 -104
- guidellm/data/prideandprejudice.txt.gz +0 -0
- guidellm/dataset/__init__.py +0 -22
- guidellm/dataset/creator.py +0 -213
- guidellm/dataset/entrypoints.py +0 -42
- guidellm/dataset/file.py +0 -92
- guidellm/dataset/hf_datasets.py +0 -62
- guidellm/dataset/in_memory.py +0 -132
- guidellm/dataset/synthetic.py +0 -287
- guidellm/objects/__init__.py +0 -18
- guidellm/objects/pydantic.py +0 -89
- guidellm/request/__init__.py +0 -18
- guidellm/request/loader.py +0 -284
- guidellm/request/request.py +0 -79
- guidellm/request/types.py +0 -10
- guidellm/scheduler/queues.py +0 -25
- guidellm/scheduler/result.py +0 -155
- guidellm/scheduler/strategy.py +0 -495
- guidellm-0.4.0a18.dist-info/RECORD +0 -62
- {guidellm-0.4.0a18.dist-info → guidellm-0.4.0a155.dist-info}/WHEEL +0 -0
- {guidellm-0.4.0a18.dist-info → guidellm-0.4.0a155.dist-info}/entry_points.txt +0 -0
- {guidellm-0.4.0a18.dist-info → guidellm-0.4.0a155.dist-info}/licenses/LICENSE +0 -0
- {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
|
|
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
|
|
13
|
-
from guidellm.
|
|
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
|
-
"
|
|
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:
|
|
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
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
:param
|
|
43
|
-
:
|
|
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:
|
|
80
|
-
filter_end:
|
|
140
|
+
filter_start: str | int | None = None,
|
|
141
|
+
filter_end: str | int | None = None,
|
|
81
142
|
) -> str:
|
|
82
143
|
"""
|
|
83
|
-
|
|
144
|
+
Extract text substring using start and end markers or indices.
|
|
84
145
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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:
|
|
213
|
+
def load_text(data: str | Path, encoding: str | None = None) -> str:
|
|
129
214
|
"""
|
|
130
|
-
Load
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
:
|
|
137
|
-
|
|
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
|
|
261
|
+
def is_punctuation(text: str) -> bool:
|
|
182
262
|
"""
|
|
183
|
-
Check if
|
|
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:
|
|
186
|
-
:
|
|
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:
|
|
203
|
-
filter_start:
|
|
204
|
-
filter_end:
|
|
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
|
|
331
|
+
if counter != 0 and not is_punctuation(add_word):
|
|
219
332
|
text += " "
|
|
220
333
|
|
|
221
334
|
text += add_word
|
guidellm/utils/typing.py
ADDED
|
@@ -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,34 +1,57 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: guidellm
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.0a155
|
|
4
4
|
Summary: Guidance platform for deploying and managing large language models.
|
|
5
5
|
Author: Red Hat
|
|
6
|
-
License
|
|
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.
|
|
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:
|
|
21
|
-
Requires-Dist:
|
|
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:
|
|
30
|
-
|
|
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~=
|
|
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
|
-
[](https://github.com/vllm-project/guidellm/releases) [](https://github.com/vllm-project/guidellm/tree/main/docs) [](https://github.com/vllm-project/guidellm/blob/main/LICENSE) [](https://pypi.python.org/pypi/guidellm) [](https://github.com/vllm-project/guidellm/releases) [](https://github.com/vllm-project/guidellm/tree/main/docs) [](https://github.com/vllm-project/guidellm/blob/main/LICENSE) [](https://pypi.python.org/pypi/guidellm) [](https://pypi.python.org/pypi/guidellm) [](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.
|
|
119
|
+
- Python: 3.10 – 3.13
|
|
97
120
|
|
|
98
121
|
The latest GuideLLM release can be installed using pip:
|
|
99
122
|
|