guidellm 0.4.0a21__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.0a21.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.0a21.dist-info/RECORD +0 -62
  113. {guidellm-0.4.0a21.dist-info → guidellm-0.4.0a155.dist-info}/WHEEL +0 -0
  114. {guidellm-0.4.0a21.dist-info → guidellm-0.4.0a155.dist-info}/entry_points.txt +0 -0
  115. {guidellm-0.4.0a21.dist-info → guidellm-0.4.0a155.dist-info}/licenses/LICENSE +0 -0
  116. {guidellm-0.4.0a21.dist-info → guidellm-0.4.0a155.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,220 @@
1
+ """
2
+ Registry system for dynamic object registration and discovery.
3
+
4
+ Provides a flexible object registration system with optional auto-discovery
5
+ capabilities through decorators and module imports. Enables dynamic discovery
6
+ and instantiation of implementations based on configuration parameters, supporting
7
+ both manual registration and automatic package-based discovery for extensible
8
+ plugin architectures.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from collections.abc import Callable
14
+ from typing import ClassVar, Generic, TypeVar, cast
15
+
16
+ from guidellm.utils.auto_importer import AutoImporterMixin
17
+
18
+ __all__ = ["RegisterT", "RegistryMixin", "RegistryObjT"]
19
+
20
+
21
+ RegistryObjT = TypeVar("RegistryObjT")
22
+ """Generic type variable for objects managed by the registry system."""
23
+ RegisterT = TypeVar(
24
+ "RegisterT", bound=type
25
+ ) # Must be bound to type to ensure __name__ is available.
26
+ """Generic type variable for the args and return values within the registry."""
27
+
28
+
29
+ class RegistryMixin(Generic[RegistryObjT], AutoImporterMixin):
30
+ """
31
+ Generic mixin for creating object registries with optional auto-discovery.
32
+
33
+ Enables classes to maintain separate registries of objects that can be dynamically
34
+ discovered and instantiated through decorators and module imports. Supports both
35
+ manual registration via decorators and automatic discovery through package scanning
36
+ for extensible plugin architectures.
37
+
38
+ Example:
39
+ ::
40
+ class BaseAlgorithm(RegistryMixin):
41
+ pass
42
+
43
+ @BaseAlgorithm.register()
44
+ class ConcreteAlgorithm(BaseAlgorithm):
45
+ pass
46
+
47
+ @BaseAlgorithm.register("custom_name")
48
+ class AnotherAlgorithm(BaseAlgorithm):
49
+ pass
50
+
51
+ # Get all registered implementations
52
+ algorithms = BaseAlgorithm.registered_objects()
53
+
54
+ Example with auto-discovery:
55
+ ::
56
+ class TokenProposal(RegistryMixin):
57
+ registry_auto_discovery = True
58
+ auto_package = "mypackage.proposals"
59
+
60
+ # Automatically imports and registers decorated objects
61
+ proposals = TokenProposal.registered_objects()
62
+
63
+ :cvar registry: Dictionary mapping names to registered objects
64
+ :cvar registry_auto_discovery: Enable automatic package-based discovery
65
+ :cvar registry_populated: Track whether auto-discovery has completed
66
+ """
67
+
68
+ registry: ClassVar[dict[str, RegistryObjT] | None] = None # type: ignore[misc]
69
+ registry_auto_discovery: ClassVar[bool] = False
70
+ registry_populated: ClassVar[bool] = False
71
+
72
+ @classmethod
73
+ def register(
74
+ cls, name: str | list[str] | None = None
75
+ ) -> Callable[[RegisterT], RegisterT]:
76
+ """
77
+ Decorator for registering objects with the registry.
78
+
79
+ :param name: Optional name(s) to register the object under.
80
+ If None, uses the object's __name__ attribute
81
+ :return: Decorator function that registers the decorated object
82
+ :raises ValueError: If name is not a string, list of strings, or None
83
+ """
84
+
85
+ def _decorator(obj: RegisterT) -> RegisterT:
86
+ cls.register_decorator(obj, name=name)
87
+ return obj
88
+
89
+ return _decorator
90
+
91
+ @classmethod
92
+ def register_decorator(
93
+ cls, obj: RegisterT, name: str | list[str] | None = None
94
+ ) -> RegisterT:
95
+ """
96
+ Register an object directly with the registry.
97
+
98
+ :param obj: The object to register
99
+ :param name: Optional name(s) to register the object under.
100
+ If None, uses the object's __name__ attribute
101
+ :return: The registered object
102
+ :raises ValueError: If the object is already registered or name is invalid
103
+ """
104
+
105
+ if name is None:
106
+ name = obj.__name__
107
+ elif not isinstance(name, str | list):
108
+ raise ValueError(
109
+ "RegistryMixin.register_decorator name must be a string or "
110
+ f"an iterable of strings. Got {name}."
111
+ )
112
+
113
+ if cls.registry is None:
114
+ cls.registry = {}
115
+
116
+ names = [name] if isinstance(name, str) else list(name)
117
+
118
+ for register_name in names:
119
+ if not isinstance(register_name, str):
120
+ raise ValueError(
121
+ "RegistryMixin.register_decorator name must be a string or "
122
+ f"a list of strings. Got {register_name}."
123
+ )
124
+
125
+ if register_name in cls.registry:
126
+ raise ValueError(
127
+ f"RegistryMixin.register_decorator cannot register an object "
128
+ f"{obj} with the name {register_name} because it is already "
129
+ "registered."
130
+ )
131
+
132
+ cls.registry[register_name] = cast("RegistryObjT", obj)
133
+
134
+ return obj
135
+
136
+ @classmethod
137
+ def auto_populate_registry(cls) -> bool:
138
+ """
139
+ Import and register all modules from the auto_package.
140
+
141
+ Automatically called by registered_objects when registry_auto_discovery is True
142
+ to ensure all available implementations are discovered.
143
+
144
+ :return: True if registry was populated, False if already populated
145
+ :raises ValueError: If called when registry_auto_discovery is False
146
+ """
147
+ if not cls.registry_auto_discovery:
148
+ raise ValueError(
149
+ "RegistryMixin.auto_populate_registry() cannot be called "
150
+ "because registry_auto_discovery is set to False. "
151
+ "Set registry_auto_discovery to True to enable auto-discovery."
152
+ )
153
+
154
+ if cls.registry_populated:
155
+ return False
156
+
157
+ cls.auto_import_package_modules()
158
+ cls.registry_populated = True
159
+
160
+ return True
161
+
162
+ @classmethod
163
+ def registered_objects(cls) -> tuple[RegistryObjT, ...]:
164
+ """
165
+ Get all registered objects from the registry.
166
+
167
+ Automatically triggers auto-discovery if registry_auto_discovery is enabled
168
+ to ensure all available implementations are included.
169
+
170
+ :return: Tuple of all registered objects including auto-discovered ones
171
+ :raises ValueError: If called before any objects have been registered
172
+ """
173
+ if cls.registry_auto_discovery:
174
+ cls.auto_populate_registry()
175
+
176
+ if cls.registry is None:
177
+ raise ValueError(
178
+ "RegistryMixin.registered_objects() must be called after "
179
+ "registering objects with RegistryMixin.register()."
180
+ )
181
+
182
+ return tuple(cls.registry.values())
183
+
184
+ @classmethod
185
+ def is_registered(cls, name: str) -> bool:
186
+ """
187
+ Check if an object is registered under the given name.
188
+ It matches first by exact name, then by str.lower().
189
+
190
+ :param name: The name to check for registration.
191
+ :return: True if the object is registered, False otherwise.
192
+ """
193
+ if cls.registry is None:
194
+ return False
195
+
196
+ return name in cls.registry or name.lower() in [
197
+ key.lower() for key in cls.registry
198
+ ]
199
+
200
+ @classmethod
201
+ def get_registered_object(cls, name: str) -> RegistryObjT | None:
202
+ """
203
+ Get a registered object by its name. It matches first by exact name,
204
+ then by str.lower().
205
+
206
+ :param name: The name of the registered object.
207
+ :return: The registered object if found, None otherwise.
208
+ """
209
+ if cls.registry is None:
210
+ return None
211
+
212
+ if name in cls.registry:
213
+ return cls.registry[name]
214
+
215
+ name_casefold = name.lower()
216
+ for k, v in cls.registry.items():
217
+ if name_casefold == k.lower():
218
+ return v
219
+
220
+ return None # Not found
@@ -0,0 +1,133 @@
1
+ """
2
+ Singleton pattern implementations for ensuring single instance classes.
3
+
4
+ Provides singleton mixins for creating classes that maintain a single instance
5
+ throughout the application lifecycle, with support for both basic and thread-safe
6
+ implementations. These mixins integrate with the scheduler and other system components
7
+ to ensure consistent state management and prevent duplicate resource allocation.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import threading
13
+
14
+ __all__ = ["SingletonMixin", "ThreadSafeSingletonMixin"]
15
+
16
+
17
+ class SingletonMixin:
18
+ """
19
+ Basic singleton mixin ensuring single instance per class.
20
+
21
+ Implements the singleton pattern using class variables to control instance
22
+ creation. Subclasses must call super().__init__() for proper initialization
23
+ state management. Suitable for single-threaded environments or when external
24
+ synchronization is provided.
25
+
26
+ Example:
27
+ ::
28
+ class ConfigManager(SingletonMixin):
29
+ def __init__(self, config_path: str):
30
+ super().__init__()
31
+ if not self.initialized:
32
+ self.config = load_config(config_path)
33
+
34
+ manager1 = ConfigManager("config.json")
35
+ manager2 = ConfigManager("config.json")
36
+ assert manager1 is manager2
37
+ """
38
+
39
+ _singleton_initialized: bool
40
+ _init_lock: threading.Lock
41
+
42
+ def __new__(cls, *args, **kwargs): # noqa: ARG004
43
+ """
44
+ Create or return the singleton instance.
45
+
46
+ :param args: Positional arguments passed to the constructor
47
+ :param kwargs: Keyword arguments passed to the constructor
48
+ :return: The singleton instance of the class
49
+ """
50
+ # Use class-specific attribute name to avoid inheritance issues
51
+ attr_name = f"_singleton_instance_{cls.__name__}"
52
+
53
+ if not hasattr(cls, attr_name) or getattr(cls, attr_name) is None:
54
+ instance = super().__new__(cls)
55
+ setattr(cls, attr_name, instance)
56
+ instance._singleton_initialized = False
57
+ return getattr(cls, attr_name)
58
+
59
+ def __init__(self):
60
+ """Initialize the singleton instance exactly once."""
61
+ if hasattr(self, "_singleton_initialized") and self._singleton_initialized:
62
+ return
63
+ self._singleton_initialized = True
64
+
65
+ @property
66
+ def initialized(self):
67
+ """Return True if the singleton has been initialized."""
68
+ return getattr(self, "_singleton_initialized", False)
69
+
70
+
71
+ class ThreadSafeSingletonMixin(SingletonMixin):
72
+ """
73
+ Thread-safe singleton mixin with locking mechanisms.
74
+
75
+ Extends SingletonMixin with thread safety using locks to prevent race
76
+ conditions during instance creation in multi-threaded environments. Essential
77
+ for scheduler components and other shared resources accessed concurrently.
78
+
79
+ Example:
80
+ ::
81
+ class SchedulerResource(ThreadSafeSingletonMixin):
82
+ def __init__(self):
83
+ super().__init__()
84
+ if not self.initialized:
85
+ self.resource_pool = initialize_resources()
86
+ """
87
+
88
+ def __new__(cls, *args, **kwargs): # noqa: ARG004
89
+ """
90
+ Create or return the singleton instance with thread safety.
91
+
92
+ :param args: Positional arguments passed to the constructor
93
+ :param kwargs: Keyword arguments passed to the constructor
94
+ :return: The singleton instance of the class
95
+ """
96
+ # Use class-specific lock and instance names to avoid inheritance issues
97
+ lock_attr_name = f"_singleton_lock_{cls.__name__}"
98
+ instance_attr_name = f"_singleton_instance_{cls.__name__}"
99
+
100
+ with getattr(cls, lock_attr_name):
101
+ instance_exists = (
102
+ hasattr(cls, instance_attr_name)
103
+ and getattr(cls, instance_attr_name) is not None
104
+ )
105
+ if not instance_exists:
106
+ instance = super(SingletonMixin, cls).__new__(cls)
107
+ setattr(cls, instance_attr_name, instance)
108
+ instance._singleton_initialized = False
109
+ instance._init_lock = threading.Lock()
110
+ return getattr(cls, instance_attr_name)
111
+
112
+ def __init_subclass__(cls, *args, **kwargs):
113
+ super().__init_subclass__(*args, **kwargs)
114
+ lock_attr_name = f"_singleton_lock_{cls.__name__}"
115
+ setattr(cls, lock_attr_name, threading.Lock())
116
+
117
+ def __init__(self):
118
+ """Initialize the singleton instance with thread-safe initialization."""
119
+ with self._init_lock:
120
+ if hasattr(self, "_singleton_initialized") and self._singleton_initialized:
121
+ return
122
+ self._singleton_initialized = True
123
+
124
+ @property
125
+ def thread_lock(self):
126
+ """Return the thread lock for this singleton instance."""
127
+ return getattr(self, "_init_lock", None)
128
+
129
+ @classmethod
130
+ def get_singleton_lock(cls):
131
+ """Get the class-specific singleton creation lock."""
132
+ lock_attr_name = f"_singleton_lock_{cls.__name__}"
133
+ return getattr(cls, lock_attr_name, None)