From a98c5f01b5d093d95c463da72f2e230c09818aa2 Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 11:40:12 +0800 Subject: [PATCH 01/14] test(contract): refresh client_api_baseline before execution-guarantees work T0.1: capture current HEAD client-facing surface so the post-refactor comparison (T8.1) shows only this spec's changes. No code changes. --- .../server/contract/client_api_baseline.json | 66 ++++--------------- 1 file changed, 11 insertions(+), 55 deletions(-) diff --git a/tests/server/contract/client_api_baseline.json b/tests/server/contract/client_api_baseline.json index 65f9db14..61f0c48a 100644 --- a/tests/server/contract/client_api_baseline.json +++ b/tests/server/contract/client_api_baseline.json @@ -1,48 +1,4 @@ { - "data_plane": { - "paths": { - "/twinkle/append": { - "POST": { - "operationId": "append_twinkle_append_post", - "parameters": [], - "responses": [ - "200", - "422" - ] - } - }, - "/twinkle/get": { - "POST": { - "operationId": "get_twinkle_get_post", - "parameters": [], - "responses": [ - "200", - "422" - ] - } - }, - "/twinkle/put": { - "POST": { - "operationId": "put_twinkle_put_post", - "parameters": [], - "responses": [ - "200", - "422" - ] - } - }, - "/twinkle/release": { - "POST": { - "operationId": "release_twinkle_release_post", - "parameters": [], - "responses": [ - "200", - "422" - ] - } - } - } - }, "gateway": { "paths": { "/asample": { @@ -580,7 +536,7 @@ "paths": { "/healthz": { "GET": { - "operationId": "healthz_healthz_get", + "operationId": "model_healthz_healthz_get", "parameters": [], "responses": [ "200" @@ -777,9 +733,9 @@ ] } }, - "/twinkle/forward_from_data_plane": { + "/twinkle/forward_backward": { "POST": { - "operationId": "forward_from_data_plane_twinkle_forward_from_data_plane_post", + "operationId": "forward_backward_twinkle_forward_backward_post", "parameters": [], "responses": [ "200", @@ -787,9 +743,9 @@ ] } }, - "/twinkle/forward_backward": { + "/twinkle/forward_backward_from_data_plane": { "POST": { - "operationId": "forward_backward_twinkle_forward_backward_post", + "operationId": "forward_backward_from_data_plane_twinkle_forward_backward_from_data_plane_post", "parameters": [], "responses": [ "200", @@ -797,9 +753,9 @@ ] } }, - "/twinkle/forward_backward_from_data_plane": { + "/twinkle/forward_from_data_plane": { "POST": { - "operationId": "forward_backward_from_data_plane_twinkle_forward_backward_from_data_plane_post", + "operationId": "forward_from_data_plane_twinkle_forward_from_data_plane_post", "parameters": [], "responses": [ "200", @@ -1074,9 +1030,9 @@ ] } }, - "/twinkle/sample_to_data_plane": { + "/twinkle/sample_stream": { "POST": { - "operationId": "sample_to_data_plane_twinkle_sample_to_data_plane_post", + "operationId": "sample_stream_twinkle_sample_stream_post", "parameters": [], "responses": [ "200", @@ -1084,9 +1040,9 @@ ] } }, - "/twinkle/sample_stream": { + "/twinkle/sample_to_data_plane": { "POST": { - "operationId": "sample_stream_twinkle_sample_stream_post", + "operationId": "sample_to_data_plane_twinkle_sample_to_data_plane_post", "parameters": [], "responses": [ "200", From c35978936b7e4cd4c0c21ef4bdc5aa756da147b8 Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 11:52:39 +0800 Subject: [PATCH 02/14] feat(infra): establish Sync_Dispatch_Path time bound (Phase 1, T1.1-T1.6) - execute_all_sync forwards timeout to ray.get (T1.1) - resolve effective ray.get timeout before choosing execute_method and flip priority to 'decorator wins, instance is fallback' at both dispatch sites; fix the 0-treated-as-falsy trap; bound __len__/__next__ bare ray.get (T1.2, T1.5) - decorator timeout=10 on ping; timeout=3600 on save/add_adapter_to_model/ resume_from_checkpoint/tinker_load/load_full_weights_from_path (T1.3) - TaskQueueConfig default execution_timeout 120->1800; effective_execution_timeout (0 -> 3600) as the single bound source; startup warning on 0 (T1.4) - infra unit tests, no GPU/Megatron/server deps (T1.6) --- src/twinkle/infra/__init__.py | 21 ++-- src/twinkle/infra/_ray/ray_helper.py | 15 ++- src/twinkle/model/megatron/megatron.py | 4 +- .../model/megatron/multi_lora_megatron.py | 6 +- .../model/transformers/transformers.py | 2 +- .../sampler/vllm_sampler/vllm_sampler.py | 2 +- .../server/model/backends/megatron_model.py | 4 +- .../server/model/backends/mock_model.py | 2 +- .../model/backends/transformers_model.py | 2 +- src/twinkle/server/utils/task_queue/config.py | 23 +++- src/twinkle/server/utils/task_queue/mixin.py | 4 + src/twinkle/server/utils/task_queue/worker.py | 9 +- tests/infra/test_ray_get_timeout.py | 116 ++++++++++++++++++ 13 files changed, 182 insertions(+), 28 deletions(-) create mode 100644 tests/infra/test_ray_get_timeout.py diff --git a/src/twinkle/infra/__init__.py b/src/twinkle/infra/__init__.py index 4758b341..3a80219b 100644 --- a/src/twinkle/infra/__init__.py +++ b/src/twinkle/infra/__init__.py @@ -996,7 +996,10 @@ def remote_function(dispatch: Union[Literal['slice', 'all', 'slice_dp', 'last_pp sync: If True, use synchronous execution (execute_all_sync) instead of async. Required for methods with NCCL collective operations (e.g., Megatron forward_backward). lazy_collect: Do lazy collect, this boolean value decides whether this function needs lazy collect. If setting to None, it will follow the global setting. - timeout: Timeout in seconds for ray.get() when collecting results. Instance attribute ``_ray_get_timeout`` overrides this. + timeout: Timeout in seconds for ray.get() when collecting results. The decorator's + explicitly declared value takes priority; the instance attribute ``_ray_get_timeout`` + is the fallback for methods that declare none (``timeout if timeout is not None + else instance``). enable_continous_work: Route each request to the least busy worker instead of slicing the batch over all of them, and return the results in the caller's order. This is what lets a batch smaller than the worker @@ -1044,7 +1047,13 @@ def wrapper(self, *args, **kwargs) -> T1: else: # This is the driver from ._ray import RayHelper - execute_method = RayHelper.execute_all_async if not sync else RayHelper.execute_all_sync + # Resolve the effective ray.get timeout before choosing execute_method: + # the decorator's explicit value wins, the instance attribute is the + # fallback. ``is not None`` (not ``or``) so that a decorator ``timeout=0`` + # is honored instead of falling back to unbounded waiting. + _rgt = timeout if timeout is not None else getattr(self, '_ray_get_timeout', None) + execute_method = RayHelper.execute_all_async if not sync else functools.partial( + RayHelper.execute_all_sync, timeout=_rgt) # Only classes whose workers run methods side by side need # this; elsewhere Ray already orders calls per actor. _concurrent_actor = bool(getattr(self, '_max_concurrency', None)) @@ -1060,8 +1069,7 @@ def wrapper(self, *args, **kwargs) -> T1: _batch_len = _cw_batch_len(args, kwargs) if _batch_len: return _run_continous_work(self, func.__name__, execute_method, _workers, args, kwargs, - _batch_len, - getattr(self, '_ray_get_timeout', None) or timeout) + _batch_len, _rgt) if RayHelper.has_ref(args, kwargs): # If has any object-ref, dispatch in worker, because we don't know the structure in the ref. # for example, dataloader returns any data list. @@ -1079,7 +1087,6 @@ def wrapper(self, *args, **kwargs) -> T1: # busy. _tracked_refs = _cw_register(self, func.__name__, result) if _concurrent_actor else [] # This is a result future, call it to get the actual result - _rgt = getattr(self, '_ray_get_timeout', None) or timeout result_func = RayHelper.do_get_and_collect_func( _collect_func, collect, result, device_mesh, timeout=_rgt) _local_lazy_collect = _lazy_collect @@ -1090,13 +1097,13 @@ def wrapper(self, *args, **kwargs) -> T1: if func.__name__ == '__len__': # Get the first result and ignore the `lazy_collect` import ray - return ray.get(result[0]) + return ray.get(result[0], timeout=_rgt) if func.__name__ == '__next__': import ray for _res in result: # raise when any worker raises StopIteration - stop = ray.get(_res[1]) + stop = ray.get(_res[1], timeout=_rgt) if stop: raise StopIteration() result = [_res[0] for _res in result] diff --git a/src/twinkle/infra/_ray/ray_helper.py b/src/twinkle/infra/_ray/ray_helper.py index ffd4e1a4..d3cbc3f5 100644 --- a/src/twinkle/infra/_ray/ray_helper.py +++ b/src/twinkle/infra/_ray/ray_helper.py @@ -137,10 +137,19 @@ def is_worker(): return RayHelper.ray_inited() and ray._private.worker.global_worker.mode == ray._private.worker.WORKER_MODE @staticmethod - def execute_all_sync(method_name: str, workers_and_args: List[Tuple[Any, List[Any], Dict[str, Any]]]): - """Execute method and return results.""" + def execute_all_sync(method_name: str, + workers_and_args: List[Tuple[Any, List[Any], Dict[str, Any]]], + timeout=None): + """Execute method and return results. + + ``timeout`` is passed to ``ray.get(list, timeout=)``, whose semantics are + the **total** wall-clock time to collect the whole list -- different from + ``LazyCollect``'s per-future timing (see ``do_get_and_collect_func``). + The two paths are each bounded on their own; the total-time semantics here + are strictly tighter. + """ import ray - return ray.get(RayHelper.execute_all_async(method_name, workers_and_args)) + return ray.get(RayHelper.execute_all_async(method_name, workers_and_args), timeout=timeout) @staticmethod def execute_all_async(method_name: str, workers_and_args: List[Tuple[Any, List[Any], Dict[str, Any]]]): diff --git a/src/twinkle/model/megatron/megatron.py b/src/twinkle/model/megatron/megatron.py index 851529c6..617cbdba 100644 --- a/src/twinkle/model/megatron/megatron.py +++ b/src/twinkle/model/megatron/megatron.py @@ -883,7 +883,7 @@ def clip_grad_and_step(self, max_grad_norm: float = 1.0, norm_type=2, **kwargs): self.zero_grad(**kwargs) self.lr_step(**kwargs) - @remote_function(dispatch='all', collect='first', sync=True) + @remote_function(dispatch='all', collect='first', sync=True, timeout=3600) def save(self, name: Optional[str] = None, output_dir: Optional[str] = None, @@ -1486,7 +1486,7 @@ def _patch_adapter(self, adapter_name: str, config_or_dir: Union[PeftConfig, str self._default_tokenizer = self.optimizer_group[adapter_name].template.processor self.active_group = adapter_name - @remote_function(dispatch='all', sync=True) + @remote_function(dispatch='all', sync=True, timeout=3600) def add_adapter_to_model( self, adapter_name: str, diff --git a/src/twinkle/model/megatron/multi_lora_megatron.py b/src/twinkle/model/megatron/multi_lora_megatron.py index ebda9150..8af62df4 100644 --- a/src/twinkle/model/megatron/multi_lora_megatron.py +++ b/src/twinkle/model/megatron/multi_lora_megatron.py @@ -291,7 +291,7 @@ def _load_multi_lora_optimizer(self, checkpoint_dir: str, adapter_name: str = '' if optimizer_config is not None and 'iteration' in state_dict: optimizer_config.cur_step = state_dict['iteration'] - @remote_function(dispatch='all', collect='first', sync=True) + @remote_function(dispatch='all', collect='first', sync=True, timeout=3600) def save(self, name, output_dir: Optional[str] = None, interval=1, **kwargs): adapter_name = kwargs.pop('adapter_name', None) self._check_adapter_valid(adapter_name) @@ -372,7 +372,7 @@ def load(self, name: str, output_dir: Optional[str] = None, **kwargs): if dist.is_initialized(): dist.barrier() - @remote_function(dispatch='all', collect='first', sync=True) + @remote_function(dispatch='all', collect='first', sync=True, timeout=3600) def resume_from_checkpoint(self, checkpoint_dir, *, resume_only_model=False, **kwargs): adapter_name = kwargs.pop('adapter_name', None) self._check_adapter_valid(adapter_name) @@ -403,7 +403,7 @@ def get_state_dict(self, **kwargs): self._check_adapter_valid(kwargs.get('adapter_name')) return self.multi_adapter.get_state_dict(**kwargs) - @remote_function(dispatch='all', sync=True) + @remote_function(dispatch='all', sync=True, timeout=3600) def add_adapter_to_model( self, adapter_name: str, diff --git a/src/twinkle/model/transformers/transformers.py b/src/twinkle/model/transformers/transformers.py index 0087cc7f..fcf856f8 100644 --- a/src/twinkle/model/transformers/transformers.py +++ b/src/twinkle/model/transformers/transformers.py @@ -1557,7 +1557,7 @@ def _restore_training_state(self, checkpoint_dir, *, adapter_name=''): return trainer_state - @remote_function(dispatch='all', collect='first', sync=True) + @remote_function(dispatch='all', collect='first', sync=True, timeout=3600) def resume_from_checkpoint(self, checkpoint_dir, *, resume_only_model=False, **kwargs): adapter_name = kwargs.get('adapter_name', '') diff --git a/src/twinkle/sampler/vllm_sampler/vllm_sampler.py b/src/twinkle/sampler/vllm_sampler/vllm_sampler.py index 7877ddb5..fe68b9d7 100644 --- a/src/twinkle/sampler/vllm_sampler/vllm_sampler.py +++ b/src/twinkle/sampler/vllm_sampler/vllm_sampler.py @@ -495,7 +495,7 @@ def unload_adapter_paths(self, adapter_paths: list[str]) -> None: """Unload policy snapshots from vLLM and clear cached requests.""" self._run_in_loop(self.engine.unload_lora_paths(adapter_paths)) - @remote_function(dispatch='all', collect='first', lazy_collect=False) + @remote_function(dispatch='all', collect='first', lazy_collect=False, timeout=3600) def load_full_weights_from_path(self, path: Optional[str] = None) -> int: """Load a full (non-LoRA) HF checkpoint into the engine's base model. diff --git a/src/twinkle/server/model/backends/megatron_model.py b/src/twinkle/server/model/backends/megatron_model.py index 56f9acc9..8c9018be 100644 --- a/src/twinkle/server/model/backends/megatron_model.py +++ b/src/twinkle/server/model/backends/megatron_model.py @@ -102,7 +102,7 @@ def tinker_calculate_metric(self, is_training, **kwargs): metric = super().calculate_metric(is_training, **kwargs) return clean_metrics(metric) - @remote_function(dispatch='all', sync=True) + @remote_function(dispatch='all', sync=True, timeout=3600) def tinker_load(self, checkpoint_dir: str, **kwargs): """Load checkpoint with token-based isolation support.""" token = kwargs.pop('token', None) @@ -135,7 +135,7 @@ def forward_backward(self, *, inputs: InputFeature | list[InputFeature] | Trajec output = super().forward_backward(inputs=inputs, **kwargs) return to_cpu_safe_output(output) - @remote_function(collect='first', lazy_collect=False) + @remote_function(collect='first', lazy_collect=False, timeout=10) def ping(self) -> bool: """Lightweight liveness probe for watchdog health checks.""" return True diff --git a/src/twinkle/server/model/backends/mock_model.py b/src/twinkle/server/model/backends/mock_model.py index 7bf9866c..b6a79bd3 100644 --- a/src/twinkle/server/model/backends/mock_model.py +++ b/src/twinkle/server/model/backends/mock_model.py @@ -240,7 +240,7 @@ def remove_adapter(self, adapter_name: str) -> None: def has_adapter(self, adapter_name: str) -> bool: return adapter_name in self._adapters - @remote_function(collect='first', lazy_collect=False) + @remote_function(collect='first', lazy_collect=False, timeout=10) def ping(self) -> bool: """Lightweight liveness probe for watchdog health checks.""" return True diff --git a/src/twinkle/server/model/backends/transformers_model.py b/src/twinkle/server/model/backends/transformers_model.py index 8dc503bb..3de2da59 100644 --- a/src/twinkle/server/model/backends/transformers_model.py +++ b/src/twinkle/server/model/backends/transformers_model.py @@ -114,7 +114,7 @@ def forward_backward(self, *, inputs: InputFeature | list[InputFeature] | Trajec output = super().forward_backward(inputs=inputs, **kwargs) return to_cpu_safe_output(output) - @remote_function(collect='first', lazy_collect=False) + @remote_function(collect='first', lazy_collect=False, timeout=10) def ping(self) -> bool: """Lightweight liveness probe for watchdog health checks.""" return True diff --git a/src/twinkle/server/utils/task_queue/config.py b/src/twinkle/server/utils/task_queue/config.py index 79d62095..fdeeaf28 100644 --- a/src/twinkle/server/utils/task_queue/config.py +++ b/src/twinkle/server/utils/task_queue/config.py @@ -11,6 +11,9 @@ from pydantic import BaseModel, ConfigDict, Field +# Substituted when execution_timeout is left at 0 ("no configured limit"). +_ZERO_EXECUTION_TIMEOUT_FALLBACK: float = 3600.0 + class TaskQueueConfig(BaseModel): """Configuration for task queue and rate limiting. @@ -20,7 +23,9 @@ class TaskQueueConfig(BaseModel): tps_limit: Maximum input tokens per second per user token. ``0`` disables. window_seconds: Sliding window for rate-limit calculations. Must be > 0. queue_timeout: Maximum time a task can wait in queue (seconds). - execution_timeout: Maximum time a task can execute (seconds). 0 means no limit. + execution_timeout: Maximum time a task can execute (seconds). ``0`` means "no + configured limit"; a finite bound of 3600s is substituted instead of + unbounded waiting (see ``effective_execution_timeout``). enabled: Whether rate limiting is enabled. token_cleanup_multiplier: Multiplier for token cleanup threshold. token_cleanup_interval: How often to run cleanup task (seconds). @@ -33,8 +38,22 @@ class TaskQueueConfig(BaseModel): tps_limit: float = Field(default=16000.0, ge=0) window_seconds: float = Field(default=1.0, gt=0) queue_timeout: float = Field(default=300.0, ge=0) - execution_timeout: float = Field(default=120.0, ge=0) + execution_timeout: float = Field(default=1800.0, ge=0) enabled: bool = True token_cleanup_multiplier: float = Field(default=10.0, ge=0) token_cleanup_interval: float = Field(default=60.0, ge=0) max_input_tokens: int = Field(default=16000, ge=1) + + @property + def effective_execution_timeout(self) -> float: + """The single source of the execution time bound. + + ``0`` is not rejected (that would fail existing deployments); it is read + as "no configured limit" and replaced by a finite fallback so the bound + is always positive. This value feeds both ``_ray_get_timeout`` and the + ComputeWorker's ``asyncio.wait_for`` -- there is no second, independently + configurable timeout. + """ + if self.execution_timeout > 0: + return self.execution_timeout + return _ZERO_EXECUTION_TIMEOUT_FALLBACK diff --git a/src/twinkle/server/utils/task_queue/mixin.py b/src/twinkle/server/utils/task_queue/mixin.py index dcdf805c..f00c5313 100644 --- a/src/twinkle/server/utils/task_queue/mixin.py +++ b/src/twinkle/server/utils/task_queue/mixin.py @@ -58,6 +58,10 @@ def _init_task_queue(self, config: TaskQueueConfig | None = None, deployment_nam config. """ self._task_queue_config = config if config is not None else TaskQueueConfig() + if self._task_queue_config.execution_timeout == 0: + logger.warning( + '[TaskQueue] execution_timeout=0: a finite %.0fs bound has replaced unbounded waiting ' + '(deployment=%s).', self._task_queue_config.effective_execution_timeout, deployment_name or 'unknown') self._deployment_name = deployment_name self._task_metrics = get_task_metrics(deployment_name) if deployment_name else None diff --git a/src/twinkle/server/utils/task_queue/worker.py b/src/twinkle/server/utils/task_queue/worker.py index fdbb36d1..ce517b19 100644 --- a/src/twinkle/server/utils/task_queue/worker.py +++ b/src/twinkle/server/utils/task_queue/worker.py @@ -232,10 +232,9 @@ async def _execute_task(self, task: QueuedTask, queue_key: str, q: asyncio.Queue f'type={task_type}, queue_key={queue_key}') with traced_operation(handler_span_name, attrs=handler_attrs): coro = task.coro_factory() - if self._config.execution_timeout > 0: - result = await asyncio.wait_for(coro, timeout=self._config.execution_timeout) - else: - result = await coro + # effective_execution_timeout is always positive (0 -> finite fallback), + # so wait_for is always in effect. + result = await asyncio.wait_for(coro, timeout=self._config.effective_execution_timeout) exec_time = time.monotonic() - exec_start logger.info(f'[ComputeWorker] Task {task.request_id} completed in {exec_time:.2f}s, type={task_type}') if task.persist_status: @@ -250,7 +249,7 @@ async def _execute_task(self, task: QueuedTask, queue_key: str, q: asyncio.Queue except asyncio.TimeoutError: task_status = 'timeout' exec_time = time.monotonic() - exec_start - error = (f'Execution timeout exceeded: {self._config.execution_timeout}s, ' + error = (f'Execution timeout exceeded: {self._config.effective_execution_timeout}s, ' f'actual execution time: {exec_time:.2f}s') logger.error(f'[ComputeWorker] Task {task.request_id} TIMEOUT after {exec_time:.2f}s, ' f'type={task_type}, queue_key={queue_key}') diff --git a/tests/infra/test_ray_get_timeout.py b/tests/infra/test_ray_get_timeout.py new file mode 100644 index 00000000..f9949eac --- /dev/null +++ b/tests/infra/test_ray_get_timeout.py @@ -0,0 +1,116 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Unit tests for the Sync_Dispatch_Path time bound (spec T1.6 / R9#1). + +These exercise only ``twinkle.infra`` against a plain sleeping Ray actor. They +depend on neither GPU, Megatron, nor any ``src/twinkle/server/**`` component. +""" +from __future__ import annotations + +import pytest + +ray = pytest.importorskip('ray') + +import twinkle.infra as infra +from twinkle.infra._ray.ray_helper import RayHelper +from twinkle.infra import remote_function + + +@ray.remote +class _Sleeper: + """A plain Ray actor whose only method sleeps for a caller-supplied time.""" + + def slow(self, seconds: float): + import time + time.sleep(seconds) + return seconds + + +@pytest.fixture(scope='module', autouse=True) +def _ray_and_ray_mode(): + """Bring up Ray and put infra into 'ray' mode for the driver-side path.""" + ray.init(ignore_reinit_error=True, num_cpus=2, logging_level='ERROR') + prev_mode = infra._mode + infra._mode = 'ray' + try: + yield + finally: + infra._mode = prev_mode + + +def _make_driver(): + """A minimal stand-in for a remote_class handle: one actor, no concurrency.""" + driver = type('Driver', (), {})() + driver._actors = [_Sleeper.remote()] + driver._max_concurrency = None + return driver + + +def test_execute_all_sync_times_out(_ray_and_ray_mode): + """R9#1: execute_all_sync(timeout=) raises when the remote does not return in time.""" + actor = _Sleeper.remote() + workers_and_args = [(actor, [3.0], {})] + with pytest.raises(ray.exceptions.GetTimeoutError): + RayHelper.execute_all_sync('slow', workers_and_args, timeout=0.5) + + +def test_execute_all_sync_returns_within_timeout(_ray_and_ray_mode): + actor = _Sleeper.remote() + workers_and_args = [(actor, [0.1], {})] + assert RayHelper.execute_all_sync('slow', workers_and_args, timeout=10.0) == [0.1] + + +def test_decorator_timeout_takes_priority_over_instance(): + """A small decorator timeout wins over a large instance ``_ray_get_timeout``.""" + + def slow(self, seconds): # body runs in the worker, not here + return seconds + + wrapped = remote_function(dispatch='all', collect='first', sync=True, timeout=0.5)(slow) + driver = _make_driver() + driver._ray_get_timeout = 100.0 # would allow the call if it were consulted + with pytest.raises(ray.exceptions.GetTimeoutError): + wrapped(driver, 3.0) + + +def test_decorator_timeout_wins_when_larger_than_instance(): + """The decorator value wins even when it is the *larger* of the two. + + A large decorator timeout with a tiny instance value must NOT time out -- + proving the instance value is ignored when the decorator declares one. + """ + + def slow(self, seconds): + return seconds + + wrapped = remote_function(dispatch='all', collect='first', sync=True, timeout=100.0)(slow) + driver = _make_driver() + driver._ray_get_timeout = 0.3 # would time out if it were consulted + result = wrapped(driver, 1.0) + # sync collect may hand back a lazy-collect callable; resolving it must not time out. + assert (result() if callable(result) else result) == 1.0 + + +def test_instance_timeout_is_fallback_when_decorator_absent(): + """With no decorator timeout, the instance ``_ray_get_timeout`` applies.""" + + def slow(self, seconds): + return seconds + + wrapped = remote_function(dispatch='all', collect='first', sync=True)(slow) + driver = _make_driver() + driver._ray_get_timeout = 0.3 + with pytest.raises(ray.exceptions.GetTimeoutError): + wrapped(driver, 2.0) + + +def test_decorator_timeout_zero_is_not_treated_as_falsy(): + """timeout=0 means 'time out immediately', not 'fall back to unbounded'.""" + + def slow(self, seconds): + return seconds + + wrapped = remote_function(dispatch='all', collect='first', sync=True, timeout=0)(slow) + driver = _make_driver() + driver._ray_get_timeout = 100.0 # the old ``or`` bug would fall back here + with pytest.raises(ray.exceptions.GetTimeoutError): + wrapped(driver, 1.0) From 1b030ea1a1f3dc00d57b86dbc582100b668768d9 Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 12:02:47 +0800 Subject: [PATCH 03/14] feat(contract): ErrorPayload contract + type base classes (Phase 2, T2.1-T2.4, T6.1) - twinkle_client/types/base.py: StrictRequest/ResponseModel/DataModel + backend_only() helper/reader; naming rulings in module docstring (defined, not applied) (T6.1) - twinkle_client/types/errors.py: ErrorCategory + ErrorPayload(ResponseModel) (T2.1) - task_errors.py: task_error_payload builds ErrorPayload dict (request_id/error_code, traceback split+tail-trim, User carries no traceback); error_payload_from_stored backfills legacy two-field payloads without ValidationError (T2.2) - worker: single-line error summary + full traceback in traceback field; TimeoutError and Ray_Get_Timeout -> 504/Server, others -> 500/Server (T2.3) - tests for ErrorPayload + updated task_errors test (T2.4) --- src/twinkle/server/utils/task_errors.py | 64 ++++++++++++- src/twinkle/server/utils/task_queue/mixin.py | 9 +- src/twinkle/server/utils/task_queue/worker.py | 35 ++++++-- src/twinkle_client/types/base.py | 90 +++++++++++++++++++ src/twinkle_client/types/errors.py | 50 +++++++++++ tests/server/state/test_error_payload.py | 63 +++++++++++++ tests/server/utils/test_task_errors.py | 35 ++++++-- 7 files changed, 327 insertions(+), 19 deletions(-) create mode 100644 src/twinkle_client/types/base.py create mode 100644 src/twinkle_client/types/errors.py create mode 100644 tests/server/state/test_error_payload.py diff --git a/src/twinkle/server/utils/task_errors.py b/src/twinkle/server/utils/task_errors.py index 478745c0..b0fa46eb 100644 --- a/src/twinkle/server/utils/task_errors.py +++ b/src/twinkle/server/utils/task_errors.py @@ -1,5 +1,65 @@ # Copyright (c) ModelScope Contributors. All rights reserved. +"""Construction and backward-compatible reading of failure payloads. +``ErrorPayload`` is the single representation of a failure both on the wire and in +state (R5). This module owns the two entry points that produce/repair it. +""" +from __future__ import annotations -def task_error_payload(error: str) -> dict[str, str]: - return {'error': error, 'category': 'Server'} +from collections.abc import Mapping +from typing import Any, Optional + +from twinkle_client.types.errors import ErrorCategory, ErrorPayload + +_ERROR_MAX = 1024 +_TRACEBACK_MAX = 65536 +_TRUNCATION_MARKER = '...[traceback truncated, tail kept]...\n' + + +def _trim_traceback(text: str) -> str: + """Keep the tail of an over-long traceback (innermost frames are densest).""" + if len(text) <= _TRACEBACK_MAX: + return text + keep = _TRACEBACK_MAX - len(_TRUNCATION_MARKER) + return _TRUNCATION_MARKER + text[-keep:] + + +def task_error_payload( + error: str, + *, + request_id: str, + error_code: int = 500, + category: ErrorCategory = ErrorCategory.Server, + traceback_text: Optional[str] = None, +) -> dict[str, Any]: + """Build an ``ErrorPayload`` and return it as a JSON-safe dict for storage. + + Traceback splitting and length trimming happen here so over-long text is never + written to State_Backend. A ``User`` category carries no traceback (R5#6). + """ + tb: Optional[str] = None + if category != ErrorCategory.User and traceback_text: + tb = _trim_traceback(traceback_text) + payload = ErrorPayload( + error=error[:_ERROR_MAX], + category=category, + error_code=error_code, + request_id=request_id, + traceback=tb, + ) + return payload.model_dump(mode='json') + + +def error_payload_from_stored(stored: Any, *, request_id: str) -> ErrorPayload: + """Build an ``ErrorPayload`` from whatever is sitting in ``FutureRecord.result``. + + Records written before this spec have only ``{error, category}``. Missing + ``error_code`` / ``request_id`` / ``category`` are backfilled with ``500`` / + the caller-supplied value / ``Unknown`` so a rolling upgrade never raises + ``pydantic.ValidationError``. + """ + data = dict(stored) if isinstance(stored, Mapping) else {'error': str(stored)} + data.setdefault('category', ErrorCategory.Unknown) + data.setdefault('error_code', 500) + data.setdefault('request_id', request_id) + return ErrorPayload.model_validate(data) diff --git a/src/twinkle/server/utils/task_queue/mixin.py b/src/twinkle/server/utils/task_queue/mixin.py index f00c5313..7a5193fd 100644 --- a/src/twinkle/server/utils/task_queue/mixin.py +++ b/src/twinkle/server/utils/task_queue/mixin.py @@ -359,8 +359,13 @@ async def _run() -> None: queue_state=QueueState.ACTIVE.value, ) logger.info(f'[TaskQueue] Background task {request_id} completed, type={task_type or "unknown"}') - except Exception: - error_payload = task_error_payload(traceback.format_exc()) + except Exception as exc: + error_payload = task_error_payload( + f'{type(exc).__name__}: {exc}', + request_id=request_id, + error_code=500, + traceback_text=traceback.format_exc(), + ) await self.state.store_future_status( request_id, TaskStatus.FAILED.value, diff --git a/src/twinkle/server/utils/task_queue/worker.py b/src/twinkle/server/utils/task_queue/worker.py index ce517b19..f02ce959 100644 --- a/src/twinkle/server/utils/task_queue/worker.py +++ b/src/twinkle/server/utils/task_queue/worker.py @@ -27,6 +27,13 @@ logger = get_logger() +# Ray_Get_Timeout is classified the same as asyncio.TimeoutError: 504/Server (R5#8). +try: + from ray.exceptions import GetTimeoutError as _RayGetTimeout + _TIMEOUT_EXCEPTIONS: tuple[type[BaseException], ...] = (asyncio.TimeoutError, _RayGetTimeout) +except Exception: # pragma: no cover - ray always present in server runtime + _TIMEOUT_EXCEPTIONS = (asyncio.TimeoutError, ) + class ComputeWorker: """Serial background worker that processes GPU compute tasks. @@ -141,14 +148,22 @@ async def _store_task_failed( error: str, queue_state: str, queue_state_reason: str | None = None, + *, + error_code: int = 500, + traceback_text: str | None = None, ) -> None: - """Store FAILED status with a standardised error payload.""" + """Store FAILED status with a standardised ``ErrorPayload``.""" if task.persist_status: await self._state.store_future_status( task.request_id, TaskStatus.FAILED.value, task.model_id, - result=task_error_payload(error), + result=task_error_payload( + error, + request_id=task.request_id, + error_code=error_code, + traceback_text=traceback_text, + ), queue_state=queue_state, queue_state_reason=queue_state_reason, ) @@ -246,21 +261,25 @@ async def _execute_task(self, task: QueuedTask, queue_key: str, q: asyncio.Queue queue_state=QueueState.ACTIVE.value, ) self._complete_result(task, result) - except asyncio.TimeoutError: + except _TIMEOUT_EXCEPTIONS: task_status = 'timeout' exec_time = time.monotonic() - exec_start - error = (f'Execution timeout exceeded: {self._config.effective_execution_timeout}s, ' + error = (f'Backend call timed out (bound {self._config.effective_execution_timeout}s), ' f'actual execution time: {exec_time:.2f}s') logger.error(f'[ComputeWorker] Task {task.request_id} TIMEOUT after {exec_time:.2f}s, ' f'type={task_type}, queue_key={queue_key}') - await self._store_task_failed(task, error, QueueState.ACTIVE.value) - except Exception: + # asyncio.TimeoutError and Ray_Get_Timeout are 504/Server (R5#8). + await self._store_task_failed(task, error, QueueState.ACTIVE.value, error_code=504) + except Exception as exc: task_status = 'failed' exec_time = time.monotonic() - exec_start - error = traceback.format_exc() + # error is a single-line summary; the full traceback goes only to the + # traceback field, never into `error` (R5#7). + error = f'{type(exc).__name__}: {exc}' logger.error(f'[ComputeWorker] Task {task.request_id} FAILED after {exec_time:.2f}s, ' f'type={task_type}:\n{traceback.format_exc(limit=3)}') - await self._store_task_failed(task, error, QueueState.ACTIVE.value) + await self._store_task_failed( + task, error, QueueState.ACTIVE.value, error_code=500, traceback_text=traceback.format_exc()) finally: q.task_done() self._record_execution_time(task_type, exec_time) diff --git a/src/twinkle_client/types/base.py b/src/twinkle_client/types/base.py new file mode 100644 index 00000000..ff06b8f1 --- /dev/null +++ b/src/twinkle_client/types/base.py @@ -0,0 +1,90 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Shared pydantic base classes and the naming rulings for the wire contract. + +This module is a public contract carrier imported across packages (Twinkle_Server +reverse-imports ``twinkle_client.types``); it therefore intentionally carries **no** +underscore prefix. + +Naming rulings (authoritative for all three split specs; kept in code, not only in +the spec, so a later reader cannot merge these away): + +1. Schema_Module modules imported across packages do NOT use an underscore prefix. + ``base.py`` / ``errors.py`` / ``lifecycle.py`` / ``data.py`` are public-contract + carriers; an underscore means "package-private", and a cross-package import of a + private module is a violation. Modules used only inside Twinkle_Client (never + imported by Twinkle_Server) are exempt. +2. New twinkle-native request models do NOT reuse a class name already present in + ``tinker.types``. Known collision to avoid: ``ForwardBackwardRequest``. Two + handlers import ``types`` from twinkle_client and from tinker respectively; a + same-named model is distinguished only by the import alias and is easy to + misread in a review diff. +3. The field expressing a failure-semantic category is named ``error_code``, NOT + ``status_code`` -- an execution-time failure is delivered with HTTP 200, so the + value is systematically unequal to the response status code. +4. A closed value set on a wire field is declared as ``Literal`` / enum, never a + bare ``str`` (see ``QueueStateLiteral`` in ``errors.py``). + +These three base classes are DEFINED here but NOT applied to any existing model by +this spec: applying ``extra='forbid'`` would immediately reject an old client's +request, which would break the zero-wire-change guarantee. +""" +from __future__ import annotations + +from pydantic import BaseModel, ConfigDict, Field +from pydantic.fields import FieldInfo +from typing import Any, Optional + + +class StrictRequest(BaseModel): + """Request bodies. Typos fail loudly.""" + + model_config = ConfigDict(frozen=True, extra='forbid') + + +class ResponseModel(BaseModel): + """Response bodies. An old client tolerates new server fields.""" + + model_config = ConfigDict(frozen=True, extra='ignore') + + +class DataModel(BaseModel): + """Data-plane models (InputFeature / Trajectory on the wire). + + Same ConfigDict as ResponseModel, different reason -- which is why this is a + separate class and not an alias. ResponseModel's ``ignore`` exists so an old + client tolerates new response fields. DataModel's ``ignore`` exists so a + user's Preprocessor / Template may leave harmless extra keys (the original + columns left by ``dataset.map``, say) without the request being rejected. + + Do NOT "fix" this to inherit StrictRequest. Doing so rejects those extra keys + and breaks a large number of existing datasets. + """ + + model_config = ConfigDict(frozen=True, extra='ignore') + + +# Key under which backend-applicability metadata is stored in a field's +# ``json_schema_extra``. A single constant, helper and reader -- kept here with the +# base classes rather than in a module of their own (no isolation benefit). +BACKEND_ONLY_KEY = 'twinkle_backend_only' + + +def backend_only(*backends: str, **field_kwargs: Any) -> FieldInfo: + """Mark a model field as applicable only to the given backend(s). + + Attaches the backend tuple to the field's ``json_schema_extra`` under + ``BACKEND_ONLY_KEY``; read it back with :func:`read_backend_only`. + """ + extra = dict(field_kwargs.pop('json_schema_extra', None) or {}) + extra[BACKEND_ONLY_KEY] = tuple(backends) + return Field(json_schema_extra=extra, **field_kwargs) + + +def read_backend_only(field_info: FieldInfo) -> Optional[tuple[str, ...]]: + """Return the backend tuple a field was tagged with, or ``None`` if untagged.""" + extra = getattr(field_info, 'json_schema_extra', None) + if isinstance(extra, dict): + value = extra.get(BACKEND_ONLY_KEY) + if value is not None: + return tuple(value) + return None diff --git a/src/twinkle_client/types/errors.py b/src/twinkle_client/types/errors.py new file mode 100644 index 00000000..50c38b73 --- /dev/null +++ b/src/twinkle_client/types/errors.py @@ -0,0 +1,50 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Structured failure payload -- the single representation of a failure. + +Twinkle <-> tinker exception mapping (verified, kept here so a future new exception +class can be lined up against its tinker counterpart): + +- tinker ``RequestFailedError`` (``tinker/_exceptions.py:176-196``; carries + ``message`` / ``request_id`` / ``category``) is the "the task completed in a failed + terminal state" exception. Its ``category`` uses the same three values as + :class:`ErrorCategory` (``Unknown`` / ``Server`` / ``User``). + +``twinkle_client/utils/patch_tinker.py`` shows two SDKs can coexist in one process, +so a semantically-equal but differently-named exception must be lookup-able. +""" +from __future__ import annotations + +from enum import StrEnum +from pydantic import Field +from typing import Any, Optional + +from .base import ResponseModel + + +class ErrorCategory(StrEnum): + """Error attribution. Matches tinker's ``RequestErrorCategory``.""" + + Unknown = 'Unknown' + Server = 'Server' + User = 'User' + + +class ErrorPayload(ResponseModel): + """The single representation of a failure, on the wire and in state. + + ``error_code``, not ``status_code``: once server-request-lifecycle lands, an + execution-time failure is delivered with HTTP 200, so this value is + *systematically* unequal to the response status code. Keeping the name + ``status_code`` would make every reader misparse it once. The 400-599 range is + kept to reuse HTTP's semantic space, not to align with response codes. + + Inherits ``ResponseModel`` (``extra='ignore'``), so a future added field does + not make an old client fail to parse it. + """ + + error: str = Field(max_length=1024) + category: ErrorCategory + error_code: int = Field(ge=400, le=599) + request_id: str + traceback: Optional[str] = Field(default=None, max_length=65536) + details: Optional[list[dict[str, Any]]] = None diff --git a/tests/server/state/test_error_payload.py b/tests/server/state/test_error_payload.py new file mode 100644 index 00000000..b5483445 --- /dev/null +++ b/tests/server/state/test_error_payload.py @@ -0,0 +1,63 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Tests for ErrorPayload construction, backfill, and tinker-SDK wire compat. + +Spec: T2.4 / R9#7 / R8#5. +""" +from __future__ import annotations + +from twinkle.server.utils.task_errors import error_payload_from_stored, task_error_payload +from twinkle_client.types.errors import ErrorCategory, ErrorPayload + + +def test_two_field_legacy_backfills_error_code_and_request_id(): + """A pre-spec {error, category} payload backfills to 500 + passed request_id.""" + stored = {'error': 'boom', 'category': 'Server'} + + payload = error_payload_from_stored(stored, request_id='req_42') + + assert isinstance(payload, ErrorPayload) + assert payload.error_code == 500 + assert payload.request_id == 'req_42' + assert payload.error == 'boom' + + +def test_overlong_traceback_is_trimmed_tail_kept_with_marker(): + long_tb = 'X' * 10 + ('line\n' * 40000) # well over 65536 chars + assert len(long_tb) > 65536 + + payload = task_error_payload( + 'RuntimeError: boom', request_id='req_1', error_code=500, traceback_text=long_tb) + + tb = payload['traceback'] + assert tb is not None + assert len(tb) <= 65536 + assert 'truncated' in tb # truncation marker present + assert tb.endswith('line\n') # tail preserved + + +def test_user_category_carries_no_traceback(): + payload = task_error_payload( + 'invalid field', request_id='req_2', error_code=422, + category=ErrorCategory.User, traceback_text='Traceback (most recent call last): ...') + + assert payload['category'] == ErrorCategory.User.value + assert payload['traceback'] is None + + +def test_tinker_sdk_parses_six_field_like_two_field(): + """R8#5: tinker's RequestFailedResponse ignores extra fields, so a six-field + payload parses equal to a two-field one on the declared fields. + + tinker's RequestErrorCategory values are lowercase ('server'), so the payloads + here use that value; the point under test is that the four extra fields are + ignored, not the category spelling.""" + from tinker.types import RequestFailedResponse + + two = {'error': 'boom', 'category': 'server'} + six = {**two, 'error_code': 504, 'request_id': 'req_9', 'traceback': None, 'details': None} + + parsed_six = RequestFailedResponse.model_validate(six) + parsed_two = RequestFailedResponse.model_validate(two) + + assert parsed_six.error == parsed_two.error + assert parsed_six.category == parsed_two.category diff --git a/tests/server/utils/test_task_errors.py b/tests/server/utils/test_task_errors.py index 0c498664..698ad5b7 100644 --- a/tests/server/utils/test_task_errors.py +++ b/tests/server/utils/test_task_errors.py @@ -1,10 +1,31 @@ -from twinkle.server.utils.task_errors import task_error_payload +from twinkle.server.utils.task_errors import error_payload_from_stored, task_error_payload +from twinkle_client.types.errors import ErrorCategory -def test_task_error_payload_keeps_lora_traceback(): - error = 'Traceback...\nRuntimeError: No lora available for tenant session-default. Max loras: 3\n' +def test_task_error_payload_builds_error_payload_dict(): + error = 'RuntimeError: No lora available for tenant session-default. Max loras: 3' - assert task_error_payload(error) == { - 'error': error, - 'category': 'Server', - } + payload = task_error_payload(error, request_id='req_1', error_code=500) + + assert payload['error'] == error + assert payload['category'] == ErrorCategory.Server.value + assert payload['error_code'] == 500 + assert payload['request_id'] == 'req_1' + assert payload['traceback'] is None + + +def test_task_error_payload_user_category_drops_traceback(): + payload = task_error_payload( + 'bad input', request_id='req_2', error_code=400, category=ErrorCategory.User, traceback_text='Traceback...') + + assert payload['category'] == ErrorCategory.User.value + assert payload['traceback'] is None + + +def test_error_payload_from_stored_backfills_two_field_legacy(): + stored = {'error': 'boom', 'category': 'Server'} + + payload = error_payload_from_stored(stored, request_id='req_3') + + assert payload.error_code == 500 + assert payload.request_id == 'req_3' From b6e0bebc1463a3465a081235effecc81fca6053d Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 12:30:47 +0800 Subject: [PATCH 04/14] feat(contract): QueueStateLiteral + naming disambiguation guard (Phase 6, T6.2-T6.3) - QueueStateLiteral in types/errors.py, values sourced to match server QueueState; consistency test asserts equal value sets (T6.2) - T6.3 realized as a guard test (per user ruling): twinkle_client already shares 18 public names with tinker.types by design (tinker-compatible client), so the literal 'no intersection' cannot hold without renaming twinkle. Guard instead asserts no src/twinkle module binds a tinker and a twinkle_client type to the same local name (tinker must be aliased when both coexist). --- src/twinkle_client/types/errors.py | 7 +- tests/twinkle_client/test_types_contract.py | 78 +++++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 tests/twinkle_client/test_types_contract.py diff --git a/src/twinkle_client/types/errors.py b/src/twinkle_client/types/errors.py index 50c38b73..61685b1e 100644 --- a/src/twinkle_client/types/errors.py +++ b/src/twinkle_client/types/errors.py @@ -16,10 +16,15 @@ class can be lined up against its tinker counterpart): from enum import StrEnum from pydantic import Field -from typing import Any, Optional +from typing import Any, Literal, Optional from .base import ResponseModel +# Closed value set, kept in sync with the server-side ``QueueState`` enum values +# (a consistency test asserts the two sets are equal). Wire fields carrying a queue +# state declare this alias, never a bare ``str`` (naming ruling 4). +QueueStateLiteral = Literal['active', 'paused_rate_limit', 'paused_capacity', 'unknown'] + class ErrorCategory(StrEnum): """Error attribution. Matches tinker's ``RequestErrorCategory``.""" diff --git a/tests/twinkle_client/test_types_contract.py b/tests/twinkle_client/test_types_contract.py new file mode 100644 index 00000000..877f2bf9 --- /dev/null +++ b/tests/twinkle_client/test_types_contract.py @@ -0,0 +1,78 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Contract-base consistency and naming-disambiguation tests. + +- T6.2 / R7#9: ``QueueStateLiteral`` value set equals the server ``QueueState`` enum. +- T6.3 / R7#7: naming disambiguation guard. + +Note on T6.3 scope (agreed deviation from the literal wording): ``twinkle_client`` is +a tinker-compatible client and already shares many public class names with +``tinker.types`` at HEAD (``ForwardRequest``, ``SampleRequest``, ``Checkpoint`` ...), +so a literal "the two modules' public export names are disjoint" assertion cannot +hold and twinkle's names are intentionally NOT renamed. Instead this guard enforces +the invariant the ruling actually targets: no ``src/twinkle/**`` module may bind a +tinker type and a twinkle_client type to the *same local name* (tinker must be +aliased when both coexist) -- which is what makes a review diff misread possible. +""" +from __future__ import annotations + +import ast +import pathlib +import typing + +import twinkle +from twinkle.server.utils.task_queue.types import QueueState +from twinkle_client.types.errors import QueueStateLiteral + +_TWINKLE_SRC = pathlib.Path(twinkle.__file__).resolve().parent + + +def test_queue_state_literal_matches_server_enum(): + literal_values = set(typing.get_args(QueueStateLiteral)) + enum_values = {state.value for state in QueueState} + assert literal_values == enum_values, ( + f'QueueStateLiteral {literal_values} != QueueState {enum_values}') + + +def _origin(module: str | None) -> str | None: + """Classify an import's source module as 'tinker', 'twinkle_client', or None.""" + if not module: + return None + if module == 'tinker' or module.startswith('tinker.'): + return 'tinker' + if module == 'twinkle_client' or module.startswith('twinkle_client.'): + return 'twinkle_client' + return None + + +def _binding_collisions(tree: ast.AST) -> set[str]: + """Return local names bound to BOTH a tinker and a twinkle_client import.""" + tinker_names: set[str] = set() + twinkle_names: set[str] = set() + for node in ast.walk(tree): + if isinstance(node, ast.ImportFrom): + origin = _origin(node.module) + if origin is None: + continue + for alias in node.names: + bound = alias.asname or alias.name + (tinker_names if origin == 'tinker' else twinkle_names).add(bound) + elif isinstance(node, ast.Import): + for alias in node.names: + origin = _origin(alias.name) + if origin is None: + continue + bound = alias.asname or alias.name.split('.')[0] + (tinker_names if origin == 'tinker' else twinkle_names).add(bound) + return tinker_names & twinkle_names + + +def test_no_tinker_twinkle_same_name_binding(): + offenders: dict[str, set[str]] = {} + for path in _TWINKLE_SRC.rglob('*.py'): + tree = ast.parse(path.read_text(), filename=str(path)) + collisions = _binding_collisions(tree) + if collisions: + offenders[str(path.relative_to(_TWINKLE_SRC))] = collisions + assert not offenders, ( + 'tinker and twinkle_client types bound to the same local name (alias tinker ' + f'to disambiguate): {offenders}') From e46345bd8b5406ccb014a03e188db6110ff9efcc Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 12:51:34 +0800 Subject: [PATCH 05/14] feat(server): Blocking_Call_Boundary + Admission_Gate (Phase 3, T3.1-T3.8) - call_backend: dedicated ThreadPoolExecutor (no max_workers=1) + per-replica opt-in Admission_Gate; gate released from the worker thread's finally so a wait_for-cancelled coroutine cannot free it while the call is still in flight; fast-fail BackendBusyError when the gate is held by a leaked call (T3.1) - ModelManagement enables the gate; SamplerManagement does not - worker maps BackendBusyError -> 503/Server - mechanical: 27 model/twinkle + 14 model/tinker + 8 sampler/twinkle + 4 sampler/tinker + 3 model/app direct backend calls -> await call_backend (T3.2-T3.5) - check_model_health async + admit=False ping; _cleanup_adapter via gate; /healthz awaits (T3.5, T3.6) - AST static check over src/twinkle/server/** + shared exemptions file (T3.7) - blocking-boundary integration tests (T3.8) --- src/twinkle/server/model/app.py | 19 +++- src/twinkle/server/model/tinker_handlers.py | 37 ++++--- src/twinkle/server/model/twinkle_handlers.py | 81 +++++++++----- src/twinkle/server/sampler/tinker_handlers.py | 9 +- .../server/sampler/twinkle_handlers.py | 17 +-- src/twinkle/server/utils/task_queue/mixin.py | 77 ++++++++++++- src/twinkle/server/utils/task_queue/types.py | 10 ++ src/twinkle/server/utils/task_queue/worker.py | 10 +- .../integration/test_blocking_boundary.py | 101 ++++++++++++++++++ tests/server/static/__init__.py | 1 + .../server/static/backend_call_exemptions.py | 23 ++++ .../static/test_no_direct_backend_call.py | 78 ++++++++++++++ 12 files changed, 401 insertions(+), 62 deletions(-) create mode 100644 tests/server/integration/test_blocking_boundary.py create mode 100644 tests/server/static/__init__.py create mode 100644 tests/server/static/backend_call_exemptions.py create mode 100644 tests/server/static/test_no_direct_backend_call.py diff --git a/src/twinkle/server/model/app.py b/src/twinkle/server/model/app.py index a56eb7dd..95f122c9 100644 --- a/src/twinkle/server/model/app.py +++ b/src/twinkle/server/model/app.py @@ -133,7 +133,9 @@ def __init__(self, self._replica_registered = False # Initialize mixins - self._init_task_queue(queue_config, deployment_name='Model') + # ModelManagement opts into the Admission_Gate (collective mis-pairing + + # queue-bypassing _cleanup_adapter); SamplerManagement does not. + self._init_task_queue(queue_config, deployment_name='Model', enable_admission_gate=True) self._init_adapter_manager(**(adapter_config or {})) # Note: countdown task is started lazily in _ensure_sticky() @@ -178,15 +180,19 @@ async def shutdown(self) -> None: pass await self.data_plane.close() - def check_model_health(self) -> dict: + async def check_model_health(self) -> dict: """Probe model actors liveness via a lightweight ping. Returns a dict with 'healthy' (bool) and 'detail' (str). If the model actors are dead (e.g. OOM/SIGSEGV), the ping call will raise RayActorError, signalling the watchdog to restart. + + The ping goes through the Blocking_Call_Boundary with ``admit=False`` so it + never blocks the event loop yet never queues behind the Admission_Gate -- + the moment a probe matters most is while a call is stuck holding the gate. """ try: - result = self.model.ping() + result = await self.call_backend(self.model.ping, admit=False) if result is True: return {'healthy': True, 'detail': 'model actors alive'} return {'healthy': False, 'detail': f'unexpected ping result: {result}'} @@ -199,9 +205,12 @@ async def _cleanup_adapter(self, adapter_name: str) -> None: if self.train_mode == 'full': # No PEFT adapter to remove; restore clean base weights so the # next tenant does not inherit this tenant's trained weights. - self.model.reload_initial_weights() + # Takes the Admission_Gate: this path is driven by the background + # countdown and never enters Task_Queue, so the gate is what keeps + # it from colliding with an in-flight training call. + await self.call_backend(self.model.reload_initial_weights) else: - self.model.remove_adapter(adapter_name) + await self.call_backend(self.model.remove_adapter, adapter_name) self.unregister_resource(adapter_name) await self.state.unload_model(adapter_name) diff --git a/src/twinkle/server/model/tinker_handlers.py b/src/twinkle/server/model/tinker_handlers.py index c3df70ef..5d95719b 100644 --- a/src/twinkle/server/model/tinker_handlers.py +++ b/src/twinkle/server/model/tinker_handlers.py @@ -69,18 +69,21 @@ async def _create_adapter(): template = get_template_for_model(self.base_model) if self.is_full_mode: self.register_resource(adapter_name, token, session_id=body.session_id) - self.model.set_template(template, adapter_name=model_adapter, model_id=self.base_model) - self.model.set_processor('InputProcessor', adapter_name=model_adapter) - self.model.set_optimizer('Adam', adapter_name=model_adapter) + await self.call_backend( + self.model.set_template, template, adapter_name=model_adapter, model_id=self.base_model) + await self.call_backend(self.model.set_processor, 'InputProcessor', adapter_name=model_adapter) + await self.call_backend(self.model.set_optimizer, 'Adam', adapter_name=model_adapter) self.set_resource_state(adapter_name, 'grad_ready', False) else: # TODO: Make LoraConfig more flexible lora_cfg = LoraConfig(r=body.lora_config.rank, target_modules='all-linear') self.register_resource(adapter_name, token, session_id=body.session_id) - self.model.add_adapter_to_model(adapter_name=adapter_name, config_or_dir=lora_cfg) - self.model.set_template(template, adapter_name=adapter_name, model_id=self.base_model) - self.model.set_processor('InputProcessor', adapter_name=adapter_name) - self.model.set_optimizer('Adam', adapter_name=adapter_name) + await self.call_backend( + self.model.add_adapter_to_model, adapter_name=adapter_name, config_or_dir=lora_cfg) + await self.call_backend( + self.model.set_template, template, adapter_name=adapter_name, model_id=self.base_model) + await self.call_backend(self.model.set_processor, 'InputProcessor', adapter_name=adapter_name) + await self.call_backend(self.model.set_optimizer, 'Adam', adapter_name=adapter_name) self.set_resource_state(adapter_name, 'grad_ready', False) training_run_manager = create_training_run_manager(token, client_type='tinker') training_run_manager.save(_model_id, body) @@ -147,7 +150,8 @@ async def _do_forward(): model_adapter = self.resolve_model_adapter_name(adapter_name) datum_list = body.forward_input.data loss_fn_config = body.forward_input.loss_fn_config or {} - output, loss = self.model.tinker_forward_only( + output, loss = await self.call_backend( + self.model.tinker_forward_only, inputs=datum_list, adapter_name=model_adapter, **loss_fn_config) return types.ForwardBackwardOutput( loss_fn_output_type='CrossEntropyLossReturn', @@ -190,7 +194,8 @@ async def _do_forward_backward(): datum_list = body.forward_backward_input.data loss_fn = body.forward_backward_input.loss_fn loss_fn_config = body.forward_backward_input.loss_fn_config or {} - output, loss = self.model.tinker_forward_backward( + output, loss = await self.call_backend( + self.model.tinker_forward_backward, inputs=datum_list, adapter_name=model_adapter, loss_fn=loss_fn, **loss_fn_config) output_type = ('ImportanceSamplingLossReturn' if loss_fn == 'importance_sampling' else 'CrossEntropyLossReturn') @@ -238,9 +243,10 @@ async def _do_optim(): if not self.get_resource_state(adapter_name, 'grad_ready', False): raise RuntimeError(f'No accumulated gradients for adapter={adapter_name}; ' 'call forward_backward before optim_step') - self.model.tinker_step(adam_params=body.adam_params, adapter_name=model_adapter) + await self.call_backend(self.model.tinker_step, adam_params=body.adam_params, adapter_name=model_adapter) self.set_resource_state(adapter_name, 'grad_ready', False) - metrics = self.model.tinker_calculate_metric(is_training=True, adapter_name=model_adapter) + metrics = await self.call_backend( + self.model.tinker_calculate_metric, is_training=True, adapter_name=model_adapter) return types.OptimStepResponse(metrics=metrics) except Exception: logger.error(traceback.format_exc()) @@ -267,7 +273,8 @@ async def _do_save(): checkpoint_manager = create_checkpoint_manager(token, client_type='tinker') checkpoint_name = checkpoint_manager.get_ckpt_name(body.path) save_dir = checkpoint_manager.get_save_dir(model_id=body.model_id, is_sampler=False) - self.model.save( + await self.call_backend( + self.model.save, name=checkpoint_name, output_dir=save_dir, adapter_name=model_adapter, save_optimizer=True) tinker_path = checkpoint_manager.save(body.model_id, name=checkpoint_name, is_sampler=False) return types.SaveWeightsResponse(path=tinker_path, type='save_weights') @@ -298,7 +305,8 @@ async def _do_save_for_sampler(): # Must save the checkpoint in the twinkle format before calling model.save() tinker_path = checkpoint_manager.save(body.model_id, name=checkpoint_name, is_sampler=True) logger.info(f'Saving weights to {save_dir}') - self.model.save( + await self.call_backend( + self.model.save, name='latest', output_dir=save_dir, adapter_name=self.resolve_model_adapter_name(adapter_name), @@ -341,7 +349,8 @@ async def _do_load(): assert self.model is not None, 'Model not loaded, please load model first' adapter_name = self.get_adapter_name(adapter_name=body.model_id) self.assert_resource_exists(adapter_name) - self.model.tinker_load( + await self.call_backend( + self.model.tinker_load, checkpoint_dir=body.path, load_optimizer=body.optimizer, adapter_name=self.resolve_model_adapter_name(adapter_name), diff --git a/src/twinkle/server/model/twinkle_handlers.py b/src/twinkle/server/model/twinkle_handlers.py index 582aa5c0..673a9c9a 100644 --- a/src/twinkle/server/model/twinkle_handlers.py +++ b/src/twinkle/server/model/twinkle_handlers.py @@ -71,7 +71,7 @@ async def model_healthz( self: ModelManagement = Depends(self_fn), ) -> dict: """Deep health probe: pings underlying model actors to verify liveness.""" - result = self.check_model_health() + result = await self.check_model_health() if not result['healthy']: from fastapi.responses import JSONResponse return JSONResponse(status_code=503, content=result) @@ -108,7 +108,8 @@ async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} inputs = _parse_inputs(body.inputs) - ret = self.model.forward( + ret = await self.call_backend( + self.model.forward, inputs=inputs, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) return {'result': ret} @@ -139,7 +140,8 @@ async def _task(): self.assert_resource_exists(adapter_name) raw_inputs, field_kwargs = await resolve_data_plane_model_inputs(body, self.data_plane) kwargs = merge_forward_kwargs(body.model_extra or {}, field_kwargs) - ret = self.model.forward( + ret = await self.call_backend( + self.model.forward, inputs=_parse_inputs(raw_inputs), adapter_name=adapter_name, **kwargs, @@ -193,7 +195,8 @@ async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} inputs = _parse_inputs(body.inputs) - ret = self.model.forward_only( + ret = await self.call_backend( + self.model.forward_only, inputs=inputs, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) return {'result': ret} @@ -222,7 +225,7 @@ async def _task(): raw_inputs, field_kwargs = await resolve_data_plane_model_inputs(body, self.data_plane) inputs = _parse_inputs(raw_inputs) kwargs = merge_forward_kwargs(body.model_extra or {}, field_kwargs) - ret = self.model.forward_only(inputs=inputs, adapter_name=adapter_name, **kwargs) + ret = await self.call_backend(self.model.forward_only, inputs=inputs, adapter_name=adapter_name, **kwargs) if body.output_ref is not None: rows = select_output_rows( ret, @@ -257,7 +260,8 @@ async def calculate_loss( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - ret = self.model.calculate_loss(adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + ret = await self.call_backend( + self.model.calculate_loss, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) return {'result': ret} return await run_task( @@ -271,7 +275,8 @@ async def backward(request: Request, body: types.AdapterRequest, self: ModelMana async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.backward(adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + await self.call_backend( + self.model.backward, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='backward')) @@ -299,7 +304,8 @@ async def _task(): for key in inputs: if isinstance(inputs[key], list) and isinstance(first_element(inputs[key]), (int, float)): inputs[key] = torch.tensor(inputs[key]) - ret = self.model.forward_backward( + ret = await self.call_backend( + self.model.forward_backward, inputs=all_inputs, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) return {'result': ret} @@ -330,7 +336,8 @@ async def _task(): self.assert_resource_exists(adapter_name) raw_inputs, field_kwargs = await resolve_data_plane_model_inputs(body, self.data_plane) kwargs = merge_forward_kwargs(body.model_extra or {}, field_kwargs) - ret = self.model.forward_backward( + ret = await self.call_backend( + self.model.forward_backward, inputs=_parse_inputs(raw_inputs), adapter_name=adapter_name, **kwargs, @@ -361,7 +368,8 @@ async def clip_grad_norm( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - ret = self.model.clip_grad_norm(adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + ret = await self.call_backend( + self.model.clip_grad_norm, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) return {'result': str(ret)} return await run_task( @@ -375,7 +383,8 @@ async def step(request: Request, body: types.AdapterRequest, self: ModelManageme async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.step(adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + await self.call_backend( + self.model.step, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='step')) @@ -387,7 +396,8 @@ async def zero_grad(request: Request, body: types.AdapterRequest, self: ModelMan async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.zero_grad(adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + await self.call_backend( + self.model.zero_grad, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='zero_grad')) @@ -399,7 +409,8 @@ async def lr_step(request: Request, body: types.AdapterRequest, self: ModelManag async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.lr_step(adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + await self.call_backend( + self.model.lr_step, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='lr_step')) @@ -415,7 +426,8 @@ async def clip_grad_and_step( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.clip_grad_and_step( + await self.call_backend( + self.model.clip_grad_and_step, max_grad_norm=body.max_grad_norm, norm_type=body.norm_type, adapter_name=self.resolve_model_adapter_name(adapter_name), @@ -437,7 +449,8 @@ async def get_train_configs( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - ret = self.model.get_train_configs( + ret = await self.call_backend( + self.model.get_train_configs, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) return {'result': ret} @@ -452,7 +465,8 @@ async def set_loss(request: Request, body: types.SetLossRequest, self: ModelMana async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.set_loss( + await self.call_backend( + self.model.set_loss, body.loss_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='set_loss')) @@ -469,7 +483,8 @@ async def set_optimizer( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.set_optimizer( + await self.call_backend( + self.model.set_optimizer, body.optimizer_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task( @@ -487,7 +502,8 @@ async def set_lr_scheduler( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.set_lr_scheduler( + await self.call_backend( + self.model.set_lr_scheduler, body.scheduler_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task( @@ -510,7 +526,8 @@ async def _task(): model_id=adapter_name, name=checkpoint_name, is_sampler=body.is_sampler) # For sampler weights the actual data is always written to 'latest/'. model_save_name = 'latest' if body.is_sampler else checkpoint_name - checkpoint_dir = self.model.save( + checkpoint_dir = await self.call_backend( + self.model.save, name=model_save_name, output_dir=save_dir, adapter_name=self.resolve_model_adapter_name(adapter_name), @@ -530,7 +547,8 @@ async def _task(): extra_kwargs = body.model_extra or {} checkpoint_manager = create_checkpoint_manager(token, client_type='twinkle') resolved = checkpoint_manager.resolve_load_path(body.name) - self.model.load( + await self.call_backend( + self.model.load, name=resolved.checkpoint_name, output_dir=resolved.checkpoint_dir, adapter_name=self.resolve_model_adapter_name(adapter_name), @@ -556,7 +574,8 @@ async def _task(): checkpoint_dir = ( Path(resolved.checkpoint_dir, resolved.checkpoint_name).as_posix() if resolved.checkpoint_dir else body.name) - ret = self.model.resume_from_checkpoint( + ret = await self.call_backend( + self.model.resume_from_checkpoint, checkpoint_dir, resume_only_model=body.resume_only_model, adapter_name=self.resolve_model_adapter_name(adapter_name), @@ -682,7 +701,7 @@ async def _task(): # No PEFT adapter to add; the default optimizer group is used. self.set_resource_state(adapter_name, 'grad_ready', False) else: - self.model.add_adapter_to_model(adapter_name, config, **extra_kwargs) + await self.call_backend(self.model.add_adapter_to_model, adapter_name, config, **extra_kwargs) except Exception: self.unregister_resource(adapter_name) await self.state.unload_model(adapter_name) @@ -706,7 +725,8 @@ async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} patch_cls = deserialize_object(body.patch_cls) - self.model.apply_patch( + await self.call_backend( + self.model.apply_patch, patch_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='apply_patch')) @@ -724,7 +744,8 @@ async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} metric_cls = deserialize_object(body.metric_cls) - self.model.add_metric( + await self.call_backend( + self.model.add_metric, metric_cls, is_training=body.is_training, adapter_name=self.resolve_model_adapter_name(adapter_name), @@ -744,7 +765,8 @@ async def set_template( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.set_template( + await self.call_backend( + self.model.set_template, body.template_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='set_template')) @@ -761,7 +783,8 @@ async def set_processor( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - self.model.set_processor( + await self.call_backend( + self.model.set_processor, body.processor_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) await run_task( @@ -779,7 +802,8 @@ async def calculate_metric( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - ret = self.model.calculate_metric( + ret = await self.call_backend( + self.model.calculate_metric, is_training=body.is_training, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) @@ -800,7 +824,8 @@ async def get_state_dict( async def _task(): self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} - ret = self.model.get_state_dict(adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + ret = await self.call_backend( + self.model.get_state_dict, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) return {'result': ret} return await run_task( diff --git a/src/twinkle/server/sampler/tinker_handlers.py b/src/twinkle/server/sampler/tinker_handlers.py index de43b4b9..921e4fdc 100644 --- a/src/twinkle/server/sampler/tinker_handlers.py +++ b/src/twinkle/server/sampler/tinker_handlers.py @@ -52,9 +52,9 @@ async def _do_sample(): # Set template for sampler based on model type template = get_template_for_model(self.model_id) - self.sampler.set_template(template, model_id=self.model_id) + await self.call_backend(self.sampler.set_template, template, model_id=self.model_id) # Reset prefix cache for new weights - self.sampler.reset_prefix_cache() + await self.call_backend(self.sampler.reset_prefix_cache) # Get model_path from body or sampling session model_path = body.model_path @@ -96,9 +96,10 @@ async def _do_sample(): if os.path.exists(os.path.join(adapter_uri, 'adapter_config.json')): lora_path = adapter_uri else: - self.sampler.load_full_weights_from_path(adapter_uri) + await self.call_backend(self.sampler.load_full_weights_from_path, adapter_uri) - responses = self.sampler.sample( + responses = await self.call_backend( + self.sampler.sample, inputs=[prompt_inputs] * body.num_samples, sampling_params=sampling_params, adapter_path=lora_path, diff --git a/src/twinkle/server/sampler/twinkle_handlers.py b/src/twinkle/server/sampler/twinkle_handlers.py index 609c25f2..16af8e70 100644 --- a/src/twinkle/server/sampler/twinkle_handlers.py +++ b/src/twinkle/server/sampler/twinkle_handlers.py @@ -231,13 +231,13 @@ async def _task(): checkpoint_manager = create_checkpoint_manager(token, client_type='twinkle') _, resolved_uri = checkpoint_manager.parse_adapter_uri(body.adapter_uri) # Reset prefix cache only when new weights are loaded - self.sampler.reset_prefix_cache() + await self.call_backend(self.sampler.reset_prefix_cache) # LoRA adapter dir (has adapter_config.json) vs full-parameter # HF checkpoint. Full checkpoints replace the sampler base model. if resolved_uri and os.path.exists(os.path.join(resolved_uri, 'adapter_config.json')): adapter_path = resolved_uri elif resolved_uri: - self.sampler.load_full_weights_from_path(resolved_uri) + await self.call_backend(self.sampler.load_full_weights_from_path, resolved_uri) # Parse inputs inputs = body.inputs @@ -259,7 +259,8 @@ async def _task(): params = SamplingParams.from_dict(body.sampling_params) # Sample - responses = self.sampler.sample( + responses = await self.call_backend( + self.sampler.sample, inputs, params, adapter_name=full_adapter_name, @@ -379,7 +380,7 @@ async def set_template( """Set the chat template for encoding Trajectory inputs.""" extra_kwargs = body.model_extra or {} with traced_operation('sampler.set_template'): - self.sampler.set_template(body.template_cls, **extra_kwargs) + await self.call_backend(self.sampler.set_template, body.template_cls, **extra_kwargs) return types.SetTemplateResponse() @app.post('/twinkle/add_adapter_to_sampler', response_model=types.AddAdapterResponse) @@ -396,7 +397,7 @@ async def add_adapter_to_sampler( config = LoraConfig(**body.config) if isinstance(body.config, dict) else body.config with traced_operation('sampler.add_adapter_to_sampler', attrs={MODEL_ID: self.model_id}): - self.sampler.add_adapter_to_sampler(full_adapter_name, config) + await self.call_backend(self.sampler.add_adapter_to_sampler, full_adapter_name, config) return types.AddAdapterResponse(adapter_name=full_adapter_name) @@ -409,7 +410,7 @@ async def apply_patch( extra_kwargs = body.model_extra or {} patch_cls = deserialize_object(body.patch_cls) with traced_operation('sampler.apply_patch'): - self.sampler.apply_patch(patch_cls, **extra_kwargs) + await self.call_backend(self.sampler.apply_patch, patch_cls, **extra_kwargs) @app.post('/twinkle/sample_stream') async def sample_stream( @@ -437,11 +438,11 @@ async def sample_stream( from twinkle.server.checkpoint import create_checkpoint_manager checkpoint_manager = create_checkpoint_manager(token, client_type='twinkle') _, resolved_uri = checkpoint_manager.parse_adapter_uri(body.adapter_uri) - self.sampler.reset_prefix_cache() + await self.call_backend(self.sampler.reset_prefix_cache) if resolved_uri and os.path.exists(os.path.join(resolved_uri, 'adapter_config.json')): adapter_path = resolved_uri elif resolved_uri: - self.sampler.load_full_weights_from_path(resolved_uri) + await self.call_backend(self.sampler.load_full_weights_from_path, resolved_uri) inputs = body.inputs if isinstance(inputs, list): diff --git a/src/twinkle/server/utils/task_queue/mixin.py b/src/twinkle/server/utils/task_queue/mixin.py index 7a5193fd..10b01bdd 100644 --- a/src/twinkle/server/utils/task_queue/mixin.py +++ b/src/twinkle/server/utils/task_queue/mixin.py @@ -8,10 +8,12 @@ from __future__ import annotations import asyncio +import functools import time import traceback import uuid from collections.abc import Callable, Coroutine +from concurrent.futures import ThreadPoolExecutor from typing import TYPE_CHECKING, Any from twinkle.server.telemetry.middleware import get_task_metrics @@ -19,7 +21,7 @@ from twinkle.utils.logger import get_logger from .config import TaskQueueConfig from .rate_limiter import RateLimiter -from .types import QueuedTask, QueueState, TaskStatus +from .types import BackendBusyError, QueuedTask, QueueState, TaskStatus from .worker import ComputeWorker if TYPE_CHECKING: @@ -50,12 +52,23 @@ class TaskQueueMixin: state: ServerState - def _init_task_queue(self, config: TaskQueueConfig | None = None, deployment_name: str = '') -> None: + def _init_task_queue( + self, + config: TaskQueueConfig | None = None, + deployment_name: str = '', + *, + enable_admission_gate: bool = False, + ) -> None: """Initialise the task queue, rate limiter, and compute worker. ``config`` must be a typed :class:`TaskQueueConfig` (the launcher passes the instance straight through). ``None`` constructs a default config. + + ``enable_admission_gate`` turns on the per-replica Admission_Gate + (:meth:`call_backend`). ``ModelManagement`` enables it; ``SamplerManagement`` + does not (vllm sampler owns its own concurrency and the weight-update / + generation mutual exclusion is covered by infra ``_cw_barrier``). """ self._task_queue_config = config if config is not None else TaskQueueConfig() if self._task_queue_config.execution_timeout == 0: @@ -83,8 +96,65 @@ def _init_task_queue(self, config: TaskQueueConfig | None = None, deployment_nam deployment_name=deployment_name, ) + # Blocking_Call_Boundary: a dedicated thread pool that moves every backend + # call off the event loop. Deliberately NOT max_workers=1 -- a call that + # leaks past its wait_for timeout keeps its thread; capping at one worker + # would let one leak block the whole queue forever. + self._backend_executor = ThreadPoolExecutor(thread_name_prefix='twinkle-backend') + # per-replica Admission_Gate; opt-in per deployment. + self._backend_admission: asyncio.Semaphore | None = ( + asyncio.Semaphore(1) if enable_admission_gate else None) + self._event_loop: asyncio.AbstractEventLoop | None = None + async def call_backend(self, fn: Callable[..., Any], /, *args: Any, admit: bool = True, **kwargs: Any) -> Any: + """The only place a Blocking_Backend_Call leaves the event loop. + + Covers every backend call in this replica process -- not just handlers. + "Does it enter Task_Queue" is deliberately NOT the exemption test: what this + boundary protects is event-loop responsiveness, orthogonal to queueing. + ``check_model_health()``'s ping, ``_cleanup_adapter()``'s two calls (driven + by a countdown, never queued) and the non-queued sampler endpoints are + exactly the calls that test would have missed. + + The Admission_Gate it takes when ``admit=True`` guards against collective + mis-pairing (a task issued to the same actors while a timed-out call is + still in flight) and against queue-bypassing paths (``_cleanup_adapter``) -- + NOT GPU parallelism (Ray already serialises calls per actor). ``admit=False`` + skips the gate: it is for liveness probes only, because the moment a probe + matters most is while a call is stuck, and that is exactly when the gate is + held by the stuck thread; a probe touches no collective. The sampler side + does not enable the gate -- infra ``_cw_barrier`` already covers it. + + When the gate is held by a leaked (timed-out) call, a new admitting call + fails fast with :class:`BackendBusyError` instead of queueing behind it. + """ + loop = asyncio.get_running_loop() + sem = self._backend_admission if admit else None + if sem is None: + return await loop.run_in_executor(self._backend_executor, functools.partial(fn, *args, **kwargs)) + + # asyncio.Semaphore.acquire() does not yield when the gate is free, so this + # check-then-acquire is race-free for a Semaphore(1): if not locked here, + # acquire succeeds synchronously. + if sem.locked(): + raise BackendBusyError( + 'This replica is waiting for a timed-out backend call to exit; ' + 'refusing to queue behind it.') + await sem.acquire() + + def _work() -> Any: + try: + return fn(*args, **kwargs) + finally: + # Release only when the thread truly finishes. A wait_for timeout + # cancels the awaiting coroutine but NOT this thread; releasing on + # cancellation would free the gate while the backend call is still + # in flight (Property 4). + loop.call_soon_threadsafe(sem.release) + + return await loop.run_in_executor(self._backend_executor, _work) + @staticmethod def _queue_key(model_id: str | None, token: str | None) -> str: if model_id: @@ -422,4 +492,7 @@ async def shutdown_task_queue(self) -> None: """Gracefully shut down the compute queue and release resources.""" await self._rate_limiter.stop_cleanup_task() await self._compute_worker.stop() + # Do not wait on threads that may be leaked on a timed-out backend call. + if getattr(self, '_backend_executor', None) is not None: + self._backend_executor.shutdown(wait=False) logger.debug('[TaskQueue] Task queue shutdown complete') diff --git a/src/twinkle/server/utils/task_queue/types.py b/src/twinkle/server/utils/task_queue/types.py index daf8d2bb..a7283dd9 100644 --- a/src/twinkle/server/utils/task_queue/types.py +++ b/src/twinkle/server/utils/task_queue/types.py @@ -26,6 +26,16 @@ class TaskStatus(Enum): RATE_LIMITED = 'rate_limited' # Task rejected due to rate limiting +class BackendBusyError(RuntimeError): + """Raised when the per-replica Admission_Gate is held by a leaked backend call. + + A new backend call arriving while the gate is closed (its holder is a call that + already exceeded ``asyncio.wait_for`` but whose executor thread has not yet + returned) fails fast with this error instead of queueing behind it. The worker + maps it to ``ErrorPayload(category='Server', error_code=503)``. + """ + + class QueueState(Enum): """Queue state for tinker client compatibility. diff --git a/src/twinkle/server/utils/task_queue/worker.py b/src/twinkle/server/utils/task_queue/worker.py index f02ce959..954db4ee 100644 --- a/src/twinkle/server/utils/task_queue/worker.py +++ b/src/twinkle/server/utils/task_queue/worker.py @@ -19,7 +19,7 @@ from twinkle.server.utils.task_errors import task_error_payload from twinkle.utils.logger import get_logger from .config import TaskQueueConfig -from .types import QueuedTask, QueueState, TaskStatus +from .types import BackendBusyError, QueuedTask, QueueState, TaskStatus if TYPE_CHECKING: from twinkle.server.state import ServerState @@ -270,6 +270,14 @@ async def _execute_task(self, task: QueuedTask, queue_key: str, q: asyncio.Queue f'type={task_type}, queue_key={queue_key}') # asyncio.TimeoutError and Ray_Get_Timeout are 504/Server (R5#8). await self._store_task_failed(task, error, QueueState.ACTIVE.value, error_code=504) + except BackendBusyError as exc: + task_status = 'failed' + exec_time = time.monotonic() - exec_start + error = str(exc) + logger.error(f'[ComputeWorker] Task {task.request_id} REFUSED (admission gate held) after ' + f'{exec_time:.2f}s, type={task_type}, queue_key={queue_key}') + # Gate held by a leaked timed-out call -> 503/Server (R2#4). + await self._store_task_failed(task, error, QueueState.ACTIVE.value, error_code=503) except Exception as exc: task_status = 'failed' exec_time = time.monotonic() - exec_start diff --git a/tests/server/integration/test_blocking_boundary.py b/tests/server/integration/test_blocking_boundary.py new file mode 100644 index 00000000..ddf0e5e8 --- /dev/null +++ b/tests/server/integration/test_blocking_boundary.py @@ -0,0 +1,101 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Blocking_Call_Boundary integration tests (T3.8 / R9#2 / Property 3-4). + +These exercise the real ``TaskQueueMixin.call_backend`` through a minimal harness +that sets only the two attributes it uses (a dedicated executor and the optional +Admission_Gate), constructed exactly as ``_init_task_queue`` does. The backend is a +deliberately slow plain callable -- no GPU, Megatron, or Ray involved. +""" +from __future__ import annotations + +import asyncio +import time +from concurrent.futures import ThreadPoolExecutor + +import pytest + +from twinkle.server.utils.task_queue.mixin import TaskQueueMixin +from twinkle.server.utils.task_queue.types import BackendBusyError + + +class _Harness(TaskQueueMixin): + """Minimal holder exposing the real call_backend with a chosen gate setting.""" + + def __init__(self, gate_enabled: bool) -> None: + self._backend_executor = ThreadPoolExecutor(thread_name_prefix='twinkle-backend') + self._backend_admission = asyncio.Semaphore(1) if gate_enabled else None + + def close(self) -> None: + self._backend_executor.shutdown(wait=False) + + +@pytest.mark.asyncio +async def test_healthz_style_probe_responsive_during_slow_backend(): + """Property 3: while a slow backend call is in flight, an admit=False probe + (as /healthz uses) returns well within 5 seconds.""" + h = _Harness(gate_enabled=True) + try: + slow = asyncio.create_task(h.call_backend(lambda: time.sleep(3.0))) + await asyncio.sleep(0.05) # let the slow call take the gate + a thread + + loop = asyncio.get_running_loop() + start = loop.time() + probe = await h.call_backend(lambda: 'pong', admit=False) # no gate, like the ping probe + elapsed = loop.time() - start + + assert probe == 'pong' + assert elapsed < 5.0 + await slow + finally: + h.close() + + +@pytest.mark.asyncio +async def test_gate_held_by_leaked_call_fast_fails_next_task(): + """Property 4 / R2#4: a call that outlives its wait_for keeps the gate; the next + admitting call fails fast with BackendBusyError instead of entering the backend.""" + h = _Harness(gate_enabled=True) + entered = {'count': 0} + + def slow(): + time.sleep(1.5) + + def would_enter_backend(): + entered['count'] += 1 + return 'should-not-run' + + try: + with pytest.raises(asyncio.TimeoutError): + await asyncio.wait_for(h.call_backend(slow), timeout=0.3) + + # The leaked thread still holds the gate. + with pytest.raises(BackendBusyError): + await h.call_backend(would_enter_backend) + assert entered['count'] == 0 # never reached the backend + + # After the leaked thread truly finishes, the gate frees on its own. + await asyncio.sleep(1.6) + assert await h.call_backend(would_enter_backend) == 'should-not-run' + assert entered['count'] == 1 + finally: + h.close() + + +@pytest.mark.asyncio +async def test_sampler_without_gate_runs_two_calls_concurrently(): + """R9#2 case 3 / opt-in: with the gate disabled (SamplerManagement), two backend + calls are in flight at once rather than serialized.""" + h = _Harness(gate_enabled=False) + try: + loop = asyncio.get_running_loop() + start = loop.time() + results = await asyncio.gather( + h.call_backend(lambda: (time.sleep(1.0), 'a')[1]), + h.call_backend(lambda: (time.sleep(1.0), 'b')[1]), + ) + elapsed = loop.time() - start + + assert sorted(results) == ['a', 'b'] + assert elapsed < 1.8 # concurrent, not ~2.0s serialized + finally: + h.close() diff --git a/tests/server/static/__init__.py b/tests/server/static/__init__.py new file mode 100644 index 00000000..85b3e739 --- /dev/null +++ b/tests/server/static/__init__.py @@ -0,0 +1 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. diff --git a/tests/server/static/backend_call_exemptions.py b/tests/server/static/backend_call_exemptions.py new file mode 100644 index 00000000..1ba0674e --- /dev/null +++ b/tests/server/static/backend_call_exemptions.py @@ -0,0 +1,23 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Shared exemption list for the "no direct backend call" static checks. + +This file is the SINGLE source of allowed Blocking_Backend_Call bypasses. It is +consumed by this spec's check (``test_no_direct_backend_call.py``) and is intended +to be consumed unchanged by the ``server-request-lifecycle`` spec's equivalent +check -- there must be exactly one physical copy, not one per spec (R2#8). + +Each entry is ``(module_relpath, function_name)`` where ``module_relpath`` is +relative to ``src/twinkle/server`` and ``function_name`` is the innermost enclosing +function of the exempted call. + +The only allowed exemption is the ray ``Queue.get`` inside ``sample_stream``'s +``_stream_generator``: it bridges the sampler actor's process boundary and is bounded +by the dedicated double-timeout of R4#10-11 (T5.5), not by ``call_backend``. No +``remote_function`` call is exempt. +""" +from __future__ import annotations + +# (module_relpath under src/twinkle/server, innermost enclosing function name) +BACKEND_CALL_EXEMPTIONS: frozenset[tuple[str, str]] = frozenset({ + ('sampler/twinkle_handlers.py', '_stream_generator'), +}) diff --git a/tests/server/static/test_no_direct_backend_call.py b/tests/server/static/test_no_direct_backend_call.py new file mode 100644 index 00000000..4e2750ee --- /dev/null +++ b/tests/server/static/test_no_direct_backend_call.py @@ -0,0 +1,78 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Static check: no direct Blocking_Backend_Call in ``src/twinkle/server/**``. + +Spec: T3.7 / R2#7 / R2#8 / Property 2. + +Asserts that no module under ``src/twinkle/server`` invokes ``self.model.(...)`` +or ``self.sampler.(...)`` directly -- every such call must go through +``call_backend`` (the Blocking_Call_Boundary). The scan range is the directory +(not a file list), so a newly added handler file cannot silently escape it. + +Allowed bypasses are read from the shared ``backend_call_exemptions`` module, which +this spec and ``server-request-lifecycle`` are meant to consume unchanged. This spec +can only verify that *its* check reads that file; the two-spec binding holds once +the lifecycle check is wired to the same file. +""" +from __future__ import annotations + +import ast +import pathlib + +import twinkle +from tests.server.static.backend_call_exemptions import BACKEND_CALL_EXEMPTIONS + +_SERVER_ROOT = pathlib.Path(twinkle.__file__).resolve().parent / 'server' + + +def _is_self_backend_call(node: ast.Call) -> str | None: + """Return 'model'/'sampler' if node is a direct self.model/self.sampler.() call.""" + func = node.func + if not isinstance(func, ast.Attribute): + return None + owner = func.value # the object the method is called on + if (isinstance(owner, ast.Attribute) and owner.attr in ('model', 'sampler') + and isinstance(owner.value, ast.Name) and owner.value.id == 'self'): + return owner.attr + return None + + +class _Collector(ast.NodeVisitor): + + def __init__(self, relpath: str) -> None: + self.relpath = relpath + self.func_stack: list[str] = [] + self.offenders: list[tuple[str, str, int, str]] = [] + + def _visit_func(self, node: ast.AST) -> None: + self.func_stack.append(node.name) + self.generic_visit(node) + self.func_stack.pop() + + visit_FunctionDef = _visit_func + visit_AsyncFunctionDef = _visit_func + + def visit_Call(self, node: ast.Call) -> None: + owner = _is_self_backend_call(node) + if owner is not None: + enclosing = self.func_stack[-1] if self.func_stack else '' + if (self.relpath, enclosing) not in BACKEND_CALL_EXEMPTIONS: + self.offenders.append((self.relpath, enclosing, node.lineno, f'self.{owner}.{node.func.attr}')) + self.generic_visit(node) + + +def test_no_direct_backend_call_in_server(): + offenders: list[tuple[str, str, int, str]] = [] + for path in _SERVER_ROOT.rglob('*.py'): + relpath = str(path.relative_to(_SERVER_ROOT)) + collector = _Collector(relpath) + collector.visit(ast.parse(path.read_text(), filename=str(path))) + offenders.extend(collector.offenders) + + assert not offenders, ( + 'Direct backend calls must go through call_backend (or be listed in ' + f'backend_call_exemptions): {offenders}') + + +def test_exemptions_are_read_from_shared_file(): + # The shared file is the single source of allowed bypasses (R2#8). + assert ('sampler/twinkle_handlers.py', '_stream_generator') in BACKEND_CALL_EXEMPTIONS From 948daaab8bfb14c7b230f8e3fa43cc85391a0634 Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 13:01:50 +0800 Subject: [PATCH 06/14] feat(server): post-timeout actor recovery + two time bounds (Phase 4, T4.1-T4.3) - set _ray_get_timeout = effective execution timeout on model/sampler backends, effective for both sync and async dispatch (T4.1) - ComputeWorker fires an optional on_backend_timeout hook after a timeout; ModelManagement probes actor liveness (admit=False ping) and sets a health bit that /healthz reflects (503) and a successful probe auto-clears (T4.2) - worker skips a dequeued task whose record is already terminal (R3#8); document record-terminal (queue_timeout+T) vs resource-release (Collect_Width*T) bounds in EN+ZH Server docs (T4.3) --- .../Usage Guide/Server and Client/Server.md | 30 ++++++++ .../\346\234\215\345\212\241\347\253\257.md" | 15 ++++ src/twinkle/server/model/app.py | 27 ++++++-- src/twinkle/server/model/twinkle_handlers.py | 2 +- src/twinkle/server/sampler/app.py | 3 + src/twinkle/server/utils/task_queue/mixin.py | 6 ++ src/twinkle/server/utils/task_queue/worker.py | 27 ++++++++ .../server/integration/test_actor_recovery.py | 69 +++++++++++++++++++ 8 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 tests/server/integration/test_actor_recovery.py diff --git a/docs/source_en/Usage Guide/Server and Client/Server.md b/docs/source_en/Usage Guide/Server and Client/Server.md index f31209b0..d57084f1 100644 --- a/docs/source_en/Usage Guide/Server and Client/Server.md +++ b/docs/source_en/Usage Guide/Server and Client/Server.md @@ -450,3 +450,33 @@ twinkle-server check-config -c server_config.yaml | `use_megatron: false` | `backend: transformers` | Additionally, this refactor introduces two new top-level fields — `telemetry` and `persistence` — which did not exist before. Add them as needed. + +## Execution time bounds + +Every backend call has a configuration-computable time bound. The single source of +the bound is the *effective execution timeout* `T`: it equals `execution_timeout` +from the task-queue config, or `3600s` when `execution_timeout` is set to `0` +("no configured limit"; a startup warning is logged). `T` drives both the +`ray.get` timeout on the backend and the `asyncio.wait_for` around each task — +there is no second, independently tunable timeout. The default `execution_timeout` +is `1800s`. + +Two distinct bounds follow, and they must not be collapsed into one number: + +| Bound | Expression | Meaning | +|-------|------------|---------| +| Record-terminal bound | `queue_timeout + T` | After this, a task's future record is guaranteed to be in a terminal state (`completed`/`failed`). Use it for alerting thresholds and client polling total-timeout. | +| Resource-release bound | `Collect_Width × T` | After this, the executor thread and the in-flight model-actor call for that task are guaranteed to have finished. Use it for capacity planning. | + +`Collect_Width = len(self._actors) = world_size = tp × pp × dp` — the number of +futures each `remote_function` collection waits on per call. Evidence: +`LazyCollect._get_result` iterates `self._futures`, which come from +`_get_workers(self._actors, execute)` (`infra/__init__.py`), covering every actor — +not just the data-parallel width. On a `tp=8` deployment the resource-release bound +is therefore `8 × T`, not `T`. + +The **difference** between the two bounds (`Collect_Width × T − (queue_timeout + T)`) +is the longest time the per-replica Admission_Gate can stay closed after a timeout: +the record is already terminal, but a leaked executor thread may still hold the gate +until its `ray.get` returns or raises. During that window newly arriving tasks fail +fast with a `Server`/503 error rather than queueing behind the stuck call. diff --git "a/docs/source_zh/\344\275\277\347\224\250\346\214\207\345\274\225/\346\234\215\345\212\241\347\253\257\345\222\214\345\256\242\346\210\267\347\253\257/\346\234\215\345\212\241\347\253\257.md" "b/docs/source_zh/\344\275\277\347\224\250\346\214\207\345\274\225/\346\234\215\345\212\241\347\253\257\345\222\214\345\256\242\346\210\267\347\253\257/\346\234\215\345\212\241\347\253\257.md" index a4df7a2d..0794fb08 100644 --- "a/docs/source_zh/\344\275\277\347\224\250\346\214\207\345\274\225/\346\234\215\345\212\241\347\253\257\345\222\214\345\256\242\346\210\267\347\253\257/\346\234\215\345\212\241\347\253\257.md" +++ "b/docs/source_zh/\344\275\277\347\224\250\346\214\207\345\274\225/\346\234\215\345\212\241\347\253\257\345\222\214\345\256\242\346\210\267\347\253\257/\346\234\215\345\212\241\347\253\257.md" @@ -450,3 +450,18 @@ twinkle-server check-config -c server_config.yaml | `use_megatron: false` | `backend: transformers` | 此外本次重构新增了 `telemetry` 和 `persistence` 两个顶层字段(旧版本中不存在),可按需添加。 + +## 执行时间上界 + +每一次 backend 调用都存在一个可由配置计算的时间上界。上界的唯一来源是 **有效 execution timeout** `T`:它等于 task-queue 配置中的 `execution_timeout`;当 `execution_timeout` 配置为 `0`(表示「无配置上限」)时取 `3600` 秒,并在启动日志输出一条 warning。`T` 同时作用于 backend 的 `ray.get` 超时与每个任务外围的 `asyncio.wait_for`——不存在第二个可独立调节的超时值。`execution_timeout` 的默认值为 `1800` 秒。 + +由此派生出两个**不同**的上界,二者不得合成一个数: + +| 上界 | 表达式 | 含义 | +|------|--------|------| +| 记录终态上界 | `queue_timeout + T` | 超过它后,任务的 future 记录必处于终态(`completed`/`failed`)。用于设置告警阈值与客户端轮询总超时。 | +| 资源释放上界 | `Collect_Width × T` | 超过它后,该任务占用的 executor 线程与 model actor 在飞调用必已结束。用于容量规划。 | + +`Collect_Width = len(self._actors) = world_size = tp × pp × dp`——即每次 `remote_function` 结果收集所等待的 future 个数。证据:`LazyCollect._get_result` 遍历的 `self._futures` 来自 `_get_workers(self._actors, execute)`(`infra/__init__.py`),覆盖全部 actor,而非 data-parallel 宽度。因此在 `tp=8` 的部署上,资源释放上界是 `8 × T` 而非 `T`。 + +两个上界的**差值**(`Collect_Width × T − (queue_timeout + T)`)即 per-replica 准入闸门在一次超时后需保持关闭的最长时长:此时记录已是终态,但泄漏的 executor 线程可能仍持有闸门,直到其 `ray.get` 返回或抛出。在该窗口内新到达的任务会以 `Server`/503 错误快速失败,而不是排队等待卡住的调用。 diff --git a/src/twinkle/server/model/app.py b/src/twinkle/server/model/app.py index 95f122c9..cd85fb4b 100644 --- a/src/twinkle/server/model/app.py +++ b/src/twinkle/server/model/app.py @@ -131,11 +131,19 @@ def __init__(self, from twinkle.server.data_plane import DataPlaneProxy self.data_plane = DataPlaneProxy(data_plane_url) self._replica_registered = False + # Health status bit, set when a post-timeout probe finds the model actor + # unreachable; auto-cleared by the next successful probe (R3#3). + self._model_unhealthy = False # Initialize mixins # ModelManagement opts into the Admission_Gate (collective mis-pairing + # queue-bypassing _cleanup_adapter); SamplerManagement does not. - self._init_task_queue(queue_config, deployment_name='Model', enable_admission_gate=True) + self._init_task_queue( + queue_config, deployment_name='Model', enable_admission_gate=True, + on_backend_timeout=self._probe_after_timeout) + # Bound every ray.get on this backend by the effective execution timeout + # (applies to both sync=True and sync=False dispatch). T4.1. + self.model._ray_get_timeout = self._task_queue_config.effective_execution_timeout self._init_adapter_manager(**(adapter_config or {})) # Note: countdown task is started lazily in _ensure_sticky() @@ -183,9 +191,8 @@ async def shutdown(self) -> None: async def check_model_health(self) -> dict: """Probe model actors liveness via a lightweight ping. - Returns a dict with 'healthy' (bool) and 'detail' (str). - If the model actors are dead (e.g. OOM/SIGSEGV), the ping call - will raise RayActorError, signalling the watchdog to restart. + Returns a dict with 'healthy' (bool) and 'detail' (str). A successful probe + clears the unhealthy status bit; a failed probe sets it (R3#3). The ping goes through the Blocking_Call_Boundary with ``admit=False`` so it never blocks the event loop yet never queues behind the Admission_Gate -- @@ -194,11 +201,23 @@ async def check_model_health(self) -> dict: try: result = await self.call_backend(self.model.ping, admit=False) if result is True: + self._model_unhealthy = False return {'healthy': True, 'detail': 'model actors alive'} + self._model_unhealthy = True return {'healthy': False, 'detail': f'unexpected ping result: {result}'} except Exception as e: + self._model_unhealthy = True return {'healthy': False, 'detail': f'model actor unreachable: {e}'} + def mark_unhealthy(self) -> None: + """Flag the deployment unhealthy; /healthz returns 503 until a probe recovers it.""" + self._model_unhealthy = True + + async def _probe_after_timeout(self) -> None: + """Fired by ComputeWorker on a backend timeout: probe and log liveness (R3#2).""" + result = await self.check_model_health() + logger.warning('[Model] post-timeout liveness probe: %s', result) + async def _cleanup_adapter(self, adapter_name: str) -> None: if self.get_resource_info(adapter_name): self.clear_resource_state(adapter_name) diff --git a/src/twinkle/server/model/twinkle_handlers.py b/src/twinkle/server/model/twinkle_handlers.py index 673a9c9a..b780b279 100644 --- a/src/twinkle/server/model/twinkle_handlers.py +++ b/src/twinkle/server/model/twinkle_handlers.py @@ -72,7 +72,7 @@ async def model_healthz( ) -> dict: """Deep health probe: pings underlying model actors to verify liveness.""" result = await self.check_model_health() - if not result['healthy']: + if self._model_unhealthy or not result['healthy']: from fastapi.responses import JSONResponse return JSONResponse(status_code=503, content=result) return result diff --git a/src/twinkle/server/sampler/app.py b/src/twinkle/server/sampler/app.py index 8941a40b..892a66bd 100644 --- a/src/twinkle/server/sampler/app.py +++ b/src/twinkle/server/sampler/app.py @@ -129,6 +129,9 @@ def __init__(self, # Initialize task queue mixin self._init_task_queue(queue_config, deployment_name='Sampler') + # Bound every ray.get on this backend by the effective execution timeout + # (applies to both sync=True and sync=False dispatch). T4.1. + self.sampler._ray_get_timeout = self._task_queue_config.effective_execution_timeout async def shutdown(self) -> None: cancel_all = getattr(self.sampler, 'cancel_all_generations', None) diff --git a/src/twinkle/server/utils/task_queue/mixin.py b/src/twinkle/server/utils/task_queue/mixin.py index 10b01bdd..d3f31d2c 100644 --- a/src/twinkle/server/utils/task_queue/mixin.py +++ b/src/twinkle/server/utils/task_queue/mixin.py @@ -58,6 +58,7 @@ def _init_task_queue( deployment_name: str = '', *, enable_admission_gate: bool = False, + on_backend_timeout: Callable[[], Coroutine[Any, Any, None]] | None = None, ) -> None: """Initialise the task queue, rate limiter, and compute worker. @@ -69,6 +70,10 @@ def _init_task_queue( (:meth:`call_backend`). ``ModelManagement`` enables it; ``SamplerManagement`` does not (vllm sampler owns its own concurrency and the weight-update / generation mutual exclusion is covered by infra ``_cw_barrier``). + + ``on_backend_timeout`` is an optional coroutine invoked once whenever a task + fails with a Ray_Get_Timeout / execution timeout, used by ModelManagement to + probe actor liveness (R3#2). """ self._task_queue_config = config if config is not None else TaskQueueConfig() if self._task_queue_config.execution_timeout == 0: @@ -94,6 +99,7 @@ def _init_task_queue( config=self._task_queue_config, task_metrics=self._task_metrics, deployment_name=deployment_name, + on_backend_timeout=on_backend_timeout, ) # Blocking_Call_Boundary: a dedicated thread pool that moves every backend diff --git a/src/twinkle/server/utils/task_queue/worker.py b/src/twinkle/server/utils/task_queue/worker.py index 954db4ee..1d951edb 100644 --- a/src/twinkle/server/utils/task_queue/worker.py +++ b/src/twinkle/server/utils/task_queue/worker.py @@ -53,11 +53,14 @@ def __init__( config: TaskQueueConfig, task_metrics: TaskMetrics | None, deployment_name: str, + on_backend_timeout: 'Callable[[], Any] | None' = None, ) -> None: self._state = state self._config = config self._task_metrics = task_metrics self._deployment_name = deployment_name + # Optional coroutine-returning callback fired on a backend timeout (R3#2). + self._on_backend_timeout = on_backend_timeout self.task_queues: dict[str, asyncio.Queue] = {} self.queue_order: Deque[str] = deque() @@ -270,6 +273,13 @@ async def _execute_task(self, task: QueuedTask, queue_key: str, q: asyncio.Queue f'type={task_type}, queue_key={queue_key}') # asyncio.TimeoutError and Ray_Get_Timeout are 504/Server (R5#8). await self._store_task_failed(task, error, QueueState.ACTIVE.value, error_code=504) + # Probe actor liveness after a timeout so an operator learns the replica's + # state without waiting for a second request to also time out (R3#2). + if self._on_backend_timeout is not None: + try: + await self._on_backend_timeout() + except Exception: + logger.error(f'[ComputeWorker] backend-timeout probe failed:\n{traceback.format_exc(limit=3)}') except BackendBusyError as exc: task_status = 'failed' exec_time = time.monotonic() - exec_start @@ -322,12 +332,29 @@ async def _try_run_one(self) -> bool: await self._fail_timed_out_task(task, queue_wait, q) continue # try the next queue + # A record already in a Terminal_State (e.g. written 'failed' by the + # state-hygiene orphan handling) must not be executed again (R3#8). + if task.persist_status and await self._is_record_terminal(task.request_id): + logger.info(f'[ComputeWorker] Task {task.request_id} already terminal on dequeue; skipping.') + q.task_done() + continue + # Execute the task (serial: stops after the first execution) await self._execute_task(task, queue_key, q) return True return False + async def _is_record_terminal(self, request_id: str) -> bool: + """True if the future record already holds a Terminal_State.""" + try: + record = await self._state.get_future(request_id) + except Exception: + return False + if not record: + return False + return record.get('status') in (TaskStatus.COMPLETED.value, TaskStatus.FAILED.value) + # ------------------------------------------------------------------ # Main worker loop # ------------------------------------------------------------------ diff --git a/tests/server/integration/test_actor_recovery.py b/tests/server/integration/test_actor_recovery.py new file mode 100644 index 00000000..2ec4f807 --- /dev/null +++ b/tests/server/integration/test_actor_recovery.py @@ -0,0 +1,69 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Post-timeout liveness probe and health status bit (T4.2 / R3#2-3). + +Binds the real ``ModelManagement`` health methods onto a minimal harness with a +toggleable mock ``ping`` and a direct ``call_backend``. No GPU/Ray/full server. +""" +from __future__ import annotations + +import pytest + +from twinkle.server.model.app import ModelManagement + + +class _MockModel: + + def __init__(self) -> None: + self.alive = True + + def ping(self) -> bool: + if not self.alive: + raise RuntimeError('actor unreachable (simulated)') + return True + + +class _HealthHarness: + # Reuse the real implementations under test. + check_model_health = ModelManagement.check_model_health + mark_unhealthy = ModelManagement.mark_unhealthy + _probe_after_timeout = ModelManagement._probe_after_timeout + + def __init__(self, model: _MockModel) -> None: + self.model = model + self._model_unhealthy = False + + async def call_backend(self, fn, /, *args, admit: bool = True, **kwargs): + return fn(*args, **kwargs) + + +@pytest.mark.asyncio +async def test_timeout_probe_marks_unhealthy_then_recovers(): + model = _MockModel() + h = _HealthHarness(model) + + # Healthy at first. + result = await h.check_model_health() + assert result['healthy'] is True + assert h._model_unhealthy is False + + # A backend timeout fires the probe while the actor is unreachable. + model.alive = False + await h._probe_after_timeout() + assert h._model_unhealthy is True # /healthz would return 503 + + # Actor recovers; one successful probe clears the bit (no restart needed). + model.alive = True + result = await h.check_model_health() + assert result['healthy'] is True + assert h._model_unhealthy is False + + +@pytest.mark.asyncio +async def test_mark_unhealthy_is_cleared_by_successful_probe(): + h = _HealthHarness(_MockModel()) + h.mark_unhealthy() + assert h._model_unhealthy is True + + result = await h.check_model_health() + assert result['healthy'] is True + assert h._model_unhealthy is False From 742faf7a7ec87c13ccfcf645708604fd9ebaf496 Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 13:20:33 +0800 Subject: [PATCH 07/14] feat(state): future record survival + ownership hygiene (Phase 5, T5.1-T5.6) - FutureRecord.replica_id set at creation, never overwritten (T5.1) - ReplicaRegistry last_seen as a separate key (max_loras type unchanged); refreshed in _on_request_start; ModelManager.get_alive_replica_ids (T5.2) - cleanup_expired rewrite: never deletes a non-terminal record; orphans and over-absolute-ttl records are written failed; signature adds alive_replica_ids + absolute_ttl; ServerState.set_execution_bounds injects queue_timeout/T/ Collect_Width; age uses the stored-timestamp clock convention (T5.3) - do-not-regress guard extended to terminal->terminal (warn on different, silent drop on same) (T5.4) - sampler _stream_generator: 60s per-get + total-lifetime bound, ray Queue shutdown in finally, empty-actor structured error (T5.5) - state hygiene tests via Ray-free FileBackend (T5.6) --- src/twinkle/server/model/app.py | 10 ++ .../server/sampler/twinkle_handlers.py | 52 +++++++-- src/twinkle/server/state/future_manager.py | 101 +++++++++++++++--- src/twinkle/server/state/model_manager.py | 23 ++++ src/twinkle/server/state/models.py | 4 + src/twinkle/server/state/replica_registry.py | 37 +++++++ src/twinkle/server/state/server_state.py | 45 +++++++- src/twinkle/server/utils/task_queue/mixin.py | 3 + tests/server/state/test_future_lifecycle.py | 95 ++++++++++++++++ 9 files changed, 345 insertions(+), 25 deletions(-) create mode 100644 tests/server/state/test_future_lifecycle.py diff --git a/src/twinkle/server/model/app.py b/src/twinkle/server/model/app.py index cd85fb4b..6495dd7d 100644 --- a/src/twinkle/server/model/app.py +++ b/src/twinkle/server/model/app.py @@ -144,6 +144,15 @@ def __init__(self, # Bound every ray.get on this backend by the effective execution timeout # (applies to both sync=True and sync=False dispatch). T4.1. self.model._ray_get_timeout = self._task_queue_config.effective_execution_timeout + # Inject the execution bounds used by state hygiene to compute the absolute + # survival TTL for non-terminal future records (T5.3). Collect_Width = + # world_size = len(self._actors). + _actors = getattr(self.model, '_actors', None) + self.state.set_execution_bounds( + queue_timeout=self._task_queue_config.queue_timeout, + execution_timeout=self._task_queue_config.effective_execution_timeout, + collect_width=len(_actors) if _actors else 1, + ) self._init_adapter_manager(**(adapter_config or {})) # Note: countdown task is started lazily in _ensure_sticky() @@ -176,6 +185,7 @@ async def _ensure_sticky(self): async def _on_request_start(self, request: Request) -> str: await self._ensure_sticky() await self._ensure_replica_registered() + await self.state.touch_replica_last_seen(self.replica_id) await self._ensure_state_cleanup_started() token = get_token_from_request(request) return token diff --git a/src/twinkle/server/sampler/twinkle_handlers.py b/src/twinkle/server/sampler/twinkle_handlers.py index 16af8e70..19100adb 100644 --- a/src/twinkle/server/sampler/twinkle_handlers.py +++ b/src/twinkle/server/sampler/twinkle_handlers.py @@ -466,7 +466,14 @@ async def sample_stream( from .backends import STREAM_SENTINEL q = Queue(maxsize=128) - actor = self.sampler._actors[0] + actors = self.sampler._actors + if not actors: + # No available sampler actor -> structured error, not an IndexError (R4#12). + async def _no_actor_generator(): + yield json.dumps({'error': 'No available sampler actor', 'category': 'Server'}) + '\n' + + return StreamingResponse(_no_actor_generator(), media_type='application/x-ndjson') + actor = actors[0] actor.sample_stream_to_queue.remote( q, inputs_parsed, @@ -475,16 +482,41 @@ async def sample_stream( adapter_path=adapter_path, ) + # Two time bounds (R4#10-11): a per-get bound and a total-lifetime bound. + single_get_timeout = 60.0 + total_timeout = self._task_queue_config.effective_execution_timeout + async def _stream_generator(): loop = asyncio.get_event_loop() - while True: - item = await loop.run_in_executor(None, q.get) - if item == STREAM_SENTINEL: - break - if isinstance(item, Exception): - yield json.dumps({'error': str(item)}) + '\n' - break - delta, reason = item - yield json.dumps({'delta': delta, 'finish_reason': reason}) + '\n' + start = loop.time() + try: + while True: + remaining = total_timeout - (loop.time() - start) + if remaining <= 0: + yield json.dumps( + {'error': 'sample_stream exceeded the execution time bound', 'category': 'Server'}) + '\n' + break + try: + item = await asyncio.wait_for( + loop.run_in_executor(None, q.get), timeout=min(single_get_timeout, remaining)) + except asyncio.TimeoutError: + yield json.dumps( + {'error': 'sample_stream timed out waiting for the next token', 'category': 'Server'}) + '\n' + break + if item == STREAM_SENTINEL: + break + if isinstance(item, Exception): + yield json.dumps({'error': str(item)}) + '\n' + break + delta, reason = item + yield json.dumps({'delta': delta, 'finish_reason': reason}) + '\n' + finally: + # The run_in_executor(None, q.get) thread is NOT cancelled when + # wait_for times out; shutting the ray Queue down makes the blocked + # get() raise so the thread exits and the pool returns to baseline. + try: + q.shutdown(force=True) + except Exception: + pass return StreamingResponse(_stream_generator(), media_type='application/x-ndjson') diff --git a/src/twinkle/server/state/future_manager.py b/src/twinkle/server/state/future_manager.py index 5adf89cc..31f5cac3 100644 --- a/src/twinkle/server/state/future_manager.py +++ b/src/twinkle/server/state/future_manager.py @@ -5,10 +5,14 @@ from datetime import datetime from typing import Any +from twinkle.server.utils.task_errors import task_error_payload +from twinkle.utils.logger import get_logger from .backend.base import StateBackend from .base import BaseManager from .models import FutureRecord +logger = get_logger() + # Status sets used by the do-not-regress guard inside the atomic transform. _TERMINAL_STATUSES = frozenset({'completed', 'failed'}) _NON_TERMINAL_STATUSES = frozenset({'pending', 'queued', 'running'}) @@ -17,12 +21,14 @@ def _future_record_transform( existing: dict | None, *, + request_id: str, new_status: str, model_id: str | None, reason: str | None, result: Any, queue_state: str | None, queue_state_reason: str | None, + replica_id: str | None, now: str, ) -> dict | None: """Atomic transform body for :meth:`FutureManager.store_status`. @@ -30,12 +36,16 @@ def _future_record_transform( Module-level so it remains picklable when forwarded across the Ray actor boundary (closures and lambdas cannot be). - Drops the write entirely (returns ``None``) when ``new_status`` would - regress a terminal status — the StateBackend.update_atomic contract treats - a ``None`` return as "keep the current value", which is what stops stale - retries from clobbering a freshly committed terminal state. + A record already in a terminal state is never overwritten (returns ``None``, + which ``update_atomic`` treats as "keep current value"). A write of a + *different* terminal state is logged; a write of the *same* terminal state is + dropped silently (State_Backend idempotent retries produce these and they + indicate no defect). """ - if (existing is not None and existing.get('status') in _TERMINAL_STATUSES and new_status in _NON_TERMINAL_STATUSES): + existing_status = existing.get('status') if existing is not None else None + if existing_status in _TERMINAL_STATUSES: + if new_status != existing_status: + logger.warning('future %s already terminal as %r; refusing %r', request_id, existing_status, new_status) return None if existing is None: @@ -46,6 +56,7 @@ def _future_record_transform( result=result, queue_state=queue_state, queue_state_reason=queue_state_reason, + replica_id=replica_id, created_at=now, updated_at=now, ) @@ -55,6 +66,7 @@ def _future_record_transform( updated['status'] = new_status updated['model_id'] = model_id updated['updated_at'] = now + # replica_id is set at creation and is deliberately NOT overwritten here. if reason is not None: updated['reason'] = reason if result is not None: @@ -86,6 +98,7 @@ async def store_status( result: Any = None, queue_state: str | None = None, queue_state_reason: str | None = None, + replica_id: str | None = None, ) -> None: """Create or update a future record with the latest status. @@ -104,34 +117,94 @@ async def store_status( self._make_key(request_id), functools.partial( _future_record_transform, + request_id=request_id, new_status=status, model_id=model_id, reason=reason, result=result, queue_state=queue_state, queue_state_reason=queue_state_reason, + replica_id=replica_id, now=now, ), ) # ----- Cleanup ----- - async def cleanup_expired(self, cutoff_time: float, **kwargs) -> int: - """Remove futures whose last update is older than cutoff_time. + async def cleanup_expired( + self, + cutoff_time: float, + *, + alive_replica_ids: set[str] | None = None, + absolute_ttl: float | None = None, + ) -> int: + """Expire future records without ever deleting a non-terminal one. + + Processing matrix (design §5.2): + + | status | replica alive | over absolute_ttl | action | + |--------------|---------------|-------------------|-------------------| + | Terminal | — | ts < cutoff | delete | + | non-Terminal | yes | no | keep (untouched) | + | non-Terminal | yes | yes | write ``failed`` | + | non-Terminal | no | — | write ``failed`` | Args: - cutoff_time: Unix timestamp threshold. + cutoff_time: Unix timestamp; terminal records older than it are deleted. + alive_replica_ids: replicas currently considered alive. ``None`` disables + the orphan check (every non-terminal record is treated as owned). + absolute_ttl: seconds; a non-terminal record whose ``created_at`` is older + than this (regardless of ``updated_at``) is failed. ``None`` disables + the absolute-survival bound. Returns: - Number of futures removed. + Number of terminal records removed (records written ``failed`` are not + counted here; they are removed on a later pass once terminal). """ all_records = await self.get_all() - expired_ids = [] + # Use the same clock convention as the stored timestamps (_parse_timestamp on + # an ISO string) so the age computation is not skewed by _now_iso writing + # local time while _parse_timestamp reads naive ISO as UTC. + now = self._parse_timestamp(datetime.now().isoformat()) + expired_ids: list[str] = [] for request_id, record in all_records.items(): - timestamp_str = record.updated_at or record.created_at - timestamp = self._parse_timestamp(timestamp_str) - if timestamp < cutoff_time: - expired_ids.append(request_id) + if record.status in _TERMINAL_STATUSES: + timestamp = self._parse_timestamp(record.updated_at or record.created_at) + if timestamp < cutoff_time: + expired_ids.append(request_id) + continue + + # Non-terminal records are never deleted -- only ever written ``failed``. + # replica_id None (pre-upgrade) => ownership unknown => treated as alive. + replica_id = record.replica_id + replica_alive = (replica_id is None or alive_replica_ids is None or replica_id in alive_replica_ids) + if not replica_alive: + await self.store_status( + request_id, + 'failed', + record.model_id, + result=task_error_payload( + 'The replica that owned this task is no longer available.', + request_id=request_id, + error_code=503, + ), + replica_id=replica_id, + ) + continue + if absolute_ttl is not None: + created = self._parse_timestamp(record.created_at) + if (now - created) > absolute_ttl: + await self.store_status( + request_id, + 'failed', + record.model_id, + result=task_error_payload( + 'Task exceeded the absolute survival bound without reaching a terminal state.', + request_id=request_id, + error_code=500, + ), + replica_id=replica_id, + ) for request_id in expired_ids: await self.remove(request_id) diff --git a/src/twinkle/server/state/model_manager.py b/src/twinkle/server/state/model_manager.py index ae75621c..f4ccf034 100644 --- a/src/twinkle/server/state/model_manager.py +++ b/src/twinkle/server/state/model_manager.py @@ -11,6 +11,7 @@ from __future__ import annotations import functools +import time from .backend.base import StateBackend from .base import BaseManager @@ -101,6 +102,28 @@ async def unregister_replica(self, replica_id: str) -> None: await self.remove(model_id) await self._replicas.unregister(replica_id) + async def touch_replica_last_seen(self, replica_id: str) -> None: + """Refresh a replica's liveness timestamp (R4#6).""" + await self._replicas.touch_last_seen(replica_id) + + async def get_alive_replica_ids(self, liveness_threshold: float) -> set[str]: + """Return replicas considered alive (R4#7, R4#8). + + A replica is alive when it has a ``last_seen`` within ``liveness_threshold``, + OR when it has a ``max_loras`` entry but no ``last_seen`` yet (registered + before this spec / before its first request -- treated as alive so an + upgrade does not orphan in-flight tasks). + """ + registered = await self._replicas.get_all() + last_seen = await self._replicas.get_all_last_seen() + now = time.time() + alive: set[str] = set() + for rid in registered: + ls = last_seen.get(rid) + if ls is None or (now - ls) <= liveness_threshold: + alive.add(rid) + return alive + async def get_available_replica_ids(self, candidate_ids: list[str]) -> list[str]: """Return the subset of ``candidate_ids`` that still have capacity. diff --git a/src/twinkle/server/state/models.py b/src/twinkle/server/state/models.py index 71279b89..60970022 100644 --- a/src/twinkle/server/state/models.py +++ b/src/twinkle/server/state/models.py @@ -53,5 +53,9 @@ class FutureRecord(BaseModel): result: Any = None queue_state: str | None = None queue_state_reason: str | None = None + # Replica that produced the record; filled at creation and never overwritten by a + # later status update. ``None`` (pre-upgrade record) means "ownership unknown" and + # is only subject to the absolute survival bound (see FutureManager.cleanup_expired). + replica_id: str | None = None created_at: str = Field(default_factory=_now_iso) updated_at: str = Field(default_factory=_now_iso) diff --git a/src/twinkle/server/state/replica_registry.py b/src/twinkle/server/state/replica_registry.py index b2e11d13..d287c1d0 100644 --- a/src/twinkle/server/state/replica_registry.py +++ b/src/twinkle/server/state/replica_registry.py @@ -13,16 +13,23 @@ """ from __future__ import annotations +import time + from .backend.base import StateBackend REPLICA_PREFIX = 'replica::' _MAX_LORAS_SUFFIX = '::max_loras' +_LAST_SEEN_SUFFIX = '::last_seen' def _make_key(replica_id: str) -> str: return f'{REPLICA_PREFIX}{replica_id}{_MAX_LORAS_SUFFIX}' +def _last_seen_key(replica_id: str) -> str: + return f'{REPLICA_PREFIX}{replica_id}{_LAST_SEEN_SUFFIX}' + + def _replica_id_from_key(key: str) -> str | None: if not key.startswith(REPLICA_PREFIX) or not key.endswith(_MAX_LORAS_SUFFIX): return None @@ -42,6 +49,36 @@ async def register(self, replica_id: str, max_loras: int) -> None: async def unregister(self, replica_id: str) -> None: """Remove the capacity entry for ``replica_id`` (idempotent).""" await self._backend.delete(_make_key(replica_id)) + await self._backend.delete(_last_seen_key(replica_id)) + + async def touch_last_seen(self, replica_id: str) -> None: + """Refresh the replica's liveness timestamp (separate key from max_loras).""" + await self._backend.set(_last_seen_key(replica_id), time.time()) + + async def get_last_seen(self, replica_id: str) -> float | None: + """Return the replica's last-seen unix time, or ``None`` if never refreshed.""" + value = await self._backend.get(_last_seen_key(replica_id)) + if value is None: + return None + try: + return float(value) + except (TypeError, ValueError): + return None + + async def get_all_last_seen(self) -> dict[str, float]: + """Return every replica's last-seen timestamp.""" + keys = await self._backend.keys(f'{REPLICA_PREFIX}*{_LAST_SEEN_SUFFIX}') + out: dict[str, float] = {} + for key in keys: + if not key.startswith(REPLICA_PREFIX) or not key.endswith(_LAST_SEEN_SUFFIX): + continue + rid = key[len(REPLICA_PREFIX):-len(_LAST_SEEN_SUFFIX)] + value = await self._backend.get(key) + try: + out[rid] = float(value) + except (TypeError, ValueError): + continue + return out async def get_max_loras(self, replica_id: str) -> int | None: """Return the declared capacity, or ``None`` if the replica is unknown.""" diff --git a/src/twinkle/server/state/server_state.py b/src/twinkle/server/state/server_state.py index 1fb548f5..e59b215d 100644 --- a/src/twinkle/server/state/server_state.py +++ b/src/twinkle/server/state/server_state.py @@ -39,6 +39,10 @@ LEASE_TTL = 30 # seconds — leader loses the lease after this without a renew LEASE_RENEW = 10 # seconds — must be < LEASE_TTL/2 so two missed renews still beat the TTL +# Integer multiple of (queue_timeout + resource-release bound) used as the absolute +# survival bound for a non-terminal record; the margin absorbs scheduling slack. +_ABSOLUTE_TTL_MULTIPLIER = 2 + def _renew_if_owner(current: str | None, *, owner: str) -> str | None: """``update_atomic`` transform: only re-write the lease if it is still mine.""" @@ -87,6 +91,13 @@ def __init__( self._cleanup_task: asyncio.Task | None = None self._cleanup_running = False + # Execution bounds injected by ModelManagement after _init_task_queue + # (see set_execution_bounds). Used to compute the absolute survival bound + # for non-terminal future records. All None => absolute bound disabled. + self._queue_timeout: float | None = None + self._effective_execution_timeout: float | None = None + self._collect_width: int | None = None + # Leader election + metrics-publish loop state. ``metrics_update_interval`` # is a typed parameter (a misspelled key now fails loudly rather than # being silently ignored); it controls how often the leader pushes counts @@ -289,6 +300,7 @@ async def store_future_status( result: Any = None, queue_state: str | None = None, queue_state_reason: str | None = None, + replica_id: str | None = None, ) -> None: """Store task status with optional result. @@ -317,6 +329,7 @@ async def store_future_status( result=result, queue_state=queue_state, queue_state_reason=queue_state_reason, + replica_id=replica_id, ) # ----- Configuration Management ----- @@ -370,7 +383,15 @@ async def cleanup_expired_resources(self) -> dict[str, int]: models_removed = await self._model_mgr.cleanup_expired(cutoff_time, expired_session_ids=expired_session_ids) samplings_removed = await self._sampling_mgr.cleanup_expired( cutoff_time, expired_session_ids=expired_session_ids) - futures_removed = await self._future_mgr.cleanup_expired(cutoff_time) + + # State hygiene for future records (design §5.2): protect non-terminal + # records owned by a live replica, fail orphans, and enforce the absolute + # survival bound. Alive set comes from ReplicaRegistry; absolute_ttl is + # computed only when the execution bounds were injected. + alive_replica_ids = await self._model_mgr.get_alive_replica_ids(self.expiration_timeout) + absolute_ttl = self._absolute_survival_ttl() + futures_removed = await self._future_mgr.cleanup_expired( + cutoff_time, alive_replica_ids=alive_replica_ids, absolute_ttl=absolute_ttl) return { 'sessions': sessions_removed, @@ -379,6 +400,28 @@ async def cleanup_expired_resources(self) -> dict[str, int]: 'futures': futures_removed, } + def set_execution_bounds(self, *, queue_timeout: float, execution_timeout: float, collect_width: int) -> None: + """Inject the execution bounds used to compute the absolute survival TTL. + + Called by ModelManagement after ``_init_task_queue``. ``ServerState`` is a + shared instance obtained via ``get_server_state()``, so these cannot be + constructor arguments; a setter is the injection path (design §5.2). + """ + self._queue_timeout = queue_timeout + self._effective_execution_timeout = execution_timeout + self._collect_width = collect_width + + def _absolute_survival_ttl(self) -> float | None: + """``k * (queue_timeout + Collect_Width * T)`` or ``None`` if not injected.""" + if (self._queue_timeout is None or self._effective_execution_timeout is None or self._collect_width is None): + return None + resource_release_bound = self._collect_width * self._effective_execution_timeout + return _ABSOLUTE_TTL_MULTIPLIER * (self._queue_timeout + resource_release_bound) + + async def touch_replica_last_seen(self, replica_id: str) -> None: + """Refresh a replica's liveness timestamp in the shared registry (R4#6).""" + await self._model_mgr.touch_replica_last_seen(replica_id) + async def _cleanup_loop(self) -> None: """Background task that periodically cleans up expired resources. diff --git a/src/twinkle/server/utils/task_queue/mixin.py b/src/twinkle/server/utils/task_queue/mixin.py index d3f31d2c..9887e259 100644 --- a/src/twinkle/server/utils/task_queue/mixin.py +++ b/src/twinkle/server/utils/task_queue/mixin.py @@ -197,6 +197,7 @@ async def reject(error_msg: str, queue_state: str) -> dict[str, Any]: result=error_payload, queue_state=queue_state, queue_state_reason=error_msg, + replica_id=getattr(self, 'replica_id', None), ) return {'request_id': request_id, 'model_id': model_id} # Private marker consumed by schedule_task_and_wait(). It is not @@ -272,6 +273,7 @@ async def _schedule_task( TaskStatus.PENDING.value, model_id, queue_state=QueueState.ACTIVE.value, + replica_id=getattr(self, 'replica_id', None), ) queue_key = self._queue_key(model_id=model_id, token=token) @@ -422,6 +424,7 @@ async def schedule_background_task( TaskStatus.RUNNING.value, model_id, queue_state=QueueState.ACTIVE.value, + replica_id=getattr(self, 'replica_id', None), ) async def _run() -> None: diff --git a/tests/server/state/test_future_lifecycle.py b/tests/server/state/test_future_lifecycle.py new file mode 100644 index 00000000..bf687044 --- /dev/null +++ b/tests/server/state/test_future_lifecycle.py @@ -0,0 +1,95 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""State-hygiene tests for FutureManager cleanup and the do-not-regress guard. + +Spec: T5.6 / R9#5 / R9#6 / Property 6 / Property 7. Uses the Ray-free FileBackend. +""" +from __future__ import annotations + +from datetime import datetime +from unittest import mock + +import pytest + +from twinkle.server.state.future_manager import FutureManager + + +@pytest.fixture +def manager(tmp_path): + from twinkle.server.state.backend.file_backend import FileBackend + backend = FileBackend(str(tmp_path / 'state.json')) + return FutureManager(backend, expiration_timeout=300.0) + + +def _clock(manager) -> float: + """Now under the same convention the stored ISO timestamps use.""" + return manager._parse_timestamp(datetime.now().isoformat()) + + +async def _store(manager, request_id, status, *, replica_id=None): + await manager.store_status(request_id, status, model_id='m1', replica_id=replica_id) + + +@pytest.mark.asyncio +async def test_non_terminal_with_live_replica_is_kept(manager): + await _store(manager, 'r1', 'running', replica_id='replica-A') + removed = await manager.cleanup_expired( + cutoff_time=_clock(manager) + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) + assert removed == 0 + rec = await manager.get('r1') + assert rec is not None and rec.status == 'running' + + +@pytest.mark.asyncio +async def test_non_terminal_orphan_is_failed_not_deleted(manager): + await _store(manager, 'r2', 'running', replica_id='dead-replica') + await manager.cleanup_expired(cutoff_time=_clock(manager) + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) + rec = await manager.get('r2') + assert rec is not None # NOT deleted (Property 6) + assert rec.status == 'failed' + assert rec.result['category'] == 'Server' + + +@pytest.mark.asyncio +async def test_non_terminal_over_absolute_ttl_is_failed(manager): + await _store(manager, 'r3', 'running', replica_id='replica-A') + # absolute_ttl=0 makes any positive age exceed the bound. + await manager.cleanup_expired(cutoff_time=_clock(manager) + 10, alive_replica_ids={'replica-A'}, absolute_ttl=0.0) + rec = await manager.get('r3') + assert rec is not None and rec.status == 'failed' + + +@pytest.mark.asyncio +async def test_terminal_expired_is_deleted(manager): + await _store(manager, 'r4', 'completed', replica_id='replica-A') + removed = await manager.cleanup_expired( + cutoff_time=_clock(manager) + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) + assert removed == 1 + assert await manager.get('r4') is None + + +@pytest.mark.asyncio +async def test_terminal_to_terminal_different_is_refused_and_warns(manager): + await _store(manager, 'r5', 'failed', replica_id='replica-A') + with mock.patch('twinkle.server.state.future_manager.logger') as log: + await manager.store_status('r5', 'completed', model_id='m1') + rec = await manager.get('r5') + assert rec.status == 'failed' # not overwritten + assert log.warning.called + + +@pytest.mark.asyncio +async def test_terminal_to_terminal_same_is_dropped_without_warning(manager): + await _store(manager, 'r6', 'completed', replica_id='replica-A') + with mock.patch('twinkle.server.state.future_manager.logger') as log: + await manager.store_status('r6', 'completed', model_id='m1') + rec = await manager.get('r6') + assert rec.status == 'completed' + assert not log.warning.called + + +@pytest.mark.asyncio +async def test_replica_id_set_at_creation_not_overwritten(manager): + await _store(manager, 'r7', 'pending', replica_id='replica-A') + await manager.store_status('r7', 'running', model_id='m1', replica_id='replica-B') + rec = await manager.get('r7') + assert rec.replica_id == 'replica-A' # creation value preserved From f461fc373495675e2ec8b18af2825026c26d9811 Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 13:44:21 +0800 Subject: [PATCH 08/14] refactor: remove all silent degradation mechanisms (Phase 7, T7.1-T7.9) - delete TWINKLE_FAIL_FAST from the 4 cookbook server configs (T7.1) - delete Layer 1 (safe_loss/SafeLossWrapper/_zero_loss) + OptimizerGroup.__setattr__ auto-wrap hook + the test_micro_batch safe_loss import/case (T7.2) - delete Layer 2 (@nccl_safe decorator, _force_zero_backward, _iter_model_params) and its two decoration points + import in transformers_model (T7.3) - delete Layer 4: the forward_step_func post-processing try/except in megatron.py, exceptions now propagate; drop the _is_fail_fast import (T7.4) - delete Fail_Fast_Switch: _is_fail_fast + env_propagation NCCL_SAFE_ENV_KEYS/ build_nccl_safe_env_vars and its call (T7.5) - nccl_safe_megatron rewritten to unconditional rank-attributed log + re-raise, no tinker/forward_only params, no degraded return; module docstring records the lost coverage window (T7.6, T7.9) - rewrite both GPU-gated e2e tests to assert failed-terminal + subsequent-success and drop degradation symbols (T7.7) - unified static check asserting the 8 symbols are absent (T7.8) --- cookbook/client/async_rl/server_config.yaml | 8 - .../client/server/megatron/server_config.yaml | 3 - .../server/megatron/server_config_4b.yaml | 8 - .../server/transformer/server_config.yaml | 8 - src/twinkle/model/megatron/megatron.py | 97 ++-- src/twinkle/model/optimizer_group.py | 6 - .../server/launcher/env_propagation.py | 10 - .../server/model/backends/megatron_model.py | 6 +- .../model/backends/transformers_model.py | 3 - src/twinkle/utils/nccl_safe.py | 370 ++------------- tests/model/test_micro_batch.py | 12 - .../integration/test_nccl_safe_tinker_e2e.py | 432 ++---------------- .../integration/test_nccl_safe_twinkle_e2e.py | 331 ++------------ tests/server/static/test_no_degraded_path.py | 68 +++ 14 files changed, 238 insertions(+), 1124 deletions(-) create mode 100644 tests/server/static/test_no_degraded_path.py diff --git a/cookbook/client/async_rl/server_config.yaml b/cookbook/client/async_rl/server_config.yaml index 103ea523..6c0eb612 100644 --- a/cookbook/client/async_rl/server_config.yaml +++ b/cookbook/client/async_rl/server_config.yaml @@ -42,9 +42,6 @@ applications: target_ongoing_requests: 128 ray_actor_options: num_cpus: 0.1 - runtime_env: - env_vars: - TWINKLE_FAIL_FAST: "0" # TransferQueue-backed DataRef service. - name: data-plane @@ -95,7 +92,6 @@ applications: runtime_env: env_vars: TWINKLE_TRUST_REMOTE_CODE: "1" - TWINKLE_FAIL_FAST: "0" # A second GPU hosts vLLM and loads the same local base model. - name: sampler-Qwen3.5-4B @@ -133,7 +129,6 @@ applications: runtime_env: env_vars: TWINKLE_TRUST_REMOTE_CODE: "1" - TWINKLE_FAIL_FAST: "0" - name: processor route_prefix: /api/v1/processor @@ -155,6 +150,3 @@ applications: target_ongoing_requests: 128 ray_actor_options: num_cpus: 0.1 - runtime_env: - env_vars: - TWINKLE_FAIL_FAST: "0" diff --git a/cookbook/client/server/megatron/server_config.yaml b/cookbook/client/server/megatron/server_config.yaml index 24132a07..81d14e75 100644 --- a/cookbook/client/server/megatron/server_config.yaml +++ b/cookbook/client/server/megatron/server_config.yaml @@ -54,7 +54,6 @@ applications: env_vars: TWINKLE_TRUST_REMOTE_CODE: "0" TWINKLE_LONG_POLL_TIMEOUT: "120" - TWINKLE_FAIL_FAST: "0" # 3. Sampler Service - Runs inference / sampling using vLLM engine # Used for generating text from the model (e.g., evaluating LoRA results). @@ -98,7 +97,6 @@ applications: env_vars: TWINKLE_TRUST_REMOTE_CODE: "0" TWINKLE_LONG_POLL_TIMEOUT: "120" - TWINKLE_FAIL_FAST: "0" # 2. Model Service - Hosts the base model for training. # Config: PP=2 x DP=2 on 4 GPUs, ~27GB weights/GPU, comfortable for LoRA training @@ -139,4 +137,3 @@ applications: env_vars: TWINKLE_TRUST_REMOTE_CODE: "0" TWINKLE_LONG_POLL_TIMEOUT: "120" - TWINKLE_FAIL_FAST: "0" diff --git a/cookbook/client/server/megatron/server_config_4b.yaml b/cookbook/client/server/megatron/server_config_4b.yaml index 9bdbd5e7..7eed4699 100644 --- a/cookbook/client/server/megatron/server_config_4b.yaml +++ b/cookbook/client/server/megatron/server_config_4b.yaml @@ -31,9 +31,6 @@ applications: target_ongoing_requests: 128 # Target concurrent requests per replica ray_actor_options: num_cpus: 0.1 # CPU resources allocated to this actor - runtime_env: - env_vars: - TWINKLE_FAIL_FAST: "0" # 2. Model Service (commented out) - Would host the base model for training. # Uncomment and configure if you need a training model worker. @@ -71,7 +68,6 @@ applications: runtime_env: env_vars: TWINKLE_TRUST_REMOTE_CODE: "0" - TWINKLE_FAIL_FAST: "0" # 3. Sampler Service - Runs inference / sampling using vLLM engine # Used for generating text from the model (e.g., evaluating LoRA results). @@ -109,7 +105,6 @@ applications: runtime_env: env_vars: TWINKLE_TRUST_REMOTE_CODE: "0" - TWINKLE_FAIL_FAST: "0" # 4. Processor Service - name: processor @@ -132,6 +127,3 @@ applications: target_ongoing_requests: 128 ray_actor_options: num_cpus: 0.1 - runtime_env: - env_vars: - TWINKLE_FAIL_FAST: "0" diff --git a/cookbook/client/server/transformer/server_config.yaml b/cookbook/client/server/transformer/server_config.yaml index d3ddb2ad..b5d8497f 100644 --- a/cookbook/client/server/transformer/server_config.yaml +++ b/cookbook/client/server/transformer/server_config.yaml @@ -49,9 +49,6 @@ applications: target_ongoing_requests: 128 # Target concurrent requests per replica ray_actor_options: num_cpus: 0.1 # CPU resources allocated to this actor - runtime_env: - env_vars: - TWINKLE_FAIL_FAST: "0" # 2. Model Service - Hosts the base model for training. - name: models-Qwen3.5-4B @@ -85,7 +82,6 @@ applications: runtime_env: env_vars: TWINKLE_TRUST_REMOTE_CODE: "1" - TWINKLE_FAIL_FAST: "0" # 3. Sampler Service - Runs inference / sampling using vLLM engine # Used for generating text from the model (e.g., evaluating LoRA results). @@ -122,7 +118,6 @@ applications: runtime_env: env_vars: TWINKLE_TRUST_REMOTE_CODE: "1" - TWINKLE_FAIL_FAST: "0" # 4. Processor Service - name: processor @@ -145,6 +140,3 @@ applications: target_ongoing_requests: 128 ray_actor_options: num_cpus: 0.1 - runtime_env: - env_vars: - TWINKLE_FAIL_FAST: "0" diff --git a/src/twinkle/model/megatron/megatron.py b/src/twinkle/model/megatron/megatron.py index 617cbdba..89a05db7 100644 --- a/src/twinkle/model/megatron/megatron.py +++ b/src/twinkle/model/megatron/megatron.py @@ -36,7 +36,6 @@ from twinkle.processor import InputProcessor from twinkle.template import Template from twinkle.utils import construct_class, get_logger, selective_log_softmax -from twinkle.utils.nccl_safe import _is_fail_fast from ._mindspeed_runtime import ensure_mindspeed_adaptor_patched from .strategy import MegatronStrategy @@ -420,62 +419,48 @@ def forward_step_func(data_iterator, model): embeddings = None _loss_instance = loss_instance is_last_pp = mpu.is_pipeline_last_stage(False, unwrapped_model.vp_stage) - try: - if task == 'embedding': - # MegatronEmbeddingPatch already pooled output to [n_seqs, hidden] on last PP stage. - if is_last_pp: - embeddings = output_tensor - elif labels is not None and is_last_pp: - _loss_require_logps = getattr(_loss_instance, 'require_logps', True) - _loss_require_entropy = getattr(_loss_instance, 'require_entropy', False) - _packed = batch.get('packed_seq_params') - cu_seqlens_q = getattr(_packed, 'cu_seqlens_q', None) if _packed is not None else None - if _loss_require_logps: - loss_mask = (labels != -100).bool() - masked_labels = labels.clone() - masked_labels[~loss_mask] = 0 - output_tensor.div_(temperature) - if _loss_require_entropy: - logps, entropies = selective_log_softmax(output_tensor, masked_labels, return_entropy=True) - else: - logps = selective_log_softmax(output_tensor, masked_labels) - # Reconstruct full-length tensors from CP-split shards - logps = processor.postprocess_tensor_cp(logps, cu_seqlens=cu_seqlens_q) - if entropies is not None: - entropies = processor.postprocess_tensor_cp(entropies, cu_seqlens=cu_seqlens_q) - batch['labels'] = processor.postprocess_tensor_cp(labels, cu_seqlens=cu_seqlens_q) - if completion_mask is not None: - # Same index space as labels, so it needs the same CP reassembly. - batch['completion_mask'] = processor.postprocess_tensor_cp( - completion_mask, cu_seqlens=cu_seqlens_q) - if 'position_ids' in batch: - pos = batch['position_ids'] - if pos.dim() == 3: - pos = pos[0] # [2/3, 1, seq] → [1, seq] - batch['position_ids'] = processor.postprocess_tensor_cp(pos, cu_seqlens=cu_seqlens_q) - # Unpack packed sequences into per-sequence batch format - _outputs = {'logps': logps} + if task == 'embedding': + # MegatronEmbeddingPatch already pooled output to [n_seqs, hidden] on last PP stage. + if is_last_pp: + embeddings = output_tensor + elif labels is not None and is_last_pp: + _loss_require_logps = getattr(_loss_instance, 'require_logps', True) + _loss_require_entropy = getattr(_loss_instance, 'require_entropy', False) + _packed = batch.get('packed_seq_params') + cu_seqlens_q = getattr(_packed, 'cu_seqlens_q', None) if _packed is not None else None + if _loss_require_logps: + loss_mask = (labels != -100).bool() + masked_labels = labels.clone() + masked_labels[~loss_mask] = 0 + output_tensor.div_(temperature) + if _loss_require_entropy: + logps, entropies = selective_log_softmax(output_tensor, masked_labels, return_entropy=True) + else: + logps = selective_log_softmax(output_tensor, masked_labels) + # Reconstruct full-length tensors from CP-split shards + logps = processor.postprocess_tensor_cp(logps, cu_seqlens=cu_seqlens_q) if entropies is not None: - _outputs['entropies'] = entropies - if hasattr(_loss_instance, 'require_logits') and _loss_instance.require_logits: - _outputs['logits'] = output_tensor - batch, _outputs = processor.unpack_packed_sequences(batch, _outputs) - logps = _outputs['logps'] - entropies = _outputs.get('entropies', None) - unpacked_logits = _outputs.get('logits', None) - except Exception as e: - # Data processing error (e.g. unpack_packed_sequences dimension mismatch). - # Must catch here inside the scheduler to prevent exception escaping - # and breaking PP P2P communication → NCCL hang. - if _is_fail_fast(): - raise - logger.warning('[nccl_safe] forward_step_func data processing error: ' - '%s: %s', - type(e).__name__, e) - logps = None - unpacked_logits = None - entropies = None - embeddings = None + entropies = processor.postprocess_tensor_cp(entropies, cu_seqlens=cu_seqlens_q) + batch['labels'] = processor.postprocess_tensor_cp(labels, cu_seqlens=cu_seqlens_q) + if completion_mask is not None: + # Same index space as labels, so it needs the same CP reassembly. + batch['completion_mask'] = processor.postprocess_tensor_cp( + completion_mask, cu_seqlens=cu_seqlens_q) + if 'position_ids' in batch: + pos = batch['position_ids'] + if pos.dim() == 3: + pos = pos[0] # [2/3, 1, seq] → [1, seq] + batch['position_ids'] = processor.postprocess_tensor_cp(pos, cu_seqlens=cu_seqlens_q) + # Unpack packed sequences into per-sequence batch format + _outputs = {'logps': logps} + if entropies is not None: + _outputs['entropies'] = entropies + if hasattr(_loss_instance, 'require_logits') and _loss_instance.require_logits: + _outputs['logits'] = output_tensor + batch, _outputs = processor.unpack_packed_sequences(batch, _outputs) + logps = _outputs['logps'] + entropies = _outputs.get('entropies', None) + unpacked_logits = _outputs.get('logits', None) return output_tensor, partial( post_loss_function, inputs=batch, diff --git a/src/twinkle/model/optimizer_group.py b/src/twinkle/model/optimizer_group.py index f5177d67..150e694b 100644 --- a/src/twinkle/model/optimizer_group.py +++ b/src/twinkle/model/optimizer_group.py @@ -48,12 +48,6 @@ class BaseOptimizerGroup: _device_mesh: DeviceMesh = None _last_grad_norm: float = 0.0 - def __setattr__(self, name, value): - if name == 'loss_instance' and value is not None: - from twinkle.utils.nccl_safe import safe_loss - value = safe_loss(value) - super().__setattr__(name, value) - def do_grad_sync(self, gradient_accumulation_steps: Optional[int] = None) -> bool: if gradient_accumulation_steps is None: gradient_accumulation_steps = self.gradient_accumulation_steps diff --git a/src/twinkle/server/launcher/env_propagation.py b/src/twinkle/server/launcher/env_propagation.py index 3b0c9b95..4d4a7a47 100644 --- a/src/twinkle/server/launcher/env_propagation.py +++ b/src/twinkle/server/launcher/env_propagation.py @@ -21,10 +21,6 @@ 'TWINKLE_MODEL_ID_ALIASES', ) -# NCCL-safe env var keys: controls fault tolerance behavior in distributed -# training (safe_loss / @nccl_safe). Must reach model worker actors. -NCCL_SAFE_ENV_KEYS: tuple[str, ...] = ('TWINKLE_FAIL_FAST', ) - def build_telemetry_env_vars() -> dict[str, str]: """Collect telemetry env vars from ``os.environ`` for worker propagation.""" @@ -37,15 +33,9 @@ def build_persistence_env_vars() -> dict[str, str]: return {k: os.environ[k] for k in PERSISTENCE_ENV_KEYS if k in os.environ} -def build_nccl_safe_env_vars() -> dict[str, str]: - """Collect NCCL-safe env vars from ``os.environ`` for worker propagation.""" - return {k: os.environ[k] for k in NCCL_SAFE_ENV_KEYS if k in os.environ} - - def build_propagated_env_vars() -> dict[str, str]: """Aggregate all env vars that must reach Ray worker processes.""" merged: dict[str, str] = {} merged.update(build_telemetry_env_vars()) merged.update(build_persistence_env_vars()) - merged.update(build_nccl_safe_env_vars()) return merged diff --git a/src/twinkle/server/model/backends/megatron_model.py b/src/twinkle/server/model/backends/megatron_model.py index 8c9018be..fb3da3f2 100644 --- a/src/twinkle/server/model/backends/megatron_model.py +++ b/src/twinkle/server/model/backends/megatron_model.py @@ -33,7 +33,7 @@ class in the MRO. For full-parameter training the ``adapter_name`` is the """ @remote_function(dispatch='slice_dp', collect=collect_forward_backward_results, sync=True) - @nccl_safe_megatron(tinker=True) + @nccl_safe_megatron def tinker_forward_backward(self, *, inputs: list[types.Datum], adapter_name: str, loss_fn: str, **kwargs): """Combined forward and backward pass.""" self._tinker_setup_loss(loss_fn, inputs, adapter_name, kwargs) @@ -54,7 +54,7 @@ def tinker_forward_backward(self, *, inputs: list[types.Datum], adapter_name: st return [results, loss] @remote_function(dispatch='slice_dp', collect=collect_forward_backward_results) - @nccl_safe_megatron(tinker=True) + @nccl_safe_megatron def tinker_forward_only(self, *, inputs: list[types.Datum], adapter_name: str = None, **kwargs): """Forward pass without gradient computation.""" template = self.get_template(adapter_name) @@ -121,7 +121,7 @@ def tinker_load(self, checkpoint_dir: str, **kwargs): # ------------------------------------------------------------------ @remote_function(dispatch='slice_dp', collect=collect_tensor_dict) - @nccl_safe_megatron(forward_only=True) + @nccl_safe_megatron def forward_only(self, *, inputs: InputFeature | list[InputFeature] | Trajectory | list[Trajectory], **kwargs): """Forward-only for twinkle-native clients (InputFeature/Trajectory I/O).""" output = super().forward_only(inputs=inputs, **kwargs) diff --git a/src/twinkle/server/model/backends/transformers_model.py b/src/twinkle/server/model/backends/transformers_model.py index 3de2da59..a2bcba83 100644 --- a/src/twinkle/server/model/backends/transformers_model.py +++ b/src/twinkle/server/model/backends/transformers_model.py @@ -23,7 +23,6 @@ from twinkle.server.common.datum import datum_to_input_feature, extract_rl_features_for_loss from twinkle.server.model.backends.common import (TwinkleCompatModelBase, clean_metrics, collect_forward_backward_results, to_cpu_safe_output) -from twinkle.utils.nccl_safe import nccl_safe class _TransformersTinkerCompatMixin(TwinkleCompatModelBase): @@ -48,7 +47,6 @@ def tinker_forward_only(self, *, inputs: list[types.Datum], adapter_name: str = return [results, 0.0] @remote_function(dispatch='slice_dp', collect=collect_forward_backward_results) - @nccl_safe(tinker=True) def tinker_forward_backward(self, *, inputs: list[types.Datum], adapter_name: str, loss_fn: str, **kwargs): self._tinker_setup_loss(loss_fn, inputs, adapter_name, kwargs) template = self.get_template(adapter_name) @@ -107,7 +105,6 @@ def forward_only(self, *, inputs: InputFeature | list[InputFeature] | Trajectory return to_cpu_safe_output(output) @remote_function(dispatch='slice_dp', collect=collect_tensor_dict) - @nccl_safe def forward_backward(self, *, inputs: InputFeature | list[InputFeature] | Trajectory | list[Trajectory], **kwargs): """Forward+backward for twinkle-native clients (InputFeature/Trajectory I/O).""" self._normalize_ref_outputs(kwargs) diff --git a/src/twinkle/utils/nccl_safe.py b/src/twinkle/utils/nccl_safe.py index 8bafeb1f..d6633355 100644 --- a/src/twinkle/utils/nccl_safe.py +++ b/src/twinkle/utils/nccl_safe.py @@ -1,339 +1,65 @@ # Copyright (c) ModelScope Contributors. All rights reserved. -"""NCCL-safe utilities for production distributed training. - -Provides three layers of protection to prevent NCCL hangs: - -Layer 1 - safe_loss(): - Wraps loss instances to catch computation errors and return - graph-connected zero loss (ensures FSDP ReduceScatter can proceed). - -Layer 2 - @nccl_safe decorator: - Wraps forward_backward methods to ensure backward() always executes - after forward() has started, even if intermediate code raises. - -Layer 3 - @nccl_safe_megatron decorator: - Wraps Megatron backend methods (forward_only, forward_backward) where - the entire function body involves NCCL communication (sync=True). - Catches pre-communication errors (e.g. data preprocessing failures) - that would otherwise leave other DP ranks waiting at a collective. - -Controlled by environment variable: - TWINKLE_FAIL_FAST=1 (default, development): all protection is transparent, - exceptions propagate normally. - TWINKLE_FAIL_FAST=0 (production): protection activated, exceptions in - NCCL-critical sections are caught and handled gracefully. +"""NCCL critical-section failure logging. + +Single responsibility: inside a Megatron NCCL-critical method, log a +rank-attributed failure and then re-raise it unchanged. + +This module does NOT prevent asymmetric-failure blocking -- nothing at this layer +can. A rank that swallows its exception still does not enter the collective, so the +other ranks stay blocked regardless. The time bound for an asymmetric failure comes +from Ray_Get_Timeout (the effective execution timeout applied per future), not from +this decorator. Diagnosability is the only reason this wrapper exists. + +Coverage removed together with the former Layer 1 (the loss-instance wrapper) and +Layer 2 (the forward/backward decorator) silent degradation: under FSDP, the window +between ``calculate_loss``'s loss call and its surrounding bookkeeping (metric +accumulation, ``status.num_tokens``), between the three calls inside a +``forward_backward`` body, and numerical problems inside a loss (NaN, shape mismatch) +may each constitute a "forward ran, backward did not" asymmetric-failure window. That +window is no longer covered by any silent degradation; its time bound is the two +bounds documented for the task queue (record-terminal = ``queue_timeout + T``; +resource-release = ``Collect_Width * T``). """ import functools -import os -from twinkle.data_format import LossOutput -from twinkle.loss import Loss from twinkle.utils.logger import get_logger logger = get_logger() +# Errors are logged with at most this many trailing characters of traceback. +_TRACEBACK_LIMIT = 8192 -def _is_fail_fast() -> bool: - """Check if fail-fast mode is enabled (default: enabled). - - Returns True (fail-fast/development mode) unless TWINKLE_FAIL_FAST - is explicitly set to a falsy value. - """ - val = os.getenv('TWINKLE_FAIL_FAST', '1').upper() - return val not in ('0', 'NO', 'FALSE', 'OFF') - - -# ─── Layer 1: safe_loss ──────────────────────────────────────────────────── +def _global_rank() -> int: + """Best-effort global rank for failure attribution; -1 if unavailable.""" + try: + from twinkle.utils import Platform + return Platform.get_rank() + except Exception: + return -1 -def safe_loss(loss_instance): - """Wrap loss instance for production graceful degradation. - Always wraps the loss instance (idempotent). The fail-fast check is deferred - to call time so that TWINKLE_FAIL_FAST can be set after wrapping (e.g. in - Ray actor processes where env vars may not be inherited from the launcher). +def nccl_safe_megatron(func): + """Log a rank-attributed failure inside the NCCL critical section, then re-raise. - When TWINKLE_FAIL_FAST=1 (default, development): wrapper is transparent, - exceptions propagate normally. - When TWINKLE_FAIL_FAST=0 (production): wrapper catches exceptions and - returns a graph-connected zero loss (ensures FSDP ReduceScatter proceeds). - - Idempotent: already-wrapped instances are returned as-is. - """ - if getattr(loss_instance, '_nccl_safe_wrapped', False): - return loss_instance - return SafeLossWrapper(loss_instance) - - -class SafeLossWrapper(Loss): - """Loss subclass that catches computation errors and returns graph-connected zero loss. - - Inherits from :class:`twinkle.loss.Loss` so ``isinstance(wrapper, Loss)`` - assertions in the training pipeline continue to pass. + This decorator does *not* prevent asymmetric-failure blocking -- nothing at this + layer can. A rank that swallows its exception still does not enter the collective. + The time bound for that case comes from Ray_Get_Timeout. Diagnosability is the only + reason this wrapper still exists. Its behavior is unconditional: no environment + variable or config switch affects it, and it returns no degraded value. """ - def __init__(self, loss_instance): - super().__init__() - self._loss_instance = loss_instance - self.require_logps = getattr(loss_instance, 'require_logps', True) - self.require_entropy = getattr(loss_instance, 'require_entropy', False) - self.require_logits = getattr(loss_instance, 'require_logits', False) - self.enable_sampling_replay = getattr(loss_instance, 'enable_sampling_replay', False) - self.require_values = getattr(loss_instance, 'require_values', False) - self.reduction = getattr(loss_instance, 'reduction', 'mean') - self._nccl_safe_wrapped = True - - def __call__(self, inputs, outputs, **kwargs): - if _is_fail_fast(): - return self._loss_instance(inputs, outputs, **kwargs) + @functools.wraps(func) + def wrapper(self, *args, **kwargs): try: - return self._loss_instance(inputs, outputs, **kwargs) - except Exception as e: + return func(self, *args, **kwargs) + except Exception as exc: import traceback - logger.warning('[nccl_safe] Loss computation skipped due to error: ' - '%s: %s\n%s', - type(e).__name__, e, traceback.format_exc()) - return _zero_loss(outputs) - - def micro_batch_scale(self, inputs, indices): - """Preserve the wrapped loss's micro-batch reduction semantics.""" - return self._loss_instance.micro_batch_scale(inputs, indices) - - -def _zero_loss(outputs) -> 'LossOutput': - """Create a graph-connected zero loss for FSDP compatibility. - - Finds a gradient-bearing tensor from outputs to maintain graph connectivity, - ensuring backward hooks (ReduceScatter) fire. - """ - import torch - if isinstance(outputs, dict): - for key in ('logps', 'values', 'logits', 'loss'): - t = outputs.get(key) - if t is not None and isinstance(t, torch.Tensor) and t.requires_grad: - return LossOutput(loss=(t.flatten()[:1] * 0).sum(), num_tokens=0) - # Fallback: standalone zero tensor (may not trigger FSDP hooks) - device = 'cpu' - if isinstance(outputs, dict): - for v in outputs.values(): - if hasattr(v, 'device'): - device = v.device - break - return LossOutput(loss=torch.zeros((), device=device, requires_grad=True), num_tokens=0) - - -# ─── Layer 2: @nccl_safe decorator ────────────────────────────────────────── - - -def nccl_safe(func=None, *, tinker=False): - """Decorator ensuring backward() executes if forward() has already run. - - Detects forward completion by comparing train_status.outputs before/after - the wrapped function call. If an exception occurs after forward has run - but before backward completes, forces a zero-gradient backward pass to - prevent NCCL hang (other ranks waiting for ReduceScatter). - - Args: - func: The function to decorate (when used without arguments). - tinker: If True, fallback returns ``[[], 0.0]`` (tinker format). - If False, fallback returns outputs dict with ``loss=0.0``. - - Usage:: - - @remote_function(dispatch='slice_dp', collect=...) - @nccl_safe(tinker=True) - def tinker_forward_backward(self, *, inputs, adapter_name, ...): - # method body completely unchanged - ... - - @remote_function(dispatch='slice_dp', collect=...) - @nccl_safe - def forward_backward(self, *, inputs, **kwargs): - # method body completely unchanged - ... - """ - - def decorator(fn): - - @functools.wraps(fn) - def wrapper(self, *args, **kwargs): - if _is_fail_fast(): - return fn(self, *args, **kwargs) - - # Extract adapter_name for state tracking - adapter_name = kwargs.get('adapter_name') - if adapter_name is None and hasattr(self, '_get_default_group'): - adapter_name = self._get_default_group() - - og = self.optimizer_group.get(adapter_name) if adapter_name else None - if og is None: - # Cannot track state without optimizer group, passthrough - return fn(self, *args, **kwargs) - - # Snapshot state before call to detect forward completion - outputs_before = og.train_status.outputs - - try: - return fn(self, *args, **kwargs) - except Exception as e: - outputs_after = og.train_status.outputs - forward_ran = (outputs_after is not None and outputs_after is not outputs_before) - - if not forward_ran: - # Pre-forward failure: no NCCL ops started, safe to propagate - raise - - # Forward completed. Check if backward already ran. - # TransformersModel.backward() clears loss_value to None. - backward_done = (og.train_status.loss_value is None) - - if backward_done: - # Post-backward failure (e.g. output formatting) - # No NCCL hang risk, just return gracefully - logger.warning(f'[nccl_safe] Post-backward error (no NCCL risk): ' - f'{type(e).__name__}: {e}') - else: - # CRITICAL: forward ran but backward didn't → NCCL hang risk! - logger.warning(f'[nccl_safe] Forcing zero backward to prevent NCCL hang: ' - f'{type(e).__name__}: {e}') - _force_zero_backward(self, og, adapter_name, kwargs) - - # Return fallback result - if tinker: - return [[], 0.0] - outputs_after['loss'] = 0.0 - return outputs_after - - return wrapper - - if func is not None: - # @nccl_safe without arguments - return decorator(func) - # @nccl_safe(tinker=True) with arguments - return decorator - - -def _iter_model_params(model): - """Iterate parameters from ``model.model``, supporting single model or list of models.""" - raw_model = getattr(model, 'model', None) - if raw_model is None: - return iter([]) - if isinstance(raw_model, (list, tuple)): - for m in raw_model: - yield from m.parameters() - else: - yield from raw_model.parameters() - - -def _force_zero_backward(model, og, adapter_name, kwargs): - """Force a zero-gradient backward pass to prevent NCCL hang. - - Creates a graph-connected zero loss tensor and calls backward(), - ensuring FSDP ReduceScatter hooks fire on all ranks. - """ - import torch - - outputs = og.train_status.outputs - - # Find a graph-connected tensor for zero loss - zero_loss = None - if outputs is not None and isinstance(outputs, dict): - for key in ('logps', 'values', 'logits', 'loss'): - t = outputs.get(key) - if t is not None and isinstance(t, torch.Tensor) and t.requires_grad: - zero_loss = (t.flatten()[:1] * 0).sum() - break - - if zero_loss is None: - # Fallback: use first model parameter to maintain graph connectivity. - # Do NOT detach() the parameter -- the zero loss must remain connected - # to the model's autograd graph so FSDP ReduceScatter hooks fire. - # Use lazy iteration to avoid materializing the full parameter list. - try: - param = next((p for p in _iter_model_params(model) if p.requires_grad), None) - if param is not None: - zero_loss = (param.flatten()[0] * 0).sum() - else: - zero_loss = torch.zeros((), device='cuda', requires_grad=True) - except Exception: - zero_loss = torch.zeros((), device='cuda', requires_grad=True) - - og.train_status.loss_value = zero_loss - - # Call backward with minimal kwargs - bwd_kwargs = {'adapter_name': adapter_name} - gas = kwargs.get('gradient_accumulation_steps') - if gas is not None: - bwd_kwargs['gradient_accumulation_steps'] = gas - model.backward(**bwd_kwargs) - - -# ─── Layer 3: @nccl_safe_megatron decorator ────────────────────────────────── - - -def nccl_safe_megatron(func=None, *, tinker=False, forward_only=False): - """Decorator for Megatron backend methods where the entire body is NCCL-critical. - - Unlike @nccl_safe (which detects forward/backward boundaries), this decorator - treats the **entire function** as a NCCL-critical section. In Megatron, - forward_only and forward_backward both call get_forward_backward_func() which - requires all DP ranks to enter synchronously. If one rank fails during data - preprocessing (before entering Megatron's scheduler), other ranks will hang - waiting for the collective. - - This decorator catches ALL exceptions (when TWINKLE_FAIL_FAST=0) and returns - a safe fallback value, preventing NCCL hang from asymmetric failures. - - Args: - func: The function to decorate (when used without arguments). - tinker: If True, fallback returns ``[[], 0.0]`` (tinker format). - forward_only: If True, fallback returns empty dict ``{}`` (forward_only format). - - Usage:: - - @remote_function(dispatch='slice_dp', collect=..., sync=True) - @nccl_safe_megatron - def forward_backward(self, *, inputs, **kwargs): - ... - - @remote_function(dispatch='slice_dp', collect=...) - @nccl_safe_megatron(forward_only=True) - def forward_only(self, *, inputs, **kwargs): - ... - - @remote_function(dispatch='slice_dp', collect=..., sync=True) - @nccl_safe_megatron(tinker=True) - def tinker_forward_backward(self, *, inputs, **kwargs): - ... - """ - - def decorator(fn): - - @functools.wraps(fn) - def wrapper(self, *args, **kwargs): - if _is_fail_fast(): - return fn(self, *args, **kwargs) - - try: - return fn(self, *args, **kwargs) - except Exception as e: - import traceback - logger.warning(f'[nccl_safe_megatron] Exception in Megatron method ' - f'{fn.__name__}: {type(e).__name__}: {e}\n' - f'{traceback.format_exc()}') - - # Return safe fallback to prevent NCCL hang on other ranks - if tinker: - return [[], 0.0] - if forward_only: - return {} - # forward_backward fallback: return dict with loss=0.0 - return {'loss': 0.0} - - return wrapper - - if func is not None: - # @nccl_safe_megatron without arguments - return decorator(func) - # @nccl_safe_megatron(tinker=True) with arguments - return decorator + tb = traceback.format_exc() + if len(tb) > _TRACEBACK_LIMIT: + tb = tb[-_TRACEBACK_LIMIT:] + logger.error('[nccl_safe_megatron] %s in %s on global rank %s:\n%s', type(exc).__name__, func.__name__, + _global_rank(), tb) + raise + + return wrapper diff --git a/tests/model/test_micro_batch.py b/tests/model/test_micro_batch.py index 8d21c1db..ec4083e9 100644 --- a/tests/model/test_micro_batch.py +++ b/tests/model/test_micro_batch.py @@ -8,7 +8,6 @@ from twinkle.model.micro_batch import MicroBatchConfig, plan_micro_batches from twinkle.model.transformers.transformers import TransformersModel from twinkle.processor import InputProcessor -from twinkle.utils.nccl_safe import safe_loss @pytest.mark.parametrize('packing_algorithm', ['ffd', 'kk']) @@ -72,17 +71,6 @@ def test_sample_mean_and_token_sum_micro_batch_scales(): assert CrossEntropyLoss(reduction='sum').micro_batch_scale(inputs, [0]) == 1.0 -def test_safe_loss_preserves_wrapped_micro_batch_scale(): - inputs = [ - {'labels': [1, -100]}, - {'labels': [2, 3]}, - {'labels': [4, -100]}, - {'labels': [5, 6]}, - ] - - assert safe_loss(GRPOLoss()).micro_batch_scale(inputs, [0, 2]) == .5 - - def test_loss_without_micro_batch_semantics_fails_when_split(): with pytest.raises(NotImplementedError, match='does not support micro-batching'): Loss().micro_batch_scale([{}, {}], [0]) diff --git a/tests/server/integration/test_nccl_safe_tinker_e2e.py b/tests/server/integration/test_nccl_safe_tinker_e2e.py index aa94f99c..b47666b9 100644 --- a/tests/server/integration/test_nccl_safe_tinker_e2e.py +++ b/tests/server/integration/test_nccl_safe_tinker_e2e.py @@ -1,16 +1,15 @@ # Copyright (c) ModelScope Contributors. All rights reserved. -"""Real E2E test for NCCL-safe fault tolerance via Tinker client path. +"""Real E2E test for loud-failure semantics via the Tinker client path. -Exercises the /tinker/forward_backward endpoint through the upstream Tinker SDK. -All adversarial scenarios verify that safe_loss catches errors gracefully without -NCCL hang or model state corruption. +Exercises ``/tinker/forward_backward`` through the upstream Tinker SDK. The +invariant under test (post silent-degradation removal): a request whose loss +computation fails does NOT come back as a silent zero-loss success -- it enters a +failed terminal state -- and a subsequent valid request on the same deployment +still succeeds. Prerequisites: - 1. Ray cluster running with GPUs (2 for model DP/TP, optionally 1 for sampler) - 2. Twinkle server started with TWINKLE_FAIL_FAST=0 - -Usage (direct): - python tests/server/integration/test_nccl_safe_tinker_e2e.py + 1. Ray cluster running with GPUs (2 for model DP/TP) + 2. Twinkle server started (no fault-tolerance env switch exists any more) Usage (pytest, requires TWINKLE_TEST_GPU_E2E=1): TWINKLE_TEST_GPU_E2E=1 pytest tests/server/integration/test_nccl_safe_tinker_e2e.py -v @@ -18,10 +17,7 @@ from __future__ import annotations import os -import sys import time -import logging -import traceback import numpy as np import pytest @@ -31,409 +27,61 @@ reason='Set TWINKLE_TEST_GPU_E2E=1 to run real GPU E2E tests (requires running server)', ) -logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s') -logger = logging.getLogger(__name__) - - -def log(msg): - """Print + flush to avoid log suppression by init_tinker_client().""" - print(f'[E2E-Tinker] {msg}', flush=True) - - BASE_MODEL = 'Qwen/Qwen3.5-4B' SERVER_URL = os.environ.get('TWINKLE_SERVER_URL', 'http://localhost:9000') TIMEOUT = 120 -def wait_for_server(url, timeout=300): - """Wait for Twinkle server to become ready.""" - import requests - start = time.time() - while time.time() - start < timeout: - try: - resp = requests.get(f'{url}/-/routes', timeout=5) - if resp.status_code == 200: - elapsed = int(time.time() - start) - log(f'Server is ready (waited {elapsed}s)') - return True - except Exception: - pass - time.sleep(5) - raise TimeoutError(f'Server not ready after {timeout}s') - - -def init_client(): - """Initialize Tinker client and create training client.""" +def _init_client(): os.environ['TINKER_BASE_URL'] = SERVER_URL os.environ['TWINKLE_SERVER_TOKEN'] = 'EMPTY_TOKEN' - from twinkle_client import init_tinker_client init_tinker_client() - from tinker import ServiceClient - service_client = ServiceClient() - training_client = service_client.create_lora_training_client(base_model=BASE_MODEL, rank=16) - log('Training client created successfully') - return training_client + return ServiceClient().create_lora_training_client(base_model=BASE_MODEL, rank=16) -def make_datum(seq_len=32, completion_len=16, *, bad_logprobs_len=None, include_advantages=True): - """Construct a Datum for GRPO training.""" +def _make_datum(seq_len=64, completion_len=32, *, bad_logprobs_len=None): from tinker import types - prompt_len = seq_len - completion_len input_tokens = list(range(1, seq_len + 1)) target_tokens = [0] * prompt_len + list(range(100, 100 + completion_len)) weights = [0] * prompt_len + [1] * completion_len - - if bad_logprobs_len is not None: - logprobs_values = np.random.randn(bad_logprobs_len).astype(np.float32) - padded_logprobs = [0.0] * prompt_len + logprobs_values.tolist() - else: - logprobs_values = np.random.randn(completion_len).astype(np.float32) - padded_logprobs = [0.0] * prompt_len + logprobs_values.tolist() - - loss_fn_inputs = { - 'target_tokens': target_tokens, - 'weights': weights, - 'logprobs': types.TensorData.from_numpy(np.array(padded_logprobs, dtype=np.float32)), - } - - if include_advantages: - advantage = float(np.random.randn()) - padded_advantages = [0.0] * prompt_len + [advantage] * completion_len - loss_fn_inputs['advantages'] = types.TensorData.from_numpy( - np.array(padded_advantages, dtype=np.float32)) - + n = bad_logprobs_len if bad_logprobs_len is not None else completion_len + padded_logprobs = [0.0] * prompt_len + np.random.randn(n).astype(np.float32).tolist() + advantage = float(np.random.randn()) return types.Datum( model_input=types.ModelInput.from_ints(input_tokens), - loss_fn_inputs=loss_fn_inputs, + loss_fn_inputs={ + 'target_tokens': target_tokens, + 'weights': weights, + 'logprobs': types.TensorData.from_numpy(np.array(padded_logprobs, dtype=np.float32)), + 'advantages': types.TensorData.from_numpy( + np.array([0.0] * prompt_len + [advantage] * completion_len, dtype=np.float32)), + }, ) -def run_forward_backward(training_client, datums, test_name, expect_success=True): - """Run forward_backward and return (success, result, elapsed_seconds).""" - log(f'[{test_name}] Sending {len(datums)} datums...') - start = time.time() - try: - result = training_client.forward_backward(datums, 'importance_sampling').result() - elapsed = time.time() - start - log(f'[{test_name}] Completed in {elapsed:.1f}s') - if hasattr(result, 'metrics') and result.metrics: - loss_avg = result.metrics.get('loss:avg', 'N/A') - log(f'[{test_name}] loss:avg = {loss_avg}') - return True, result, elapsed - except Exception as e: - elapsed = time.time() - start - log(f'[{test_name}] FAILED in {elapsed:.1f}s: {type(e).__name__}: {e}') - if elapsed > TIMEOUT: - log(f'[{test_name}] TIMEOUT! This suggests NCCL hang!') - return False, None, elapsed - - -def do_optim_step(training_client, test_name): - """Run optimizer step.""" - from tinker import types - try: - training_client.optim_step(types.AdamParams(learning_rate=1e-5)).result() - log(f'[{test_name}] optim_step OK') - return True - except Exception as e: - log(f'[{test_name}] optim_step FAILED: {e}') - return False - - -# ═══════════════════════════════════════════════════════════════════════════ -# Test Scenarios (19 tests) -# ═══════════════════════════════════════════════════════════════════════════ - -def test_1_normal_grpo(tc): - datums = [make_datum(seq_len=64, completion_len=32) for _ in range(4)] - ok, result, elapsed = run_forward_backward(tc, datums, 'TEST-1-NORMAL') - assert ok and elapsed < TIMEOUT - do_optim_step(tc, 'TEST-1-NORMAL') - return True - -def test_2_bad_old_logps(tc): - datums = [ - make_datum(seq_len=64, completion_len=32), - make_datum(seq_len=64, completion_len=32, bad_logprobs_len=5), - make_datum(seq_len=64, completion_len=32), - make_datum(seq_len=64, completion_len=32, bad_logprobs_len=99), - ] - ok, result, elapsed = run_forward_backward(tc, datums, 'TEST-2-BAD-LOGPS') - if not ok: - return elapsed < TIMEOUT - assert elapsed < TIMEOUT - do_optim_step(tc, 'TEST-2-BAD-LOGPS') - return True - -def test_3_recovery(tc): - datums = [make_datum(seq_len=64, completion_len=32) for _ in range(4)] - ok, _, elapsed = run_forward_backward(tc, datums, 'TEST-3-RECOVERY') - assert ok and elapsed < TIMEOUT - do_optim_step(tc, 'TEST-3-RECOVERY') - return True - -def test_4_no_advantages(tc): - datums = [make_datum(seq_len=64, completion_len=32, include_advantages=False) for _ in range(4)] - ok, _, elapsed = run_forward_backward(tc, datums, 'TEST-4-NO-ADV') - assert ok and elapsed < TIMEOUT - do_optim_step(tc, 'TEST-4-NO-ADV') - return True - -def test_5_consecutive_bad(tc): - for i in range(5): - datums = [make_datum(seq_len=64, completion_len=32, bad_logprobs_len=3+i) for _ in range(4)] - _, _, elapsed = run_forward_backward(tc, datums, f'TEST-5-{i+1}') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, f'TEST-5-{i+1}') - return True +def test_failure_is_terminal_then_valid_request_succeeds(): + """A malformed request fails loudly (terminal), a subsequent valid one succeeds. -def test_6_nan_logprobs(tc): + Replaces the former assertion "failure degraded to zero loss and training + continued". If the recovery request does not reach a terminal success, that is + recorded as evidence that R3#2-3 actor recovery and R2#3-4 admission gate are + necessary, not optional. + """ from tinker import types - datums = [] - for _ in range(4): - d = make_datum(seq_len=64, completion_len=32) - d.loss_fn_inputs['logprobs'] = types.TensorData.from_numpy( - np.array([float('nan')] * 64, dtype=np.float32)) - datums.append(d) - _, _, elapsed = run_forward_backward(tc, datums, 'TEST-6-NAN') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-6-NAN') - return True + tc = _init_client() -def test_7_inf_logprobs(tc): - from tinker import types - datums = [] - for _ in range(4): - d = make_datum(seq_len=64, completion_len=32) - inf_arr = np.full(64, float('inf'), dtype=np.float32) - inf_arr[::2] = float('-inf') - d.loss_fn_inputs['logprobs'] = types.TensorData.from_numpy(inf_arr) - datums.append(d) - _, _, elapsed = run_forward_backward(tc, datums, 'TEST-7-INF') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-7-INF') - return True - -def test_8_extreme_advantages(tc): - from tinker import types - datums = [] - for i in range(4): - d = make_datum(seq_len=64, completion_len=32) - val = 1e30 if i % 2 == 0 else -1e30 - adv = np.full(64, 0.0, dtype=np.float32) - adv[32:] = val - d.loss_fn_inputs['advantages'] = types.TensorData.from_numpy(adv) - datums.append(d) - _, _, elapsed = run_forward_backward(tc, datums, 'TEST-8-EXTREME-ADV') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-8-EXTREME-ADV') - return True - -def test_9_zero_completion(tc): - from tinker import types - datums = [] - for _ in range(4): - d = types.Datum( - model_input=types.ModelInput.from_ints(list(range(1, 65))), - loss_fn_inputs={ - 'target_tokens': [0]*64, 'weights': [0]*64, - 'logprobs': types.TensorData.from_numpy(np.zeros(64, dtype=np.float32)), - 'advantages': types.TensorData.from_numpy(np.zeros(64, dtype=np.float32)), - }, - ) - datums.append(d) - _, _, elapsed = run_forward_backward(tc, datums, 'TEST-9-ZERO-COMPL') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-9-ZERO-COMPL') - return True - -def test_10_partial_advantages(tc): - datums = [ - make_datum(seq_len=64, completion_len=32, include_advantages=True), - make_datum(seq_len=64, completion_len=32, include_advantages=False), - make_datum(seq_len=64, completion_len=32, include_advantages=True), - make_datum(seq_len=64, completion_len=32, include_advantages=False), - ] - _, _, elapsed = run_forward_backward(tc, datums, 'TEST-10-PARTIAL-ADV') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-10-PARTIAL-ADV') - return True - -def test_11_mixed_seq_lengths(tc): - datums = [ - make_datum(seq_len=32, completion_len=16), - make_datum(seq_len=128, completion_len=64), - make_datum(seq_len=48, completion_len=24), - make_datum(seq_len=96, completion_len=48), - ] - _, _, elapsed = run_forward_backward(tc, datums, 'TEST-11-MIXED') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-11-MIXED') - return True - -def test_12_all_bad(tc): - datums = [make_datum(seq_len=64, completion_len=32, bad_logprobs_len=i) for i in range(4)] - _, _, elapsed = run_forward_backward(tc, datums, 'TEST-12-ALL-BAD') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-12-ALL-BAD') - return True - -def test_13_forward_only_then_train(tc): - datums_infer = [make_datum(seq_len=64, completion_len=32, include_advantages=False) for _ in range(4)] + # Deliberately malformed: logprobs length inconsistent with the completion. + bad = [_make_datum(bad_logprobs_len=5) for _ in range(4)] start = time.time() - try: - tc.forward(datums_infer).result() - except Exception: - if time.time() - start >= TIMEOUT: - return False - datums_train = [make_datum(seq_len=64, completion_len=32) for _ in range(4)] - ok, _, elapsed = run_forward_backward(tc, datums_train, 'TEST-13-TRAIN') - if not ok or elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-13-TRAIN') - return True - -def test_14_rapid_bad_good(tc): - for i in range(5): - bad = [make_datum(seq_len=64, completion_len=32, bad_logprobs_len=i+1) for _ in range(4)] - _, _, elapsed = run_forward_backward(tc, bad, f'TEST-14-BAD-{i+1}') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, f'TEST-14-BAD-{i+1}') - good = [make_datum(seq_len=64, completion_len=32) for _ in range(4)] - ok, _, elapsed = run_forward_backward(tc, good, f'TEST-14-GOOD-{i+1}') - if not ok or elapsed >= TIMEOUT: - return False - do_optim_step(tc, f'TEST-14-GOOD-{i+1}') - return True - -def test_15_final_health(tc): - datums = [make_datum(seq_len=64, completion_len=32) for _ in range(4)] - ok, _, elapsed = run_forward_backward(tc, datums, 'TEST-15-FINAL') - assert ok and elapsed < TIMEOUT - do_optim_step(tc, 'TEST-15-FINAL') - return True - -def test_16_large_batch(tc): - datums = [make_datum(seq_len=64, completion_len=32) for _ in range(16)] - ok, _, elapsed = run_forward_backward(tc, datums, 'TEST-16-LARGE') - if elapsed >= TIMEOUT: - return False - assert ok - do_optim_step(tc, 'TEST-16-LARGE') - return True - -def test_17_single_datum(tc): - # With dp_size=2 + nproc_per_node=2, minimum batch must be >= data_world_size - datums = [make_datum(seq_len=64, completion_len=32) for _ in range(4)] - ok, _, elapsed = run_forward_backward(tc, datums, 'TEST-17-SMALL') - if elapsed >= TIMEOUT: - return False - assert ok - do_optim_step(tc, 'TEST-17-SMALL') - return True - -def test_18_save_after_error(tc): - bad = [make_datum(seq_len=64, completion_len=32, bad_logprobs_len=2) for _ in range(4)] - _, _, elapsed = run_forward_backward(tc, bad, 'TEST-18-ERR') - if elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-18-ERR') - try: - tc.save_weights_for_sampler().result() - except Exception: - pass - good = [make_datum(seq_len=64, completion_len=32) for _ in range(4)] - ok, _, elapsed = run_forward_backward(tc, good, 'TEST-18-POST') - if not ok or elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-18-POST') - return True - -def test_19_consecutive_optim_steps(tc): - datums = [make_datum(seq_len=64, completion_len=32) for _ in range(4)] - ok, _, elapsed = run_forward_backward(tc, datums, 'TEST-19-BASE') - assert ok and elapsed < TIMEOUT - for i in range(3): - do_optim_step(tc, f'TEST-19-STEP-{i+1}') - datums = [make_datum(seq_len=64, completion_len=32) for _ in range(4)] - ok, _, elapsed = run_forward_backward(tc, datums, 'TEST-19-VERIFY') - if not ok or elapsed >= TIMEOUT: - return False - do_optim_step(tc, 'TEST-19-VERIFY') - return True - - -ALL_TESTS = [ - ('TEST-1: Normal GRPO Training', test_1_normal_grpo), - ('TEST-2: Bad old_logps (original bug)', test_2_bad_old_logps), - ('TEST-3: Recovery after error', test_3_recovery), - ('TEST-4: No advantages (zero loss)', test_4_no_advantages), - ('TEST-5: Consecutive bad batches', test_5_consecutive_bad), - ('TEST-6: NaN logprobs', test_6_nan_logprobs), - ('TEST-7: +Inf/-Inf logprobs', test_7_inf_logprobs), - ('TEST-8: Extreme advantages (1e30)', test_8_extreme_advantages), - ('TEST-9: Zero completion tokens', test_9_zero_completion), - ('TEST-10: Partial advantages (ragged)', test_10_partial_advantages), - ('TEST-11: Mixed sequence lengths', test_11_mixed_seq_lengths), - ('TEST-12: All datums bad (100%)', test_12_all_bad), - ('TEST-13: forward_only then train', test_13_forward_only_then_train), - ('TEST-14: Rapid bad->good alternation', test_14_rapid_bad_good), - ('TEST-15: Final health check', test_15_final_health), - ('TEST-16: Large batch (16 datums)', test_16_large_batch), - ('TEST-17: Single datum batch', test_17_single_datum), - ('TEST-18: Save after error', test_18_save_after_error), - ('TEST-19: Consecutive optim_steps', test_19_consecutive_optim_steps), -] - - -def main(): - log('=' * 60) - log('NCCL-Safe E2E Test - Tinker Client Path') - log('=' * 60) - log(f'Server URL: {SERVER_URL}') - log(f'Base Model: {BASE_MODEL}') - log(f'TWINKLE_FAIL_FAST = {os.getenv("TWINKLE_FAIL_FAST", "1 (default)")}') - - wait_for_server(SERVER_URL) - tc = init_client() - - results = [] - for name, test_fn in ALL_TESTS: - log(f'\n{"=" * 60}\n{name}\n{"=" * 60}') - try: - passed = test_fn(tc) - results.append((name, 'PASS' if passed else 'FAIL')) - log(f'[{name}] {"PASS" if passed else "FAIL"}') - except Exception as e: - log(f'{name}: EXCEPTION: {e}') - traceback.print_exc() - results.append((name, 'FAIL')) - - log(f'\n{"=" * 60}\nRESULTS SUMMARY\n{"=" * 60}') - all_passed = all(s == 'PASS' for _, s in results) - for name, status in results: - log(f' [{status}] {name}') - log(f'\n{"ALL" if all_passed else "SOME"} {len(results)} TESTS {"PASSED" if all_passed else "FAILED"}!') - return 0 if all_passed else 1 - - -def test_nccl_safe_tinker_e2e(): - """Pytest-collected entry point.""" - rc = main() - assert rc == 0, 'Some Tinker NCCL-safe E2E tests failed' - - -if __name__ == '__main__': - sys.exit(main()) + with pytest.raises(Exception): # RequestFailedError or a raised failed terminal + tc.forward_backward(bad, 'importance_sampling').result() + assert time.time() - start < TIMEOUT, 'malformed request must fail fast, not hang (NCCL)' + + # Recovery: a subsequent valid request on the same deployment must succeed. + good = [_make_datum() for _ in range(4)] + result = tc.forward_backward(good, 'importance_sampling').result() + assert result is not None + tc.optim_step(types.AdamParams(learning_rate=1e-5)).result() diff --git a/tests/server/integration/test_nccl_safe_twinkle_e2e.py b/tests/server/integration/test_nccl_safe_twinkle_e2e.py index c9cce48a..90a33cf3 100644 --- a/tests/server/integration/test_nccl_safe_twinkle_e2e.py +++ b/tests/server/integration/test_nccl_safe_twinkle_e2e.py @@ -1,16 +1,14 @@ # Copyright (c) ModelScope Contributors. All rights reserved. -"""Real E2E test for NCCL-safe fault tolerance via Twinkle client path. +"""Real E2E test for loud-failure semantics via the Twinkle-native client path. -Exercises the /twinkle/forward_backward endpoint through the Twinkle SDK -(init_twinkle_client + MultiLoraTransformersModel). This is a SEPARATE code -path from the Tinker SDK (/tinker/forward_backward). +Exercises ``/twinkle/forward_backward`` through the Twinkle client. The invariant +under test (post silent-degradation removal): a request whose loss computation fails +does NOT come back as a silent zero-loss success -- it fails loudly -- and a +subsequent valid request on the same deployment still succeeds. Prerequisites: - 1. Ray cluster running with GPUs (2 for model DP/TP, optionally 1 for sampler) - 2. Twinkle server started with TWINKLE_FAIL_FAST=0 - -Usage (direct): - python tests/server/integration/test_nccl_safe_twinkle_e2e.py + 1. Ray cluster running with GPUs (2 for model DP/TP) + 2. Twinkle server started (no fault-tolerance env switch exists any more) Usage (pytest, requires TWINKLE_TEST_GPU_E2E=1): TWINKLE_TEST_GPU_E2E=1 pytest tests/server/integration/test_nccl_safe_twinkle_e2e.py -v @@ -18,11 +16,7 @@ from __future__ import annotations import os -import sys import time -import logging -import traceback -from typing import Any, Dict, List import numpy as np import pytest @@ -32,44 +26,18 @@ reason='Set TWINKLE_TEST_GPU_E2E=1 to run real GPU E2E tests (requires running server)', ) -logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(message)s') -logger = logging.getLogger(__name__) - - -def log(msg): - print(f'[E2E-Twinkle] {msg}', flush=True) - - BASE_MODEL = 'Qwen/Qwen3.5-4B' SERVER_URL = os.environ.get('TWINKLE_SERVER_URL', 'http://localhost:9000') TIMEOUT = 120 -ADAPTER_NAME = 'nccl-safe-test' +ADAPTER_NAME = 'loud-failure-test' -def wait_for_server(url, timeout=300): - """Wait for Twinkle server to become ready.""" - import requests - start = time.time() - while time.time() - start < timeout: - try: - resp = requests.get(f'{url}/-/routes', timeout=5) - if resp.status_code == 200: - log(f'Server is ready (waited {int(time.time() - start)}s)') - return True - except Exception: - pass - time.sleep(5) - raise TimeoutError(f'Server not ready after {timeout}s') - - -def init_client(): - """Initialize Twinkle client and configure model for GRPO training.""" +def _init_client(): + from peft import LoraConfig from twinkle_client import init_twinkle_client from twinkle_client.model import MultiLoraTransformersModel - from peft import LoraConfig init_twinkle_client(base_url=SERVER_URL, api_key='EMPTY_TOKEN') - model = MultiLoraTransformersModel(model_id=f'ms://{BASE_MODEL}') model.add_adapter_to_model( adapter_name=ADAPTER_NAME, @@ -80,266 +48,43 @@ def init_client(): model.set_optimizer('Adam', lr=1e-5) model.set_template('Qwen3_5Template') model.set_processor('InputProcessor', padding_side='right') - log('Twinkle client + model configured successfully') return model -def make_input_features( - batch_size=4, seq_len=64, completion_len=32, *, - bad_old_logps_len=None, include_advantages=True, - nan_old_logps=False, extreme_advantages=None, all_labels_masked=False, -): - """Construct InputFeature list + old_logps + advantages for GRPO.""" +def _make_inputs(batch_size=4, seq_len=64, completion_len=32, *, bad_old_logps_len=None): prompt_len = seq_len - completion_len - input_features = [] - old_logps_list = [] - advantages_list = [] - - for i in range(batch_size): - input_ids = list(range(1, seq_len + 1)) - labels = [-100] * seq_len if all_labels_masked else ( - [-100] * prompt_len + list(range(100, 100 + completion_len))) - input_features.append({ - 'input_ids': input_ids, - 'labels': labels, + features, old_logps, advantages = [], [], [] + for _ in range(batch_size): + features.append({ + 'input_ids': list(range(1, seq_len + 1)), + 'labels': [-100] * prompt_len + list(range(100, 100 + completion_len)), 'attention_mask': [1] * seq_len, 'position_ids': list(range(seq_len)), }) - - if bad_old_logps_len is not None: - logps = np.random.randn(bad_old_logps_len).tolist() - elif nan_old_logps: - logps = [float('nan')] * completion_len - else: - logps = np.random.randn(completion_len).tolist() - old_logps_list.append(logps) - - if extreme_advantages is not None: - advantages_list.append(extreme_advantages if i % 2 == 0 else -extreme_advantages) - else: - advantages_list.append(float(np.random.randn())) - - old_logps = old_logps_list if include_advantages else None - advantages = advantages_list if include_advantages else None - return input_features, old_logps, advantages - - -def run_forward_backward(model, inputs, old_logps, advantages, test_name): - """Run forward_backward and return (success, result, elapsed_seconds).""" - log(f'[{test_name}] Sending {len(inputs)} input features...') - start = time.time() - try: - kwargs: Dict[str, Any] = {} - if old_logps is not None: - kwargs['old_logps'] = old_logps - if advantages is not None: - kwargs['advantages'] = advantages - - result = model.forward_backward(inputs=inputs, **kwargs) - elapsed = time.time() - start - log(f'[{test_name}] Completed in {elapsed:.1f}s') - if hasattr(result, 'result') and result.result is not None: - log(f'[{test_name}] result = {result.result}') - return True, result, elapsed - except Exception as e: - elapsed = time.time() - start - log(f'[{test_name}] FAILED in {elapsed:.1f}s: {type(e).__name__}: {e}') - if elapsed > TIMEOUT: - log(f'[{test_name}] TIMEOUT! This suggests NCCL hang!') - return False, None, elapsed - - -def do_optim_step(model, test_name): - """Run clip_grad_and_step.""" - try: - model.clip_grad_and_step() - log(f'[{test_name}] clip_grad_and_step OK') - return True - except Exception as e: - log(f'[{test_name}] clip_grad_and_step FAILED: {e}') - return False + n = bad_old_logps_len if bad_old_logps_len is not None else completion_len + old_logps.append(np.random.randn(n).tolist()) + advantages.append(float(np.random.randn())) + return features, old_logps, advantages -# ═══════════════════════════════════════════════════════════════════════════ -# Test Scenarios (12 tests) -# ═══════════════════════════════════════════════════════════════════════════ +def test_failure_is_terminal_then_valid_request_succeeds(): + """A malformed request fails loudly, a subsequent valid one succeeds. -def test_1_normal_grpo(m): - inputs, old_logps, adv = make_input_features(batch_size=4) - ok, _, elapsed = run_forward_backward(m, inputs, old_logps, adv, 'TEST-1-NORMAL') - assert ok and elapsed < TIMEOUT - do_optim_step(m, 'TEST-1-NORMAL') - return True + Replaces the former assertion "failure degraded to zero loss and training + continued". If the recovery request does not reach a terminal success, that is + recorded as evidence that R3#2-3 actor recovery and R2#3-4 admission gate are + necessary, not optional. + """ + model = _init_client() -def test_2_bad_old_logps(m): - inputs, old_logps, adv = make_input_features(batch_size=4, bad_old_logps_len=5) - ok, _, elapsed = run_forward_backward(m, inputs, old_logps, adv, 'TEST-2-BAD-LOGPS') - if not ok: - return elapsed < TIMEOUT - assert elapsed < TIMEOUT - do_optim_step(m, 'TEST-2-BAD-LOGPS') - return True - -def test_3_recovery(m): - inputs, old_logps, adv = make_input_features(batch_size=4) - ok, _, elapsed = run_forward_backward(m, inputs, old_logps, adv, 'TEST-3-RECOVERY') - assert ok and elapsed < TIMEOUT - do_optim_step(m, 'TEST-3-RECOVERY') - return True - -def test_4_nan_old_logps(m): - inputs, old_logps, adv = make_input_features(batch_size=4, nan_old_logps=True) - _, _, elapsed = run_forward_backward(m, inputs, old_logps, adv, 'TEST-4-NAN') - if elapsed >= TIMEOUT: - return False - do_optim_step(m, 'TEST-4-NAN') - return True - -def test_5_extreme_advantages(m): - inputs, old_logps, adv = make_input_features(batch_size=4, extreme_advantages=1e30) - _, _, elapsed = run_forward_backward(m, inputs, old_logps, adv, 'TEST-5-EXTREME') - if elapsed >= TIMEOUT: - return False - do_optim_step(m, 'TEST-5-EXTREME') - return True - -def test_6_all_labels_masked(m): - inputs, old_logps, adv = make_input_features(batch_size=4, all_labels_masked=True) - _, _, elapsed = run_forward_backward(m, inputs, old_logps, adv, 'TEST-6-MASKED') - if elapsed >= TIMEOUT: - return False - do_optim_step(m, 'TEST-6-MASKED') - return True - -def test_7_consecutive_bad(m): - for i in range(5): - inputs, old_logps, adv = make_input_features(batch_size=4, bad_old_logps_len=i+1) - _, _, elapsed = run_forward_backward(m, inputs, old_logps, adv, f'TEST-7-{i+1}') - if elapsed >= TIMEOUT: - return False - do_optim_step(m, f'TEST-7-{i+1}') - return True - -def test_8_rapid_bad_good(m): - for i in range(5): - bad_in, bad_lp, bad_adv = make_input_features(batch_size=4, bad_old_logps_len=i+1) - _, _, elapsed = run_forward_backward(m, bad_in, bad_lp, bad_adv, f'TEST-8-BAD-{i+1}') - if elapsed >= TIMEOUT: - return False - do_optim_step(m, f'TEST-8-BAD-{i+1}') - good_in, good_lp, good_adv = make_input_features(batch_size=4) - ok, _, elapsed = run_forward_backward(m, good_in, good_lp, good_adv, f'TEST-8-GOOD-{i+1}') - if not ok or elapsed >= TIMEOUT: - return False - do_optim_step(m, f'TEST-8-GOOD-{i+1}') - return True - -def test_9_final_health(m): - inputs, old_logps, adv = make_input_features(batch_size=4) - ok, _, elapsed = run_forward_backward(m, inputs, old_logps, adv, 'TEST-9-FINAL') - assert ok and elapsed < TIMEOUT - do_optim_step(m, 'TEST-9-FINAL') - return True - -def test_10_gradient_accumulation_error(m): - inputs, lp, adv = make_input_features(batch_size=4) - ok, _, elapsed = run_forward_backward(m, inputs, lp, adv, 'TEST-10-GA1') - if not ok or elapsed >= TIMEOUT: - return False - bad_in, bad_lp, bad_adv = make_input_features(batch_size=4, bad_old_logps_len=3) - _, _, elapsed = run_forward_backward(m, bad_in, bad_lp, bad_adv, 'TEST-10-GA2-BAD') - if elapsed >= TIMEOUT: - return False - inputs, lp, adv = make_input_features(batch_size=4) - ok, _, elapsed = run_forward_backward(m, inputs, lp, adv, 'TEST-10-GA3') - if not ok or elapsed >= TIMEOUT: - return False - do_optim_step(m, 'TEST-10-GA') - return True - -def test_11_forward_only_then_train(m): - inputs, _, _ = make_input_features(batch_size=4, include_advantages=False) + bad_features, bad_old_logps, bad_adv = _make_inputs(bad_old_logps_len=5) start = time.time() - try: - m.forward_only(inputs=inputs) - except Exception: - if time.time() - start >= TIMEOUT: - return False - train_in, lp, adv = make_input_features(batch_size=4) - ok, _, elapsed = run_forward_backward(m, train_in, lp, adv, 'TEST-11-TRAIN') - if not ok or elapsed >= TIMEOUT: - return False - do_optim_step(m, 'TEST-11-TRAIN') - return True - -def test_12_mixed_seq_lengths(m): - all_inputs, all_lp, all_adv = [], [], [] - for sl, cl in [(32, 16), (128, 64), (48, 24), (96, 48)]: - feats, lp, adv = make_input_features(batch_size=1, seq_len=sl, completion_len=cl) - all_inputs.extend(feats) - if lp: - all_lp.extend(lp) - if adv: - all_adv.extend(adv) - _, _, elapsed = run_forward_backward(m, all_inputs, all_lp, all_adv, 'TEST-12-MIXED') - if elapsed >= TIMEOUT: - return False - do_optim_step(m, 'TEST-12-MIXED') - return True - - -ALL_TESTS = [ - ('TEST-1: Normal GRPO Training', test_1_normal_grpo), - ('TEST-2: Bad old_logps (original bug)', test_2_bad_old_logps), - ('TEST-3: Recovery after error', test_3_recovery), - ('TEST-4: NaN old_logps', test_4_nan_old_logps), - ('TEST-5: Extreme advantages (1e30)', test_5_extreme_advantages), - ('TEST-6: All labels masked (-100)', test_6_all_labels_masked), - ('TEST-7: Consecutive bad batches', test_7_consecutive_bad), - ('TEST-8: Rapid bad->good', test_8_rapid_bad_good), - ('TEST-9: Final health check', test_9_final_health), - ('TEST-10: Gradient accumulation error', test_10_gradient_accumulation_error), - ('TEST-11: forward_only then train', test_11_forward_only_then_train), - ('TEST-12: Mixed sequence lengths', test_12_mixed_seq_lengths), -] - - -def main(): - log('=' * 60) - log('NCCL-Safe E2E Test - Twinkle Client Path') - log('=' * 60) - log(f'Server URL: {SERVER_URL}') - log(f'Base Model: {BASE_MODEL}') - log(f'TWINKLE_FAIL_FAST = {os.getenv("TWINKLE_FAIL_FAST", "1 (default)")}') - - wait_for_server(SERVER_URL) - m = init_client() - - results = [] - for name, test_fn in ALL_TESTS: - log(f'\n{"=" * 60}\n{name}\n{"=" * 60}') - try: - passed = test_fn(m) - results.append((name, 'PASS' if passed else 'FAIL')) - log(f'[{name}] {"PASS" if passed else "FAIL"}') - except Exception as e: - log(f'{name}: EXCEPTION: {e}') - traceback.print_exc() - results.append((name, 'FAIL')) - - log(f'\n{"=" * 60}\nRESULTS SUMMARY\n{"=" * 60}') - all_passed = all(s == 'PASS' for _, s in results) - for name, status in results: - log(f' [{status}] {name}') - log(f'\n{"ALL" if all_passed else "SOME"} {len(results)} TESTS {"PASSED" if all_passed else "FAILED"}!') - return 0 if all_passed else 1 - - -def test_nccl_safe_twinkle_e2e(): - """Pytest-collected entry point.""" - rc = main() - assert rc == 0, 'Some Twinkle NCCL-safe E2E tests failed' - - -if __name__ == '__main__': - sys.exit(main()) + with pytest.raises(Exception): + model.forward_backward( + inputs=bad_features, adapter_name=ADAPTER_NAME, old_logps=bad_old_logps, advantages=bad_adv) + assert time.time() - start < TIMEOUT, 'malformed request must fail fast, not hang (NCCL)' + + good_features, good_old_logps, good_adv = _make_inputs() + result = model.forward_backward( + inputs=good_features, adapter_name=ADAPTER_NAME, old_logps=good_old_logps, advantages=good_adv) + assert result is not None diff --git a/tests/server/static/test_no_degraded_path.py b/tests/server/static/test_no_degraded_path.py new file mode 100644 index 00000000..765f760a --- /dev/null +++ b/tests/server/static/test_no_degraded_path.py @@ -0,0 +1,68 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Static check: no silent-degradation symbols remain (T7.8 / R6#6 / R9#4 / Property 9). + +One wildcard search covering eight symbols; each must occur zero times in its scope. +The symbols are matched as identifiers (word boundaries) so that ``nccl_safe_megatron`` +(the retained decorator), the ``twinkle.utils.nccl_safe`` module path, and unrelated +test names like ``test_zero_loss_...`` are not counted. +""" +from __future__ import annotations + +import pathlib +import re + +import twinkle + +_TWINKLE_SRC = pathlib.Path(twinkle.__file__).resolve().parent +_REPO_ROOT = _TWINKLE_SRC.parent.parent # .../src/twinkle -> repo root +_TESTS = _REPO_ROOT / 'tests' +_COOKBOOK = _REPO_ROOT / 'cookbook' +_SELF = pathlib.Path(__file__).resolve() + +# symbol -> compiled identifier pattern. +_IDENT = { + 'safe_loss': re.compile(r'(? Date: Tue, 15 Sep 2026 13:55:27 +0800 Subject: [PATCH 09/14] test(contract): zero-wire-change guard + CI/pre-commit closeout (Phase 8, T8.1/T8.2/T8.4) - test_client_api_contract.py: OpenAPI surface == pre-impl baseline (T0.1), schedule_task_and_wait retained, only new client modules base.py/errors.py (T8.1) - new checks are auto-run by CI 'pytest tests'; lint.yaml runs pre-commit --all-files; applied yapf/isort/pyupgrade auto-fixes so all hooks pass on changed src files (T8.2) - tests/server/README.md documents the mock-backend evidence boundary (T8.4) --- src/twinkle/infra/__init__.py | 1 + src/twinkle/infra/_ray/ray_helper.py | 4 +- src/twinkle/model/megatron/megatron.py | 3 +- src/twinkle/server/model/app.py | 4 +- src/twinkle/server/model/tinker_handlers.py | 16 ++++--- src/twinkle/server/model/twinkle_handlers.py | 39 ++++++++++++----- .../server/sampler/twinkle_handlers.py | 12 ++++-- src/twinkle/server/utils/task_errors.py | 6 +-- src/twinkle/server/utils/task_queue/mixin.py | 8 ++-- src/twinkle/server/utils/task_queue/worker.py | 2 +- src/twinkle/utils/nccl_safe.py | 4 +- tests/server/README.md | 23 ++++++++++ .../contract/test_client_api_contract.py | 42 +++++++++++++++++++ 13 files changed, 128 insertions(+), 36 deletions(-) create mode 100644 tests/server/README.md create mode 100644 tests/server/contract/test_client_api_contract.py diff --git a/src/twinkle/infra/__init__.py b/src/twinkle/infra/__init__.py index 3a80219b..2cf7c148 100644 --- a/src/twinkle/infra/__init__.py +++ b/src/twinkle/infra/__init__.py @@ -1047,6 +1047,7 @@ def wrapper(self, *args, **kwargs) -> T1: else: # This is the driver from ._ray import RayHelper + # Resolve the effective ray.get timeout before choosing execute_method: # the decorator's explicit value wins, the instance attribute is the # fallback. ``is not None`` (not ``or``) so that a decorator ``timeout=0`` diff --git a/src/twinkle/infra/_ray/ray_helper.py b/src/twinkle/infra/_ray/ray_helper.py index d3cbc3f5..4cc5f6a6 100644 --- a/src/twinkle/infra/_ray/ray_helper.py +++ b/src/twinkle/infra/_ray/ray_helper.py @@ -137,9 +137,7 @@ def is_worker(): return RayHelper.ray_inited() and ray._private.worker.global_worker.mode == ray._private.worker.WORKER_MODE @staticmethod - def execute_all_sync(method_name: str, - workers_and_args: List[Tuple[Any, List[Any], Dict[str, Any]]], - timeout=None): + def execute_all_sync(method_name: str, workers_and_args: List[Tuple[Any, List[Any], Dict[str, Any]]], timeout=None): """Execute method and return results. ``timeout`` is passed to ``ray.get(list, timeout=)``, whose semantics are diff --git a/src/twinkle/model/megatron/megatron.py b/src/twinkle/model/megatron/megatron.py index 89a05db7..4e4e2bbd 100644 --- a/src/twinkle/model/megatron/megatron.py +++ b/src/twinkle/model/megatron/megatron.py @@ -444,8 +444,7 @@ def forward_step_func(data_iterator, model): batch['labels'] = processor.postprocess_tensor_cp(labels, cu_seqlens=cu_seqlens_q) if completion_mask is not None: # Same index space as labels, so it needs the same CP reassembly. - batch['completion_mask'] = processor.postprocess_tensor_cp( - completion_mask, cu_seqlens=cu_seqlens_q) + batch['completion_mask'] = processor.postprocess_tensor_cp(completion_mask, cu_seqlens=cu_seqlens_q) if 'position_ids' in batch: pos = batch['position_ids'] if pos.dim() == 3: diff --git a/src/twinkle/server/model/app.py b/src/twinkle/server/model/app.py index 6495dd7d..7445ce0d 100644 --- a/src/twinkle/server/model/app.py +++ b/src/twinkle/server/model/app.py @@ -139,7 +139,9 @@ def __init__(self, # ModelManagement opts into the Admission_Gate (collective mis-pairing + # queue-bypassing _cleanup_adapter); SamplerManagement does not. self._init_task_queue( - queue_config, deployment_name='Model', enable_admission_gate=True, + queue_config, + deployment_name='Model', + enable_admission_gate=True, on_backend_timeout=self._probe_after_timeout) # Bound every ray.get on this backend by the effective execution timeout # (applies to both sync=True and sync=False dispatch). T4.1. diff --git a/src/twinkle/server/model/tinker_handlers.py b/src/twinkle/server/model/tinker_handlers.py index 5d95719b..7f34c2ae 100644 --- a/src/twinkle/server/model/tinker_handlers.py +++ b/src/twinkle/server/model/tinker_handlers.py @@ -151,8 +151,7 @@ async def _do_forward(): datum_list = body.forward_input.data loss_fn_config = body.forward_input.loss_fn_config or {} output, loss = await self.call_backend( - self.model.tinker_forward_only, - inputs=datum_list, adapter_name=model_adapter, **loss_fn_config) + self.model.tinker_forward_only, inputs=datum_list, adapter_name=model_adapter, **loss_fn_config) return types.ForwardBackwardOutput( loss_fn_output_type='CrossEntropyLossReturn', loss_fn_outputs=output, @@ -196,7 +195,10 @@ async def _do_forward_backward(): loss_fn_config = body.forward_backward_input.loss_fn_config or {} output, loss = await self.call_backend( self.model.tinker_forward_backward, - inputs=datum_list, adapter_name=model_adapter, loss_fn=loss_fn, **loss_fn_config) + inputs=datum_list, + adapter_name=model_adapter, + loss_fn=loss_fn, + **loss_fn_config) output_type = ('ImportanceSamplingLossReturn' if loss_fn == 'importance_sampling' else 'CrossEntropyLossReturn') self.set_resource_state(adapter_name, 'grad_ready', True) @@ -243,7 +245,8 @@ async def _do_optim(): if not self.get_resource_state(adapter_name, 'grad_ready', False): raise RuntimeError(f'No accumulated gradients for adapter={adapter_name}; ' 'call forward_backward before optim_step') - await self.call_backend(self.model.tinker_step, adam_params=body.adam_params, adapter_name=model_adapter) + await self.call_backend( + self.model.tinker_step, adam_params=body.adam_params, adapter_name=model_adapter) self.set_resource_state(adapter_name, 'grad_ready', False) metrics = await self.call_backend( self.model.tinker_calculate_metric, is_training=True, adapter_name=model_adapter) @@ -275,7 +278,10 @@ async def _do_save(): save_dir = checkpoint_manager.get_save_dir(model_id=body.model_id, is_sampler=False) await self.call_backend( self.model.save, - name=checkpoint_name, output_dir=save_dir, adapter_name=model_adapter, save_optimizer=True) + name=checkpoint_name, + output_dir=save_dir, + adapter_name=model_adapter, + save_optimizer=True) tinker_path = checkpoint_manager.save(body.model_id, name=checkpoint_name, is_sampler=False) return types.SaveWeightsResponse(path=tinker_path, type='save_weights') except Exception: diff --git a/src/twinkle/server/model/twinkle_handlers.py b/src/twinkle/server/model/twinkle_handlers.py index b780b279..01eadbe6 100644 --- a/src/twinkle/server/model/twinkle_handlers.py +++ b/src/twinkle/server/model/twinkle_handlers.py @@ -110,7 +110,9 @@ async def _task(): inputs = _parse_inputs(body.inputs) ret = await self.call_backend( self.model.forward, - inputs=inputs, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + inputs=inputs, + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) return {'result': ret} inputs_list = body.inputs if isinstance(body.inputs, list) else [body.inputs] @@ -197,7 +199,9 @@ async def _task(): inputs = _parse_inputs(body.inputs) ret = await self.call_backend( self.model.forward_only, - inputs=inputs, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + inputs=inputs, + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) return {'result': ret} inputs_list = body.inputs if isinstance(body.inputs, list) else [body.inputs] @@ -306,7 +310,9 @@ async def _task(): inputs[key] = torch.tensor(inputs[key]) ret = await self.call_backend( self.model.forward_backward, - inputs=all_inputs, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + inputs=all_inputs, + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) return {'result': ret} inputs_list = body.inputs if isinstance(body.inputs, list) else [body.inputs] @@ -451,7 +457,8 @@ async def _task(): extra_kwargs = body.model_extra or {} ret = await self.call_backend( self.model.get_train_configs, - adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) return {'result': ret} return await run_task( @@ -467,7 +474,9 @@ async def _task(): extra_kwargs = body.model_extra or {} await self.call_backend( self.model.set_loss, - body.loss_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + body.loss_cls, + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='set_loss')) @@ -485,7 +494,9 @@ async def _task(): extra_kwargs = body.model_extra or {} await self.call_backend( self.model.set_optimizer, - body.optimizer_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + body.optimizer_cls, + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) await run_task( self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='set_optimizer')) @@ -504,7 +515,9 @@ async def _task(): extra_kwargs = body.model_extra or {} await self.call_backend( self.model.set_lr_scheduler, - body.scheduler_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + body.scheduler_cls, + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) await run_task( self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='set_lr_scheduler')) @@ -727,7 +740,9 @@ async def _task(): patch_cls = deserialize_object(body.patch_cls) await self.call_backend( self.model.apply_patch, - patch_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + patch_cls, + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='apply_patch')) @@ -767,7 +782,9 @@ async def _task(): extra_kwargs = body.model_extra or {} await self.call_backend( self.model.set_template, - body.template_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + body.template_cls, + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) await run_task(self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='set_template')) @@ -785,7 +802,9 @@ async def _task(): extra_kwargs = body.model_extra or {} await self.call_backend( self.model.set_processor, - body.processor_cls, adapter_name=self.resolve_model_adapter_name(adapter_name), **extra_kwargs) + body.processor_cls, + adapter_name=self.resolve_model_adapter_name(adapter_name), + **extra_kwargs) await run_task( self.schedule_task_and_wait(_task, model_id=adapter_name, token=token, task_type='set_processor')) diff --git a/src/twinkle/server/sampler/twinkle_handlers.py b/src/twinkle/server/sampler/twinkle_handlers.py index 19100adb..22515b4e 100644 --- a/src/twinkle/server/sampler/twinkle_handlers.py +++ b/src/twinkle/server/sampler/twinkle_handlers.py @@ -493,15 +493,19 @@ async def _stream_generator(): while True: remaining = total_timeout - (loop.time() - start) if remaining <= 0: - yield json.dumps( - {'error': 'sample_stream exceeded the execution time bound', 'category': 'Server'}) + '\n' + yield json.dumps({ + 'error': 'sample_stream exceeded the execution time bound', + 'category': 'Server' + }) + '\n' break try: item = await asyncio.wait_for( loop.run_in_executor(None, q.get), timeout=min(single_get_timeout, remaining)) except asyncio.TimeoutError: - yield json.dumps( - {'error': 'sample_stream timed out waiting for the next token', 'category': 'Server'}) + '\n' + yield json.dumps({ + 'error': 'sample_stream timed out waiting for the next token', + 'category': 'Server' + }) + '\n' break if item == STREAM_SENTINEL: break diff --git a/src/twinkle/server/utils/task_errors.py b/src/twinkle/server/utils/task_errors.py index b0fa46eb..7e977cf1 100644 --- a/src/twinkle/server/utils/task_errors.py +++ b/src/twinkle/server/utils/task_errors.py @@ -7,7 +7,7 @@ from __future__ import annotations from collections.abc import Mapping -from typing import Any, Optional +from typing import Any from twinkle_client.types.errors import ErrorCategory, ErrorPayload @@ -30,14 +30,14 @@ def task_error_payload( request_id: str, error_code: int = 500, category: ErrorCategory = ErrorCategory.Server, - traceback_text: Optional[str] = None, + traceback_text: str | None = None, ) -> dict[str, Any]: """Build an ``ErrorPayload`` and return it as a JSON-safe dict for storage. Traceback splitting and length trimming happen here so over-long text is never written to State_Backend. A ``User`` category carries no traceback (R5#6). """ - tb: Optional[str] = None + tb: str | None = None if category != ErrorCategory.User and traceback_text: tb = _trim_traceback(traceback_text) payload = ErrorPayload( diff --git a/src/twinkle/server/utils/task_queue/mixin.py b/src/twinkle/server/utils/task_queue/mixin.py index 9887e259..4260b893 100644 --- a/src/twinkle/server/utils/task_queue/mixin.py +++ b/src/twinkle/server/utils/task_queue/mixin.py @@ -108,8 +108,7 @@ def _init_task_queue( # would let one leak block the whole queue forever. self._backend_executor = ThreadPoolExecutor(thread_name_prefix='twinkle-backend') # per-replica Admission_Gate; opt-in per deployment. - self._backend_admission: asyncio.Semaphore | None = ( - asyncio.Semaphore(1) if enable_admission_gate else None) + self._backend_admission: asyncio.Semaphore | None = (asyncio.Semaphore(1) if enable_admission_gate else None) self._event_loop: asyncio.AbstractEventLoop | None = None @@ -144,9 +143,8 @@ async def call_backend(self, fn: Callable[..., Any], /, *args: Any, admit: bool # check-then-acquire is race-free for a Semaphore(1): if not locked here, # acquire succeeds synchronously. if sem.locked(): - raise BackendBusyError( - 'This replica is waiting for a timed-out backend call to exit; ' - 'refusing to queue behind it.') + raise BackendBusyError('This replica is waiting for a timed-out backend call to exit; ' + 'refusing to queue behind it.') await sem.acquire() def _work() -> Any: diff --git a/src/twinkle/server/utils/task_queue/worker.py b/src/twinkle/server/utils/task_queue/worker.py index 1d951edb..121d7345 100644 --- a/src/twinkle/server/utils/task_queue/worker.py +++ b/src/twinkle/server/utils/task_queue/worker.py @@ -53,7 +53,7 @@ def __init__( config: TaskQueueConfig, task_metrics: TaskMetrics | None, deployment_name: str, - on_backend_timeout: 'Callable[[], Any] | None' = None, + on_backend_timeout: Callable[[], Any] | None = None, ) -> None: self._state = state self._config = config diff --git a/src/twinkle/utils/nccl_safe.py b/src/twinkle/utils/nccl_safe.py index d6633355..214f3a17 100644 --- a/src/twinkle/utils/nccl_safe.py +++ b/src/twinkle/utils/nccl_safe.py @@ -58,8 +58,8 @@ def wrapper(self, *args, **kwargs): tb = traceback.format_exc() if len(tb) > _TRACEBACK_LIMIT: tb = tb[-_TRACEBACK_LIMIT:] - logger.error('[nccl_safe_megatron] %s in %s on global rank %s:\n%s', type(exc).__name__, func.__name__, - _global_rank(), tb) + logger.error('[nccl_safe_megatron] %s in %s on global rank %s:\n%s', + type(exc).__name__, func.__name__, _global_rank(), tb) raise return wrapper diff --git a/tests/server/README.md b/tests/server/README.md new file mode 100644 index 00000000..44a998a8 --- /dev/null +++ b/tests/server/README.md @@ -0,0 +1,23 @@ +# Server test notes + +## Mock backend evidence boundary (spec T8.4 / R9#10) + +`server/model/backends/mock_model.py` is a stand-in backend for tests that must run +without a GPU or a real Ray-distributed model. Two properties bound what a test using +it can prove: + +1. **Every method takes `**kwargs` and performs no argument validation.** A test that + drives the mock backend therefore **cannot** be used as evidence for request/argument + validation behavior — the mock accepts anything. +2. **It never enters a real collective.** The mock does no NCCL communication, so a test + using it **cannot** be used as evidence for NCCL behavior (asymmetric failure, + collective mis-pairing, ReduceScatter, etc.). + +What the mock backend *can* evidence is exactly the parts that do not depend on the +backend's internals: the **dispatch path** (that a call reaches the backend via +`call_backend` / the task queue) and the **timeout / admission mechanisms** themselves +(that a slow or leaked call is bounded and the event loop stays responsive). + +Tests that need to prove validation or NCCL behavior are the GPU-gated end-to-end tests +under `tests/server/integration/test_nccl_safe_*_e2e.py` (run only with +`TWINKLE_TEST_GPU_E2E=1` against a real server). diff --git a/tests/server/contract/test_client_api_contract.py b/tests/server/contract/test_client_api_contract.py new file mode 100644 index 00000000..afed5e2c --- /dev/null +++ b/tests/server/contract/test_client_api_contract.py @@ -0,0 +1,42 @@ +# Copyright (c) ModelScope Contributors. All rights reserved. +"""Zero-wire-change contract guard (T8.1 / R8 / Property 10). + +Re-exports the OpenAPI surface of all four apps and compares it field-by-field with +the baseline captured before this spec's implementation (T0.1). The diff must be +empty. Also asserts the load-bearing invariants: ``schedule_task_and_wait`` still +exists and the only client-side additions are ``types/base.py`` and ``types/errors.py``. +""" +from __future__ import annotations + +import pytest + +from tests.server.contract.client_api_harness import extract_full_surface, load_baseline + + +def test_openapi_surface_matches_baseline(): + current = extract_full_surface() + baseline = load_baseline() + assert current == baseline, ( + 'Client-facing OpenAPI surface changed vs the pre-implementation baseline; ' + 'this spec must be zero-wire-change. Diffing apps: ' + f'{[a for a in set(current) | set(baseline) if current.get(a) != baseline.get(a)]}') + + +def test_schedule_task_and_wait_not_removed(): + from twinkle.server.utils.task_queue.mixin import TaskQueueMixin + assert hasattr(TaskQueueMixin, 'schedule_task_and_wait') + + +def test_new_client_types_importable(): + # The only permitted client-side additions. + import twinkle_client.types.base as base + import twinkle_client.types.errors as errors + + for symbol in ('StrictRequest', 'ResponseModel', 'DataModel', 'backend_only'): + assert hasattr(base, symbol) + for symbol in ('ErrorPayload', 'ErrorCategory', 'QueueStateLiteral'): + assert hasattr(errors, symbol) + + +if __name__ == '__main__': + raise SystemExit(pytest.main([__file__, '-v'])) From d54d9a1f08eda8f3f9ab173d6b2a17af9bf78acb Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 14:22:27 +0800 Subject: [PATCH 10/14] fix(state): store state timestamps as UTC so expiry is timezone-independent Root cause: _now_iso() wrote naive local time while _parse_timestamp() reads a naive ISO string as UTC; compared against a time.time()-based cutoff this skewed every expiry check by the host's UTC offset (premature deletion west of UTC, over-retention east; invisible on UTC/CI hosts). Fix (option A): _now_iso() now emits UTC-aware ISO; future_manager reuses it for record writes and its cleanup 'now' reverts to time.time() (both UTC epoch). _parse_timestamp is unchanged and still parses legacy naive records as UTC (same as before). Not a wire-schema change (R8 unaffected). Adds a timezone-independent regression test asserting a freshly written record parses to within 1s of time.time(); the suite passes under TZ=America/Los_Angeles. --- src/twinkle/server/state/future_manager.py | 11 +++----- src/twinkle/server/state/models.py | 7 +++-- tests/server/state/test_future_lifecycle.py | 30 ++++++++++++++------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/twinkle/server/state/future_manager.py b/src/twinkle/server/state/future_manager.py index 31f5cac3..9d3b3a3c 100644 --- a/src/twinkle/server/state/future_manager.py +++ b/src/twinkle/server/state/future_manager.py @@ -2,14 +2,14 @@ from __future__ import annotations import functools -from datetime import datetime +import time from typing import Any from twinkle.server.utils.task_errors import task_error_payload from twinkle.utils.logger import get_logger from .backend.base import StateBackend from .base import BaseManager -from .models import FutureRecord +from .models import FutureRecord, _now_iso logger = get_logger() @@ -112,7 +112,7 @@ async def store_status( if result is not None and hasattr(result, 'model_dump'): result = result.model_dump() - now = datetime.now().isoformat() + now = _now_iso() await self._backend.update_atomic( self._make_key(request_id), functools.partial( @@ -162,10 +162,7 @@ async def cleanup_expired( counted here; they are removed on a later pass once terminal). """ all_records = await self.get_all() - # Use the same clock convention as the stored timestamps (_parse_timestamp on - # an ISO string) so the age computation is not skewed by _now_iso writing - # local time while _parse_timestamp reads naive ISO as UTC. - now = self._parse_timestamp(datetime.now().isoformat()) + now = time.time() expired_ids: list[str] = [] for request_id, record in all_records.items(): if record.status in _TERMINAL_STATUSES: diff --git a/src/twinkle/server/state/models.py b/src/twinkle/server/state/models.py index 60970022..d3d3133b 100644 --- a/src/twinkle/server/state/models.py +++ b/src/twinkle/server/state/models.py @@ -2,13 +2,16 @@ from __future__ import annotations import time -from datetime import datetime +from datetime import datetime, timezone from pydantic import BaseModel, Field from typing import Any def _now_iso() -> str: - return datetime.now().isoformat() + # UTC-aware so _parse_timestamp (which reads timestamps back as UTC) agrees with + # it and with time.time(); a naive local string would be misread as UTC and skew + # every expiry comparison by the host's UTC offset. + return datetime.now(timezone.utc).isoformat() class SessionRecord(BaseModel): diff --git a/tests/server/state/test_future_lifecycle.py b/tests/server/state/test_future_lifecycle.py index bf687044..c32a6172 100644 --- a/tests/server/state/test_future_lifecycle.py +++ b/tests/server/state/test_future_lifecycle.py @@ -5,7 +5,7 @@ """ from __future__ import annotations -from datetime import datetime +import time from unittest import mock import pytest @@ -20,11 +20,6 @@ def manager(tmp_path): return FutureManager(backend, expiration_timeout=300.0) -def _clock(manager) -> float: - """Now under the same convention the stored ISO timestamps use.""" - return manager._parse_timestamp(datetime.now().isoformat()) - - async def _store(manager, request_id, status, *, replica_id=None): await manager.store_status(request_id, status, model_id='m1', replica_id=replica_id) @@ -33,7 +28,7 @@ async def _store(manager, request_id, status, *, replica_id=None): async def test_non_terminal_with_live_replica_is_kept(manager): await _store(manager, 'r1', 'running', replica_id='replica-A') removed = await manager.cleanup_expired( - cutoff_time=_clock(manager) + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) + cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) assert removed == 0 rec = await manager.get('r1') assert rec is not None and rec.status == 'running' @@ -42,7 +37,7 @@ async def test_non_terminal_with_live_replica_is_kept(manager): @pytest.mark.asyncio async def test_non_terminal_orphan_is_failed_not_deleted(manager): await _store(manager, 'r2', 'running', replica_id='dead-replica') - await manager.cleanup_expired(cutoff_time=_clock(manager) + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) + await manager.cleanup_expired(cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) rec = await manager.get('r2') assert rec is not None # NOT deleted (Property 6) assert rec.status == 'failed' @@ -53,7 +48,7 @@ async def test_non_terminal_orphan_is_failed_not_deleted(manager): async def test_non_terminal_over_absolute_ttl_is_failed(manager): await _store(manager, 'r3', 'running', replica_id='replica-A') # absolute_ttl=0 makes any positive age exceed the bound. - await manager.cleanup_expired(cutoff_time=_clock(manager) + 10, alive_replica_ids={'replica-A'}, absolute_ttl=0.0) + await manager.cleanup_expired(cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}, absolute_ttl=0.0) rec = await manager.get('r3') assert rec is not None and rec.status == 'failed' @@ -62,7 +57,7 @@ async def test_non_terminal_over_absolute_ttl_is_failed(manager): async def test_terminal_expired_is_deleted(manager): await _store(manager, 'r4', 'completed', replica_id='replica-A') removed = await manager.cleanup_expired( - cutoff_time=_clock(manager) + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) + cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) assert removed == 1 assert await manager.get('r4') is None @@ -93,3 +88,18 @@ async def test_replica_id_set_at_creation_not_overwritten(manager): await manager.store_status('r7', 'running', model_id='m1', replica_id='replica-B') rec = await manager.get('r7') assert rec.replica_id == 'replica-A' # creation value preserved + + +@pytest.mark.asyncio +async def test_stored_timestamps_align_with_wall_clock_regardless_of_host_tz(manager): + """Writer (_now_iso), reader (_parse_timestamp) and time.time() must agree. + + A record written now must parse to within a second of time.time() on any host, + not skewed by the host's UTC offset (the former naive-local / read-as-UTC bug). + """ + before = time.time() + await _store(manager, 'r8', 'running', replica_id='replica-A') + after = time.time() + rec = await manager.get('r8') + parsed = manager._parse_timestamp(rec.created_at) + assert before - 1 <= parsed <= after + 1 From f97810482ad04a7e0b7646701089c33477665305 Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 15:33:46 +0800 Subject: [PATCH 11/14] fix: restore multi lora state after load failure --- src/twinkle/model/multi_lora.py | 14 ++++--- .../test_multi_lora_target_parameters.py | 39 ++++++++++++++++++- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/twinkle/model/multi_lora.py b/src/twinkle/model/multi_lora.py index ff776610..6eb80ed2 100644 --- a/src/twinkle/model/multi_lora.py +++ b/src/twinkle/model/multi_lora.py @@ -193,12 +193,14 @@ def _after(_module): _before(_module) else: _before(self.module) - yield adapter_name - if isinstance(self.module, list): - for _module in self.module: - _after(_module) - else: - _after(self.module) + try: + yield adapter_name + finally: + if isinstance(self.module, list): + for _module in self.module: + _after(_module) + else: + _after(self.module) # self.deactivate_adapter() def check_length( diff --git a/tests/model/test_multi_lora_target_parameters.py b/tests/model/test_multi_lora_target_parameters.py index b28ef6b3..c76854ce 100644 --- a/tests/model/test_multi_lora_target_parameters.py +++ b/tests/model/test_multi_lora_target_parameters.py @@ -2,6 +2,7 @@ import sys import types +import pytest import torch from peft import LoraConfig, get_peft_model from peft.utils import set_peft_model_state_dict @@ -45,6 +46,42 @@ def forward(self, x, expert_idx=0): return self.mlp.experts(x, expert_idx=expert_idx) +class FakePeftModule: + + def __init__(self, peft_config, active_adapter): + self.peft_config = peft_config + self.active_adapter = active_adapter + + +def test_save_context_restores_peft_state_when_load_fails(): + from twinkle.model.multi_lora import LoraTenant, MultiLora + + original_config = {'lora_0': object(), 'lora_1': object()} + modules = [ + FakePeftModule(original_config, 'lora_1'), + FakePeftModule(original_config, 'lora_0'), + ] + multi_lora = MultiLora(max_loras=2, max_r=4) + multi_lora.module = modules + multi_lora.loras = [ + LoraTenant( + index=0, + adapter_name='lora_0', + config=_make_target_cfg(), + tenant_adapter_name='tenant', + tenant_config=_make_target_cfg(), + ) + ] + + with pytest.raises(RuntimeError, match='load failed'): + with multi_lora.save_context('tenant') as adapter_name: + assert adapter_name == 'lora_0' + raise RuntimeError('load failed') + + assert [module.peft_config for module in modules] == [original_config, original_config] + assert [module.active_adapter for module in modules] == ['lora_1', 'lora_0'] + + def test_peft_target_parameter_key_shapes_for_3d_experts(): model = FakeModel() cfg = LoraConfig( @@ -266,4 +303,4 @@ def test_multilora_transformers_installs_target_parameters_once(): assert test_target_parameter_multi_lora_updates_only_active_adapter() == True assert test_multilora_releases_target_parameter_slot_to_initial_weights() == True assert test_multilora_state_dict_round_trips_target_parameters() == True - assert test_multilora_transformers_installs_target_parameters_once() == True \ No newline at end of file + assert test_multilora_transformers_installs_target_parameters_once() == True From 26a4311d227d01b1c977c38ba4daeda59174e04e Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Tue, 15 Sep 2026 21:31:03 +0800 Subject: [PATCH 12/14] feat(server): finalize execution guarantees (backend boundary + stream/gen bounds) Complete the server-execution-guarantees spec by routing the remaining sampler paths through the Blocking_Call_Boundary and bounding every long-lived operation: - sampler: submit/collect/cancel generation, unload, and streaming now go through call_backend; _await_generation is bounded by the effective execution timeout and _stream_queue enforces a double timeout (total + per-token) instead of blocking indefinitely. - task queue: thread collect_width through _init_task_queue so state hygiene computes the absolute survival TTL without a separate set_execution_bounds hop. - errors: stream/generation failures surface as ErrorPayload wire frames rather than silent drops. - deps: bump tinker to 0.29.0 (python>=3.11) and refresh poetry.lock. - tests/docs: add error-wire, stream-guarantee and nccl_safe coverage; refresh the client API contract baseline (zero wire change). --- .../Usage Guide/Server and Client/Server.md | 32 +- .../\346\234\215\345\212\241\347\253\257.md" | 10 +- poetry.lock | 2933 +++++- pyproject.toml | 2 +- src/twinkle/infra/__init__.py | 5 +- src/twinkle/server/gateway/tinker_handlers.py | 5 +- src/twinkle/server/model/app.py | 52 +- .../server/model/backends/megatron_model.py | 3 +- .../server/model/backends/mock_model.py | 2 +- .../model/backends/transformers_model.py | 3 +- src/twinkle/server/model/tinker_handlers.py | 58 +- src/twinkle/server/model/twinkle_handlers.py | 14 +- .../server/processor/twinkle_handlers.py | 3 +- src/twinkle/server/sampler/app.py | 33 +- src/twinkle/server/sampler/tinker_handlers.py | 33 +- .../server/sampler/twinkle_handlers.py | 137 +- src/twinkle/server/state/future_manager.py | 46 +- src/twinkle/server/state/model_manager.py | 4 +- src/twinkle/server/state/models.py | 5 +- src/twinkle/server/state/replica_registry.py | 15 +- src/twinkle/server/state/server_state.py | 39 +- src/twinkle/server/utils/task_errors.py | 24 +- .../server/utils/task_queue/__init__.py | 3 +- src/twinkle/server/utils/task_queue/config.py | 10 +- src/twinkle/server/utils/task_queue/mixin.py | 151 +- src/twinkle/server/utils/task_queue/types.py | 6 +- src/twinkle/server/utils/task_queue/worker.py | 17 +- src/twinkle/utils/nccl_safe.py | 10 +- src/twinkle_client/types/errors.py | 27 +- tests/infra/test_ray_get_timeout.py | 27 +- tests/server/README.md | 6 +- .../server/contract/client_api_baseline.json | 8148 +++++++++++++++-- tests/server/contract/client_api_harness.py | 138 +- .../contract/test_client_api_contract.py | 11 +- tests/server/contract/test_error_wire.py | 39 + .../server/integration/test_actor_recovery.py | 17 + .../integration/test_blocking_boundary.py | 121 +- .../integration/test_nccl_safe_tinker_e2e.py | 30 +- .../integration/test_nccl_safe_twinkle_e2e.py | 8 +- tests/server/model/test_replica_lifecycle.py | 11 +- tests/server/model/test_tinker_handlers.py | 4 +- .../server/sampler/test_stream_guarantees.py | 113 + tests/server/sampler/test_tinker_handlers.py | 5 + tests/server/state/test_error_payload.py | 38 +- tests/server/state/test_future_lifecycle.py | 45 +- tests/server/state/test_managers.py | 6 + .../server/static/backend_call_exemptions.py | 2 +- .../static/test_no_direct_backend_call.py | 74 +- tests/server/utils/task_queue/test_config.py | 13 + tests/server/utils/test_task_errors.py | 10 +- tests/server/utils/test_task_queue_mixin.py | 30 +- tests/twinkle_client/test_types_contract.py | 43 +- tests/utils/test_nccl_safe.py | 18 + 53 files changed, 11305 insertions(+), 1334 deletions(-) create mode 100644 tests/server/contract/test_error_wire.py create mode 100644 tests/server/sampler/test_stream_guarantees.py create mode 100644 tests/utils/test_nccl_safe.py diff --git a/docs/source_en/Usage Guide/Server and Client/Server.md b/docs/source_en/Usage Guide/Server and Client/Server.md index d57084f1..5e67e37c 100644 --- a/docs/source_en/Usage Guide/Server and Client/Server.md +++ b/docs/source_en/Usage Guide/Server and Client/Server.md @@ -453,30 +453,30 @@ Additionally, this refactor introduces two new top-level fields — `telemetry` ## Execution time bounds -Every backend call has a configuration-computable time bound. The single source of -the bound is the *effective execution timeout* `T`: it equals `execution_timeout` -from the task-queue config, or `3600s` when `execution_timeout` is set to `0` -("no configured limit"; a startup warning is logged). `T` drives both the -`ray.get` timeout on the backend and the `asyncio.wait_for` around each task — -there is no second, independently tunable timeout. The default `execution_timeout` -is `1800s`. +Every backend call has a finite time bound. `T` is the effective task execution +timeout: it equals `execution_timeout`, or `3600s` when that setting is `0`. +`asyncio.wait_for` uses `T`. The Ray wait uses `R`, which is a method's explicit +constant timeout when present and otherwise `T`. The default `T` is `1800s`. Two distinct bounds follow, and they must not be collapsed into one number: | Bound | Expression | Meaning | |-------|------------|---------| | Record-terminal bound | `queue_timeout + T` | After this, a task's future record is guaranteed to be in a terminal state (`completed`/`failed`). Use it for alerting thresholds and client polling total-timeout. | -| Resource-release bound | `Collect_Width × T` | After this, the executor thread and the in-flight model-actor call for that task are guaranteed to have finished. Use it for capacity planning. | +| Resource-release bound | `Collect_Width × R` from execution start, or `queue_timeout + Collect_Width × R` from submission | After this, the executor thread and the in-flight model-actor call for that task are guaranteed to have finished. Use it for capacity planning. | `Collect_Width = len(self._actors) = world_size = tp × pp × dp` — the number of futures each `remote_function` collection waits on per call. Evidence: `LazyCollect._get_result` iterates `self._futures`, which come from `_get_workers(self._actors, execute)` (`infra/__init__.py`), covering every actor — -not just the data-parallel width. On a `tp=8` deployment the resource-release bound -is therefore `8 × T`, not `T`. - -The **difference** between the two bounds (`Collect_Width × T − (queue_timeout + T)`) -is the longest time the per-replica Admission_Gate can stay closed after a timeout: -the record is already terminal, but a leaked executor thread may still hold the gate -until its `ray.get` returns or raises. During that window newly arriving tasks fail -fast with a `Server`/503 error rather than queueing behind the stuck call. +not just the data-parallel width. On a `tp=8` deployment the execution-start +resource-release bound is therefore `8 × R`, not `R`. + +After the task record becomes terminal, the per-replica Admission_Gate can remain +closed for at most `max(0, Collect_Width × R − T)`: the record is already terminal, +but a leaked executor thread may still hold the gate until its `ray.get` returns or +raises. During that window newly arriving tasks fail fast with a `server`/503 error. + +Each persisted future stores its immutable `absolute_deadline` when it is created. +Cleanup therefore reaches the same decision regardless of which deployment process +holds the cleanup lease. diff --git "a/docs/source_zh/\344\275\277\347\224\250\346\214\207\345\274\225/\346\234\215\345\212\241\347\253\257\345\222\214\345\256\242\346\210\267\347\253\257/\346\234\215\345\212\241\347\253\257.md" "b/docs/source_zh/\344\275\277\347\224\250\346\214\207\345\274\225/\346\234\215\345\212\241\347\253\257\345\222\214\345\256\242\346\210\267\347\253\257/\346\234\215\345\212\241\347\253\257.md" index 0794fb08..db71e41a 100644 --- "a/docs/source_zh/\344\275\277\347\224\250\346\214\207\345\274\225/\346\234\215\345\212\241\347\253\257\345\222\214\345\256\242\346\210\267\347\253\257/\346\234\215\345\212\241\347\253\257.md" +++ "b/docs/source_zh/\344\275\277\347\224\250\346\214\207\345\274\225/\346\234\215\345\212\241\347\253\257\345\222\214\345\256\242\346\210\267\347\253\257/\346\234\215\345\212\241\347\253\257.md" @@ -453,15 +453,17 @@ twinkle-server check-config -c server_config.yaml ## 执行时间上界 -每一次 backend 调用都存在一个可由配置计算的时间上界。上界的唯一来源是 **有效 execution timeout** `T`:它等于 task-queue 配置中的 `execution_timeout`;当 `execution_timeout` 配置为 `0`(表示「无配置上限」)时取 `3600` 秒,并在启动日志输出一条 warning。`T` 同时作用于 backend 的 `ray.get` 超时与每个任务外围的 `asyncio.wait_for`——不存在第二个可独立调节的超时值。`execution_timeout` 的默认值为 `1800` 秒。 +每一次 backend 调用都存在有限时间上界。`T` 是任务的有效 execution timeout:等于 task-queue 配置中的 `execution_timeout`;配置为 `0` 时取 `3600` 秒。`asyncio.wait_for` 使用 `T`。Ray 等待使用 `R`:方法显式声明 timeout 时取该常量,否则取 `T`。`T` 的默认值为 `1800` 秒。 由此派生出两个**不同**的上界,二者不得合成一个数: | 上界 | 表达式 | 含义 | |------|--------|------| | 记录终态上界 | `queue_timeout + T` | 超过它后,任务的 future 记录必处于终态(`completed`/`failed`)。用于设置告警阈值与客户端轮询总超时。 | -| 资源释放上界 | `Collect_Width × T` | 超过它后,该任务占用的 executor 线程与 model actor 在飞调用必已结束。用于容量规划。 | +| 资源释放上界 | 从执行开始为 `Collect_Width × R`;从提交开始为 `queue_timeout + Collect_Width × R` | 超过它后,该任务占用的 executor 线程与 model actor 在飞调用必已结束。用于容量规划。 | -`Collect_Width = len(self._actors) = world_size = tp × pp × dp`——即每次 `remote_function` 结果收集所等待的 future 个数。证据:`LazyCollect._get_result` 遍历的 `self._futures` 来自 `_get_workers(self._actors, execute)`(`infra/__init__.py`),覆盖全部 actor,而非 data-parallel 宽度。因此在 `tp=8` 的部署上,资源释放上界是 `8 × T` 而非 `T`。 +`Collect_Width = len(self._actors) = world_size = tp × pp × dp`——即每次 `remote_function` 结果收集所等待的 future 个数。证据:`LazyCollect._get_result` 遍历的 `self._futures` 来自 `_get_workers(self._actors, execute)`(`infra/__init__.py`),覆盖全部 actor,而非 data-parallel 宽度。因此在 `tp=8` 的部署上,从执行开始的资源释放上界是 `8 × R` 而非 `R`。 -两个上界的**差值**(`Collect_Width × T − (queue_timeout + T)`)即 per-replica 准入闸门在一次超时后需保持关闭的最长时长:此时记录已是终态,但泄漏的 executor 线程可能仍持有闸门,直到其 `ray.get` 返回或抛出。在该窗口内新到达的任务会以 `Server`/503 错误快速失败,而不是排队等待卡住的调用。 +任务记录进入终态后,per-replica 准入闸门额外保持关闭的最长时长为 `max(0, Collect_Width × R − T)`:此时记录已是终态,但泄漏的 executor 线程可能仍持有闸门,直到其 `ray.get` 返回或抛出。在该窗口内新到达的任务会以 `server`/503 错误快速失败。 + +每条持久化 future 在创建时写入不可变的 `absolute_deadline`,因此无论哪个 deployment 进程持有 cleanup lease,清理结果都由任务自身契约决定。 diff --git a/poetry.lock b/poetry.lock index 773c9b14..4a7b37e2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,17 @@ -# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. + +[[package]] +name = "absl-py" +version = "2.5.0" +description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "absl_py-2.5.0-py3-none-any.whl", hash = "sha256:0f17b89f2a4eaaedc4f28c622998aa690564b3012a396a4ffad0821007fe03ba"}, + {file = "absl_py-2.5.0.tar.gz", hash = "sha256:0c996f25c0490700fadabe6351630f6111534fa0ae252cc6d2014ea3b141135f"}, +] [[package]] name = "accelerate" @@ -210,6 +223,7 @@ files = [ [package.dependencies] aiohappyeyeballs = ">=2.5.0" aiosignal = ">=1.4.0" +async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" @@ -226,7 +240,7 @@ description = "CORS support for aiohttp" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "aiohttp_cors-0.8.1-py3-none-any.whl", hash = "sha256:3180cf304c5c712d626b9162b195b1db7ddf976a2a25172b35bb2448b890a80d"}, {file = "aiohttp_cors-0.8.1.tar.gz", hash = "sha256:ccacf9cb84b64939ea15f859a146af1f662a6b1d68175754a07315e305fb1403"}, @@ -268,9 +282,10 @@ files = [ name = "aliyun-python-sdk-core" version = "2.11.5" description = "The core module of Aliyun Python SDK." -optional = false +optional = true python-versions = "*" groups = ["main"] +markers = "extra == \"eval\"" files = [ {file = "aliyun-python-sdk-core-2.11.5.tar.gz", hash = "sha256:577265c630c02207c692ca19958bd21665d56208306a834d0885e7770553975e"}, ] @@ -282,9 +297,10 @@ pycryptodome = ">=3.4.7" name = "aliyun-python-sdk-kms" version = "2.16.5" description = "The kms module of Aliyun Python sdk." -optional = false +optional = true python-versions = "*" groups = ["main"] +markers = "extra == \"eval\"" files = [ {file = "aliyun-python-sdk-kms-2.16.5.tar.gz", hash = "sha256:f328a8a19d83ecbb965ffce0ec1e9930755216d104638cd95ecd362753b813b3"}, {file = "aliyun_python_sdk_kms-2.16.5-py2.py3-none-any.whl", hash = "sha256:24b6cdc4fd161d2942619479c8d050c63ea9cd22b044fe33b60bbb60153786f0"}, @@ -324,7 +340,7 @@ description = "The official Python library for the anthropic API" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "anthropic-0.84.0-py3-none-any.whl", hash = "sha256:861c4c50f91ca45f942e091d83b60530ad6d4f98733bfe648065364da05d29e7"}, {file = "anthropic-0.84.0.tar.gz", hash = "sha256:72f5f90e5aebe62dca316cb013629cfa24996b0f5a4593b8c3d712bc03c43c37"}, @@ -370,6 +386,7 @@ files = [ ] [package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} @@ -383,7 +400,7 @@ description = "tvm ffi" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "apache_tvm_ffi-0.1.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d911cbbc83bf12a0d9ec03e5315ff1bb92d95702fe912cd7a050393274382e71"}, {file = "apache_tvm_ffi-0.1.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1c8dd4018420c0d14bace688594710909ce198056ff8ac2ad1cd462b30fe1bdd"}, @@ -437,12 +454,25 @@ description = "Read/rewrite/write Python ASTs" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, ] +[[package]] +name = "async-timeout" +version = "5.0.1" +description = "Timeout context manager for asyncio programs" +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "python_full_version < \"3.11.3\" and extra == \"server\" or python_version == \"3.10\"" +files = [ + {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, + {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, +] + [[package]] name = "attrs" version = "25.4.0" @@ -471,6 +501,19 @@ files = [ [package.extras] dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] +[[package]] +name = "backports-asyncio-runner" +version = "1.2.0" +description = "Backport of asyncio.Runner, a context manager that controls event loop life cycle." +optional = true +python-versions = "<3.11,>=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" and extra == \"test\"" +files = [ + {file = "backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5"}, + {file = "backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162"}, +] + [[package]] name = "beautifulsoup4" version = "4.14.3" @@ -502,7 +545,7 @@ description = "Python bindings for the Rust blake3 crate" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "blake3-1.0.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:8956bb9aec47b6c37ccce935a943588f1f5e6e2e85d43bb7cb76a574238f8a9b"}, {file = "blake3-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7adbbee5dd0c302218eb8acdfd82b7006930eb5798f56f79f9cca89f6f192662"}, @@ -625,7 +668,7 @@ description = "Extensible memoizing collections and decorators" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "cachetools-7.0.1-py3-none-any.whl", hash = "sha256:8f086515c254d5664ae2146d14fc7f65c9a4bce75152eb247e5a9c5e6d7b2ecf"}, {file = "cachetools-7.0.1.tar.gz", hash = "sha256:e31e579d2c5b6e2944177a0397150d312888ddf4e16e12f1016068f0c03b8341"}, @@ -638,7 +681,7 @@ description = "CBOR (de)serializer with extensive tag support" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "cbor2-5.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2263c0c892194f10012ced24c322d025d9d7b11b41da1c357f3b3fe06676e6b7"}, {file = "cbor2-5.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ffe4ca079f6f8ed393f5c71a8de22651cb27bd50e74e2bcd6bc9c8f853a732b"}, @@ -702,10 +745,10 @@ files = [ name = "cffi" version = "2.0.0" description = "Foreign Function Interface for Python calling C code." -optional = true +optional = false python-versions = ">=3.9" groups = ["main"] -markers = "platform_python_implementation != \"PyPy\" and (extra == \"vllm\" or extra == \"ray\") or extra == \"vllm\" and implementation_name == \"pypy\"" +markers = "(platform_python_implementation != \"PyPy\" or implementation_name == \"pypy\") and (implementation_name == \"pypy\" or extra == \"rl\" or extra == \"async-rl\")" files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -923,10 +966,9 @@ files = [ name = "click" version = "8.3.1" description = "Composable command line interface toolkit" -optional = true +optional = false python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\" or extra == \"tinker\"" files = [ {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, @@ -942,7 +984,7 @@ description = "Pickler class to extend the standard pickle.Pickler functionality optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a"}, {file = "cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414"}, @@ -955,7 +997,7 @@ description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["main"] -markers = "(extra == \"vllm\" or extra == \"ray\" or extra == \"docs\") and sys_platform == \"win32\" or platform_system == \"Windows\"" +markers = "(platform_system == \"Windows\" or sys_platform == \"win32\" or extra == \"eval\") and (platform_system == \"Windows\" or extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"test\" or extra == \"docs\")" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -968,7 +1010,7 @@ description = "Terminal string styling done right, in Python." optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "colorful-0.5.8-py2.py3-none-any.whl", hash = "sha256:a9381fdda3337fbaba5771991020abc69676afa102646650b759927892875992"}, {file = "colorful-0.5.8.tar.gz", hash = "sha256:bb16502b198be2f1c42ba3c52c703d5f651d826076817185f0294c1a549a7445"}, @@ -977,6 +1019,25 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} +[[package]] +name = "colorlog" +version = "6.12.0" +description = "Add colours to the output of Python's logging module." +optional = true +python-versions = ">=3.6" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "colorlog-6.12.0-py3-none-any.whl", hash = "sha256:30d392604e9110045a2c2aeefc27d7a017abbab63f3a8aee594eac0801df784e"}, + {file = "colorlog-6.12.0.tar.gz", hash = "sha256:2a7924c1dadf18b22a0eb8b06d1c7b01d5341707ec1641eb6fcc4fde0c3e8e5f"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +development = ["black", "flake8", "mypy", "pytest", "types-colorama"] + [[package]] name = "commonmark" version = "0.9.1" @@ -1000,7 +1061,7 @@ description = "Library for utilization of compressed safetensors of neural netwo optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "compressed_tensors-0.13.0-py3-none-any.whl", hash = "sha256:3518799c9baf034eb642efb551db6b0537b8713d45a64fe4def26f7f8d6cabec"}, {file = "compressed_tensors-0.13.0.tar.gz", hash = "sha256:23893824d3498ea3f1a829f14a8fa85f9a5e76a34c711a038b8d7c619ca9a67c"}, @@ -1020,9 +1081,10 @@ dev = ["black (==22.12.0)", "flake8 (>=3.8.3)", "isort (==5.8.0)", "nbconvert (> name = "crcmod" version = "1.7" description = "CRC Generator" -optional = false +optional = true python-versions = "*" groups = ["main"] +markers = "extra == \"eval\"" files = [ {file = "crcmod-1.7.tar.gz", hash = "sha256:dc7051a0db5f2bd48665a990d3ec1cc305a466a77358ca4492826f41f283601e"}, ] @@ -1034,7 +1096,7 @@ description = "cryptography is a package which provides cryptographic recipes an optional = true python-versions = "!=3.9.0,!=3.9.1,>=3.8" groups = ["main"] -markers = "extra == \"ray\" or extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad"}, {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b"}, @@ -1089,6 +1151,7 @@ files = [ [package.dependencies] cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""} +typing-extensions = {version = ">=4.13.2", markers = "python_full_version < \"3.11.0\""} [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] @@ -1107,7 +1170,7 @@ description = "Python bindings for CUDA" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "cuda_bindings-13.1.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4400370a83f1538e25ed4c18c34a0e9d5fad39741e282e69ce24d1479a11017d"}, {file = "cuda_bindings-13.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:81f92500e2f6aec2dac00a5a1ce77d5aa77ea77b606dc484d951f1f2cc3eaa13"}, @@ -1142,7 +1205,7 @@ description = "Pathfinder for CUDA components" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "cuda_pathfinder-1.4.0-py3-none-any.whl", hash = "sha256:437079ca59e7b61ae439ecc501d69ed87b3accc34d58153ef1e54815e2c2e118"}, ] @@ -1154,7 +1217,7 @@ description = "CUDA Python: Performance meets Productivity" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "cuda_python-13.1.1-py3-none-any.whl", hash = "sha256:944cc4fe6482673d28dd545797a28840945a1668739328fa2ad1e9be4f7050d9"}, ] @@ -1173,7 +1236,7 @@ description = "CuPy: NumPy & SciPy for GPU" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" and sys_platform != \"darwin\"" +markers = "sys_platform != \"darwin\" and (extra == \"rl\" or extra == \"async-rl\")" files = [ {file = "cupy_cuda12x-14.0.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:b42da54c9da0d5a7748e4120f13c47594d3e1fc2741b712591aa915517741096"}, {file = "cupy_cuda12x-14.0.1-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:7c775e1e1ebc0c4c9f94a4c6bb66a0c07d109de5dfcef671f9e4056df4bd81ca"}, @@ -1244,6 +1307,19 @@ tests-numpy2 = ["Pillow (>=9.4.0)", "absl-py", "aiohttp", "decorator", "elastics torch = ["torch"] vision = ["Pillow (>=9.4.0)"] +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "depyf" version = "0.20.0" @@ -1251,7 +1327,7 @@ description = "Decompile python functions, from bytecode to source code!" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "depyf-0.20.0-py3-none-any.whl", hash = "sha256:d31effad4261cebecb58955d832e448ace88f432328f95f82fd99c30fd9308d4"}, {file = "depyf-0.20.0.tar.gz", hash = "sha256:fb7683bd72c44f67b56029df2c47721e9a02ffa4d7b19095f1c54c4ebf797a98"}, @@ -1287,7 +1363,7 @@ description = "Disk Cache -- Disk and file backed persistent cache." optional = true python-versions = ">=3" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19"}, {file = "diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc"}, @@ -1300,7 +1376,7 @@ description = "Distribution utilities" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, @@ -1313,7 +1389,7 @@ description = "Distro - an OS platform information API" optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"tinker\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, @@ -1326,7 +1402,7 @@ description = "DNS toolkit" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af"}, {file = "dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f"}, @@ -1348,7 +1424,7 @@ description = "Parse Python docstrings in reST, Google and Numpydoc format" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708"}, {file = "docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912"}, @@ -1372,6 +1448,103 @@ files = [ {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, ] +[[package]] +name = "dotenv" +version = "0.9.9" +description = "Deprecated package" +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9"}, +] + +[package.dependencies] +python-dotenv = "*" + +[[package]] +name = "editdistance" +version = "0.8.1" +description = "Fast implementation of the edit distance (Levenshtein distance)" +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "editdistance-0.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:adeb705f32b93accc74960d227875abff150ee42d676e428536361fe5f8f5388"}, + {file = "editdistance-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3de77951b105d0972deec7684a0b3d1a9dee69c9b5d34f6e2acc0d76cd4a1c52"}, + {file = "editdistance-0.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e88efb052d45e924606c305cb833a80579dca3e8e4ff01309d50ba2c1c0bbd5"}, + {file = "editdistance-0.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0247e7a1e9c66ea75211a97e725366bff19a52aac2c838ed5f90025630e976dd"}, + {file = "editdistance-0.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67d143429a49ab552411505f550a0fb4285a1d4336e096804d233ec495ac20fc"}, + {file = "editdistance-0.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca9d3be2b10e5d44a950a4bd1e84bca9ebbecd364bce0cf5693bf8224c78eaef"}, + {file = "editdistance-0.8.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5c72aa1df8535f2e2b3d8773a1a7da091bc1a7e52bb396e7e48d375ba687e7b2"}, + {file = "editdistance-0.8.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a606c34a2a6cc190e4fffc856b36333cdcf1f1fab5b22bd3088e585c22d6ca0"}, + {file = "editdistance-0.8.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5af173d442ffac33b7c7990132f97f88818a3abf4b21c0c702a7022df37c0c5c"}, + {file = "editdistance-0.8.1-cp310-cp310-win32.whl", hash = "sha256:fd64b58f5a7b59afd9d75982aaeeacd2a98498bf472fa0360c122ffe6ea4c871"}, + {file = "editdistance-0.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:6c7c62c3cae45ca1fa01bb2722b297b9de1e3a244ac44cfba88bdcb488fe6aee"}, + {file = "editdistance-0.8.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:486105603a273d73d12a54f347dffa70ab281749d7c3879658b377bc49e4b98c"}, + {file = "editdistance-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fad081f5f86a175c1a09a4e9e45b95c9349e454c21e181e842e01c85f1f536fc"}, + {file = "editdistance-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cb78e125f6759398885a775f5eed07c2bb72b2f86da43e674c6b6a3335b273b"}, + {file = "editdistance-0.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3778ca60aa89def9144b70e330bcec5330c7da1d69cb28c612e90b84510a1d3d"}, + {file = "editdistance-0.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fba945eaa0436cf40bc53d7e299dc537c7c71353379a095b7459ff4af910da33"}, + {file = "editdistance-0.8.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:877f2a0d801f32bc1a1878901ffb947b974361e849c66e314a7f1d786a446b58"}, + {file = "editdistance-0.8.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e79d351ca40a6ead5f3763253fd7521572ee0d3e5d42538630e56d10f48db481"}, + {file = "editdistance-0.8.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:70ed382b3052a51161bad0149d4665003bf3b949fce0b01bf1253a4cc1a88239"}, + {file = "editdistance-0.8.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a529bfb384c4000775d76739c4e64f73337f0f5a3784933b1321b577a62bed4e"}, + {file = "editdistance-0.8.1-cp311-cp311-win32.whl", hash = "sha256:b082232429e731f181af7f7d2bcf79da6ca8fadd04e9086c11e2973f7d330c81"}, + {file = "editdistance-0.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:cef1a4359252a49f2c4718e64e9d40027d9d951b289d045bdb278656e59f6af8"}, + {file = "editdistance-0.8.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04af61b3fcdd287a07c15b6ae3b02af01c5e3e9c3aca76b8c1d13bd266b6f57"}, + {file = "editdistance-0.8.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:18fc8b6eaae01bfd9cf999af726c1e8dcf667d120e81aa7dbd515bea7427f62f"}, + {file = "editdistance-0.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6a87839450a5987028738d061ffa5ef6a68bac2ddc68c9147a8aae9806629c7f"}, + {file = "editdistance-0.8.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24b5f9c9673c823d91b5973d0af8b39f883f414a55ade2b9d097138acd10f31e"}, + {file = "editdistance-0.8.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c59248eabfad603f0fba47b0c263d5dc728fb01c2b6b50fb6ca187cec547fdb3"}, + {file = "editdistance-0.8.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84e239d88ff52821cf64023fabd06a1d9a07654f364b64bf1284577fd3a79d0e"}, + {file = "editdistance-0.8.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2f7f71698f83e8c83839ac0d876a0f4ef996c86c5460aebd26d85568d4afd0db"}, + {file = "editdistance-0.8.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:04e229d6f4ce0c12abc9f4cd4023a5b5fa9620226e0207b119c3c2778b036250"}, + {file = "editdistance-0.8.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e16721636da6d6b68a2c09eaced35a94f4a4a704ec09f45756d4fd5e128ed18d"}, + {file = "editdistance-0.8.1-cp312-cp312-win32.whl", hash = "sha256:87533cf2ebc3777088d991947274cd7e1014b9c861a8aa65257bcdc0ee492526"}, + {file = "editdistance-0.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:09f01ed51746d90178af7dd7ea4ebb41497ef19f53c7f327e864421743dffb0a"}, + {file = "editdistance-0.8.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0b6f52a9d7d434f6882db3dc0340e42da6f177644c23f6a02a739b6247a14b82"}, + {file = "editdistance-0.8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5b413aeb8fe3f77a9e95485fcb64ce84e6b14bcd368124d38bd0062167b3456"}, + {file = "editdistance-0.8.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4ba571e8b6796ad34faeb8581ddc311c35946b2fc183eaebfef59e12ea3538b3"}, + {file = "editdistance-0.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e361e932a85ee1f7091fcb8f7e4619681592c1a0cca251dfd26976dd58254"}, + {file = "editdistance-0.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf200104ed4923d4f51ca543bc8488732a31a17848058e65bcba855a7eee2bd2"}, + {file = "editdistance-0.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:387d3bb45befbf8514eb8d17180307580efe4ebaa40ad8b2c14eb04c52ad18a0"}, + {file = "editdistance-0.8.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8e4ea90e92f0e3494bdddad45928393094c258aeef9e4def81a39c3429df0e19"}, + {file = "editdistance-0.8.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5d746ecbf7db7fe0f93ba6971ac43225aac877818a3c2003d41436fee9b33905"}, + {file = "editdistance-0.8.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d789a8ef6fe7cb287ff199381bbd62e9fb2ba4b1e69db817b761d9b42bf8ca7b"}, + {file = "editdistance-0.8.1-cp38-cp38-win32.whl", hash = "sha256:dbbf050fece6c78838a8a95fa4e9a4132023c3d85138870ac83c9dc1dfbfe513"}, + {file = "editdistance-0.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:1c49df0717f64a2c8869edc32c01ba9a22ba20b6cc482876c1067e3a92a6cb2d"}, + {file = "editdistance-0.8.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4d8e9a3e65a68c13dcadc1d2caca620f1716a8d02f2602047e0721b509161ec7"}, + {file = "editdistance-0.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7994a6a0a6ae92db87c144e12f1549ca0e50f43c6cc64e32c628e7af6b9c74b6"}, + {file = "editdistance-0.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dbe0cbc15466e9b7fbf73e34bdcae11cb0c2acd09a60ef4740f2172f9aa5e751"}, + {file = "editdistance-0.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc5f0c7f12a3a3bf2d129e2900deaaa5e47203ef61918343ddc4b6c03e50f089"}, + {file = "editdistance-0.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98572c662fd7d425ff24acb8197ad4be7849558a48aebbc60012090bfda4dce9"}, + {file = "editdistance-0.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b35c647a8a17b77441e7b6111b74ae1016851589109e1efc990d27225b3217b"}, + {file = "editdistance-0.8.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2f56c0e006f6b5207985c1bdd62e1873e66bb06a60849cad32716cad1bb3ae40"}, + {file = "editdistance-0.8.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d6bc5a827b262dc9b0d03cfd821682334ce1280520edf6385dc1730e390b5201"}, + {file = "editdistance-0.8.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ad68a2357664e45823b38c9f67a315ff9771263ec502a710057b78c6ca6fcfcd"}, + {file = "editdistance-0.8.1-cp39-cp39-win32.whl", hash = "sha256:16b3e413c020e42b2ef2d4ba01386ead43007217f0bdd704e90474ace90d2023"}, + {file = "editdistance-0.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:331f1a8d3a753858a9d689c0bcd79ad1959e0df464bb6c22cb263cfb6da208e4"}, + {file = "editdistance-0.8.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a4a90c6b03094c07358572027a8d0a13cca7450b1aa6caca98a5f1fa4f0b8961"}, + {file = "editdistance-0.8.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:510a4f9ced348a4fd89ae2e102357d4d801a771e29bb2bc2f130a1692193407f"}, + {file = "editdistance-0.8.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4787fa7228ba6a34b430066d174320f011d605015baa7299c2c4911e6ea6bd46"}, + {file = "editdistance-0.8.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee02601375073afccd6b4d811129ce1cb696d47db734784d8dbd1fddcea75447"}, + {file = "editdistance-0.8.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bc7ad9f9a20e6f351523de77c59249f005242e3f317b5de45d02c378d24f6531"}, + {file = "editdistance-0.8.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7743895df48482fa5a7136543d6bde72e6c10c78a4a4b772fcddda48f792ef68"}, + {file = "editdistance-0.8.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9f139d921aff07deb2c9e592fe23d994af0e59267962a20c062cd66750a0ca4"}, + {file = "editdistance-0.8.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:493587829de3e500bdf34f03f5ab12501867b911acc838e1d04047a3f8941aad"}, + {file = "editdistance-0.8.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16c521157f5d29bf2cb20472482de8450722685d27a6dd801ff1e80cb13a1fd1"}, + {file = "editdistance-0.8.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2a956eb9584d9e8d165bddd9091791924648071c3cdb1e03ec94b1320c2edefd"}, + {file = "editdistance-0.8.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8131acb6b5170382b8b74efab92df8739ac591dc841314e0153af63c4493cb43"}, + {file = "editdistance-0.8.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f182e5e1d2a446138cab085409395c62af36eb1abcbe8cfacb083febfeafd5ce"}, + {file = "editdistance-0.8.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f4f19a829aff230377041acb77afec73becbebafe35b7e322be00cdb3122ddb"}, + {file = "editdistance-0.8.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b978c5927100a57791131dd2418040f4e5d33970d37b97a84c1a530ec481f557"}, + {file = "editdistance-0.8.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0c96a8e981f385f0b7392d047c5caab8e0b24f94b71120787fd78241efc34237"}, + {file = "editdistance-0.8.1.tar.gz", hash = "sha256:d1cdf80a5d5014b0c9126a69a42ce55a457b457f6986ff69ca98e4fe4d2d8fed"}, +] + [[package]] name = "einops" version = "0.8.2" @@ -1391,7 +1564,7 @@ description = "A robust email address syntax and deliverability validation libra optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4"}, {file = "email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426"}, @@ -1401,6 +1574,115 @@ files = [ dnspython = ">=2.0.0" idna = ">=2.0.0" +[[package]] +name = "evalscope" +version = "1.11.1" +description = "EvalScope: Lightweight LLMs Evaluation Framework" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "evalscope-1.11.1-py3-none-any.whl", hash = "sha256:5058c5112ee0dfff0048a48ee1ff9c6e1ca28bbed39ef5cd34a6a14d3ddf2b66"}, + {file = "evalscope-1.11.1.tar.gz", hash = "sha256:4a6f4437a37543a608a08f5279eb215a2832d32d1ecc812ba8442a67c3340460"}, +] + +[package.dependencies] +aiohttp = "*" +colorlog = "*" +docstring_parser = "*" +dotenv = "*" +editdistance = "*" +filetype = "*" +jieba = "*" +jinja2 = "*" +jsonlines = "*" +jsonschema = "*" +latex2sympy2_extended = {version = "*", extras = ["antlr4-9-3"]} +litellm = ">=1.55,<2.0" +Markdown = "*" +modelscope = {version = ">=1.34", extras = ["datasets"]} +more_itertools = "*" +nltk = "*" +openai = "*" +overrides = "*" +pandas = "*" +pillow = "*" +plotly = "*" +pydantic = "*" +pylatexenc = "*" +pyyaml = ">=5.1" +requests = "*" +rich = "*" +rouge-chinese = "*" +rouge-score = ">=0.1.0" +sacrebleu = "*" +sympy = "*" +tabulate = "*" +tqdm = "*" +transformers = ">=4.33,<4.57.2 || >4.57.2" +word2number = "*" +zhconv = "*" + +[package.extras] +aigc = ["diffusers", "iopath", "lpips", "omegaconf", "open_clip_torch", "opencv-python", "peft (>=0.17)", "torch", "torchvision"] +air-bench = ["soundfile"] +all = ["aiohttp", "diffusers", "fastapi", "flask (>=2.0.0)", "flask (>=2.0.0)", "instructor", "iopath", "jinja2", "langchain (>=0.3.0)", "langchain-community (>=0.3.0)", "langchain-core (>=0.3.0)", "langchain-huggingface (>=0.1.0)", "langchain-openai (>=0.3.0)", "lpips", "modelscope[datasets] (>=1.10.0)", "ms-opencompass (>=0.1.6)", "ms-vlmeval (>=0.0.17)", "mteb (>=2.7.0,<3.0.0)", "numpy", "omegaconf", "open_clip_torch", "openai (>=1.0.0)", "opencv-python", "peft (>=0.17)", "plotly (>=5.23.0)", "plotly (>=5.23.0)", "ragas (>=0.4.0,<0.5.0)", "rich", "sentence-transformers (>=5.4.0)", "sse_starlette", "torch", "torch (>=2.0.0)", "torchvision", "transformers", "unstructured", "uvicorn", "uvloop ; sys_platform != \"win32\"", "webdataset (>0.2.0)"] +app = ["flask (>=2.0.0)", "plotly (>=5.23.0)"] +arena-hard = ["scikit-learn"] +bfcl = ["bfcl-eval (==2025.10.27.1)"] +caption = ["pycocoevalcap"] +cc-ocr-v2 = ["apted", "distance", "lxml", "python-Levenshtein", "scipy", "zss"] +deep-swe = ["datacurve-pier (>=0.3.0)"] +dev = ["hypothesis (==6.155.2)", "pre-commit (==4.6.0)", "pytest", "pytest-cov", "python-dotenv"] +docs = ["docutils (>=0.16.0)", "myst_parser", "recommonmark", "sphinx (>=5.3.0)", "sphinx-design", "sphinxawesome-theme"] +general-arena = ["scikit-learn"] +ifbench = ["emoji", "nltk (>=3.9)", "syllapy"] +ifeval = ["langdetect", "nltk (>=3.9)"] +maritime-ocr-bench = ["numpy", "pillow", "shapely"] +mcp = ["mcp (>=1.0)", "mcp-server-fetch"] +miniwob = ["browsergym-miniwob (==0.14.3)"] +multi-if = ["emoji", "langdetect", "nltk (>=3.9)", "pythainlp"] +needle-haystack = ["matplotlib", "seaborn"] +ocr-bench = ["Polygon3", "apted", "distance", "editdistance", "jieba", "lxml", "nltk (>=3.9)", "python-Levenshtein", "zss"] +olmocr-bench = ["beautifulsoup4", "fuzzysearch", "rapidfuzz"] +olympiad-bench = ["latex2sympy2_extended[antlr4-9-3]"] +omnidoc-bench = ["apted", "beautifulsoup4", "distance", "jieba", "lxml", "python-Levenshtein"] +openai-mrcr = ["tiktoken"] +opencompass = ["ms-opencompass (>=0.1.6)"] +perf = ["aiohttp", "fastapi", "jinja2", "numpy", "rich", "sse_starlette", "transformers", "uvicorn", "uvloop ; sys_platform != \"win32\""] +rag = ["instructor", "langchain (>=0.3.0)", "langchain-community (>=0.3.0)", "langchain-core (>=0.3.0)", "langchain-huggingface (>=0.1.0)", "langchain-openai (>=0.3.0)", "modelscope[datasets] (>=1.10.0)", "mteb (>=2.7.0,<3.0.0)", "openai (>=1.0.0)", "ragas (>=0.4.0,<0.5.0)", "sentence-transformers (>=5.4.0)", "torch (>=2.0.0)", "unstructured", "webdataset (>0.2.0)"] +refcoco = ["pycocoevalcap"] +sandbox = ["ms-enclave[docker] (>=0.0.8)"] +service = ["aiohttp", "fastapi", "flask (>=2.0.0)", "jinja2", "numpy", "plotly (>=5.23.0)", "rich", "sse_starlette", "transformers", "uvicorn", "uvloop ; sys_platform != \"win32\""] +swe-bench = ["swebench (==4.1.0)"] +terminal-bench = ["harbor (>=0.8.0,<1.0.0)"] +toolathlon = ["httpx", "websockets"] +torgo = ["jellyfish", "jiwer"] +vlmeval = ["ms-vlmeval (>=0.0.17)"] +vtcbench = ["beautifulsoup4"] +wide-search = ["dateparser"] +wmt = ["unbabel-comet"] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +groups = ["main"] +markers = "python_version == \"3.10\"" +files = [ + {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, + {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "fastapi" version = "0.135.1" @@ -1440,7 +1722,7 @@ description = "Run and manage FastAPI apps from the command line with FastAPI CL optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "fastapi_cli-0.0.24-py3-none-any.whl", hash = "sha256:4a1f78ed798f106b4fee85ca93b85d8fe33c0a3570f775964d37edb80b8f0edc"}, {file = "fastapi_cli-0.0.24.tar.gz", hash = "sha256:1afc9c9e21d7ebc8a3ca5e31790cd8d837742be7e4f8b9236e99cb3451f0de00"}, @@ -1449,6 +1731,7 @@ files = [ [package.dependencies] fastapi-cloud-cli = {version = ">=0.1.1", optional = true, markers = "extra == \"standard\""} rich-toolkit = ">=0.14.8" +tomli = {version = ">=2.0.0", markers = "python_version < \"3.11\""} typer = ">=0.16.0" uvicorn = {version = ">=0.15.0", extras = ["standard"]} @@ -1464,7 +1747,7 @@ description = "Deploy and manage FastAPI Cloud apps from the command line 🚀" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "fastapi_cloud_cli-0.14.0-py3-none-any.whl", hash = "sha256:325fcb4b45e661184152da6db861d9fb718739fbcd561a4d334dbe78c026586f"}, {file = "fastapi_cloud_cli-0.14.0.tar.gz", hash = "sha256:d3ecb8c942685a71df0af7bd59f463b5eff76f5818b48e5a03c6159726831e68"}, @@ -1473,7 +1756,10 @@ files = [ [package.dependencies] fastar = ">=0.8.0" httpx = ">=0.27.0" -pydantic = {version = ">=2.7.4", extras = ["email"], markers = "python_version < \"3.13\""} +pydantic = [ + {version = ">=2.7.4", extras = ["email"], markers = "python_version < \"3.13\""}, + {version = ">=2.8.0", extras = ["email"], markers = "python_version == \"3.13\""}, +] rich-toolkit = ">=0.19.7" rignore = ">=0.5.1" sentry-sdk = ">=2.20.0" @@ -1490,7 +1776,7 @@ description = "High-level bindings for the Rust tar crate" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "fastar-0.8.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c9f930cff014cf79d396d0541bd9f3a3f170c9b5e45d10d634d98f9ed08788c3"}, {file = "fastar-0.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07b70f712d20622346531a4b46bb332569bea621f61314c0b7e80903a16d14cf"}, @@ -1648,6 +1934,95 @@ files = [ {file = "fastar-0.8.0.tar.gz", hash = "sha256:f4d4d68dbf1c4c2808f0e730fac5843493fc849f70fe3ad3af60dfbaf68b9a12"}, ] +[[package]] +name = "fastuuid" +version = "0.14.0" +description = "Python bindings to Rust's UUID library." +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "fastuuid-0.14.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6e6243d40f6c793c3e2ee14c13769e341b90be5ef0c23c82fa6515a96145181a"}, + {file = "fastuuid-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:13ec4f2c3b04271f62be2e1ce7e95ad2dd1cf97e94503a3760db739afbd48f00"}, + {file = "fastuuid-0.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b2fdd48b5e4236df145a149d7125badb28e0a383372add3fbaac9a6b7a394470"}, + {file = "fastuuid-0.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f74631b8322d2780ebcf2d2d75d58045c3e9378625ec51865fe0b5620800c39d"}, + {file = "fastuuid-0.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83cffc144dc93eb604b87b179837f2ce2af44871a7b323f2bfed40e8acb40ba8"}, + {file = "fastuuid-0.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a771f135ab4523eb786e95493803942a5d1fc1610915f131b363f55af53b219"}, + {file = "fastuuid-0.14.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4edc56b877d960b4eda2c4232f953a61490c3134da94f3c28af129fb9c62a4f6"}, + {file = "fastuuid-0.14.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bcc96ee819c282e7c09b2eed2b9bd13084e3b749fdb2faf58c318d498df2efbe"}, + {file = "fastuuid-0.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7a3c0bca61eacc1843ea97b288d6789fbad7400d16db24e36a66c28c268cfe3d"}, + {file = "fastuuid-0.14.0-cp310-cp310-win32.whl", hash = "sha256:7f2f3efade4937fae4e77efae1af571902263de7b78a0aee1a1653795a093b2a"}, + {file = "fastuuid-0.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:ae64ba730d179f439b0736208b4c279b8bc9c089b102aec23f86512ea458c8a4"}, + {file = "fastuuid-0.14.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:73946cb950c8caf65127d4e9a325e2b6be0442a224fd51ba3b6ac44e1912ce34"}, + {file = "fastuuid-0.14.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:12ac85024637586a5b69645e7ed986f7535106ed3013640a393a03e461740cb7"}, + {file = "fastuuid-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:05a8dde1f395e0c9b4be515b7a521403d1e8349443e7641761af07c7ad1624b1"}, + {file = "fastuuid-0.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09378a05020e3e4883dfdab438926f31fea15fd17604908f3d39cbeb22a0b4dc"}, + {file = "fastuuid-0.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbb0c4b15d66b435d2538f3827f05e44e2baafcc003dd7d8472dc67807ab8fd8"}, + {file = "fastuuid-0.14.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cd5a7f648d4365b41dbf0e38fe8da4884e57bed4e77c83598e076ac0c93995e7"}, + {file = "fastuuid-0.14.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c0a94245afae4d7af8c43b3159d5e3934c53f47140be0be624b96acd672ceb73"}, + {file = "fastuuid-0.14.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2b29e23c97e77c3a9514d70ce343571e469098ac7f5a269320a0f0b3e193ab36"}, + {file = "fastuuid-0.14.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1e690d48f923c253f28151b3a6b4e335f2b06bf669c68a02665bc150b7839e94"}, + {file = "fastuuid-0.14.0-cp311-cp311-win32.whl", hash = "sha256:a6f46790d59ab38c6aa0e35c681c0484b50dc0acf9e2679c005d61e019313c24"}, + {file = "fastuuid-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:e150eab56c95dc9e3fefc234a0eedb342fac433dacc273cd4d150a5b0871e1fa"}, + {file = "fastuuid-0.14.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77e94728324b63660ebf8adb27055e92d2e4611645bf12ed9d88d30486471d0a"}, + {file = "fastuuid-0.14.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:caa1f14d2102cb8d353096bc6ef6c13b2c81f347e6ab9d6fbd48b9dea41c153d"}, + {file = "fastuuid-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d23ef06f9e67163be38cece704170486715b177f6baae338110983f99a72c070"}, + {file = "fastuuid-0.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c9ec605ace243b6dbe3bd27ebdd5d33b00d8d1d3f580b39fdd15cd96fd71796"}, + {file = "fastuuid-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:808527f2407f58a76c916d6aa15d58692a4a019fdf8d4c32ac7ff303b7d7af09"}, + {file = "fastuuid-0.14.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fb3c0d7fef6674bbeacdd6dbd386924a7b60b26de849266d1ff6602937675c8"}, + {file = "fastuuid-0.14.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab3f5d36e4393e628a4df337c2c039069344db5f4b9d2a3c9cea48284f1dd741"}, + {file = "fastuuid-0.14.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b9a0ca4f03b7e0b01425281ffd44e99d360e15c895f1907ca105854ed85e2057"}, + {file = "fastuuid-0.14.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3acdf655684cc09e60fb7e4cf524e8f42ea760031945aa8086c7eae2eeeabeb8"}, + {file = "fastuuid-0.14.0-cp312-cp312-win32.whl", hash = "sha256:9579618be6280700ae36ac42c3efd157049fe4dd40ca49b021280481c78c3176"}, + {file = "fastuuid-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:d9e4332dc4ba054434a9594cbfaf7823b57993d7d8e7267831c3e059857cf397"}, + {file = "fastuuid-0.14.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77a09cb7427e7af74c594e409f7731a0cf887221de2f698e1ca0ebf0f3139021"}, + {file = "fastuuid-0.14.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9bd57289daf7b153bfa3e8013446aa144ce5e8c825e9e366d455155ede5ea2dc"}, + {file = "fastuuid-0.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ac60fc860cdf3c3f327374db87ab8e064c86566ca8c49d2e30df15eda1b0c2d5"}, + {file = "fastuuid-0.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab32f74bd56565b186f036e33129da77db8be09178cd2f5206a5d4035fb2a23f"}, + {file = "fastuuid-0.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33e678459cf4addaedd9936bbb038e35b3f6b2061330fd8f2f6a1d80414c0f87"}, + {file = "fastuuid-0.14.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1e3cc56742f76cd25ecb98e4b82a25f978ccffba02e4bdce8aba857b6d85d87b"}, + {file = "fastuuid-0.14.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cb9a030f609194b679e1660f7e32733b7a0f332d519c5d5a6a0a580991290022"}, + {file = "fastuuid-0.14.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:09098762aad4f8da3a888eb9ae01c84430c907a297b97166b8abc07b640f2995"}, + {file = "fastuuid-0.14.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1383fff584fa249b16329a059c68ad45d030d5a4b70fb7c73a08d98fd53bcdab"}, + {file = "fastuuid-0.14.0-cp313-cp313-win32.whl", hash = "sha256:a0809f8cc5731c066c909047f9a314d5f536c871a7a22e815cc4967c110ac9ad"}, + {file = "fastuuid-0.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:0df14e92e7ad3276327631c9e7cec09e32572ce82089c55cb1bb8df71cf394ed"}, + {file = "fastuuid-0.14.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b852a870a61cfc26c884af205d502881a2e59cc07076b60ab4a951cc0c94d1ad"}, + {file = "fastuuid-0.14.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c7502d6f54cd08024c3ea9b3514e2d6f190feb2f46e6dbcd3747882264bb5f7b"}, + {file = "fastuuid-0.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ca61b592120cf314cfd66e662a5b54a578c5a15b26305e1b8b618a6f22df714"}, + {file = "fastuuid-0.14.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa75b6657ec129d0abded3bec745e6f7ab642e6dba3a5272a68247e85f5f316f"}, + {file = "fastuuid-0.14.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8a0dfea3972200f72d4c7df02c8ac70bad1bb4c58d7e0ec1e6f341679073a7f"}, + {file = "fastuuid-0.14.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1bf539a7a95f35b419f9ad105d5a8a35036df35fdafae48fb2fd2e5f318f0d75"}, + {file = "fastuuid-0.14.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:9a133bf9cc78fdbd1179cb58a59ad0100aa32d8675508150f3658814aeefeaa4"}, + {file = "fastuuid-0.14.0-cp314-cp314-musllinux_1_1_i686.whl", hash = "sha256:f54d5b36c56a2d5e1a31e73b950b28a0d83eb0c37b91d10408875a5a29494bad"}, + {file = "fastuuid-0.14.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:ec27778c6ca3393ef662e2762dba8af13f4ec1aaa32d08d77f71f2a70ae9feb8"}, + {file = "fastuuid-0.14.0-cp314-cp314-win32.whl", hash = "sha256:e23fc6a83f112de4be0cc1990e5b127c27663ae43f866353166f87df58e73d06"}, + {file = "fastuuid-0.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:df61342889d0f5e7a32f7284e55ef95103f2110fee433c2ae7c2c0956d76ac8a"}, + {file = "fastuuid-0.14.0-cp38-cp38-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:47c821f2dfe95909ead0085d4cb18d5149bca704a2b03e03fb3f81a5202d8cea"}, + {file = "fastuuid-0.14.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:3964bab460c528692c70ab6b2e469dd7a7b152fbe8c18616c58d34c93a6cf8d4"}, + {file = "fastuuid-0.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c501561e025b7aea3508719c5801c360c711d5218fc4ad5d77bf1c37c1a75779"}, + {file = "fastuuid-0.14.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dce5d0756f046fa792a40763f36accd7e466525c5710d2195a038f93ff96346"}, + {file = "fastuuid-0.14.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193ca10ff553cf3cc461572da83b5780fc0e3eea28659c16f89ae5202f3958d4"}, + {file = "fastuuid-0.14.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0737606764b29785566f968bd8005eace73d3666bd0862f33a760796e26d1ede"}, + {file = "fastuuid-0.14.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e0976c0dff7e222513d206e06341503f07423aceb1db0b83ff6851c008ceee06"}, + {file = "fastuuid-0.14.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6fbc49a86173e7f074b1a9ec8cf12ca0d54d8070a85a06ebf0e76c309b84f0d0"}, + {file = "fastuuid-0.14.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:de01280eabcd82f7542828ecd67ebf1551d37203ecdfd7ab1f2e534edb78d505"}, + {file = "fastuuid-0.14.0-cp38-cp38-win32.whl", hash = "sha256:af5967c666b7d6a377098849b07f83462c4fedbafcf8eb8bc8ff05dcbe8aa209"}, + {file = "fastuuid-0.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3091e63acf42f56a6f74dc65cfdb6f99bfc79b5913c8a9ac498eb7ca09770a8"}, + {file = "fastuuid-0.14.0-cp39-cp39-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:2ec3d94e13712a133137b2805073b65ecef4a47217d5bac15d8ac62376cefdb4"}, + {file = "fastuuid-0.14.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:139d7ff12bb400b4a0c76be64c28cbe2e2edf60b09826cbfd85f33ed3d0bbe8b"}, + {file = "fastuuid-0.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d55b7e96531216fc4f071909e33e35e5bfa47962ae67d9e84b00a04d6e8b7173"}, + {file = "fastuuid-0.14.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0eb25f0fd935e376ac4334927a59e7c823b36062080e2e13acbaf2af15db836"}, + {file = "fastuuid-0.14.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:089c18018fdbdda88a6dafd7d139f8703a1e7c799618e33ea25eb52503d28a11"}, + {file = "fastuuid-0.14.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fc37479517d4d70c08696960fad85494a8a7a0af4e93e9a00af04d74c59f9e3"}, + {file = "fastuuid-0.14.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:73657c9f778aba530bc96a943d30e1a7c80edb8278df77894fe9457540df4f85"}, + {file = "fastuuid-0.14.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d31f8c257046b5617fc6af9c69be066d2412bdef1edaa4bdf6a214cf57806105"}, + {file = "fastuuid-0.14.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5816d41f81782b209843e52fdef757a361b448d782452d96abedc53d545da722"}, + {file = "fastuuid-0.14.0-cp39-cp39-win32.whl", hash = "sha256:448aa6833f7a84bfe37dd47e33df83250f404d591eb83527fa2cac8d1e57d7f3"}, + {file = "fastuuid-0.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:84b0779c5abbdec2a9511d5ffbfcd2e53079bf889824b32be170c0d8ef5fc74c"}, + {file = "fastuuid-0.14.0.tar.gz", hash = "sha256:178947fc2f995b38497a74172adee64fdeb8b7ec18f2a5934d037641ba265d26"}, +] + [[package]] name = "filelock" version = "3.25.0" @@ -1660,6 +2035,19 @@ files = [ {file = "filelock-3.25.0.tar.gz", hash = "sha256:8f00faf3abf9dc730a1ffe9c354ae5c04e079ab7d3a683b7c32da5dd05f26af3"}, ] +[[package]] +name = "filetype" +version = "1.2.0" +description = "Infer file type and MIME type of any file/buffer. No external dependencies." +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25"}, + {file = "filetype-1.2.0.tar.gz", hash = "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb"}, +] + [[package]] name = "flashinfer-python" version = "0.6.3" @@ -1667,7 +2055,7 @@ description = "FlashInfer: Kernel Library for LLM Serving" optional = true python-versions = "<4.0,>=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "flashinfer_python-0.6.3-py3-none-any.whl", hash = "sha256:0fe2de934a4b3690c543dafb03f38d7bb4a762431abe8ae4f7292d6fef10c65d"}, {file = "flashinfer_python-0.6.3.tar.gz", hash = "sha256:84a762538247a86bc52ff31d9505d161ce1ec059174c1821c87c3ed1e44670fc"}, @@ -1878,7 +2266,7 @@ description = "Read and write ML models in GGUF for GGML" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "gguf-0.18.0-py3-none-any.whl", hash = "sha256:af93f7ef198a265cbde5fa6a6b3101528bca285903949ab0a3e591cd993a1864"}, {file = "gguf-0.18.0.tar.gz", hash = "sha256:b4659093d5d0dccdb5902a904d54b327f4052879fe5e90946ad5fce9f8018c2e"}, @@ -1900,7 +2288,7 @@ description = "Google API client core library" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "google_api_core-2.30.0-py3-none-any.whl", hash = "sha256:80be49ee937ff9aba0fd79a6eddfde35fe658b9953ab9b79c57dd7061afa8df5"}, {file = "google_api_core-2.30.0.tar.gz", hash = "sha256:02edfa9fab31e17fc0befb5f161b3bf93c9096d99aed584625f38065c511ad9b"}, @@ -1909,7 +2297,10 @@ files = [ [package.dependencies] google-auth = ">=2.14.1,<3.0.0" googleapis-common-protos = ">=1.56.3,<2.0.0" -proto-plus = ">=1.22.3,<2.0.0" +proto-plus = [ + {version = ">=1.22.3,<2.0.0"}, + {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""}, +] protobuf = ">=4.25.8,<7.0.0" requests = ">=2.20.0,<3.0.0" @@ -1924,7 +2315,7 @@ description = "Google Authentication Library" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "google_auth-2.48.0-py3-none-any.whl", hash = "sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f"}, {file = "google_auth-2.48.0.tar.gz", hash = "sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce"}, @@ -1953,7 +2344,7 @@ description = "Common protobufs used in Google APIs" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" files = [ {file = "googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038"}, {file = "googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5"}, @@ -1972,7 +2363,7 @@ description = "HTTP/2-based RPC framework" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"server\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "grpcio-1.78.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:7cc47943d524ee0096f973e1081cb8f4f17a4615f2116882a5f1416e4cfe92b5"}, {file = "grpcio-1.78.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c3f293fdc675ccba4db5a561048cca627b5e7bd1c8a6973ffedabe7d116e22e2"}, @@ -2050,7 +2441,7 @@ description = "Standard Protobuf Reflection Service for gRPC" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "grpcio_reflection-1.78.0-py3-none-any.whl", hash = "sha256:06fcfde9e6888cdd12e9dd1cf6dc7c440c2e9acf420f696ccbe008672ed05b60"}, {file = "grpcio_reflection-1.78.0.tar.gz", hash = "sha256:e6e60c0b85dbcdf963b4d4d150c0f1d238ba891d805b575c52c0365d07fc0c40"}, @@ -2067,7 +2458,7 @@ description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\" or extra == \"tinker\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" files = [ {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, @@ -2080,7 +2471,7 @@ description = "Pure-Python HTTP/2 protocol implementation" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"tinker\"" +markers = "python_version >= \"3.11\" and extra == \"client\"" files = [ {file = "h2-4.3.0-py3-none-any.whl", hash = "sha256:c438f029a25f7945c69e0ccf0fb951dc3f73a5f6412981daee861431b70e2bdd"}, {file = "h2-4.3.0.tar.gz", hash = "sha256:6c59efe4323fa18b47a632221a1888bd7fde6249819beda254aeca909f221bf1"}, @@ -2136,7 +2527,7 @@ description = "Pure-Python HPACK header encoding" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"tinker\"" +markers = "python_version >= \"3.11\" and extra == \"client\"" files = [ {file = "hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496"}, {file = "hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca"}, @@ -2149,7 +2540,7 @@ description = "A minimal low-level HTTP client." optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"tinker\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" files = [ {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, @@ -2172,7 +2563,7 @@ description = "A collection of framework independent HTTP protocol utils." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "httptools-0.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:11d01b0ff1fe02c4c32d60af61a4d613b74fad069e47e06e9067758c01e9ac78"}, {file = "httptools-0.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d86c1e5afdc479a6fdabf570be0d3eb791df0ae727e8dbc0259ed1249998d4"}, @@ -2226,7 +2617,7 @@ description = "The next generation HTTP client." optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"tinker\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" files = [ {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, @@ -2253,7 +2644,7 @@ description = "Consume Server-Sent Event (SSE) messages with HTTPX." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc"}, {file = "httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d"}, @@ -2298,6 +2689,24 @@ testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "authlib (>=1. torch = ["safetensors[torch]", "torch"] typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] +[[package]] +name = "hydra-core" +version = "1.3.7" +description = "A framework for elegantly configuring complex applications" +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "hydra_core-1.3.7-py3-none-any.whl", hash = "sha256:83606c4a05c770f1e026e0489875f28989829d151799eabd8cfa8cbe82164515"}, + {file = "hydra_core-1.3.7.tar.gz", hash = "sha256:d4ff629c7e23b64a9db5fe5b027cf7c55b633b737f03be51ef41b77ed016f75e"}, +] + +[package.dependencies] +antlr4-python3-runtime = "==4.9.*" +omegaconf = ">=2.2,<2.4" +packaging = "*" + [[package]] name = "hyperframe" version = "6.1.0" @@ -2305,12 +2714,126 @@ description = "Pure-Python HTTP/2 framing" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"tinker\"" +markers = "python_version >= \"3.11\" and extra == \"client\"" files = [ {file = "hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5"}, {file = "hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08"}, ] +[[package]] +name = "hypothesis" +version = "6.168.0" +description = "The property-based testing library for Python" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"test\"" +files = [ + {file = "hypothesis-6.168.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:47b89491ff02e3ae9b302c440457938e87b47a45b9a1d98ff5575b6910d779e2"}, + {file = "hypothesis-6.168.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:1f4cd0ff11bd470a1a846296ed5fe55e84214194850370994fd1370fe73d3099"}, + {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:732ae5d47482f99d8028cca096729625f05690a83f5e7ce31466e266155792f4"}, + {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2085ee74ac3ab6b70e2f7ffae9b4cb74c246da2f574b2de81a0818a8a30f659f"}, + {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1894782fae5d9a7bb44e6dcf848ccb09ccb5babab48d8b5c31a0a7fc025b82a1"}, + {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecf0ab13cef899efb816ffdd7963e0679f372520884ce06756c7642f3df94213"}, + {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:3f6dcf66270278d078bed01b401f47db4e26456cd909d8e23c6b9366a6c0b131"}, + {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bfef4d46dbf1704a7b8fa3a78778651a2cb18870ca0a70da19c381646822b149"}, + {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1d1aa5b3484e329295d88488a5ba06243909e65c2ab616513c2d36721de4ed1d"}, + {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:3bc00fd8cda04b58e37a1163e8a65389b247b4f5ee547ae37d244a4960995517"}, + {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:990026952d5b2eca290c88f639ac639233f47e13dae338c6dfb6e4774bcab349"}, + {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:a74b0945acbbd552c7c2d0a99a3b5232962b8848c8eed1829451800a9bfcf00b"}, + {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2a380b521b5a76a9e8917d64adcf7f861a45a4360a34b1579af14c5df8eb0377"}, + {file = "hypothesis-6.168.0-cp310-abi3-win32.whl", hash = "sha256:2264f15a1c80329e3ad48e39c44bd5c9429b7b04c9ee62cdd72f4b10aaac9f29"}, + {file = "hypothesis-6.168.0-cp310-abi3-win_amd64.whl", hash = "sha256:5b54769033b84477931d2072e7133a7555e0de5c53fd5ca3bbde960762d7d31b"}, + {file = "hypothesis-6.168.0-cp310-abi3-win_arm64.whl", hash = "sha256:112b0900059bf9d7d6528ed729770629ab146e0d133c4143b9bd4a01dc002bcc"}, + {file = "hypothesis-6.168.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:cb10aa59b0af45badca76911f5323f40d24fdbe00d01b7b67fef8648c99411b5"}, + {file = "hypothesis-6.168.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e21e30b76b6d3adb87c550576132a3204f4c257ec43353f6c09b9d59bb762abc"}, + {file = "hypothesis-6.168.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:527452b43e79e6dfbf9cb69145a940547a3cd177c556698a3fc939ed2354c4b3"}, + {file = "hypothesis-6.168.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:489d5c060f49f495b64215cae627c71730cffd5ef59dc4d7f431932e6e6d2e67"}, + {file = "hypothesis-6.168.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c3af200b322f710c76c2189866246cdcff2039165dd77edff1a7bf1157162fb0"}, + {file = "hypothesis-6.168.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73084b76e4a79cd0f7883ce80fc60c9f374ce7dcad8f520b39db40470ce1852f"}, + {file = "hypothesis-6.168.0-cp310-cp310-win_amd64.whl", hash = "sha256:8067e6b4b48e5cfdc849a1a20c9d4972b3f532b3e3edb5e2b5dfd106045a5236"}, + {file = "hypothesis-6.168.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4d7d29dd63ad9fdc4aa1d65fa272449e14aaf6c6bb8451091818c2945533a43a"}, + {file = "hypothesis-6.168.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a72ed7afa1f7e30488b8a5754fca0ad9755518bdb77d6f0b003cadf7437a5f9"}, + {file = "hypothesis-6.168.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcc5bad4300a751804ce41f0e10d77f85272668160708ce39ec579bca8984843"}, + {file = "hypothesis-6.168.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53469a1a7c4861b12c9a8622f762d7d1fd7bcf171884e1018ed5a8f063a5c063"}, + {file = "hypothesis-6.168.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a9650c4882fdbdd8e90bdae602a8bfa8c6f09dc5d06afec5b9b23982e8f60a04"}, + {file = "hypothesis-6.168.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:348d9b93fd4129f67f9bab94f3d70709a9372bbe0e0d22731325ce85d5eb409f"}, + {file = "hypothesis-6.168.0-cp311-cp311-win_amd64.whl", hash = "sha256:719b45b0512e3535a6a0077c2f7c6053b02ac0e72d60693f66f98790a33855b2"}, + {file = "hypothesis-6.168.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6b750390dac4429da0cb70ab3fe758457f0cea3d9c843d48c59d0690d1189fda"}, + {file = "hypothesis-6.168.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e4b2d434e0dd134f3d31ac1efc1825bf99730dfe70fec005ff66d7211836d79"}, + {file = "hypothesis-6.168.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d4d36ed2fd62de11382f1d608169c1ffa9a49d3b9351146d8ff87cb81a66f7"}, + {file = "hypothesis-6.168.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5920d267f7d8cfd376672f2bde5905cdf284d47519582e41ce7c142d48ee46c4"}, + {file = "hypothesis-6.168.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fb8cdf45361e259df86e19f8cd042ce2d6c7e6ad88fa631b78a4e3a83c2e572d"}, + {file = "hypothesis-6.168.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b3ce1cce70b25a37ed1a38a53ce7204785726c675c0f41a0f83c338a7e47b3d"}, + {file = "hypothesis-6.168.0-cp312-cp312-win_amd64.whl", hash = "sha256:f62bdabf278db9ff61df5f3203d608949f0d893d0e30cdac3f2330e67e41ae68"}, + {file = "hypothesis-6.168.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d55562bf8d41cfa18559c33f30cadf44ceac8e517509d7a022a9feace621f28"}, + {file = "hypothesis-6.168.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92cff497b92e2285ff6a94193fdee04aba483a4115d501c1f9a570bd103fcd20"}, + {file = "hypothesis-6.168.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ff259260015f9be3756dcd4bc11c08e007314dec6b43d9a89084c4f34f94475"}, + {file = "hypothesis-6.168.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35f1262831b5acc74ded15f629965daffcd657f6016ee04fc9605f6eb2b334c0"}, + {file = "hypothesis-6.168.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:046fe4bcfce2a2fa186ba9d96bbb62c25c2f6c2e4071f0783ed6b5cc481d0669"}, + {file = "hypothesis-6.168.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:24b52a2b1c8db6e1e516f9295c8e4ef7ef63303ff24fbbc5b35f4ff71dcd732c"}, + {file = "hypothesis-6.168.0-cp313-cp313-win_amd64.whl", hash = "sha256:ec0886fe0be9091669937989f9a662beca42ae14a4a6dab25491c2c63365f88d"}, + {file = "hypothesis-6.168.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e2df8afacf9261070795db36db4a394e3ccdbb663fd2d38c7a9fba0c836dcecc"}, + {file = "hypothesis-6.168.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9ba679f183c67adcb6f4ad93694beafb6da99fe691757f4e57b04ae77e581ba8"}, + {file = "hypothesis-6.168.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d9a8574f80fc859313aee56167d202e8625c0eedd200971130f0839f06d1c93"}, + {file = "hypothesis-6.168.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deb02de608268928d779aa889b0a9d67794b1cc0c54a322cf19e386be8a46ca7"}, + {file = "hypothesis-6.168.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:076a2096c34448931c3cfeb2eb7a6b843a56ffdce5e4e3a025bfdf8f935666d9"}, + {file = "hypothesis-6.168.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f099b1c8fc49ec2d9d7944e661addb97d7c38e818fb8d1f78073c43895a87f6"}, + {file = "hypothesis-6.168.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:93413d1b0af50a7b165d66278c529174bf2fd1773c78027735dc0b50d1d3fd27"}, + {file = "hypothesis-6.168.0-cp314-cp314-win_amd64.whl", hash = "sha256:db2751c27bffc8491a96d72969649089d5400115e4b7c49bf7167ebbdcc84193"}, + {file = "hypothesis-6.168.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:cd0c1dcf308e919c8ae708054d0ad61921ae87634a9aea574a9851da584cebc1"}, + {file = "hypothesis-6.168.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d0bdb77f976740b8cd5ec697327ea343d02d052b9916d213b5d4c65d823415cd"}, + {file = "hypothesis-6.168.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f7486bed33225d02f6aa78a4c4ba2b6f84992a82571cdda1bf08dce41d13507"}, + {file = "hypothesis-6.168.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ba3838c4a92e0b9730d1ed7e67e4950c152ad79d0a0c7594065262db84c55c4"}, + {file = "hypothesis-6.168.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:891b2d281ede45130e7fa0a22fd65336cc77ef2f780ec3792e8de6fc274a02c8"}, + {file = "hypothesis-6.168.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e86820053afad84677f301c0b892a226be1df49790800a65668ae7cc8a1ac571"}, + {file = "hypothesis-6.168.0-cp314-cp314t-win_amd64.whl", hash = "sha256:a4956f41ab1ec6e6ef9262a35970e9f3e2caaaa1cdafe0d413156c6934dd99d8"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:754016594fe78cef91790e0922f60d183c52f531255fbfa30dac495b813e2128"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:6f0dd437ec01140676192422b61f2f833b3ce6a3213da9b7e196ad6b3777e795"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f77af7721ff35a58fa8797decd14c932c350a2548686c6e9b844db710a3a2441"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a0d28418c104d7268fdebcc09bc49f7b6569b5eb942430c6859f53ec8d4edf63"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:812a84c4cc7f7ae4fcb39a5647cc2698e6c18254f8423126425578f1dcdac782"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6de30e559eb151de14a5f74bceb4d97792a9315ada2a1816b5da825cd7d28edc"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:9018b20acdb061b2ef4b2fa7f558ca5db97ffea316e0a528bc003a24b2ac996e"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bc935a5d5f86fd8f5af951b8fbe00307f6f7c596f82a9a27c17d974f6ab0a26c"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:45fcfa05f746e253350f55f216bcef59754f5f2b85745f1fc2bb8ba81dd517a9"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:f89d8e998d3c936ffbbd1c3686c96f0378f6558aecc5967a3035a857f2bab0ad"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:d0620fa320fa66649e6bfd71e94f3f86115fffebb7e3c6dcece19d1aaff8e07f"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:4085b61e25d3dcc6c9151d4115269870aee8cdb921611ee5c989b2786449be09"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:b5449a64eb37d9a4aa6ac9cd2ab0fd1a24145adf421ef1536884f73f39824887"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-win32.whl", hash = "sha256:91e3de666a6c4f7543000d1710e25055d63ef3032c98bd2ab338b3087bdaa780"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:9a2079cd09919956dd388f1a1f8ea5a79f2b2437650fbeda31d8661217ffefef"}, + {file = "hypothesis-6.168.0-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:085c9aa246487c56a40ca89003d285cbffdbb5be4097ba6d0139f9c21003c04a"}, + {file = "hypothesis-6.168.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:16864797de4b024e4c6cebd44598af932f870aad811341bc5bc24c738801ff76"}, + {file = "hypothesis-6.168.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:283eda952bcb1987ccba1c8b634db0e8a960e1e92e2daa7003bc2392f19cea01"}, + {file = "hypothesis-6.168.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5427a3c951080c18170486f775df6a82153882b819eca6b8e7ed77693634e5ab"}, + {file = "hypothesis-6.168.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a838218ff1eab8d7b4bf66b96037fce0a802f61f2fa5fd4b784696cac365ce7"}, + {file = "hypothesis-6.168.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:34e3c8b66047ba92f8b8df5e427074058d92db58038f007da4bf9d14e934ad3c"}, + {file = "hypothesis-6.168.0.tar.gz", hash = "sha256:72af51087b7b5ab21c49f0d502f803c20897678652835596bd2a8b169a39135e"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.0", markers = "python_full_version < \"3.11.0\""} +sortedcontainers = ">=2.1.0,<3.0.0" + +[package.extras] +all = ["black (>=20.8b0)", "click (>=7.0)", "crosshair-tool (>=0.0.110)", "django (>=5.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.30)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.21.6)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2026.3) ; sys_platform == \"emscripten\" or sys_platform == \"win32\"", "watchdog (>=4.0.0)"] +cli = ["black (>=20.8b0)", "click (>=7.0)", "rich (>=9.0.0)"] +codemods = ["libcst (>=0.3.16)"] +crosshair = ["crosshair-tool (>=0.0.110)", "hypothesis-crosshair (>=0.0.30)"] +dateutil = ["python-dateutil (>=1.4)"] +django = ["django (>=5.2)"] +dpcontracts = ["dpcontracts (>=0.4)"] +ghostwriter = ["black (>=20.8b0)"] +lark = ["lark (>=0.10.1)"] +numpy = ["numpy (>=1.21.6)"] +pandas = ["pandas (>=1.1)"] +pytest = ["pytest (>=4.6)"] +pytz = ["pytz (>=2014.1)"] +redis = ["redis (>=3.0.0)"] +watchdog = ["watchdog (>=4.0.0)"] +zoneinfo = ["tzdata (>=2026.3) ; sys_platform == \"emscripten\" or sys_platform == \"win32\""] + [[package]] name = "idna" version = "3.11" @@ -2333,7 +2856,7 @@ description = "Iterative JSON parser with standard Python iterator interfaces" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "ijson-3.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ea8dcac10d86adaeead454bc25c97b68d0bda573d5fd6f86f5e21cf8f7906f88"}, {file = "ijson-3.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:92b0495bbb2150bbf14fc5d98fb6d76bcd1c526605a172709e602e6fedc96495"}, @@ -2452,7 +2975,7 @@ description = "Read metadata from Python packages" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"megatron\" or extra == \"ray\"" +markers = "(python_version >= \"3.11\" or extra == \"eval\" or extra == \"megatron\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\") and (python_version == \"3.11\" or extra == \"eval\" or extra == \"megatron\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"client\") and (extra == \"client\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"eval\" or extra == \"megatron\")" files = [ {file = "importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151"}, {file = "importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb"}, @@ -2470,6 +2993,19 @@ perf = ["ipython"] test = ["flufl.flake8", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["mypy (<1.19) ; platform_python_implementation == \"PyPy\"", "pytest-mypy (>=1.0.1)"] +[[package]] +name = "iniconfig" +version = "2.3.0" +description = "brain-dead simple config-ini parsing" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"test\"" +files = [ + {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, + {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, +] + [[package]] name = "interegular" version = "0.3.3" @@ -2477,12 +3013,24 @@ description = "a regex intersection checker" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "interegular-0.3.3-py37-none-any.whl", hash = "sha256:b0c07007d48c89d6d19f7204972d369b2a77222722e126b6aa63aa721dc3b19c"}, {file = "interegular-0.3.3.tar.gz", hash = "sha256:d9b697b21b34884711399ba0f0376914b81899ce670032486d0d048344a76600"}, ] +[[package]] +name = "jieba" +version = "0.42.1" +description = "Chinese Words Segmentation Utilities" +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "jieba-0.42.1.tar.gz", hash = "sha256:055ca12f62674fafed09427f176506079bc135638a14e23e25be909131928db2"}, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -2508,7 +3056,7 @@ description = "Fast iterable JSON parser." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" files = [ {file = "jiter-0.13.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2ffc63785fd6c7977defe49b9824ae6ce2b2e2b77ce539bdaf006c26da06342e"}, {file = "jiter-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4a638816427006c1e3f0013eb66d391d7a3acda99a7b0cf091eff4497ccea33a"}, @@ -2621,12 +3169,48 @@ description = "JSON Matching Expressions" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64"}, {file = "jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d"}, ] +[[package]] +name = "joblib" +version = "1.6.0" +description = "Lightweight pipelining with Python functions" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "joblib-1.6.0-py3-none-any.whl", hash = "sha256:3dbbf9f6e4b592a2357b854608e980fe6390d131d7a82f011a377ef2ebef7aba"}, + {file = "joblib-1.6.0.tar.gz", hash = "sha256:2ccc96785b12046c08fd6d55839c12857831b54a3c1673ffadd2f04bfc4eda03"}, +] + +[package.dependencies] +cloudpickle = ">=3.0" + +[package.extras] +docs = ["distributed", "lz4", "matplotlib", "numpy", "numpydoc", "pandas", "psutil", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx-gallery", "tqdm"] +test = ["distributed", "lz4", "memory_profiler", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-run-parallel", "pytest-timeout", "threadpoolctl"] + +[[package]] +name = "jsonlines" +version = "4.0.0" +description = "Library with helpers for the jsonlines file format" +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "jsonlines-4.0.0-py3-none-any.whl", hash = "sha256:185b334ff2ca5a91362993f42e83588a360cf95ce4b71a73548502bda52a7c55"}, + {file = "jsonlines-4.0.0.tar.gz", hash = "sha256:0c6d2c09117550c089995247f605ae4cf77dd1533041d366351f6f298822ea74"}, +] + +[package.dependencies] +attrs = ">=19.2.0" + [[package]] name = "jsonschema" version = "4.26.0" @@ -2634,7 +3218,7 @@ description = "An implementation of JSON Schema validation for Python" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce"}, {file = "jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326"}, @@ -2642,7 +3226,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.3.6" +jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" rpds-py = ">=0.25.0" @@ -2657,7 +3241,7 @@ description = "The JSON Schema meta-schemas and vocabularies, exposed as a Regis optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, @@ -2666,30 +3250,6 @@ files = [ [package.dependencies] referencing = ">=0.31.0" -[[package]] -name = "kernels" -version = "0.12.1" -description = "Download compute kernels" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"kernels\"" -files = [ - {file = "kernels-0.12.1-py3-none-any.whl", hash = "sha256:4569fe00bc6a2b0f2cccff81841d7917af143c786ade152c3b2a78f61097c757"}, - {file = "kernels-0.12.1.tar.gz", hash = "sha256:41e31ef167add0062cdc302a943ce287194c13b5af12b82a5fa76e7353ca0042"}, -] - -[package.dependencies] -huggingface_hub = ">=0.26.0,<2.0" -packaging = ">=20.0" -pyyaml = ">=6" - -[package.extras] -abi-check = ["kernel-abi-check (>=0.6.2,<0.7.0)"] -benchmark = ["numpy (>=2.0.2)", "requests (>=2.32.5)", "torch"] -docs = ["hf-doc-builder"] -torch = ["torch"] - [[package]] name = "lark" version = "1.2.2" @@ -2697,7 +3257,7 @@ description = "a modern parsing library" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "lark-1.2.2-py3-none-any.whl", hash = "sha256:c2276486b02f0f1b90be155f2c8ba4a8e194d42775786db622faccd652d8e80c"}, {file = "lark-1.2.2.tar.gz", hash = "sha256:ca807d0162cd16cef15a8feecb862d7319e7a09bdb13aef927968e45040fed80"}, @@ -2709,6 +3269,107 @@ interegular = ["interegular (>=0.3.1,<0.4.0)"] nearley = ["js2py"] regex = ["regex"] +[[package]] +name = "latex2sympy2-extended" +version = "1.10.2" +description = "Convert LaTeX math to SymPy expressions" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"eval\" or extra == \"async-rl\"" +files = [ + {file = "latex2sympy2_extended-1.10.2-py3-none-any.whl", hash = "sha256:f910442c5b02a466c1046f47d05cc5285181068b882399281f30102715337fb7"}, + {file = "latex2sympy2_extended-1.10.2.tar.gz", hash = "sha256:41a517ffcc5a140e910a7d1646ce6ff440817e5f9d48fc8279d88bd0925bc389"}, +] + +[package.dependencies] +antlr4-python3-runtime = [ + {version = ">=4.9.3,<=4.13.2"}, + {version = "4.9.3", optional = true, markers = "extra == \"antlr4-9-3\""}, +] +sympy = "*" + +[package.extras] +antlr4-11-0 = ["antlr4-python3-runtime (==4.11.0)"] +antlr4-13-2 = ["antlr4-python3-runtime (==4.13.2)"] +antlr4-9-3 = ["antlr4-python3-runtime (==4.9.3)"] +dev = ["pytest"] + +[[package]] +name = "linkify-it-py" +version = "2.2.0" +description = "Links recognition library with FULL unicode support." +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"client\"" +files = [ + {file = "linkify_it_py-2.2.0-py3-none-any.whl", hash = "sha256:3adc40eb5af300b2605fcfdb968c24e1d780a90f1f2221af7c15e5111e94d443"}, + {file = "linkify_it_py-2.2.0.tar.gz", hash = "sha256:907acd2d17ac1fbb9ddb62c8957ccbd6158cac602231a15c3b0cd1e215f03cee"}, +] + +[package.extras] +benchmark = ["pytest", "pytest-benchmark"] +dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"] +doc = ["myst-parser", "sphinx", "sphinx_book_theme"] +test = ["coverage", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "litellm" +version = "1.95.0" +description = "Library to easily interface with LLM API providers" +optional = true +python-versions = "<3.15,>=3.10" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "litellm-1.95.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:0106b3564b60d00cb5b2810824ebf5071f59c9f9262318884d9c6f040aa2c435"}, + {file = "litellm-1.95.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:053cea1a584bf92d5d44b422f99fa03715bf7c346c8fe080c29bf0c6bd71eddc"}, + {file = "litellm-1.95.0-cp310-cp310-win_amd64.whl", hash = "sha256:667cc7cc58e05a9f9c4bf4588cd4ff5c785fd265060acdfb9147332b75b73ce9"}, + {file = "litellm-1.95.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:4bafa3494d503a3c6c1f2eeb785a2af364d85463c71a92cabaaa761c9227d62a"}, + {file = "litellm-1.95.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:4c2a06d2263a07a29228cd3af2b594cf86cd3a4182a7324c517cba88a9415969"}, + {file = "litellm-1.95.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac37bb6d2be191bafc0ce590ed06d21dd7e5a37599ffc1af1071899f6c74b73"}, + {file = "litellm-1.95.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:cb667f84f08520f32b076e03c7a3fa51bf3f7e8b641dade34ab046bf00314d6b"}, + {file = "litellm-1.95.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:1bdf7153557cc0851fa9477b137fde476c56d5de92a5778ecfc6c3a75439a4e1"}, + {file = "litellm-1.95.0-cp312-cp312-win_amd64.whl", hash = "sha256:62cc5d834e8223dbd16c9ad0b46c73354b6d67cc7fa0eba2764ce65b3b8c474f"}, + {file = "litellm-1.95.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9d80a9adc506bfce48145621d6649e3fd428407811eb00211bcce33344054701"}, + {file = "litellm-1.95.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:cf014ff515825ad49937b4cdf95616270789311db7841d16702e0a5b1ac5b067"}, + {file = "litellm-1.95.0-cp313-cp313-win_amd64.whl", hash = "sha256:c73df441153e585832d4e90e3717d17ae888b269daa71d723336369e81ef884b"}, + {file = "litellm-1.95.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:c8e712f95764a9a730f3aec9dff8be916973423411ca12a79a35c8bea3f7d5a4"}, + {file = "litellm-1.95.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:071a63c0e1d949bf7ed5e5c73843cb042a6e00324d3f214b13f8c6b90da6822d"}, + {file = "litellm-1.95.0-cp314-cp314-win_amd64.whl", hash = "sha256:c3684dcf16aefe98bd6f11586d60a9a92bb1bf7e85468a6a4ac28a65532fab3e"}, + {file = "litellm-1.95.0.tar.gz", hash = "sha256:0ef126d52c7a559f8353e50d60fd0d5e7e6c8767ad54df25ddaf79b9edca1afc"}, +] + +[package.dependencies] +aiohttp = ">=3.10,<4.0" +click = ">=8.0.0,<9.0" +fastuuid = ">=0.14.0,<1.0" +httpx = ">=0.28.0,<1.0" +importlib-metadata = ">=8.0.0,<9.0" +jinja2 = ">=3.1.6,<4.0" +jsonschema = ">=4.0.0,<5.0" +openai = ">=2.20.0,<3.0.0" +pydantic = ">=2.10.0,<3.0.0" +python-dotenv = ">=1.0.0,<2.0" +tiktoken = ">=0.8.0,<1.0" +tokenizers = ">=0.21.0,<1.0" + +[package.extras] +bedrock-realtime = ["aws-sdk-bedrock-runtime (>=0.7.0,<0.8.0) ; python_full_version >= \"3.12.0\""] +caching = ["diskcache (>=5.6.3,<6.0)"] +cli = ["inquirerpy (>=0.3.4,<1.0)", "pyyaml (>=6.0.3,<7.0)", "requests (>=2.32.0,<3.0)", "rich (>=13.9.4,<14.0)"] +extra-proxy = ["a2a-sdk (>=1.1.0,<2.0)", "azure-identity (>=1.25.2,<2.0)", "azure-keyvault-secrets (>=4.10.0,<5.0)", "google-cloud-iam (>=2.19.1,<3.0)", "google-cloud-kms (>=2.24.2,<3.0)", "prisma (>=0.11.0,<1.0)", "redisvl (>=0.4.1,<1.0)", "resend (>=2.23.0,<3.0)"] +google = ["google-cloud-aiplatform (>=1.133.0,<2.0)"] +grpc = ["grpcio (==1.78.0)"] +mlflow = ["mlflow (>=3.11.1,<4.0)"] +proxy = ["apscheduler (>=3.11.2,<4.0)", "azure-identity (>=1.25.2,<2.0)", "azure-storage-blob (>=12.28.0,<13.0)", "backoff (>=2.2.1,<3.0)", "boto3 (>=1.43.1,<2.0)", "cryptography (>=48.0.1,<49.0)", "expression (>=5.6.0,<6.0)", "fastapi (>=0.136.3,<1.0)", "fastapi-sso (>=0.19.0,<1.0)", "granian (>=2.7.4,<3.0)", "gunicorn (>=23.0.0,<24.0)", "inquirerpy (>=0.3.4,<1.0)", "litellm-enterprise (==0.1.52)", "litellm-proxy-extras (==0.4.81)", "mcp (>=1.28.1,<2.0)", "orjson (>=3.11.6,<4.0)", "polars (>=1.38.1,<2.0)", "pydantic-settings (>=2.14.1,<3.0)", "pyjwt (>=2.13.0,<3.0)", "pynacl (>=1.6.2,<2.0)", "pyroscope-io (>=0.8.16,<1.0) ; sys_platform != \"win32\"", "python-multipart (>=0.0.27,<1.0)", "pyyaml (>=6.0.3,<7.0)", "restrictedpython (>=8.1,<9.0)", "rich (>=13.9.4,<14.0)", "rq (>=2.7.0,<3.0)", "soundfile (>=0.12.1,<1.0)", "starlette (>=1.0.1,<2.0)", "uvicorn (>=0.33.0,<1.0)", "uvloop (>=0.21.0,<1.0) ; sys_platform != \"win32\"", "websockets (>=15.0.1,<16.0)"] +proxy-runtime = ["anthropic[vertex] (>=0.84.0,<1.0)", "azure-ai-contentsafety (>=1.0.0,<2.0)", "azure-storage-file-datalake (>=12.20.0,<13.0)", "ddtrace (>=4.8.2,<5.0)", "detect-secrets (>=1.5.0,<2.0)", "google-cloud-aiplatform (>=1.133.0,<2.0)", "google-genai (>=1.37.0,<2.0)", "grpcio (==1.78.0)", "langfuse (>=2.59.7,<3.0)", "llm-sandbox (>=0.3.39,<1.0)", "mangum (>=0.17.0,<1.0)", "opentelemetry-api (==1.28.0)", "opentelemetry-exporter-otlp (==1.28.0)", "opentelemetry-instrumentation-fastapi (==0.49b0)", "opentelemetry-sdk (==1.28.0)", "prometheus-client (>=0.20.0,<1.0)", "pypdf (>=6.12.0,<7.0)", "sentry-sdk (>=2.21.0,<3.0)"] +saml = ["python3-saml (>=1.16.0,<2.0)"] +semantic-router = ["aurelio-sdk (>=0.0.19,<1.0) ; python_full_version < \"3.14.0\"", "semantic-router (>=0.1.15,<1.0) ; python_full_version < \"3.14.0\""] +stt-nvidia-riva = ["audioread (>=3.0.1)", "numpy (>=1.26.0)", "nvidia-riva-client (>=2.15.0)", "soundfile (>=0.12.1)"] +utils = ["numpydoc (>=1.8.0,<2.0)"] + [[package]] name = "llguidance" version = "1.3.0" @@ -2716,7 +3377,7 @@ description = "Bindings for the Low-level Guidance (llguidance) Rust library for optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\" and (platform_machine == \"x86_64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\")" +markers = "(extra == \"rl\" or extra == \"async-rl\") and (platform_machine == \"x86_64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\")" files = [ {file = "llguidance-1.3.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f7685222660a762e481ac633d49cc559c64980fe2ee59c8f932a5bb5cbc0c2c2"}, {file = "llguidance-1.3.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:098030ff0687261a3f1bd54cf21fe951fc861d56d37a0671250dd36677eaf224"}, @@ -2735,7 +3396,7 @@ description = "lightweight wrapper around basic LLVM functionality" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "llvmlite-0.44.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:9fbadbfba8422123bab5535b293da1cf72f9f478a65645ecd73e781f962ca614"}, {file = "llvmlite-0.44.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cccf8eb28f24840f2689fb1a45f9c0f7e582dd24e088dcf96e424834af11f791"}, @@ -2767,7 +3428,7 @@ description = "Enforce the output format (JSON Schema, Regex etc) of a language optional = true python-versions = "<4.0,>=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "lm_format_enforcer-0.11.3-py3-none-any.whl", hash = "sha256:cf586350875def1ae7a8fba84fcbbfc8371424b6c9d05c1fcba70aa233fbf06f"}, {file = "lm_format_enforcer-0.11.3.tar.gz", hash = "sha256:e68081c108719cce284a9bcc889709b26ffb085a1945b5eba3a12cfa96d528da"}, @@ -2786,7 +3447,7 @@ description = "Python logging made (stupidly) simple" optional = true python-versions = "<4.0,>=3.5" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, @@ -2797,7 +3458,200 @@ colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] -dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==0.910) ; python_version < \"3.6\"", "mypy (==0.971) ; python_version == \"3.6\"", "mypy (==1.13.0) ; python_version >= \"3.8\"", "mypy (==1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] +dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==v0.910) ; python_version < \"3.6\"", "mypy (==v0.971) ; python_version == \"3.6\"", "mypy (==v1.13.0) ; python_version >= \"3.8\"", "mypy (==v1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] + +[[package]] +name = "lxml" +version = "6.1.3" +description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "lxml-6.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:40bcbd9f94166ffe925811e730607385cec959f42fb1bb7dad83748680465221"}, + {file = "lxml-6.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:05f5bce9af14fd1506997594bd81cee6d9c6b58ea80a39c058327aa6371ed9e9"}, + {file = "lxml-6.1.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff88a92cafde90888511242d1c54afcc1a8adbb6dc0a88fa7f87e29e92400d4a"}, + {file = "lxml-6.1.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c00e26288784460885fe76e4d4b293573e0f791f52e6d60e27b42edf005922eb"}, + {file = "lxml-6.1.3-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:773062aec2f2e56b2b22d37054123f0de8a22a4688a0c3376c3fe42685f975cf"}, + {file = "lxml-6.1.3-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f6449672f9c93316deb5e2839e18931f468670e44d5bd9b1301a5a9655d45c07"}, + {file = "lxml-6.1.3-cp310-cp310-manylinux_2_28_i686.whl", hash = "sha256:ec295280f4b37769256da025acf5890370355ac589c27e89caae0b5e9eedc702"}, + {file = "lxml-6.1.3-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:5929d9df5e7e3379183be0e21f7d559618a5b61cb63280df6164019242e337ed"}, + {file = "lxml-6.1.3-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6e1eb8a4cbffd5553680ad96be6680e364710656eced73d1dc90ec489df599a3"}, + {file = "lxml-6.1.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:16148acd77ed1d8836a56db883af2f5eed720f9723088110b16a0d08582130a6"}, + {file = "lxml-6.1.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:23c366231259cd75ad06495174701afb3fcb36a92917fa47de2d1f1bd9d95739"}, + {file = "lxml-6.1.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:da85db328e507da922d586c3c7416ec360ec22e9cd9e0700691afacde0c81f53"}, + {file = "lxml-6.1.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0f17d83c48ee9dfd96abae3ac3e2108c76d2fc86ce96355e37b8da9f7f4ecc08"}, + {file = "lxml-6.1.3-cp310-cp310-win32.whl", hash = "sha256:7dd624c1eaa629ad44b59a1a0145fdf2d67895592dce94c9358b938b3d075e65"}, + {file = "lxml-6.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:18a4db52b5a7b53a3540b0b0f4123319334621ee8083d496de314d0bf06ff59a"}, + {file = "lxml-6.1.3-cp310-cp310-win_arm64.whl", hash = "sha256:0feebef8d0521188d0157f758356072e840173aa61ca45b8b3f87959ac283dd5"}, + {file = "lxml-6.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c66f858b82497173f73366795fc6ee8171620e75a338506d6b2e7bc16f5fca11"}, + {file = "lxml-6.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:032a0a97eed428bd143c75a11118238546424ceb2fa311cca5f073aa44658dc4"}, + {file = "lxml-6.1.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4a579dfb9c835f8ab47f4b8ed33440cbc75b806b73297208e6ec2a33e903740b"}, + {file = "lxml-6.1.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:49fbc2682a9306135b7ec49e93f97f9c26689b9b7f96ed2742d8d6497e994d13"}, + {file = "lxml-6.1.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea2c01cdb16dc12156e455007c406dfaaece0c89aa4ba0e3b47586779f951d41"}, + {file = "lxml-6.1.3-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:527195c188d7d0af748cd48d220ab8cdc5cb99be3d49ac4d9be7324d8abf9bc0"}, + {file = "lxml-6.1.3-cp311-cp311-manylinux_2_28_i686.whl", hash = "sha256:20384c2bbcbf87180c8c61eb60869699c1ec0cd09b62cfd13804022d860b0867"}, + {file = "lxml-6.1.3-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:424aa5657141d306ba9ad1baab4b2c0a0719040075ee6c66aee9bb2dea2b5054"}, + {file = "lxml-6.1.3-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4736e6c87e603146d8949d8501da621ad20c31015060d3fcf95ace2859f3e3e6"}, + {file = "lxml-6.1.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6374e9e382e5a98c9c5e66d41b357b470da1c54bce30f17f9dc4bcc58436cc1c"}, + {file = "lxml-6.1.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:22eec57e26c418cde02c051ce9914a365e52a7f135a565c6f0480242aeebab48"}, + {file = "lxml-6.1.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8753b8d51dbc86fd335ee31fcf7f3658e9f5c016d4edfb23f76ad295f4b8c9d0"}, + {file = "lxml-6.1.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:207dfc3d47cf0e575e643bbc140dacc8863b39abaa1e5307cd64c7f2365b8a12"}, + {file = "lxml-6.1.3-cp311-cp311-win32.whl", hash = "sha256:18293f8a8d8b6a8e71ef37706b659e3846a4261232158167b1ddf35f6994f633"}, + {file = "lxml-6.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:7ae4949f212a53b007dbc355884fda122545c5764a54256c9217e419a62a6559"}, + {file = "lxml-6.1.3-cp311-cp311-win_arm64.whl", hash = "sha256:2123e5aa075ac20d23c7af489255efd129cbfe190dbe88fd42598cc9df3199b6"}, + {file = "lxml-6.1.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c0710ac085a157b593c38fbcacd950f15c4afa8e2057527185875ab302752bc"}, + {file = "lxml-6.1.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:623c8799c17128753c65699f1c3aa32402657393a9ad6db09ed8b98ddf76611d"}, + {file = "lxml-6.1.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f683dc6300317700025e41d89a43e0276692ded16113a3c43eab704d605c58e5"}, + {file = "lxml-6.1.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:379f8a75cf6eb7eef0af074b55f49ab73b868388a98de14646abcdfa4564bb11"}, + {file = "lxml-6.1.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b37772102d44bb6628186accca3a121b1fa3a6b3d97518a8c29a5229ca4c0d0a"}, + {file = "lxml-6.1.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ddcf547bea2aee967d6a77779376a45e77e610e8465147a1f3d7e20d539d6e32"}, + {file = "lxml-6.1.3-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:909f4e927bb051f7740d6367285fc60cdcfdaf0258c2dba4ff5ba7eadadc250c"}, + {file = "lxml-6.1.3-cp312-cp312-manylinux_2_28_i686.whl", hash = "sha256:a5c18810318303ce9afb3f95e2ddb54834f96fa699a8600433fd5a93dcf44c56"}, + {file = "lxml-6.1.3-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:3e42265103fb385d8642a78672edf376c6f7e1d3598a7a4f9cb1278f2f6b5f6f"}, + {file = "lxml-6.1.3-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:21402998e4b78e7cce237d2788841aaa21ac9a4d1574d04dc2d12ee41ae807b5"}, + {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:38fc4e4e4e084e0bd491949482527d406788045c546d4f8789e93fc527b91385"}, + {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5609efdb0d3c95499c00046bc53648b3482ec2175b5503d6e611b3f0555dc71d"}, + {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:97ce49699d87ebf8aad631b55d65b33219a4f1bfefbbf5bff19dc9af160aeaf9"}, + {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:48542c9acba9ff9450bd18d871d2c2c8787fdb283572b623d206f1b927cd7d9e"}, + {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c55e71a9b1db1f107efb60da49c093689b74c5c31a708e5379e2fd9439d4fbb5"}, + {file = "lxml-6.1.3-cp312-cp312-win32.whl", hash = "sha256:b3ff39654f0ce6ebd4db154211136dbe7e8157bcc3bed2344c87f32c7c6ecb6c"}, + {file = "lxml-6.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:3e9a00d1c2c30936f7add097c41afc5da6556c580909104aafd382cac92a855c"}, + {file = "lxml-6.1.3-cp312-cp312-win_arm64.whl", hash = "sha256:1aeca87830c4fe649dcf93fe2b059525b71c72587f21be4ae4af7103082a79fa"}, + {file = "lxml-6.1.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3a48093cdb058a93af842ede9703520e810b05dcd0fc6d7190a06376c3bfb6bd"}, + {file = "lxml-6.1.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:887c021d9a977cff89cb273047c1352997b772a8908a25c21836861f69b92be1"}, + {file = "lxml-6.1.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:611a51e61c92f62345a50b0035df6fc0d678f9299f33728826d831598862f59d"}, + {file = "lxml-6.1.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b477912f42c5c33405a10c759d22f80cf5af043ae02d95b9d8e5e5bc555739ed"}, + {file = "lxml-6.1.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cffe18571ccc51d742cd08cbb3f8b756de9311d18c7ea98f5d92f37b8fb60c2"}, + {file = "lxml-6.1.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:75cc6569e86be5785b6188ef1642670c6adbc984e81ec35e224842ecd9eefcc8"}, + {file = "lxml-6.1.3-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d85dfab42dd672f87a7f76e9de7172962aee69fa12044f0d6e1a23cbd53fb80e"}, + {file = "lxml-6.1.3-cp313-cp313-manylinux_2_28_i686.whl", hash = "sha256:42632b4024ab24a6b488f559ac851312509888b6b80ae2aa11cf29a646a0d245"}, + {file = "lxml-6.1.3-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:febd35ef45f603c2d74b74655efdbf45e14f55fc0aef4ac82b663ca829b283e0"}, + {file = "lxml-6.1.3-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a43b3bdf11e477dc7770609d3477316f974354dfc8425d596f64f471cc8daf6e"}, + {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d582042c69857c364e8153de6e18e0da9b7b515a6a8113caf69a6ec8e0520f2"}, + {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8e49a646acfab83c68974f4aa1d0a2acca9e88d7d627ae0fc13201b14b76d310"}, + {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0dee106e9aa97fb00541b1ed7827070564d0549c3d3fba8920e6b20fd980f748"}, + {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:dd5e90f34cffcfed97f36cf066325773d2b6021c60c29942e53a18b028501b1d"}, + {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d9b3e7d71bf6acff341233417abbdface29c647e3113892d9aaedc02eb4aa2bc"}, + {file = "lxml-6.1.3-cp313-cp313-win32.whl", hash = "sha256:160fcf381f76c3aeac28a756bec44f48942a8f7245a87aa28e3a523b4d90cd87"}, + {file = "lxml-6.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:e477aca0bc0d19f3b4ae9e4f2a1cfd687c31bf772d78734910658186b40b2477"}, + {file = "lxml-6.1.3-cp313-cp313-win_arm64.whl", hash = "sha256:b1cc980905221a5d8b3c476330730b3adb40ff80add71ffbdb6215ba055656f1"}, + {file = "lxml-6.1.3-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:2bec13085dc8ef48a3fe62f7dfcacfeda2c785cdf19cc8eeda2bb9ed081da165"}, + {file = "lxml-6.1.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4f4db7c7e954d289d71878938348b3d91b904a3e8210a11939359fb758a58e7d"}, + {file = "lxml-6.1.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2cae5d5c90a62d9139c512a0cb1aad1d182b022b5740daea2617eb5bf7fc658e"}, + {file = "lxml-6.1.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c6c0c13128a32eb04a51357e56a094e13aa8e6d3d1884de2e9ae923f6915e1a8"}, + {file = "lxml-6.1.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2221e88679d1351e9a40aaee54bc65679b9795bbd0160bc3d5e36b163344eb75"}, + {file = "lxml-6.1.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cfb398886a7eb4c719161c3efcff2a1248febc53a4d8e5072d2d8a87fed84ac9"}, + {file = "lxml-6.1.3-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7eb78ba28b187e1e9203a55c60fcf70df2d22cb205fe6d51b9383d6097419f0"}, + {file = "lxml-6.1.3-cp314-cp314-manylinux_2_28_i686.whl", hash = "sha256:ea6b1e9105b4b24a34c722432d9fb578f9ed83af21fa1abda639011e0f22bbb6"}, + {file = "lxml-6.1.3-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:e8b17e23df3e827a69d25af70990ca2420e92668aaffaeeb3cd2351d7916a023"}, + {file = "lxml-6.1.3-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b7c37339d7e75cab9a123a04248e243cefefb302ad6db566ea0c77cbcde421e"}, + {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:83e3a51e7933db700a0da0db31849db3a24022d9970da9bb73001e1d0326fd92"}, + {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:9bde9ae026a55b9a192078dfa6e27dd0ca4a050171ab6272e92f97b757dfdf48"}, + {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1a635e837b50a1819bebfedaac5916498ea024120969da8790500148fb0a894d"}, + {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d0c5c362bc94f1929dc7e96e715bbe7bd17037f802e6d8f0d1545df9133c0559"}, + {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c59e4265608da6a041f54646ecc0c9ecdbb19aaf14c4c684bb6c2114998cc415"}, + {file = "lxml-6.1.3-cp314-cp314-win32.whl", hash = "sha256:2e62c569ec7531b679b184cbfe335c501c1d13c4b363560013019962eb630e6d"}, + {file = "lxml-6.1.3-cp314-cp314-win_amd64.whl", hash = "sha256:66299564c046bc7e0cc5de5106601eae907e9fa5904cd68a323380a8502f7861"}, + {file = "lxml-6.1.3-cp314-cp314-win_arm64.whl", hash = "sha256:ebd054ad1737a68fb7c5c073d405cef2b88bb824e294de3b4a4e995b47f0e376"}, + {file = "lxml-6.1.3-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:5a143e6207579de8baeded4eaac9134413200359f1969d636f0bfb98ee8c3c8f"}, + {file = "lxml-6.1.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a1cec0f99b9b914d39176347a93b7610dc09324491aee1cbc57cd291a41a1d55"}, + {file = "lxml-6.1.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f6b9d2aad499c769ee8287609ab0e6de99d8bcea99c6e6c2e64945259fd52fb2"}, + {file = "lxml-6.1.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a23fefdb345b2d4d0ff2860571b5ff9a89a28b6a120f720e8fb0324d346626"}, + {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:545ccc14fb05485f48b4439ec35beb16d5b5280eb6c81c658bd4707a2a119414"}, + {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:93476b6514b373fc6ca67d26c442784f7807c86f00635bfe79f935c3eab2af17"}, + {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8db38ff3fb7aee7d6a82ae4da2eef1178656fe1216841fbd24870062a9d60473"}, + {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:25f4118c438f96bb466e83108506d03d5c31b1bd2387e83e5b070bda6ded9c37"}, + {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:1beb0f9909b26cee938df9ba56b15252a84429b1fc30ce6fca161390b9789a70"}, + {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3a27ac6c780c8b8a1cd231b58407634cafc1c4cc28cd6c7141362df0f36351e7"}, + {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a1932d7ce78a561367512c594fe66eac2b2ec9b9264cfd9b5f950622f4a116e2"}, + {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:7d0f5976aa2701996f759b30172925829867547bb073af0ae67d1307a0f0262c"}, + {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e7ce578aa8a80910a72a8ca0bbea3baae10100827249001999726a788456d8"}, + {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d97c5227621af74b111882a290b10f371780a38eef9d9e730408fba2259b52fb"}, + {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:da707f14ea3c35ee463d50acd596d6488e4b2b4ae7cf77a5bf93f55c023d63e8"}, + {file = "lxml-6.1.3-cp314-cp314t-win32.whl", hash = "sha256:9efe56a68179f3adc4de41861c9358931db03837c48dd5e1c78077b84dd07f3a"}, + {file = "lxml-6.1.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c9389b3784b56c58d933b5e0aecdf28f901b073ff385358d8a7d40907f6e14b2"}, + {file = "lxml-6.1.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32a409be3190b088f960ac92bfedfbef2f86c49ff940765e1548177592d20026"}, + {file = "lxml-6.1.3-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:6ea2f13dce778ca072ccee598bca46a092ce192e8fd907b6c1f0e52c800529a0"}, + {file = "lxml-6.1.3-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:c581b1d68b3845fb86c6b2983e755b29bf001461c59fa411d2c26a911b6559a9"}, + {file = "lxml-6.1.3-cp315-cp315-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e01125896585139453cab8cb235893644d8815d7509520da95ae3ee8d1c1f79"}, + {file = "lxml-6.1.3-cp315-cp315-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:290f66b97ede0e552e1cb44a0fd8a74f9753ee635b50830a0b122fb72788d015"}, + {file = "lxml-6.1.3-cp315-cp315-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73fc05988ed20809450474ba760a87c8ad4e455fc09783c02195e56ec634b41a"}, + {file = "lxml-6.1.3-cp315-cp315-manylinux_2_31_armv7l.whl", hash = "sha256:dc3a44689eea43eab836e5c98a8ab015dc2419987d1ea6eafc7c590cdff86bed"}, + {file = "lxml-6.1.3-cp315-cp315-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:209c3ccbfe35a04ac6d24f0611f9d1cbf8025d49991b14acd935236234d6c156"}, + {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:2f5b2a2b9811b853b39bfa41367c6d78747b8e3e80e07fc5a24aae295c1a4d7d"}, + {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:6a406d0b3cb207b0fa460ed4dc93e866f44f105da0169361cb18ff998a44c7f0"}, + {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:53258656846f5c48996b882fb4b135885e088a3ad3d96b4bc0530f95124d1f69"}, + {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:aa633613ff907ea91b9b0489a1f0da1b8725d8c6ccec6b77e8a1c9c235044bb0"}, + {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:90f709b9accab6b2e4d14f5c8718203877a0486bcb3afd74d8b539ecd1e961d4"}, + {file = "lxml-6.1.3-cp315-cp315-win32.whl", hash = "sha256:b4fc6b03b9d9d90557274f571ab30e7fbbfc527955536935d96f98b6817a86e4"}, + {file = "lxml-6.1.3-cp315-cp315-win_amd64.whl", hash = "sha256:33cadd956b667997e4de1635fce9541f2e8ede2038fcde8cf55aa14d571d1bad"}, + {file = "lxml-6.1.3-cp315-cp315-win_arm64.whl", hash = "sha256:8a330c0ee5fa318c7b5cbbaad882baeca3f570357e7eb25ab34bf31008150758"}, + {file = "lxml-6.1.3-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:0bf5a3e397df2ec4258eb5eea4c1ac6cf013ca1abd04a176903bff20a70021fe"}, + {file = "lxml-6.1.3-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:13d22c0d57355366b393936acf6b98a5e0edeadddd3fccbc6a846c50a76b8741"}, + {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cad7617727a96d189bd6f979d0fadf765198c7934e85f4edaba9bf3ad919a300"}, + {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cae82b5ca24b0c2beedb269f6e2a96f466acd926879ab00ae19f1a65cbf9ffb0"}, + {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:69cafd61aea04ebb3502c93c2aaa568b12931ca0802231e0b5de76bf8b6e74bd"}, + {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_31_armv7l.whl", hash = "sha256:dc205732d593118cf701d986f40e9de7801bb2e371cb189ddbda9b7348f4d97e"}, + {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:88e719b9437f148f7e1465df845c758dd1598618cbea3a2fd1e61a715542f2b2"}, + {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:40983eabefd13da003e68170928c7acc011f0d095eefce5871a3c71c9385fb9a"}, + {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:fad67b12ffe0f71e02b4932b04883cbc76a9072bbd30731409d3523cf058b011"}, + {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd11e7550d89e551a87dcec30f04b1fca32e86b68708aa01a4daa455d8605e5"}, + {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:ca0ec532ad2f5ba1e5ec120ac157769c57f01855b3d8bf37213f5d88abd9ba0a"}, + {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:e99e09ab7741f1281e2677f4c0058c7f5267d182530b09c87e4f6aa26adf3887"}, + {file = "lxml-6.1.3-cp315-cp315t-win32.whl", hash = "sha256:ace1d2c83b2bd24db5940600541140e87a325e119cb32d5fa9ad720d7e76648e"}, + {file = "lxml-6.1.3-cp315-cp315t-win_amd64.whl", hash = "sha256:b49638355ea3bebba70da783ccbc630fd72afa16bc46c54474bfa1f9a915bbc6"}, + {file = "lxml-6.1.3-cp315-cp315t-win_arm64.whl", hash = "sha256:5a721a98c649855963811b59b55755b30566e7f7fc40bdc9803d66dee9f811cf"}, + {file = "lxml-6.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:13a620a3fcc20023f9e6ed5c383e00e826f1c2d5db554df2f67240760f9118e8"}, + {file = "lxml-6.1.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fbfb70ba01355251faf6b293171df49f73a88a1b6494db109ffea85442574458"}, + {file = "lxml-6.1.3-cp38-cp38-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:302f72413251c03f671e063c9414bed5dc8c927069e5abb69245521e51a4e81b"}, + {file = "lxml-6.1.3-cp38-cp38-manylinux_2_28_i686.whl", hash = "sha256:ce1f220114959941170e22b8ad44279f6dee2dcef7591814d01ae805dc058889"}, + {file = "lxml-6.1.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:170773d8a3cdc76259065523ddd978c44f9806e28605f08812e8f86783e44ac6"}, + {file = "lxml-6.1.3-cp38-cp38-win32.whl", hash = "sha256:92d96586376fb79a33474797186bf993250152ee5c32650b67db78d54b92e6f3"}, + {file = "lxml-6.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:d44442effeb8781f392340c5dc8c6716fba41dbeacb82fd4c0f09026fb5ff682"}, + {file = "lxml-6.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:869dfcd4d381cb0ea87085cc4f011b9171b494ef21e76ad8665f6d5e2d1dc8a1"}, + {file = "lxml-6.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6ba4fe5bfbef6811a8e49b3719cde373ad399006c0c1ac184b7297116ecbba5d"}, + {file = "lxml-6.1.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:61116cec57ed69aebc70f37a545eec095339bb829efbdabcfb97c51e9536e158"}, + {file = "lxml-6.1.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4e11e885e0704be185867fcf71b904d8f65d7d6877bc121f69870b0d0479ba7b"}, + {file = "lxml-6.1.3-cp39-cp39-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41e2d428110b408e963b6fb18f9bbf1f5c027b56bd4b498d54556476c0aeb1c3"}, + {file = "lxml-6.1.3-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa9fd1ee2a5dacfc41039ed49ffeeacfa75bafbd255b69f3b578e11897a0e623"}, + {file = "lxml-6.1.3-cp39-cp39-manylinux_2_28_i686.whl", hash = "sha256:7f75b9b9fec2a9c6b18095c81865580e795b1441c429e42d22fcc82a77f40039"}, + {file = "lxml-6.1.3-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:cc669256d28736f7f3a149df5c380c50ace2692ba3e62203d10656fade4a2145"}, + {file = "lxml-6.1.3-cp39-cp39-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d077f21f4b16f0471353883748f126f62038760397c107bb9fad2ca94dc0dfb7"}, + {file = "lxml-6.1.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0d12846d6ce434fb3857918eef4315ec9b4769deb020c75828798614bfcfd"}, + {file = "lxml-6.1.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:2b9b1325ca1c2a9a2dbb6eb913ae563313f2082ae60b03210f7e83ee80712274"}, + {file = "lxml-6.1.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:a2e3f70673a1d5b82f38255f777d26cd855bf2092b1436c4867464a7892f9238"}, + {file = "lxml-6.1.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c34ca1dc41bd86d9ff830d5bdf4e4a752bba6c54f7d2707027ce0eabd36084c9"}, + {file = "lxml-6.1.3-cp39-cp39-win32.whl", hash = "sha256:b50343241eb69fd85f7791cf8bcc7b1c4729826b7d59ba2f6b27db29638fa745"}, + {file = "lxml-6.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:0794e04ba343852c6d78e996c58ef4b8e579b4ecc72f8df0d4058bf843b4c96e"}, + {file = "lxml-6.1.3-cp39-cp39-win_arm64.whl", hash = "sha256:0ab2467e405e748d93495fb5568e74044802b8d3ff2b2a1607c3f78c6e982de5"}, + {file = "lxml-6.1.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4b061064b4a2fe8598a466d723d43dbcd5a610a5d5cfe02fb6226f5c17349f75"}, + {file = "lxml-6.1.3-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8499d464de86fab0f102313cce32a9bed9ab1f06ec813cf025cb790964fbb765"}, + {file = "lxml-6.1.3-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9e67324961ac9bbe616cce5100514d2e34d88665aeb07071e8b16eac55d06d94"}, + {file = "lxml-6.1.3-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d12669a2c419b0e8dc423d23dea24bb82f6f9cb829f32e04674b0ba40322a7c"}, + {file = "lxml-6.1.3-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97acecb11cbc411473f15b8d780df06d7a9f3a2aad9aca78364f56640c8fb70e"}, + {file = "lxml-6.1.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f8b9c8ceebae6387d0dc77f7f4dbbfbfc962dba2efbfe6877486075a480726b4"}, + {file = "lxml-6.1.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d2765c18ce303149ee804b1f3dad11232726dd0a702d73a15cf19179ac8cc962"}, + {file = "lxml-6.1.3-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d5a748d12dd9b535e0a130f60dae9ddf0adafbabe61e7864f55c7436c84547a"}, + {file = "lxml-6.1.3-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:41096ec0740a58dad03d3ae0c7486d306d20becefb13ceb1649835ab3eb64167"}, + {file = "lxml-6.1.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:415e3a115c0d510e329020012834d1c0aa1c581ee53a218603e38abbc1dea70a"}, + {file = "lxml-6.1.3-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20428910dae17a1a93152a3ff2c0441d2f4932992c0797d65651dd0561f1792f"}, + {file = "lxml-6.1.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bc8dd3d9c93e70c3df974a201ac2958b6d77b465d813c51d1f15fa8e645763ae"}, + {file = "lxml-6.1.3-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3847e71a78cbbc1aff955dbbbaf2fff12153f611d3162c5beaa3395636cbc2f9"}, + {file = "lxml-6.1.3-pp39-pypy39_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe91993149523aa59941b9e3c90e2eb45f57ad014697aef6c8b13339a59c019e"}, + {file = "lxml-6.1.3-pp39-pypy39_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:71532ebf30be0048a45559b4fab15333fbaaf9042f658e878d918ecd0cf09805"}, + {file = "lxml-6.1.3-pp39-pypy39_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c1b50797ac246bb2942a04b6c0f69af0667aba7cf7535f39bbb1b3208fd5d128"}, + {file = "lxml-6.1.3-pp39-pypy39_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2bb7d703bed7ac893bf7f40d97b5d9279d35d2ce460624ca28929eab0d5a3d"}, + {file = "lxml-6.1.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:be5346653c0b0e34be96869ff9dbeba23860156f89a2896a64c64fb419260cb6"}, + {file = "lxml-6.1.3.tar.gz", hash = "sha256:45222d94ddd511536f3b2f7d9deae3b2339b4ce0f075f1ca25703b07cad9dd21"}, +] + +[package.extras] +cssselect = ["cssselect (>=0.7)"] +html-clean = ["lxml_html_clean"] +html5 = ["html5lib"] +htmlsoup = ["BeautifulSoup4"] [[package]] name = "markdown" @@ -2806,7 +3660,7 @@ description = "Python implementation of John Gruber's Markdown." optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"docs\"" +markers = "extra == \"eval\" or extra == \"docs\"" files = [ {file = "markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36"}, {file = "markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950"}, @@ -2820,16 +3674,16 @@ testing = ["coverage", "pyyaml"] name = "markdown-it-py" version = "2.2.0" description = "Python port of markdown-it. Markdown parsing, done right!" -optional = true +optional = false python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"tinker\" or extra == \"docs\"" files = [ {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, ] [package.dependencies] +linkify-it-py = {version = ">=1,<3", optional = true, markers = "extra == \"linkify\""} mdurl = ">=0.1,<1.0" [package.extras] @@ -2941,6 +3795,52 @@ files = [ {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] +[[package]] +name = "math-verify" +version = "0.8.0" +description = "HuggingFace library for verifying mathematical answers" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "math_verify-0.8.0-py3-none-any.whl", hash = "sha256:31ca651296d817a9bb3fd58ca1fd0d192dcea709b1e5ecf2d0a4514c16f89087"}, + {file = "math_verify-0.8.0.tar.gz", hash = "sha256:3295e0adb94bfe553ff6e3189c44f1916a85aa24ab5d1900f2086a706e28f7c4"}, +] + +[package.dependencies] +latex2sympy2_extended = "1.10.2" + +[package.extras] +antlr4-11-0 = ["latex2sympy2_extended[antlr4-11-0]"] +antlr4-13-2 = ["latex2sympy2_extended[antlr4-13-2]"] +antlr4-9-3 = ["latex2sympy2_extended[antlr4-9-3]"] +dev = ["math-verify[format]", "math-verify[test]"] +format = ["ruff"] +inference = ["lighteval[math]"] +test = ["pytest"] + +[[package]] +name = "mcore-bridge" +version = "1.6.4" +description = "MCore-Bridge: Making Megatron training as simple as Transformers" +optional = true +python-versions = ">=3.8.0" +groups = ["main"] +markers = "extra == \"megatron\"" +files = [ + {file = "mcore_bridge-1.6.4-py3-none-any.whl", hash = "sha256:df8ab70f3a8122184833221af8f7756ff937bf980ee6fef6cbeaa3fcc1d00a73"}, + {file = "mcore_bridge-1.6.4.tar.gz", hash = "sha256:6df211f0e810d0d3d4be61de72bf68aa730c7da00a7ed5ecc18ffd1ec3563cf2"}, +] + +[package.dependencies] +megatron-core = ">=0.16,<0.20" +modelscope = "*" +peft = ">=0.11,<0.21" +safetensors = "*" +tqdm = "*" +transformers = ">=4.33,<5.17.0" + [[package]] name = "mcp" version = "1.26.0" @@ -2948,7 +3848,7 @@ description = "Model Context Protocol SDK" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "mcp-1.26.0-py3-none-any.whl", hash = "sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca"}, {file = "mcp-1.26.0.tar.gz", hash = "sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66"}, @@ -2982,7 +3882,7 @@ description = "Collection of plugins for markdown-it-py" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"docs\"" +markers = "extra == \"client\" or extra == \"docs\"" files = [ {file = "mdit-py-plugins-0.3.5.tar.gz", hash = "sha256:eee0adc7195e5827e17e02d2a258a2ba159944a0748f59c5099a4a27f78fcf6a"}, {file = "mdit_py_plugins-0.3.5-py3-none-any.whl", hash = "sha256:ca9a0714ea59a24b2b044a1831f48d817dd0c817e84339f20e7889f392d77c4e"}, @@ -3000,10 +3900,9 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" -optional = true +optional = false python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"tinker\" or extra == \"docs\"" files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -3046,7 +3945,7 @@ description = "Mistral-common is a library of common utilities for Mistral AI." optional = true python-versions = "<3.14,>=3.10.0" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "mistral_common-1.9.1-py3-none-any.whl", hash = "sha256:9e2b2520b6f67bac2e2bb06fcf985b7a1277b01938da2b7cda8cf0fdbfa92e91"}, {file = "mistral_common-1.9.1.tar.gz", hash = "sha256:550583d70a395c3586cfb748ffab53bd1d7c3409507f0efc0118bff30ffb26e9"}, @@ -3126,6 +4025,8 @@ files = [ [package.dependencies] numpy = [ {version = ">=1.23.3", markers = "python_version >= \"3.11\""}, + {version = ">=1.21.2", markers = "python_version == \"3.10\""}, + {version = ">=2.1.0", markers = "python_version >= \"3.13\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] @@ -3139,7 +4040,7 @@ description = "A framework for machine learning on Apple silicon." optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" and platform_machine == \"arm64\" and platform_system == \"Darwin\"" +markers = "(extra == \"rl\" or extra == \"async-rl\") and platform_machine == \"arm64\" and platform_system == \"Darwin\"" files = [ {file = "mlx-0.31.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:38680838e0dd9a621ed4adc5a9ed8b94aeb6a4798142fbe215b821b8c6b8fc36"}, {file = "mlx-0.31.0-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:7aded590bcf6839307c3acc899e196936991f97b499ddbdd0cd3b228bf10792f"}, @@ -3185,7 +4086,7 @@ description = "LLMs with MLX and the Hugging Face Hub" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\" and platform_machine == \"arm64\" and platform_system == \"Darwin\"" +markers = "(extra == \"rl\" or extra == \"async-rl\") and platform_machine == \"arm64\" and platform_system == \"Darwin\"" files = [ {file = "mlx_lm-0.29.1-py3-none-any.whl", hash = "sha256:440941b3054c2a2216e97615de584cc90fa1ea874782e20699b9895721fad8dc"}, {file = "mlx_lm-0.29.1.tar.gz", hash = "sha256:b99180d8f33d33a077b814e550bfb2d8a59ae003d668fd1f4b3fff62a381d34b"}, @@ -3214,7 +4115,7 @@ description = "A framework for machine learning on Apple silicon." optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" and platform_machine == \"arm64\" and platform_system == \"Darwin\"" +markers = "(extra == \"rl\" or extra == \"async-rl\") and platform_machine == \"arm64\" and platform_system == \"Darwin\"" files = [ {file = "mlx_metal-0.31.0-py3-none-macosx_14_0_arm64.whl", hash = "sha256:1c572a6e3634a63060c103b0c38ac309e2d217be15519e3d8f0d6b452bb015f5"}, {file = "mlx_metal-0.31.0-py3-none-macosx_15_0_arm64.whl", hash = "sha256:554dc7cb29e0ea5fb6941df42f11a1de385b095848e6183c7a99d7c1f1a11f5d"}, @@ -3228,7 +4129,7 @@ description = "Python toolkit for standardized model hosting container implement optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "model_hosting_container_standards-0.1.13-py3-none-any.whl", hash = "sha256:be307d4a988cc660df4e6bd8bdedb7917844bac940e332f9fd001cb385d7994c"}, {file = "model_hosting_container_standards-0.1.13.tar.gz", hash = "sha256:27a1333410dde2719286a300a2803e24fdde407baa91894eb845c0f268aa194d"}, @@ -3256,19 +4157,47 @@ files = [ ] [package.dependencies] -addict = {version = "*", optional = true, markers = "extra == \"framework\""} -attrs = {version = "*", optional = true, markers = "extra == \"framework\""} -datasets = {version = ">=3.0.0,<=3.6.0", optional = true, markers = "extra == \"framework\""} -einops = {version = "*", optional = true, markers = "extra == \"framework\""} +addict = [ + {version = "*", optional = true, markers = "extra == \"framework\""}, + {version = "*", optional = true, markers = "extra == \"datasets\""}, +] +attrs = [ + {version = "*", optional = true, markers = "extra == \"framework\""}, + {version = "*", optional = true, markers = "extra == \"datasets\""}, +] +datasets = [ + {version = ">=3.0.0,<=3.6.0", optional = true, markers = "extra == \"framework\""}, + {version = ">=3.0.0,<=3.6.0", optional = true, markers = "extra == \"datasets\""}, +] +einops = [ + {version = "*", optional = true, markers = "extra == \"framework\""}, + {version = "*", optional = true, markers = "extra == \"datasets\""}, +] filelock = "*" -Pillow = {version = "*", optional = true, markers = "extra == \"framework\""} -python-dateutil = {version = ">=2.1", optional = true, markers = "extra == \"framework\""} +oss2 = {version = "*", optional = true, markers = "extra == \"datasets\""} +Pillow = [ + {version = "*", optional = true, markers = "extra == \"framework\""}, + {version = "*", optional = true, markers = "extra == \"datasets\""}, +] +python-dateutil = [ + {version = ">=2.1", optional = true, markers = "extra == \"framework\""}, + {version = ">=2.1", optional = true, markers = "extra == \"datasets\""}, +] PyYAML = {version = ">=5.4", optional = true, markers = "extra == \"framework\""} requests = ">=2.25" -scipy = {version = "*", optional = true, markers = "extra == \"framework\""} +scipy = [ + {version = "*", optional = true, markers = "extra == \"framework\""}, + {version = "*", optional = true, markers = "extra == \"datasets\""}, +] setuptools = "*" -simplejson = {version = ">=3.3.0", optional = true, markers = "extra == \"framework\""} -sortedcontainers = {version = ">=1.5.9", optional = true, markers = "extra == \"framework\""} +simplejson = [ + {version = ">=3.3.0", optional = true, markers = "extra == \"framework\""}, + {version = ">=3.3.0", optional = true, markers = "extra == \"datasets\""}, +] +sortedcontainers = [ + {version = ">=1.5.9", optional = true, markers = "extra == \"framework\""}, + {version = ">=1.5.9", optional = true, markers = "extra == \"datasets\""}, +] tqdm = ">=4.64.0" transformers = {version = "*", optional = true, markers = "extra == \"framework\""} urllib3 = ">=1.26" @@ -3292,6 +4221,19 @@ science = ["Pillow", "PyYAML (>=5.4)", "addict", "attrs", "biopython", "datasets server = ["fastapi", "sse-starlette", "uvicorn"] tests = ["expecttest", "flake8", "isort (>=4.3.21)", "pre-commit", "yapf (==0.30.0)"] +[[package]] +name = "more-itertools" +version = "11.1.0" +description = "More routines for operating on iterables, beyond itertools" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "more_itertools-11.1.0-py3-none-any.whl", hash = "sha256:4b65538ae22f6fed0ce4874efd317463a7489796a0939fa66824dd542125a192"}, + {file = "more_itertools-11.1.0.tar.gz", hash = "sha256:48e8f4d9e7e5878571ecf6f2b4e57634f93cd474cc8cfbd2376f2d11b396e30d"}, +] + [[package]] name = "mpmath" version = "1.3.0" @@ -3317,7 +4259,7 @@ description = "MessagePack serializer" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "msgpack-1.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0051fffef5a37ca2cd16978ae4f0aef92f164df86823871b5162812bebecd8e2"}, {file = "msgpack-1.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a605409040f2da88676e9c9e5853b3449ba8011973616189ea5ee55ddbc5bc87"}, @@ -3390,7 +4332,7 @@ description = "A fast serialization and validation library, with builtin support optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "msgspec-0.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:23a6ec2a3b5038c233b04740a545856a068bc5cb8db184ff493a58e08c994fbf"}, {file = "msgspec-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cde2c41ed3eaaef6146365cb0d69580078a19f974c6cb8165cc5dcd5734f573e"}, @@ -3611,6 +4553,9 @@ files = [ {file = "multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d"}, ] +[package.dependencies] +typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} + [[package]] name = "multiprocess" version = "0.70.16" @@ -3660,10 +4605,58 @@ sphinx = ">=5,<7" [package.extras] code-style = ["pre-commit (>=3.0,<4.0)"] linkify = ["linkify-it-py (>=1.0,<2.0)"] -rtd = ["ipython", "pydata-sphinx-theme (==0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.7.5,<0.8.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] +rtd = ["ipython", "pydata-sphinx-theme (==v0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.7.5,<0.8.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=7,<8)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4,<0.4.0)"] +[[package]] +name = "narwhals" +version = "2.26.0" +description = "Extremely lightweight compatibility layer between dataframe libraries" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "narwhals-2.26.0-py3-none-any.whl", hash = "sha256:29326d74f107c347fd1009bd58e38d9f7c7c5b51e6de97bc93dbc325d9038b54"}, + {file = "narwhals-2.26.0.tar.gz", hash = "sha256:6b9cadca82f375c7e4cf584fdc86ca25da54827307a9c58f94547ee6104b82dd"}, +] + +[package.extras] +cudf = ["cudf-cu12 (>=24.10.0) ; sys_platform == \"linux\""] +dask = ["dask[dataframe] (>=2024.8)"] +duckdb = ["duckdb (>=1.1)"] +ibis = ["ibis-framework (>=6.0.0)", "packaging (>=21.3)", "pyarrow-hotfix (>=0.7)"] +modin = ["modin (>=0.22.0)"] +pandas = ["pandas (>=1.3.4)"] +polars = ["polars (>=0.20.4)"] +pyarrow = ["pyarrow (>=13.0.0)"] +pyspark = ["pyspark (>=3.5.0)"] +pyspark-connect = ["pyspark[connect] (>=3.5.0)"] +sql = ["narwhals[duckdb]", "sqlparse (>=0.5.5)"] +sqlframe = ["sqlframe (>=3.22.0,!=3.39.3)"] + +[[package]] +name = "networkx" +version = "3.4.2" +description = "Python package for creating and manipulating graphs and networks" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version == \"3.10\"" +files = [ + {file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"}, + {file = "networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1"}, +] + +[package.extras] +default = ["matplotlib (>=3.7)", "numpy (>=1.24)", "pandas (>=2.0)", "scipy (>=1.10,!=1.11.0,!=1.11.1)"] +developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] +doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.15)", "sphinx (>=7.3)", "sphinx-gallery (>=0.16)", "texext (>=0.6.7)"] +example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "momepy (>=0.7.2)", "osmnx (>=1.9)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"] +extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"] +test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] + [[package]] name = "networkx" version = "3.6.1" @@ -3671,6 +4664,7 @@ description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = "!=3.14.1,>=3.11" groups = ["main"] +markers = "python_version >= \"3.11\"" files = [ {file = "networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762"}, {file = "networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509"}, @@ -3694,7 +4688,7 @@ description = "Ninja is a small build system with a focus on speed" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "ninja-1.13.0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:fa2a8bfc62e31b08f83127d1613d10821775a0eb334197154c4d6067b7068ff1"}, {file = "ninja-1.13.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3d00c692fb717fd511abeb44b8c5d00340c36938c12d6538ba989fe764e79630"}, @@ -3717,6 +4711,34 @@ files = [ {file = "ninja-1.13.0.tar.gz", hash = "sha256:4a40ce995ded54d9dc24f8ea37ff3bf62ad192b547f6c7126e7e25045e76f978"}, ] +[[package]] +name = "nltk" +version = "3.10.3" +description = "Natural Language Toolkit" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "nltk-3.10.3-py3-none-any.whl", hash = "sha256:ff9598a8e20518ee0d557745890cc4435b9578489e2dcbc69c4f81fa060caf7c"}, + {file = "nltk-3.10.3.tar.gz", hash = "sha256:bb9327a461c3811c2fa4900e03840401f2126adfb30c0072827c433bd2444ea4"}, +] + +[package.dependencies] +click = "*" +defusedxml = "*" +joblib = "*" +regex = ">=2021.8.3" +tqdm = "*" + +[package.extras] +all = ["matplotlib", "numpy", "pyparsing", "python-crfsuite", "requests", "scikit-learn", "scipy", "twython"] +corenlp = ["requests"] +machine-learning = ["numpy", "python-crfsuite", "scikit-learn", "scipy"] +plot = ["matplotlib"] +tgrep = ["pyparsing"] +twitter = ["twython"] + [[package]] name = "numba" version = "0.61.2" @@ -3724,7 +4746,7 @@ description = "compiling Python code using LLVM" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "numba-0.61.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:cf9f9fc00d6eca0c23fc840817ce9f439b9f03c8f03d6246c0e7f0cb15b7162a"}, {file = "numba-0.61.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ea0247617edcb5dd61f6106a56255baab031acc4257bddaeddb3a1003b4ca3fd"}, @@ -3917,7 +4939,7 @@ description = "CUDNN FrontEnd python library" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "nvidia_cudnn_frontend-1.18.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:baa6fbc8e7c55f1c78c0374ed9a890e1cf81acaca0c92d6135d18a8e3c985244"}, {file = "nvidia_cudnn_frontend-1.18.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4bcca42259e358002c8867e3624a558f66cd5dff2cc6c3aafd860ef2f41730"}, @@ -4043,7 +5065,7 @@ description = "NVIDIA CUTLASS Python DSL" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "nvidia_cutlass_dsl-4.4.1-py3-none-any.whl", hash = "sha256:7b8ffa0117be35ef6c9a88f4462ee2a794efd0f7d9f65090e10a953e434fbfce"}, ] @@ -4061,7 +5083,7 @@ description = "NVIDIA CUTLASS Python DSL" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "nvidia_cutlass_dsl_libs_base-4.4.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:f8e3ecf646074bea34b301be283578806e02b712f277717f3dd1b28671aefa95"}, {file = "nvidia_cutlass_dsl_libs_base-4.4.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:fb2dc0039061fa4e03db6ffc54eaebc7a3b590f45463be461f048b819bb99efe"}, @@ -4085,7 +5107,7 @@ description = "Python Bindings for the NVIDIA Management Library" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" files = [ {file = "nvidia_ml_py-13.590.48-py3-none-any.whl", hash = "sha256:fd43d30ee9cd0b7940f5f9f9220b68d42722975e3992b6c21d14144c48760e43"}, {file = "nvidia_ml_py-13.590.48.tar.gz", hash = "sha256:8184d1be52914ac7f0991cd1c0d946c65dc88a840c754cd12c274b77b88760dd"}, @@ -4252,7 +5274,7 @@ description = "The official Python library for the openai API" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" files = [ {file = "openai-2.24.0-py3-none-any.whl", hash = "sha256:fed30480d7d6c884303287bde864980a4b137b60553ffbcf9ab4a233b7a73d94"}, {file = "openai-2.24.0.tar.gz", hash = "sha256:1e5769f540dbd01cb33bc4716a23e67b9d695161a734aff9c5f925e2bf99a673"}, @@ -4281,7 +5303,7 @@ description = "OpenAI's response format for its open-weight model series gpt-oss optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "openai_harmony-0.0.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:029ec25ca74abe48fdb58eb9fdd2a8c1618581fc33ce8e5653f8a1ffbfbd9326"}, {file = "openai_harmony-0.0.8-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4f709815924ec325b9a890e6ab2bbb0ceec8e319a4e257328eb752cf36b2efc"}, @@ -4311,7 +5333,7 @@ description = "A stats collection and distributed tracing framework" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "opencensus-0.11.4-py2.py3-none-any.whl", hash = "sha256:a18487ce68bc19900336e0ff4655c5a116daf10c1b3685ece8d971bddad6a864"}, {file = "opencensus-0.11.4.tar.gz", hash = "sha256:cbef87d8b8773064ab60e5c2a1ced58bbaa38a6d052c41aec224958ce544eff2"}, @@ -4329,7 +5351,7 @@ description = "OpenCensus Runtime Context" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "opencensus-context-0.1.3.tar.gz", hash = "sha256:a03108c3c10d8c80bb5ddf5c8a1f033161fa61972a9917f9b9b3a18517f0088c"}, {file = "opencensus_context-0.1.3-py2.py3-none-any.whl", hash = "sha256:073bb0590007af276853009fac7e4bab1d523c3f03baf4cb4511ca38967c6039"}, @@ -4342,7 +5364,7 @@ description = "Wrapper package for OpenCV python bindings." optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "opencv_python_headless-4.13.0.92-cp37-abi3-macosx_13_0_arm64.whl", hash = "sha256:1a7d040ac656c11b8c38677cc8cccdc149f98535089dbe5b081e80a4e5903209"}, {file = "opencv_python_headless-4.13.0.92-cp37-abi3-macosx_14_0_x86_64.whl", hash = "sha256:3e0a6f0a37994ec6ce5f59e936be21d5d6384a4556f2d2da9c2f9c5dc948394c"}, @@ -4364,7 +5386,7 @@ description = "OpenTelemetry Python API" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"ray\"" +markers = "(python_version >= \"3.11\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\") and (python_version == \"3.11\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"client\") and (extra == \"client\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\")" files = [ {file = "opentelemetry_api-1.39.1-py3-none-any.whl", hash = "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950"}, {file = "opentelemetry_api-1.39.1.tar.gz", hash = "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c"}, @@ -4374,6 +5396,92 @@ files = [ importlib-metadata = ">=6.0,<8.8.0" typing-extensions = ">=4.5.0" +[[package]] +name = "opentelemetry-exporter-otlp" +version = "1.39.1" +description = "OpenTelemetry Collector Exporters" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"server\"" +files = [ + {file = "opentelemetry_exporter_otlp-1.39.1-py3-none-any.whl", hash = "sha256:68ae69775291f04f000eb4b698ff16ff685fdebe5cb52871bc4e87938a7b00fe"}, + {file = "opentelemetry_exporter_otlp-1.39.1.tar.gz", hash = "sha256:7cf7470e9fd0060c8a38a23e4f695ac686c06a48ad97f8d4867bc9b420180b9c"}, +] + +[package.dependencies] +opentelemetry-exporter-otlp-proto-grpc = "1.39.1" +opentelemetry-exporter-otlp-proto-http = "1.39.1" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.39.1" +description = "OpenTelemetry Protobuf encoding" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"server\"" +files = [ + {file = "opentelemetry_exporter_otlp_proto_common-1.39.1-py3-none-any.whl", hash = "sha256:08f8a5862d64cc3435105686d0216c1365dc5701f86844a8cd56597d0c764fde"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.39.1.tar.gz", hash = "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464"}, +] + +[package.dependencies] +opentelemetry-proto = "1.39.1" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-grpc" +version = "1.39.1" +description = "OpenTelemetry Collector Protobuf over gRPC Exporter" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"server\"" +files = [ + {file = "opentelemetry_exporter_otlp_proto_grpc-1.39.1-py3-none-any.whl", hash = "sha256:fa1c136a05c7e9b4c09f739469cbdb927ea20b34088ab1d959a849b5cc589c18"}, + {file = "opentelemetry_exporter_otlp_proto_grpc-1.39.1.tar.gz", hash = "sha256:772eb1c9287485d625e4dbe9c879898e5253fea111d9181140f51291b5fec3ad"}, +] + +[package.dependencies] +googleapis-common-protos = ">=1.57,<2.0" +grpcio = [ + {version = ">=1.63.2,<2.0.0", markers = "python_version < \"3.13\""}, + {version = ">=1.66.2,<2.0.0", markers = "python_version >= \"3.13\""}, +] +opentelemetry-api = ">=1.15,<2.0" +opentelemetry-exporter-otlp-proto-common = "1.39.1" +opentelemetry-proto = "1.39.1" +opentelemetry-sdk = ">=1.39.1,<1.40.0" +typing-extensions = ">=4.6.0" + +[package.extras] +gcp-auth = ["opentelemetry-exporter-credential-provider-gcp (>=0.59b0)"] + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.39.1" +description = "OpenTelemetry Collector Protobuf over HTTP Exporter" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"server\"" +files = [ + {file = "opentelemetry_exporter_otlp_proto_http-1.39.1-py3-none-any.whl", hash = "sha256:d9f5207183dd752a412c4cd564ca8875ececba13be6e9c6c370ffb752fd59985"}, + {file = "opentelemetry_exporter_otlp_proto_http-1.39.1.tar.gz", hash = "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb"}, +] + +[package.dependencies] +googleapis-common-protos = ">=1.52,<2.0" +opentelemetry-api = ">=1.15,<2.0" +opentelemetry-exporter-otlp-proto-common = "1.39.1" +opentelemetry-proto = "1.39.1" +opentelemetry-sdk = ">=1.39.1,<1.40.0" +requests = ">=2.7,<3.0" +typing-extensions = ">=4.5.0" + +[package.extras] +gcp-auth = ["opentelemetry-exporter-credential-provider-gcp (>=0.59b0)"] + [[package]] name = "opentelemetry-exporter-prometheus" version = "0.60b1" @@ -4381,7 +5489,7 @@ description = "Prometheus Metric Exporter for OpenTelemetry" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "opentelemetry_exporter_prometheus-0.60b1-py3-none-any.whl", hash = "sha256:49f59178de4f4590e3cef0b8b95cf6e071aae70e1f060566df5546fad773b8fd"}, {file = "opentelemetry_exporter_prometheus-0.60b1.tar.gz", hash = "sha256:a4011b46906323f71724649d301b4dc188aaa068852e814f4df38cc76eac616b"}, @@ -4392,6 +5500,42 @@ opentelemetry-api = ">=1.12,<2.0" opentelemetry-sdk = ">=1.39.1,<1.40.0" prometheus-client = ">=0.5.0,<1.0.0" +[[package]] +name = "opentelemetry-instrumentation" +version = "0.60b1" +description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"server\"" +files = [ + {file = "opentelemetry_instrumentation-0.60b1-py3-none-any.whl", hash = "sha256:04480db952b48fb1ed0073f822f0ee26012b7be7c3eac1a3793122737c78632d"}, + {file = "opentelemetry_instrumentation-0.60b1.tar.gz", hash = "sha256:57ddc7974c6eb35865af0426d1a17132b88b2ed8586897fee187fd5b8944bd6a"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.4,<2.0" +opentelemetry-semantic-conventions = "0.60b1" +packaging = ">=18.0" +wrapt = ">=1.0.0,<2.0.0" + +[[package]] +name = "opentelemetry-instrumentation-logging" +version = "0.60b1" +description = "OpenTelemetry Logging instrumentation" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"server\"" +files = [ + {file = "opentelemetry_instrumentation_logging-0.60b1-py3-none-any.whl", hash = "sha256:f2e18cbc7e1dd3628c80e30d243897fdc93c5b7e0c8ae60abd2b9b6a99f82343"}, + {file = "opentelemetry_instrumentation_logging-0.60b1.tar.gz", hash = "sha256:98f4b9c7aeb9314a30feee7c002c7ea9abea07c90df5f97fb058b850bc45b89a"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.12,<2.0" +opentelemetry-instrumentation = "0.60b1" + [[package]] name = "opentelemetry-proto" version = "1.39.1" @@ -4399,7 +5543,7 @@ description = "OpenTelemetry Python Proto" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" files = [ {file = "opentelemetry_proto-1.39.1-py3-none-any.whl", hash = "sha256:22cdc78efd3b3765d09e68bfbd010d4fc254c9818afd0b6b423387d9dee46007"}, {file = "opentelemetry_proto-1.39.1.tar.gz", hash = "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8"}, @@ -4415,7 +5559,7 @@ description = "OpenTelemetry Python SDK" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" files = [ {file = "opentelemetry_sdk-1.39.1-py3-none-any.whl", hash = "sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c"}, {file = "opentelemetry_sdk-1.39.1.tar.gz", hash = "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6"}, @@ -4433,7 +5577,7 @@ description = "OpenTelemetry Semantic Conventions" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" files = [ {file = "opentelemetry_semantic_conventions-0.60b1-py3-none-any.whl", hash = "sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb"}, {file = "opentelemetry_semantic_conventions-0.60b1.tar.gz", hash = "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953"}, @@ -4443,13 +5587,90 @@ files = [ opentelemetry-api = "1.39.1" typing-extensions = ">=4.5.0" +[[package]] +name = "orjson" +version = "3.12.0" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "(python_version >= \"3.11\" or extra == \"async-rl\") and (extra == \"async-rl\" or extra == \"client\")" +files = [ + {file = "orjson-3.12.0-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:747843254519dd43b93eee3153a19e5a509334320c4d2f823ec879232db5c796"}, + {file = "orjson-3.12.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:7c2ad193c8004254f34b499f3bd2c80f043d10754aff2b38f93da574f4883f98"}, + {file = "orjson-3.12.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:bc7a872f03522d90e0429e6c0c5cd23084f767bedcb4c58048eec19294613344"}, + {file = "orjson-3.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18a87929f31d94a77f7dc93cf527e91f39ce7fe7813d588a4de2507efd32a387"}, + {file = "orjson-3.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9683ee9ea0659da64f36574ef675b8a86330c34c19ea75db1fb93c3ff99e0ef"}, + {file = "orjson-3.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:103b5db66aa53c1f9e88c2524be4f383e831ba7dfd5f9f5af6336a177c622f11"}, + {file = "orjson-3.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd57d79aefa3f84eec851d6de7a366795b9345cfaf17f82b4820430a7a5fa241"}, + {file = "orjson-3.12.0-cp310-cp310-win32.whl", hash = "sha256:3dbce9b6b3074b31a5d5dd322a9c4e5b16f206091ece4194c2e36952847a105e"}, + {file = "orjson-3.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:3bb17a06f9bd15237b3216c044209fe92597379124018cfc196fbb846cde64df"}, + {file = "orjson-3.12.0-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a94f0f0c6fcbb2b5bd9734c57a489c7584a732bbdf04a39e8c83b861e9d03e92"}, + {file = "orjson-3.12.0-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:a696529ec96a90d9a5f9570207efe403c8b08f8e4aa2783ee3403511e2fdfa10"}, + {file = "orjson-3.12.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:e4ac5059baab4b3acbd99485de019ff8cda0fdf34b61fa74f7197a53db78bfe8"}, + {file = "orjson-3.12.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:8e29957429c35bbb5a185a119c523aa2428b7bbf1a293724c7b9375ed8f892a3"}, + {file = "orjson-3.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dce0166feb0a737ab84f598c9a338cbc0b764a036617aa686194f53c7eba0c3e"}, + {file = "orjson-3.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9caf3d09f47c3c70c4451ada20ef9bc4a4cdffa26f49862cf0a253b329aae2d5"}, + {file = "orjson-3.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b9dca132b1fda5565088e65a6b6e742285e0aeceb6fae549fa8863e16c7d3998"}, + {file = "orjson-3.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a791f793b287bbc135b8e87c34e35c8bfc693e2a8a620fab1ae682b925f9a32e"}, + {file = "orjson-3.12.0-cp311-cp311-win32.whl", hash = "sha256:31ed278a36304390adc3eec5d7f6fd593a7c3e99e5a06cd07866396c4b1b4710"}, + {file = "orjson-3.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb2539159dfe8d371914f354360fa50e4a577cc89222a3828b9650a5e5040252"}, + {file = "orjson-3.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:61318b6de893c7a9d9f3e5ecbadccbfc26a7eb417ccc7bbf0771de3b4d72f868"}, + {file = "orjson-3.12.0-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:aa3e43a6846e91d7bde3d5a9c66090fcd8744f569a9b6cffc5e1ca38f6a461c0"}, + {file = "orjson-3.12.0-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:11edb4660a6680abee9788a3a9072208a2c96538cc1322bd79542065229d8e54"}, + {file = "orjson-3.12.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:2d3a9da945a4d96ae758fdaaca56742e6b73b6fd554c5d8876f252a6dad70b83"}, + {file = "orjson-3.12.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:92ffc09e07233a6ab6d4e067f7841edcbcc134cb4812155cf171ea5255a421d7"}, + {file = "orjson-3.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf44e374aadde77b1f6109f1030be51433eb61984379852766b6f4e187db7b1e"}, + {file = "orjson-3.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1192a7021b6d071aaf909864f6e924d6a2675ca360485b972b8401749311750b"}, + {file = "orjson-3.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:53c0c474a9d9aff9aebfc0c88de1f28f843d940e6e3a80729abdf6a20274356f"}, + {file = "orjson-3.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:532ff8cd4bd59a327a953a7dcde922c7fc25b85e29721bb8633265430d3a3873"}, + {file = "orjson-3.12.0-cp312-cp312-win32.whl", hash = "sha256:a6cf4b18e7de173f209f2084ffbd736dd72389a396326ee80a7022168be232e5"}, + {file = "orjson-3.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:010811c1b69773450a01cef97727a67b223242f350b77d4ca000e59a9ef2155a"}, + {file = "orjson-3.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:ad29eece0c601737f2a60edc2752a84e7a0785df3efb62e3012834700a5afe0d"}, + {file = "orjson-3.12.0-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a36ec60f1796f9a3f13e3b98390295e17a1c7c10155b448d264098bf9ee5900"}, + {file = "orjson-3.12.0-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:ad0422b92d5195443a39f80c3bcf731cc2e00f153bd32063a47b73b057bd0f03"}, + {file = "orjson-3.12.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:5a0fdbc216388f653d3752ff310e710f59253bd4ed6a2bfb3f4f06b84714bbd8"}, + {file = "orjson-3.12.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2eb5c56e534127b2b8fa38d2363c8b1b8190367ee0d1d16c041517d880843b94"}, + {file = "orjson-3.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:784106539f4b9d4b930e0b4eb8d45168507dae001945e71b4675a367f1e5e806"}, + {file = "orjson-3.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c680706fc8396d95e7c4c1f9482563f552137aef91b57237a3ad5aaf64629df"}, + {file = "orjson-3.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:83445adc40cba26d6d621185a45128ce455b766af368cad2ab64b970603a7978"}, + {file = "orjson-3.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:644d005bc82f917337a95ce270c9f6f92f9834c2bed7b1477572f8db00784222"}, + {file = "orjson-3.12.0-cp313-cp313-win32.whl", hash = "sha256:d8e78d3d93705e3d27cc17cdb209e44d7a8ea203010cac6ce9c7ffc1ae1996f1"}, + {file = "orjson-3.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b85931be5b6763c31283805c9bdaae1ca03ad9f6f12a15f1cbf6745b907932c2"}, + {file = "orjson-3.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:6a31348d7dfa64cd9c78bd1f510ff44c48fe64d71094e6b90e364dba3b55949e"}, + {file = "orjson-3.12.0-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9e6fee342a48760e854d743e7a81534d8e2925a6f46e09f750cf56b50fd1de5d"}, + {file = "orjson-3.12.0-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:8c3bb86dd10f39b3fbf434b7d5dc7cac77d6fc8ac572ae30a10731ede2c4b647"}, + {file = "orjson-3.12.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:2bb3ce43203936072dd8b4917b01d3aecfc02329bfb42510cb7cfb24708adc9c"}, + {file = "orjson-3.12.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:6a2a79c89984dc719817d388c8709e0efc2a2795a934eaa746b4882eb6045adc"}, + {file = "orjson-3.12.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f06dd838d1e07d9b1de0932ec0485ec92c4d5f5d1ad4817a656268c3e88be1e1"}, + {file = "orjson-3.12.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6b11be792c3d2c6a4be2af4ebf97a68d0bf5f580aca6e86a418a354f6cc846a"}, + {file = "orjson-3.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:477ecaf6b9f88f873341b91fcc736119ca81b5e002a9f7f308ff5b4f2ce2a70e"}, + {file = "orjson-3.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f3c0683136acdc29afdf88a5bc2f7d3d0e34087788d1d63c0144b805a87a196f"}, + {file = "orjson-3.12.0-cp314-cp314-win32.whl", hash = "sha256:d39f3f5c3927e2dc0913fe5bbc1a2f6b1b9d1bba1de6358340d0ad0d0c00ca92"}, + {file = "orjson-3.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:0b1ac5bf6609b2716c7954011c5fef6254922df029f45d032ee4ebf5d363cbed"}, + {file = "orjson-3.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:50fae885cb073eac7556353ff3df93312b0d5137b0a5056b2bb63f97ed9a93c7"}, + {file = "orjson-3.12.0-cp315-cp315-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:01efac2074fffb4cb1ea3fab7861e9d0f2a26913854a972f5ac760525dbdaf6e"}, + {file = "orjson-3.12.0-cp315-cp315-macosx_15_0_arm64.whl", hash = "sha256:ed4ca42bd55955aa34deedcfdfd0e0c31abf51143aae158ae2bc3520b626e517"}, + {file = "orjson-3.12.0-cp315-cp315-manylinux_2_39_aarch64.whl", hash = "sha256:40f92192227505acca4e2533ce565f8e6b9535f7d0d09b0968452f18b7376b38"}, + {file = "orjson-3.12.0-cp315-cp315-manylinux_2_39_armv7l.whl", hash = "sha256:33efefcf5d88eaf400b47e2eba02f91f319bb9951be61ca500b7d536d3f2079d"}, + {file = "orjson-3.12.0-cp315-cp315-manylinux_2_39_i686.whl", hash = "sha256:8e386b0bc0ddd7cd2056f884b5a0af33592bd01ac66a7ca4b42a65a7e7774a13"}, + {file = "orjson-3.12.0-cp315-cp315-manylinux_2_39_x86_64.whl", hash = "sha256:58c58e1de0006ffb580368d6793c36c7b0b021db066479cf281bf5061e732328"}, + {file = "orjson-3.12.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:08231552159be266a7269555bd9f7c016aee7d9ad6dab06eb58796c5ccb7101c"}, + {file = "orjson-3.12.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:a15f9a891bce5f5cc5d210e3ad8614d4d1b489a56448c099d6d2a7168b2d954a"}, + {file = "orjson-3.12.0-cp315-cp315-win32.whl", hash = "sha256:03091c8a64db4be38746597ceea68f33c238e27acd9bfe99fb59420224ae7a55"}, + {file = "orjson-3.12.0-cp315-cp315-win_amd64.whl", hash = "sha256:2b7bcefb9f40fa242fa6b06377232c048e655747790829609168c01162f60578"}, + {file = "orjson-3.12.0-cp315-cp315-win_arm64.whl", hash = "sha256:859fc4196855890150bb08e649b30d2c93b249b3e3edd0d3bb2231abf8aa8adc"}, + {file = "orjson-3.12.0.tar.gz", hash = "sha256:d14203fb1aae2ad9b3d52f8a0e82aeb10197ef1c9bc61da7f358bd70b00123d5"}, +] + [[package]] name = "oss2" version = "2.13.1" description = "Aliyun OSS (Object Storage Service) SDK" -optional = false +optional = true python-versions = "*" groups = ["main"] +markers = "extra == \"eval\"" files = [ {file = "oss2-2.13.1.tar.gz", hash = "sha256:8548ea7d43326f6fd679bc8b79b3a2dfbfe9c6a60ed57e2410818fec57023dda"}, ] @@ -4469,7 +5690,7 @@ description = "Structured Text Generation in Rust" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "outlines_core-0.2.11-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:89d79d8454b321f60047541a896d410ca9db631d241960266c4fe839cf5cd1b1"}, {file = "outlines_core-0.2.11-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:44d581893f8644da02db7be11887229a40d26077cbdd22072ad1ed1db0ad0b2d"}, @@ -4517,6 +5738,19 @@ files = [ [package.extras] test = ["asv", "coverage[toml] (>=5.1)", "diff-cover", "maturin[patchelf]", "numba", "numpy", "pre-commit", "psutil", "pydantic", "pytest", "pytest-benchmark", "pytest-cov", "pytest-mock", "scipy", "torch"] +[[package]] +name = "overrides" +version = "7.7.0" +description = "A decorator to automatically detect mismatch when overriding a method." +optional = true +python-versions = ">=3.6" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, + {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, +] + [[package]] name = "packaging" version = "26.0" @@ -4529,6 +5763,103 @@ files = [ {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, ] +[[package]] +name = "pandas" +version = "2.3.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +groups = ["main"] +markers = "python_version == \"3.10\"" +files = [ + {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, + {file = "pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a"}, + {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1"}, + {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838"}, + {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250"}, + {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4"}, + {file = "pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523"}, + {file = "pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66"}, + {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791"}, + {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151"}, + {file = "pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53"}, + {file = "pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908"}, + {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98"}, + {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084"}, + {file = "pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b"}, + {file = "pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713"}, + {file = "pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8"}, + {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d"}, + {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac"}, + {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c"}, + {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493"}, + {file = "pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee"}, + {file = "pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5"}, + {file = "pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21"}, + {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78"}, + {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110"}, + {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86"}, + {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc"}, + {file = "pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0"}, + {file = "pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593"}, + {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c"}, + {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b"}, + {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6"}, + {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3"}, + {file = "pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5"}, + {file = "pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec"}, + {file = "pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7"}, + {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450"}, + {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5"}, + {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788"}, + {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87"}, + {file = "pandas-2.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2"}, + {file = "pandas-2.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8"}, + {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff"}, + {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29"}, + {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73"}, + {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9"}, + {file = "pandas-2.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa"}, + {file = "pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b"}, +] + +[package.dependencies] +numpy = {version = ">=1.22.4", markers = "python_version < \"3.11\""} +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + [[package]] name = "pandas" version = "3.0.1" @@ -4536,6 +5867,7 @@ description = "Powerful data structures for data analysis, time series, and stat optional = false python-versions = ">=3.11" groups = ["main"] +markers = "python_version >= \"3.11\"" files = [ {file = "pandas-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de09668c1bf3b925c07e5762291602f0d789eca1b3a781f99c1c78f6cac0e7ea"}, {file = "pandas-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24ba315ba3d6e5806063ac6eb717504e499ce30bd8c236d8693a5fd3f084c796"}, @@ -4625,7 +5957,7 @@ description = "Parse partial JSON generated by LLM" optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "partial_json_parser-0.2.1.1.post7-py3-none-any.whl", hash = "sha256:145119e5eabcf80cbb13844a6b50a85c68bf99d376f8ed771e2a3c3b03e653ae"}, {file = "partial_json_parser-0.2.1.1.post7.tar.gz", hash = "sha256:86590e1ba6bcb6739a2dfc17d2323f028cb5884f4c6ce23db376999132c9a922"}, @@ -4780,12 +6112,117 @@ description = "A small Python package for determining appropriate platform-speci optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" files = [ {file = "platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd"}, {file = "platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291"}, ] +[[package]] +name = "plotext" +version = "6.1.0" +description = "plotext plots directly on terminal" +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"client\"" +files = [ + {file = "plotext-6.1.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:4fec26b86ad32b3597de5861cfbf0023bb5ae02250f0ca940b12b069bccf43e6"}, + {file = "plotext-6.1.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:bfafad58a20da6c279e722481b5c3e67a9c8c54bde722d414c5ceffe71b7c652"}, + {file = "plotext-6.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c035440296be20e539ee70d4de07290d84bb0c9017bb3bc5867a8b3f9cead56"}, + {file = "plotext-6.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e59f54cedfb56129e2aec1f885869fe13903fdd4e6f18a10301e71a7d5b9851c"}, + {file = "plotext-6.1.0-py3-none-win_amd64.whl", hash = "sha256:60c85326da5454db482c9b1357c9ba385bae4a05c9dd498ff604e80458e03e3b"}, + {file = "plotext-6.1.0.tar.gz", hash = "sha256:6b729ce6376c5c1c2152fe85e0449dcc54879d0923b3c6c8d1670108245c6f84"}, +] + +[package.extras] +image = ["pillow (>=8.4)"] +video = ["ffpyplayer (>=4.3.5)", "pillow (>=8.4)", "yt-dlp (>=2024.1.1)"] + +[[package]] +name = "plotly" +version = "7.0.0" +description = "An open-source interactive data visualization library for Python" +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "plotly-7.0.0-py3-none-any.whl", hash = "sha256:78cbf7bd06d1b05bb3b8ec1b709864695229b55151b6f7530fbf55517ead6fdd"}, + {file = "plotly-7.0.0.tar.gz", hash = "sha256:08b21f1244a97e7a1a699833c4bb2678475aa108b3f1989886ed0b038ebfd849"}, +] + +[package.dependencies] +narwhals = ">=1.15.1" +packaging = "*" + +[package.extras] +dev = ["anywidget", "build", "colorcet", "fiona (<=1.9.6) ; python_version <= \"3.8\"", "geopandas", "inflect", "jupyter-builder", "jupyterlab", "kaleido (>=1.3.0)", "numpy (>=1.22)", "orjson", "pandas", "pdfrw", "pillow", "polars[timezone]", "pyarrow", "pytest", "pytz", "requests", "ruff (==0.11.12)", "scikit-image", "scipy", "statsmodels", "vaex ; python_version <= \"3.9\"", "xarray"] +dev-build = ["build", "jupyter-builder", "pytest", "requests", "ruff (==0.11.12)"] +dev-codegen = ["inflect", "pytest", "requests", "ruff (==0.11.12)"] +dev-core = ["pytest", "requests", "ruff (==0.11.12)"] +dev-optional = ["anywidget", "build", "colorcet", "fiona (<=1.9.6) ; python_version <= \"3.8\"", "geopandas", "inflect", "jupyter-builder", "jupyterlab", "kaleido (>=1.3.0)", "numpy (>=1.22)", "orjson", "pandas", "pdfrw", "pillow", "polars[timezone]", "pyarrow", "pytest", "pytz", "requests", "ruff (==0.11.12)", "scikit-image", "scipy", "statsmodels", "vaex ; python_version <= \"3.9\"", "xarray"] +dev-pandas1 = ["numpy (>=1,<2)", "pandas (>=1,<2)", "setuptools (<82)"] +dev-pandas2 = ["pandas (>=2,<3)"] +dev-pandas3 = ["pandas (>=3) ; python_version >= \"3.11\""] +express = ["numpy (>=1.22)"] +kaleido = ["kaleido (>=1.3.0)"] + +[[package]] +name = "pluggy" +version = "1.6.0" +description = "plugin and hook calling mechanisms for python" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"test\"" +files = [ + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] + +[[package]] +name = "portalocker" +version = "4.3.2" +description = "Cross-platform file locking, with Redis, PID-file and bounded-semaphore locks" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "portalocker-4.3.2-py3-none-any.whl", hash = "sha256:42f0362e7343af78b25eb095c0cde300e746a0ab6647a835cc30764918490c93"}, + {file = "portalocker-4.3.2.tar.gz", hash = "sha256:8de4a1330f55b3c9a1d50ab1b70a765f2f136d6399ae206411117ed98c3b8e2b"}, +] + +[package.extras] +docs = ["furo", "sphinx (>=7)"] +redis = ["redis (>=5.0)"] +tests = ["coverage-conditional-plugin (>=0.9)", "fakeredis (>=2.31.0)", "portalocker[redis]", "pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-rerunfailures (>=15.1)", "pytest-timeout (>=2.1.0)", "types-pywin32 (>=310.0.0.20250429)", "typing-extensions (>=4.4)"] +win32 = ["pywin32 (>=226) ; sys_platform == \"win32\""] + +[[package]] +name = "prettytable" +version = "3.18.0" +description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "prettytable-3.18.0-py3-none-any.whl", hash = "sha256:b3346e0e6f79180833aebaac088ae926340586cf6d7d991b9eb125b65f72313a"}, + {file = "prettytable-3.18.0.tar.gz", hash = "sha256:439217116152244369caf3d9f1caf2f9fe29b03bd79e88d2928c8e718c95d680"}, +] + +[package.dependencies] +wcwidth = ">=0.3.5" + +[package.extras] +tests = ["pytest (>=9)", "pytest-cov", "pytest-lazy-fixtures"] + [[package]] name = "prometheus-client" version = "0.24.1" @@ -4793,7 +6230,7 @@ description = "Python client for the Prometheus monitoring system." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055"}, {file = "prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9"}, @@ -4811,7 +6248,7 @@ description = "Instrument your FastAPI app with Prometheus metrics" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "prometheus_fastapi_instrumentator-7.1.0-py3-none-any.whl", hash = "sha256:978130f3c0bb7b8ebcc90d35516a6fe13e02d2eb358c8f83887cdef7020c31e9"}, {file = "prometheus_fastapi_instrumentator-7.1.0.tar.gz", hash = "sha256:be7cd61eeea4e5912aeccb4261c6631b3f227d8924542d79eaf5af3f439cbe5e"}, @@ -4960,7 +6397,7 @@ description = "Beautiful, Pythonic protocol buffers" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "proto_plus-1.27.1-py3-none-any.whl", hash = "sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc"}, {file = "proto_plus-1.27.1.tar.gz", hash = "sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147"}, @@ -4979,7 +6416,7 @@ description = "" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"ray\" or extra == \"vllm\" or extra == \"megatron\"" +markers = "(python_version >= \"3.11\" or extra == \"async-rl\" or extra == \"rl\" or extra == \"server\" or extra == \"megatron\") and (extra == \"async-rl\" or extra == \"rl\" or extra == \"server\" or extra == \"megatron\" or extra == \"client\")" files = [ {file = "protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b"}, {file = "protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c"}, @@ -5028,6 +6465,18 @@ files = [ dev = ["abi3audit", "black", "check-manifest", "colorama ; os_name == \"nt\"", "coverage", "packaging", "psleak", "pylint", "pyperf", "pypinfo", "pyreadline3 ; os_name == \"nt\"", "pytest", "pytest-cov", "pytest-instafail", "pytest-xdist", "pywin32 ; os_name == \"nt\" and implementation_name != \"pypy\"", "requests", "rstcheck", "ruff", "setuptools", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "validate-pyproject[all]", "virtualenv", "vulture", "wheel", "wheel ; os_name == \"nt\" and implementation_name != \"pypy\"", "wmi ; os_name == \"nt\" and implementation_name != \"pypy\""] test = ["psleak", "pytest", "pytest-instafail", "pytest-xdist", "pywin32 ; os_name == \"nt\" and implementation_name != \"pypy\"", "setuptools", "wheel ; os_name == \"nt\" and implementation_name != \"pypy\"", "wmi ; os_name == \"nt\" and implementation_name != \"pypy\""] +[[package]] +name = "pwinput" +version = "1.0.3" +description = "A cross-platform Python module that displays **** for password input. Works on Windows, unlike getpass. Formerly called stdiomask." +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "pwinput-1.0.3.tar.gz", hash = "sha256:ca1a8bd06e28872d751dbd4132d8637127c25b408ea3a349377314a5491426f3"}, +] + [[package]] name = "py-cpuinfo" version = "9.0.0" @@ -5035,12 +6484,25 @@ description = "Get CPU info with pure Python" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690"}, {file = "py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5"}, ] +[[package]] +name = "py-data-juicer" +version = "1.1.0" +description = "A One-Stop Data Processing System for Large Language Models." +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"data\"" +files = [ + {file = "py_data_juicer-1.1.0-py3-none-any.whl", hash = "sha256:27faf8ab1ee4a9597c09b4f9f18286a2292b1d7fb4ffe08b94ab5a1108489221"}, + {file = "py_data_juicer-1.1.0.tar.gz", hash = "sha256:675dca2b0fde9341c676351a29aec7cfa0a756608d64160a2745fe07e0fb4bf2"}, +] + [[package]] name = "py-spy" version = "0.4.1" @@ -5048,7 +6510,7 @@ description = "" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "py_spy-0.4.1-py2.py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:809094208c6256c8f4ccadd31e9a513fe2429253f48e20066879239ba12cd8cc"}, {file = "py_spy-0.4.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:1fb8bf71ab8df95a95cc387deed6552934c50feef2cf6456bc06692a5508fd0c"}, @@ -5130,7 +6592,7 @@ description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf"}, {file = "pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b"}, @@ -5143,7 +6605,7 @@ description = "A collection of ASN.1-based protocols modules" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a"}, {file = "pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6"}, @@ -5159,7 +6621,7 @@ description = "Fast Base64 encoding/decoding" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "pybase64-1.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f63aa7f29139b8a05ce5f97cdb7fad63d29071e5bdc8a638a343311fe996112a"}, {file = "pybase64-1.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f5943ec1ae87a8b4fe310905bb57205ea4330c75e2c628433a7d9dd52295b588"}, @@ -5385,7 +6847,7 @@ description = "ISO country, subdivision, language, currency and script definitio optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "pycountry-26.2.16-py3-none-any.whl", hash = "sha256:115c4baf7cceaa30f59a4694d79483c9167dbce7a9de4d3d571c5f3ea77c305a"}, {file = "pycountry-26.2.16.tar.gz", hash = "sha256:5b6027d453fcd6060112b951dd010f01f168b51b4bf8a1f1fc8c95c8d94a0801"}, @@ -5395,10 +6857,10 @@ files = [ name = "pycparser" version = "3.0" description = "C parser in Python" -optional = true +optional = false python-versions = ">=3.10" groups = ["main"] -markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\" and (extra == \"vllm\" or extra == \"ray\") or extra == \"vllm\" and implementation_name == \"pypy\"" +markers = "(platform_python_implementation != \"PyPy\" or implementation_name == \"pypy\") and (extra == \"rl\" or extra == \"async-rl\" or implementation_name == \"pypy\") and implementation_name != \"PyPy\"" files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, @@ -5408,9 +6870,10 @@ files = [ name = "pycryptodome" version = "3.23.0" description = "Cryptographic library for Python" -optional = false +optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["main"] +markers = "extra == \"eval\"" files = [ {file = "pycryptodome-3.23.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a176b79c49af27d7f6c12e4b178b0824626f40a7b9fed08f712291b6d54bf566"}, {file = "pycryptodome-3.23.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:573a0b3017e06f2cffd27d92ef22e46aa3be87a2d317a5abf7cc0e84e321bd75"}, @@ -5619,7 +7082,7 @@ description = "Extra Pydantic types." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "pydantic_extra_types-2.11.0-py3-none-any.whl", hash = "sha256:84b864d250a0fc62535b7ec591e36f2c5b4d1325fa0017eb8cda9aeb63b374a6"}, {file = "pydantic_extra_types-2.11.0.tar.gz", hash = "sha256:4e9991959d045b75feb775683437a97991d02c138e00b59176571db9ce634f0e"}, @@ -5646,7 +7109,7 @@ description = "Settings management using Pydantic" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237"}, {file = "pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025"}, @@ -5694,14 +7157,37 @@ doc = ["ablog (>=0.11.8)", "colorama", "graphviz", "ipykernel", "ipyleaflet", "i i18n = ["Babel", "jinja2"] test = ["pytest", "pytest-cov", "pytest-regressions", "sphinx[test]"] +[[package]] +name = "pyecharts" +version = "2.1.0" +description = "Python options, make charting easier" +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "pyecharts-2.1.0-py3-none-any.whl", hash = "sha256:5cba0aa06af3d9390a1fed18aa4e76acd7bdfb323cdf131874f46eaf7e78c6c7"}, + {file = "pyecharts-2.1.0.tar.gz", hash = "sha256:077f8205390aea705b8cc0be9d0c09916a2c060e9e5c8d9c9d11b7d8f4bdc1da"}, +] + +[package.dependencies] +jinja2 = "*" +prettytable = "*" +simplejson = "*" + +[package.extras] +images = ["PIL"] +phantomjs = ["snapshot-phantomjs"] +pyppeteer = ["snapshot-pyppeteer"] +selenium = ["snapshot-selenium"] + [[package]] name = "pygments" version = "2.19.2" description = "Pygments is a syntax highlighting package written in Python." -optional = true +optional = false python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"tinker\" or extra == \"docs\"" files = [ {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, @@ -5717,7 +7203,7 @@ description = "JSON Web Token implementation in Python" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "pyjwt-2.11.0-py3-none-any.whl", hash = "sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469"}, {file = "pyjwt-2.11.0.tar.gz", hash = "sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623"}, @@ -5732,6 +7218,237 @@ dev = ["coverage[toml] (==7.10.7)", "cryptography (>=3.4.0)", "pre-commit", "pyt docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] tests = ["coverage[toml] (==7.10.7)", "pytest (>=8.4.2,<9.0.0)"] +[[package]] +name = "pylatexenc" +version = "2.11" +description = "Simple LaTeX parser providing latex-to-unicode and unicode-to-latex conversion" +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "pylatexenc-2.11-py2.py3-none-any.whl", hash = "sha256:e78e7391d6c104f1ed150e21cfaa58016cdb50aa54406a2eecb793649ffdfdd0"}, + {file = "pylatexenc-2.11.tar.gz", hash = "sha256:305a072a99ce736246049c9da05841b9d718c0f7ea8888f5f596cf15cb621053"}, +] + +[[package]] +name = "pynvml" +version = "13.0.1" +description = "Python utilities for the NVIDIA Management Library" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"server\"" +files = [ + {file = "pynvml-13.0.1-py3-none-any.whl", hash = "sha256:e2b20e0a501eeec951e2455b7ab444759cf048e0e13a57b08049fa2775266aa8"}, + {file = "pynvml-13.0.1.tar.gz", hash = "sha256:1245991d9db786b4d2f277ce66869bd58f38ac654e38c9397d18f243c8f6e48f"}, +] + +[package.dependencies] +nvidia-ml-py = ">=12.0.0" + +[package.extras] +test = ["pytest (>=3.6)", "pytest-cov", "pytest-runner"] + +[[package]] +name = "pyqwest" +version = "0.10.0" +description = "A modern, high-performance HTTP client for Python and Rust." +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version >= \"3.11\" and extra == \"client\"" +files = [ + {file = "pyqwest-0.10.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:aa492d5777dd145a60795ed95d9d4707a3cd1091fdcdfc93a82ac7fdc43ebacd"}, + {file = "pyqwest-0.10.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:59f3f16628e518c674102e7b5fcff2101bba6abb4f6737ec5fade9b9278e6a53"}, + {file = "pyqwest-0.10.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6e7db305a8318b1f3218053e87501f8f245ca8bd63e948e0282d04bf0883470"}, + {file = "pyqwest-0.10.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5c757cfac5f53c8671dcb4850d5fc4c4339ea3e90636331c9318f8e3ddabc06"}, + {file = "pyqwest-0.10.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:234b3f71e3f314d997c203d8cf829b7117edd041153f9c277d0060ab90134148"}, + {file = "pyqwest-0.10.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5637256a0dac0ef57e0eaa02b032014965e4a4c995e1deca1b1b97e6d1765f78"}, + {file = "pyqwest-0.10.0-cp310-abi3-win_amd64.whl", hash = "sha256:7ea761937acf3a00d1a7e70e982949d18946e5471d1419266ab3a78bbfa19759"}, + {file = "pyqwest-0.10.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a21f1f15252a8303623b4f17b9c6de595ace11b3ade07f2adb6d07121e8191aa"}, + {file = "pyqwest-0.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:eb472c6e5d6833ebfec79db310e426eb17b01ac64c0e2c251bd9192c0d2ee0c5"}, + {file = "pyqwest-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83578e24cccd5e0dc04d60a0af7bfb43325b5f22d03ff74ff79ed0ecf553b50d"}, + {file = "pyqwest-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bb511c434f79c641efb5573e5795e56dc972252f4b96e52a9636d4ece5231a4"}, + {file = "pyqwest-0.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1aaccd8a9db9430b2aedb5bad8ead80742cbc056b85c229516c70dc80539f906"}, + {file = "pyqwest-0.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:73d9eb438ab4a957a1ce0619d3af8c1c1126bfb9181033b123d792fcf4224531"}, + {file = "pyqwest-0.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:317a74d633abe3bc5bccabf479e069c515dab9e6a755274b0ccb1d8a5bbfede3"}, + {file = "pyqwest-0.10.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3978e794b9cfd8eaa500fb5d7aee63bc6172c605efa0abc1f62d85485bc049e1"}, + {file = "pyqwest-0.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:715991fd4f04862cd7a9d7452daabcdbd74dff4dff55eb20c22d60382dc2a4ed"}, + {file = "pyqwest-0.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c04798bed79c1dfa0e5b0e30fb137124311083490d44d6dfbe068d3dd254349e"}, + {file = "pyqwest-0.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35b472877e73dd63fed089c2bc8fa198407f005c8c19e0a93f025ebefde01a81"}, + {file = "pyqwest-0.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:564ec360b7848b35e009038ffbca00466305a9708ab21829477f64aa8cad4c64"}, + {file = "pyqwest-0.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b5c80e88a5967c1cadb3237c450f91a84a3683f8838c8dca96f09fee3612e762"}, + {file = "pyqwest-0.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc3d80b402fb59dbe015e25993ac8147456fb231a4c949f92a89f31315ad50f9"}, + {file = "pyqwest-0.10.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:23a28beb55fa6d975949bffae4adfb69378f3229bb5cbd71231e95bf66f5b26c"}, + {file = "pyqwest-0.10.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e4415ae40b8eedb1713dab14d7f9fecc3f79d26f3206c561087b88b99d5ce24b"}, + {file = "pyqwest-0.10.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14b875d2273212d7fa8e4b755d8d736ffd226b1c707a9c0017dfdc8393a96eca"}, + {file = "pyqwest-0.10.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5071491e416ea54e3b95bf9ffbed0bd065b093cb96e10a75c3d8f2cbe3c9823"}, + {file = "pyqwest-0.10.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b68b5e68d513a4c63a072f8f40e38015160cf90bfbf7e8ef7c3935ca87e9e022"}, + {file = "pyqwest-0.10.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c48910d27820b9c46fcd001b0fe514a3cf47d4784f59512dcdb8c91c395f82e4"}, + {file = "pyqwest-0.10.0-cp314-cp314-win_amd64.whl", hash = "sha256:d03ba2cd17948b623a6210981d342eb122546d8a8e910ec77511aff4b1acdd00"}, + {file = "pyqwest-0.10.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:07a0eb595f4096232c2d22549b6e4612c1ecada7934e46462c2c37ce14a89cfb"}, + {file = "pyqwest-0.10.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:26401baf7dafc71c8d12d2e8389519d141e6f7c14094d0dd4cf9ec1d3b5555bd"}, + {file = "pyqwest-0.10.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5e3c436e041d8873ce5bb0fdcf9f9e86f5604e8f0ef9e03149efebd8cb474f6"}, + {file = "pyqwest-0.10.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09364115761579eabfc79d1e954cdb3ded508dac1903fac7285d4c6f058c683f"}, + {file = "pyqwest-0.10.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:559674a98a8b1217e1830ecd41c9905bf2b60983c6b8017063dfac199f00727c"}, + {file = "pyqwest-0.10.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f399a696392fff3db3eef0a18ef65b8a3b8396d129193487d966b8eb11006376"}, + {file = "pyqwest-0.10.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0f9163d6dd991bf1bf27308ba38ba021af660b15fffa47ebca98e41cf6f00309"}, + {file = "pyqwest-0.10.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cfcc7ba0229baa17831582befb046ace167b368140dae022d0b89b8d586ba12c"}, + {file = "pyqwest-0.10.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:eff9ccf427604d34c635954def07b6113d4754f968073eef2df40bdb80b05bf5"}, + {file = "pyqwest-0.10.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78662158093f9d5c742368f4dd9956aa595f44c6ac0860777c98853ddd5e1610"}, + {file = "pyqwest-0.10.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0879a3f0b37876372aa328b9fee956165db174c1ab72464146fe515f49399ddb"}, + {file = "pyqwest-0.10.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:850b8de6ade09a60bdb2f969871a177c2c304b594b2034ba3f5962c7bea75551"}, + {file = "pyqwest-0.10.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:399802647ea646c6ac9b5460e541b7c209b7a13563c667b2690ded2060185f2e"}, + {file = "pyqwest-0.10.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c26f3de1feb5d066d7a66802a47407a93ba043696064ad80beda4a0a4bf10056"}, + {file = "pyqwest-0.10.0.tar.gz", hash = "sha256:6c1a693be17d57d2c2eca4085e32c2809c53090c16719a907c90ebcf1f40dc01"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.39.1" + +[[package]] +name = "pyroaring" +version = "1.0.3" +description = "Library for handling efficiently sorted integer sets." +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "pyroaring-1.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c10e4cfbe203a578c78808406af491e3615d5e46cf69a7709050243346cd68bc"}, + {file = "pyroaring-1.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cc329c62e504f2531c4008240f31736bcd2dee4339071f1eac0648068e6d17fa"}, + {file = "pyroaring-1.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c7fb6ddf6ef31148f0939bc5c26b681d63df301ee1e372525012dd7bfe4a30a"}, + {file = "pyroaring-1.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd18446832ea04a7d33bd6b78270b0be14eabcda5937af3428d6cb3d2bf98e54"}, + {file = "pyroaring-1.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f0cbc766df2a24e28f23d69b66bbec64e691799219fd82c2f2236f03fc88e2e"}, + {file = "pyroaring-1.0.3-cp310-cp310-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:96a51e96f8f473381615f0f852f7238ad0a47f28e4a35e9f082468c5cfe4e9c3"}, + {file = "pyroaring-1.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:654af38b1f1c9bdc27b4f6d331fc5d91599df96e72a6df1886f4d95eea60ab29"}, + {file = "pyroaring-1.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6721036afa31c07bdcbb4fcafa166660cf9c2eac695dcd495f8778549fa55899"}, + {file = "pyroaring-1.0.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:0caa10f20329d09233fac6550b2adce4d9f173f748a9a9a5ea3b7033827dfe2d"}, + {file = "pyroaring-1.0.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f109be8af937e85c52cb920d3fd120db52b172f59460852d2e3d2e3d13a4f52a"}, + {file = "pyroaring-1.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ddc80bfcd313c7c524a2742d263e73cae088b6a611b77dcc46fa90c306f6dace"}, + {file = "pyroaring-1.0.3-cp310-cp310-win32.whl", hash = "sha256:5a183f5ec069757fe5b60e37f7c6fa8a53178eacf0d76601b739e2890edee036"}, + {file = "pyroaring-1.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:051bd9a66ce855a1143faa2b879ea6c6ca2905209e172ce9eedf79834897c730"}, + {file = "pyroaring-1.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:3043ff5c85375310ca3cd3e01944e03026e0ec07885e52dfabcfcd9dc303867f"}, + {file = "pyroaring-1.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:755cdac1f9a1b7b5c621e570d4f6dbcf3b8e4a1e35a66f976104ecb35dce4ed2"}, + {file = "pyroaring-1.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ebab073db620f26f0ba11e13fa2f35e3b1298209fba47b6bc8cb6f0e2c9627f9"}, + {file = "pyroaring-1.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:684fb8dffe19bdb7f91897c65eac6eee23b1e46043c47eb24288f28a1170fe04"}, + {file = "pyroaring-1.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:678d31fc24e82945a1bfb14816c77823983382ffea76985d494782aa2f058427"}, + {file = "pyroaring-1.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d815f624e0285db3669f673d1725cb754b120ec70d0032d7c7166103a96c96d"}, + {file = "pyroaring-1.0.3-cp311-cp311-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:57fd5b80dacb8e888402b6b7508a734c6a527063e4e24e882ff2e0fd90721ada"}, + {file = "pyroaring-1.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab26a7a45a0bb46c00394d1a60a9f2d57c220f84586e30d59b39784b0f94aee6"}, + {file = "pyroaring-1.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9232f3f606315d59049c128154100fd05008d5c5c211e48b21848cd41ee64d26"}, + {file = "pyroaring-1.0.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f34b44b3ec3df97b978799f2901fefb2a48d367496fd1cde3cc5fe8b3bc13510"}, + {file = "pyroaring-1.0.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:25a83ec6bac3106568bd3fdd316f0fee52aa0be8c72da565ad02b10ae7905924"}, + {file = "pyroaring-1.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c17d4ec53b5b6b333d9a9515051213a691293ada785dc8c025d3641482597ed3"}, + {file = "pyroaring-1.0.3-cp311-cp311-win32.whl", hash = "sha256:d54024459ace600f1d1ffbc6dc3c60eb47cca3b678701f06148f59e10f6f8d7b"}, + {file = "pyroaring-1.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:c28750148ef579a7447a8cb60b39e5943e03f8c29bce8f2788728f6f23d1887a"}, + {file = "pyroaring-1.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:535d8deccbd8db2c6bf38629243e9646756905574a742b2a72ff51d6461d616c"}, + {file = "pyroaring-1.0.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:add3e4c78eb590a76526ecce8d1566eecdd5822e351c36b3697997f4a80ed808"}, + {file = "pyroaring-1.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ebaffe846cf4ba4f00ce6b8a9f39613f24e2d09447e77be4fa6e898bc36451b6"}, + {file = "pyroaring-1.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9459f27498f97d08031a34a5ead230b77eb0ab3cc3d85b7f54faa2fd548acd6"}, + {file = "pyroaring-1.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2b2eb8bd1c35c772994889be9f7dda09477475d7aa1e2af9ab4ef18619326f6"}, + {file = "pyroaring-1.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d31f4c1c906f1af14ce61a3959d04a14a64c594f8a768399146a45bbd341f21f"}, + {file = "pyroaring-1.0.3-cp312-cp312-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53be988fc86698d56c11049bfe5113a2f6990adb1fa2782b29636509808b6aa7"}, + {file = "pyroaring-1.0.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7df84d223424523b19a23781f4246cc247fd6d821e1bc0853c2f25669136f7d0"}, + {file = "pyroaring-1.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:34a781f1f9766897f63ef18be129827340ae37764015b83fdcff1efb9e29136d"}, + {file = "pyroaring-1.0.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1f414343b4ed0756734328cdf2a91022fc54503769e3f8d79bd0b672ea815a16"}, + {file = "pyroaring-1.0.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d16ae185c72dc64f76335dbe53e53a892e78115adc92194957d1b7ef74d230b9"}, + {file = "pyroaring-1.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f888447bf22dde7759108bfe6dfbeb6bbb61b14948de9c4cb6843c4dd57e2215"}, + {file = "pyroaring-1.0.3-cp312-cp312-win32.whl", hash = "sha256:fbbdc44c51a0a3efd7be3dbe04466278ce098fcd101aa1905849319042159770"}, + {file = "pyroaring-1.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:3b217c4b3ad953b4c759a0d2f9bd95316f0c345b9f7adb49e6ded7a1f5106bd4"}, + {file = "pyroaring-1.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:e6bcf838564c21bab8fe6c2748b4990d4cd90612d8c470c04889def7bb5114ea"}, + {file = "pyroaring-1.0.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:20bc947054b197d1baa76cd05d70b8e04f95b82e698266e2f8f2f4b36d764477"}, + {file = "pyroaring-1.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ba5909b4c66bb85cab345e2f3a87e5ce671509c94b8c9823d8db64e107cbe854"}, + {file = "pyroaring-1.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b744746ba5da27fad760067f12633f5d384db6a1e65648d00244ceacbbd87731"}, + {file = "pyroaring-1.0.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b16c2a2791a5a09c4b59c0e1069ac1c877d0df25cae3155579c7eac8844676e"}, + {file = "pyroaring-1.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7f68dfcf8d01177267f4bc06c4960fe8e39577470d1b52c9af8b61a72ca8767"}, + {file = "pyroaring-1.0.3-cp313-cp313-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:dba4e4700030182a981a3c887aa73887697145fc9ffb192f908aa59b718fbbdd"}, + {file = "pyroaring-1.0.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e26dd1dc1edba02288902914bdb559e53e346e9155defa43c31fcab831b55342"}, + {file = "pyroaring-1.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6eb98d2cacfc6d51c6a69893f04075e07b3df761eac71ba162c43b9b4c4452ad"}, + {file = "pyroaring-1.0.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a967e9eddb9485cbdd95d6371e3dada67880844d836c0283d3b11efe9225d1b7"}, + {file = "pyroaring-1.0.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b12ef7f992ba7be865f91c7c098fd8ac6c413563aaa14d5b1e2bcb8cb43a4614"}, + {file = "pyroaring-1.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:82ca5be174b85c40be7b00bc6bf39b2931a1b4a465f3af17ec6b9c48e9aa6fe0"}, + {file = "pyroaring-1.0.3-cp313-cp313-win32.whl", hash = "sha256:f758c681e63ffe74b20423695e71f0410920f41b075cee679ffb5bc2bf38440b"}, + {file = "pyroaring-1.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:428c3bb384fe4c483feb5cf7aa3aef1621fb0a5c4f3d391da67b2c4a43f08a10"}, + {file = "pyroaring-1.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:9c0c856e8aa5606e8aed5f30201286e404fdc9093f81fefe82d2e79e67472bb2"}, + {file = "pyroaring-1.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6321a95b5b2ba69aa32e920dd1aa7f8fc4fac55b75981978aa4f2378724dee27"}, + {file = "pyroaring-1.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:054eb6ef04ff9d2ed3ddd18ae21e5e51e02d0f8cdd7e5cb948648f77ddb04ea2"}, + {file = "pyroaring-1.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4d064aea3827e63eb60294ae3e6623e29613f5c8844869646d06f3735a425dd9"}, + {file = "pyroaring-1.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c84d5b17ef628c3956d9a79c2f78c5bea7dda6f7aeb01f34671034d2650b9efb"}, + {file = "pyroaring-1.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8038f7dd25eb83c277b8e0ea14c5e61f085cc76bd0c6b9f6679f1770e33541ec"}, + {file = "pyroaring-1.0.3-cp38-cp38-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:defc508ef7acaf58d07e603c55feda6742c4034f5262cfd616f92cc3adbc2815"}, + {file = "pyroaring-1.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd0831326971b0ffa08ccce79abe7c2450d5d9254804d855e23a8ba31f70351a"}, + {file = "pyroaring-1.0.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:03e063329481396cbb70f1ce8b8ca0f01d74a45ee9d908b6645b0282b23832b0"}, + {file = "pyroaring-1.0.3-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:7a1b1c82d2da0bedc7c22d4047bd62544ef0e25c6be86ccf4b9d1ccc38876ee8"}, + {file = "pyroaring-1.0.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:dd7f9e5b7366b8f9bafca2a0fcf83fa534a00cc12d4ca01e301d8662bcdb805c"}, + {file = "pyroaring-1.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a5a1db84e0952805223a7bf77eae58384b700a6b9affc53fb9772dddf868c712"}, + {file = "pyroaring-1.0.3-cp38-cp38-win32.whl", hash = "sha256:54cb0c2bddd330e22099773c4681aca90847265afe56a9201a92c1a758494261"}, + {file = "pyroaring-1.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:47d985293f861df1f2b03b41cef4fd3249c1c9608081750bcf3153051c2312d0"}, + {file = "pyroaring-1.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d46eb5db78b673d8d8ca83651a1cce1e15eec5a922f2951b1f61014463b72af5"}, + {file = "pyroaring-1.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ce202452de2b58bffa3eb02e27c681eefcfb54e27f8ef85b5c93ebaada50f3f3"}, + {file = "pyroaring-1.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:531b6ae56989b61742dde1b64fedc5537acc046cf04a333548322366c1bf3922"}, + {file = "pyroaring-1.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3035db9459bd8635a0145b4a9e3102869d621cb0b3648051115f06d31ffd1976"}, + {file = "pyroaring-1.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c8fb6b0ad0e8db1b9559b2da180b103b48adddf0e4f24404269e2a3b5db268d"}, + {file = "pyroaring-1.0.3-cp39-cp39-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8d5df95d9511bc83048da9348c7ab1c20f97ff4d95faf27ee1fdf2e8a96e200e"}, + {file = "pyroaring-1.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65d2d81e5aed7698fab23058db70fb2b65fad221090be037a0af498569109915"}, + {file = "pyroaring-1.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e195636034a0b62ec0e5325ed2f610f39cc8955ace3f47a5bc7f484159f02341"}, + {file = "pyroaring-1.0.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:bb7f2561e3ec26c3c869458431cbcba6b83f7e925b024460c136dbb5fadf3b31"}, + {file = "pyroaring-1.0.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:8e996939de01f448eb9448d91b47ab60bff0555c2a80d5c12a8405814072cd35"}, + {file = "pyroaring-1.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c656d62d0cf96ede0edc4e7d392889238777bdf88b32afd5d51c3cab016c29a0"}, + {file = "pyroaring-1.0.3-cp39-cp39-win32.whl", hash = "sha256:a7a7d14822c64841ae64e98309697e1631ebadba55ded33daa7cd16d1b487d11"}, + {file = "pyroaring-1.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:a86b88adbe0531b75f94f87279a6d4ee68e63335e29bbdab4400a05704fc2587"}, + {file = "pyroaring-1.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:1ed2e9c7af46052466b5fa0392fe540331474718d97b9756cefa23233bfdb3ea"}, + {file = "pyroaring-1.0.3.tar.gz", hash = "sha256:cd7392d1c010c9e41c11c62cd0610c8852e7e9698b1f7f6c2fcdefe50e7ef6da"}, +] + +[[package]] +name = "pytest" +version = "9.1.1" +description = "pytest: simple powerful testing with Python" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"test\"" +files = [ + {file = "pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c"}, + {file = "pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313"}, +] + +[package.dependencies] +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1.0.1" +packaging = ">=22" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-asyncio" +version = "1.4.0" +description = "Pytest support for asyncio" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"test\"" +files = [ + {file = "pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1"}, + {file = "pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42"}, +] + +[package.dependencies] +backports-asyncio-runner = {version = ">=1.1,<2", markers = "python_version < \"3.11\""} +pytest = ">=8.4,<10" +typing-extensions = {version = ">=4.12", markers = "python_version < \"3.13\""} + +[package.extras] +docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)", "sphinx-tabs (>=3.5)"] +testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -5754,7 +7471,7 @@ description = "Python interpreter discovery" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "python_discovery-1.1.0-py3-none-any.whl", hash = "sha256:a162893b8809727f54594a99ad2179d2ede4bf953e12d4c7abc3cc9cdbd1437b"}, {file = "python_discovery-1.1.0.tar.gz", hash = "sha256:447941ba1aed8cc2ab7ee3cb91be5fc137c5bdbb05b7e6ea62fbdcb66e50b268"}, @@ -5775,7 +7492,7 @@ description = "Read key-value pairs from a .env file and set them as environment optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a"}, {file = "python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3"}, @@ -5791,7 +7508,7 @@ description = "JSON Log Formatter for the Python Logging Package" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2"}, {file = "python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f"}, @@ -5807,12 +7524,38 @@ description = "A streaming multipart parser for Python" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155"}, {file = "python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58"}, ] +[[package]] +name = "pytz" +version = "2026.3.post1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +groups = ["main"] +markers = "python_version == \"3.10\"" +files = [ + {file = "pytz-2026.3.post1-py2.py3-none-any.whl", hash = "sha256:dd95840dd199baea12d9cc096a1d452caa6596a1c1e4b5f3dbd1541855d5e815"}, + {file = "pytz-2026.3.post1.tar.gz", hash = "sha256:2211d3fcf9a797d3405cac96ac7f61d80e6a644f72a3309607282fe8a2010c5d"}, +] + +[[package]] +name = "pyvers" +version = "0.2.3" +description = "A Python library for managing multiple versions of dependencies" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "pyvers-0.2.3-py3-none-any.whl", hash = "sha256:6f5b5612f2f4bd08caa49baa70fc5f875fc7da701a5385c13e244eea6b8114dd"}, + {file = "pyvers-0.2.3.tar.gz", hash = "sha256:c4b81c3a033963245e124cdecb052783c9c4cea3bb08c051833af1c44faa6283"}, +] + [[package]] name = "pywin32" version = "311" @@ -5820,7 +7563,7 @@ description = "Python for Window Extensions" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"vllm\" and sys_platform == \"win32\"" +markers = "sys_platform == \"win32\" and (extra == \"rl\" or extra == \"async-rl\")" files = [ {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, @@ -5931,10 +7674,9 @@ files = [ name = "pyzmq" version = "27.1.0" description = "Python bindings for 0MQ" -optional = true +optional = false python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" files = [ {file = "pyzmq-27.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:508e23ec9bc44c0005c4946ea013d9317ae00ac67778bd47519fdf5a0e930ff4"}, {file = "pyzmq-27.1.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:507b6f430bdcf0ee48c0d30e734ea89ce5567fd7b8a0f0044a369c176aa44556"}, @@ -6040,7 +7782,7 @@ description = "Ray provides a simple, universal API for building distributed app optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "ray-2.54.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:a22937f09ee74a43171df338d84b45ef882c1c05748947ca9d5343a44d4b9379"}, {file = "ray-2.54.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:1e63e491155695d527513ffe9d33a6aeb3f3cdccb6309adadfd6f8dd7c0300f7"}, @@ -6060,34 +7802,71 @@ files = [ ] [package.dependencies] -aiohttp = {version = ">=3.13.3", optional = true, markers = "extra == \"serve\""} -aiohttp_cors = {version = "*", optional = true, markers = "extra == \"serve\""} +aiohttp = [ + {version = ">=3.13.3", optional = true, markers = "extra == \"serve\""}, + {version = ">=3.13.3", optional = true, markers = "extra == \"default\""}, +] +aiohttp_cors = [ + {version = "*", optional = true, markers = "extra == \"serve\""}, + {version = "*", optional = true, markers = "extra == \"default\""}, +] click = ">=7.0" -colorful = {version = "*", optional = true, markers = "extra == \"serve\""} +colorful = [ + {version = "*", optional = true, markers = "extra == \"serve\""}, + {version = "*", optional = true, markers = "extra == \"default\""}, +] cupy-cuda12x = {version = "*", optional = true, markers = "sys_platform != \"darwin\" and extra == \"cgraph\""} fastapi = {version = "*", optional = true, markers = "extra == \"serve\""} filelock = "*" -grpcio = {version = ">=1.42.0", optional = true, markers = "extra == \"serve\""} +grpcio = [ + {version = ">=1.42.0", optional = true, markers = "extra == \"serve\""}, + {version = ">=1.42.0", optional = true, markers = "extra == \"default\""}, +] jsonschema = "*" msgpack = ">=1.0.0,<2.0.0" -opencensus = {version = "*", optional = true, markers = "extra == \"serve\""} -opentelemetry-exporter-prometheus = {version = "*", optional = true, markers = "extra == \"serve\""} -opentelemetry-proto = {version = "*", optional = true, markers = "extra == \"serve\""} -opentelemetry-sdk = {version = ">=1.30.0", optional = true, markers = "extra == \"serve\""} +opencensus = [ + {version = "*", optional = true, markers = "extra == \"serve\""}, + {version = "*", optional = true, markers = "extra == \"default\""}, +] +opentelemetry-exporter-prometheus = [ + {version = "*", optional = true, markers = "extra == \"serve\""}, + {version = "*", optional = true, markers = "extra == \"default\""}, +] +opentelemetry-proto = [ + {version = "*", optional = true, markers = "extra == \"serve\""}, + {version = "*", optional = true, markers = "extra == \"default\""}, +] +opentelemetry-sdk = [ + {version = ">=1.30.0", optional = true, markers = "extra == \"serve\""}, + {version = ">=1.30.0", optional = true, markers = "extra == \"default\""}, +] packaging = ">=24.2" -prometheus_client = {version = ">=0.7.1", optional = true, markers = "extra == \"serve\""} +prometheus_client = [ + {version = ">=0.7.1", optional = true, markers = "extra == \"serve\""}, + {version = ">=0.7.1", optional = true, markers = "extra == \"default\""}, +] protobuf = ">=3.20.3" py-spy = [ {version = ">=0.2.0", optional = true, markers = "python_version < \"3.12\" and extra == \"serve\""}, + {version = ">=0.2.0", optional = true, markers = "python_version < \"3.12\" and extra == \"default\""}, {version = ">=0.4.0", optional = true, markers = "python_version >= \"3.12\" and extra == \"serve\""}, ] -pydantic = {version = "<2.0.dev0 || >=2.12.dev0,<3", optional = true, markers = "extra == \"serve\""} +pydantic = [ + {version = "<2.0.dev0 || >=2.12.dev0,<3", optional = true, markers = "extra == \"serve\""}, + {version = "<2.0.dev0 || >=2.12.dev0,<3", optional = true, markers = "extra == \"default\""}, +] pyyaml = "*" requests = "*" -smart_open = {version = "*", optional = true, markers = "extra == \"serve\""} +smart_open = [ + {version = "*", optional = true, markers = "extra == \"serve\""}, + {version = "*", optional = true, markers = "extra == \"default\""}, +] starlette = {version = "*", optional = true, markers = "extra == \"serve\""} uvicorn = {version = "*", extras = ["standard"], optional = true, markers = "extra == \"serve\""} -virtualenv = {version = ">=20.0.24,<20.21.1 || >20.21.1", optional = true, markers = "extra == \"serve\""} +virtualenv = [ + {version = ">=20.0.24,<20.21.1 || >20.21.1", optional = true, markers = "extra == \"serve\""}, + {version = ">=20.0.24,<20.21.1 || >20.21.1", optional = true, markers = "extra == \"default\""}, +] watchfiles = {version = "*", optional = true, markers = "extra == \"serve\""} [package.extras] @@ -6127,6 +7906,30 @@ commonmark = ">=0.8.1" docutils = ">=0.11" sphinx = ">=1.3.1" +[[package]] +name = "redis" +version = "8.1.0" +description = "Python client for Redis database and key-value store" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"server\"" +files = [ + {file = "redis-8.1.0-py3-none-any.whl", hash = "sha256:a4fe1aac3d3b3cc791d4b3d5931c5a956045dc951ee74d1c913ee3ac4d2ee9fb"}, + {file = "redis-8.1.0.tar.gz", hash = "sha256:6e1a19beef9225c83efd689c7e6b7da2d5215b1f42cd13b7fc3714d0a09c7b25"}, +] + +[package.dependencies] +async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} + +[package.extras] +circuit-breaker = ["pybreaker (>=1.4.0)"] +hiredis = ["hiredis (>=3.2.0)"] +jwt = ["pyjwt (>=2.13.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (>=20.0.1)", "requests (>=2.31.0)"] +otel = ["opentelemetry-api (>=1.39.1)", "opentelemetry-exporter-otlp-proto-http (>=1.39.1)", "opentelemetry-sdk (>=1.39.1)"] +xxhash = ["xxhash (>=3.6.0,<3.7.0)"] + [[package]] name = "referencing" version = "0.37.0" @@ -6134,7 +7937,7 @@ description = "JSON Referencing + Python" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, @@ -6295,10 +8098,9 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "rich" version = "14.3.3" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = true +optional = false python-versions = ">=3.8.0" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"tinker\"" files = [ {file = "rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d"}, {file = "rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b"}, @@ -6318,7 +8120,7 @@ description = "Rich toolkit for building command-line applications" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "rich_toolkit-0.19.7-py3-none-any.whl", hash = "sha256:0288e9203728c47c5a4eb60fd2f0692d9df7455a65901ab6f898437a2ba5989d"}, {file = "rich_toolkit-0.19.7.tar.gz", hash = "sha256:133c0915872da91d4c25d85342d5ec1dfacc69b63448af1a08a0d4b4f23ef46e"}, @@ -6336,7 +8138,7 @@ description = "Python Bindings for the ignore crate" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "rignore-0.7.6-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f3c74a7e5ee77aea669c95fdb3933f2a6c7549893700082e759128a29cf67e45"}, {file = "rignore-0.7.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7202404958f5fe3474bac91f65350f0b1dde1a5e05089f2946549b7e91e79ec"}, @@ -6494,6 +8296,40 @@ files = [ {file = "rignore-0.7.6.tar.gz", hash = "sha256:00d3546cd793c30cb17921ce674d2c8f3a4b00501cb0e3dd0e82217dbeba2671"}, ] +[[package]] +name = "rouge-chinese" +version = "1.0.3" +description = "Python ROUGE Score Implementation for Chinese Language Task (official rouge score)" +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "rouge_chinese-1.0.3-py3-none-any.whl", hash = "sha256:afda22cb64f9a0f1d7a19e88d7cd9acfd2c1f5d45bf463ade7ecadf87f30624d"}, + {file = "rouge_chinese-1.0.3.tar.gz", hash = "sha256:4074de21b01a83ca6032fe6d6354c5f618a305da60c994294133be2abf030f4a"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "rouge-score" +version = "0.1.2" +description = "Pure python implementation of ROUGE-1.5.5." +optional = true +python-versions = ">=3.7" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "rouge_score-0.1.2.tar.gz", hash = "sha256:c7d4da2683e68c9abf0135ef915d63a46643666f848e558a1b9f7ead17ff0f04"}, +] + +[package.dependencies] +absl-py = "*" +nltk = "*" +numpy = "*" +six = ">=1.14.0" + [[package]] name = "rpds-py" version = "0.30.0" @@ -6501,7 +8337,7 @@ description = "Python bindings to Rust's persistent data structures (rpds)" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, {file = "rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00"}, @@ -6627,7 +8463,7 @@ description = "Pure-Python RSA implementation" optional = true python-versions = "<4,>=3.6" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762"}, {file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"}, @@ -6636,6 +8472,32 @@ files = [ [package.dependencies] pyasn1 = ">=0.1.3" +[[package]] +name = "sacrebleu" +version = "2.6.0" +description = "Hassle-free computation of shareable, comparable, and reproducible BLEU, chrF, and TER scores" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "sacrebleu-2.6.0-py3-none-any.whl", hash = "sha256:3edc1531575cfe4ad04ce53491a9307e234af1c3f805a1f491cbec844229a8a8"}, + {file = "sacrebleu-2.6.0.tar.gz", hash = "sha256:91499b6cd46138d95154fff1e863c2f9be57e82f0c719d8dd718d0006cf6c566"}, +] + +[package.dependencies] +colorama = "*" +lxml = "*" +numpy = ">=1.17" +portalocker = "*" +regex = "*" +tabulate = ">=0.8.9" + +[package.extras] +dev = ["lxml-stubs", "mypy", "pytest", "setuptools", "types-tabulate", "wheel"] +ja = ["ipadic (>=1.0,<2.0)", "mecab-python3 (>=1.0.9,<2.0.0)"] +ko = ["mecab-ko (>=1.0.2,<2.0.0)", "mecab-ko-dic (>=1.0,<2.0)"] + [[package]] name = "safetensors" version = "0.7.0" @@ -6683,6 +8545,71 @@ testing = ["h5py (>=3.7.0)", "huggingface-hub (>=0.12.1)", "hypothesis (>=6.70.2 testingfree = ["huggingface-hub (>=0.12.1)", "hypothesis (>=6.70.2)", "pytest (>=7.2.0)", "pytest-benchmark (>=4.0.0)", "safetensors[numpy]", "setuptools-rust (>=1.5.2)"] torch = ["packaging", "safetensors[numpy]", "torch (>=1.10)"] +[[package]] +name = "scipy" +version = "1.15.3" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = ">=3.10" +groups = ["main"] +markers = "python_version == \"3.10\"" +files = [ + {file = "scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c"}, + {file = "scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253"}, + {file = "scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f"}, + {file = "scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92"}, + {file = "scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82"}, + {file = "scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40"}, + {file = "scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e"}, + {file = "scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c"}, + {file = "scipy-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13"}, + {file = "scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b"}, + {file = "scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba"}, + {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65"}, + {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1"}, + {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889"}, + {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982"}, + {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9"}, + {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594"}, + {file = "scipy-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb"}, + {file = "scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019"}, + {file = "scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6"}, + {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477"}, + {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c"}, + {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45"}, + {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49"}, + {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e"}, + {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539"}, + {file = "scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed"}, + {file = "scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759"}, + {file = "scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62"}, + {file = "scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb"}, + {file = "scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730"}, + {file = "scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825"}, + {file = "scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7"}, + {file = "scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11"}, + {file = "scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126"}, + {file = "scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163"}, + {file = "scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8"}, + {file = "scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5"}, + {file = "scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e"}, + {file = "scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb"}, + {file = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723"}, + {file = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb"}, + {file = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4"}, + {file = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5"}, + {file = "scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca"}, + {file = "scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf"}, +] + +[package.dependencies] +numpy = ">=1.23.5,<2.5" + +[package.extras] +dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"] +doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"] +test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + [[package]] name = "scipy" version = "1.17.1" @@ -6690,6 +8617,7 @@ description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.11" groups = ["main"] +markers = "python_version >= \"3.11\"" files = [ {file = "scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec"}, {file = "scipy-1.17.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696"}, @@ -6769,7 +8697,7 @@ description = "Unsupervised text tokenizer and detokenizer." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "sentencepiece-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e10fa50bdbaa5e2445dbd387979980d391760faf0ec99a09bd7780ff37eaec44"}, {file = "sentencepiece-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f27ae6deea72efdb6f361750c92f6c21fd0ad087445082770cc34015213c526"}, @@ -6849,7 +8777,7 @@ description = "Python client for Sentry (https://sentry.io)" optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "sentry_sdk-2.53.0-py2.py3-none-any.whl", hash = "sha256:46e1ed8d84355ae54406c924f6b290c3d61f4048625989a723fd622aab838899"}, {file = "sentry_sdk-2.53.0.tar.gz", hash = "sha256:6520ef2c4acd823f28efc55e43eb6ce2e6d9f954a95a3aa96b6fd14871e92b77"}, @@ -6913,7 +8841,7 @@ description = "A Python module to customize the process title" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "setproctitle-1.3.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cf555b6299f10a6eb44e4f96d2f5a3884c70ce25dc5c8796aaa2f7b40e72cb1b"}, {file = "setproctitle-1.3.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:690b4776f9c15aaf1023bb07d7c5b797681a17af98a4a69e76a1d504e41108b7"}, @@ -7024,7 +8952,7 @@ description = "Easily download, build, install, upgrade, and uninstall Python pa optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_version == \"3.12\"" +markers = "python_full_version == \"3.13.0\" or python_version == \"3.12\"" files = [ {file = "setuptools-80.10.2-py3-none-any.whl", hash = "sha256:95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173"}, {file = "setuptools-80.10.2.tar.gz", hash = "sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70"}, @@ -7046,7 +8974,6 @@ description = "Easily download, build, install, upgrade, and uninstall Python pa optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_version == \"3.11\"" files = [ {file = "setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0"}, {file = "setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb"}, @@ -7065,10 +8992,9 @@ type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.deve name = "shellingham" version = "1.5.4" description = "Tool to Detect Surrounding Shell" -optional = true +optional = false python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"vllm\"" files = [ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, @@ -7213,7 +9139,7 @@ description = "Utils for streaming large files (S3, HDFS, GCS, SFTP, Azure Blob optional = true python-versions = "<4.0,>=3.10" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "smart_open-7.5.1-py3-none-any.whl", hash = "sha256:3e07cbbd9c8a908bcb8e25d48becf1a5cbb4886fa975e9f34c672ed171df2318"}, {file = "smart_open-7.5.1.tar.gz", hash = "sha256:3f08e16827c4733699e6b2cc40328a3568f900cb12ad9a3ad233ba6c872d9fe7"}, @@ -7240,7 +9166,7 @@ description = "Sniff out which async library your code is running under" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"tinker\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -7549,7 +9475,7 @@ description = "SSE plugin for Starlette" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "sse_starlette-3.3.2-py3-none-any.whl", hash = "sha256:5c3ea3dad425c601236726af2f27689b74494643f57017cafcb6f8c9acfbb862"}, {file = "sse_starlette-3.3.2.tar.gz", hash = "sha256:678fca55a1945c734d8472a6cad186a55ab02840b4f6786f5ee8770970579dcd"}, @@ -7591,7 +9517,7 @@ description = "A system for controlling process state under UNIX" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "supervisor-4.3.0-py2.py3-none-any.whl", hash = "sha256:0bcb763fddafba410f35cbde226aa7f8514b9fb82eb05a0c85f6588d1c13f8db"}, {file = "supervisor-4.3.0.tar.gz", hash = "sha256:4a2bf149adf42997e1bb44b70c43b613275ec9852c3edacca86a9166b27e945e"}, @@ -7600,6 +9526,44 @@ files = [ [package.extras] test = ["pytest", "pytest-cov"] +[[package]] +name = "swanlab" +version = "0.10.0" +description = "Python library for streamlined tracking and management of AI training processes." +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "swanlab-0.10.0-py3-none-any.whl", hash = "sha256:5467143d68925ee0968e3409174fbf25958a7736b0c6f347c90aabaf257f9057"}, + {file = "swanlab-0.10.0.tar.gz", hash = "sha256:746ca2798a4ca40a5d0cb2535993b0f4c88348b7a182da813a4b45feda24eef9"}, +] + +[package.dependencies] +click = "*" +nvidia-ml-py = "*" +orjson = {version = "*", markers = "python_version > \"3.9\""} +platformdirs = ">=4.2.0" +protobuf = {version = ">=6.31.1,<7", markers = "python_version > \"3.9\" or sys_platform != \"linux\""} +psutil = ">=5.0.0" +pwinput = ">=1.0.3" +pydantic = ">=2.0,<3.0" +pydantic-settings = ">=2.8.1" +pyecharts = ">=2.0.0" +pyroaring = {version = ">=1.0.0,<1.0.4", markers = "python_version < \"3.14\""} +pyyaml = "*" +requests = ">=2.28.0" +rich = ">=13.6.0" +setuptools = "*" +urllib3 = ">=1.26.0" +watchdog = "*" +wrapt = ">=1.17.0" + +[package.extras] +dashboard = ["swanboard (==0.1.10b2)"] +media = ["imageio[ffmpeg]", "matplotlib", "moviepy", "numpy", "pillow", "rdkit (<=2023.9.6) ; python_version == \"3.9\"", "rdkit (>=2025.9.6) ; python_version > \"3.9\"", "soundfile"] +s3 = ["boto3 (>=1.35.49)"] + [[package]] name = "sympy" version = "1.14.0" @@ -7625,7 +9589,7 @@ description = "Pretty-print tabular data" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, @@ -7634,6 +9598,85 @@ files = [ [package.extras] widechars = ["wcwidth"] +[[package]] +name = "tensordict" +version = "0.14.2" +description = "TensorDict is a pytorch dedicated tensor container." +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "tensordict-0.14.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:9e4650b76d4e0672cf9c0320225b21434a589f4629d5836114019335875ffee9"}, + {file = "tensordict-0.14.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:b9963fdd3bdcfea7919eea15208d5730c7862bcb028efd26fb46b6072a2abc79"}, + {file = "tensordict-0.14.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:404f47a5d024e1215792a920d7a742402981e907bc8a0c86f374358e719fefb3"}, + {file = "tensordict-0.14.2-cp310-cp310-win_amd64.whl", hash = "sha256:45c851e2b884c2e63180d75a82599ccb343b816a4ab3da4b28290695726184df"}, + {file = "tensordict-0.14.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:e2ac08238d0404a7f17f938331918c9bea026123bc7df4c07f2ce52b3068953f"}, + {file = "tensordict-0.14.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:001c62b1b9b7305077f29ab4e1a06693f1a7add7bfb2cd42d03b2172f185d425"}, + {file = "tensordict-0.14.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:002ce1387d1b6bb2ee29affbb68aaae4c79fa8773137bef88534fc2fadefca2f"}, + {file = "tensordict-0.14.2-cp311-cp311-win_amd64.whl", hash = "sha256:0d1f8f949db128b896b9cb022de532d3d87902811d2751c11f52270a27eabd9a"}, + {file = "tensordict-0.14.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:0e8b65def0da306741d262976e7613afb2079e8b521b6be910edd8080a33c265"}, + {file = "tensordict-0.14.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:1553be455faf595bdc0e2b18649ca8791728ea13359805c22fe8c2aff6bd8fd0"}, + {file = "tensordict-0.14.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:0a748755bfb35db40123bcda67bfebac0138283d25deda76fe30be58ce10c247"}, + {file = "tensordict-0.14.2-cp312-cp312-win_amd64.whl", hash = "sha256:5e676f6048c4e3ad53de379469270545526d6a19badbc48bd5870b68c64e84f4"}, + {file = "tensordict-0.14.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c5e4aa2a4a8b4b1370828186836fad9605f2091a3fa3e009b15423d787aaed3"}, + {file = "tensordict-0.14.2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:7d79bf7bcbdf6b0686ba756debffe9b73de9686e9fa5923747538408f130df9d"}, + {file = "tensordict-0.14.2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:75a2a55f4633fbd3b82d158b2442e561bd595d48138ca473a2008e4e8689e640"}, + {file = "tensordict-0.14.2-cp313-cp313-win_amd64.whl", hash = "sha256:99a36acdc59eb162d3de214be464be2c85998f004b83ddb425aa23f74b92b6f6"}, + {file = "tensordict-0.14.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:10ae025f99e23dcec102652a9859c609122abac053fc3cd09ad999959d9069f2"}, + {file = "tensordict-0.14.2-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:4ec2d0d1ca4a61196deadb7a88584d9df47dc720ba45d00af15783396961295f"}, + {file = "tensordict-0.14.2-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:6d710cbc3091be3fee8d009492fb372df4c732e064495cf0ed5cdfacb5e168bd"}, + {file = "tensordict-0.14.2-cp314-cp314-win_amd64.whl", hash = "sha256:31512077ade1931b47b90be02a96ebfea23db28ab195c158bea01e11a0c71638"}, + {file = "tensordict-0.14.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:ad9c5a260b031145cd8a10a2fcdc5aa6c817c0e92cb80ec40bb140a0368b868a"}, + {file = "tensordict-0.14.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:595cdb56991ea6a7880af363f349299bb432041aa117fd8cdde76f0976f335a3"}, + {file = "tensordict-0.14.2-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:0482dd97ba526d4918f8920aaa3936f6fe32f2ed4682a714e779582eacba4c2c"}, + {file = "tensordict-0.14.2-cp314-cp314t-win_amd64.whl", hash = "sha256:68cba296f45c4eb98587644ce07902fbe75e064a2b738b8c5b2b590b8ea8f85b"}, +] + +[package.dependencies] +cloudpickle = "*" +importlib_metadata = "*" +numpy = "*" +orjson = {version = "*", markers = "python_version < \"3.13\""} +packaging = "*" +pyvers = ">=0.2.0,<0.3.0" +torch = "*" + +[package.extras] +dev = ["ninja", "pybind11 (>=2.13)"] +h5 = ["h5py (>=3.8)"] +onnx = ["onnx", "onnxruntime", "onnxscript"] +pandas = ["pandas (>=1.5)"] +parquet = ["pyarrow (>=10.0)"] +tabular = ["pandas (>=1.5)", "pyarrow (>=10.0)"] +tests = ["pytest", "pytest-benchmark", "pytest-instafail", "pytest-rerunfailures", "pyyaml"] +typecheck = ["mypy (>=1.0.0)"] +zarr = ["zarr (>=3.0) ; python_version >= \"3.11\""] + +[[package]] +name = "textual" +version = "8.2.8" +description = "Modern Text User Interface framework" +optional = true +python-versions = "<4.0,>=3.9" +groups = ["main"] +markers = "extra == \"client\"" +files = [ + {file = "textual-8.2.8-py3-none-any.whl", hash = "sha256:267375fd402dc8d981457212efa71f0e3365fd17bba144ba9bb3ed7563cb374a"}, + {file = "textual-8.2.8.tar.gz", hash = "sha256:3f106a9fbc73e39dd266c9712432087de78a6d644084c7c241d6a25c3169115b"}, +] + +[package.dependencies] +markdown-it-py = {version = ">=2.1.0", extras = ["linkify"]} +mdit-py-plugins = "*" +platformdirs = ">=3.6.0,<5" +pygments = ">=2.19.2,<3.0.0" +rich = ">=14.2.0" +typing-extensions = ">=4.4.0,<5.0.0" + +[package.extras] +syntax = ["tree-sitter (>=0.25.0) ; python_version >= \"3.10\"", "tree-sitter-bash (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-css (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-go (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-html (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-java (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-javascript (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-json (>=0.24.0) ; python_version >= \"3.10\"", "tree-sitter-markdown (>=0.3.0) ; python_version >= \"3.10\"", "tree-sitter-python (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-regex (>=0.24.0) ; python_version >= \"3.10\"", "tree-sitter-rust (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-sql (>=0.3.11) ; python_version >= \"3.10\"", "tree-sitter-toml (>=0.6.0) ; python_version >= \"3.10\"", "tree-sitter-xml (>=0.7.0) ; python_version >= \"3.10\"", "tree-sitter-yaml (>=0.6.0) ; python_version >= \"3.10\""] + [[package]] name = "tiktoken" version = "0.12.0" @@ -7641,7 +9684,7 @@ description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "tiktoken-0.12.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3de02f5a491cfd179aec916eddb70331814bd6bf764075d39e21d5862e533970"}, {file = "tiktoken-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6cfb6d9b7b54d20af21a912bfe63a2727d9cfa8fbda642fd8322c70340aad16"}, @@ -7711,15 +9754,15 @@ blobfile = ["blobfile (>=2)"] [[package]] name = "tinker" -version = "0.14.0" +version = "0.29.0" description = "The official Python SDK for the tinker API" optional = true python-versions = ">=3.11" groups = ["main"] -markers = "extra == \"tinker\"" +markers = "python_version >= \"3.11\" and extra == \"client\"" files = [ - {file = "tinker-0.14.0-py3-none-any.whl", hash = "sha256:b8e4dd2c77858e80177cb0b970c5d64a7dae085b67a711cc7e1d95352534c563"}, - {file = "tinker-0.14.0.tar.gz", hash = "sha256:554b30c43d9cf83b41eb07775a2a9f65eb2e77bed2cd79792bd8cd0d7693e717"}, + {file = "tinker-0.29.0-py3-none-any.whl", hash = "sha256:d3a9edd08718edaa8d8f72fe4ffa2a7f1ae8da2967f35e1ab206988b86a1b1fb"}, + {file = "tinker-0.29.0.tar.gz", hash = "sha256:615ed096ff647addafd1637096e8c688ce1581b8132bb937426492d2c5c0d619"}, ] [package.dependencies] @@ -7728,11 +9771,15 @@ click = ">=8.0.0" distro = ">=1.7.0,<2" httpx = {version = ">=0.23.0,<1", extras = ["http2"]} numpy = "*" +orjson = ">=3.10.0" +protobuf = ">=4.21" pydantic = ">=1.9.0,<3" +pyqwest = ">=0.4.1" rich = ">=13.0.0" sniffio = "*" transformers = "*" typing-extensions = ">=4.10,<5" +zstandard = ">=0.24.0" [package.extras] aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.8)"] @@ -7780,6 +9827,64 @@ dev = ["tokenizers[testing]"] docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] testing = ["datasets", "numpy", "pytest", "pytest-asyncio", "requests", "ruff", "ty"] +[[package]] +name = "tomli" +version = "2.4.1" +description = "A lil' TOML parser" +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "python_version == \"3.10\" and (extra == \"rl\" or extra == \"async-rl\" or extra == \"test\")" +files = [ + {file = "tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30"}, + {file = "tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc"}, + {file = "tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049"}, + {file = "tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e"}, + {file = "tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1"}, + {file = "tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917"}, + {file = "tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9"}, + {file = "tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5"}, + {file = "tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd"}, + {file = "tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36"}, + {file = "tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba"}, + {file = "tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6"}, + {file = "tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7"}, + {file = "tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f"}, + {file = "tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8"}, + {file = "tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26"}, + {file = "tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396"}, + {file = "tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe"}, + {file = "tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f"}, +] + [[package]] name = "torch" version = "2.9.1" @@ -7855,7 +9960,7 @@ description = "An audio package for PyTorch" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "torchaudio-2.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd13541197e035338bd43225b2067532056486d357c661e12d49ace4fc37f8bb"}, {file = "torchaudio-2.9.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:31ec46b718b7caa0182221bfb42e2ad223947b752a996dcdc0388c34a678c966"}, @@ -7897,7 +10002,7 @@ description = "image and video datasets and models for torch deep learning" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"transformers\" or extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "torchvision-0.24.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ded5e625788572e4e1c4d155d1bbc48805c113794100d70e19c76e39e4d53465"}, {file = "torchvision-0.24.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:54ed17c3d30e718e08d8da3fd5b30ea44b0311317e55647cb97077a29ecbc25b"}, @@ -7960,6 +10065,35 @@ notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] +[[package]] +name = "transferqueue" +version = "0.1.10" +description = "TransferQueue: An Asynchronous Streaming Data Management Module" +optional = true +python-versions = ">=3.10" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "transferqueue-0.1.10-py3-none-any.whl", hash = "sha256:a8efceb971fe57d52ac7ddd86d9a6ef63f1824819dddc2ea980a96b73ff2f8ea"}, +] + +[package.dependencies] +hydra-core = "*" +msgspec = "*" +numpy = "*" +omegaconf = "*" +prometheus_client = ">=0.20.0" +psutil = "*" +pyzmq = "*" +ray = {version = "*", extras = ["default"]} +tensordict = ">=0.10.0" + +[package.extras] +build = ["build"] +mooncake = ["cuda-python", "mooncake-transfer-engine (>=0.3.10.post2)"] +test = ["flake8", "pytest (>=7.0.0)", "pytest-asyncio (>=0.20.0)", "pytest-mock"] +yuanrong = ["openyuanrong-datasystem"] + [[package]] name = "transformer-engine" version = "2.12.0" @@ -8134,10 +10268,9 @@ tutorials = ["matplotlib", "pandas", "tabulate"] name = "typer" version = "0.24.1" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." -optional = true +optional = false python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\"" files = [ {file = "typer-0.24.1-py3-none-any.whl", hash = "sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e"}, {file = "typer-0.24.1.tar.gz", hash = "sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45"}, @@ -8183,7 +10316,7 @@ description = "Provider of IANA time zone data" optional = false python-versions = ">=2" groups = ["main"] -markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\"" +markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version == \"3.10\"" files = [ {file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"}, {file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"}, @@ -8214,7 +10347,7 @@ description = "The lightning-fast ASGI server." optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "uvicorn-0.41.0-py3-none-any.whl", hash = "sha256:29e35b1d2c36a04b9e180d4007ede3bcb32a85fbdfd6c6aeb3f26839de088187"}, {file = "uvicorn-0.41.0.tar.gz", hash = "sha256:09d11cf7008da33113824ee5a1c6422d89fbc2ff476540d69a34c87fab8b571a"}, @@ -8227,6 +10360,7 @@ h11 = ">=0.8" httptools = {version = ">=0.6.3", optional = true, markers = "extra == \"standard\""} python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} +typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} uvloop = {version = ">=0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} watchfiles = {version = ">=0.20", optional = true, markers = "extra == \"standard\""} websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} @@ -8241,7 +10375,7 @@ description = "Fast implementation of asyncio event loop on top of libuv" optional = true python-versions = ">=3.8.1" groups = ["main"] -markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and (extra == \"vllm\" or extra == \"ray\")" +markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and (extra == \"rl\" or extra == \"async-rl\")" files = [ {file = "uvloop-0.22.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c"}, {file = "uvloop-0.22.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7cd375a12b71d33d46af85a3343b35d98e8116134ba404bd657b3b1d15988792"}, @@ -8306,7 +10440,7 @@ description = "Virtual Python Environment builder" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "virtualenv-21.1.0-py3-none-any.whl", hash = "sha256:164f5e14c5587d170cf98e60378eb91ea35bf037be313811905d3a24ea33cc07"}, {file = "virtualenv-21.1.0.tar.gz", hash = "sha256:1990a0188c8f16b6b9cf65c9183049007375b26aad415514d377ccacf1e4fb44"}, @@ -8317,6 +10451,7 @@ distlib = ">=0.3.7,<1" filelock = {version = ">=3.24.2,<4", markers = "python_version >= \"3.10\""} platformdirs = ">=3.9.1,<5" python-discovery = ">=1" +typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\""} [[package]] name = "vllm" @@ -8325,7 +10460,7 @@ description = "A high-throughput and memory-efficient inference and serving engi optional = true python-versions = "<3.14,>=3.10" groups = ["main"] -markers = "extra == \"vllm\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "vllm-0.16.0-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:dfaa14846608fd229dda9d372e2ad3f13854fd09147c2ba36b40579cf3c03804"}, {file = "vllm-0.16.0-cp38-abi3-manylinux_2_31_x86_64.whl", hash = "sha256:f066b2a2f8597a4a3ada8fbbfd122b59086864b2260ca42dc81bf9fb57af0c42"}, @@ -8404,6 +10539,50 @@ petit-kernel = ["petit-kernel"] runai = ["runai-model-streamer[gcs,s3] (>=0.15.3)"] tensorizer = ["tensorizer (==2.10.1)"] +[[package]] +name = "watchdog" +version = "6.0.0" +description = "Filesystem events monitoring" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"}, + {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"}, + {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"}, + {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"}, + {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"}, + {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"}, + {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"}, + {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"}, + {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"}, + {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"}, + {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"}, + {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"}, + {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"}, + {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"}, + {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"}, + {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"}, + {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"}, + {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"}, + {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"}, + {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"}, + {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"}, + {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"}, + {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"}, + {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"}, +] + +[package.extras] +watchmedo = ["PyYAML (>=3.10)"] + [[package]] name = "watchfiles" version = "1.1.1" @@ -8411,7 +10590,7 @@ description = "Simple, modern and high performance file watching and code reload optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "watchfiles-1.1.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:eef58232d32daf2ac67f42dea51a2c80f0d03379075d44a587051e63cc2e368c"}, {file = "watchfiles-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03fa0f5237118a0c5e496185cafa92878568b652a2e9a9382a5151b1a0380a43"}, @@ -8527,6 +10706,19 @@ files = [ [package.dependencies] anyio = ">=3.0.0" +[[package]] +name = "wcwidth" +version = "0.8.3" +description = "Measures the displayed width of unicode strings in a terminal" +optional = true +python-versions = ">=3.8" +groups = ["main"] +markers = "extra == \"async-rl\"" +files = [ + {file = "wcwidth-0.8.3-py3-none-any.whl", hash = "sha256:d5b73dba6158a595ec9370350e7f2637bcac8d6c5e4fde34f30fcffb6103a5e4"}, + {file = "wcwidth-0.8.3.tar.gz", hash = "sha256:d128512515fbf4612e0ff21fd6380399210318b7b54a9af59dff8454cf9730eb"}, +] + [[package]] name = "websockets" version = "16.0" @@ -8534,7 +10726,7 @@ description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"vllm\" or extra == \"ray\"" +markers = "extra == \"rl\" or extra == \"async-rl\"" files = [ {file = "websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a"}, {file = "websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0"}, @@ -8606,7 +10798,7 @@ description = "A small Python utility to set file creation time on Windows" optional = true python-versions = ">=3.5" groups = ["main"] -markers = "extra == \"vllm\" and sys_platform == \"win32\"" +markers = "sys_platform == \"win32\" and (extra == \"rl\" or extra == \"async-rl\")" files = [ {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, @@ -8615,93 +10807,109 @@ files = [ [package.extras] dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] +[[package]] +name = "word2number" +version = "1.1" +description = "Convert number words eg. three hundred and forty two to numbers (342)." +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "word2number-1.1.zip", hash = "sha256:70e27a5d387f67b04c71fbb7621c05930b19bfd26efd6851e6e0f9969dcde7d0"}, +] + [[package]] name = "wrapt" -version = "2.1.1" +version = "1.17.3" description = "Module for decorators, wrappers and monkey patching." optional = true -python-versions = ">=3.9" +python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"ray\"" -files = [ - {file = "wrapt-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7e927375e43fd5a985b27a8992327c22541b6dede1362fc79df337d26e23604f"}, - {file = "wrapt-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c99544b6a7d40ca22195563b6d8bc3986ee8bb82f272f31f0670fe9440c869"}, - {file = "wrapt-2.1.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b2be3fa5f4efaf16ee7c77d0556abca35f5a18ad4ac06f0ef3904c3399010ce9"}, - {file = "wrapt-2.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67c90c1ae6489a6cb1a82058902caa8006706f7b4e8ff766f943e9d2c8e608d0"}, - {file = "wrapt-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:05c0db35ccffd7480143e62df1e829d101c7b86944ae3be7e4869a7efa621f53"}, - {file = "wrapt-2.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0c2ec9f616755b2e1e0bf4d0961f59bb5c2e7a77407e7e2c38ef4f7d2fdde12c"}, - {file = "wrapt-2.1.1-cp310-cp310-win32.whl", hash = "sha256:203ba6b3f89e410e27dbd30ff7dccaf54dcf30fda0b22aa1b82d560c7f9fe9a1"}, - {file = "wrapt-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:6f9426d9cfc2f8732922fc96198052e55c09bb9db3ddaa4323a18e055807410e"}, - {file = "wrapt-2.1.1-cp310-cp310-win_arm64.whl", hash = "sha256:69c26f51b67076b40714cff81bdd5826c0b10c077fb6b0678393a6a2f952a5fc"}, - {file = "wrapt-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c366434a7fb914c7a5de508ed735ef9c133367114e1a7cb91dfb5cd806a1549"}, - {file = "wrapt-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d6a2068bd2e1e19e5a317c8c0b288267eec4e7347c36bc68a6e378a39f19ee7"}, - {file = "wrapt-2.1.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:891ab4713419217b2aed7dd106c9200f64e6a82226775a0d2ebd6bef2ebd1747"}, - {file = "wrapt-2.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8ef36a0df38d2dc9d907f6617f89e113c5892e0a35f58f45f75901af0ce7d81"}, - {file = "wrapt-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:76e9af3ebd86f19973143d4d592cbf3e970cf3f66ddee30b16278c26ae34b8ab"}, - {file = "wrapt-2.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ff562067485ebdeaef2fa3fe9b1876bc4e7b73762e0a01406ad81e2076edcebf"}, - {file = "wrapt-2.1.1-cp311-cp311-win32.whl", hash = "sha256:9e60a30aa0909435ec4ea2a3c53e8e1b50ac9f640c0e9fe3f21fd248a22f06c5"}, - {file = "wrapt-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:7d79954f51fcf84e5ec4878ab4aea32610d70145c5bbc84b3370eabfb1e096c2"}, - {file = "wrapt-2.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:d3ffc6b0efe79e08fd947605fd598515aebefe45e50432dc3b5cd437df8b1ada"}, - {file = "wrapt-2.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab8e3793b239db021a18782a5823fcdea63b9fe75d0e340957f5828ef55fcc02"}, - {file = "wrapt-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7c0300007836373d1c2df105b40777986accb738053a92fe09b615a7a4547e9f"}, - {file = "wrapt-2.1.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2b27c070fd1132ab23957bcd4ee3ba707a91e653a9268dc1afbd39b77b2799f7"}, - {file = "wrapt-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b0e36d845e8b6f50949b6b65fc6cd279f47a1944582ed4ec8258cd136d89a64"}, - {file = "wrapt-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4aeea04a9889370fcfb1ef828c4cc583f36a875061505cd6cd9ba24d8b43cc36"}, - {file = "wrapt-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d88b46bb0dce9f74b6817bc1758ff2125e1ca9e1377d62ea35b6896142ab6825"}, - {file = "wrapt-2.1.1-cp312-cp312-win32.whl", hash = "sha256:63decff76ca685b5c557082dfbea865f3f5f6d45766a89bff8dc61d336348833"}, - {file = "wrapt-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:b828235d26c1e35aca4107039802ae4b1411be0fe0367dd5b7e4d90e562fcbcd"}, - {file = "wrapt-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:75128507413a9f1bcbe2db88fd18fbdbf80f264b82fa33a6996cdeaf01c52352"}, - {file = "wrapt-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ce9646e17fa7c3e2e7a87e696c7de66512c2b4f789a8db95c613588985a2e139"}, - {file = "wrapt-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:428cfc801925454395aa468ba7ddb3ed63dc0d881df7b81626cdd433b4e2b11b"}, - {file = "wrapt-2.1.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5797f65e4d58065a49088c3b32af5410751cd485e83ba89e5a45e2aa8905af98"}, - {file = "wrapt-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a2db44a71202c5ae4bb5f27c6d3afbc5b23053f2e7e78aa29704541b5dad789"}, - {file = "wrapt-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8d5350c3590af09c1703dd60ec78a7370c0186e11eaafb9dda025a30eee6492d"}, - {file = "wrapt-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d9b076411bed964e752c01b49fd224cc385f3a96f520c797d38412d70d08359"}, - {file = "wrapt-2.1.1-cp313-cp313-win32.whl", hash = "sha256:0bb7207130ce6486727baa85373503bf3334cc28016f6928a0fa7e19d7ecdc06"}, - {file = "wrapt-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:cbfee35c711046b15147b0ae7db9b976f01c9520e6636d992cd9e69e5e2b03b1"}, - {file = "wrapt-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:7d2756061022aebbf57ba14af9c16e8044e055c22d38de7bf40d92b565ecd2b0"}, - {file = "wrapt-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4814a3e58bc6971e46baa910ecee69699110a2bf06c201e24277c65115a20c20"}, - {file = "wrapt-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:106c5123232ab9b9f4903692e1fa0bdc231510098f04c13c3081f8ad71c3d612"}, - {file = "wrapt-2.1.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1a40b83ff2535e6e56f190aff123821eea89a24c589f7af33413b9c19eb2c738"}, - {file = "wrapt-2.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:789cea26e740d71cf1882e3a42bb29052bc4ada15770c90072cb47bf73fb3dbf"}, - {file = "wrapt-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ba49c14222d5e5c0ee394495a8655e991dc06cbca5398153aefa5ac08cd6ccd7"}, - {file = "wrapt-2.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ac8cda531fe55be838a17c62c806824472bb962b3afa47ecbd59b27b78496f4e"}, - {file = "wrapt-2.1.1-cp313-cp313t-win32.whl", hash = "sha256:b8af75fe20d381dd5bcc9db2e86a86d7fcfbf615383a7147b85da97c1182225b"}, - {file = "wrapt-2.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:45c5631c9b6c792b78be2d7352129f776dd72c605be2c3a4e9be346be8376d83"}, - {file = "wrapt-2.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:da815b9263947ac98d088b6414ac83507809a1d385e4632d9489867228d6d81c"}, - {file = "wrapt-2.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9aa1765054245bb01a37f615503290d4e207e3fd59226e78341afb587e9c1236"}, - {file = "wrapt-2.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:feff14b63a6d86c1eee33a57f77573649f2550935981625be7ff3cb7342efe05"}, - {file = "wrapt-2.1.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81fc5f22d5fcfdbabde96bb3f5379b9f4476d05c6d524d7259dc5dfb501d3281"}, - {file = "wrapt-2.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:951b228ecf66def855d22e006ab9a1fc12535111ae7db2ec576c728f8ddb39e8"}, - {file = "wrapt-2.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ddf582a95641b9a8c8bd643e83f34ecbbfe1b68bc3850093605e469ab680ae3"}, - {file = "wrapt-2.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:fc5c500966bf48913f795f1984704e6d452ba2414207b15e1f8c339a059d5b16"}, - {file = "wrapt-2.1.1-cp314-cp314-win32.whl", hash = "sha256:4aa4baadb1f94b71151b8e44a0c044f6af37396c3b8bcd474b78b49e2130a23b"}, - {file = "wrapt-2.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:860e9d3fd81816a9f4e40812f28be4439ab01f260603c749d14be3c0a1170d19"}, - {file = "wrapt-2.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:3c59e103017a2c1ea0ddf589cbefd63f91081d7ce9d491d69ff2512bb1157e23"}, - {file = "wrapt-2.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9fa7c7e1bee9278fc4f5dd8275bc8d25493281a8ec6c61959e37cc46acf02007"}, - {file = "wrapt-2.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:39c35e12e8215628984248bd9c8897ce0a474be2a773db207eb93414219d8469"}, - {file = "wrapt-2.1.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:94ded4540cac9125eaa8ddf5f651a7ec0da6f5b9f248fe0347b597098f8ec14c"}, - {file = "wrapt-2.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da0af328373f97ed9bdfea24549ac1b944096a5a71b30e41c9b8b53ab3eec04a"}, - {file = "wrapt-2.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4ad839b55f0bf235f8e337ce060572d7a06592592f600f3a3029168e838469d3"}, - {file = "wrapt-2.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0d89c49356e5e2a50fa86b40e0510082abcd0530f926cbd71cf25bee6b9d82d7"}, - {file = "wrapt-2.1.1-cp314-cp314t-win32.whl", hash = "sha256:f4c7dd22cf7f36aafe772f3d88656559205c3af1b7900adfccb70edeb0d2abc4"}, - {file = "wrapt-2.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f76bc12c583ab01e73ba0ea585465a41e48d968f6d1311b4daec4f8654e356e3"}, - {file = "wrapt-2.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7ea74fc0bec172f1ae5f3505b6655c541786a5cabe4bbc0d9723a56ac32eb9b9"}, - {file = "wrapt-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e03b3d486eb39f5d3f562839f59094dcee30c4039359ea15768dc2214d9e07c"}, - {file = "wrapt-2.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0fdf3073f488ce4d929929b7799e3b8c52b220c9eb3f4a5a51e2dc0e8ff07881"}, - {file = "wrapt-2.1.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0cb4f59238c6625fae2eeb72278da31c9cfba0ff4d9cbe37446b73caa0e9bcf7"}, - {file = "wrapt-2.1.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f794a1c148871b714cb566f5466ec8288e0148a1c417550983864b3981737cd"}, - {file = "wrapt-2.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:95ef3866631c6da9ce1fc0f1e17b90c4c0aa6d041fc70a11bc90733aee122e1a"}, - {file = "wrapt-2.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:66bc1b2446f01cbbd3c56b79a3a8435bcd4178ac4e06b091913f7751a7f528b8"}, - {file = "wrapt-2.1.1-cp39-cp39-win32.whl", hash = "sha256:1b9e08e57cabc32972f7c956d10e85093c5da9019faa24faf411e7dd258e528c"}, - {file = "wrapt-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:e75ad48c3cca739f580b5e14c052993eb644c7fa5b4c90aa51193280b30875ae"}, - {file = "wrapt-2.1.1-cp39-cp39-win_arm64.whl", hash = "sha256:9ccd657873b7f964711447d004563a2bc08d1476d7a1afcad310f3713e6f50f4"}, - {file = "wrapt-2.1.1-py3-none-any.whl", hash = "sha256:3b0f4629eb954394a3d7c7a1c8cca25f0b07cefe6aa8545e862e9778152de5b7"}, - {file = "wrapt-2.1.1.tar.gz", hash = "sha256:5fdcb09bf6db023d88f312bd0767594b414655d58090fc1c46b3414415f67fac"}, -] - -[package.extras] -dev = ["pytest", "setuptools"] +markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" +files = [ + {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04"}, + {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2"}, + {file = "wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c"}, + {file = "wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775"}, + {file = "wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd"}, + {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05"}, + {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418"}, + {file = "wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390"}, + {file = "wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6"}, + {file = "wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18"}, + {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7"}, + {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85"}, + {file = "wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f"}, + {file = "wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311"}, + {file = "wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1"}, + {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5"}, + {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2"}, + {file = "wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89"}, + {file = "wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77"}, + {file = "wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a"}, + {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0"}, + {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba"}, + {file = "wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd"}, + {file = "wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828"}, + {file = "wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9"}, + {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396"}, + {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc"}, + {file = "wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe"}, + {file = "wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c"}, + {file = "wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6"}, + {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0"}, + {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77"}, + {file = "wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7"}, + {file = "wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277"}, + {file = "wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d"}, + {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa"}, + {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050"}, + {file = "wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8"}, + {file = "wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb"}, + {file = "wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16"}, + {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39"}, + {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235"}, + {file = "wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c"}, + {file = "wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b"}, + {file = "wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa"}, + {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7"}, + {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4"}, + {file = "wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10"}, + {file = "wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6"}, + {file = "wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58"}, + {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a"}, + {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067"}, + {file = "wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454"}, + {file = "wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e"}, + {file = "wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f"}, + {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056"}, + {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804"}, + {file = "wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977"}, + {file = "wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116"}, + {file = "wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6"}, + {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225"}, + {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a"}, + {file = "wrapt-1.17.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f"}, + {file = "wrapt-1.17.3-cp38-cp38-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00"}, + {file = "wrapt-1.17.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56"}, + {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5"}, + {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22"}, + {file = "wrapt-1.17.3-cp38-cp38-win32.whl", hash = "sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c"}, + {file = "wrapt-1.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2"}, + {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc"}, + {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9"}, + {file = "wrapt-1.17.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d"}, + {file = "wrapt-1.17.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a"}, + {file = "wrapt-1.17.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139"}, + {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df"}, + {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b"}, + {file = "wrapt-1.17.3-cp39-cp39-win32.whl", hash = "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81"}, + {file = "wrapt-1.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f"}, + {file = "wrapt-1.17.3-cp39-cp39-win_arm64.whl", hash = "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f"}, + {file = "wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22"}, + {file = "wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0"}, +] [[package]] name = "xgrammar" @@ -8710,7 +10918,7 @@ description = "Efficient, Flexible and Portable Structured Generation" optional = true python-versions = "<4,>=3.8" groups = ["main"] -markers = "extra == \"vllm\" and (platform_machine == \"x86_64\" or platform_machine == \"aarch64\" or platform_machine == \"arm64\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\")" +markers = "(extra == \"rl\" or extra == \"async-rl\") and (platform_machine == \"x86_64\" or platform_machine == \"aarch64\" or platform_machine == \"arm64\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\")" files = [ {file = "xgrammar-0.1.29-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:fdc66e834b915cf956168ac086bd577f138261644b944e73d73f07085682a4d8"}, {file = "xgrammar-0.1.29-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48c5a5c60c5ca5ab09ff5ef9f6b382384a04b153bae5908006cd4f7d80d71e07"}, @@ -9043,6 +11251,18 @@ idna = ">=2.0" multidict = ">=4.0" propcache = ">=0.2.1" +[[package]] +name = "zhconv" +version = "1.4.3" +description = "A simple implementation of Simplified-Traditional Chinese conversion." +optional = true +python-versions = "*" +groups = ["main"] +markers = "extra == \"eval\"" +files = [ + {file = "zhconv-1.4.3.tar.gz", hash = "sha256:ad42d9057ca0605f8e41d62b67ca797f879f58193ee6840562c51459b2698c45"}, +] + [[package]] name = "zipp" version = "3.23.0" @@ -9050,7 +11270,7 @@ description = "Backport of pathlib-compatible object wrapper for zip files" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"megatron\" or extra == \"ray\"" +markers = "(python_version >= \"3.11\" or extra == \"eval\" or extra == \"megatron\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\") and (python_version == \"3.11\" or extra == \"eval\" or extra == \"megatron\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"client\") and (extra == \"client\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"eval\" or extra == \"megatron\")" files = [ {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, @@ -9064,16 +11284,131 @@ enabler = ["pytest-enabler (>=2.2)"] test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] +[[package]] +name = "zstandard" +version = "0.25.0" +description = "Zstandard bindings for Python" +optional = true +python-versions = ">=3.9" +groups = ["main"] +markers = "python_version >= \"3.11\" and extra == \"client\"" +files = [ + {file = "zstandard-0.25.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e59fdc271772f6686e01e1b3b74537259800f57e24280be3f29c8a0deb1904dd"}, + {file = "zstandard-0.25.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4d441506e9b372386a5271c64125f72d5df6d2a8e8a2a45a0ae09b03cb781ef7"}, + {file = "zstandard-0.25.0-cp310-cp310-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:ab85470ab54c2cb96e176f40342d9ed41e58ca5733be6a893b730e7af9c40550"}, + {file = "zstandard-0.25.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e05ab82ea7753354bb054b92e2f288afb750e6b439ff6ca78af52939ebbc476d"}, + {file = "zstandard-0.25.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:78228d8a6a1c177a96b94f7e2e8d012c55f9c760761980da16ae7546a15a8e9b"}, + {file = "zstandard-0.25.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b6bd67528ee8b5c5f10255735abc21aa106931f0dbaf297c7be0c886353c3d0"}, + {file = "zstandard-0.25.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4b6d83057e713ff235a12e73916b6d356e3084fd3d14ced499d84240f3eecee0"}, + {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9174f4ed06f790a6869b41cba05b43eeb9a35f8993c4422ab853b705e8112bbd"}, + {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:25f8f3cd45087d089aef5ba3848cd9efe3ad41163d3400862fb42f81a3a46701"}, + {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3756b3e9da9b83da1796f8809dd57cb024f838b9eeafde28f3cb472012797ac1"}, + {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:81dad8d145d8fd981b2962b686b2241d3a1ea07733e76a2f15435dfb7fb60150"}, + {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a5a419712cf88862a45a23def0ae063686db3d324cec7edbe40509d1a79a0aab"}, + {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e7360eae90809efd19b886e59a09dad07da4ca9ba096752e61a2e03c8aca188e"}, + {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:75ffc32a569fb049499e63ce68c743155477610532da1eb38e7f24bf7cd29e74"}, + {file = "zstandard-0.25.0-cp310-cp310-win32.whl", hash = "sha256:106281ae350e494f4ac8a80470e66d1fe27e497052c8d9c3b95dc4cf1ade81aa"}, + {file = "zstandard-0.25.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea9d54cc3d8064260114a0bbf3479fc4a98b21dffc89b3459edd506b69262f6e"}, + {file = "zstandard-0.25.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:933b65d7680ea337180733cf9e87293cc5500cc0eb3fc8769f4d3c88d724ec5c"}, + {file = "zstandard-0.25.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3f79487c687b1fc69f19e487cd949bf3aae653d181dfb5fde3bf6d18894706f"}, + {file = "zstandard-0.25.0-cp311-cp311-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:0bbc9a0c65ce0eea3c34a691e3c4b6889f5f3909ba4822ab385fab9057099431"}, + {file = "zstandard-0.25.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:01582723b3ccd6939ab7b3a78622c573799d5d8737b534b86d0e06ac18dbde4a"}, + {file = "zstandard-0.25.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5f1ad7bf88535edcf30038f6919abe087f606f62c00a87d7e33e7fc57cb69fcc"}, + {file = "zstandard-0.25.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:06acb75eebeedb77b69048031282737717a63e71e4ae3f77cc0c3b9508320df6"}, + {file = "zstandard-0.25.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9300d02ea7c6506f00e627e287e0492a5eb0371ec1670ae852fefffa6164b072"}, + {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfd06b1c5584b657a2892a6014c2f4c20e0db0208c159148fa78c65f7e0b0277"}, + {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f373da2c1757bb7f1acaf09369cdc1d51d84131e50d5fa9863982fd626466313"}, + {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6c0e5a65158a7946e7a7affa6418878ef97ab66636f13353b8502d7ea03c8097"}, + {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c8e167d5adf59476fa3e37bee730890e389410c354771a62e3c076c86f9f7778"}, + {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:98750a309eb2f020da61e727de7d7ba3c57c97cf6213f6f6277bb7fb42a8e065"}, + {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:22a086cff1b6ceca18a8dd6096ec631e430e93a8e70a9ca5efa7561a00f826fa"}, + {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:72d35d7aa0bba323965da807a462b0966c91608ef3a48ba761678cb20ce5d8b7"}, + {file = "zstandard-0.25.0-cp311-cp311-win32.whl", hash = "sha256:f5aeea11ded7320a84dcdd62a3d95b5186834224a9e55b92ccae35d21a8b63d4"}, + {file = "zstandard-0.25.0-cp311-cp311-win_amd64.whl", hash = "sha256:daab68faadb847063d0c56f361a289c4f268706b598afbf9ad113cbe5c38b6b2"}, + {file = "zstandard-0.25.0-cp311-cp311-win_arm64.whl", hash = "sha256:22a06c5df3751bb7dc67406f5374734ccee8ed37fc5981bf1ad7041831fa1137"}, + {file = "zstandard-0.25.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b3c3a3ab9daa3eed242d6ecceead93aebbb8f5f84318d82cee643e019c4b73b"}, + {file = "zstandard-0.25.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:913cbd31a400febff93b564a23e17c3ed2d56c064006f54efec210d586171c00"}, + {file = "zstandard-0.25.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:011d388c76b11a0c165374ce660ce2c8efa8e5d87f34996aa80f9c0816698b64"}, + {file = "zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dffecc361d079bb48d7caef5d673c88c8988d3d33fb74ab95b7ee6da42652ea"}, + {file = "zstandard-0.25.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7149623bba7fdf7e7f24312953bcf73cae103db8cae49f8154dd1eadc8a29ecb"}, + {file = "zstandard-0.25.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6a573a35693e03cf1d67799fd01b50ff578515a8aeadd4595d2a7fa9f3ec002a"}, + {file = "zstandard-0.25.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5a56ba0db2d244117ed744dfa8f6f5b366e14148e00de44723413b2f3938a902"}, + {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:10ef2a79ab8e2974e2075fb984e5b9806c64134810fac21576f0668e7ea19f8f"}, + {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aaf21ba8fb76d102b696781bddaa0954b782536446083ae3fdaa6f16b25a1c4b"}, + {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1869da9571d5e94a85a5e8d57e4e8807b175c9e4a6294e3b66fa4efb074d90f6"}, + {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:809c5bcb2c67cd0ed81e9229d227d4ca28f82d0f778fc5fea624a9def3963f91"}, + {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f27662e4f7dbf9f9c12391cb37b4c4c3cb90ffbd3b1fb9284dadbbb8935fa708"}, + {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99c0c846e6e61718715a3c9437ccc625de26593fea60189567f0118dc9db7512"}, + {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:474d2596a2dbc241a556e965fb76002c1ce655445e4e3bf38e5477d413165ffa"}, + {file = "zstandard-0.25.0-cp312-cp312-win32.whl", hash = "sha256:23ebc8f17a03133b4426bcc04aabd68f8236eb78c3760f12783385171b0fd8bd"}, + {file = "zstandard-0.25.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffef5a74088f1e09947aecf91011136665152e0b4b359c42be3373897fb39b01"}, + {file = "zstandard-0.25.0-cp312-cp312-win_arm64.whl", hash = "sha256:181eb40e0b6a29b3cd2849f825e0fa34397f649170673d385f3598ae17cca2e9"}, + {file = "zstandard-0.25.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec996f12524f88e151c339688c3897194821d7f03081ab35d31d1e12ec975e94"}, + {file = "zstandard-0.25.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a1a4ae2dec3993a32247995bdfe367fc3266da832d82f8438c8570f989753de1"}, + {file = "zstandard-0.25.0-cp313-cp313-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:e96594a5537722fdfb79951672a2a63aec5ebfb823e7560586f7484819f2a08f"}, + {file = "zstandard-0.25.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bfc4e20784722098822e3eee42b8e576b379ed72cca4a7cb856ae733e62192ea"}, + {file = "zstandard-0.25.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:457ed498fc58cdc12fc48f7950e02740d4f7ae9493dd4ab2168a47c93c31298e"}, + {file = "zstandard-0.25.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:fd7a5004eb1980d3cefe26b2685bcb0b17989901a70a1040d1ac86f1d898c551"}, + {file = "zstandard-0.25.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8e735494da3db08694d26480f1493ad2cf86e99bdd53e8e9771b2752a5c0246a"}, + {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3a39c94ad7866160a4a46d772e43311a743c316942037671beb264e395bdd611"}, + {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:172de1f06947577d3a3005416977cce6168f2261284c02080e7ad0185faeced3"}, + {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c83b0188c852a47cd13ef3bf9209fb0a77fa5374958b8c53aaa699398c6bd7b"}, + {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1673b7199bbe763365b81a4f3252b8e80f44c9e323fc42940dc8843bfeaf9851"}, + {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0be7622c37c183406f3dbf0cba104118eb16a4ea7359eeb5752f0794882fc250"}, + {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5f5e4c2a23ca271c218ac025bd7d635597048b366d6f31f420aaeb715239fc98"}, + {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f187a0bb61b35119d1926aee039524d1f93aaf38a9916b8c4b78ac8514a0aaf"}, + {file = "zstandard-0.25.0-cp313-cp313-win32.whl", hash = "sha256:7030defa83eef3e51ff26f0b7bfb229f0204b66fe18e04359ce3474ac33cbc09"}, + {file = "zstandard-0.25.0-cp313-cp313-win_amd64.whl", hash = "sha256:1f830a0dac88719af0ae43b8b2d6aef487d437036468ef3c2ea59c51f9d55fd5"}, + {file = "zstandard-0.25.0-cp313-cp313-win_arm64.whl", hash = "sha256:85304a43f4d513f5464ceb938aa02c1e78c2943b29f44a750b48b25ac999a049"}, + {file = "zstandard-0.25.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e29f0cf06974c899b2c188ef7f783607dbef36da4c242eb6c82dcd8b512855e3"}, + {file = "zstandard-0.25.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:05df5136bc5a011f33cd25bc9f506e7426c0c9b3f9954f056831ce68f3b6689f"}, + {file = "zstandard-0.25.0-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:f604efd28f239cc21b3adb53eb061e2a205dc164be408e553b41ba2ffe0ca15c"}, + {file = "zstandard-0.25.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223415140608d0f0da010499eaa8ccdb9af210a543fac54bce15babbcfc78439"}, + {file = "zstandard-0.25.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e54296a283f3ab5a26fc9b8b5d4978ea0532f37b231644f367aa588930aa043"}, + {file = "zstandard-0.25.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ca54090275939dc8ec5dea2d2afb400e0f83444b2fc24e07df7fdef677110859"}, + {file = "zstandard-0.25.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e09bb6252b6476d8d56100e8147b803befa9a12cea144bbe629dd508800d1ad0"}, + {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a9ec8c642d1ec73287ae3e726792dd86c96f5681eb8df274a757bf62b750eae7"}, + {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a4089a10e598eae6393756b036e0f419e8c1d60f44a831520f9af41c14216cf2"}, + {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f67e8f1a324a900e75b5e28ffb152bcac9fbed1cc7b43f99cd90f395c4375344"}, + {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9654dbc012d8b06fc3d19cc825af3f7bf8ae242226df5f83936cb39f5fdc846c"}, + {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4203ce3b31aec23012d3a4cf4a2ed64d12fea5269c49aed5e4c3611b938e4088"}, + {file = "zstandard-0.25.0-cp314-cp314-win32.whl", hash = "sha256:da469dc041701583e34de852d8634703550348d5822e66a0c827d39b05365b12"}, + {file = "zstandard-0.25.0-cp314-cp314-win_amd64.whl", hash = "sha256:c19bcdd826e95671065f8692b5a4aa95c52dc7a02a4c5a0cac46deb879a017a2"}, + {file = "zstandard-0.25.0-cp314-cp314-win_arm64.whl", hash = "sha256:d7541afd73985c630bafcd6338d2518ae96060075f9463d7dc14cfb33514383d"}, + {file = "zstandard-0.25.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b9af1fe743828123e12b41dd8091eca1074d0c1569cc42e6e1eee98027f2bbd0"}, + {file = "zstandard-0.25.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b14abacf83dfb5c25eb4e4a79520de9e7e205f72c9ee7702f91233ae57d33a2"}, + {file = "zstandard-0.25.0-cp39-cp39-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:a51ff14f8017338e2f2e5dab738ce1ec3b5a851f23b18c1ae1359b1eecbee6df"}, + {file = "zstandard-0.25.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3b870ce5a02d4b22286cf4944c628e0f0881b11b3f14667c1d62185a99e04f53"}, + {file = "zstandard-0.25.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:05353cef599a7b0b98baca9b068dd36810c3ef0f42bf282583f438caf6ddcee3"}, + {file = "zstandard-0.25.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:19796b39075201d51d5f5f790bf849221e58b48a39a5fc74837675d8bafc7362"}, + {file = "zstandard-0.25.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:53e08b2445a6bc241261fea89d065536f00a581f02535f8122eba42db9375530"}, + {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1f3689581a72eaba9131b1d9bdbfe520ccd169999219b41000ede2fca5c1bfdb"}, + {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d8c56bb4e6c795fc77d74d8e8b80846e1fb8292fc0b5060cd8131d522974b751"}, + {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:53f94448fe5b10ee75d246497168e5825135d54325458c4bfffbaafabcc0a577"}, + {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c2ba942c94e0691467ab901fc51b6f2085ff48f2eea77b1a48240f011e8247c7"}, + {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:07b527a69c1e1c8b5ab1ab14e2afe0675614a09182213f21a0717b62027b5936"}, + {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:51526324f1b23229001eb3735bc8c94f9c578b1bd9e867a0a646a3b17109f388"}, + {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89c4b48479a43f820b749df49cd7ba2dbc2b1b78560ecb5ab52985574fd40b27"}, + {file = "zstandard-0.25.0-cp39-cp39-win32.whl", hash = "sha256:1cd5da4d8e8ee0e88be976c294db744773459d51bb32f707a0f166e5ad5c8649"}, + {file = "zstandard-0.25.0-cp39-cp39-win_amd64.whl", hash = "sha256:37daddd452c0ffb65da00620afb8e17abd4adaae6ce6310702841760c2c26860"}, + {file = "zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b"}, +] + +[package.extras] +cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and python_version < \"3.14\"", "cffi (>=2.0.0b) ; platform_python_implementation != \"PyPy\" and python_version >= \"3.14\""] + [extras] +async-rl = ["TransferQueue", "math-verify", "ray", "swanlab", "vllm"] +client = ["httpx", "openai", "plotext", "textual", "tinker"] +data = ["py-data-juicer"] docs = ["docutils", "myst_parser", "recommonmark", "sphinx", "sphinx-book-theme", "sphinx-copybutton", "sphinx-rtd-theme", "sphinx_markdown_tables", "sphinxcontrib-mermaid"] -kernels = ["kernels"] -megatron = ["megatron-core", "transformer-engine"] -ray = ["ray"] -tinker = ["tinker"] -transformers = ["accelerate", "torch", "torchvision"] -vllm = ["vllm"] +eval = ["evalscope"] +megatron = ["mcore_bridge", "megatron-core", "transformer-engine"] +rl = ["ray", "vllm"] +server = ["opentelemetry-api", "opentelemetry-exporter-otlp", "opentelemetry-instrumentation-logging", "opentelemetry-sdk", "psutil", "pynvml", "redis"] +test = ["hypothesis", "pytest", "pytest-asyncio"] [metadata] lock-version = "2.1" -python-versions = ">=3.11,<3.13" -content-hash = "6bc839d412edaa773717488aaf25cb1e5b663f305e3f9945d9f92fe1524160d2" +python-versions = ">=3.10,<=3.13" +content-hash = "2d8b26118c2aa4ef455e5e6983c89df8abc28279fb59146b867ccb9d31441b02" diff --git a/pyproject.toml b/pyproject.toml index 4b52c9c9..3641f275 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ client = [ "plotext>=5.2.0", "openai>=1.0.0", "httpx>=0.25.0", - "tinker==0.16.1", + "tinker==0.29.0; python_version >= '3.11'", ] server = [ "redis>=5.0", diff --git a/src/twinkle/infra/__init__.py b/src/twinkle/infra/__init__.py index 2cf7c148..6d6ae8d0 100644 --- a/src/twinkle/infra/__init__.py +++ b/src/twinkle/infra/__init__.py @@ -10,7 +10,7 @@ from twinkle.notifier import Notifier, notify_exception from twinkle.utils import DeviceGroup, DeviceMesh, Platform, check_unsafe, framework_util, get_logger, requires -from .collectors import collect_tensor_dict +from .collectors import collect_tensor_dict as collect_tensor_dict logger = get_logger() @@ -530,7 +530,7 @@ def _run_continous_work(self, func_name: str, execute_method, workers, args, kwa try: ordered: List[Any] = [None] * batch_len for _, indices, ref in submitted: - part = ray.get(ref, timeout=ray_get_timeout) if ray_get_timeout else ray.get(ref) + part = ray.get(ref, timeout=ray_get_timeout) if ray_get_timeout is not None else ray.get(ref) if not isinstance(part, (list, tuple)) or len(part) != len(indices): raise TypeError(f'{func_name}: enable_continous_work needs one result per request, but a worker given ' f'{len(indices)} request(s) returned {type(part).__name__} of length ' @@ -740,7 +740,6 @@ def _get_device_mesh_param(args, kwargs): def _prepare_lazy_collect(args, kwargs): # if a worker received an actor handle, # lazy collect should be false to prevent any outer function receives an object ref - from ._ray import RayHelper if not os.environ.get('WORKER_NAME'): # If this is a driver return args, kwargs diff --git a/src/twinkle/server/gateway/tinker_handlers.py b/src/twinkle/server/gateway/tinker_handlers.py index 9ef98ce1..af2e8adb 100644 --- a/src/twinkle/server/gateway/tinker_handlers.py +++ b/src/twinkle/server/gateway/tinker_handlers.py @@ -19,6 +19,7 @@ from twinkle.hub import HubOperation from twinkle.server.checkpoint import create_checkpoint_manager, create_training_run_manager +from twinkle.server.utils.task_errors import error_payload_from_stored from twinkle.server.utils.task_queue import QueueState from twinkle.server.utils.validation import get_token_from_request from twinkle.utils.logger import get_logger @@ -119,8 +120,8 @@ async def retrieve_future(request: Request, } if status == 'failed': - result = record.get('result', {}) - return {'error': result.get('error', 'Unknown error'), 'category': result.get('category', 'Server')} + payload = error_payload_from_stored(record.get('result'), request_id=request_id) + return payload.model_dump(mode='json', exclude_none=True) result = record.get('result') if result is None: diff --git a/src/twinkle/server/model/app.py b/src/twinkle/server/model/app.py index 545f5a45..0b73cbc6 100644 --- a/src/twinkle/server/model/app.py +++ b/src/twinkle/server/model/app.py @@ -7,7 +7,8 @@ """ from __future__ import annotations -from fastapi import FastAPI, Request +import asyncio +from fastapi import FastAPI, HTTPException, Request from ray import serve from ray.serve.config import RequestRouterConfig from typing import Any @@ -131,30 +132,18 @@ async def __init__(self, from twinkle.server.data_plane import DataPlaneProxy self.data_plane = DataPlaneProxy(data_plane_url) self._replica_registered = False - # Health status bit, set when a post-timeout probe finds the model actor - # unreachable; auto-cleared by the next successful probe (R3#3). self._model_unhealthy = False + self._health_probe_task = None - # Initialize mixins - # ModelManagement opts into the Admission_Gate (collective mis-pairing + - # queue-bypassing _cleanup_adapter); SamplerManagement does not. + actors = getattr(self.model, '_actors', None) self._init_task_queue( queue_config, deployment_name='Model', enable_admission_gate=True, - on_backend_timeout=self._probe_after_timeout) - # Bound every ray.get on this backend by the effective execution timeout - # (applies to both sync=True and sync=False dispatch). T4.1. - self.model._ray_get_timeout = self._task_queue_config.effective_execution_timeout - # Inject the execution bounds used by state hygiene to compute the absolute - # survival TTL for non-terminal future records (T5.3). Collect_Width = - # world_size = len(self._actors). - _actors = getattr(self.model, '_actors', None) - self.state.set_execution_bounds( - queue_timeout=self._task_queue_config.queue_timeout, - execution_timeout=self._task_queue_config.effective_execution_timeout, - collect_width=len(_actors) if _actors else 1, + on_backend_timeout=self._probe_after_timeout, + collect_width=len(actors) if actors else 1, ) + self.model._ray_get_timeout = self._task_queue_config.effective_execution_timeout self._init_adapter_manager(**(adapter_config or {})) await self._register_replica_on_startup() # Note: countdown task is started lazily in _ensure_sticky() @@ -173,6 +162,7 @@ async def _register_replica_on_startup(self) -> None: """Register this replica's capacity before Ray Serve marks it ready.""" if not self._replica_registered: await self.state.register_replica(self.replica_id, self.max_loras) + await self.state.touch_replica_last_seen(self.replica_id) self._replica_registered = True @serve.multiplexed(max_num_models_per_replica=5) @@ -189,8 +179,9 @@ async def _on_request_start(self, request: Request) -> str: await self._ensure_sticky() await self.state.touch_replica_last_seen(self.replica_id) await self._ensure_state_cleanup_started() - token = get_token_from_request(request) - return token + if self._model_unhealthy: + raise HTTPException(status_code=503, detail='Model actors are unavailable') + return get_token_from_request(request) async def shutdown(self) -> None: """Explicit async cleanup — called via FastAPI shutdown event.""" @@ -198,18 +189,10 @@ async def shutdown(self) -> None: await self.state.unregister_replica(self.replica_id) except Exception: pass + await self.shutdown_task_queue() await self.data_plane.close() - async def check_model_health(self) -> dict: - """Probe model actors liveness via a lightweight ping. - - Returns a dict with 'healthy' (bool) and 'detail' (str). A successful probe - clears the unhealthy status bit; a failed probe sets it (R3#3). - - The ping goes through the Blocking_Call_Boundary with ``admit=False`` so it - never blocks the event loop yet never queues behind the Admission_Gate -- - the moment a probe matters most is while a call is stuck holding the gate. - """ + async def _run_model_health_probe(self) -> dict: try: result = await self.call_backend(self.model.ping, admit=False) if result is True: @@ -221,6 +204,13 @@ async def check_model_health(self) -> dict: self._model_unhealthy = True return {'healthy': False, 'detail': f'model actor unreachable: {e}'} + async def check_model_health(self) -> dict: + """Run one coalesced actor probe outside the event loop.""" + current = getattr(self, '_health_probe_task', None) + if current is None or current.done(): + self._health_probe_task = asyncio.create_task(self._run_model_health_probe()) + return await asyncio.shield(self._health_probe_task) + def mark_unhealthy(self) -> None: """Flag the deployment unhealthy; /healthz returns 503 until a probe recovers it.""" self._model_unhealthy = True @@ -232,7 +222,6 @@ async def _probe_after_timeout(self) -> None: async def _cleanup_adapter(self, adapter_name: str) -> None: if self.get_resource_info(adapter_name): - self.clear_resource_state(adapter_name) if self.train_mode == 'full': # No PEFT adapter to remove; restore clean base weights so the # next tenant does not inherit this tenant's trained weights. @@ -242,6 +231,7 @@ async def _cleanup_adapter(self, adapter_name: str) -> None: await self.call_backend(self.model.reload_initial_weights) else: await self.call_backend(self.model.remove_adapter, adapter_name) + self.clear_resource_state(adapter_name) self.unregister_resource(adapter_name) await self.state.unload_model(adapter_name) diff --git a/src/twinkle/server/model/backends/megatron_model.py b/src/twinkle/server/model/backends/megatron_model.py index fb3da3f2..15dd3470 100644 --- a/src/twinkle/server/model/backends/megatron_model.py +++ b/src/twinkle/server/model/backends/megatron_model.py @@ -11,7 +11,6 @@ """ import torch from tinker import types -from typing import TYPE_CHECKING, Any, List, Optional, Tuple, Union from twinkle import remote_class, remote_function from twinkle.data_format import InputFeature, Trajectory @@ -135,7 +134,7 @@ def forward_backward(self, *, inputs: InputFeature | list[InputFeature] | Trajec output = super().forward_backward(inputs=inputs, **kwargs) return to_cpu_safe_output(output) - @remote_function(collect='first', lazy_collect=False, timeout=10) + @remote_function(collect='first', lazy_collect=False, sync=True, timeout=4) def ping(self) -> bool: """Lightweight liveness probe for watchdog health checks.""" return True diff --git a/src/twinkle/server/model/backends/mock_model.py b/src/twinkle/server/model/backends/mock_model.py index b6a79bd3..c9bc12ff 100644 --- a/src/twinkle/server/model/backends/mock_model.py +++ b/src/twinkle/server/model/backends/mock_model.py @@ -240,7 +240,7 @@ def remove_adapter(self, adapter_name: str) -> None: def has_adapter(self, adapter_name: str) -> bool: return adapter_name in self._adapters - @remote_function(collect='first', lazy_collect=False, timeout=10) + @remote_function(collect='first', lazy_collect=False, sync=True, timeout=4) def ping(self) -> bool: """Lightweight liveness probe for watchdog health checks.""" return True diff --git a/src/twinkle/server/model/backends/transformers_model.py b/src/twinkle/server/model/backends/transformers_model.py index a2bcba83..ff709a69 100644 --- a/src/twinkle/server/model/backends/transformers_model.py +++ b/src/twinkle/server/model/backends/transformers_model.py @@ -13,7 +13,6 @@ (InputFeature/Trajectory-based I/O) via /twinkle/* endpoints. """ from tinker import types -from typing import List, Union from twinkle import remote_class, remote_function from twinkle.data_format import InputFeature, Trajectory @@ -111,7 +110,7 @@ def forward_backward(self, *, inputs: InputFeature | list[InputFeature] | Trajec output = super().forward_backward(inputs=inputs, **kwargs) return to_cpu_safe_output(output) - @remote_function(collect='first', lazy_collect=False, timeout=10) + @remote_function(collect='first', lazy_collect=False, sync=True, timeout=4) def ping(self) -> bool: """Lightweight liveness probe for watchdog health checks.""" return True diff --git a/src/twinkle/server/model/tinker_handlers.py b/src/twinkle/server/model/tinker_handlers.py index 7f34c2ae..d868a0d2 100644 --- a/src/twinkle/server/model/tinker_handlers.py +++ b/src/twinkle/server/model/tinker_handlers.py @@ -10,9 +10,8 @@ import traceback from collections.abc import Callable from fastapi import Depends, FastAPI, Request -from peft import LoraConfig from tinker import types -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING if TYPE_CHECKING: from .app import ModelManagement @@ -20,6 +19,7 @@ from twinkle.server.checkpoint import create_checkpoint_manager, create_training_run_manager from twinkle.server.exceptions import FullModeBusyError from twinkle.server.utils import get_template_for_model +from twinkle.server.utils.task_queue.types import UserTaskError from twinkle.utils.logger import get_logger logger = get_logger() @@ -45,17 +45,11 @@ async def _create_adapter(): try: # Validate lora_config against the deployment's train_mode up front. if self.is_full_mode and body.lora_config: - return types.RequestFailedResponse( - error='This deployment runs in full-parameter (exclusive) mode; do not pass ' - 'lora_config. Use create_full_training_client (or omit lora_config).', - category=types.RequestErrorCategory.User, - ) + raise UserTaskError('This deployment runs in full-parameter (exclusive) mode; do not pass ' + 'lora_config. Use create_full_training_client (or omit lora_config).') if (not self.is_full_mode) and (not body.lora_config): - return types.RequestFailedResponse( - error='This deployment runs in LoRA mode; lora_config is required. ' - 'Use create_lora_training_client.', - category=types.RequestErrorCategory.User, - ) + raise UserTaskError('This deployment runs in LoRA mode; lora_config is required. ' + 'Use create_lora_training_client.') # Exclusive full-parameter training: reject early (before touching # state) if another tenant already holds the deployment. if self.is_full_mode: @@ -75,7 +69,7 @@ async def _create_adapter(): await self.call_backend(self.model.set_optimizer, 'Adam', adapter_name=model_adapter) self.set_resource_state(adapter_name, 'grad_ready', False) else: - # TODO: Make LoraConfig more flexible + from peft import LoraConfig lora_cfg = LoraConfig(r=body.lora_config.rank, target_modules='all-linear') self.register_resource(adapter_name, token, session_id=body.session_id) await self.call_backend( @@ -89,17 +83,13 @@ async def _create_adapter(): training_run_manager.save(_model_id, body) return types.CreateModelResponse(model_id=_model_id) except FullModeBusyError as e: - # Nothing was registered yet (check runs before register_model). - return types.RequestFailedResponse(error=str(e), category=types.RequestErrorCategory.User) + raise UserTaskError(str(e)) from e except Exception: if _model_id: adapter_name = self.get_adapter_name(adapter_name=_model_id) await self._cleanup_adapter(adapter_name) logger.error(traceback.format_exc()) - return types.RequestFailedResponse( - error=traceback.format_exc(), - category=types.RequestErrorCategory.Server, - ) + raise return await self.schedule_task(_create_adapter, token=token, task_type='create_model') @@ -159,10 +149,7 @@ async def _do_forward(): ) except Exception: logger.error(traceback.format_exc()) - return types.RequestFailedResponse( - error=traceback.format_exc(), - category=types.RequestErrorCategory.Server, - ) + raise datum_list = body.forward_input.data input_tokens = sum(len(d.model_input.to_ints()) for d in datum_list) @@ -209,10 +196,7 @@ async def _do_forward_backward(): ) except Exception: logger.error(traceback.format_exc()) - return types.RequestFailedResponse( - error=traceback.format_exc(), - category=types.RequestErrorCategory.Server, - ) + raise datum_list = body.forward_backward_input.data input_tokens = sum(len(d.model_input.to_ints()) for d in datum_list) @@ -253,10 +237,7 @@ async def _do_optim(): return types.OptimStepResponse(metrics=metrics) except Exception: logger.error(traceback.format_exc()) - return types.RequestFailedResponse( - error=traceback.format_exc(), - category=types.RequestErrorCategory.Server, - ) + raise return await self.schedule_task(_do_optim, model_id=body.model_id, token=token, task_type='optim_step') @@ -286,10 +267,7 @@ async def _do_save(): return types.SaveWeightsResponse(path=tinker_path, type='save_weights') except Exception: logger.error(traceback.format_exc()) - return types.RequestFailedResponse( - error=traceback.format_exc(), - category=types.RequestErrorCategory.Server, - ) + raise return await self.schedule_task(_do_save, model_id=body.model_id, token=token, task_type='save_weights') @@ -334,10 +312,7 @@ async def _do_save_for_sampler(): path=tinker_path, sampling_session_id=sampling_session_id) except Exception: logger.error(traceback.format_exc()) - return types.RequestFailedResponse( - error=traceback.format_exc(), - category=types.RequestErrorCategory.Server, - ) + raise return await self.schedule_task( _do_save_for_sampler, model_id=body.model_id, token=token, task_type='save_weights_for_sampler') @@ -365,9 +340,6 @@ async def _do_load(): return types.LoadWeightsResponse(path=body.path, type='load_weights') except Exception: logger.error(traceback.format_exc()) - return types.RequestFailedResponse( - error=traceback.format_exc(), - category=types.RequestErrorCategory.Server, - ) + raise return await self.schedule_task(_do_load, model_id=body.model_id, token=token, task_type='load_weights') diff --git a/src/twinkle/server/model/twinkle_handlers.py b/src/twinkle/server/model/twinkle_handlers.py index 01eadbe6..c743c5d3 100644 --- a/src/twinkle/server/model/twinkle_handlers.py +++ b/src/twinkle/server/model/twinkle_handlers.py @@ -8,13 +8,11 @@ """ from __future__ import annotations -import asyncio import torch import traceback from collections.abc import Callable from fastapi import Depends, FastAPI, HTTPException, Request from pathlib import Path -from peft import LoraConfig from typing import TYPE_CHECKING, Any if TYPE_CHECKING: @@ -29,7 +27,6 @@ select_output_rows) from twinkle.server.utils.validation import get_session_id_from_request from twinkle.utils.logger import get_logger -from twinkle_client.common.serialize import deserialize_object logger = get_logger() @@ -620,11 +617,7 @@ async def _task(): checkpoint_manager.get_ckpt_dir(model_id=model_id_to_load, checkpoint_id=checkpoint_id)) else: checkpoint_dir = body.checkpoint_dir - # Run blocking upload in thread pool so the event loop is not blocked. - # async_upload is intentionally ignored here: the task queue + client polling - # already provide the fire-and-forget / wait semantics without holding the - # HTTP connection open for the full duration of the upload. - await asyncio.to_thread( + await self.call_backend( self.model.upload_to_hub, checkpoint_dir=checkpoint_dir, hub_model_id=body.hub_model_id, @@ -672,6 +665,9 @@ async def add_adapter_to_model( raise HTTPException(status_code=400, detail=str(exc)) async def _task(): + from peft import LoraConfig + + from twinkle_client.common.serialize import deserialize_object config = deserialize_object(body.config) extra_kwargs = body.model_extra or {} training_run_manager = create_training_run_manager(token, client_type='twinkle') @@ -735,6 +731,7 @@ async def apply_patch( adapter_name = _get_twinkle_adapter_name(request, body.adapter_name) async def _task(): + from twinkle_client.common.serialize import deserialize_object self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} patch_cls = deserialize_object(body.patch_cls) @@ -756,6 +753,7 @@ async def add_metric( adapter_name = _get_twinkle_adapter_name(request, body.adapter_name) async def _task(): + from twinkle_client.common.serialize import deserialize_object self.assert_resource_exists(adapter_name) extra_kwargs = body.model_extra or {} metric_cls = deserialize_object(body.metric_cls) diff --git a/src/twinkle/server/processor/twinkle_handlers.py b/src/twinkle/server/processor/twinkle_handlers.py index d9da305b..e8f8792c 100644 --- a/src/twinkle/server/processor/twinkle_handlers.py +++ b/src/twinkle/server/processor/twinkle_handlers.py @@ -23,7 +23,6 @@ from twinkle.server.telemetry.tracing import traced_operation from twinkle.server.utils.validation import get_session_id_from_request, get_token_from_request from twinkle.utils.logger import get_logger -from twinkle_client.common.serialize import deserialize_object logger = get_logger() @@ -61,6 +60,7 @@ async def create( _kwargs.pop('remote_group', None) _kwargs.pop('device_mesh', None) + from twinkle_client.common.serialize import deserialize_object resolved_kwargs = {} for key, value in _kwargs.items(): if isinstance(value, str) and value.startswith('pid:'): @@ -107,6 +107,7 @@ async def call( assert function is not None, f'`{function_name}` not found in {processor.__class__}' assert hasattr(function, '_execute'), f'Cannot call inner method of {processor.__class__}' + from twinkle_client.common.serialize import deserialize_object resolved_kwargs = {} for key, value in _kwargs.items(): if isinstance(value, str) and value.startswith('pid:'): diff --git a/src/twinkle/server/sampler/app.py b/src/twinkle/server/sampler/app.py index 892a66bd..3e7d0145 100644 --- a/src/twinkle/server/sampler/app.py +++ b/src/twinkle/server/sampler/app.py @@ -7,7 +7,6 @@ """ from __future__ import annotations -import asyncio from fastapi import FastAPI, Request from ray import serve from typing import Any @@ -103,12 +102,12 @@ def __init__(self, self.sampler_type = sampler_type self.model_id = model_id replica_context = serve.get_replica_context() - replica_id = replica_context.replica_id.unique_id + self.replica_id = replica_context.replica_id.unique_id sampler_kwargs: dict[str, Any] = { 'model_id': model_id, 'remote_group': self.device_group.name, - 'instance_id': replica_id, + 'instance_id': self.replica_id, } if sampler_type != 'mock': sampler_kwargs.update( @@ -127,17 +126,25 @@ def __init__(self, from twinkle.server.data_plane import DataPlaneProxy self.data_plane = DataPlaneProxy(data_plane_url) - # Initialize task queue mixin - self._init_task_queue(queue_config, deployment_name='Sampler') - # Bound every ray.get on this backend by the effective execution timeout - # (applies to both sync=True and sync=False dispatch). T4.1. + actors = getattr(self.sampler, '_actors', None) + self._init_task_queue( + queue_config, + deployment_name='Sampler', + collect_width=len(actors) if actors else 1, + ) self.sampler._ray_get_timeout = self._task_queue_config.effective_execution_timeout async def shutdown(self) -> None: - cancel_all = getattr(self.sampler, 'cancel_all_generations', None) - if callable(cancel_all): - await asyncio.to_thread(cancel_all) - await self.data_plane.close() + try: + cancel_all = getattr(self.sampler, 'cancel_all_generations', None) + if callable(cancel_all): + await self.call_backend(cancel_all) + finally: + try: + await self.state.unregister_replica(self.replica_id) + finally: + await self.shutdown_task_queue() + await self.data_plane.close() @serve.multiplexed(max_num_models_per_replica=5) async def _sticky_entry(self, sticky_key: str): @@ -149,9 +156,9 @@ async def _ensure_sticky(self): async def _on_request_start(self, request: Request) -> str: await self._ensure_sticky() + await self.state.touch_replica_last_seen(self.replica_id) await self._ensure_state_cleanup_started() - token = get_token_from_request(request) - return token + return get_token_from_request(request) def build_sampler_app(model_id: str, diff --git a/src/twinkle/server/sampler/tinker_handlers.py b/src/twinkle/server/sampler/tinker_handlers.py index 921e4fdc..02cef849 100644 --- a/src/twinkle/server/sampler/tinker_handlers.py +++ b/src/twinkle/server/sampler/tinker_handlers.py @@ -8,6 +8,7 @@ import os import traceback +import uuid from collections.abc import Callable from fastapi import Depends, FastAPI, Request from tinker import types @@ -19,11 +20,29 @@ from twinkle.data_format import SamplingParams from twinkle.server.checkpoint import create_checkpoint_manager from twinkle.server.utils import get_template_for_model +from twinkle.server.utils.task_queue.types import UserTaskError from twinkle.utils.logger import get_logger logger = get_logger() +def _sampled_sequence(*, stop_reason, tokens, logprobs): + return types.SampledSequence( + stop_reason=stop_reason, + sequence_id=uuid.uuid4().hex, + _tokens_list=tokens, + _logprobs_list=logprobs, + ) + + +def _sample_response(*, sequences, prompt_logprobs, topk_prompt_logprobs): + return types.SampleResponse( + sequences=sequences, + _prompt_logprobs_list=prompt_logprobs, + _topk_prompt_logprobs_list=topk_prompt_logprobs, + ) + + def _register_tinker_sampler_routes(app: FastAPI, self_fn: Callable[[], SamplerManagement]) -> None: """Register the tinker sampler route on the given FastAPI app. @@ -71,10 +90,7 @@ async def _do_sample(): # Base-model sampling is valid when no model_path was provided. if adapter_uri and not os.path.exists(adapter_uri): - return types.RequestFailedResponse( - error=f'Adapter URI {model_path} does not exist. Please check the model_path.', - category=types.RequestErrorCategory.User, - ) + raise UserTaskError(f'Adapter URI {model_path} does not exist. Please check the model_path.') # Convert tinker SamplingParams to twinkle SamplingParams if needed sampling_params = None @@ -120,22 +136,19 @@ async def _do_sample(): if flattened and len(flattened) == len(seq.logprobs): logprobs = flattened tinker_sequences.append( - types.SampledSequence( + _sampled_sequence( stop_reason=seq.stop_reason, tokens=list(seq.tokens), logprobs=logprobs, )) - return types.SampleResponse( + return _sample_response( sequences=tinker_sequences, prompt_logprobs=responses[0].prompt_logprobs, topk_prompt_logprobs=responses[0].topk_prompt_logprobs, ) except Exception: logger.error(traceback.format_exc()) - return types.RequestFailedResponse( - error=traceback.format_exc(), - category=types.RequestErrorCategory.Server, - ) + raise input_tokens = len(body.prompt.to_ints()) return await self.schedule_task( diff --git a/src/twinkle/server/sampler/twinkle_handlers.py b/src/twinkle/server/sampler/twinkle_handlers.py index 22515b4e..c5428b05 100644 --- a/src/twinkle/server/sampler/twinkle_handlers.py +++ b/src/twinkle/server/sampler/twinkle_handlers.py @@ -15,8 +15,6 @@ from fastapi.responses import StreamingResponse from typing import TYPE_CHECKING -from twinkle_client.common.serialize import deserialize_object - if TYPE_CHECKING: from .app import SamplerManagement @@ -24,8 +22,9 @@ import twinkle_client.types as types from twinkle.data_format import InputFeature, SamplingParams, Trajectory -from twinkle.server.telemetry.correlation import MODEL_ID, TOKEN_ID +from twinkle.server.telemetry.correlation import MODEL_ID from twinkle.server.telemetry.tracing import traced_operation +from twinkle.server.utils.task_errors import task_error_payload from twinkle.server.utils.validation import get_session_id_from_request from twinkle.utils.logger import get_logger from twinkle_client.common.json_utils import json_safe @@ -132,31 +131,55 @@ def _submission_states(value) -> list[dict]: return value if isinstance(value, list) else [value] -async def _await_generation( - sampler, - submission_id: str, -): - """Poll an admitted generation without occupying the sampler admission queue.""" - collected = False +async def _stream_queue(q, sentinel, request_id: str, total_timeout: float, single_get_timeout: float = 60.0): + loop = asyncio.get_running_loop() + start = loop.time() try: + while True: + remaining = total_timeout - (loop.time() - start) + if remaining <= 0: + payload = task_error_payload( + 'sample_stream exceeded the execution time bound', request_id=request_id, error_code=504) + yield json.dumps(payload) + '\n' + break + try: + item = await asyncio.wait_for( + loop.run_in_executor(None, q.get), timeout=min(single_get_timeout, remaining)) + except asyncio.TimeoutError: + payload = task_error_payload( + 'sample_stream timed out waiting for the next token', request_id=request_id, error_code=504) + yield json.dumps(payload) + '\n' + break + if item == sentinel: + break + if isinstance(item, Exception): + payload = task_error_payload(f'{type(item).__name__}: {item}', request_id=request_id, error_code=500) + yield json.dumps(payload) + '\n' + break + delta, reason = item + yield json.dumps({'delta': delta, 'finish_reason': reason}) + '\n' + finally: + try: + q.shutdown(force=True) + except Exception: + pass + + +async def _await_generation(service: SamplerManagement, submission_id: str, timeout: float): + """Poll one admitted generation through the backend boundary.""" + collected = False + + async def poll(): + nonlocal collected poll_interval = 0.01 while True: try: - states = _submission_states(await asyncio.to_thread(sampler.get_generation_status, submission_id)) + states = _submission_states(await service.call_backend(service.sampler.get_generation_status, + submission_id)) except Exception as error: - # A pending read-only actor call can be cancelled by Ray while - # the generation submitted just above remains alive. Treating - # that as a generation failure makes the finally block discard - # otherwise valid rollout work. Retry only Ray's explicit task - # cancellation; actor death and application errors must still - # propagate immediately. from ray.exceptions import TaskCancelledError if not isinstance(error, TaskCancelledError): raise - logger.warning( - 'Generation status poll was cancelled; retrying submission %s', - submission_id, - ) await asyncio.sleep(poll_interval) poll_interval = min(poll_interval * 1.5, 0.25) continue @@ -168,15 +191,19 @@ async def _await_generation( error = failed.get('error') or failed.get('status', 'unknown failure') raise RuntimeError(f'generation {submission_id} failed: {error}') if states and all(state.get('status') == 'completed' for state in states): - responses = await asyncio.to_thread(sampler.collect_generation, submission_id) + responses = await service.call_backend(service.sampler.collect_generation, submission_id) collected = True return responses await asyncio.sleep(poll_interval) poll_interval = min(poll_interval * 1.5, 0.25) + + try: + return await asyncio.wait_for(poll(), timeout=timeout) finally: if not collected: try: - await asyncio.to_thread(sampler.cancel_generation, submission_id) + await asyncio.wait_for( + service.call_backend(service.sampler.cancel_generation, submission_id), timeout=4.0) except Exception: logger.warning('Failed to cancel generation %s', submission_id, exc_info=True) @@ -315,7 +342,7 @@ async def sample_to_data_plane( submission_id = uuid.uuid4().hex async def _admit(): - await asyncio.to_thread( + await self.call_backend( self.sampler.submit_generation, submission_id, inputs, @@ -338,7 +365,7 @@ async def _admit(): task_type='sample_admission', )) - responses = await _await_generation(self.sampler, submission_id) + responses = await _await_generation(self, submission_id, self._task_queue_config.effective_execution_timeout) rows, tags = _build_rollout_rows_and_tags( _to_sample_response_models(responses), group_ids=body.group_ids, @@ -368,7 +395,7 @@ async def unload_adapter_paths( resolved_paths.append(adapter_path) unload = getattr(self.sampler, 'unload_adapter_paths', None) if unload is not None: - unload(resolved_paths) + await self.call_backend(unload, resolved_paths) return {'status': 'ok'} @app.post('/twinkle/set_template', response_model=types.SetTemplateResponse) @@ -407,6 +434,7 @@ async def apply_patch( body: types.ApplyPatchRequest, self: SamplerManagement = Depends(self_fn), ) -> None: + from twinkle_client.common.serialize import deserialize_object extra_kwargs = body.model_extra or {} patch_cls = deserialize_object(body.patch_cls) with traced_operation('sampler.apply_patch'): @@ -465,14 +493,16 @@ async def sample_stream( from .backends import STREAM_SENTINEL - q = Queue(maxsize=128) + request_id = f'req_{uuid.uuid4().hex}' actors = self.sampler._actors if not actors: - # No available sampler actor -> structured error, not an IndexError (R4#12). + async def _no_actor_generator(): - yield json.dumps({'error': 'No available sampler actor', 'category': 'Server'}) + '\n' + payload = task_error_payload('No available sampler actor', request_id=request_id, error_code=503) + yield json.dumps(payload) + '\n' return StreamingResponse(_no_actor_generator(), media_type='application/x-ndjson') + q = Queue(maxsize=128) actor = actors[0] actor.sample_stream_to_queue.remote( q, @@ -482,45 +512,12 @@ async def _no_actor_generator(): adapter_path=adapter_path, ) - # Two time bounds (R4#10-11): a per-get bound and a total-lifetime bound. - single_get_timeout = 60.0 - total_timeout = self._task_queue_config.effective_execution_timeout - - async def _stream_generator(): - loop = asyncio.get_event_loop() - start = loop.time() - try: - while True: - remaining = total_timeout - (loop.time() - start) - if remaining <= 0: - yield json.dumps({ - 'error': 'sample_stream exceeded the execution time bound', - 'category': 'Server' - }) + '\n' - break - try: - item = await asyncio.wait_for( - loop.run_in_executor(None, q.get), timeout=min(single_get_timeout, remaining)) - except asyncio.TimeoutError: - yield json.dumps({ - 'error': 'sample_stream timed out waiting for the next token', - 'category': 'Server' - }) + '\n' - break - if item == STREAM_SENTINEL: - break - if isinstance(item, Exception): - yield json.dumps({'error': str(item)}) + '\n' - break - delta, reason = item - yield json.dumps({'delta': delta, 'finish_reason': reason}) + '\n' - finally: - # The run_in_executor(None, q.get) thread is NOT cancelled when - # wait_for times out; shutting the ray Queue down makes the blocked - # get() raise so the thread exits and the pool returns to baseline. - try: - q.shutdown(force=True) - except Exception: - pass - - return StreamingResponse(_stream_generator(), media_type='application/x-ndjson') + return StreamingResponse( + _stream_queue( + q, + STREAM_SENTINEL, + request_id, + self._task_queue_config.effective_execution_timeout, + ), + media_type='application/x-ndjson', + ) diff --git a/src/twinkle/server/state/future_manager.py b/src/twinkle/server/state/future_manager.py index 9d3b3a3c..3a9bd917 100644 --- a/src/twinkle/server/state/future_manager.py +++ b/src/twinkle/server/state/future_manager.py @@ -29,6 +29,7 @@ def _future_record_transform( queue_state: str | None, queue_state_reason: str | None, replica_id: str | None, + absolute_deadline: float | None, now: str, ) -> dict | None: """Atomic transform body for :meth:`FutureManager.store_status`. @@ -57,6 +58,7 @@ def _future_record_transform( queue_state=queue_state, queue_state_reason=queue_state_reason, replica_id=replica_id, + absolute_deadline=absolute_deadline, created_at=now, updated_at=now, ) @@ -79,10 +81,7 @@ def _future_record_transform( class FutureManager(BaseManager[FutureRecord]): - """Manages async task futures / request statuses. - - Expiry is based on `updated_at` (falls back to `created_at`). - """ + """Manage future state, terminal retention, and immutable task deadlines.""" def __init__(self, backend: StateBackend, expiration_timeout: float) -> None: super().__init__(backend, 'future::', FutureRecord, expiration_timeout) @@ -99,6 +98,7 @@ async def store_status( queue_state: str | None = None, queue_state_reason: str | None = None, replica_id: str | None = None, + absolute_deadline: float | None = None, ) -> None: """Create or update a future record with the latest status. @@ -125,6 +125,7 @@ async def store_status( queue_state=queue_state, queue_state_reason=queue_state_reason, replica_id=replica_id, + absolute_deadline=absolute_deadline, now=now, ), ) @@ -136,14 +137,13 @@ async def cleanup_expired( cutoff_time: float, *, alive_replica_ids: set[str] | None = None, - absolute_ttl: float | None = None, ) -> int: """Expire future records without ever deleting a non-terminal one. Processing matrix (design §5.2): - | status | replica alive | over absolute_ttl | action | - |--------------|---------------|-------------------|-------------------| + | status | replica alive | past deadline | action | + |--------------|---------------|---------------|-------------------| | Terminal | — | ts < cutoff | delete | | non-Terminal | yes | no | keep (untouched) | | non-Terminal | yes | yes | write ``failed`` | @@ -153,9 +153,6 @@ async def cleanup_expired( cutoff_time: Unix timestamp; terminal records older than it are deleted. alive_replica_ids: replicas currently considered alive. ``None`` disables the orphan check (every non-terminal record is treated as owned). - absolute_ttl: seconds; a non-terminal record whose ``created_at`` is older - than this (regardless of ``updated_at``) is failed. ``None`` disables - the absolute-survival bound. Returns: Number of terminal records removed (records written ``failed`` are not @@ -188,20 +185,21 @@ async def cleanup_expired( replica_id=replica_id, ) continue - if absolute_ttl is not None: - created = self._parse_timestamp(record.created_at) - if (now - created) > absolute_ttl: - await self.store_status( - request_id, - 'failed', - record.model_id, - result=task_error_payload( - 'Task exceeded the absolute survival bound without reaching a terminal state.', - request_id=request_id, - error_code=500, - ), - replica_id=replica_id, - ) + deadline = record.absolute_deadline + if deadline is None: + deadline = self._parse_timestamp(record.created_at) + self.expiration_timeout + if now > deadline: + await self.store_status( + request_id, + 'failed', + record.model_id, + result=task_error_payload( + 'Task exceeded the absolute survival bound without reaching a terminal state.', + request_id=request_id, + error_code=500, + ), + replica_id=replica_id, + ) for request_id in expired_ids: await self.remove(request_id) diff --git a/src/twinkle/server/state/model_manager.py b/src/twinkle/server/state/model_manager.py index f4ccf034..58edf59b 100644 --- a/src/twinkle/server/state/model_manager.py +++ b/src/twinkle/server/state/model_manager.py @@ -118,9 +118,9 @@ async def get_alive_replica_ids(self, liveness_threshold: float) -> set[str]: last_seen = await self._replicas.get_all_last_seen() now = time.time() alive: set[str] = set() - for rid in registered: + for rid in set(registered) | set(last_seen): ls = last_seen.get(rid) - if ls is None or (now - ls) <= liveness_threshold: + if (ls is None and rid in registered) or (ls is not None and (now - ls) <= liveness_threshold): alive.add(rid) return alive diff --git a/src/twinkle/server/state/models.py b/src/twinkle/server/state/models.py index d3d3133b..7b11813a 100644 --- a/src/twinkle/server/state/models.py +++ b/src/twinkle/server/state/models.py @@ -56,9 +56,8 @@ class FutureRecord(BaseModel): result: Any = None queue_state: str | None = None queue_state_reason: str | None = None - # Replica that produced the record; filled at creation and never overwritten by a - # later status update. ``None`` (pre-upgrade record) means "ownership unknown" and - # is only subject to the absolute survival bound (see FutureManager.cleanup_expired). + # Replica ownership and deadline are fixed when the record is created. replica_id: str | None = None + absolute_deadline: float | None = None created_at: str = Field(default_factory=_now_iso) updated_at: str = Field(default_factory=_now_iso) diff --git a/src/twinkle/server/state/replica_registry.py b/src/twinkle/server/state/replica_registry.py index d287c1d0..d3eda8d8 100644 --- a/src/twinkle/server/state/replica_registry.py +++ b/src/twinkle/server/state/replica_registry.py @@ -1,15 +1,8 @@ # Copyright (c) ModelScope Contributors. All rights reserved. -"""Backend-backed registry of replica capacity. +"""Backend-backed registry of replica capacity and liveness. -Each entry persists to ``replica::::max_loras`` in the configured -:class:`StateBackend` (Redis or the actor-wrapped RayActorBackend), so every -Ray Serve worker sees one consistent view of the cluster's capacity even -though each worker holds its own ``ServerState`` instance. - -The registry knows *only* about declared capacity. The current loaded-model -count is derived by querying the persisted ``model::*`` records directly — -nothing here caches that count, so concurrent writes from different workers -cannot drift into an inconsistent local index. +Capacity and ``last_seen`` use separate keys so sampler liveness does not alter +the model-capacity data shape. """ from __future__ import annotations @@ -37,7 +30,7 @@ def _replica_id_from_key(key: str) -> str | None: class ReplicaRegistry: - """Read/write replica capacity through the shared :class:`StateBackend`.""" + """Read/write replica capacity and liveness through the shared backend.""" def __init__(self, backend: StateBackend) -> None: self._backend = backend diff --git a/src/twinkle/server/state/server_state.py b/src/twinkle/server/state/server_state.py index e59b215d..fc8014a0 100644 --- a/src/twinkle/server/state/server_state.py +++ b/src/twinkle/server/state/server_state.py @@ -39,10 +39,6 @@ LEASE_TTL = 30 # seconds — leader loses the lease after this without a renew LEASE_RENEW = 10 # seconds — must be < LEASE_TTL/2 so two missed renews still beat the TTL -# Integer multiple of (queue_timeout + resource-release bound) used as the absolute -# survival bound for a non-terminal record; the margin absorbs scheduling slack. -_ABSOLUTE_TTL_MULTIPLIER = 2 - def _renew_if_owner(current: str | None, *, owner: str) -> str | None: """``update_atomic`` transform: only re-write the lease if it is still mine.""" @@ -91,13 +87,6 @@ def __init__( self._cleanup_task: asyncio.Task | None = None self._cleanup_running = False - # Execution bounds injected by ModelManagement after _init_task_queue - # (see set_execution_bounds). Used to compute the absolute survival bound - # for non-terminal future records. All None => absolute bound disabled. - self._queue_timeout: float | None = None - self._effective_execution_timeout: float | None = None - self._collect_width: int | None = None - # Leader election + metrics-publish loop state. ``metrics_update_interval`` # is a typed parameter (a misspelled key now fails loudly rather than # being silently ignored); it controls how often the leader pushes counts @@ -301,6 +290,7 @@ async def store_future_status( queue_state: str | None = None, queue_state_reason: str | None = None, replica_id: str | None = None, + absolute_deadline: float | None = None, ) -> None: """Store task status with optional result. @@ -330,6 +320,7 @@ async def store_future_status( queue_state=queue_state, queue_state_reason=queue_state_reason, replica_id=replica_id, + absolute_deadline=absolute_deadline, ) # ----- Configuration Management ----- @@ -384,14 +375,8 @@ async def cleanup_expired_resources(self) -> dict[str, int]: samplings_removed = await self._sampling_mgr.cleanup_expired( cutoff_time, expired_session_ids=expired_session_ids) - # State hygiene for future records (design §5.2): protect non-terminal - # records owned by a live replica, fail orphans, and enforce the absolute - # survival bound. Alive set comes from ReplicaRegistry; absolute_ttl is - # computed only when the execution bounds were injected. alive_replica_ids = await self._model_mgr.get_alive_replica_ids(self.expiration_timeout) - absolute_ttl = self._absolute_survival_ttl() - futures_removed = await self._future_mgr.cleanup_expired( - cutoff_time, alive_replica_ids=alive_replica_ids, absolute_ttl=absolute_ttl) + futures_removed = await self._future_mgr.cleanup_expired(cutoff_time, alive_replica_ids=alive_replica_ids) return { 'sessions': sessions_removed, @@ -400,24 +385,6 @@ async def cleanup_expired_resources(self) -> dict[str, int]: 'futures': futures_removed, } - def set_execution_bounds(self, *, queue_timeout: float, execution_timeout: float, collect_width: int) -> None: - """Inject the execution bounds used to compute the absolute survival TTL. - - Called by ModelManagement after ``_init_task_queue``. ``ServerState`` is a - shared instance obtained via ``get_server_state()``, so these cannot be - constructor arguments; a setter is the injection path (design §5.2). - """ - self._queue_timeout = queue_timeout - self._effective_execution_timeout = execution_timeout - self._collect_width = collect_width - - def _absolute_survival_ttl(self) -> float | None: - """``k * (queue_timeout + Collect_Width * T)`` or ``None`` if not injected.""" - if (self._queue_timeout is None or self._effective_execution_timeout is None or self._collect_width is None): - return None - resource_release_bound = self._collect_width * self._effective_execution_timeout - return _ABSOLUTE_TTL_MULTIPLIER * (self._queue_timeout + resource_release_bound) - async def touch_replica_last_seen(self, replica_id: str) -> None: """Refresh a replica's liveness timestamp in the shared registry (R4#6).""" await self._model_mgr.touch_replica_last_seen(replica_id) diff --git a/src/twinkle/server/utils/task_errors.py b/src/twinkle/server/utils/task_errors.py index 7e977cf1..031f71cf 100644 --- a/src/twinkle/server/utils/task_errors.py +++ b/src/twinkle/server/utils/task_errors.py @@ -29,25 +29,27 @@ def task_error_payload( *, request_id: str, error_code: int = 500, - category: ErrorCategory = ErrorCategory.Server, + category: ErrorCategory | str = ErrorCategory.Server, traceback_text: str | None = None, ) -> dict[str, Any]: """Build an ``ErrorPayload`` and return it as a JSON-safe dict for storage. Traceback splitting and length trimming happen here so over-long text is never - written to State_Backend. A ``User`` category carries no traceback (R5#6). + written to State_Backend. A ``user`` category carries no traceback. """ - tb: str | None = None - if category != ErrorCategory.User and traceback_text: - tb = _trim_traceback(traceback_text) + if isinstance(category, str): + category = ErrorCategory(category.lower()) + tb = _trim_traceback(traceback_text) if category is ErrorCategory.Server and traceback_text else None + lines = str(error).splitlines() + summary = (lines[0] if lines else '')[:_ERROR_MAX] payload = ErrorPayload( - error=error[:_ERROR_MAX], + error=summary, category=category, error_code=error_code, request_id=request_id, traceback=tb, ) - return payload.model_dump(mode='json') + return payload.model_dump(mode='json', exclude_none=True) def error_payload_from_stored(stored: Any, *, request_id: str) -> ErrorPayload: @@ -58,8 +60,14 @@ def error_payload_from_stored(stored: Any, *, request_id: str) -> ErrorPayload: the caller-supplied value / ``Unknown`` so a rolling upgrade never raises ``pydantic.ValidationError``. """ - data = dict(stored) if isinstance(stored, Mapping) else {'error': str(stored)} + if isinstance(stored, Mapping): + data = dict(stored) + else: + data = {'error': 'Unknown error' if stored is None else str(stored)} data.setdefault('category', ErrorCategory.Unknown) data.setdefault('error_code', 500) data.setdefault('request_id', request_id) + category = str(data['category']).lower() + if category != ErrorCategory.Server.value: + data.pop('traceback', None) return ErrorPayload.model_validate(data) diff --git a/src/twinkle/server/utils/task_queue/__init__.py b/src/twinkle/server/utils/task_queue/__init__.py index 5c90d318..d77dfe18 100644 --- a/src/twinkle/server/utils/task_queue/__init__.py +++ b/src/twinkle/server/utils/task_queue/__init__.py @@ -12,12 +12,13 @@ from .config import TaskQueueConfig from .mixin import TaskQueueMixin from .rate_limiter import RateLimiter -from .types import QueuedTask, QueueState, TaskStatus +from .types import QueuedTask, QueueState, TaskStatus, UserTaskError from .worker import ComputeWorker __all__ = [ 'TaskStatus', 'QueueState', + 'UserTaskError', 'QueuedTask', 'TaskQueueConfig', 'TaskQueueMixin', diff --git a/src/twinkle/server/utils/task_queue/config.py b/src/twinkle/server/utils/task_queue/config.py index fdeeaf28..4de98e0d 100644 --- a/src/twinkle/server/utils/task_queue/config.py +++ b/src/twinkle/server/utils/task_queue/config.py @@ -11,8 +11,10 @@ from pydantic import BaseModel, ConfigDict, Field -# Substituted when execution_timeout is left at 0 ("no configured limit"). +# Finite bounds used when configuration omits a limit and by long-running methods. _ZERO_EXECUTION_TIMEOUT_FALLBACK: float = 3600.0 +_MAX_DECLARED_BACKEND_TIMEOUT: float = 3600.0 +_ABSOLUTE_TTL_MULTIPLIER: int = 2 class TaskQueueConfig(BaseModel): @@ -57,3 +59,9 @@ def effective_execution_timeout(self) -> float: if self.execution_timeout > 0: return self.execution_timeout return _ZERO_EXECUTION_TIMEOUT_FALLBACK + + def absolute_future_ttl(self, collect_width: int) -> float: + """Conservative lifetime for a non-terminal future record.""" + ray_timeout = max(self.effective_execution_timeout, _MAX_DECLARED_BACKEND_TIMEOUT) + resource_bound = max(1, collect_width) * ray_timeout + return _ABSOLUTE_TTL_MULTIPLIER * (self.queue_timeout + resource_bound) diff --git a/src/twinkle/server/utils/task_queue/mixin.py b/src/twinkle/server/utils/task_queue/mixin.py index 4260b893..83526c39 100644 --- a/src/twinkle/server/utils/task_queue/mixin.py +++ b/src/twinkle/server/utils/task_queue/mixin.py @@ -8,6 +8,7 @@ from __future__ import annotations import asyncio +import contextlib import functools import time import traceback @@ -19,6 +20,7 @@ from twinkle.server.telemetry.middleware import get_task_metrics from twinkle.server.utils.task_errors import task_error_payload from twinkle.utils.logger import get_logger +from twinkle_client.types.errors import ErrorCategory from .config import TaskQueueConfig from .rate_limiter import RateLimiter from .types import BackendBusyError, QueuedTask, QueueState, TaskStatus @@ -59,6 +61,7 @@ def _init_task_queue( *, enable_admission_gate: bool = False, on_backend_timeout: Callable[[], Coroutine[Any, Any, None]] | None = None, + collect_width: int = 1, ) -> None: """Initialise the task queue, rate limiter, and compute worker. @@ -71,9 +74,9 @@ def _init_task_queue( does not (vllm sampler owns its own concurrency and the weight-update / generation mutual exclusion is covered by infra ``_cw_barrier``). - ``on_backend_timeout`` is an optional coroutine invoked once whenever a task - fails with a Ray_Get_Timeout / execution timeout, used by ModelManagement to - probe actor liveness (R3#2). + ``on_backend_timeout`` runs after a backend timeout. ``collect_width`` is the + number of actor results a backend call may collect and determines the persisted + future deadline. """ self._task_queue_config = config if config is not None else TaskQueueConfig() if self._task_queue_config.execution_timeout == 0: @@ -82,6 +85,7 @@ def _init_task_queue( '(deployment=%s).', self._task_queue_config.effective_execution_timeout, deployment_name or 'unknown') self._deployment_name = deployment_name self._task_metrics = get_task_metrics(deployment_name) if deployment_name else None + self._future_absolute_ttl = self._task_queue_config.absolute_future_ttl(collect_width) self._rate_limiter = RateLimiter( rps_limit=self._task_queue_config.rps_limit, @@ -102,62 +106,91 @@ def _init_task_queue( on_backend_timeout=on_backend_timeout, ) - # Blocking_Call_Boundary: a dedicated thread pool that moves every backend - # call off the event loop. Deliberately NOT max_workers=1 -- a call that - # leaks past its wait_for timeout keeps its thread; capping at one worker - # would let one leak block the whole queue forever. self._backend_executor = ThreadPoolExecutor(thread_name_prefix='twinkle-backend') - # per-replica Admission_Gate; opt-in per deployment. - self._backend_admission: asyncio.Semaphore | None = (asyncio.Semaphore(1) if enable_admission_gate else None) - + self._backend_probe_executor = ThreadPoolExecutor(max_workers=1, thread_name_prefix='twinkle-backend-probe') + self._backend_admission: asyncio.Lock | None = asyncio.Lock() if enable_admission_gate else None + self._backend_poisoned = asyncio.Event() self._event_loop: asyncio.AbstractEventLoop | None = None + async def _acquire_backend_gate(self, gate: asyncio.Lock) -> None: + if self._backend_poisoned.is_set(): + raise BackendBusyError('This replica is waiting for a timed-out backend call to exit.') + if not gate.locked(): + await gate.acquire() + else: + acquire_task = asyncio.create_task(gate.acquire()) + poison_task = asyncio.create_task(self._backend_poisoned.wait()) + try: + done, _ = await asyncio.wait((acquire_task, poison_task), return_when=asyncio.FIRST_COMPLETED) + except asyncio.CancelledError: + acquire_task.cancel() + poison_task.cancel() + await asyncio.gather(acquire_task, poison_task, return_exceptions=True) + if acquire_task.done() and not acquire_task.cancelled() and acquire_task.result(): + gate.release() + raise + if poison_task in done and self._backend_poisoned.is_set(): + if acquire_task.done() and not acquire_task.cancelled() and acquire_task.result(): + gate.release() + else: + acquire_task.cancel() + with contextlib.suppress(asyncio.CancelledError): + await acquire_task + raise BackendBusyError('This replica is waiting for a timed-out backend call to exit.') + poison_task.cancel() + with contextlib.suppress(asyncio.CancelledError): + await poison_task + await acquire_task + if self._backend_poisoned.is_set(): + gate.release() + raise BackendBusyError('This replica is waiting for a timed-out backend call to exit.') + async def call_backend(self, fn: Callable[..., Any], /, *args: Any, admit: bool = True, **kwargs: Any) -> Any: - """The only place a Blocking_Backend_Call leaves the event loop. - - Covers every backend call in this replica process -- not just handlers. - "Does it enter Task_Queue" is deliberately NOT the exemption test: what this - boundary protects is event-loop responsiveness, orthogonal to queueing. - ``check_model_health()``'s ping, ``_cleanup_adapter()``'s two calls (driven - by a countdown, never queued) and the non-queued sampler endpoints are - exactly the calls that test would have missed. - - The Admission_Gate it takes when ``admit=True`` guards against collective - mis-pairing (a task issued to the same actors while a timed-out call is - still in flight) and against queue-bypassing paths (``_cleanup_adapter``) -- - NOT GPU parallelism (Ray already serialises calls per actor). ``admit=False`` - skips the gate: it is for liveness probes only, because the moment a probe - matters most is while a call is stuck, and that is exactly when the gate is - held by the stuck thread; a probe touches no collective. The sampler side - does not enable the gate -- infra ``_cw_barrier`` already covers it. - - When the gate is held by a leaked (timed-out) call, a new admitting call - fails fast with :class:`BackendBusyError` instead of queueing behind it. + """Run one backend call outside the event loop. + + Normal model calls serialize through the admission gate. If the awaiting + task times out while its thread is still running, the gate is poisoned: + waiters fail immediately until that thread exits. Health probes bypass the + gate and use a reserved executor thread. Sampler deployments disable the + gate because their backend owns request concurrency. """ loop = asyncio.get_running_loop() - sem = self._backend_admission if admit else None - if sem is None: - return await loop.run_in_executor(self._backend_executor, functools.partial(fn, *args, **kwargs)) - - # asyncio.Semaphore.acquire() does not yield when the gate is free, so this - # check-then-acquire is race-free for a Semaphore(1): if not locked here, - # acquire succeeds synchronously. - if sem.locked(): - raise BackendBusyError('This replica is waiting for a timed-out backend call to exit; ' - 'refusing to queue behind it.') - await sem.acquire() - - def _work() -> Any: - try: - return fn(*args, **kwargs) - finally: - # Release only when the thread truly finishes. A wait_for timeout - # cancels the awaiting coroutine but NOT this thread; releasing on - # cancellation would free the gate while the backend call is still - # in flight (Property 4). - loop.call_soon_threadsafe(sem.release) + gate = self._backend_admission if admit else None + if gate is not None: + await self._acquire_backend_gate(gate) + + executor = self._backend_executor if admit else self._backend_probe_executor + try: + concurrent_future = executor.submit(functools.partial(fn, *args, **kwargs)) + except Exception: + if gate is not None and gate.locked(): + gate.release() + raise + + if gate is not None: - return await loop.run_in_executor(self._backend_executor, _work) + def release_gate(_future) -> None: + + def release() -> None: + self._backend_poisoned.clear() + if gate.locked(): + gate.release() + + with contextlib.suppress(RuntimeError): + loop.call_soon_threadsafe(release) + + concurrent_future.add_done_callback(release_gate) + + try: + return await asyncio.wrap_future(concurrent_future, loop=loop) + except asyncio.CancelledError: + if gate is not None and concurrent_future.running(): + self._backend_poisoned.set() + raise + + def _future_deadline(self) -> float: + ttl = getattr(self, '_future_absolute_ttl', self._task_queue_config.absolute_future_ttl(1)) + return time.time() + ttl @staticmethod def _queue_key(model_id: str | None, token: str | None) -> str: @@ -186,7 +219,13 @@ async def _perform_preflight_checks( return None async def reject(error_msg: str, queue_state: str) -> dict[str, Any]: - error_payload = {'error': error_msg, 'category': 'User'} + error_code = 429 if queue_state == QueueState.PAUSED_RATE_LIMIT.value else 400 + error_payload = task_error_payload( + error_msg, + request_id=request_id, + error_code=error_code, + category=ErrorCategory.User, + ) if persist_failure: await self.state.store_future_status( request_id, @@ -272,6 +311,7 @@ async def _schedule_task( model_id, queue_state=QueueState.ACTIVE.value, replica_id=getattr(self, 'replica_id', None), + absolute_deadline=self._future_deadline(), ) queue_key = self._queue_key(model_id=model_id, token=token) @@ -423,6 +463,7 @@ async def schedule_background_task( model_id, queue_state=QueueState.ACTIVE.value, replica_id=getattr(self, 'replica_id', None), + absolute_deadline=self._future_deadline(), ) async def _run() -> None: @@ -501,5 +542,7 @@ async def shutdown_task_queue(self) -> None: await self._compute_worker.stop() # Do not wait on threads that may be leaked on a timed-out backend call. if getattr(self, '_backend_executor', None) is not None: - self._backend_executor.shutdown(wait=False) + self._backend_executor.shutdown(wait=False, cancel_futures=True) + if getattr(self, '_backend_probe_executor', None) is not None: + self._backend_probe_executor.shutdown(wait=False, cancel_futures=True) logger.debug('[TaskQueue] Task queue shutdown complete') diff --git a/src/twinkle/server/utils/task_queue/types.py b/src/twinkle/server/utils/task_queue/types.py index a7283dd9..c7f51462 100644 --- a/src/twinkle/server/utils/task_queue/types.py +++ b/src/twinkle/server/utils/task_queue/types.py @@ -26,13 +26,17 @@ class TaskStatus(Enum): RATE_LIMITED = 'rate_limited' # Task rejected due to rate limiting +class UserTaskError(ValueError): + """A queued operation rejected because of caller input or usage.""" + + class BackendBusyError(RuntimeError): """Raised when the per-replica Admission_Gate is held by a leaked backend call. A new backend call arriving while the gate is closed (its holder is a call that already exceeded ``asyncio.wait_for`` but whose executor thread has not yet returned) fails fast with this error instead of queueing behind it. The worker - maps it to ``ErrorPayload(category='Server', error_code=503)``. + maps it to ``ErrorPayload(category='server', error_code=503)``. """ diff --git a/src/twinkle/server/utils/task_queue/worker.py b/src/twinkle/server/utils/task_queue/worker.py index 121d7345..b1e276cf 100644 --- a/src/twinkle/server/utils/task_queue/worker.py +++ b/src/twinkle/server/utils/task_queue/worker.py @@ -12,14 +12,15 @@ import time import traceback from collections import deque -from typing import TYPE_CHECKING, Any, Deque +from typing import TYPE_CHECKING, Any, Callable, Deque from twinkle.server.telemetry.correlation import MODEL_ID, TOKEN_ID from twinkle.server.telemetry.tracing import traced_operation from twinkle.server.utils.task_errors import task_error_payload from twinkle.utils.logger import get_logger +from twinkle_client.types.errors import ErrorCategory from .config import TaskQueueConfig -from .types import BackendBusyError, QueuedTask, QueueState, TaskStatus +from .types import BackendBusyError, QueuedTask, QueueState, TaskStatus, UserTaskError if TYPE_CHECKING: from twinkle.server.state import ServerState @@ -153,6 +154,7 @@ async def _store_task_failed( queue_state_reason: str | None = None, *, error_code: int = 500, + category: ErrorCategory = ErrorCategory.Server, traceback_text: str | None = None, ) -> None: """Store FAILED status with a standardised ``ErrorPayload``.""" @@ -165,6 +167,7 @@ async def _store_task_failed( error, request_id=task.request_id, error_code=error_code, + category=category, traceback_text=traceback_text, ), queue_state=queue_state, @@ -280,6 +283,16 @@ async def _execute_task(self, task: QueuedTask, queue_key: str, q: asyncio.Queue await self._on_backend_timeout() except Exception: logger.error(f'[ComputeWorker] backend-timeout probe failed:\n{traceback.format_exc(limit=3)}') + except UserTaskError as exc: + task_status = 'failed' + exec_time = time.monotonic() - exec_start + await self._store_task_failed( + task, + f'{type(exc).__name__}: {exc}', + QueueState.UNKNOWN.value, + error_code=400, + category=ErrorCategory.User, + ) except BackendBusyError as exc: task_status = 'failed' exec_time = time.monotonic() - exec_start diff --git a/src/twinkle/utils/nccl_safe.py b/src/twinkle/utils/nccl_safe.py index 214f3a17..a7c7eef0 100644 --- a/src/twinkle/utils/nccl_safe.py +++ b/src/twinkle/utils/nccl_safe.py @@ -55,11 +55,19 @@ def wrapper(self, *args, **kwargs): return func(self, *args, **kwargs) except Exception as exc: import traceback + rank = _global_rank() + context = f'twinkle backend method={func.__name__}, global_rank={rank}' + if hasattr(exc, 'add_note'): + exc.add_note(context) + elif exc.args: + exc.args = (f'{exc.args[0]} [{context}]', *exc.args[1:]) + else: + exc.args = (context, ) tb = traceback.format_exc() if len(tb) > _TRACEBACK_LIMIT: tb = tb[-_TRACEBACK_LIMIT:] logger.error('[nccl_safe_megatron] %s in %s on global rank %s:\n%s', - type(exc).__name__, func.__name__, _global_rank(), tb) + type(exc).__name__, func.__name__, rank, tb) raise return wrapper diff --git a/src/twinkle_client/types/errors.py b/src/twinkle_client/types/errors.py index 61685b1e..f1f4e3e1 100644 --- a/src/twinkle_client/types/errors.py +++ b/src/twinkle_client/types/errors.py @@ -4,10 +4,10 @@ Twinkle <-> tinker exception mapping (verified, kept here so a future new exception class can be lined up against its tinker counterpart): -- tinker ``RequestFailedError`` (``tinker/_exceptions.py:176-196``; carries +- Tinker 0.29.0 ``RequestFailedError`` (``tinker/_exceptions.py``; carries ``message`` / ``request_id`` / ``category``) is the "the task completed in a failed - terminal state" exception. Its ``category`` uses the same three values as - :class:`ErrorCategory` (``Unknown`` / ``Server`` / ``User``). + terminal state" exception. Its wire values are ``unknown`` / ``server`` / + ``user``, matching :class:`ErrorCategory`; legacy TitleCase values are normalized. ``twinkle_client/utils/patch_tinker.py`` shows two SDKs can coexist in one process, so a semantically-equal but differently-named exception must be lookup-able. @@ -15,7 +15,7 @@ class can be lined up against its tinker counterpart): from __future__ import annotations from enum import StrEnum -from pydantic import Field +from pydantic import Field, field_validator, model_validator from typing import Any, Literal, Optional from .base import ResponseModel @@ -29,9 +29,9 @@ class can be lined up against its tinker counterpart): class ErrorCategory(StrEnum): """Error attribution. Matches tinker's ``RequestErrorCategory``.""" - Unknown = 'Unknown' - Server = 'Server' - User = 'User' + Unknown = 'unknown' + Server = 'server' + User = 'user' class ErrorPayload(ResponseModel): @@ -53,3 +53,16 @@ class ErrorPayload(ResponseModel): request_id: str traceback: Optional[str] = Field(default=None, max_length=65536) details: Optional[list[dict[str, Any]]] = None + + @field_validator('category', mode='before') + @classmethod + def normalize_legacy_category(cls, value: Any) -> Any: + if isinstance(value, str): + return value.lower() + return value + + @model_validator(mode='after') + def traceback_is_server_only(self) -> 'ErrorPayload': + if self.traceback is not None and self.category is not ErrorCategory.Server: + raise ValueError('traceback is only valid for server errors') + return self diff --git a/tests/infra/test_ray_get_timeout.py b/tests/infra/test_ray_get_timeout.py index f9949eac..00a3b79c 100644 --- a/tests/infra/test_ray_get_timeout.py +++ b/tests/infra/test_ray_get_timeout.py @@ -10,9 +10,9 @@ ray = pytest.importorskip('ray') -import twinkle.infra as infra -from twinkle.infra._ray.ray_helper import RayHelper -from twinkle.infra import remote_function +import twinkle.infra as infra # noqa: E402 +from twinkle.infra import remote_function # noqa: E402 +from twinkle.infra._ray.ray_helper import RayHelper # noqa: E402 @ray.remote @@ -24,6 +24,14 @@ def slow(self, seconds: float): time.sleep(seconds) return seconds + def slow_batch(self, seconds: list[float]): + import time + time.sleep(seconds[0]) + return seconds + + def _twinkle_async_slow_batch(self, seconds: list[float]): + return self.slow_batch(seconds) + @pytest.fixture(scope='module', autouse=True) def _ray_and_ray_mode(): @@ -103,6 +111,19 @@ def slow(self, seconds): wrapped(driver, 2.0) +def test_continuous_work_timeout_zero_is_not_treated_as_falsy(): + + def slow_batch(self, seconds): + return seconds + + wrapped = remote_function( + dispatch='all', collect='first', timeout=0, enable_continous_work=True)(slow_batch) + driver = _make_driver() + driver._ray_get_timeout = 100.0 + with pytest.raises(ray.exceptions.GetTimeoutError): + wrapped(driver, [1.0]) + + def test_decorator_timeout_zero_is_not_treated_as_falsy(): """timeout=0 means 'time out immediately', not 'fall back to unbounded'.""" diff --git a/tests/server/README.md b/tests/server/README.md index 44a998a8..49adf2cb 100644 --- a/tests/server/README.md +++ b/tests/server/README.md @@ -20,4 +20,8 @@ backend's internals: the **dispatch path** (that a call reaches the backend via Tests that need to prove validation or NCCL behavior are the GPU-gated end-to-end tests under `tests/server/integration/test_nccl_safe_*_e2e.py` (run only with -`TWINKLE_TEST_GPU_E2E=1` against a real server). +`TWINKLE_TEST_GPU_E2E=1` against a real server configured with the test execution timeout). + +The contract suite covers all five apps and recursively snapshots request and response +types. Tinker compatibility assertions follow the 0.29.0 SDK wire values. The blocking +boundary suite uses a real serial Ray actor for the health-probe timing case. diff --git a/tests/server/contract/client_api_baseline.json b/tests/server/contract/client_api_baseline.json index 61f0c48a..243a0567 100644 --- a/tests/server/contract/client_api_baseline.json +++ b/tests/server/contract/client_api_baseline.json @@ -1,533 +1,3937 @@ { + "data_plane": { + "paths": { + "/twinkle/append": { + "POST": { + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "DataRef": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + } + }, + "properties": { + "ref": { + "$ref": "#/$defs/DataRef" + }, + "rows": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Rows", + "type": "array" + }, + "tags": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tags" + } + }, + "required": [ + "ref", + "rows" + ], + "title": "DataAppendRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "append", + "path": [], + "query": [], + "response": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + }, + "responses": {}, + "statusCode": 200 + } + }, + "/twinkle/get": { + "POST": { + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "DataRef": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + } + }, + "properties": { + "fields": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Fields" + }, + "include_tags": { + "default": false, + "title": "Include Tags", + "type": "boolean" + }, + "ref": { + "$ref": "#/$defs/DataRef" + } + }, + "required": [ + "ref" + ], + "title": "DataGetRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "get", + "path": [], + "query": [], + "response": { + "properties": { + "rows": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Rows", + "type": "array" + }, + "tags": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Tags", + "type": "array" + } + }, + "required": [ + "rows" + ], + "title": "DataRowsResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 + } + }, + "/twinkle/put": { + "POST": { + "body": [ + { + "name": "body", + "required": true, + "schema": { + "properties": { + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "rows": { + "items": { + "additionalProperties": true, + "type": "object" + }, + "title": "Rows", + "type": "array" + }, + "tags": { + "anyOf": [ + { + "items": { + "additionalProperties": true, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tags" + } + }, + "required": [ + "rows" + ], + "title": "DataPutRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "put", + "path": [], + "query": [], + "response": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + }, + "responses": {}, + "statusCode": 200 + } + }, + "/twinkle/release": { + "POST": { + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "DataRef": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + } + }, + "properties": { + "ref": { + "$ref": "#/$defs/DataRef" + } + }, + "required": [ + "ref" + ], + "title": "DataReleaseRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "release", + "path": [], + "query": [], + "response": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "responses": {}, + "statusCode": 200 + } + } + } + }, "gateway": { "paths": { "/asample": { "POST": { - "operationId": "asample_asample_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "DmelChunk": { + "additionalProperties": false, + "properties": { + "dmel": { + "format": "binary", + "title": "Dmel", + "type": "string" + }, + "type": { + "const": "dmel", + "default": "dmel", + "title": "Type", + "type": "string" + } + }, + "required": [ + "dmel" + ], + "title": "DmelChunk", + "type": "object" + }, + "EncodedTextChunk": { + "additionalProperties": false, + "properties": { + "tokens": { + "items": { + "type": "integer" + }, + "title": "Tokens", + "type": "array" + }, + "type": { + "const": "encoded_text", + "default": "encoded_text", + "title": "Type", + "type": "string" + } + }, + "required": [ + "tokens" + ], + "title": "EncodedTextChunk", + "type": "object" + }, + "ImageAssetPointerChunk": { + "additionalProperties": false, + "properties": { + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "location": { + "title": "Location", + "type": "string" + }, + "type": { + "const": "image_asset_pointer", + "default": "image_asset_pointer", + "title": "Type", + "type": "string" + } + }, + "required": [ + "format", + "location" + ], + "title": "ImageAssetPointerChunk", + "type": "object" + }, + "ImageChunk": { + "additionalProperties": false, + "properties": { + "data": { + "format": "binary", + "title": "Data", + "type": "string" + }, + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "type": { + "const": "image", + "default": "image", + "title": "Type", + "type": "string" + } + }, + "required": [ + "data", + "format" + ], + "title": "ImageChunk", + "type": "object" + }, + "ModelInput": { + "additionalProperties": false, + "properties": { + "chunks": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/EncodedTextChunk" + }, + { + "$ref": "#/$defs/ImageAssetPointerChunk" + }, + { + "$ref": "#/$defs/ImageChunk" + }, + { + "$ref": "#/$defs/DmelChunk" + } + ] + }, + "title": "Chunks", + "type": "array" + } + }, + "required": [ + "chunks" + ], + "title": "ModelInput", + "type": "object" + }, + "SamplingParams": { + "properties": { + "max_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Max Tokens" + }, + "seed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seed" + }, + "stop": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Stop" + }, + "temperature": { + "default": 1, + "title": "Temperature", + "type": "number" + }, + "top_k": { + "default": -1, + "title": "Top K", + "type": "integer" + }, + "top_p": { + "default": 1, + "title": "Top P", + "type": "number" + } + }, + "title": "SamplingParams", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "base_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Base Model" + }, + "model_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Path" + }, + "num_samples": { + "default": 1, + "title": "Num Samples", + "type": "integer" + }, + "prompt": { + "$ref": "#/$defs/ModelInput" + }, + "prompt_logprobs": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Prompt Logprobs" + }, + "record_stability_info": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Record Stability Info" + }, + "sampling_params": { + "$ref": "#/$defs/SamplingParams" + }, + "sampling_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sampling Session Id" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "topk_prompt_logprobs": { + "default": 0, + "title": "Topk Prompt Logprobs", + "type": "integer" + }, + "topk_sample_logprobs": { + "default": 0, + "title": "Topk Sample Logprobs", + "type": "integer" + }, + "type": { + "const": "sample", + "default": "sample", + "title": "Type", + "type": "string" + } + }, + "required": [ + "prompt", + "sampling_params" + ], + "title": "SampleRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "asample", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/chat/completions": { "POST": { - "operationId": "chat_completions_chat_completions_post", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "chat_completions", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/create_model": { "POST": { - "operationId": "create_model_create_model_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "LoraConfig": { + "additionalProperties": false, + "properties": { + "rank": { + "title": "Rank", + "type": "integer" + }, + "seed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seed" + }, + "train_attn": { + "default": true, + "title": "Train Attn", + "type": "boolean" + }, + "train_mlp": { + "default": true, + "title": "Train Mlp", + "type": "boolean" + }, + "train_unembed": { + "default": true, + "title": "Train Unembed", + "type": "boolean" + } + }, + "required": [ + "rank" + ], + "title": "LoraConfig", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "base_model": { + "title": "Base Model", + "type": "string" + }, + "lora_config": { + "anyOf": [ + { + "$ref": "#/$defs/LoraConfig" + }, + { + "type": "null" + } + ], + "default": null + }, + "model_seq_id": { + "title": "Model Seq Id", + "type": "integer" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "type": { + "const": "create_model", + "default": "create_model", + "title": "Type", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "session_id", + "model_seq_id", + "base_model" + ], + "title": "CreateModelRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "create_model", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/create_sampling_session": { "POST": { - "operationId": "create_sampling_session_create_sampling_session_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "base_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Base Model" + }, + "model_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Path" + }, + "sampling_session_seq_id": { + "title": "Sampling Session Seq Id", + "type": "integer" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "type": { + "const": "create_sampling_session", + "default": "create_sampling_session", + "title": "Type", + "type": "string" + } + }, + "required": [ + "session_id", + "sampling_session_seq_id" + ], + "title": "CreateSamplingSessionRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "create_sampling_session", + "path": [], + "query": [], + "response": { + "properties": { + "sampling_session_id": { + "title": "Sampling Session Id", + "type": "string" + }, + "type": { + "const": "create_sampling_session", + "default": "create_sampling_session", + "title": "Type", + "type": "string" + } + }, + "required": [ + "sampling_session_id" + ], + "title": "CreateSamplingSessionResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/create_session": { "POST": { - "operationId": "create_session_create_session_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "project_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Project Id" + }, + "sdk_version": { + "title": "Sdk Version", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "title": "Tags", + "type": "array" + }, + "type": { + "const": "create_session", + "default": "create_session", + "title": "Type", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "User Metadata" + } + }, + "required": [ + "tags", + "user_metadata", + "sdk_version" + ], + "title": "CreateSessionRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "create_session", + "path": [], + "query": [], + "response": { + "properties": { + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error Message" + }, + "info_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Info Message" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "type": { + "const": "create_session", + "default": "create_session", + "title": "Type", + "type": "string" + }, + "warning_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Warning Message" + } + }, + "required": [ + "session_id" + ], + "title": "CreateSessionResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/forward": { "POST": { - "operationId": "forward_forward_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "properties": { + "forward_input": { + "properties": { + "data": { + "items": { + "properties": { + "loss_fn_input_spans": { + "pythonType": "'Optional[ProvenanceSpans]'" + }, + "loss_fn_inputs": { + "pythonType": "'LossFnInputs'" + }, + "model_input": { + "pythonType": "'ModelInput'" + }, + "model_input_spans": { + "pythonType": "'Optional[ProvenanceSpans]'" + } + }, + "required": [ + "model_input" + ], + "type": "object" + }, + "type": "array" + }, + "loss_fn": { + "enum": [ + "cross_entropy", + "importance_sampling", + "ppo", + "cispo", + "dro" + ] + }, + "loss_fn_config": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "data", + "loss_fn" + ], + "type": "object" + }, + "model_id": { + "type": "string" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "forward_input", + "model_id" + ], + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/forward_backward": { "POST": { - "operationId": "forward_backward_forward_backward_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "properties": { + "forward_backward_input": { + "properties": { + "data": { + "items": { + "properties": { + "loss_fn_input_spans": { + "pythonType": "'Optional[ProvenanceSpans]'" + }, + "loss_fn_inputs": { + "pythonType": "'LossFnInputs'" + }, + "model_input": { + "pythonType": "'ModelInput'" + }, + "model_input_spans": { + "pythonType": "'Optional[ProvenanceSpans]'" + } + }, + "required": [ + "model_input" + ], + "type": "object" + }, + "type": "array" + }, + "loss_fn": { + "enum": [ + "cross_entropy", + "importance_sampling", + "ppo", + "cispo", + "dro" + ] + }, + "loss_fn_config": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "data", + "loss_fn" + ], + "type": "object" + }, + "model_id": { + "type": "string" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "forward_backward_input", + "model_id" + ], + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward_backward", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/get_info": { "POST": { - "operationId": "get_info_get_info_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "model_id": { + "title": "Model Id", + "type": "string" + }, + "type": { + "const": "get_info", + "default": "get_info", + "title": "Type", + "type": "string" + } + }, + "required": [ + "model_id" + ], + "title": "GetInfoRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "get_info", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/get_server_capabilities": { "GET": { - "operationId": "get_server_capabilities_get_server_capabilities_get", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_server_capabilities", + "path": [], + "query": [], + "response": { + "$defs": { + "SupportedModel": { + "description": "Information about a model supported by the server.", + "properties": { + "max_context_length": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Max Context Length" + }, + "model_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Name" + }, + "sampleable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sampleable" + }, + "trainable": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Trainable" + } + }, + "title": "SupportedModel", + "type": "object" + } + }, + "description": "Response containing the server's supported models and capabilities.", + "properties": { + "supported_models": { + "items": { + "$ref": "#/$defs/SupportedModel" + }, + "title": "Supported Models", + "type": "array" + } + }, + "required": [ + "supported_models" + ], + "title": "GetServerCapabilitiesResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/healthz": { "GET": { - "operationId": "healthz_healthz_get", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "healthz", + "path": [], + "query": [], + "response": { + "properties": { + "status": { + "const": "ok", + "title": "Status", + "type": "string" + } + }, + "required": [ + "status" + ], + "title": "HealthResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/load_weights": { "POST": { - "operationId": "load_weights_load_weights_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "base_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Base Model" + }, + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "model_seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Seq Id" + }, + "optimizer": { + "title": "Optimizer", + "type": "boolean" + }, + "path": { + "title": "Path", + "type": "string" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "type": { + "const": "load_weights", + "default": "load_weights", + "title": "Type", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + }, + "weights_access_token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Weights Access Token" + } + }, + "required": [ + "path", + "optimizer" + ], + "title": "LoadWeightsRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "load_weights", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/models": { "GET": { - "operationId": "list_models_models_get", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "list_models", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/optim_step": { "POST": { - "operationId": "optim_step_optim_step_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "AdamParams": { + "additionalProperties": false, + "properties": { + "beta1": { + "default": 0.9, + "title": "Beta1", + "type": "number" + }, + "beta2": { + "default": 0.95, + "title": "Beta2", + "type": "number" + }, + "eps": { + "default": 1e-12, + "title": "Eps", + "type": "number" + }, + "grad_clip_norm": { + "default": 0.0, + "title": "Grad Clip Norm", + "type": "number" + }, + "learning_rate": { + "default": 0.0001, + "title": "Learning Rate", + "type": "number" + }, + "weight_decay": { + "default": 0.0, + "title": "Weight Decay", + "type": "number" + } + }, + "title": "AdamParams", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "adam_params": { + "$ref": "#/$defs/AdamParams" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "type": { + "const": "optim_step", + "default": "optim_step", + "title": "Type", + "type": "string" + } + }, + "required": [ + "adam_params", + "model_id" + ], + "title": "OptimStepRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "optim_step", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/retrieve_future": { "POST": { - "operationId": "retrieve_future_retrieve_future_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "allow_metadata_only": { + "default": false, + "title": "Allow Metadata Only", + "type": "boolean" + }, + "request_id": { + "title": "Request Id", + "type": "string" + } + }, + "required": [ + "request_id" + ], + "title": "FutureRetrieveRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "retrieve_future", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/save_weights": { "POST": { - "operationId": "save_weights_save_weights_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "model_id": { + "title": "Model Id", + "type": "string" + }, + "overwrite": { + "default": false, + "title": "Overwrite", + "type": "boolean" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "ttl_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ttl Seconds" + }, + "type": { + "const": "save_weights", + "default": "save_weights", + "title": "Type", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "model_id" + ], + "title": "SaveWeightsRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "save_weights", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/save_weights_for_sampler": { "POST": { - "operationId": "save_weights_for_sampler_save_weights_for_sampler_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "model_id": { + "title": "Model Id", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "sampling_session_seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sampling Session Seq Id" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "ttl_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ttl Seconds" + }, + "type": { + "const": "save_weights_for_sampler", + "default": "save_weights_for_sampler", + "title": "Type", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "model_id" + ], + "title": "SaveWeightsForSamplerRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "save_weights_for_sampler", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/session_heartbeat": { "POST": { - "operationId": "session_heartbeat_session_heartbeat_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + }, + "type": { + "const": "session_heartbeat", + "default": "session_heartbeat", + "title": "Type", + "type": "string" + } + }, + "required": [ + "session_id" + ], + "title": "SessionHeartbeatRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "session_heartbeat", + "path": [], + "query": [], + "response": { + "properties": { + "type": { + "const": "session_heartbeat", + "default": "session_heartbeat", + "title": "Type", + "type": "string" + } + }, + "title": "SessionHeartbeatResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/telemetry": { "POST": { - "operationId": "telemetry_telemetry_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "GenericEvent": { + "properties": { + "event": { + "enum": [ + "SESSION_START", + "SESSION_END", + "UNHANDLED_EXCEPTION", + "GENERIC_EVENT" + ], + "title": "Event", + "type": "string" + }, + "event_data": { + "additionalProperties": true, + "default": {}, + "title": "Event Data", + "type": "object" + }, + "event_id": { + "title": "Event Id", + "type": "string" + }, + "event_name": { + "title": "Event Name", + "type": "string" + }, + "event_session_index": { + "title": "Event Session Index", + "type": "integer" + }, + "severity": { + "enum": [ + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "CRITICAL" + ], + "title": "Severity", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "event", + "event_id", + "event_name", + "event_session_index", + "severity", + "timestamp" + ], + "title": "GenericEvent", + "type": "object" + }, + "SessionEndEvent": { + "properties": { + "duration": { + "title": "Duration", + "type": "string" + }, + "event": { + "enum": [ + "SESSION_START", + "SESSION_END", + "UNHANDLED_EXCEPTION", + "GENERIC_EVENT" + ], + "title": "Event", + "type": "string" + }, + "event_id": { + "title": "Event Id", + "type": "string" + }, + "event_session_index": { + "title": "Event Session Index", + "type": "integer" + }, + "severity": { + "enum": [ + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "CRITICAL" + ], + "title": "Severity", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "duration", + "event", + "event_id", + "event_session_index", + "severity", + "timestamp" + ], + "title": "SessionEndEvent", + "type": "object" + }, + "SessionStartEvent": { + "properties": { + "event": { + "enum": [ + "SESSION_START", + "SESSION_END", + "UNHANDLED_EXCEPTION", + "GENERIC_EVENT" + ], + "title": "Event", + "type": "string" + }, + "event_id": { + "title": "Event Id", + "type": "string" + }, + "event_session_index": { + "title": "Event Session Index", + "type": "integer" + }, + "severity": { + "enum": [ + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "CRITICAL" + ], + "title": "Severity", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string" + } + }, + "required": [ + "event", + "event_id", + "event_session_index", + "severity", + "timestamp" + ], + "title": "SessionStartEvent", + "type": "object" + }, + "UnhandledExceptionEvent": { + "properties": { + "error_message": { + "title": "Error Message", + "type": "string" + }, + "error_type": { + "title": "Error Type", + "type": "string" + }, + "event": { + "enum": [ + "SESSION_START", + "SESSION_END", + "UNHANDLED_EXCEPTION", + "GENERIC_EVENT" + ], + "title": "Event", + "type": "string" + }, + "event_id": { + "title": "Event Id", + "type": "string" + }, + "event_session_index": { + "title": "Event Session Index", + "type": "integer" + }, + "severity": { + "enum": [ + "DEBUG", + "INFO", + "WARNING", + "ERROR", + "CRITICAL" + ], + "title": "Severity", + "type": "string" + }, + "timestamp": { + "format": "date-time", + "title": "Timestamp", + "type": "string" + }, + "traceback": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Traceback" + } + }, + "required": [ + "error_message", + "error_type", + "event", + "event_id", + "event_session_index", + "severity", + "timestamp" + ], + "title": "UnhandledExceptionEvent", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "events": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/SessionStartEvent" + }, + { + "$ref": "#/$defs/SessionEndEvent" + }, + { + "$ref": "#/$defs/UnhandledExceptionEvent" + }, + { + "$ref": "#/$defs/GenericEvent" + } + ] + }, + "title": "Events", + "type": "array" + }, + "platform": { + "title": "Platform", + "type": "string" + }, + "process_uuid": { + "title": "Process Uuid", + "type": "string" + }, + "sdk_version": { + "title": "Sdk Version", + "type": "string" + }, + "session_id": { + "title": "Session Id", + "type": "string" + } + }, + "required": [ + "events", + "platform", + "sdk_version", + "session_id", + "process_uuid" + ], + "title": "TelemetrySendRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "telemetry", + "path": [], + "query": [], + "response": { + "properties": { + "status": { + "const": "accepted", + "title": "Status", + "type": "string" + } + }, + "required": [ + "status" + ], + "title": "TelemetryResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/training_runs": { "GET": { - "operationId": "get_training_runs_training_runs_get", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_training_runs", + "path": [], + "query": [ { - "in": "query", "name": "limit", "required": false, "schema": { - "default": 20, - "title": "Limit", "type": "integer" } }, { - "in": "query", "name": "offset", "required": false, "schema": { - "default": 0, - "title": "Offset", "type": "integer" } } ], - "responses": [ - "200", - "422" - ] + "response": { + "$defs": { + "Checkpoint": { + "properties": { + "checkpoint_id": { + "title": "Checkpoint Id", + "type": "string" + }, + "checkpoint_type": { + "enum": [ + "training", + "sampler", + "external" + ], + "title": "Checkpoint Type", + "type": "string" + }, + "expires_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expires At" + }, + "public": { + "default": false, + "title": "Public", + "type": "boolean" + }, + "size_bytes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Size Bytes" + }, + "time": { + "format": "date-time", + "title": "Time", + "type": "string" + }, + "tinker_path": { + "title": "Tinker Path", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "checkpoint_id", + "checkpoint_type", + "time", + "tinker_path" + ], + "title": "Checkpoint", + "type": "object" + }, + "Cursor": { + "properties": { + "limit": { + "title": "Limit", + "type": "integer" + }, + "offset": { + "title": "Offset", + "type": "integer" + }, + "total_count": { + "title": "Total Count", + "type": "integer" + } + }, + "required": [ + "offset", + "limit", + "total_count" + ], + "title": "Cursor", + "type": "object" + }, + "TrainingRun": { + "properties": { + "base_model": { + "title": "Base Model", + "type": "string" + }, + "corrupted": { + "default": false, + "title": "Corrupted", + "type": "boolean" + }, + "is_lora": { + "title": "Is Lora", + "type": "boolean" + }, + "last_checkpoint": { + "anyOf": [ + { + "$ref": "#/$defs/Checkpoint" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_request_time": { + "format": "date-time", + "title": "Last Request Time", + "type": "string" + }, + "last_sampler_checkpoint": { + "anyOf": [ + { + "$ref": "#/$defs/Checkpoint" + }, + { + "type": "null" + } + ], + "default": null + }, + "lora_rank": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lora Rank" + }, + "model_owner": { + "title": "Model Owner", + "type": "string" + }, + "training_run_id": { + "title": "Training Run Id", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "training_run_id", + "base_model", + "model_owner", + "is_lora", + "last_request_time" + ], + "title": "TrainingRun", + "type": "object" + } + }, + "properties": { + "cursor": { + "$ref": "#/$defs/Cursor" + }, + "training_runs": { + "items": { + "$ref": "#/$defs/TrainingRun" + }, + "title": "Training Runs", + "type": "array" + } + }, + "required": [ + "training_runs", + "cursor" + ], + "title": "TrainingRunsResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/training_runs/{run_id}": { "GET": { - "operationId": "get_training_run_training_runs__run_id__get", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_training_run", + "path": [ { - "in": "path", "name": "run_id", "required": true, "schema": { - "title": "Run Id", "type": "string" } } ], - "responses": [ - "200", - "422" - ] + "query": [], + "response": { + "$defs": { + "Checkpoint": { + "properties": { + "checkpoint_id": { + "title": "Checkpoint Id", + "type": "string" + }, + "checkpoint_type": { + "enum": [ + "training", + "sampler", + "external" + ], + "title": "Checkpoint Type", + "type": "string" + }, + "expires_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expires At" + }, + "public": { + "default": false, + "title": "Public", + "type": "boolean" + }, + "size_bytes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Size Bytes" + }, + "time": { + "format": "date-time", + "title": "Time", + "type": "string" + }, + "tinker_path": { + "title": "Tinker Path", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "checkpoint_id", + "checkpoint_type", + "time", + "tinker_path" + ], + "title": "Checkpoint", + "type": "object" + } + }, + "properties": { + "base_model": { + "title": "Base Model", + "type": "string" + }, + "corrupted": { + "default": false, + "title": "Corrupted", + "type": "boolean" + }, + "is_lora": { + "title": "Is Lora", + "type": "boolean" + }, + "last_checkpoint": { + "anyOf": [ + { + "$ref": "#/$defs/Checkpoint" + }, + { + "type": "null" + } + ], + "default": null + }, + "last_request_time": { + "format": "date-time", + "title": "Last Request Time", + "type": "string" + }, + "last_sampler_checkpoint": { + "anyOf": [ + { + "$ref": "#/$defs/Checkpoint" + }, + { + "type": "null" + } + ], + "default": null + }, + "lora_rank": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lora Rank" + }, + "model_owner": { + "title": "Model Owner", + "type": "string" + }, + "training_run_id": { + "title": "Training Run Id", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "training_run_id", + "base_model", + "model_owner", + "is_lora", + "last_request_time" + ], + "title": "TrainingRun", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/training_runs/{run_id}/checkpoints": { "GET": { - "operationId": "get_run_checkpoints_training_runs__run_id__checkpoints_get", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_run_checkpoints", + "path": [ { - "in": "path", "name": "run_id", "required": true, "schema": { - "title": "Run Id", "type": "string" } } ], - "responses": [ - "200", - "422" - ] + "query": [], + "response": { + "$defs": { + "Checkpoint": { + "properties": { + "checkpoint_id": { + "title": "Checkpoint Id", + "type": "string" + }, + "checkpoint_type": { + "enum": [ + "training", + "sampler", + "external" + ], + "title": "Checkpoint Type", + "type": "string" + }, + "expires_at": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expires At" + }, + "public": { + "default": false, + "title": "Public", + "type": "boolean" + }, + "size_bytes": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Size Bytes" + }, + "time": { + "format": "date-time", + "title": "Time", + "type": "string" + }, + "tinker_path": { + "title": "Tinker Path", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "checkpoint_id", + "checkpoint_type", + "time", + "tinker_path" + ], + "title": "Checkpoint", + "type": "object" + }, + "Cursor": { + "properties": { + "limit": { + "title": "Limit", + "type": "integer" + }, + "offset": { + "title": "Offset", + "type": "integer" + }, + "total_count": { + "title": "Total Count", + "type": "integer" + } + }, + "required": [ + "offset", + "limit", + "total_count" + ], + "title": "Cursor", + "type": "object" + } + }, + "properties": { + "checkpoints": { + "items": { + "$ref": "#/$defs/Checkpoint" + }, + "title": "Checkpoints", + "type": "array" + }, + "cursor": { + "anyOf": [ + { + "$ref": "#/$defs/Cursor" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "checkpoints" + ], + "title": "CheckpointsListResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, - "/training_runs/{run_id}/checkpoints/{checkpoint_id}": { + "/training_runs/{run_id}/checkpoints/{checkpoint_id:path}": { "DELETE": { - "operationId": "delete_run_checkpoint_training_runs__run_id__checkpoints__checkpoint_id__delete", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "delete_run_checkpoint", + "path": [ { - "in": "path", "name": "run_id", "required": true, "schema": { - "title": "Run Id", "type": "string" } }, { - "in": "path", "name": "checkpoint_id", "required": true, "schema": { - "title": "Checkpoint Id", "type": "string" } } ], - "responses": [ - "200", - "422" - ] + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, - "/training_runs/{run_id}/checkpoints/{checkpoint_id}/publish": { + "/training_runs/{run_id}/checkpoints/{checkpoint_id:path}/publish": { "POST": { - "operationId": "publish_checkpoint_training_runs__run_id__checkpoints__checkpoint_id__publish_post", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "publish_checkpoint", + "path": [ { - "in": "path", "name": "run_id", "required": true, "schema": { - "title": "Run Id", "type": "string" } }, { - "in": "path", "name": "checkpoint_id", "required": true, "schema": { - "title": "Checkpoint Id", "type": "string" } } ], - "responses": [ - "200", - "422" - ] + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/capacity_info": { "GET": { - "operationId": "get_capacity_info_twinkle_capacity_info_get", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_capacity_info", + "path": [], + "query": [], + "response": { + "description": "Response body for the /capacity_info endpoint.", + "properties": { + "free_loras": { + "title": "Free Loras", + "type": "integer" + }, + "max_loras": { + "title": "Max Loras", + "type": "integer" + }, + "used_loras": { + "title": "Used Loras", + "type": "integer" + } + }, + "required": [ + "max_loras", + "used_loras", + "free_loras" + ], + "title": "CapacityInfoResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, - "/twinkle/checkpoint_path/{run_id}/{checkpoint_id}": { + "/twinkle/checkpoint_path/{run_id}/{checkpoint_id:path}": { "GET": { - "operationId": "get_checkpoint_path_twinkle_checkpoint_path__run_id___checkpoint_id__get", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_checkpoint_path", + "path": [ { - "in": "path", "name": "run_id", "required": true, "schema": { - "title": "Run Id", "type": "string" } }, { - "in": "path", "name": "checkpoint_id", "required": true, "schema": { - "title": "Checkpoint Id", "type": "string" } } ], - "responses": [ - "200", - "422" - ] + "query": [], + "response": { + "description": "Response body for the /checkpoint_path endpoint.", + "properties": { + "path": { + "title": "Path", + "type": "string" + }, + "twinkle_path": { + "title": "Twinkle Path", + "type": "string" + } + }, + "required": [ + "path", + "twinkle_path" + ], + "title": "CheckpointPathResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/create_session": { "POST": { - "operationId": "create_session_twinkle_create_session_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "description": "Request body for POST /twinkle/create_session.", + "properties": { + "metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Metadata" + } + }, + "title": "CreateSessionRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "create_session", + "path": [], + "query": [], + "response": { + "description": "Response body for POST /twinkle/create_session.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + } + }, + "required": [ + "session_id" + ], + "title": "CreateSessionResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/get_server_capabilities": { "GET": { - "operationId": "get_server_capabilities_twinkle_get_server_capabilities_get", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_server_capabilities", + "path": [], + "query": [], + "response": { + "$defs": { + "SupportedModel": { + "description": "Information about a supported model.", + "properties": { + "model_name": { + "title": "Model Name", + "type": "string" + } + }, + "required": [ + "model_name" + ], + "title": "SupportedModel", + "type": "object" + } + }, + "description": "Response body for the /get_server_capabilities endpoint.", + "properties": { + "supported_models": { + "items": { + "$ref": "#/$defs/SupportedModel" + }, + "title": "Supported Models", + "type": "array" + } + }, + "required": [ + "supported_models" + ], + "title": "GetServerCapabilitiesResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/healthz": { "GET": { - "operationId": "healthz_twinkle_healthz_get", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "healthz", + "path": [], + "query": [], + "response": { + "properties": { + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "status" + ], + "title": "HealthResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/healthz/deep": { "GET": { - "operationId": "healthz_deep_twinkle_healthz_deep_get", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "healthz_deep", + "path": [], + "query": [], + "response": { + "pythonType": "dict" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/session_heartbeat": { "POST": { - "operationId": "session_heartbeat_twinkle_session_heartbeat_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "description": "Request body for POST /twinkle/session_heartbeat.", + "properties": { + "session_id": { + "title": "Session Id", + "type": "string" + } + }, + "required": [ + "session_id" + ], + "title": "SessionHeartbeatRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "session_heartbeat", + "path": [], + "query": [], + "response": { + "description": "Response body for POST /twinkle/session_heartbeat.", + "properties": {}, + "title": "SessionHeartbeatResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/status": { "GET": { - "operationId": "status_twinkle_status_get", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "status", + "path": [], + "query": [], + "response": { + "pythonType": "dict" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/training_runs": { "GET": { - "operationId": "get_training_runs_twinkle_training_runs_get", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_training_runs", + "path": [], + "query": [ { - "in": "query", "name": "limit", "required": false, "schema": { - "default": 20, - "title": "Limit", "type": "integer" } }, { - "in": "query", "name": "offset", "required": false, "schema": { - "default": 0, - "title": "Offset", "type": "integer" } } ], - "responses": [ - "200", - "422" - ] + "response": { + "$defs": { + "Cursor": { + "properties": { + "limit": { + "title": "Limit", + "type": "integer" + }, + "offset": { + "title": "Offset", + "type": "integer" + }, + "total_count": { + "title": "Total Count", + "type": "integer" + } + }, + "required": [ + "limit", + "offset", + "total_count" + ], + "title": "Cursor", + "type": "object" + }, + "TrainingRun": { + "description": "Twinkle training run model.", + "properties": { + "base_model": { + "title": "Base Model", + "type": "string" + }, + "corrupted": { + "default": false, + "title": "Corrupted", + "type": "boolean" + }, + "is_lora": { + "default": false, + "title": "Is Lora", + "type": "boolean" + }, + "last_checkpoint": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Checkpoint" + }, + "last_request_time": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Request Time" + }, + "last_sampler_checkpoint": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Sampler Checkpoint" + }, + "lora_rank": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lora Rank" + }, + "model_owner": { + "title": "Model Owner", + "type": "string" + }, + "save_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Save Dir" + }, + "training_run_id": { + "title": "Training Run Id", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "training_run_id", + "base_model", + "model_owner" + ], + "title": "TrainingRun", + "type": "object" + } + }, + "properties": { + "cursor": { + "$ref": "#/$defs/Cursor" + }, + "training_runs": { + "items": { + "$ref": "#/$defs/TrainingRun" + }, + "title": "Training Runs", + "type": "array" + } + }, + "required": [ + "training_runs", + "cursor" + ], + "title": "TrainingRunsResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/training_runs/{run_id}": { "GET": { - "operationId": "get_training_run_twinkle_training_runs__run_id__get", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_training_run", + "path": [ { - "in": "path", "name": "run_id", "required": true, "schema": { - "title": "Run Id", "type": "string" } } ], - "responses": [ - "200", - "422" - ] + "query": [], + "response": { + "description": "Twinkle training run model.", + "properties": { + "base_model": { + "title": "Base Model", + "type": "string" + }, + "corrupted": { + "default": false, + "title": "Corrupted", + "type": "boolean" + }, + "is_lora": { + "default": false, + "title": "Is Lora", + "type": "boolean" + }, + "last_checkpoint": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Checkpoint" + }, + "last_request_time": { + "anyOf": [ + { + "format": "date-time", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Request Time" + }, + "last_sampler_checkpoint": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Last Sampler Checkpoint" + }, + "lora_rank": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lora Rank" + }, + "model_owner": { + "title": "Model Owner", + "type": "string" + }, + "save_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Save Dir" + }, + "training_run_id": { + "title": "Training Run Id", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "training_run_id", + "base_model", + "model_owner" + ], + "title": "TrainingRun", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/training_runs/{run_id}/checkpoints": { "GET": { - "operationId": "get_run_checkpoints_twinkle_training_runs__run_id__checkpoints_get", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "get_run_checkpoints", + "path": [ { - "in": "path", "name": "run_id", "required": true, "schema": { - "title": "Run Id", "type": "string" } } ], - "responses": [ - "200", - "422" - ] + "query": [], + "response": { + "$defs": { + "Checkpoint": { + "description": "Twinkle checkpoint model.", + "properties": { + "base_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Base Model" + }, + "checkpoint_id": { + "title": "Checkpoint Id", + "type": "string" + }, + "checkpoint_type": { + "title": "Checkpoint Type", + "type": "string" + }, + "is_lora": { + "default": false, + "title": "Is Lora", + "type": "boolean" + }, + "lora_rank": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lora Rank" + }, + "public": { + "default": false, + "title": "Public", + "type": "boolean" + }, + "size_bytes": { + "title": "Size Bytes", + "type": "integer" + }, + "time": { + "format": "date-time", + "title": "Time", + "type": "string" + }, + "train_attn": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Train Attn" + }, + "train_mlp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Train Mlp" + }, + "train_unembed": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Train Unembed" + }, + "twinkle_path": { + "title": "Twinkle Path", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "checkpoint_id", + "checkpoint_type", + "time", + "size_bytes", + "twinkle_path" + ], + "title": "Checkpoint", + "type": "object" + }, + "Cursor": { + "properties": { + "limit": { + "title": "Limit", + "type": "integer" + }, + "offset": { + "title": "Offset", + "type": "integer" + }, + "total_count": { + "title": "Total Count", + "type": "integer" + } + }, + "required": [ + "limit", + "offset", + "total_count" + ], + "title": "Cursor", + "type": "object" + } + }, + "properties": { + "checkpoints": { + "items": { + "$ref": "#/$defs/Checkpoint" + }, + "title": "Checkpoints", + "type": "array" + }, + "cursor": { + "anyOf": [ + { + "$ref": "#/$defs/Cursor" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "checkpoints" + ], + "title": "CheckpointsListResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, - "/twinkle/training_runs/{run_id}/checkpoints/{checkpoint_id}": { + "/twinkle/training_runs/{run_id}/checkpoints/{checkpoint_id:path}": { "DELETE": { - "operationId": "delete_run_checkpoint_twinkle_training_runs__run_id__checkpoints__checkpoint_id__delete", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "delete_run_checkpoint", + "path": [ { - "in": "path", "name": "run_id", "required": true, "schema": { - "title": "Run Id", "type": "string" } }, { - "in": "path", "name": "checkpoint_id", "required": true, "schema": { - "title": "Checkpoint Id", "type": "string" } } ], - "responses": [ - "200", - "422" - ] + "query": [], + "response": { + "properties": { + "message": { + "title": "Message", + "type": "string" + }, + "success": { + "title": "Success", + "type": "boolean" + } + }, + "required": [ + "success", + "message" + ], + "title": "DeleteCheckpointResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/weights_info": { "POST": { - "operationId": "weights_info_twinkle_weights_info_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "properties": { + "twinkle_path": { + "title": "Twinkle Path", + "type": "string" + } + }, + "required": [ + "twinkle_path" + ], + "title": "WeightsInfoRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "weights_info", + "path": [], + "query": [], + "response": { + "description": "Twinkle weights info response.", + "properties": { + "base_model": { + "title": "Base Model", + "type": "string" + }, + "is_lora": { + "default": false, + "title": "Is Lora", + "type": "boolean" + }, + "lora_rank": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lora Rank" + }, + "model_owner": { + "title": "Model Owner", + "type": "string" + }, + "training_run_id": { + "title": "Training Run Id", + "type": "string" + } + }, + "required": [ + "training_run_id", + "base_model", + "model_owner" + ], + "title": "WeightsInfoResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/unload_model": { "POST": { - "operationId": "unload_model_unload_model_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "model_id": { + "title": "Model Id", + "type": "string" + }, + "type": { + "const": "unload_model", + "default": "unload_model", + "title": "Type", + "type": "string" + } + }, + "required": [ + "model_id" + ], + "title": "UnloadModelRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "unload_model", + "path": [], + "query": [], + "response": {}, + "responses": {}, + "statusCode": 200 } }, "/weights_info": { "POST": { - "operationId": "weights_info_weights_info_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": {}, + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "weights_info", + "path": [], + "query": [], + "response": { + "description": "Minimal information for loading public checkpoints.", + "properties": { + "base_model": { + "title": "Base Model", + "type": "string" + }, + "is_lora": { + "title": "Is Lora", + "type": "boolean" + }, + "lora_rank": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lora Rank" + }, + "train_attn": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Train Attn" + }, + "train_mlp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Train Mlp" + }, + "train_unembed": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Train Unembed" + } + }, + "required": [ + "base_model", + "is_lora" + ], + "title": "WeightsInfoResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } } } @@ -536,421 +3940,2897 @@ "paths": { "/healthz": { "GET": { - "operationId": "model_healthz_healthz_get", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "model_healthz", + "path": [], + "query": [], + "response": { + "pythonType": "dict" + }, + "responses": {}, + "statusCode": 200 } }, "/tinker/create_model": { "POST": { - "operationId": "create_model_tinker_create_model_post", - "parameters": [], - "responses": [ - "200", - "422" - ] - } - }, - "/tinker/forward": { - "POST": { - "operationId": "forward_tinker_forward_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "LoraConfig": { + "additionalProperties": false, + "properties": { + "rank": { + "title": "Rank", + "type": "integer" + }, + "seed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seed" + }, + "train_attn": { + "default": true, + "title": "Train Attn", + "type": "boolean" + }, + "train_mlp": { + "default": true, + "title": "Train Mlp", + "type": "boolean" + }, + "train_unembed": { + "default": true, + "title": "Train Unembed", + "type": "boolean" + } + }, + "required": [ + "rank" + ], + "title": "LoraConfig", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "base_model": { + "title": "Base Model", + "type": "string" + }, + "lora_config": { + "anyOf": [ + { + "$ref": "#/$defs/LoraConfig" + }, + { + "type": "null" + } + ], + "default": null + }, + "model_seq_id": { + "title": "Model Seq Id", + "type": "integer" + }, + "session_id": { + "title": "Session Id", + "type": "string" + }, + "type": { + "const": "create_model", + "default": "create_model", + "title": "Type", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "session_id", + "model_seq_id", + "base_model" + ], + "title": "CreateModelRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "create_model", + "path": [], + "query": [], + "response": { + "properties": { + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "sample_sequence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Sequence Ids" + } + }, + "required": [ + "request_id" + ], + "title": "UntypedAPIFuture", + "type": "object" + }, + "responses": {}, + "statusCode": 200 + } + }, + "/tinker/forward": { + "POST": { + "body": [ + { + "name": "body", + "required": true, + "schema": { + "properties": { + "forward_input": { + "properties": { + "data": { + "items": { + "properties": { + "loss_fn_input_spans": { + "pythonType": "'Optional[ProvenanceSpans]'" + }, + "loss_fn_inputs": { + "pythonType": "'LossFnInputs'" + }, + "model_input": { + "pythonType": "'ModelInput'" + }, + "model_input_spans": { + "pythonType": "'Optional[ProvenanceSpans]'" + } + }, + "required": [ + "model_input" + ], + "type": "object" + }, + "type": "array" + }, + "loss_fn": { + "enum": [ + "cross_entropy", + "importance_sampling", + "ppo", + "cispo", + "dro" + ] + }, + "loss_fn_config": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "data", + "loss_fn" + ], + "type": "object" + }, + "model_id": { + "type": "string" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "forward_input", + "model_id" + ], + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward", + "path": [], + "query": [], + "response": { + "properties": { + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "sample_sequence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Sequence Ids" + } + }, + "required": [ + "request_id" + ], + "title": "UntypedAPIFuture", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/tinker/forward_backward": { "POST": { - "operationId": "forward_backward_tinker_forward_backward_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "properties": { + "forward_backward_input": { + "properties": { + "data": { + "items": { + "properties": { + "loss_fn_input_spans": { + "pythonType": "'Optional[ProvenanceSpans]'" + }, + "loss_fn_inputs": { + "pythonType": "'LossFnInputs'" + }, + "model_input": { + "pythonType": "'ModelInput'" + }, + "model_input_spans": { + "pythonType": "'Optional[ProvenanceSpans]'" + } + }, + "required": [ + "model_input" + ], + "type": "object" + }, + "type": "array" + }, + "loss_fn": { + "enum": [ + "cross_entropy", + "importance_sampling", + "ppo", + "cispo", + "dro" + ] + }, + "loss_fn_config": { + "anyOf": [ + { + "additionalProperties": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ] + }, + "type": "object" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "data", + "loss_fn" + ], + "type": "object" + }, + "model_id": { + "type": "string" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "forward_backward_input", + "model_id" + ], + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward_backward", + "path": [], + "query": [], + "response": { + "properties": { + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "sample_sequence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Sequence Ids" + } + }, + "required": [ + "request_id" + ], + "title": "UntypedAPIFuture", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/tinker/get_info": { "POST": { - "operationId": "get_info_tinker_get_info_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "model_id": { + "title": "Model Id", + "type": "string" + }, + "type": { + "const": "get_info", + "default": "get_info", + "title": "Type", + "type": "string" + } + }, + "required": [ + "model_id" + ], + "title": "GetInfoRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "get_info", + "path": [], + "query": [], + "response": { + "$defs": { + "ModelData": { + "description": "Metadata about a model's architecture and configuration.", + "properties": { + "arch": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Arch" + }, + "model_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Name" + }, + "tokenizer_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Tokenizer Id" + } + }, + "title": "ModelData", + "type": "object" + } + }, + "description": "Response containing information about a training client's model.", + "properties": { + "is_lora": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Is Lora" + }, + "lora_rank": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Lora Rank" + }, + "model_data": { + "$ref": "#/$defs/ModelData" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "model_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Name" + }, + "type": { + "anyOf": [ + { + "const": "get_info", + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Type" + } + }, + "required": [ + "model_data", + "model_id" + ], + "title": "GetInfoResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/tinker/load_weights": { "POST": { - "operationId": "load_weights_tinker_load_weights_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "base_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Base Model" + }, + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "model_seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Seq Id" + }, + "optimizer": { + "title": "Optimizer", + "type": "boolean" + }, + "path": { + "title": "Path", + "type": "string" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Session Id" + }, + "type": { + "const": "load_weights", + "default": "load_weights", + "title": "Type", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + }, + "weights_access_token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Weights Access Token" + } + }, + "required": [ + "path", + "optimizer" + ], + "title": "LoadWeightsRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "load_weights", + "path": [], + "query": [], + "response": { + "properties": { + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "sample_sequence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Sequence Ids" + } + }, + "required": [ + "request_id" + ], + "title": "UntypedAPIFuture", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/tinker/optim_step": { "POST": { - "operationId": "optim_step_tinker_optim_step_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "AdamParams": { + "additionalProperties": false, + "properties": { + "beta1": { + "default": 0.9, + "title": "Beta1", + "type": "number" + }, + "beta2": { + "default": 0.95, + "title": "Beta2", + "type": "number" + }, + "eps": { + "default": 1e-12, + "title": "Eps", + "type": "number" + }, + "grad_clip_norm": { + "default": 0.0, + "title": "Grad Clip Norm", + "type": "number" + }, + "learning_rate": { + "default": 0.0001, + "title": "Learning Rate", + "type": "number" + }, + "weight_decay": { + "default": 0.0, + "title": "Weight Decay", + "type": "number" + } + }, + "title": "AdamParams", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "adam_params": { + "$ref": "#/$defs/AdamParams" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "type": { + "const": "optim_step", + "default": "optim_step", + "title": "Type", + "type": "string" + } + }, + "required": [ + "adam_params", + "model_id" + ], + "title": "OptimStepRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "optim_step", + "path": [], + "query": [], + "response": { + "properties": { + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "sample_sequence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Sequence Ids" + } + }, + "required": [ + "request_id" + ], + "title": "UntypedAPIFuture", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/tinker/save_weights": { "POST": { - "operationId": "save_weights_tinker_save_weights_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "model_id": { + "title": "Model Id", + "type": "string" + }, + "overwrite": { + "default": false, + "title": "Overwrite", + "type": "boolean" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "ttl_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ttl Seconds" + }, + "type": { + "const": "save_weights", + "default": "save_weights", + "title": "Type", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "model_id" + ], + "title": "SaveWeightsRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "save_weights", + "path": [], + "query": [], + "response": { + "properties": { + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "sample_sequence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Sequence Ids" + } + }, + "required": [ + "request_id" + ], + "title": "UntypedAPIFuture", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/tinker/save_weights_for_sampler": { "POST": { - "operationId": "save_weights_for_sampler_tinker_save_weights_for_sampler_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "model_id": { + "title": "Model Id", + "type": "string" + }, + "path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Path" + }, + "sampling_session_seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sampling Session Seq Id" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "ttl_seconds": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Ttl Seconds" + }, + "type": { + "const": "save_weights_for_sampler", + "default": "save_weights_for_sampler", + "title": "Type", + "type": "string" + }, + "user_metadata": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "User Metadata" + } + }, + "required": [ + "model_id" + ], + "title": "SaveWeightsForSamplerRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "save_weights_for_sampler", + "path": [], + "query": [], + "response": { + "properties": { + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "sample_sequence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Sequence Ids" + } + }, + "required": [ + "request_id" + ], + "title": "UntypedAPIFuture", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/tinker/unload_model": { "POST": { - "operationId": "unload_model_tinker_unload_model_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": false, + "properties": { + "model_id": { + "title": "Model Id", + "type": "string" + }, + "type": { + "const": "unload_model", + "default": "unload_model", + "title": "Type", + "type": "string" + } + }, + "required": [ + "model_id" + ], + "title": "UnloadModelRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "unload_model", + "path": [], + "query": [], + "response": { + "properties": { + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "sample_sequence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Sequence Ids" + } + }, + "required": [ + "request_id" + ], + "title": "UntypedAPIFuture", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/add_adapter_to_model": { "POST": { - "operationId": "add_adapter_to_model_twinkle_add_adapter_to_model_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "config": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Config" + }, + "save_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Save Dir" + } + }, + "required": [ + "adapter_name" + ], + "title": "AddAdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "add_adapter_to_model", + "path": [], + "query": [], + "response": { + "description": "Response body for the /add_adapter_to_sampler endpoint.", + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "status": { + "default": "ok", + "title": "Status", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AddAdapterResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/add_metric": { "POST": { - "operationId": "add_metric_twinkle_add_metric_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "is_training": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Is Training" + }, + "metric_cls": { + "title": "Metric Cls", + "type": "string" + } + }, + "required": [ + "metric_cls", + "adapter_name" + ], + "title": "AddMetricRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "add_metric", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/apply_patch": { "POST": { - "operationId": "apply_patch_twinkle_apply_patch_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "patch_cls": { + "title": "Patch Cls", + "type": "string" + } + }, + "required": [ + "patch_cls", + "adapter_name" + ], + "title": "ApplyPatchRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "apply_patch", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/backward": { "POST": { - "operationId": "backward_twinkle_backward_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "backward", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/calculate_loss": { "POST": { - "operationId": "calculate_loss_twinkle_calculate_loss_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "calculate_loss", + "path": [], + "query": [], + "response": { + "description": "Response for /calculate_loss endpoint (returns float).", + "properties": { + "result": { + "title": "Result", + "type": "number" + } + }, + "required": [ + "result" + ], + "title": "CalculateLossResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/calculate_metric": { "POST": { - "operationId": "calculate_metric_twinkle_calculate_metric_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "is_training": { + "default": true, + "title": "Is Training", + "type": "boolean" + } + }, + "required": [ + "adapter_name" + ], + "title": "CalculateMetricRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "calculate_metric", + "path": [], + "query": [], + "response": { + "description": "Response for /calculate_metric endpoint (returns Dict).", + "properties": { + "result": { + "additionalProperties": true, + "title": "Result", + "type": "object" + } + }, + "required": [ + "result" + ], + "title": "CalculateMetricResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/clip_grad_and_step": { "POST": { - "operationId": "clip_grad_and_step_twinkle_clip_grad_and_step_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "max_grad_norm": { + "default": 1.0, + "title": "Max Grad Norm", + "type": "number" + }, + "norm_type": { + "default": 2, + "title": "Norm Type", + "type": "integer" + } + }, + "required": [ + "adapter_name" + ], + "title": "ClipGradAndStepRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "clip_grad_and_step", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/clip_grad_norm": { "POST": { - "operationId": "clip_grad_norm_twinkle_clip_grad_norm_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "clip_grad_norm", + "path": [], + "query": [], + "response": { + "description": "Response for /clip_grad_norm endpoint (returns float as str).", + "properties": { + "result": { + "title": "Result", + "type": "string" + } + }, + "required": [ + "result" + ], + "title": "ClipGradNormResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/create": { "POST": { - "operationId": "create_twinkle_create_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": {}, + "title": "CreateRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "create", + "path": [], + "query": [], + "response": { + "description": "Response for /create endpoint.", + "properties": { + "status": { + "default": "ok", + "title": "Status", + "type": "string" + } + }, + "title": "CreateResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/forward": { "POST": { - "operationId": "forward_twinkle_forward_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "inputs": { + "title": "Inputs" + } + }, + "required": [ + "inputs", + "adapter_name" + ], + "title": "ForwardRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward", + "path": [], + "query": [], + "response": { + "description": "Response for /forward and /forward_only endpoints (returns ModelOutput).", + "properties": { + "result": { + "title": "Result" + } + }, + "required": [ + "result" + ], + "title": "ForwardResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/forward_backward": { "POST": { - "operationId": "forward_backward_twinkle_forward_backward_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "inputs": { + "title": "Inputs" + } + }, + "required": [ + "inputs", + "adapter_name" + ], + "title": "ForwardRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward_backward", + "path": [], + "query": [], + "response": { + "description": "Response for /forward_backward endpoint (returns ModelOutput).", + "properties": { + "result": { + "title": "Result" + } + }, + "required": [ + "result" + ], + "title": "ForwardBackwardResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/forward_backward_from_data_plane": { "POST": { - "operationId": "forward_backward_from_data_plane_twinkle_forward_backward_from_data_plane_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "DataRef": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + } + }, + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "input_field": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Input Field" + }, + "input_refs": { + "items": { + "$ref": "#/$defs/DataRef" + }, + "minItems": 1, + "title": "Input Refs", + "type": "array" + }, + "kwarg_fields": { + "additionalProperties": { + "type": "string" + }, + "title": "Kwarg Fields", + "type": "object" + } + }, + "required": [ + "input_refs", + "adapter_name" + ], + "title": "DataPlaneForwardRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward_backward_from_data_plane", + "path": [], + "query": [], + "response": { + "description": "Response for /forward_backward endpoint (returns ModelOutput).", + "properties": { + "result": { + "title": "Result" + } + }, + "required": [ + "result" + ], + "title": "ForwardBackwardResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/forward_from_data_plane": { "POST": { - "operationId": "forward_from_data_plane_twinkle_forward_from_data_plane_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "DataRef": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + } + }, + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "input_field": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Input Field" + }, + "input_refs": { + "items": { + "$ref": "#/$defs/DataRef" + }, + "minItems": 1, + "title": "Input Refs", + "type": "array" + }, + "kwarg_fields": { + "additionalProperties": { + "type": "string" + }, + "title": "Kwarg Fields", + "type": "object" + } + }, + "required": [ + "input_refs", + "adapter_name" + ], + "title": "DataPlaneForwardRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward_from_data_plane", + "path": [], + "query": [], + "response": { + "description": "Response for /forward and /forward_only endpoints (returns ModelOutput).", + "properties": { + "result": { + "title": "Result" + } + }, + "required": [ + "result" + ], + "title": "ForwardResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/forward_only": { "POST": { - "operationId": "forward_only_twinkle_forward_only_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Adapter Name" + }, + "inputs": { + "title": "Inputs" + } + }, + "required": [ + "inputs" + ], + "title": "ForwardOnlyRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward_only", + "path": [], + "query": [], + "response": { + "description": "Response for /forward and /forward_only endpoints (returns ModelOutput).", + "properties": { + "result": { + "title": "Result" + } + }, + "required": [ + "result" + ], + "title": "ForwardResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/forward_only_from_data_plane": { "POST": { - "operationId": "forward_only_from_data_plane_twinkle_forward_only_from_data_plane_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "DataRef": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + } + }, + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "input_field": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Input Field" + }, + "input_refs": { + "items": { + "$ref": "#/$defs/DataRef" + }, + "minItems": 1, + "title": "Input Refs", + "type": "array" + }, + "kwarg_fields": { + "additionalProperties": { + "type": "string" + }, + "title": "Kwarg Fields", + "type": "object" + }, + "output_fields": { + "additionalProperties": { + "type": "string" + }, + "title": "Output Fields", + "type": "object" + }, + "output_ref": { + "anyOf": [ + { + "$ref": "#/$defs/DataRef" + }, + { + "type": "null" + } + ], + "default": null + } + }, + "required": [ + "input_refs", + "adapter_name" + ], + "title": "DataPlaneForwardOnlyRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "forward_only_from_data_plane", + "path": [], + "query": [], + "response": { + "description": "Response for /forward and /forward_only endpoints (returns ModelOutput).", + "properties": { + "result": { + "title": "Result" + } + }, + "required": [ + "result" + ], + "title": "ForwardResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/get_state_dict": { "POST": { - "operationId": "get_state_dict_twinkle_get_state_dict_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "GetStateDictRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "get_state_dict", + "path": [], + "query": [], + "response": { + "description": "Response for /get_state_dict endpoint (returns Dict).", + "properties": { + "result": { + "additionalProperties": true, + "title": "Result", + "type": "object" + } + }, + "required": [ + "result" + ], + "title": "GetStateDictResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/get_train_configs": { "POST": { - "operationId": "get_train_configs_twinkle_get_train_configs_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "get_train_configs", + "path": [], + "query": [], + "response": { + "description": "Response for /get_train_configs endpoint (returns str).", + "properties": { + "result": { + "title": "Result", + "type": "string" + } + }, + "required": [ + "result" + ], + "title": "GetTrainConfigsResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/load": { "POST": { - "operationId": "load_twinkle_load_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "load_optimizer": { + "default": false, + "title": "Load Optimizer", + "type": "boolean" + }, + "name": { + "title": "Name", + "type": "string" + } + }, + "required": [ + "adapter_name", + "name" + ], + "title": "LoadRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "load", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/lr_step": { "POST": { - "operationId": "lr_step_twinkle_lr_step_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "lr_step", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/remove_adapter": { "POST": { - "operationId": "remove_adapter_twinkle_remove_adapter_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "remove_adapter", + "path": [], + "query": [], + "response": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/resume_from_checkpoint": { "POST": { - "operationId": "resume_from_checkpoint_twinkle_resume_from_checkpoint_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "description": "Request for /resume_from_checkpoint endpoint.", + "properties": { + "adapter_name": { + "default": "", + "title": "Adapter Name", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + }, + "resume_only_model": { + "default": false, + "title": "Resume Only Model", + "type": "boolean" + } + }, + "required": [ + "name" + ], + "title": "ResumeFromCheckpointRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "resume_from_checkpoint", + "path": [], + "query": [], + "response": { + "description": "Response for /resume_from_checkpoint endpoint.", + "properties": { + "result": { + "additionalProperties": true, + "title": "Result", + "type": "object" + } + }, + "required": [ + "result" + ], + "title": "TrainingProgressResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/save": { "POST": { - "operationId": "save_twinkle_save_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "is_sampler": { + "default": false, + "title": "Is Sampler", + "type": "boolean" + }, + "name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Name" + }, + "save_optimizer": { + "default": false, + "title": "Save Optimizer", + "type": "boolean" + } + }, + "required": [ + "adapter_name" + ], + "title": "SaveRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "save", + "path": [], + "query": [], + "response": { + "description": "Response for /save endpoint (returns twinkle path + checkpoint dir).", + "properties": { + "checkpoint_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Checkpoint Dir" + }, + "twinkle_path": { + "title": "Twinkle Path", + "type": "string" + } + }, + "required": [ + "twinkle_path" + ], + "title": "SaveResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/set_loss": { "POST": { - "operationId": "set_loss_twinkle_set_loss_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "loss_cls": { + "title": "Loss Cls", + "type": "string" + } + }, + "required": [ + "loss_cls", + "adapter_name" + ], + "title": "SetLossRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "set_loss", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/set_lr_scheduler": { "POST": { - "operationId": "set_lr_scheduler_twinkle_set_lr_scheduler_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "scheduler_cls": { + "title": "Scheduler Cls", + "type": "string" + } + }, + "required": [ + "scheduler_cls", + "adapter_name" + ], + "title": "SetLrSchedulerRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "set_lr_scheduler", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/set_optimizer": { "POST": { - "operationId": "set_optimizer_twinkle_set_optimizer_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "optimizer_cls": { + "title": "Optimizer Cls", + "type": "string" + } + }, + "required": [ + "optimizer_cls", + "adapter_name" + ], + "title": "SetOptimizerRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "set_optimizer", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/set_processor": { "POST": { - "operationId": "set_processor_twinkle_set_processor_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "processor_cls": { + "title": "Processor Cls", + "type": "string" + } + }, + "required": [ + "processor_cls", + "adapter_name" + ], + "title": "SetProcessorRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "set_processor", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/set_template": { "POST": { - "operationId": "set_template_twinkle_set_template_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "template_cls": { + "title": "Template Cls", + "type": "string" + } + }, + "required": [ + "template_cls", + "adapter_name" + ], + "title": "SetTemplateRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "set_template", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/step": { "POST": { - "operationId": "step_twinkle_step_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "step", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/upload_status/{request_id}": { "GET": { - "operationId": "upload_status_twinkle_upload_status__request_id__get", - "parameters": [ + "body": [], + "cookies": [], + "headers": [], + "operationId": "upload_status", + "path": [ { - "in": "path", "name": "request_id", "required": true, "schema": { - "title": "Request Id", "type": "string" } } ], - "responses": [ - "200", - "422" - ] + "query": [], + "response": { + "description": "Response for /upload_status/{request_id} endpoint.", + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Error" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "status": { + "title": "Status", + "type": "string" + } + }, + "required": [ + "request_id", + "status" + ], + "title": "UploadStatusResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/upload_to_hub": { "POST": { - "operationId": "upload_to_hub_twinkle_upload_to_hub_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "async_upload": { + "default": false, + "title": "Async Upload", + "type": "boolean" + }, + "checkpoint_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "additionalProperties": true, + "type": "object" + } + ], + "title": "Checkpoint Dir" + }, + "hub_model_id": { + "title": "Hub Model Id", + "type": "string" + }, + "hub_token": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Hub Token" + } + }, + "required": [ + "checkpoint_dir", + "hub_model_id" + ], + "title": "UploadToHubRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "upload_to_hub", + "path": [], + "query": [], + "response": { + "description": "Response for /upload_to_hub endpoint.", + "properties": { + "request_id": { + "title": "Request Id", + "type": "string" + } + }, + "required": [ + "request_id" + ], + "title": "UploadToHubResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/zero_grad": { "POST": { - "operationId": "zero_grad_twinkle_zero_grad_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "zero_grad", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } } } @@ -959,22 +6839,101 @@ "paths": { "/twinkle/call": { "POST": { - "operationId": "call_twinkle_call_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "function": { + "title": "Function", + "type": "string" + }, + "processor_id": { + "title": "Processor Id", + "type": "string" + } + }, + "required": [ + "processor_id", + "function" + ], + "title": "ProcessorCallRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "call", + "path": [], + "query": [], + "response": { + "description": "Response body for the /call endpoint.", + "properties": { + "result": { + "title": "Result" + } + }, + "required": [ + "result" + ], + "title": "ProcessorCallResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/create": { "POST": { - "operationId": "create_twinkle_create_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "class_type": { + "title": "Class Type", + "type": "string" + }, + "processor_type": { + "title": "Processor Type", + "type": "string" + } + }, + "required": [ + "processor_type", + "class_type" + ], + "title": "ProcessorCreateRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "create", + "path": [], + "query": [], + "response": { + "description": "Response body for the /create endpoint.", + "properties": { + "processor_id": { + "title": "Processor Id", + "type": "string" + } + }, + "required": [ + "processor_id" + ], + "title": "ProcessorCreateResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } } } @@ -983,91 +6942,1130 @@ "paths": { "/tinker/asample": { "POST": { - "operationId": "asample_tinker_asample_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "DmelChunk": { + "additionalProperties": false, + "properties": { + "dmel": { + "format": "binary", + "title": "Dmel", + "type": "string" + }, + "type": { + "const": "dmel", + "default": "dmel", + "title": "Type", + "type": "string" + } + }, + "required": [ + "dmel" + ], + "title": "DmelChunk", + "type": "object" + }, + "EncodedTextChunk": { + "additionalProperties": false, + "properties": { + "tokens": { + "items": { + "type": "integer" + }, + "title": "Tokens", + "type": "array" + }, + "type": { + "const": "encoded_text", + "default": "encoded_text", + "title": "Type", + "type": "string" + } + }, + "required": [ + "tokens" + ], + "title": "EncodedTextChunk", + "type": "object" + }, + "ImageAssetPointerChunk": { + "additionalProperties": false, + "properties": { + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "location": { + "title": "Location", + "type": "string" + }, + "type": { + "const": "image_asset_pointer", + "default": "image_asset_pointer", + "title": "Type", + "type": "string" + } + }, + "required": [ + "format", + "location" + ], + "title": "ImageAssetPointerChunk", + "type": "object" + }, + "ImageChunk": { + "additionalProperties": false, + "properties": { + "data": { + "format": "binary", + "title": "Data", + "type": "string" + }, + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "type": { + "const": "image", + "default": "image", + "title": "Type", + "type": "string" + } + }, + "required": [ + "data", + "format" + ], + "title": "ImageChunk", + "type": "object" + }, + "ModelInput": { + "additionalProperties": false, + "properties": { + "chunks": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/EncodedTextChunk" + }, + { + "$ref": "#/$defs/ImageAssetPointerChunk" + }, + { + "$ref": "#/$defs/ImageChunk" + }, + { + "$ref": "#/$defs/DmelChunk" + } + ] + }, + "title": "Chunks", + "type": "array" + } + }, + "required": [ + "chunks" + ], + "title": "ModelInput", + "type": "object" + }, + "SamplingParams": { + "properties": { + "max_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Max Tokens" + }, + "seed": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seed" + }, + "stop": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Stop" + }, + "temperature": { + "default": 1, + "title": "Temperature", + "type": "number" + }, + "top_k": { + "default": -1, + "title": "Top K", + "type": "integer" + }, + "top_p": { + "default": 1, + "title": "Top P", + "type": "number" + } + }, + "title": "SamplingParams", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "base_model": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Base Model" + }, + "model_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Path" + }, + "num_samples": { + "default": 1, + "title": "Num Samples", + "type": "integer" + }, + "prompt": { + "$ref": "#/$defs/ModelInput" + }, + "prompt_logprobs": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Prompt Logprobs" + }, + "record_stability_info": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Record Stability Info" + }, + "sampling_params": { + "$ref": "#/$defs/SamplingParams" + }, + "sampling_session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sampling Session Id" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" + }, + "topk_prompt_logprobs": { + "default": 0, + "title": "Topk Prompt Logprobs", + "type": "integer" + }, + "topk_sample_logprobs": { + "default": 0, + "title": "Topk Sample Logprobs", + "type": "integer" + }, + "type": { + "const": "sample", + "default": "sample", + "title": "Type", + "type": "string" + } + }, + "required": [ + "prompt", + "sampling_params" + ], + "title": "SampleRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "asample", + "path": [], + "query": [], + "response": { + "properties": { + "model_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Model Id" + }, + "request_id": { + "title": "Request Id", + "type": "string" + }, + "sample_sequence_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sample Sequence Ids" + } + }, + "required": [ + "request_id" + ], + "title": "UntypedAPIFuture", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/add_adapter_to_sampler": { "POST": { - "operationId": "add_adapter_to_sampler_twinkle_add_adapter_to_sampler_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "config": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Config" + }, + "save_dir": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Save Dir" + } + }, + "required": [ + "adapter_name" + ], + "title": "AddAdapterRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "add_adapter_to_sampler", + "path": [], + "query": [], + "response": { + "description": "Response body for the /add_adapter_to_sampler endpoint.", + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "status": { + "default": "ok", + "title": "Status", + "type": "string" + } + }, + "required": [ + "adapter_name" + ], + "title": "AddAdapterResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/apply_patch": { "POST": { - "operationId": "apply_patch_twinkle_apply_patch_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "patch_cls": { + "title": "Patch Cls", + "type": "string" + } + }, + "required": [ + "patch_cls", + "adapter_name" + ], + "title": "ApplyPatchRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "apply_patch", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/create": { "POST": { - "operationId": "create_twinkle_create_post", - "parameters": [], - "responses": [ - "200" - ] + "body": [], + "cookies": [], + "headers": [], + "operationId": "create", + "path": [], + "query": [], + "response": { + "description": "Response for /create endpoint.", + "properties": { + "status": { + "default": "ok", + "title": "Status", + "type": "string" + } + }, + "title": "CreateResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/sample": { "POST": { - "operationId": "sample_twinkle_sample_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "description": "Request body for the /sample endpoint.", + "properties": { + "adapter_name": { + "default": "", + "description": "Adapter name for LoRA inference", + "title": "Adapter Name", + "type": "string" + }, + "adapter_uri": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Adapter URI (twinkle:// path or local path) for LoRA inference", + "title": "Adapter Uri" + }, + "inputs": { + "description": "List of Trajectory or InputFeature dicts", + "title": "Inputs" + }, + "sampling_params": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sampling parameters (max_tokens, temperature, num_samples, etc.)", + "title": "Sampling Params" + } + }, + "required": [ + "inputs" + ], + "title": "SampleRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "sample", + "path": [], + "query": [], + "response": { + "$defs": { + "SampleResponseModel": { + "description": "Mirroring twinkle.data_format.SampleResponse.", + "properties": { + "prompt_logprobs": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Prompt Logprobs" + }, + "prompt_token_ids": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Token IDs of the prompt the sequences continue", + "title": "Prompt Token Ids" + }, + "sequences": { + "description": "List of sampled sequences", + "items": { + "$ref": "#/$defs/SampledSequenceModel" + }, + "title": "Sequences", + "type": "array" + }, + "topk_prompt_logprobs": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "type": "array" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Topk Prompt Logprobs" + } + }, + "required": [ + "sequences" + ], + "title": "SampleResponseModel", + "type": "object" + }, + "SampledSequenceModel": { + "description": "A single sampled sequence, mirroring twinkle.data_format.SampledSequence.", + "properties": { + "decoded": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Decoded text of the sampled sequence", + "title": "Decoded" + }, + "logprobs": { + "anyOf": [ + { + "items": { + "anyOf": [ + { + "items": { + "maxItems": 2, + "minItems": 2, + "prefixItems": [ + { + "type": "integer" + }, + { + "type": "number" + } + ], + "type": "array" + }, + "type": "array" + }, + { + "type": "null" + } + ] + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Per-token log-probabilities", + "title": "Logprobs" + }, + "new_input_feature": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Updated InputFeature after sampling (input_ids, labels, etc.)", + "title": "New Input Feature" + }, + "stop_reason": { + "description": "Stop reason: 'length' or 'stop'", + "enum": [ + "length", + "stop", + "abort", + "error" + ], + "title": "Stop Reason", + "type": "string" + }, + "tokens": { + "description": "Token IDs of the sampled sequence", + "items": { + "type": "integer" + }, + "title": "Tokens", + "type": "array" + } + }, + "required": [ + "stop_reason", + "tokens" + ], + "title": "SampledSequenceModel", + "type": "object" + } + }, + "description": "Response body for the /sample endpoint", + "properties": { + "samples": { + "description": "List of sample responses", + "items": { + "$ref": "#/$defs/SampleResponseModel" + }, + "title": "Samples", + "type": "array" + } + }, + "required": [ + "samples" + ], + "title": "SampleResponseModelList", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/sample_stream": { "POST": { - "operationId": "sample_stream_twinkle_sample_stream_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "description": "Request body for the /sample endpoint.", + "properties": { + "adapter_name": { + "default": "", + "description": "Adapter name for LoRA inference", + "title": "Adapter Name", + "type": "string" + }, + "adapter_uri": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Adapter URI (twinkle:// path or local path) for LoRA inference", + "title": "Adapter Uri" + }, + "inputs": { + "description": "List of Trajectory or InputFeature dicts", + "title": "Inputs" + }, + "sampling_params": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sampling parameters (max_tokens, temperature, num_samples, etc.)", + "title": "Sampling Params" + } + }, + "required": [ + "inputs" + ], + "title": "SampleRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "sample_stream", + "path": [], + "query": [], + "response": { + "type": "null" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/sample_to_data_plane": { "POST": { - "operationId": "sample_to_data_plane_twinkle_sample_to_data_plane_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "$defs": { + "DataRef": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + } + }, + "properties": { + "adapter_name": { + "default": "", + "title": "Adapter Name", + "type": "string" + }, + "adapter_uri": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Adapter Uri" + }, + "group_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Group Ids" + }, + "input_ref": { + "anyOf": [ + { + "$ref": "#/$defs/DataRef" + }, + { + "type": "null" + } + ], + "default": null + }, + "inputs": { + "default": null, + "title": "Inputs" + }, + "num_samples": { + "default": 1, + "title": "Num Samples", + "type": "integer" + }, + "policy_version": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Policy Version" + }, + "sampling_params": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Sampling Params" + } + }, + "title": "DataPlaneSampleRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "sample_to_data_plane", + "path": [], + "query": [], + "response": { + "description": "Opaque reference to rows stored in the server-side TransferQueue.", + "properties": { + "fields": { + "items": { + "type": "string" + }, + "title": "Fields", + "type": "array" + }, + "kind": { + "default": "data", + "title": "Kind", + "type": "string" + }, + "num_tokens": { + "default": 0, + "title": "Num Tokens", + "type": "integer" + }, + "ref_id": { + "title": "Ref Id", + "type": "string" + }, + "size": { + "title": "Size", + "type": "integer" + } + }, + "required": [ + "ref_id", + "size" + ], + "title": "DataRef", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/set_template": { "POST": { - "operationId": "set_template_twinkle_set_template_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "additionalProperties": true, + "properties": { + "adapter_name": { + "title": "Adapter Name", + "type": "string" + }, + "template_cls": { + "title": "Template Cls", + "type": "string" + } + }, + "required": [ + "template_cls", + "adapter_name" + ], + "title": "SetTemplateRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "set_template", + "path": [], + "query": [], + "response": { + "description": "Response for /set_template endpoint.", + "properties": { + "status": { + "default": "ok", + "title": "Status", + "type": "string" + } + }, + "title": "SetTemplateResponse", + "type": "object" + }, + "responses": {}, + "statusCode": 200 } }, "/twinkle/unload_adapter_paths": { "POST": { - "operationId": "unload_adapter_paths_twinkle_unload_adapter_paths_post", - "parameters": [], - "responses": [ - "200", - "422" - ] + "body": [ + { + "name": "body", + "required": true, + "schema": { + "properties": { + "adapter_paths": { + "items": { + "type": "string" + }, + "title": "Adapter Paths", + "type": "array" + } + }, + "required": [ + "adapter_paths" + ], + "title": "UnloadAdapterPathsRequest", + "type": "object" + } + } + ], + "cookies": [], + "headers": [], + "operationId": "unload_adapter_paths", + "path": [], + "query": [], + "response": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "responses": {}, + "statusCode": 200 } } } diff --git a/tests/server/contract/client_api_harness.py b/tests/server/contract/client_api_harness.py index 0496a1b0..919639bb 100644 --- a/tests/server/contract/client_api_harness.py +++ b/tests/server/contract/client_api_harness.py @@ -2,10 +2,10 @@ """ Client-API contract harness. -Builds the four FastAPI apps used by the Ray Serve deployments (Gateway, Model, -Sampler, Processor) by registering their route-registration helpers against a -fresh FastAPI instance, then extracts the client-facing surface (route paths, -HTTP methods, and request/response schemas) as a stable JSON dict. +Builds the five FastAPI apps used by the Ray Serve deployments (Data Plane, +Gateway, Model, Sampler, Processor) by registering their route-registration helpers against a +fresh FastAPI instance, then extracts route paths, methods, parameters, and +recursive request/response type shapes as a stable JSON dict. Used to: - snapshot the current surface into ``client_api_baseline.json`` before the @@ -25,12 +25,17 @@ """ from __future__ import annotations +import dataclasses import json -from collections.abc import Callable +import sys +import types as pytypes +from collections.abc import Callable, Mapping, Sequence +from enum import Enum from fastapi import FastAPI -from fastapi.openapi.utils import get_openapi +from fastapi.routing import APIRoute from pathlib import Path -from typing import Any +from pydantic import BaseModel +from typing import Annotated, Any, Literal, Union, get_args, get_origin, get_type_hints # ----- App build helpers --------------------------------------------------- # @@ -39,6 +44,14 @@ def _noop_self() -> None: return None +def build_data_plane_app() -> FastAPI: + from twinkle.server.data_plane.handlers import register_data_plane_routes + + app = FastAPI() + register_data_plane_routes(app, _noop_self) + return app + + def build_gateway_app() -> FastAPI: from twinkle.server.gateway.openai_handlers import _register_openai_routes from twinkle.server.gateway.tinker_handlers import _register_tinker_routes @@ -80,6 +93,7 @@ def build_processor_app() -> FastAPI: APP_BUILDERS: dict[str, Callable[[], FastAPI]] = { + 'data_plane': build_data_plane_app, 'gateway': build_gateway_app, 'model': build_model_app, 'sampler': build_sampler_app, @@ -91,41 +105,95 @@ def build_processor_app() -> FastAPI: _HTTP_METHODS = {'GET', 'POST', 'PUT', 'PATCH', 'DELETE'} -def _extract_app_surface(app: FastAPI) -> dict[str, Any]: - """Return a SLIM client-contract view of ``app``'s OpenAPI surface. - - Snapshots, per path and HTTP method, only the stable client-facing contract: - the ``operationId``, the ``parameters``, and the set of response status - codes. The full ``components.schemas`` body and per-operation ``requestBody`` - schema are intentionally NOT snapshotted — they churn on Pydantic / FastAPI - version bumps without representing a real client-contract change. Route - paths, HTTP methods, and response status codes remain frozen. - """ - spec = get_openapi( - title='contract', - version='0.0.0', - routes=app.routes, - ) +def _type_contract(annotation: Any, seen: frozenset[str] = frozenset()) -> Any: + """Build a stable field-level schema for Pydantic models and SDK dataclasses.""" + if annotation is None or annotation is type(None): + return {'type': 'null'} + if annotation is Any: + return {} + origin = get_origin(annotation) + args = get_args(annotation) + if origin is Annotated: + return _type_contract(args[0], seen) + if origin in (Union, pytypes.UnionType): + return {'anyOf': [_type_contract(arg, seen) for arg in args]} + if origin in (list, set, tuple, Sequence): + return {'type': 'array', 'items': _type_contract(args[0], seen) if args else {}} + if origin in (dict, Mapping): + return {'type': 'object', 'additionalProperties': _type_contract(args[1], seen) if len(args) > 1 else {}} + if origin is Literal: + return {'enum': list(args)} + if isinstance(annotation, type) and issubclass(annotation, Enum): + return {'enum': [item.value for item in annotation]} + if isinstance(annotation, type) and issubclass(annotation, BaseModel): + return annotation.model_json_schema() + if isinstance(annotation, type) and dataclasses.is_dataclass(annotation): + name = f'{annotation.__module__}.{annotation.__qualname__}' + if name in seen: + return {'$ref': name} + module = sys.modules.get(annotation.__module__) + try: + hints = get_type_hints(annotation, globalns=vars(module) if module else None) + except (NameError, TypeError): + hints = annotation.__annotations__ + properties = {} + required = [] + for field in dataclasses.fields(annotation): + if not field.init or field.name.startswith('_'): + continue + properties[field.name] = _type_contract(hints.get(field.name, Any), seen | {name}) + if field.default is dataclasses.MISSING and field.default_factory is dataclasses.MISSING: + required.append(field.name) + result = {'type': 'object', 'properties': properties} + if required: + result['required'] = required + return result + primitive = {str: 'string', int: 'integer', float: 'number', bool: 'boolean'} + if annotation in primitive: + return {'type': primitive[annotation]} + return {'pythonType': getattr(annotation, '__qualname__', repr(annotation))} + + +def _parameter_contract(field: Any) -> dict[str, Any]: + annotation = getattr(field.field_info, 'annotation', field.type_) + return { + 'name': field.alias, + 'required': bool(field.required), + 'schema': _type_contract(annotation), + } + +def _extract_app_surface(app: FastAPI) -> dict[str, Any]: + """Return every route's complete request and response type shape.""" paths: dict[str, dict[str, Any]] = {} - for path, ops in (spec.get('paths') or {}).items(): - clean_ops: dict[str, Any] = {} - for method, op in ops.items(): - if method.upper() not in _HTTP_METHODS: - continue - clean_ops[method.upper()] = { - 'operationId': op.get('operationId'), - 'parameters': op.get('parameters', []), - 'responses': sorted((op.get('responses') or {}).keys()), + for route in app.routes: + if not isinstance(route, APIRoute): + continue + extra_responses = {} + for status, response in route.responses.items(): + extra_responses[str(status)] = { + 'description': response.get('description'), + 'content': response.get('content'), + 'model': _type_contract(response.get('model')) if response.get('model') else None, } - if clean_ops: - paths[path] = clean_ops - + operation = { + 'operationId': route.operation_id or route.name, + 'body': [_parameter_contract(field) for field in route.dependant.body_params], + 'path': [_parameter_contract(field) for field in route.dependant.path_params], + 'query': [_parameter_contract(field) for field in route.dependant.query_params], + 'headers': [_parameter_contract(field) for field in route.dependant.header_params], + 'cookies': [_parameter_contract(field) for field in route.dependant.cookie_params], + 'response': _type_contract(route.response_model), + 'responses': extra_responses, + 'statusCode': route.status_code or 200, + } + for method in sorted(route.methods & _HTTP_METHODS): + paths.setdefault(route.path, {})[method] = operation return {'paths': paths} def extract_full_surface() -> dict[str, Any]: - """Build all four apps and return a per-app contract surface dict.""" + """Build all five apps and return a per-app contract surface dict.""" surface: dict[str, Any] = {} for name, builder in APP_BUILDERS.items(): app = builder() diff --git a/tests/server/contract/test_client_api_contract.py b/tests/server/contract/test_client_api_contract.py index afed5e2c..ea0f743b 100644 --- a/tests/server/contract/test_client_api_contract.py +++ b/tests/server/contract/test_client_api_contract.py @@ -1,9 +1,9 @@ # Copyright (c) ModelScope Contributors. All rights reserved. """Zero-wire-change contract guard (T8.1 / R8 / Property 10). -Re-exports the OpenAPI surface of all four apps and compares it field-by-field with -the baseline captured before this spec's implementation (T0.1). The diff must be -empty. Also asserts the load-bearing invariants: ``schedule_task_and_wait`` still +Exports the request/response surface of all five apps and compares it field-by-field with +the canonical baseline. The diff must be empty. Also asserts the load-bearing +invariants: ``schedule_task_and_wait`` still exists and the only client-side additions are ``types/base.py`` and ``types/errors.py``. """ from __future__ import annotations @@ -13,11 +13,12 @@ from tests.server.contract.client_api_harness import extract_full_surface, load_baseline -def test_openapi_surface_matches_baseline(): +def test_wire_surface_matches_baseline(): current = extract_full_surface() baseline = load_baseline() + assert set(current) == {'data_plane', 'gateway', 'model', 'processor', 'sampler'} assert current == baseline, ( - 'Client-facing OpenAPI surface changed vs the pre-implementation baseline; ' + 'Client-facing wire surface changed vs the canonical baseline; ' 'this spec must be zero-wire-change. Diffing apps: ' f'{[a for a in set(current) | set(baseline) if current.get(a) != baseline.get(a)]}') diff --git a/tests/server/contract/test_error_wire.py b/tests/server/contract/test_error_wire.py new file mode 100644 index 00000000..df6be289 --- /dev/null +++ b/tests/server/contract/test_error_wire.py @@ -0,0 +1,39 @@ +from __future__ import annotations + +from fastapi import FastAPI +from fastapi.testclient import TestClient +from tinker.types import RequestFailedResponse + +from twinkle.server.gateway.tinker_handlers import _register_tinker_routes + + +class _State: + + async def get_future(self, request_id: str): + return { + 'status': 'failed', + 'result': { + 'error': 'backend timed out', + 'category': 'server', + 'error_code': 504, + 'request_id': request_id, + }, + } + + +class _Gateway: + state = _State() + + +def test_retrieve_future_returns_parseable_error_payload(): + app = FastAPI() + _register_tinker_routes(app, lambda: _Gateway()) + + response = TestClient(app).post('/retrieve_future', json={'request_id': 'req-1'}) + + assert response.status_code == 200 + body = response.json() + assert body['error_code'] == 504 + assert body['request_id'] == 'req-1' + parsed = RequestFailedResponse.model_validate(body) + assert parsed.category.value == 'server' diff --git a/tests/server/integration/test_actor_recovery.py b/tests/server/integration/test_actor_recovery.py index 2ec4f807..64696637 100644 --- a/tests/server/integration/test_actor_recovery.py +++ b/tests/server/integration/test_actor_recovery.py @@ -7,8 +7,10 @@ from __future__ import annotations import pytest +from fastapi import FastAPI from twinkle.server.model.app import ModelManagement +from twinkle.server.model.twinkle_handlers import _register_twinkle_routes class _MockModel: @@ -24,6 +26,7 @@ def ping(self) -> bool: class _HealthHarness: # Reuse the real implementations under test. + _run_model_health_probe = ModelManagement._run_model_health_probe check_model_health = ModelManagement.check_model_health mark_unhealthy = ModelManagement.mark_unhealthy _probe_after_timeout = ModelManagement._probe_after_timeout @@ -58,6 +61,20 @@ async def test_timeout_probe_marks_unhealthy_then_recovers(): assert h._model_unhealthy is False +@pytest.mark.asyncio +async def test_health_route_returns_503_when_probe_fails(): + model = _MockModel() + model.alive = False + harness = _HealthHarness(model) + app = FastAPI() + _register_twinkle_routes(app, lambda: harness) + route = next(route for route in app.routes if getattr(route, 'path', None) == '/healthz') + + response = await route.endpoint(object(), harness) + + assert response.status_code == 503 + + @pytest.mark.asyncio async def test_mark_unhealthy_is_cleared_by_successful_probe(): h = _HealthHarness(_MockModel()) diff --git a/tests/server/integration/test_blocking_boundary.py b/tests/server/integration/test_blocking_boundary.py index ddf0e5e8..6432ad79 100644 --- a/tests/server/integration/test_blocking_boundary.py +++ b/tests/server/integration/test_blocking_boundary.py @@ -9,24 +9,34 @@ from __future__ import annotations import asyncio +import threading import time from concurrent.futures import ThreadPoolExecutor +import httpx import pytest +from fastapi import FastAPI +from fastapi.responses import JSONResponse -from twinkle.server.utils.task_queue.mixin import TaskQueueMixin -from twinkle.server.utils.task_queue.types import BackendBusyError +ray = pytest.importorskip('ray') + +from twinkle.server.utils.task_queue.mixin import TaskQueueMixin # noqa: E402 +from twinkle.server.utils.task_queue.types import BackendBusyError # noqa: E402 class _Harness(TaskQueueMixin): """Minimal holder exposing the real call_backend with a chosen gate setting.""" - def __init__(self, gate_enabled: bool) -> None: - self._backend_executor = ThreadPoolExecutor(thread_name_prefix='twinkle-backend') - self._backend_admission = asyncio.Semaphore(1) if gate_enabled else None + def __init__(self, gate_enabled: bool, *, max_workers: int | None = None) -> None: + self._backend_executor = ThreadPoolExecutor( + max_workers=max_workers, thread_name_prefix='twinkle-backend') + self._backend_probe_executor = ThreadPoolExecutor(max_workers=1, thread_name_prefix='twinkle-backend-probe') + self._backend_admission = asyncio.Lock() if gate_enabled else None + self._backend_poisoned = asyncio.Event() def close(self) -> None: - self._backend_executor.shutdown(wait=False) + self._backend_executor.shutdown(wait=False, cancel_futures=True) + self._backend_probe_executor.shutdown(wait=False, cancel_futures=True) @pytest.mark.asyncio @@ -50,6 +60,62 @@ async def test_healthz_style_probe_responsive_during_slow_backend(): h.close() +@pytest.mark.asyncio +async def test_normal_gate_contention_waits_instead_of_failing(): + h = _Harness(gate_enabled=True) + try: + first = asyncio.create_task(h.call_backend(lambda: (time.sleep(0.2), 'first')[1])) + await asyncio.sleep(0.05) + second = asyncio.create_task(h.call_backend(lambda: 'second')) + assert await first == 'first' + assert await second == 'second' + finally: + h.close() + + +@pytest.mark.asyncio +async def test_cancelled_gate_waiter_does_not_steal_lock(): + h = _Harness(gate_enabled=True) + release = threading.Event() + + def wait_for_release(): + while not release.is_set(): + time.sleep(0.01) + + try: + first = asyncio.create_task(h.call_backend(wait_for_release)) + await asyncio.sleep(0.05) + waiter = asyncio.create_task(h.call_backend(lambda: 'cancelled')) + await asyncio.sleep(0.05) + waiter.cancel() + with pytest.raises(asyncio.CancelledError): + await waiter + release.set() + await first + assert await h.call_backend(lambda: 'next') == 'next' + finally: + release.set() + h.close() + + +@pytest.mark.asyncio +async def test_cancelled_queued_backend_call_releases_gate(): + h = _Harness(gate_enabled=True, max_workers=1) + release_worker = threading.Event() + occupied = h._backend_executor.submit(release_worker.wait) + try: + with pytest.raises(asyncio.TimeoutError): + await asyncio.wait_for(h.call_backend(lambda: 'never-started'), timeout=0.05) + await asyncio.sleep(0) + assert not h._backend_admission.locked() + release_worker.set() + occupied.result(timeout=5) + assert await h.call_backend(lambda: 'next') == 'next' + finally: + release_worker.set() + h.close() + + @pytest.mark.asyncio async def test_gate_held_by_leaked_call_fast_fails_next_task(): """Property 4 / R2#4: a call that outlives its wait_for keeps the gate; the next @@ -81,6 +147,49 @@ def would_enter_backend(): h.close() +@pytest.mark.asyncio +async def test_probe_times_out_while_same_serial_actor_is_busy(): + + @ray.remote + class SerialActor: + + def slow(self): + time.sleep(1.0) + + def ping(self): + return True + + started_ray = not ray.is_initialized() + if started_ray: + ray.init(num_cpus=1, logging_level='ERROR') + actor = SerialActor.remote() + h = _Harness(gate_enabled=True) + app = FastAPI() + + @app.get('/healthz') + async def healthz(): + try: + await h.call_backend(lambda: ray.get(actor.ping.remote(), timeout=0.2), admit=False) + return {'healthy': True} + except ray.exceptions.GetTimeoutError: + return JSONResponse(status_code=503, content={'healthy': False}) + + try: + slow = asyncio.create_task(h.call_backend(lambda: ray.get(actor.slow.remote(), timeout=2))) + await asyncio.sleep(0.1) + start = time.monotonic() + async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url='http://test') as client: + response = await client.get('/healthz') + assert response.status_code == 503 + assert time.monotonic() - start < 5 + await slow + finally: + h.close() + ray.kill(actor) + if started_ray: + ray.shutdown() + + @pytest.mark.asyncio async def test_sampler_without_gate_runs_two_calls_concurrently(): """R9#2 case 3 / opt-in: with the gate disabled (SamplerManagement), two backend diff --git a/tests/server/integration/test_nccl_safe_tinker_e2e.py b/tests/server/integration/test_nccl_safe_tinker_e2e.py index b47666b9..4846a2bc 100644 --- a/tests/server/integration/test_nccl_safe_tinker_e2e.py +++ b/tests/server/integration/test_nccl_safe_tinker_e2e.py @@ -9,7 +9,7 @@ Prerequisites: 1. Ray cluster running with GPUs (2 for model DP/TP) - 2. Twinkle server started (no fault-tolerance env switch exists any more) + 2. Twinkle server started with queue_config.execution_timeout=30 Usage (pytest, requires TWINKLE_TEST_GPU_E2E=1): TWINKLE_TEST_GPU_E2E=1 pytest tests/server/integration/test_nccl_safe_tinker_e2e.py -v @@ -29,7 +29,8 @@ BASE_MODEL = 'Qwen/Qwen3.5-4B' SERVER_URL = os.environ.get('TWINKLE_SERVER_URL', 'http://localhost:9000') -TIMEOUT = 120 +EXECUTION_TIMEOUT = float(os.environ.get('TWINKLE_TEST_EXECUTION_TIMEOUT', '30')) +TIMEOUT = EXECUTION_TIMEOUT + 15 def _init_client(): @@ -71,13 +72,15 @@ def test_failure_is_terminal_then_valid_request_succeeds(): necessary, not optional. """ from tinker import types + from tinker._exceptions import RequestFailedError tc = _init_client() # Deliberately malformed: logprobs length inconsistent with the completion. bad = [_make_datum(bad_logprobs_len=5) for _ in range(4)] start = time.time() - with pytest.raises(Exception): # RequestFailedError or a raised failed terminal - tc.forward_backward(bad, 'importance_sampling').result() + with pytest.raises(RequestFailedError) as caught: + tc.forward_backward(bad, 'importance_sampling').result(timeout=TIMEOUT) + assert caught.value.category is types.RequestErrorCategory.Server assert time.time() - start < TIMEOUT, 'malformed request must fail fast, not hang (NCCL)' # Recovery: a subsequent valid request on the same deployment must succeed. @@ -85,3 +88,22 @@ def test_failure_is_terminal_then_valid_request_succeeds(): result = tc.forward_backward(good, 'importance_sampling').result() assert result is not None tc.optim_step(types.AdamParams(learning_rate=1e-5)).result() + + +def test_partial_rank_failure_is_terminal_then_recovers(): + from tinker import types + from tinker._exceptions import RequestFailedError + tc = _init_client() + + batch = [_make_datum() for _ in range(4)] + batch[0] = _make_datum(bad_logprobs_len=5) + start = time.time() + with pytest.raises(RequestFailedError) as caught: + tc.forward_backward(batch, 'importance_sampling').result(timeout=TIMEOUT) + assert caught.value.category is types.RequestErrorCategory.Server + assert 'global_rank=' in str(caught.value) + assert time.time() - start < TIMEOUT + + result = tc.forward_backward([_make_datum() for _ in range(4)], 'importance_sampling').result() + assert result is not None + tc.optim_step(types.AdamParams(learning_rate=1e-5)).result() diff --git a/tests/server/integration/test_nccl_safe_twinkle_e2e.py b/tests/server/integration/test_nccl_safe_twinkle_e2e.py index 90a33cf3..5eed7141 100644 --- a/tests/server/integration/test_nccl_safe_twinkle_e2e.py +++ b/tests/server/integration/test_nccl_safe_twinkle_e2e.py @@ -8,7 +8,7 @@ Prerequisites: 1. Ray cluster running with GPUs (2 for model DP/TP) - 2. Twinkle server started (no fault-tolerance env switch exists any more) + 2. Twinkle server started with queue_config.execution_timeout=30 Usage (pytest, requires TWINKLE_TEST_GPU_E2E=1): TWINKLE_TEST_GPU_E2E=1 pytest tests/server/integration/test_nccl_safe_twinkle_e2e.py -v @@ -28,7 +28,8 @@ BASE_MODEL = 'Qwen/Qwen3.5-4B' SERVER_URL = os.environ.get('TWINKLE_SERVER_URL', 'http://localhost:9000') -TIMEOUT = 120 +EXECUTION_TIMEOUT = float(os.environ.get('TWINKLE_TEST_EXECUTION_TIMEOUT', '30')) +TIMEOUT = EXECUTION_TIMEOUT + 15 ADAPTER_NAME = 'loud-failure-test' @@ -79,9 +80,10 @@ def test_failure_is_terminal_then_valid_request_succeeds(): bad_features, bad_old_logps, bad_adv = _make_inputs(bad_old_logps_len=5) start = time.time() - with pytest.raises(Exception): + with pytest.raises(Exception) as caught: model.forward_backward( inputs=bad_features, adapter_name=ADAPTER_NAME, old_logps=bad_old_logps, advantages=bad_adv) + assert 'global_rank=' in str(caught.value) assert time.time() - start < TIMEOUT, 'malformed request must fail fast, not hang (NCCL)' good_features, good_old_logps, good_adv = _make_inputs() diff --git a/tests/server/model/test_replica_lifecycle.py b/tests/server/model/test_replica_lifecycle.py index e42193c3..84b96139 100644 --- a/tests/server/model/test_replica_lifecycle.py +++ b/tests/server/model/test_replica_lifecycle.py @@ -12,12 +12,17 @@ class _CapacityState: def __init__(self) -> None: self.capacities: dict[str, int] = {} + self.last_seen: set[str] = set() async def register_replica(self, replica_id: str, max_loras: int) -> None: self.capacities[replica_id] = max_loras async def unregister_replica(self, replica_id: str) -> None: self.capacities.pop(replica_id, None) + self.last_seen.discard(replica_id) + + async def touch_replica_last_seen(self, replica_id: str) -> None: + self.last_seen.add(replica_id) async def get_capacity_info(self) -> dict[str, int]: max_loras = sum(self.capacities.values()) @@ -31,6 +36,7 @@ def _make_lifecycle_manager(state: _CapacityState, replica_id: str, max_loras: i manager.max_loras = max_loras manager._replica_registered = False manager.data_plane = SimpleNamespace(close=AsyncMock()) + manager.shutdown_task_queue = AsyncMock() return manager @@ -42,6 +48,7 @@ async def test_replica_lifecycle_updates_shared_capacity() -> None: await first._register_replica_on_startup() assert await state.get_capacity_info() == {'max_loras': 3, 'used_loras': 0, 'free_loras': 3} + assert state.last_seen == {'replica-1'} await second._register_replica_on_startup() assert await state.get_capacity_info() == {'max_loras': 6, 'used_loras': 0, 'free_loras': 6} @@ -52,9 +59,10 @@ async def test_replica_lifecycle_updates_shared_capacity() -> None: @pytest.mark.asyncio async def test_async_constructor_registers_replica_before_ready() -> None: - state = SimpleNamespace(register_replica=AsyncMock()) + state = SimpleNamespace(register_replica=AsyncMock(), touch_replica_last_seen=AsyncMock()) replica_context = SimpleNamespace(replica_id=SimpleNamespace(unique_id='replica-1')) manager = ModelManagement.__new__(ModelManagement) + manager._task_queue_config = SimpleNamespace(effective_execution_timeout=1800.0) with patch('twinkle.server.model.app.DeviceGroup', return_value=SimpleNamespace(name='group')), \ patch('twinkle.server.model.app.init_twinkle_runtime', return_value=None), \ @@ -75,4 +83,5 @@ async def test_async_constructor_registers_replica_before_ready() -> None: ) state.register_replica.assert_awaited_once_with('replica-1', 3) + state.touch_replica_last_seen.assert_awaited_once_with('replica-1') assert manager._replica_registered is True diff --git a/tests/server/model/test_tinker_handlers.py b/tests/server/model/test_tinker_handlers.py index 474ce700..66a9ff98 100644 --- a/tests/server/model/test_tinker_handlers.py +++ b/tests/server/model/test_tinker_handlers.py @@ -73,9 +73,11 @@ def assert_resource_exists(self, adapter_name): pass async def schedule_task(self, task, **kwargs): - # Actually execute the task to test response logic return await task() + async def call_backend(self, fn, /, *args, **kwargs): + return fn(*args, **kwargs) + @pytest.mark.asyncio @patch('twinkle.server.model.tinker_handlers.create_checkpoint_manager') diff --git a/tests/server/sampler/test_stream_guarantees.py b/tests/server/sampler/test_stream_guarantees.py new file mode 100644 index 00000000..d1489575 --- /dev/null +++ b/tests/server/sampler/test_stream_guarantees.py @@ -0,0 +1,113 @@ +from __future__ import annotations + +import asyncio +import json +import threading +from types import SimpleNamespace +from unittest.mock import AsyncMock + +import pytest +from fastapi import FastAPI + +from twinkle.server.sampler.app import SamplerManagement +from twinkle.server.sampler.twinkle_handlers import _await_generation, _register_twinkle_sampler_routes, _stream_queue + + +class _BlockingQueue: + + def __init__(self) -> None: + self.released = threading.Event() + self.get_exited = threading.Event() + self.closed = False + + def get(self): + self.released.wait() + self.get_exited.set() + return 'sentinel' + + def shutdown(self, *, force: bool) -> None: + assert force is True + self.closed = True + self.released.set() + + +@pytest.mark.asyncio +async def test_sampler_request_refreshes_replica_liveness(): + service = SamplerManagement.__new__(SamplerManagement) + service.replica_id = 'sampler-replica' + service.state = SimpleNamespace(touch_replica_last_seen=AsyncMock()) + service._ensure_sticky = AsyncMock() + service._ensure_state_cleanup_started = AsyncMock() + request = SimpleNamespace( + headers={'Authorization': 'Bearer token'}, state=SimpleNamespace(token='token')) + + assert await service._on_request_start(request) == 'token' + service.state.touch_replica_last_seen.assert_awaited_once_with('sampler-replica') + + +@pytest.mark.asyncio +async def test_stream_without_actor_returns_structured_error(): + service = SimpleNamespace( + sampler=SimpleNamespace(_actors=[]), + _on_request_start=AsyncMock(return_value='token'), + ) + app = FastAPI() + _register_twinkle_sampler_routes(app, lambda: service) + route = next(route for route in app.routes if getattr(route, 'path', None) == '/twinkle/sample_stream') + request = SimpleNamespace(state=SimpleNamespace(request_id='request')) + body = SimpleNamespace(adapter_name='', adapter_uri=None, inputs={'input_ids': [1]}, sampling_params=None) + + response = await route.endpoint(request, body, service) + chunks = [chunk async for chunk in response.body_iterator] + payload = json.loads(chunks[0]) + assert payload['category'] == 'server' + assert payload['error_code'] == 503 + assert payload['request_id'].startswith('req_') + + +@pytest.mark.asyncio +async def test_stream_timeout_returns_error_payload_and_closes_queue(): + queue = _BlockingQueue() + chunks = [ + chunk async for chunk in _stream_queue( + queue, + sentinel='sentinel', + request_id='req-stream', + total_timeout=0.05, + single_get_timeout=0.05, + ) + ] + + payload = json.loads(chunks[0]) + assert payload['category'] == 'server' + assert payload['error_code'] == 504 + assert payload['request_id'] == 'req-stream' + assert queue.closed is True + assert queue.get_exited.wait(timeout=5) + + +class _GenerationService: + + def __init__(self) -> None: + self.cancelled = False + self.sampler = SimpleNamespace( + get_generation_status=lambda _submission_id: {'status': 'running'}, + collect_generation=lambda _submission_id: [], + cancel_generation=self._cancel, + ) + + async def call_backend(self, fn, /, *args, **kwargs): + return fn(*args, **kwargs) + + def _cancel(self, _submission_id: str) -> None: + self.cancelled = True + + +@pytest.mark.asyncio +async def test_generation_poll_has_total_timeout_and_cancels(): + service = _GenerationService() + + with pytest.raises(asyncio.TimeoutError): + await _await_generation(service, 'submission', timeout=0.05) + + assert service.cancelled is True diff --git a/tests/server/sampler/test_tinker_handlers.py b/tests/server/sampler/test_tinker_handlers.py index 1e338594..77a15ce6 100644 --- a/tests/server/sampler/test_tinker_handlers.py +++ b/tests/server/sampler/test_tinker_handlers.py @@ -52,6 +52,9 @@ async def _on_request_start(self, request): async def schedule_task(self, task, **kwargs): return await task() + async def call_backend(self, fn, /, *args, **kwargs): + return fn(*args, **kwargs) + @pytest.mark.asyncio async def test_tinker_asample_allows_base_model_session_without_model_path(): @@ -71,4 +74,6 @@ async def test_tinker_asample_allows_base_model_session_without_model_path(): response = await route.endpoint(request, body, management) assert isinstance(response, types.SampleResponse) + assert response.sequences[0].tokens == [1, 2] + assert response.sequences[0].sequence_id assert management.sampler.adapter_paths == [None] diff --git a/tests/server/state/test_error_payload.py b/tests/server/state/test_error_payload.py index b5483445..eb224f73 100644 --- a/tests/server/state/test_error_payload.py +++ b/tests/server/state/test_error_payload.py @@ -5,6 +5,9 @@ """ from __future__ import annotations +import pytest +from pydantic import ValidationError + from twinkle.server.utils.task_errors import error_payload_from_stored, task_error_payload from twinkle_client.types.errors import ErrorCategory, ErrorPayload @@ -41,7 +44,13 @@ def test_user_category_carries_no_traceback(): category=ErrorCategory.User, traceback_text='Traceback (most recent call last): ...') assert payload['category'] == ErrorCategory.User.value - assert payload['traceback'] is None + assert 'traceback' not in payload + + +def test_error_category_matches_tinker_wire_values(): + from tinker.types import RequestErrorCategory + + assert {item.value for item in RequestErrorCategory} == {item.value for item in ErrorCategory} def test_tinker_sdk_parses_six_field_like_two_field(): @@ -54,10 +63,35 @@ def test_tinker_sdk_parses_six_field_like_two_field(): from tinker.types import RequestFailedResponse two = {'error': 'boom', 'category': 'server'} - six = {**two, 'error_code': 504, 'request_id': 'req_9', 'traceback': None, 'details': None} + six = task_error_payload('boom', request_id='req_9', error_code=504) parsed_six = RequestFailedResponse.model_validate(six) parsed_two = RequestFailedResponse.model_validate(two) assert parsed_six.error == parsed_two.error assert parsed_six.category == parsed_two.category + + +def test_legacy_title_case_category_is_normalized(): + payload = error_payload_from_stored({'error': 'boom', 'category': 'Server'}, request_id='req_10') + assert payload.category is ErrorCategory.Server + assert payload.category.value == 'server' + + +@pytest.mark.parametrize('category', [ErrorCategory.User, ErrorCategory.Unknown]) +def test_non_server_traceback_is_rejected(category): + with pytest.raises(ValidationError): + ErrorPayload( + error='bad input', + category=category, + error_code=400, + request_id='req_11', + traceback='server stack', + ) + + +def test_legacy_unknown_traceback_is_removed(): + payload = error_payload_from_stored( + {'error': 'legacy', 'category': 'Unknown', 'traceback': 'old stack'}, request_id='req_12') + assert payload.category is ErrorCategory.Unknown + assert payload.traceback is None diff --git a/tests/server/state/test_future_lifecycle.py b/tests/server/state/test_future_lifecycle.py index c32a6172..55905afa 100644 --- a/tests/server/state/test_future_lifecycle.py +++ b/tests/server/state/test_future_lifecycle.py @@ -20,15 +20,21 @@ def manager(tmp_path): return FutureManager(backend, expiration_timeout=300.0) -async def _store(manager, request_id, status, *, replica_id=None): - await manager.store_status(request_id, status, model_id='m1', replica_id=replica_id) +async def _store(manager, request_id, status, *, replica_id=None, absolute_deadline=None): + await manager.store_status( + request_id, + status, + model_id='m1', + replica_id=replica_id, + absolute_deadline=absolute_deadline, + ) @pytest.mark.asyncio async def test_non_terminal_with_live_replica_is_kept(manager): await _store(manager, 'r1', 'running', replica_id='replica-A') removed = await manager.cleanup_expired( - cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) + cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}) assert removed == 0 rec = await manager.get('r1') assert rec is not None and rec.status == 'running' @@ -37,27 +43,35 @@ async def test_non_terminal_with_live_replica_is_kept(manager): @pytest.mark.asyncio async def test_non_terminal_orphan_is_failed_not_deleted(manager): await _store(manager, 'r2', 'running', replica_id='dead-replica') - await manager.cleanup_expired(cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) + await manager.cleanup_expired(cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}) rec = await manager.get('r2') assert rec is not None # NOT deleted (Property 6) assert rec.status == 'failed' - assert rec.result['category'] == 'Server' + assert rec.result['category'] == 'server' @pytest.mark.asyncio -async def test_non_terminal_over_absolute_ttl_is_failed(manager): - await _store(manager, 'r3', 'running', replica_id='replica-A') - # absolute_ttl=0 makes any positive age exceed the bound. - await manager.cleanup_expired(cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}, absolute_ttl=0.0) +async def test_non_terminal_past_absolute_deadline_is_failed(manager): + await _store(manager, 'r3', 'running', replica_id='replica-A', absolute_deadline=time.time() - 1) + await manager.cleanup_expired(cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}) rec = await manager.get('r3') assert rec is not None and rec.status == 'failed' +@pytest.mark.asyncio +async def test_legacy_record_without_deadline_uses_expiration_timeout(manager): + await _store(manager, 'legacy', 'running', replica_id=None) + with mock.patch('twinkle.server.state.future_manager.time.time', return_value=time.time() + 301): + await manager.cleanup_expired(cutoff_time=time.time() + 10, alive_replica_ids=set()) + rec = await manager.get('legacy') + assert rec is not None and rec.status == 'failed' + + @pytest.mark.asyncio async def test_terminal_expired_is_deleted(manager): await _store(manager, 'r4', 'completed', replica_id='replica-A') removed = await manager.cleanup_expired( - cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}, absolute_ttl=None) + cutoff_time=time.time() + 10, alive_replica_ids={'replica-A'}) assert removed == 1 assert await manager.get('r4') is None @@ -83,11 +97,14 @@ async def test_terminal_to_terminal_same_is_dropped_without_warning(manager): @pytest.mark.asyncio -async def test_replica_id_set_at_creation_not_overwritten(manager): - await _store(manager, 'r7', 'pending', replica_id='replica-A') - await manager.store_status('r7', 'running', model_id='m1', replica_id='replica-B') +async def test_replica_id_and_deadline_set_at_creation_not_overwritten(manager): + deadline = time.time() + 100 + await _store(manager, 'r7', 'pending', replica_id='replica-A', absolute_deadline=deadline) + await manager.store_status( + 'r7', 'running', model_id='m1', replica_id='replica-B', absolute_deadline=time.time() + 999) rec = await manager.get('r7') - assert rec.replica_id == 'replica-A' # creation value preserved + assert rec.replica_id == 'replica-A' + assert rec.absolute_deadline == deadline @pytest.mark.asyncio diff --git a/tests/server/state/test_managers.py b/tests/server/state/test_managers.py index 1b9016be..63fc24be 100644 --- a/tests/server/state/test_managers.py +++ b/tests/server/state/test_managers.py @@ -172,6 +172,12 @@ async def test_replica_registration(self, manager): assert info['used_loras'] == 0 assert info['free_loras'] == 5 + @pytest.mark.asyncio + async def test_liveness_only_replica_is_alive(self, manager): + await manager.touch_replica_last_seen('sampler-replica') + alive = await manager.get_alive_replica_ids(liveness_threshold=60) + assert 'sampler-replica' in alive + @pytest.mark.asyncio async def test_capacity_info_after_add(self, manager): await manager.register_replica('r1', max_loras=3) diff --git a/tests/server/static/backend_call_exemptions.py b/tests/server/static/backend_call_exemptions.py index 1ba0674e..4dcd3bf0 100644 --- a/tests/server/static/backend_call_exemptions.py +++ b/tests/server/static/backend_call_exemptions.py @@ -19,5 +19,5 @@ # (module_relpath under src/twinkle/server, innermost enclosing function name) BACKEND_CALL_EXEMPTIONS: frozenset[tuple[str, str]] = frozenset({ - ('sampler/twinkle_handlers.py', '_stream_generator'), + ('sampler/twinkle_handlers.py', '_stream_queue'), }) diff --git a/tests/server/static/test_no_direct_backend_call.py b/tests/server/static/test_no_direct_backend_call.py index 4e2750ee..5b218e91 100644 --- a/tests/server/static/test_no_direct_backend_call.py +++ b/tests/server/static/test_no_direct_backend_call.py @@ -3,10 +3,9 @@ Spec: T3.7 / R2#7 / R2#8 / Property 2. -Asserts that no module under ``src/twinkle/server`` invokes ``self.model.(...)`` -or ``self.sampler.(...)`` directly -- every such call must go through -``call_backend`` (the Blocking_Call_Boundary). The scan range is the directory -(not a file list), so a newly added handler file cannot silently escape it. +Asserts that backend methods are invoked only through ``call_backend``. The check +covers direct calls, aliases created with ``getattr``, and methods passed to generic +thread executors. The scan range is the server directory rather than a file list. Allowed bypasses are read from the shared ``backend_call_exemptions`` module, which this spec and ``server-request-lifecycle`` are meant to consume unchanged. This spec @@ -24,14 +23,22 @@ _SERVER_ROOT = pathlib.Path(twinkle.__file__).resolve().parent / 'server' -def _is_self_backend_call(node: ast.Call) -> str | None: - """Return 'model'/'sampler' if node is a direct self.model/self.sampler.() call.""" - func = node.func - if not isinstance(func, ast.Attribute): +def _backend_method(node: ast.AST) -> str | None: + if not isinstance(node, ast.Attribute): return None - owner = func.value # the object the method is called on - if (isinstance(owner, ast.Attribute) and owner.attr in ('model', 'sampler') - and isinstance(owner.value, ast.Name) and owner.value.id == 'self'): + owner = node.value + if isinstance(owner, ast.Attribute) and owner.attr in ('model', 'sampler'): + return owner.attr + return None + + +def _getattr_backend_method(node: ast.AST) -> str | None: + if not isinstance(node, ast.Call) or not isinstance(node.func, ast.Name) or node.func.id != 'getattr': + return None + if not node.args: + return None + owner = node.args[0] + if isinstance(owner, ast.Attribute) and owner.attr in ('model', 'sampler'): return owner.attr return None @@ -41,6 +48,7 @@ class _Collector(ast.NodeVisitor): def __init__(self, relpath: str) -> None: self.relpath = relpath self.func_stack: list[str] = [] + self.backend_aliases: set[str] = set() self.offenders: list[tuple[str, str, int, str]] = [] def _visit_func(self, node: ast.AST) -> None: @@ -51,12 +59,26 @@ def _visit_func(self, node: ast.AST) -> None: visit_FunctionDef = _visit_func visit_AsyncFunctionDef = _visit_func + def visit_Assign(self, node: ast.Assign) -> None: + if _getattr_backend_method(node.value) is not None: + self.backend_aliases.update(target.id for target in node.targets if isinstance(target, ast.Name)) + self.generic_visit(node) + def visit_Call(self, node: ast.Call) -> None: - owner = _is_self_backend_call(node) + owner = _backend_method(node.func) + label = ast.unparse(node.func) if owner is not None else None + if isinstance(node.func, ast.Name) and node.func.id in self.backend_aliases: + owner = 'alias' + label = node.func.id + if isinstance(node.func, ast.Attribute) and node.func.attr in ('to_thread', 'run_in_executor') and node.args: + escaped_owner = _backend_method(node.args[0]) or _getattr_backend_method(node.args[0]) + if escaped_owner is not None: + owner = escaped_owner + label = f'{ast.unparse(node.func)}({ast.unparse(node.args[0])})' if owner is not None: enclosing = self.func_stack[-1] if self.func_stack else '' if (self.relpath, enclosing) not in BACKEND_CALL_EXEMPTIONS: - self.offenders.append((self.relpath, enclosing, node.lineno, f'self.{owner}.{node.func.attr}')) + self.offenders.append((self.relpath, enclosing, node.lineno, label or owner)) self.generic_visit(node) @@ -74,5 +96,27 @@ def test_no_direct_backend_call_in_server(): def test_exemptions_are_read_from_shared_file(): - # The shared file is the single source of allowed bypasses (R2#8). - assert ('sampler/twinkle_handlers.py', '_stream_generator') in BACKEND_CALL_EXEMPTIONS + assert ('sampler/twinkle_handlers.py', '_stream_queue') in BACKEND_CALL_EXEMPTIONS + + +def test_checker_detects_indirect_backend_calls(): + source = """ +async def route(self): + await asyncio.to_thread(self.model.save) + unload = getattr(self.sampler, 'unload_adapter_paths') + unload([]) +""" + collector = _Collector('example.py') + collector.visit(ast.parse(source)) + assert len(collector.offenders) == 2 + + +def test_checker_allows_call_backend(): + source = """ +async def route(self): + unload = getattr(self.sampler, 'unload_adapter_paths') + await self.call_backend(unload, []) +""" + collector = _Collector('example.py') + collector.visit(ast.parse(source)) + assert collector.offenders == [] diff --git a/tests/server/utils/task_queue/test_config.py b/tests/server/utils/task_queue/test_config.py index 3126c507..878bfa12 100644 --- a/tests/server/utils/task_queue/test_config.py +++ b/tests/server/utils/task_queue/test_config.py @@ -22,6 +22,7 @@ 'tps_limit': 16000.0, 'window_seconds': 1.0, 'queue_timeout': 300.0, + 'execution_timeout': 1800.0, 'token_cleanup_interval': 60.0, 'max_input_tokens': 16000, } @@ -113,3 +114,15 @@ def test_extra_field_rejected() -> None: """``extra='forbid'`` rejects unknown keys.""" with pytest.raises(ValidationError): TaskQueueConfig(unknown_field=1) + + +def test_zero_execution_timeout_uses_finite_fallback() -> None: + assert TaskQueueConfig(execution_timeout=0).effective_execution_timeout == 3600 + + +def test_absolute_future_ttl_uses_conservative_backend_bound() -> None: + config = TaskQueueConfig(queue_timeout=10, execution_timeout=20) + assert config.absolute_future_ttl(collect_width=2) == 2 * (10 + 2 * 3600) + + config = TaskQueueConfig(queue_timeout=10, execution_timeout=5000) + assert config.absolute_future_ttl(collect_width=2) == 2 * (10 + 2 * 5000) diff --git a/tests/server/utils/test_task_errors.py b/tests/server/utils/test_task_errors.py index 698ad5b7..832ca109 100644 --- a/tests/server/utils/test_task_errors.py +++ b/tests/server/utils/test_task_errors.py @@ -11,7 +11,7 @@ def test_task_error_payload_builds_error_payload_dict(): assert payload['category'] == ErrorCategory.Server.value assert payload['error_code'] == 500 assert payload['request_id'] == 'req_1' - assert payload['traceback'] is None + assert 'traceback' not in payload def test_task_error_payload_user_category_drops_traceback(): @@ -19,7 +19,13 @@ def test_task_error_payload_user_category_drops_traceback(): 'bad input', request_id='req_2', error_code=400, category=ErrorCategory.User, traceback_text='Traceback...') assert payload['category'] == ErrorCategory.User.value - assert payload['traceback'] is None + assert 'traceback' not in payload + + +def test_error_summary_is_single_line(): + payload = task_error_payload( + 'RuntimeError: boom\n File "/server/path.py", line 1', request_id='req-lines') + assert payload['error'] == 'RuntimeError: boom' def test_error_payload_from_stored_backfills_two_field_legacy(): diff --git a/tests/server/utils/test_task_queue_mixin.py b/tests/server/utils/test_task_queue_mixin.py index f0bdbf96..04200285 100644 --- a/tests/server/utils/test_task_queue_mixin.py +++ b/tests/server/utils/test_task_queue_mixin.py @@ -4,6 +4,7 @@ from twinkle.server.utils.task_queue.config import TaskQueueConfig from twinkle.server.utils.task_queue.mixin import TaskQueueMixin +from twinkle.server.utils.task_queue.types import UserTaskError from twinkle.server.utils.task_queue.worker import ComputeWorker @@ -57,7 +58,7 @@ async def test_preflight_rejects_batch_without_per_dp_multiple(): assert result == {'request_id': 'req1', 'model_id': 'model1'} _, kwargs = queue.state.records[-1] - assert kwargs['result']['category'] == 'User' + assert kwargs['result']['category'] == 'user' assert 'Batch size 2 must be divisible by 4' in kwargs['result']['error'] @@ -93,6 +94,7 @@ async def work(): await asyncio.sleep(0) assert [args[1] for args, _ in queue.state.records] == ['running', 'completed'] + assert queue.state.records[0][1]['absolute_deadline'] > 0 assert queue.state.records[-1][1]['result'] == {'ok': True} @@ -122,6 +124,7 @@ async def work(): @pytest.mark.asyncio async def test_polling_schedule_task_still_persists_its_result(): queue = _DummyQueue() + queue.replica_id = 'replica-1' queue.enable_compute_worker() result = {'value': 42} @@ -142,6 +145,9 @@ async def work(): finally: await queue._compute_worker.stop() + pending = next(kwargs for args, kwargs in queue.state.records if args[1] == 'pending') + assert pending['replica_id'] == 'replica-1' + assert pending['absolute_deadline'] > 0 assert completed[-1]['result'] is result @@ -167,6 +173,28 @@ async def work(): assert queue.state.records == [] +@pytest.mark.asyncio +async def test_user_task_error_is_stored_as_user_failure(): + queue = _DummyQueue() + queue.enable_compute_worker() + + async def work(): + raise UserTaskError('invalid request') + + try: + await queue.schedule_task(work, model_id='model1', token='token1') + for _ in range(100): + failed = [kwargs for args, kwargs in queue.state.records if args[1] == 'failed'] + if failed: + break + await asyncio.sleep(0) + finally: + await queue._compute_worker.stop() + + assert failed[-1]['result']['category'] == 'user' + assert 'traceback' not in failed[-1]['result'] + + @pytest.mark.asyncio async def test_schedule_task_and_wait_reports_preflight_failure_without_persisting_it(): queue = _DummyQueue() diff --git a/tests/twinkle_client/test_types_contract.py b/tests/twinkle_client/test_types_contract.py index 877f2bf9..3b048c61 100644 --- a/tests/twinkle_client/test_types_contract.py +++ b/tests/twinkle_client/test_types_contract.py @@ -4,14 +4,9 @@ - T6.2 / R7#9: ``QueueStateLiteral`` value set equals the server ``QueueState`` enum. - T6.3 / R7#7: naming disambiguation guard. -Note on T6.3 scope (agreed deviation from the literal wording): ``twinkle_client`` is -a tinker-compatible client and already shares many public class names with -``tinker.types`` at HEAD (``ForwardRequest``, ``SampleRequest``, ``Checkpoint`` ...), -so a literal "the two modules' public export names are disjoint" assertion cannot -hold and twinkle's names are intentionally NOT renamed. Instead this guard enforces -the invariant the ruling actually targets: no ``src/twinkle/**`` module may bind a -tinker type and a twinkle_client type to the *same local name* (tinker must be -aliased when both coexist) -- which is what makes a review diff misread possible. +The two SDKs already share public names. The contract freezes that legacy set and +rejects new collisions while requiring explicit aliases when both SDKs are imported +in one module. """ from __future__ import annotations @@ -24,6 +19,26 @@ from twinkle_client.types.errors import QueueStateLiteral _TWINKLE_SRC = pathlib.Path(twinkle.__file__).resolve().parent +_LEGACY_PUBLIC_NAME_OVERLAP = frozenset({ + 'Checkpoint', + 'CheckpointsListResponse', + 'CreateModelRequest', + 'CreateSessionRequest', + 'CreateSessionResponse', + 'Cursor', + 'ForwardRequest', + 'GetServerCapabilitiesResponse', + 'HealthResponse', + 'LoraConfig', + 'SampleRequest', + 'SessionHeartbeatRequest', + 'SessionHeartbeatResponse', + 'SupportedModel', + 'TrainingRun', + 'TrainingRunsResponse', + 'WeightsInfoResponse', + 'checkpoint', +}) def test_queue_state_literal_matches_server_enum(): @@ -66,6 +81,18 @@ def _binding_collisions(tree: ast.AST) -> set[str]: return tinker_names & twinkle_names +def test_public_name_overlap_does_not_grow(): + import tinker.types + import twinkle_client.types + + overlap = { + name + for name in set(dir(tinker.types)) & set(dir(twinkle_client.types)) + if not name.startswith('_') + } + assert overlap == _LEGACY_PUBLIC_NAME_OVERLAP + + def test_no_tinker_twinkle_same_name_binding(): offenders: dict[str, set[str]] = {} for path in _TWINKLE_SRC.rglob('*.py'): diff --git a/tests/utils/test_nccl_safe.py b/tests/utils/test_nccl_safe.py new file mode 100644 index 00000000..62b0d8e1 --- /dev/null +++ b/tests/utils/test_nccl_safe.py @@ -0,0 +1,18 @@ +from unittest.mock import patch + +import pytest + +from twinkle.utils.nccl_safe import nccl_safe_megatron + + +def test_nccl_failure_preserves_type_and_adds_rank_context(): + + @nccl_safe_megatron + def fail(_self): + raise ValueError('bad shape') + + with patch('twinkle.utils.nccl_safe._global_rank', return_value=3): + with pytest.raises(ValueError) as caught: + fail(object()) + + assert 'global_rank=3' in ''.join(getattr(caught.value, '__notes__', caught.value.args)) From d56bcca38c484548e54ec8cc6205e583feae6288 Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Wed, 16 Sep 2026 01:01:43 +0800 Subject: [PATCH 13/14] fix: revert tinker to 0.16.1 and keep request types FastAPI-compatible tinker 0.29.0 turned its tensor request types into dataclasses, which breaks FastAPI OpenAPI generation. Revert the pin and the code that had been migrated to the 0.29.0 API: - pyproject: tinker 0.29.0 -> 0.16.1; restore poetry.lock to match - sampler/tinker_handlers: use 0.16.1 SampledSequence/SampleResponse fields - contract harness: fastapi 0.136 ModelField compat; normalize :path route converters so the baseline stores client-facing paths - regenerate client_api_baseline.json against tinker 0.16.1 - test fixtures: add call_backend/_task_queue_config; drop 0.29-only assertion --- poetry.lock | 2935 ++--------------- pyproject.toml | 2 +- src/twinkle/server/sampler/tinker_handlers.py | 10 +- .../server/contract/client_api_baseline.json | 1648 +++++---- tests/server/contract/client_api_harness.py | 10 +- .../server/model/test_twinkle_async_inputs.py | 3 + tests/server/sampler/test_tinker_handlers.py | 1 - .../server/sampler/test_twinkle_async_rows.py | 6 + 8 files changed, 1284 insertions(+), 3331 deletions(-) diff --git a/poetry.lock b/poetry.lock index 4a7b37e2..773c9b14 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,17 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. - -[[package]] -name = "absl-py" -version = "2.5.0" -description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "absl_py-2.5.0-py3-none-any.whl", hash = "sha256:0f17b89f2a4eaaedc4f28c622998aa690564b3012a396a4ffad0821007fe03ba"}, - {file = "absl_py-2.5.0.tar.gz", hash = "sha256:0c996f25c0490700fadabe6351630f6111534fa0ae252cc6d2014ea3b141135f"}, -] +# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand. [[package]] name = "accelerate" @@ -223,7 +210,6 @@ files = [ [package.dependencies] aiohappyeyeballs = ">=2.5.0" aiosignal = ">=1.4.0" -async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" @@ -240,7 +226,7 @@ description = "CORS support for aiohttp" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "aiohttp_cors-0.8.1-py3-none-any.whl", hash = "sha256:3180cf304c5c712d626b9162b195b1db7ddf976a2a25172b35bb2448b890a80d"}, {file = "aiohttp_cors-0.8.1.tar.gz", hash = "sha256:ccacf9cb84b64939ea15f859a146af1f662a6b1d68175754a07315e305fb1403"}, @@ -282,10 +268,9 @@ files = [ name = "aliyun-python-sdk-core" version = "2.11.5" description = "The core module of Aliyun Python SDK." -optional = true +optional = false python-versions = "*" groups = ["main"] -markers = "extra == \"eval\"" files = [ {file = "aliyun-python-sdk-core-2.11.5.tar.gz", hash = "sha256:577265c630c02207c692ca19958bd21665d56208306a834d0885e7770553975e"}, ] @@ -297,10 +282,9 @@ pycryptodome = ">=3.4.7" name = "aliyun-python-sdk-kms" version = "2.16.5" description = "The kms module of Aliyun Python sdk." -optional = true +optional = false python-versions = "*" groups = ["main"] -markers = "extra == \"eval\"" files = [ {file = "aliyun-python-sdk-kms-2.16.5.tar.gz", hash = "sha256:f328a8a19d83ecbb965ffce0ec1e9930755216d104638cd95ecd362753b813b3"}, {file = "aliyun_python_sdk_kms-2.16.5-py2.py3-none-any.whl", hash = "sha256:24b6cdc4fd161d2942619479c8d050c63ea9cd22b044fe33b60bbb60153786f0"}, @@ -340,7 +324,7 @@ description = "The official Python library for the anthropic API" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "anthropic-0.84.0-py3-none-any.whl", hash = "sha256:861c4c50f91ca45f942e091d83b60530ad6d4f98733bfe648065364da05d29e7"}, {file = "anthropic-0.84.0.tar.gz", hash = "sha256:72f5f90e5aebe62dca316cb013629cfa24996b0f5a4593b8c3d712bc03c43c37"}, @@ -386,7 +370,6 @@ files = [ ] [package.dependencies] -exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} @@ -400,7 +383,7 @@ description = "tvm ffi" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "apache_tvm_ffi-0.1.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d911cbbc83bf12a0d9ec03e5315ff1bb92d95702fe912cd7a050393274382e71"}, {file = "apache_tvm_ffi-0.1.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1c8dd4018420c0d14bace688594710909ce198056ff8ac2ad1cd462b30fe1bdd"}, @@ -454,25 +437,12 @@ description = "Read/rewrite/write Python ASTs" optional = true python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, ] -[[package]] -name = "async-timeout" -version = "5.0.1" -description = "Timeout context manager for asyncio programs" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "python_full_version < \"3.11.3\" and extra == \"server\" or python_version == \"3.10\"" -files = [ - {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, - {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, -] - [[package]] name = "attrs" version = "25.4.0" @@ -501,19 +471,6 @@ files = [ [package.extras] dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] -[[package]] -name = "backports-asyncio-runner" -version = "1.2.0" -description = "Backport of asyncio.Runner, a context manager that controls event loop life cycle." -optional = true -python-versions = "<3.11,>=3.8" -groups = ["main"] -markers = "python_version == \"3.10\" and extra == \"test\"" -files = [ - {file = "backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5"}, - {file = "backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162"}, -] - [[package]] name = "beautifulsoup4" version = "4.14.3" @@ -545,7 +502,7 @@ description = "Python bindings for the Rust blake3 crate" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "blake3-1.0.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:8956bb9aec47b6c37ccce935a943588f1f5e6e2e85d43bb7cb76a574238f8a9b"}, {file = "blake3-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7adbbee5dd0c302218eb8acdfd82b7006930eb5798f56f79f9cca89f6f192662"}, @@ -668,7 +625,7 @@ description = "Extensible memoizing collections and decorators" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "cachetools-7.0.1-py3-none-any.whl", hash = "sha256:8f086515c254d5664ae2146d14fc7f65c9a4bce75152eb247e5a9c5e6d7b2ecf"}, {file = "cachetools-7.0.1.tar.gz", hash = "sha256:e31e579d2c5b6e2944177a0397150d312888ddf4e16e12f1016068f0c03b8341"}, @@ -681,7 +638,7 @@ description = "CBOR (de)serializer with extensive tag support" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "cbor2-5.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2263c0c892194f10012ced24c322d025d9d7b11b41da1c357f3b3fe06676e6b7"}, {file = "cbor2-5.8.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6ffe4ca079f6f8ed393f5c71a8de22651cb27bd50e74e2bcd6bc9c8f853a732b"}, @@ -745,10 +702,10 @@ files = [ name = "cffi" version = "2.0.0" description = "Foreign Function Interface for Python calling C code." -optional = false +optional = true python-versions = ">=3.9" groups = ["main"] -markers = "(platform_python_implementation != \"PyPy\" or implementation_name == \"pypy\") and (implementation_name == \"pypy\" or extra == \"rl\" or extra == \"async-rl\")" +markers = "platform_python_implementation != \"PyPy\" and (extra == \"vllm\" or extra == \"ray\") or extra == \"vllm\" and implementation_name == \"pypy\"" files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -966,9 +923,10 @@ files = [ name = "click" version = "8.3.1" description = "Composable command line interface toolkit" -optional = false +optional = true python-versions = ">=3.10" groups = ["main"] +markers = "extra == \"vllm\" or extra == \"ray\" or extra == \"tinker\"" files = [ {file = "click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6"}, {file = "click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a"}, @@ -984,7 +942,7 @@ description = "Pickler class to extend the standard pickle.Pickler functionality optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "cloudpickle-3.1.2-py3-none-any.whl", hash = "sha256:9acb47f6afd73f60dc1df93bb801b472f05ff42fa6c84167d25cb206be1fbf4a"}, {file = "cloudpickle-3.1.2.tar.gz", hash = "sha256:7fda9eb655c9c230dab534f1983763de5835249750e85fbcef43aaa30a9a2414"}, @@ -997,7 +955,7 @@ description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["main"] -markers = "(platform_system == \"Windows\" or sys_platform == \"win32\" or extra == \"eval\") and (platform_system == \"Windows\" or extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"test\" or extra == \"docs\")" +markers = "(extra == \"vllm\" or extra == \"ray\" or extra == \"docs\") and sys_platform == \"win32\" or platform_system == \"Windows\"" files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, @@ -1010,7 +968,7 @@ description = "Terminal string styling done right, in Python." optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "colorful-0.5.8-py2.py3-none-any.whl", hash = "sha256:a9381fdda3337fbaba5771991020abc69676afa102646650b759927892875992"}, {file = "colorful-0.5.8.tar.gz", hash = "sha256:bb16502b198be2f1c42ba3c52c703d5f651d826076817185f0294c1a549a7445"}, @@ -1019,25 +977,6 @@ files = [ [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} -[[package]] -name = "colorlog" -version = "6.12.0" -description = "Add colours to the output of Python's logging module." -optional = true -python-versions = ">=3.6" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "colorlog-6.12.0-py3-none-any.whl", hash = "sha256:30d392604e9110045a2c2aeefc27d7a017abbab63f3a8aee594eac0801df784e"}, - {file = "colorlog-6.12.0.tar.gz", hash = "sha256:2a7924c1dadf18b22a0eb8b06d1c7b01d5341707ec1641eb6fcc4fde0c3e8e5f"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} - -[package.extras] -development = ["black", "flake8", "mypy", "pytest", "types-colorama"] - [[package]] name = "commonmark" version = "0.9.1" @@ -1061,7 +1000,7 @@ description = "Library for utilization of compressed safetensors of neural netwo optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "compressed_tensors-0.13.0-py3-none-any.whl", hash = "sha256:3518799c9baf034eb642efb551db6b0537b8713d45a64fe4def26f7f8d6cabec"}, {file = "compressed_tensors-0.13.0.tar.gz", hash = "sha256:23893824d3498ea3f1a829f14a8fa85f9a5e76a34c711a038b8d7c619ca9a67c"}, @@ -1081,10 +1020,9 @@ dev = ["black (==22.12.0)", "flake8 (>=3.8.3)", "isort (==5.8.0)", "nbconvert (> name = "crcmod" version = "1.7" description = "CRC Generator" -optional = true +optional = false python-versions = "*" groups = ["main"] -markers = "extra == \"eval\"" files = [ {file = "crcmod-1.7.tar.gz", hash = "sha256:dc7051a0db5f2bd48665a990d3ec1cc305a466a77358ca4492826f41f283601e"}, ] @@ -1096,7 +1034,7 @@ description = "cryptography is a package which provides cryptographic recipes an optional = true python-versions = "!=3.9.0,!=3.9.1,>=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\" or extra == \"vllm\"" files = [ {file = "cryptography-46.0.5-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:351695ada9ea9618b3500b490ad54c739860883df6c1f555e088eaf25b1bbaad"}, {file = "cryptography-46.0.5-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b"}, @@ -1151,7 +1089,6 @@ files = [ [package.dependencies] cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""} -typing-extensions = {version = ">=4.13.2", markers = "python_full_version < \"3.11.0\""} [package.extras] docs = ["sphinx (>=5.3.0)", "sphinx-inline-tabs", "sphinx-rtd-theme (>=3.0.0)"] @@ -1170,7 +1107,7 @@ description = "Python bindings for CUDA" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "cuda_bindings-13.1.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4400370a83f1538e25ed4c18c34a0e9d5fad39741e282e69ce24d1479a11017d"}, {file = "cuda_bindings-13.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:81f92500e2f6aec2dac00a5a1ce77d5aa77ea77b606dc484d951f1f2cc3eaa13"}, @@ -1205,7 +1142,7 @@ description = "Pathfinder for CUDA components" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "cuda_pathfinder-1.4.0-py3-none-any.whl", hash = "sha256:437079ca59e7b61ae439ecc501d69ed87b3accc34d58153ef1e54815e2c2e118"}, ] @@ -1217,7 +1154,7 @@ description = "CUDA Python: Performance meets Productivity" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "cuda_python-13.1.1-py3-none-any.whl", hash = "sha256:944cc4fe6482673d28dd545797a28840945a1668739328fa2ad1e9be4f7050d9"}, ] @@ -1236,7 +1173,7 @@ description = "CuPy: NumPy & SciPy for GPU" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "sys_platform != \"darwin\" and (extra == \"rl\" or extra == \"async-rl\")" +markers = "extra == \"vllm\" and sys_platform != \"darwin\"" files = [ {file = "cupy_cuda12x-14.0.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:b42da54c9da0d5a7748e4120f13c47594d3e1fc2741b712591aa915517741096"}, {file = "cupy_cuda12x-14.0.1-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:7c775e1e1ebc0c4c9f94a4c6bb66a0c07d109de5dfcef671f9e4056df4bd81ca"}, @@ -1307,19 +1244,6 @@ tests-numpy2 = ["Pillow (>=9.4.0)", "absl-py", "aiohttp", "decorator", "elastics torch = ["torch"] vision = ["Pillow (>=9.4.0)"] -[[package]] -name = "defusedxml" -version = "0.7.1" -description = "XML bomb protection for Python stdlib modules" -optional = true -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, - {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, -] - [[package]] name = "depyf" version = "0.20.0" @@ -1327,7 +1251,7 @@ description = "Decompile python functions, from bytecode to source code!" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "depyf-0.20.0-py3-none-any.whl", hash = "sha256:d31effad4261cebecb58955d832e448ace88f432328f95f82fd99c30fd9308d4"}, {file = "depyf-0.20.0.tar.gz", hash = "sha256:fb7683bd72c44f67b56029df2c47721e9a02ffa4d7b19095f1c54c4ebf797a98"}, @@ -1363,7 +1287,7 @@ description = "Disk Cache -- Disk and file backed persistent cache." optional = true python-versions = ">=3" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19"}, {file = "diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc"}, @@ -1376,7 +1300,7 @@ description = "Distribution utilities" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, @@ -1389,7 +1313,7 @@ description = "Distro - an OS platform information API" optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" +markers = "extra == \"vllm\" or extra == \"tinker\"" files = [ {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, @@ -1402,7 +1326,7 @@ description = "DNS toolkit" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af"}, {file = "dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f"}, @@ -1424,7 +1348,7 @@ description = "Parse Python docstrings in reST, Google and Numpydoc format" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "docstring_parser-0.17.0-py3-none-any.whl", hash = "sha256:cf2569abd23dce8099b300f9b4fa8191e9582dda731fd533daf54c4551658708"}, {file = "docstring_parser-0.17.0.tar.gz", hash = "sha256:583de4a309722b3315439bb31d64ba3eebada841f2e2cee23b99df001434c912"}, @@ -1448,103 +1372,6 @@ files = [ {file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, ] -[[package]] -name = "dotenv" -version = "0.9.9" -description = "Deprecated package" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9"}, -] - -[package.dependencies] -python-dotenv = "*" - -[[package]] -name = "editdistance" -version = "0.8.1" -description = "Fast implementation of the edit distance (Levenshtein distance)" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "editdistance-0.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:adeb705f32b93accc74960d227875abff150ee42d676e428536361fe5f8f5388"}, - {file = "editdistance-0.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3de77951b105d0972deec7684a0b3d1a9dee69c9b5d34f6e2acc0d76cd4a1c52"}, - {file = "editdistance-0.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e88efb052d45e924606c305cb833a80579dca3e8e4ff01309d50ba2c1c0bbd5"}, - {file = "editdistance-0.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0247e7a1e9c66ea75211a97e725366bff19a52aac2c838ed5f90025630e976dd"}, - {file = "editdistance-0.8.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67d143429a49ab552411505f550a0fb4285a1d4336e096804d233ec495ac20fc"}, - {file = "editdistance-0.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca9d3be2b10e5d44a950a4bd1e84bca9ebbecd364bce0cf5693bf8224c78eaef"}, - {file = "editdistance-0.8.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5c72aa1df8535f2e2b3d8773a1a7da091bc1a7e52bb396e7e48d375ba687e7b2"}, - {file = "editdistance-0.8.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a606c34a2a6cc190e4fffc856b36333cdcf1f1fab5b22bd3088e585c22d6ca0"}, - {file = "editdistance-0.8.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5af173d442ffac33b7c7990132f97f88818a3abf4b21c0c702a7022df37c0c5c"}, - {file = "editdistance-0.8.1-cp310-cp310-win32.whl", hash = "sha256:fd64b58f5a7b59afd9d75982aaeeacd2a98498bf472fa0360c122ffe6ea4c871"}, - {file = "editdistance-0.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:6c7c62c3cae45ca1fa01bb2722b297b9de1e3a244ac44cfba88bdcb488fe6aee"}, - {file = "editdistance-0.8.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:486105603a273d73d12a54f347dffa70ab281749d7c3879658b377bc49e4b98c"}, - {file = "editdistance-0.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fad081f5f86a175c1a09a4e9e45b95c9349e454c21e181e842e01c85f1f536fc"}, - {file = "editdistance-0.8.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cb78e125f6759398885a775f5eed07c2bb72b2f86da43e674c6b6a3335b273b"}, - {file = "editdistance-0.8.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3778ca60aa89def9144b70e330bcec5330c7da1d69cb28c612e90b84510a1d3d"}, - {file = "editdistance-0.8.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fba945eaa0436cf40bc53d7e299dc537c7c71353379a095b7459ff4af910da33"}, - {file = "editdistance-0.8.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:877f2a0d801f32bc1a1878901ffb947b974361e849c66e314a7f1d786a446b58"}, - {file = "editdistance-0.8.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e79d351ca40a6ead5f3763253fd7521572ee0d3e5d42538630e56d10f48db481"}, - {file = "editdistance-0.8.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:70ed382b3052a51161bad0149d4665003bf3b949fce0b01bf1253a4cc1a88239"}, - {file = "editdistance-0.8.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a529bfb384c4000775d76739c4e64f73337f0f5a3784933b1321b577a62bed4e"}, - {file = "editdistance-0.8.1-cp311-cp311-win32.whl", hash = "sha256:b082232429e731f181af7f7d2bcf79da6ca8fadd04e9086c11e2973f7d330c81"}, - {file = "editdistance-0.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:cef1a4359252a49f2c4718e64e9d40027d9d951b289d045bdb278656e59f6af8"}, - {file = "editdistance-0.8.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04af61b3fcdd287a07c15b6ae3b02af01c5e3e9c3aca76b8c1d13bd266b6f57"}, - {file = "editdistance-0.8.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:18fc8b6eaae01bfd9cf999af726c1e8dcf667d120e81aa7dbd515bea7427f62f"}, - {file = "editdistance-0.8.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6a87839450a5987028738d061ffa5ef6a68bac2ddc68c9147a8aae9806629c7f"}, - {file = "editdistance-0.8.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24b5f9c9673c823d91b5973d0af8b39f883f414a55ade2b9d097138acd10f31e"}, - {file = "editdistance-0.8.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c59248eabfad603f0fba47b0c263d5dc728fb01c2b6b50fb6ca187cec547fdb3"}, - {file = "editdistance-0.8.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84e239d88ff52821cf64023fabd06a1d9a07654f364b64bf1284577fd3a79d0e"}, - {file = "editdistance-0.8.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2f7f71698f83e8c83839ac0d876a0f4ef996c86c5460aebd26d85568d4afd0db"}, - {file = "editdistance-0.8.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:04e229d6f4ce0c12abc9f4cd4023a5b5fa9620226e0207b119c3c2778b036250"}, - {file = "editdistance-0.8.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e16721636da6d6b68a2c09eaced35a94f4a4a704ec09f45756d4fd5e128ed18d"}, - {file = "editdistance-0.8.1-cp312-cp312-win32.whl", hash = "sha256:87533cf2ebc3777088d991947274cd7e1014b9c861a8aa65257bcdc0ee492526"}, - {file = "editdistance-0.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:09f01ed51746d90178af7dd7ea4ebb41497ef19f53c7f327e864421743dffb0a"}, - {file = "editdistance-0.8.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0b6f52a9d7d434f6882db3dc0340e42da6f177644c23f6a02a739b6247a14b82"}, - {file = "editdistance-0.8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5b413aeb8fe3f77a9e95485fcb64ce84e6b14bcd368124d38bd0062167b3456"}, - {file = "editdistance-0.8.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4ba571e8b6796ad34faeb8581ddc311c35946b2fc183eaebfef59e12ea3538b3"}, - {file = "editdistance-0.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e361e932a85ee1f7091fcb8f7e4619681592c1a0cca251dfd26976dd58254"}, - {file = "editdistance-0.8.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf200104ed4923d4f51ca543bc8488732a31a17848058e65bcba855a7eee2bd2"}, - {file = "editdistance-0.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:387d3bb45befbf8514eb8d17180307580efe4ebaa40ad8b2c14eb04c52ad18a0"}, - {file = "editdistance-0.8.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8e4ea90e92f0e3494bdddad45928393094c258aeef9e4def81a39c3429df0e19"}, - {file = "editdistance-0.8.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5d746ecbf7db7fe0f93ba6971ac43225aac877818a3c2003d41436fee9b33905"}, - {file = "editdistance-0.8.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d789a8ef6fe7cb287ff199381bbd62e9fb2ba4b1e69db817b761d9b42bf8ca7b"}, - {file = "editdistance-0.8.1-cp38-cp38-win32.whl", hash = "sha256:dbbf050fece6c78838a8a95fa4e9a4132023c3d85138870ac83c9dc1dfbfe513"}, - {file = "editdistance-0.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:1c49df0717f64a2c8869edc32c01ba9a22ba20b6cc482876c1067e3a92a6cb2d"}, - {file = "editdistance-0.8.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4d8e9a3e65a68c13dcadc1d2caca620f1716a8d02f2602047e0721b509161ec7"}, - {file = "editdistance-0.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7994a6a0a6ae92db87c144e12f1549ca0e50f43c6cc64e32c628e7af6b9c74b6"}, - {file = "editdistance-0.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dbe0cbc15466e9b7fbf73e34bdcae11cb0c2acd09a60ef4740f2172f9aa5e751"}, - {file = "editdistance-0.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc5f0c7f12a3a3bf2d129e2900deaaa5e47203ef61918343ddc4b6c03e50f089"}, - {file = "editdistance-0.8.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98572c662fd7d425ff24acb8197ad4be7849558a48aebbc60012090bfda4dce9"}, - {file = "editdistance-0.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b35c647a8a17b77441e7b6111b74ae1016851589109e1efc990d27225b3217b"}, - {file = "editdistance-0.8.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2f56c0e006f6b5207985c1bdd62e1873e66bb06a60849cad32716cad1bb3ae40"}, - {file = "editdistance-0.8.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d6bc5a827b262dc9b0d03cfd821682334ce1280520edf6385dc1730e390b5201"}, - {file = "editdistance-0.8.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ad68a2357664e45823b38c9f67a315ff9771263ec502a710057b78c6ca6fcfcd"}, - {file = "editdistance-0.8.1-cp39-cp39-win32.whl", hash = "sha256:16b3e413c020e42b2ef2d4ba01386ead43007217f0bdd704e90474ace90d2023"}, - {file = "editdistance-0.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:331f1a8d3a753858a9d689c0bcd79ad1959e0df464bb6c22cb263cfb6da208e4"}, - {file = "editdistance-0.8.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a4a90c6b03094c07358572027a8d0a13cca7450b1aa6caca98a5f1fa4f0b8961"}, - {file = "editdistance-0.8.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:510a4f9ced348a4fd89ae2e102357d4d801a771e29bb2bc2f130a1692193407f"}, - {file = "editdistance-0.8.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4787fa7228ba6a34b430066d174320f011d605015baa7299c2c4911e6ea6bd46"}, - {file = "editdistance-0.8.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee02601375073afccd6b4d811129ce1cb696d47db734784d8dbd1fddcea75447"}, - {file = "editdistance-0.8.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bc7ad9f9a20e6f351523de77c59249f005242e3f317b5de45d02c378d24f6531"}, - {file = "editdistance-0.8.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7743895df48482fa5a7136543d6bde72e6c10c78a4a4b772fcddda48f792ef68"}, - {file = "editdistance-0.8.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9f139d921aff07deb2c9e592fe23d994af0e59267962a20c062cd66750a0ca4"}, - {file = "editdistance-0.8.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:493587829de3e500bdf34f03f5ab12501867b911acc838e1d04047a3f8941aad"}, - {file = "editdistance-0.8.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16c521157f5d29bf2cb20472482de8450722685d27a6dd801ff1e80cb13a1fd1"}, - {file = "editdistance-0.8.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2a956eb9584d9e8d165bddd9091791924648071c3cdb1e03ec94b1320c2edefd"}, - {file = "editdistance-0.8.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8131acb6b5170382b8b74efab92df8739ac591dc841314e0153af63c4493cb43"}, - {file = "editdistance-0.8.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f182e5e1d2a446138cab085409395c62af36eb1abcbe8cfacb083febfeafd5ce"}, - {file = "editdistance-0.8.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f4f19a829aff230377041acb77afec73becbebafe35b7e322be00cdb3122ddb"}, - {file = "editdistance-0.8.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b978c5927100a57791131dd2418040f4e5d33970d37b97a84c1a530ec481f557"}, - {file = "editdistance-0.8.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0c96a8e981f385f0b7392d047c5caab8e0b24f94b71120787fd78241efc34237"}, - {file = "editdistance-0.8.1.tar.gz", hash = "sha256:d1cdf80a5d5014b0c9126a69a42ce55a457b457f6986ff69ca98e4fe4d2d8fed"}, -] - [[package]] name = "einops" version = "0.8.2" @@ -1564,7 +1391,7 @@ description = "A robust email address syntax and deliverability validation libra optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4"}, {file = "email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426"}, @@ -1574,115 +1401,6 @@ files = [ dnspython = ">=2.0.0" idna = ">=2.0.0" -[[package]] -name = "evalscope" -version = "1.11.1" -description = "EvalScope: Lightweight LLMs Evaluation Framework" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "evalscope-1.11.1-py3-none-any.whl", hash = "sha256:5058c5112ee0dfff0048a48ee1ff9c6e1ca28bbed39ef5cd34a6a14d3ddf2b66"}, - {file = "evalscope-1.11.1.tar.gz", hash = "sha256:4a6f4437a37543a608a08f5279eb215a2832d32d1ecc812ba8442a67c3340460"}, -] - -[package.dependencies] -aiohttp = "*" -colorlog = "*" -docstring_parser = "*" -dotenv = "*" -editdistance = "*" -filetype = "*" -jieba = "*" -jinja2 = "*" -jsonlines = "*" -jsonschema = "*" -latex2sympy2_extended = {version = "*", extras = ["antlr4-9-3"]} -litellm = ">=1.55,<2.0" -Markdown = "*" -modelscope = {version = ">=1.34", extras = ["datasets"]} -more_itertools = "*" -nltk = "*" -openai = "*" -overrides = "*" -pandas = "*" -pillow = "*" -plotly = "*" -pydantic = "*" -pylatexenc = "*" -pyyaml = ">=5.1" -requests = "*" -rich = "*" -rouge-chinese = "*" -rouge-score = ">=0.1.0" -sacrebleu = "*" -sympy = "*" -tabulate = "*" -tqdm = "*" -transformers = ">=4.33,<4.57.2 || >4.57.2" -word2number = "*" -zhconv = "*" - -[package.extras] -aigc = ["diffusers", "iopath", "lpips", "omegaconf", "open_clip_torch", "opencv-python", "peft (>=0.17)", "torch", "torchvision"] -air-bench = ["soundfile"] -all = ["aiohttp", "diffusers", "fastapi", "flask (>=2.0.0)", "flask (>=2.0.0)", "instructor", "iopath", "jinja2", "langchain (>=0.3.0)", "langchain-community (>=0.3.0)", "langchain-core (>=0.3.0)", "langchain-huggingface (>=0.1.0)", "langchain-openai (>=0.3.0)", "lpips", "modelscope[datasets] (>=1.10.0)", "ms-opencompass (>=0.1.6)", "ms-vlmeval (>=0.0.17)", "mteb (>=2.7.0,<3.0.0)", "numpy", "omegaconf", "open_clip_torch", "openai (>=1.0.0)", "opencv-python", "peft (>=0.17)", "plotly (>=5.23.0)", "plotly (>=5.23.0)", "ragas (>=0.4.0,<0.5.0)", "rich", "sentence-transformers (>=5.4.0)", "sse_starlette", "torch", "torch (>=2.0.0)", "torchvision", "transformers", "unstructured", "uvicorn", "uvloop ; sys_platform != \"win32\"", "webdataset (>0.2.0)"] -app = ["flask (>=2.0.0)", "plotly (>=5.23.0)"] -arena-hard = ["scikit-learn"] -bfcl = ["bfcl-eval (==2025.10.27.1)"] -caption = ["pycocoevalcap"] -cc-ocr-v2 = ["apted", "distance", "lxml", "python-Levenshtein", "scipy", "zss"] -deep-swe = ["datacurve-pier (>=0.3.0)"] -dev = ["hypothesis (==6.155.2)", "pre-commit (==4.6.0)", "pytest", "pytest-cov", "python-dotenv"] -docs = ["docutils (>=0.16.0)", "myst_parser", "recommonmark", "sphinx (>=5.3.0)", "sphinx-design", "sphinxawesome-theme"] -general-arena = ["scikit-learn"] -ifbench = ["emoji", "nltk (>=3.9)", "syllapy"] -ifeval = ["langdetect", "nltk (>=3.9)"] -maritime-ocr-bench = ["numpy", "pillow", "shapely"] -mcp = ["mcp (>=1.0)", "mcp-server-fetch"] -miniwob = ["browsergym-miniwob (==0.14.3)"] -multi-if = ["emoji", "langdetect", "nltk (>=3.9)", "pythainlp"] -needle-haystack = ["matplotlib", "seaborn"] -ocr-bench = ["Polygon3", "apted", "distance", "editdistance", "jieba", "lxml", "nltk (>=3.9)", "python-Levenshtein", "zss"] -olmocr-bench = ["beautifulsoup4", "fuzzysearch", "rapidfuzz"] -olympiad-bench = ["latex2sympy2_extended[antlr4-9-3]"] -omnidoc-bench = ["apted", "beautifulsoup4", "distance", "jieba", "lxml", "python-Levenshtein"] -openai-mrcr = ["tiktoken"] -opencompass = ["ms-opencompass (>=0.1.6)"] -perf = ["aiohttp", "fastapi", "jinja2", "numpy", "rich", "sse_starlette", "transformers", "uvicorn", "uvloop ; sys_platform != \"win32\""] -rag = ["instructor", "langchain (>=0.3.0)", "langchain-community (>=0.3.0)", "langchain-core (>=0.3.0)", "langchain-huggingface (>=0.1.0)", "langchain-openai (>=0.3.0)", "modelscope[datasets] (>=1.10.0)", "mteb (>=2.7.0,<3.0.0)", "openai (>=1.0.0)", "ragas (>=0.4.0,<0.5.0)", "sentence-transformers (>=5.4.0)", "torch (>=2.0.0)", "unstructured", "webdataset (>0.2.0)"] -refcoco = ["pycocoevalcap"] -sandbox = ["ms-enclave[docker] (>=0.0.8)"] -service = ["aiohttp", "fastapi", "flask (>=2.0.0)", "jinja2", "numpy", "plotly (>=5.23.0)", "rich", "sse_starlette", "transformers", "uvicorn", "uvloop ; sys_platform != \"win32\""] -swe-bench = ["swebench (==4.1.0)"] -terminal-bench = ["harbor (>=0.8.0,<1.0.0)"] -toolathlon = ["httpx", "websockets"] -torgo = ["jellyfish", "jiwer"] -vlmeval = ["ms-vlmeval (>=0.0.17)"] -vtcbench = ["beautifulsoup4"] -wide-search = ["dateparser"] -wmt = ["unbabel-comet"] - -[[package]] -name = "exceptiongroup" -version = "1.3.1" -description = "Backport of PEP 654 (exception groups)" -optional = false -python-versions = ">=3.7" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, - {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, -] - -[package.dependencies] -typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} - -[package.extras] -test = ["pytest (>=6)"] - [[package]] name = "fastapi" version = "0.135.1" @@ -1722,7 +1440,7 @@ description = "Run and manage FastAPI apps from the command line with FastAPI CL optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "fastapi_cli-0.0.24-py3-none-any.whl", hash = "sha256:4a1f78ed798f106b4fee85ca93b85d8fe33c0a3570f775964d37edb80b8f0edc"}, {file = "fastapi_cli-0.0.24.tar.gz", hash = "sha256:1afc9c9e21d7ebc8a3ca5e31790cd8d837742be7e4f8b9236e99cb3451f0de00"}, @@ -1731,7 +1449,6 @@ files = [ [package.dependencies] fastapi-cloud-cli = {version = ">=0.1.1", optional = true, markers = "extra == \"standard\""} rich-toolkit = ">=0.14.8" -tomli = {version = ">=2.0.0", markers = "python_version < \"3.11\""} typer = ">=0.16.0" uvicorn = {version = ">=0.15.0", extras = ["standard"]} @@ -1747,7 +1464,7 @@ description = "Deploy and manage FastAPI Cloud apps from the command line 🚀" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "fastapi_cloud_cli-0.14.0-py3-none-any.whl", hash = "sha256:325fcb4b45e661184152da6db861d9fb718739fbcd561a4d334dbe78c026586f"}, {file = "fastapi_cloud_cli-0.14.0.tar.gz", hash = "sha256:d3ecb8c942685a71df0af7bd59f463b5eff76f5818b48e5a03c6159726831e68"}, @@ -1756,10 +1473,7 @@ files = [ [package.dependencies] fastar = ">=0.8.0" httpx = ">=0.27.0" -pydantic = [ - {version = ">=2.7.4", extras = ["email"], markers = "python_version < \"3.13\""}, - {version = ">=2.8.0", extras = ["email"], markers = "python_version == \"3.13\""}, -] +pydantic = {version = ">=2.7.4", extras = ["email"], markers = "python_version < \"3.13\""} rich-toolkit = ">=0.19.7" rignore = ">=0.5.1" sentry-sdk = ">=2.20.0" @@ -1776,7 +1490,7 @@ description = "High-level bindings for the Rust tar crate" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "fastar-0.8.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c9f930cff014cf79d396d0541bd9f3a3f170c9b5e45d10d634d98f9ed08788c3"}, {file = "fastar-0.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07b70f712d20622346531a4b46bb332569bea621f61314c0b7e80903a16d14cf"}, @@ -1934,95 +1648,6 @@ files = [ {file = "fastar-0.8.0.tar.gz", hash = "sha256:f4d4d68dbf1c4c2808f0e730fac5843493fc849f70fe3ad3af60dfbaf68b9a12"}, ] -[[package]] -name = "fastuuid" -version = "0.14.0" -description = "Python bindings to Rust's UUID library." -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "fastuuid-0.14.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:6e6243d40f6c793c3e2ee14c13769e341b90be5ef0c23c82fa6515a96145181a"}, - {file = "fastuuid-0.14.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:13ec4f2c3b04271f62be2e1ce7e95ad2dd1cf97e94503a3760db739afbd48f00"}, - {file = "fastuuid-0.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b2fdd48b5e4236df145a149d7125badb28e0a383372add3fbaac9a6b7a394470"}, - {file = "fastuuid-0.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f74631b8322d2780ebcf2d2d75d58045c3e9378625ec51865fe0b5620800c39d"}, - {file = "fastuuid-0.14.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83cffc144dc93eb604b87b179837f2ce2af44871a7b323f2bfed40e8acb40ba8"}, - {file = "fastuuid-0.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a771f135ab4523eb786e95493803942a5d1fc1610915f131b363f55af53b219"}, - {file = "fastuuid-0.14.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4edc56b877d960b4eda2c4232f953a61490c3134da94f3c28af129fb9c62a4f6"}, - {file = "fastuuid-0.14.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bcc96ee819c282e7c09b2eed2b9bd13084e3b749fdb2faf58c318d498df2efbe"}, - {file = "fastuuid-0.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7a3c0bca61eacc1843ea97b288d6789fbad7400d16db24e36a66c28c268cfe3d"}, - {file = "fastuuid-0.14.0-cp310-cp310-win32.whl", hash = "sha256:7f2f3efade4937fae4e77efae1af571902263de7b78a0aee1a1653795a093b2a"}, - {file = "fastuuid-0.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:ae64ba730d179f439b0736208b4c279b8bc9c089b102aec23f86512ea458c8a4"}, - {file = "fastuuid-0.14.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:73946cb950c8caf65127d4e9a325e2b6be0442a224fd51ba3b6ac44e1912ce34"}, - {file = "fastuuid-0.14.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:12ac85024637586a5b69645e7ed986f7535106ed3013640a393a03e461740cb7"}, - {file = "fastuuid-0.14.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:05a8dde1f395e0c9b4be515b7a521403d1e8349443e7641761af07c7ad1624b1"}, - {file = "fastuuid-0.14.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09378a05020e3e4883dfdab438926f31fea15fd17604908f3d39cbeb22a0b4dc"}, - {file = "fastuuid-0.14.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbb0c4b15d66b435d2538f3827f05e44e2baafcc003dd7d8472dc67807ab8fd8"}, - {file = "fastuuid-0.14.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cd5a7f648d4365b41dbf0e38fe8da4884e57bed4e77c83598e076ac0c93995e7"}, - {file = "fastuuid-0.14.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c0a94245afae4d7af8c43b3159d5e3934c53f47140be0be624b96acd672ceb73"}, - {file = "fastuuid-0.14.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2b29e23c97e77c3a9514d70ce343571e469098ac7f5a269320a0f0b3e193ab36"}, - {file = "fastuuid-0.14.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1e690d48f923c253f28151b3a6b4e335f2b06bf669c68a02665bc150b7839e94"}, - {file = "fastuuid-0.14.0-cp311-cp311-win32.whl", hash = "sha256:a6f46790d59ab38c6aa0e35c681c0484b50dc0acf9e2679c005d61e019313c24"}, - {file = "fastuuid-0.14.0-cp311-cp311-win_amd64.whl", hash = "sha256:e150eab56c95dc9e3fefc234a0eedb342fac433dacc273cd4d150a5b0871e1fa"}, - {file = "fastuuid-0.14.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77e94728324b63660ebf8adb27055e92d2e4611645bf12ed9d88d30486471d0a"}, - {file = "fastuuid-0.14.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:caa1f14d2102cb8d353096bc6ef6c13b2c81f347e6ab9d6fbd48b9dea41c153d"}, - {file = "fastuuid-0.14.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d23ef06f9e67163be38cece704170486715b177f6baae338110983f99a72c070"}, - {file = "fastuuid-0.14.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c9ec605ace243b6dbe3bd27ebdd5d33b00d8d1d3f580b39fdd15cd96fd71796"}, - {file = "fastuuid-0.14.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:808527f2407f58a76c916d6aa15d58692a4a019fdf8d4c32ac7ff303b7d7af09"}, - {file = "fastuuid-0.14.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fb3c0d7fef6674bbeacdd6dbd386924a7b60b26de849266d1ff6602937675c8"}, - {file = "fastuuid-0.14.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab3f5d36e4393e628a4df337c2c039069344db5f4b9d2a3c9cea48284f1dd741"}, - {file = "fastuuid-0.14.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b9a0ca4f03b7e0b01425281ffd44e99d360e15c895f1907ca105854ed85e2057"}, - {file = "fastuuid-0.14.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3acdf655684cc09e60fb7e4cf524e8f42ea760031945aa8086c7eae2eeeabeb8"}, - {file = "fastuuid-0.14.0-cp312-cp312-win32.whl", hash = "sha256:9579618be6280700ae36ac42c3efd157049fe4dd40ca49b021280481c78c3176"}, - {file = "fastuuid-0.14.0-cp312-cp312-win_amd64.whl", hash = "sha256:d9e4332dc4ba054434a9594cbfaf7823b57993d7d8e7267831c3e059857cf397"}, - {file = "fastuuid-0.14.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77a09cb7427e7af74c594e409f7731a0cf887221de2f698e1ca0ebf0f3139021"}, - {file = "fastuuid-0.14.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:9bd57289daf7b153bfa3e8013446aa144ce5e8c825e9e366d455155ede5ea2dc"}, - {file = "fastuuid-0.14.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ac60fc860cdf3c3f327374db87ab8e064c86566ca8c49d2e30df15eda1b0c2d5"}, - {file = "fastuuid-0.14.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab32f74bd56565b186f036e33129da77db8be09178cd2f5206a5d4035fb2a23f"}, - {file = "fastuuid-0.14.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33e678459cf4addaedd9936bbb038e35b3f6b2061330fd8f2f6a1d80414c0f87"}, - {file = "fastuuid-0.14.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1e3cc56742f76cd25ecb98e4b82a25f978ccffba02e4bdce8aba857b6d85d87b"}, - {file = "fastuuid-0.14.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cb9a030f609194b679e1660f7e32733b7a0f332d519c5d5a6a0a580991290022"}, - {file = "fastuuid-0.14.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:09098762aad4f8da3a888eb9ae01c84430c907a297b97166b8abc07b640f2995"}, - {file = "fastuuid-0.14.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:1383fff584fa249b16329a059c68ad45d030d5a4b70fb7c73a08d98fd53bcdab"}, - {file = "fastuuid-0.14.0-cp313-cp313-win32.whl", hash = "sha256:a0809f8cc5731c066c909047f9a314d5f536c871a7a22e815cc4967c110ac9ad"}, - {file = "fastuuid-0.14.0-cp313-cp313-win_amd64.whl", hash = "sha256:0df14e92e7ad3276327631c9e7cec09e32572ce82089c55cb1bb8df71cf394ed"}, - {file = "fastuuid-0.14.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:b852a870a61cfc26c884af205d502881a2e59cc07076b60ab4a951cc0c94d1ad"}, - {file = "fastuuid-0.14.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:c7502d6f54cd08024c3ea9b3514e2d6f190feb2f46e6dbcd3747882264bb5f7b"}, - {file = "fastuuid-0.14.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ca61b592120cf314cfd66e662a5b54a578c5a15b26305e1b8b618a6f22df714"}, - {file = "fastuuid-0.14.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa75b6657ec129d0abded3bec745e6f7ab642e6dba3a5272a68247e85f5f316f"}, - {file = "fastuuid-0.14.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8a0dfea3972200f72d4c7df02c8ac70bad1bb4c58d7e0ec1e6f341679073a7f"}, - {file = "fastuuid-0.14.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1bf539a7a95f35b419f9ad105d5a8a35036df35fdafae48fb2fd2e5f318f0d75"}, - {file = "fastuuid-0.14.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:9a133bf9cc78fdbd1179cb58a59ad0100aa32d8675508150f3658814aeefeaa4"}, - {file = "fastuuid-0.14.0-cp314-cp314-musllinux_1_1_i686.whl", hash = "sha256:f54d5b36c56a2d5e1a31e73b950b28a0d83eb0c37b91d10408875a5a29494bad"}, - {file = "fastuuid-0.14.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:ec27778c6ca3393ef662e2762dba8af13f4ec1aaa32d08d77f71f2a70ae9feb8"}, - {file = "fastuuid-0.14.0-cp314-cp314-win32.whl", hash = "sha256:e23fc6a83f112de4be0cc1990e5b127c27663ae43f866353166f87df58e73d06"}, - {file = "fastuuid-0.14.0-cp314-cp314-win_amd64.whl", hash = "sha256:df61342889d0f5e7a32f7284e55ef95103f2110fee433c2ae7c2c0956d76ac8a"}, - {file = "fastuuid-0.14.0-cp38-cp38-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:47c821f2dfe95909ead0085d4cb18d5149bca704a2b03e03fb3f81a5202d8cea"}, - {file = "fastuuid-0.14.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:3964bab460c528692c70ab6b2e469dd7a7b152fbe8c18616c58d34c93a6cf8d4"}, - {file = "fastuuid-0.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c501561e025b7aea3508719c5801c360c711d5218fc4ad5d77bf1c37c1a75779"}, - {file = "fastuuid-0.14.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2dce5d0756f046fa792a40763f36accd7e466525c5710d2195a038f93ff96346"}, - {file = "fastuuid-0.14.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193ca10ff553cf3cc461572da83b5780fc0e3eea28659c16f89ae5202f3958d4"}, - {file = "fastuuid-0.14.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0737606764b29785566f968bd8005eace73d3666bd0862f33a760796e26d1ede"}, - {file = "fastuuid-0.14.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e0976c0dff7e222513d206e06341503f07423aceb1db0b83ff6851c008ceee06"}, - {file = "fastuuid-0.14.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6fbc49a86173e7f074b1a9ec8cf12ca0d54d8070a85a06ebf0e76c309b84f0d0"}, - {file = "fastuuid-0.14.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:de01280eabcd82f7542828ecd67ebf1551d37203ecdfd7ab1f2e534edb78d505"}, - {file = "fastuuid-0.14.0-cp38-cp38-win32.whl", hash = "sha256:af5967c666b7d6a377098849b07f83462c4fedbafcf8eb8bc8ff05dcbe8aa209"}, - {file = "fastuuid-0.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3091e63acf42f56a6f74dc65cfdb6f99bfc79b5913c8a9ac498eb7ca09770a8"}, - {file = "fastuuid-0.14.0-cp39-cp39-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:2ec3d94e13712a133137b2805073b65ecef4a47217d5bac15d8ac62376cefdb4"}, - {file = "fastuuid-0.14.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:139d7ff12bb400b4a0c76be64c28cbe2e2edf60b09826cbfd85f33ed3d0bbe8b"}, - {file = "fastuuid-0.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d55b7e96531216fc4f071909e33e35e5bfa47962ae67d9e84b00a04d6e8b7173"}, - {file = "fastuuid-0.14.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0eb25f0fd935e376ac4334927a59e7c823b36062080e2e13acbaf2af15db836"}, - {file = "fastuuid-0.14.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:089c18018fdbdda88a6dafd7d139f8703a1e7c799618e33ea25eb52503d28a11"}, - {file = "fastuuid-0.14.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fc37479517d4d70c08696960fad85494a8a7a0af4e93e9a00af04d74c59f9e3"}, - {file = "fastuuid-0.14.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:73657c9f778aba530bc96a943d30e1a7c80edb8278df77894fe9457540df4f85"}, - {file = "fastuuid-0.14.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d31f8c257046b5617fc6af9c69be066d2412bdef1edaa4bdf6a214cf57806105"}, - {file = "fastuuid-0.14.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5816d41f81782b209843e52fdef757a361b448d782452d96abedc53d545da722"}, - {file = "fastuuid-0.14.0-cp39-cp39-win32.whl", hash = "sha256:448aa6833f7a84bfe37dd47e33df83250f404d591eb83527fa2cac8d1e57d7f3"}, - {file = "fastuuid-0.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:84b0779c5abbdec2a9511d5ffbfcd2e53079bf889824b32be170c0d8ef5fc74c"}, - {file = "fastuuid-0.14.0.tar.gz", hash = "sha256:178947fc2f995b38497a74172adee64fdeb8b7ec18f2a5934d037641ba265d26"}, -] - [[package]] name = "filelock" version = "3.25.0" @@ -2035,19 +1660,6 @@ files = [ {file = "filelock-3.25.0.tar.gz", hash = "sha256:8f00faf3abf9dc730a1ffe9c354ae5c04e079ab7d3a683b7c32da5dd05f26af3"}, ] -[[package]] -name = "filetype" -version = "1.2.0" -description = "Infer file type and MIME type of any file/buffer. No external dependencies." -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "filetype-1.2.0-py2.py3-none-any.whl", hash = "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25"}, - {file = "filetype-1.2.0.tar.gz", hash = "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb"}, -] - [[package]] name = "flashinfer-python" version = "0.6.3" @@ -2055,7 +1667,7 @@ description = "FlashInfer: Kernel Library for LLM Serving" optional = true python-versions = "<4.0,>=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "flashinfer_python-0.6.3-py3-none-any.whl", hash = "sha256:0fe2de934a4b3690c543dafb03f38d7bb4a762431abe8ae4f7292d6fef10c65d"}, {file = "flashinfer_python-0.6.3.tar.gz", hash = "sha256:84a762538247a86bc52ff31d9505d161ce1ec059174c1821c87c3ed1e44670fc"}, @@ -2266,7 +1878,7 @@ description = "Read and write ML models in GGUF for GGML" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "gguf-0.18.0-py3-none-any.whl", hash = "sha256:af93f7ef198a265cbde5fa6a6b3101528bca285903949ab0a3e591cd993a1864"}, {file = "gguf-0.18.0.tar.gz", hash = "sha256:b4659093d5d0dccdb5902a904d54b327f4052879fe5e90946ad5fce9f8018c2e"}, @@ -2288,7 +1900,7 @@ description = "Google API client core library" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "google_api_core-2.30.0-py3-none-any.whl", hash = "sha256:80be49ee937ff9aba0fd79a6eddfde35fe658b9953ab9b79c57dd7061afa8df5"}, {file = "google_api_core-2.30.0.tar.gz", hash = "sha256:02edfa9fab31e17fc0befb5f161b3bf93c9096d99aed584625f38065c511ad9b"}, @@ -2297,10 +1909,7 @@ files = [ [package.dependencies] google-auth = ">=2.14.1,<3.0.0" googleapis-common-protos = ">=1.56.3,<2.0.0" -proto-plus = [ - {version = ">=1.22.3,<2.0.0"}, - {version = ">=1.25.0,<2.0.0", markers = "python_version >= \"3.13\""}, -] +proto-plus = ">=1.22.3,<2.0.0" protobuf = ">=4.25.8,<7.0.0" requests = ">=2.20.0,<3.0.0" @@ -2315,7 +1924,7 @@ description = "Google Authentication Library" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "google_auth-2.48.0-py3-none-any.whl", hash = "sha256:2e2a537873d449434252a9632c28bfc268b0adb1e53f9fb62afc5333a975903f"}, {file = "google_auth-2.48.0.tar.gz", hash = "sha256:4f7e706b0cd3208a3d940a19a822c37a476ddba5450156c3e6624a71f7c841ce"}, @@ -2344,7 +1953,7 @@ description = "Common protobufs used in Google APIs" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" +markers = "extra == \"ray\"" files = [ {file = "googleapis_common_protos-1.72.0-py3-none-any.whl", hash = "sha256:4299c5a82d5ae1a9702ada957347726b167f9f8d1fc352477702a1e851ff4038"}, {file = "googleapis_common_protos-1.72.0.tar.gz", hash = "sha256:e55a601c1b32b52d7a3e65f43563e2aa61bcd737998ee672ac9b951cd49319f5"}, @@ -2363,7 +1972,7 @@ description = "HTTP/2-based RPC framework" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"server\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "grpcio-1.78.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:7cc47943d524ee0096f973e1081cb8f4f17a4615f2116882a5f1416e4cfe92b5"}, {file = "grpcio-1.78.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:c3f293fdc675ccba4db5a561048cca627b5e7bd1c8a6973ffedabe7d116e22e2"}, @@ -2441,7 +2050,7 @@ description = "Standard Protobuf Reflection Service for gRPC" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "grpcio_reflection-1.78.0-py3-none-any.whl", hash = "sha256:06fcfde9e6888cdd12e9dd1cf6dc7c440c2e9acf420f696ccbe008672ed05b60"}, {file = "grpcio_reflection-1.78.0.tar.gz", hash = "sha256:e6e60c0b85dbcdf963b4d4d150c0f1d238ba891d805b575c52c0365d07fc0c40"}, @@ -2458,7 +2067,7 @@ description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" +markers = "extra == \"vllm\" or extra == \"ray\" or extra == \"tinker\"" files = [ {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, @@ -2471,7 +2080,7 @@ description = "Pure-Python HTTP/2 protocol implementation" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "python_version >= \"3.11\" and extra == \"client\"" +markers = "extra == \"tinker\"" files = [ {file = "h2-4.3.0-py3-none-any.whl", hash = "sha256:c438f029a25f7945c69e0ccf0fb951dc3f73a5f6412981daee861431b70e2bdd"}, {file = "h2-4.3.0.tar.gz", hash = "sha256:6c59efe4323fa18b47a632221a1888bd7fde6249819beda254aeca909f221bf1"}, @@ -2527,7 +2136,7 @@ description = "Pure-Python HPACK header encoding" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "python_version >= \"3.11\" and extra == \"client\"" +markers = "extra == \"tinker\"" files = [ {file = "hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496"}, {file = "hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca"}, @@ -2540,7 +2149,7 @@ description = "A minimal low-level HTTP client." optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" +markers = "extra == \"vllm\" or extra == \"tinker\"" files = [ {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, @@ -2563,7 +2172,7 @@ description = "A collection of framework independent HTTP protocol utils." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "httptools-0.7.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:11d01b0ff1fe02c4c32d60af61a4d613b74fad069e47e06e9067758c01e9ac78"}, {file = "httptools-0.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84d86c1e5afdc479a6fdabf570be0d3eb791df0ae727e8dbc0259ed1249998d4"}, @@ -2617,7 +2226,7 @@ description = "The next generation HTTP client." optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" +markers = "extra == \"vllm\" or extra == \"tinker\"" files = [ {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, @@ -2644,7 +2253,7 @@ description = "Consume Server-Sent Event (SSE) messages with HTTPX." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc"}, {file = "httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d"}, @@ -2689,24 +2298,6 @@ testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "authlib (>=1. torch = ["safetensors[torch]", "torch"] typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] -[[package]] -name = "hydra-core" -version = "1.3.7" -description = "A framework for elegantly configuring complex applications" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "hydra_core-1.3.7-py3-none-any.whl", hash = "sha256:83606c4a05c770f1e026e0489875f28989829d151799eabd8cfa8cbe82164515"}, - {file = "hydra_core-1.3.7.tar.gz", hash = "sha256:d4ff629c7e23b64a9db5fe5b027cf7c55b633b737f03be51ef41b77ed016f75e"}, -] - -[package.dependencies] -antlr4-python3-runtime = "==4.9.*" -omegaconf = ">=2.2,<2.4" -packaging = "*" - [[package]] name = "hyperframe" version = "6.1.0" @@ -2714,126 +2305,12 @@ description = "Pure-Python HTTP/2 framing" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "python_version >= \"3.11\" and extra == \"client\"" +markers = "extra == \"tinker\"" files = [ {file = "hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5"}, {file = "hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08"}, ] -[[package]] -name = "hypothesis" -version = "6.168.0" -description = "The property-based testing library for Python" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"test\"" -files = [ - {file = "hypothesis-6.168.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:47b89491ff02e3ae9b302c440457938e87b47a45b9a1d98ff5575b6910d779e2"}, - {file = "hypothesis-6.168.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:1f4cd0ff11bd470a1a846296ed5fe55e84214194850370994fd1370fe73d3099"}, - {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:732ae5d47482f99d8028cca096729625f05690a83f5e7ce31466e266155792f4"}, - {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2085ee74ac3ab6b70e2f7ffae9b4cb74c246da2f574b2de81a0818a8a30f659f"}, - {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1894782fae5d9a7bb44e6dcf848ccb09ccb5babab48d8b5c31a0a7fc025b82a1"}, - {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecf0ab13cef899efb816ffdd7963e0679f372520884ce06756c7642f3df94213"}, - {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:3f6dcf66270278d078bed01b401f47db4e26456cd909d8e23c6b9366a6c0b131"}, - {file = "hypothesis-6.168.0-cp310-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bfef4d46dbf1704a7b8fa3a78778651a2cb18870ca0a70da19c381646822b149"}, - {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1d1aa5b3484e329295d88488a5ba06243909e65c2ab616513c2d36721de4ed1d"}, - {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:3bc00fd8cda04b58e37a1163e8a65389b247b4f5ee547ae37d244a4960995517"}, - {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:990026952d5b2eca290c88f639ac639233f47e13dae338c6dfb6e4774bcab349"}, - {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:a74b0945acbbd552c7c2d0a99a3b5232962b8848c8eed1829451800a9bfcf00b"}, - {file = "hypothesis-6.168.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2a380b521b5a76a9e8917d64adcf7f861a45a4360a34b1579af14c5df8eb0377"}, - {file = "hypothesis-6.168.0-cp310-abi3-win32.whl", hash = "sha256:2264f15a1c80329e3ad48e39c44bd5c9429b7b04c9ee62cdd72f4b10aaac9f29"}, - {file = "hypothesis-6.168.0-cp310-abi3-win_amd64.whl", hash = "sha256:5b54769033b84477931d2072e7133a7555e0de5c53fd5ca3bbde960762d7d31b"}, - {file = "hypothesis-6.168.0-cp310-abi3-win_arm64.whl", hash = "sha256:112b0900059bf9d7d6528ed729770629ab146e0d133c4143b9bd4a01dc002bcc"}, - {file = "hypothesis-6.168.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:cb10aa59b0af45badca76911f5323f40d24fdbe00d01b7b67fef8648c99411b5"}, - {file = "hypothesis-6.168.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e21e30b76b6d3adb87c550576132a3204f4c257ec43353f6c09b9d59bb762abc"}, - {file = "hypothesis-6.168.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:527452b43e79e6dfbf9cb69145a940547a3cd177c556698a3fc939ed2354c4b3"}, - {file = "hypothesis-6.168.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:489d5c060f49f495b64215cae627c71730cffd5ef59dc4d7f431932e6e6d2e67"}, - {file = "hypothesis-6.168.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c3af200b322f710c76c2189866246cdcff2039165dd77edff1a7bf1157162fb0"}, - {file = "hypothesis-6.168.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73084b76e4a79cd0f7883ce80fc60c9f374ce7dcad8f520b39db40470ce1852f"}, - {file = "hypothesis-6.168.0-cp310-cp310-win_amd64.whl", hash = "sha256:8067e6b4b48e5cfdc849a1a20c9d4972b3f532b3e3edb5e2b5dfd106045a5236"}, - {file = "hypothesis-6.168.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4d7d29dd63ad9fdc4aa1d65fa272449e14aaf6c6bb8451091818c2945533a43a"}, - {file = "hypothesis-6.168.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a72ed7afa1f7e30488b8a5754fca0ad9755518bdb77d6f0b003cadf7437a5f9"}, - {file = "hypothesis-6.168.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcc5bad4300a751804ce41f0e10d77f85272668160708ce39ec579bca8984843"}, - {file = "hypothesis-6.168.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53469a1a7c4861b12c9a8622f762d7d1fd7bcf171884e1018ed5a8f063a5c063"}, - {file = "hypothesis-6.168.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a9650c4882fdbdd8e90bdae602a8bfa8c6f09dc5d06afec5b9b23982e8f60a04"}, - {file = "hypothesis-6.168.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:348d9b93fd4129f67f9bab94f3d70709a9372bbe0e0d22731325ce85d5eb409f"}, - {file = "hypothesis-6.168.0-cp311-cp311-win_amd64.whl", hash = "sha256:719b45b0512e3535a6a0077c2f7c6053b02ac0e72d60693f66f98790a33855b2"}, - {file = "hypothesis-6.168.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6b750390dac4429da0cb70ab3fe758457f0cea3d9c843d48c59d0690d1189fda"}, - {file = "hypothesis-6.168.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8e4b2d434e0dd134f3d31ac1efc1825bf99730dfe70fec005ff66d7211836d79"}, - {file = "hypothesis-6.168.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76d4d36ed2fd62de11382f1d608169c1ffa9a49d3b9351146d8ff87cb81a66f7"}, - {file = "hypothesis-6.168.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5920d267f7d8cfd376672f2bde5905cdf284d47519582e41ce7c142d48ee46c4"}, - {file = "hypothesis-6.168.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fb8cdf45361e259df86e19f8cd042ce2d6c7e6ad88fa631b78a4e3a83c2e572d"}, - {file = "hypothesis-6.168.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b3ce1cce70b25a37ed1a38a53ce7204785726c675c0f41a0f83c338a7e47b3d"}, - {file = "hypothesis-6.168.0-cp312-cp312-win_amd64.whl", hash = "sha256:f62bdabf278db9ff61df5f3203d608949f0d893d0e30cdac3f2330e67e41ae68"}, - {file = "hypothesis-6.168.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d55562bf8d41cfa18559c33f30cadf44ceac8e517509d7a022a9feace621f28"}, - {file = "hypothesis-6.168.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92cff497b92e2285ff6a94193fdee04aba483a4115d501c1f9a570bd103fcd20"}, - {file = "hypothesis-6.168.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ff259260015f9be3756dcd4bc11c08e007314dec6b43d9a89084c4f34f94475"}, - {file = "hypothesis-6.168.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35f1262831b5acc74ded15f629965daffcd657f6016ee04fc9605f6eb2b334c0"}, - {file = "hypothesis-6.168.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:046fe4bcfce2a2fa186ba9d96bbb62c25c2f6c2e4071f0783ed6b5cc481d0669"}, - {file = "hypothesis-6.168.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:24b52a2b1c8db6e1e516f9295c8e4ef7ef63303ff24fbbc5b35f4ff71dcd732c"}, - {file = "hypothesis-6.168.0-cp313-cp313-win_amd64.whl", hash = "sha256:ec0886fe0be9091669937989f9a662beca42ae14a4a6dab25491c2c63365f88d"}, - {file = "hypothesis-6.168.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e2df8afacf9261070795db36db4a394e3ccdbb663fd2d38c7a9fba0c836dcecc"}, - {file = "hypothesis-6.168.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9ba679f183c67adcb6f4ad93694beafb6da99fe691757f4e57b04ae77e581ba8"}, - {file = "hypothesis-6.168.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d9a8574f80fc859313aee56167d202e8625c0eedd200971130f0839f06d1c93"}, - {file = "hypothesis-6.168.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deb02de608268928d779aa889b0a9d67794b1cc0c54a322cf19e386be8a46ca7"}, - {file = "hypothesis-6.168.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:076a2096c34448931c3cfeb2eb7a6b843a56ffdce5e4e3a025bfdf8f935666d9"}, - {file = "hypothesis-6.168.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f099b1c8fc49ec2d9d7944e661addb97d7c38e818fb8d1f78073c43895a87f6"}, - {file = "hypothesis-6.168.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:93413d1b0af50a7b165d66278c529174bf2fd1773c78027735dc0b50d1d3fd27"}, - {file = "hypothesis-6.168.0-cp314-cp314-win_amd64.whl", hash = "sha256:db2751c27bffc8491a96d72969649089d5400115e4b7c49bf7167ebbdcc84193"}, - {file = "hypothesis-6.168.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:cd0c1dcf308e919c8ae708054d0ad61921ae87634a9aea574a9851da584cebc1"}, - {file = "hypothesis-6.168.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d0bdb77f976740b8cd5ec697327ea343d02d052b9916d213b5d4c65d823415cd"}, - {file = "hypothesis-6.168.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f7486bed33225d02f6aa78a4c4ba2b6f84992a82571cdda1bf08dce41d13507"}, - {file = "hypothesis-6.168.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ba3838c4a92e0b9730d1ed7e67e4950c152ad79d0a0c7594065262db84c55c4"}, - {file = "hypothesis-6.168.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:891b2d281ede45130e7fa0a22fd65336cc77ef2f780ec3792e8de6fc274a02c8"}, - {file = "hypothesis-6.168.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e86820053afad84677f301c0b892a226be1df49790800a65668ae7cc8a1ac571"}, - {file = "hypothesis-6.168.0-cp314-cp314t-win_amd64.whl", hash = "sha256:a4956f41ab1ec6e6ef9262a35970e9f3e2caaaa1cdafe0d413156c6934dd99d8"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:754016594fe78cef91790e0922f60d183c52f531255fbfa30dac495b813e2128"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:6f0dd437ec01140676192422b61f2f833b3ce6a3213da9b7e196ad6b3777e795"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f77af7721ff35a58fa8797decd14c932c350a2548686c6e9b844db710a3a2441"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a0d28418c104d7268fdebcc09bc49f7b6569b5eb942430c6859f53ec8d4edf63"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:812a84c4cc7f7ae4fcb39a5647cc2698e6c18254f8423126425578f1dcdac782"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6de30e559eb151de14a5f74bceb4d97792a9315ada2a1816b5da825cd7d28edc"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:9018b20acdb061b2ef4b2fa7f558ca5db97ffea316e0a528bc003a24b2ac996e"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bc935a5d5f86fd8f5af951b8fbe00307f6f7c596f82a9a27c17d974f6ab0a26c"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:45fcfa05f746e253350f55f216bcef59754f5f2b85745f1fc2bb8ba81dd517a9"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:f89d8e998d3c936ffbbd1c3686c96f0378f6558aecc5967a3035a857f2bab0ad"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:d0620fa320fa66649e6bfd71e94f3f86115fffebb7e3c6dcece19d1aaff8e07f"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:4085b61e25d3dcc6c9151d4115269870aee8cdb921611ee5c989b2786449be09"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:b5449a64eb37d9a4aa6ac9cd2ab0fd1a24145adf421ef1536884f73f39824887"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-win32.whl", hash = "sha256:91e3de666a6c4f7543000d1710e25055d63ef3032c98bd2ab338b3087bdaa780"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:9a2079cd09919956dd388f1a1f8ea5a79f2b2437650fbeda31d8661217ffefef"}, - {file = "hypothesis-6.168.0-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:085c9aa246487c56a40ca89003d285cbffdbb5be4097ba6d0139f9c21003c04a"}, - {file = "hypothesis-6.168.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:16864797de4b024e4c6cebd44598af932f870aad811341bc5bc24c738801ff76"}, - {file = "hypothesis-6.168.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:283eda952bcb1987ccba1c8b634db0e8a960e1e92e2daa7003bc2392f19cea01"}, - {file = "hypothesis-6.168.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5427a3c951080c18170486f775df6a82153882b819eca6b8e7ed77693634e5ab"}, - {file = "hypothesis-6.168.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a838218ff1eab8d7b4bf66b96037fce0a802f61f2fa5fd4b784696cac365ce7"}, - {file = "hypothesis-6.168.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:34e3c8b66047ba92f8b8df5e427074058d92db58038f007da4bf9d14e934ad3c"}, - {file = "hypothesis-6.168.0.tar.gz", hash = "sha256:72af51087b7b5ab21c49f0d502f803c20897678652835596bd2a8b169a39135e"}, -] - -[package.dependencies] -exceptiongroup = {version = ">=1.0.0", markers = "python_full_version < \"3.11.0\""} -sortedcontainers = ">=2.1.0,<3.0.0" - -[package.extras] -all = ["black (>=20.8b0)", "click (>=7.0)", "crosshair-tool (>=0.0.110)", "django (>=5.2)", "dpcontracts (>=0.4)", "hypothesis-crosshair (>=0.0.30)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.21.6)", "pandas (>=1.1)", "pytest (>=4.6)", "python-dateutil (>=1.4)", "pytz (>=2014.1)", "redis (>=3.0.0)", "rich (>=9.0.0)", "tzdata (>=2026.3) ; sys_platform == \"emscripten\" or sys_platform == \"win32\"", "watchdog (>=4.0.0)"] -cli = ["black (>=20.8b0)", "click (>=7.0)", "rich (>=9.0.0)"] -codemods = ["libcst (>=0.3.16)"] -crosshair = ["crosshair-tool (>=0.0.110)", "hypothesis-crosshair (>=0.0.30)"] -dateutil = ["python-dateutil (>=1.4)"] -django = ["django (>=5.2)"] -dpcontracts = ["dpcontracts (>=0.4)"] -ghostwriter = ["black (>=20.8b0)"] -lark = ["lark (>=0.10.1)"] -numpy = ["numpy (>=1.21.6)"] -pandas = ["pandas (>=1.1)"] -pytest = ["pytest (>=4.6)"] -pytz = ["pytz (>=2014.1)"] -redis = ["redis (>=3.0.0)"] -watchdog = ["watchdog (>=4.0.0)"] -zoneinfo = ["tzdata (>=2026.3) ; sys_platform == \"emscripten\" or sys_platform == \"win32\""] - [[package]] name = "idna" version = "3.11" @@ -2856,7 +2333,7 @@ description = "Iterative JSON parser with standard Python iterator interfaces" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "ijson-3.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ea8dcac10d86adaeead454bc25c97b68d0bda573d5fd6f86f5e21cf8f7906f88"}, {file = "ijson-3.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:92b0495bbb2150bbf14fc5d98fb6d76bcd1c526605a172709e602e6fedc96495"}, @@ -2975,7 +2452,7 @@ description = "Read metadata from Python packages" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "(python_version >= \"3.11\" or extra == \"eval\" or extra == \"megatron\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\") and (python_version == \"3.11\" or extra == \"eval\" or extra == \"megatron\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"client\") and (extra == \"client\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"eval\" or extra == \"megatron\")" +markers = "extra == \"megatron\" or extra == \"ray\"" files = [ {file = "importlib_metadata-8.7.1-py3-none-any.whl", hash = "sha256:5a1f80bf1daa489495071efbb095d75a634cf28a8bc299581244063b53176151"}, {file = "importlib_metadata-8.7.1.tar.gz", hash = "sha256:49fef1ae6440c182052f407c8d34a68f72efc36db9ca90dc0113398f2fdde8bb"}, @@ -2993,19 +2470,6 @@ perf = ["ipython"] test = ["flufl.flake8", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["mypy (<1.19) ; platform_python_implementation == \"PyPy\"", "pytest-mypy (>=1.0.1)"] -[[package]] -name = "iniconfig" -version = "2.3.0" -description = "brain-dead simple config-ini parsing" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"test\"" -files = [ - {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, - {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, -] - [[package]] name = "interegular" version = "0.3.3" @@ -3013,24 +2477,12 @@ description = "a regex intersection checker" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "interegular-0.3.3-py37-none-any.whl", hash = "sha256:b0c07007d48c89d6d19f7204972d369b2a77222722e126b6aa63aa721dc3b19c"}, {file = "interegular-0.3.3.tar.gz", hash = "sha256:d9b697b21b34884711399ba0f0376914b81899ce670032486d0d048344a76600"}, ] -[[package]] -name = "jieba" -version = "0.42.1" -description = "Chinese Words Segmentation Utilities" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "jieba-0.42.1.tar.gz", hash = "sha256:055ca12f62674fafed09427f176506079bc135638a14e23e25be909131928db2"}, -] - [[package]] name = "jinja2" version = "3.1.6" @@ -3056,7 +2508,7 @@ description = "Fast iterable JSON parser." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" +markers = "extra == \"vllm\"" files = [ {file = "jiter-0.13.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2ffc63785fd6c7977defe49b9824ae6ce2b2e2b77ce539bdaf006c26da06342e"}, {file = "jiter-0.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4a638816427006c1e3f0013eb66d391d7a3acda99a7b0cf091eff4497ccea33a"}, @@ -3169,48 +2621,12 @@ description = "JSON Matching Expressions" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64"}, {file = "jmespath-1.1.0.tar.gz", hash = "sha256:472c87d80f36026ae83c6ddd0f1d05d4e510134ed462851fd5f754c8c3cbb88d"}, ] -[[package]] -name = "joblib" -version = "1.6.0" -description = "Lightweight pipelining with Python functions" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "joblib-1.6.0-py3-none-any.whl", hash = "sha256:3dbbf9f6e4b592a2357b854608e980fe6390d131d7a82f011a377ef2ebef7aba"}, - {file = "joblib-1.6.0.tar.gz", hash = "sha256:2ccc96785b12046c08fd6d55839c12857831b54a3c1673ffadd2f04bfc4eda03"}, -] - -[package.dependencies] -cloudpickle = ">=3.0" - -[package.extras] -docs = ["distributed", "lz4", "matplotlib", "numpy", "numpydoc", "pandas", "psutil", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx-gallery", "tqdm"] -test = ["distributed", "lz4", "memory_profiler", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-run-parallel", "pytest-timeout", "threadpoolctl"] - -[[package]] -name = "jsonlines" -version = "4.0.0" -description = "Library with helpers for the jsonlines file format" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "jsonlines-4.0.0-py3-none-any.whl", hash = "sha256:185b334ff2ca5a91362993f42e83588a360cf95ce4b71a73548502bda52a7c55"}, - {file = "jsonlines-4.0.0.tar.gz", hash = "sha256:0c6d2c09117550c089995247f605ae4cf77dd1533041d366351f6f298822ea74"}, -] - -[package.dependencies] -attrs = ">=19.2.0" - [[package]] name = "jsonschema" version = "4.26.0" @@ -3218,7 +2634,7 @@ description = "An implementation of JSON Schema validation for Python" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce"}, {file = "jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326"}, @@ -3226,7 +2642,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.03.6" +jsonschema-specifications = ">=2023.3.6" referencing = ">=0.28.4" rpds-py = ">=0.25.0" @@ -3241,7 +2657,7 @@ description = "The JSON Schema meta-schemas and vocabularies, exposed as a Regis optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe"}, {file = "jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d"}, @@ -3251,124 +2667,47 @@ files = [ referencing = ">=0.31.0" [[package]] -name = "lark" -version = "1.2.2" -description = "a modern parsing library" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" -files = [ - {file = "lark-1.2.2-py3-none-any.whl", hash = "sha256:c2276486b02f0f1b90be155f2c8ba4a8e194d42775786db622faccd652d8e80c"}, - {file = "lark-1.2.2.tar.gz", hash = "sha256:ca807d0162cd16cef15a8feecb862d7319e7a09bdb13aef927968e45040fed80"}, -] - -[package.extras] -atomic-cache = ["atomicwrites"] -interegular = ["interegular (>=0.3.1,<0.4.0)"] -nearley = ["js2py"] -regex = ["regex"] - -[[package]] -name = "latex2sympy2-extended" -version = "1.10.2" -description = "Convert LaTeX math to SymPy expressions" +name = "kernels" +version = "0.12.1" +description = "Download compute kernels" optional = true -python-versions = ">=3.10" +python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"eval\" or extra == \"async-rl\"" +markers = "extra == \"kernels\"" files = [ - {file = "latex2sympy2_extended-1.10.2-py3-none-any.whl", hash = "sha256:f910442c5b02a466c1046f47d05cc5285181068b882399281f30102715337fb7"}, - {file = "latex2sympy2_extended-1.10.2.tar.gz", hash = "sha256:41a517ffcc5a140e910a7d1646ce6ff440817e5f9d48fc8279d88bd0925bc389"}, + {file = "kernels-0.12.1-py3-none-any.whl", hash = "sha256:4569fe00bc6a2b0f2cccff81841d7917af143c786ade152c3b2a78f61097c757"}, + {file = "kernels-0.12.1.tar.gz", hash = "sha256:41e31ef167add0062cdc302a943ce287194c13b5af12b82a5fa76e7353ca0042"}, ] [package.dependencies] -antlr4-python3-runtime = [ - {version = ">=4.9.3,<=4.13.2"}, - {version = "4.9.3", optional = true, markers = "extra == \"antlr4-9-3\""}, -] -sympy = "*" +huggingface_hub = ">=0.26.0,<2.0" +packaging = ">=20.0" +pyyaml = ">=6" [package.extras] -antlr4-11-0 = ["antlr4-python3-runtime (==4.11.0)"] -antlr4-13-2 = ["antlr4-python3-runtime (==4.13.2)"] -antlr4-9-3 = ["antlr4-python3-runtime (==4.9.3)"] -dev = ["pytest"] +abi-check = ["kernel-abi-check (>=0.6.2,<0.7.0)"] +benchmark = ["numpy (>=2.0.2)", "requests (>=2.32.5)", "torch"] +docs = ["hf-doc-builder"] +torch = ["torch"] [[package]] -name = "linkify-it-py" -version = "2.2.0" -description = "Links recognition library with FULL unicode support." +name = "lark" +version = "1.2.2" +description = "a modern parsing library" optional = true -python-versions = ">=3.10" +python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"client\"" +markers = "extra == \"vllm\"" files = [ - {file = "linkify_it_py-2.2.0-py3-none-any.whl", hash = "sha256:3adc40eb5af300b2605fcfdb968c24e1d780a90f1f2221af7c15e5111e94d443"}, - {file = "linkify_it_py-2.2.0.tar.gz", hash = "sha256:907acd2d17ac1fbb9ddb62c8957ccbd6158cac602231a15c3b0cd1e215f03cee"}, + {file = "lark-1.2.2-py3-none-any.whl", hash = "sha256:c2276486b02f0f1b90be155f2c8ba4a8e194d42775786db622faccd652d8e80c"}, + {file = "lark-1.2.2.tar.gz", hash = "sha256:ca807d0162cd16cef15a8feecb862d7319e7a09bdb13aef927968e45040fed80"}, ] [package.extras] -benchmark = ["pytest", "pytest-benchmark"] -dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"] -doc = ["myst-parser", "sphinx", "sphinx_book_theme"] -test = ["coverage", "pytest", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "litellm" -version = "1.95.0" -description = "Library to easily interface with LLM API providers" -optional = true -python-versions = "<3.15,>=3.10" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "litellm-1.95.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:0106b3564b60d00cb5b2810824ebf5071f59c9f9262318884d9c6f040aa2c435"}, - {file = "litellm-1.95.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:053cea1a584bf92d5d44b422f99fa03715bf7c346c8fe080c29bf0c6bd71eddc"}, - {file = "litellm-1.95.0-cp310-cp310-win_amd64.whl", hash = "sha256:667cc7cc58e05a9f9c4bf4588cd4ff5c785fd265060acdfb9147332b75b73ce9"}, - {file = "litellm-1.95.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:4bafa3494d503a3c6c1f2eeb785a2af364d85463c71a92cabaaa761c9227d62a"}, - {file = "litellm-1.95.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:4c2a06d2263a07a29228cd3af2b594cf86cd3a4182a7324c517cba88a9415969"}, - {file = "litellm-1.95.0-cp311-cp311-win_amd64.whl", hash = "sha256:aac37bb6d2be191bafc0ce590ed06d21dd7e5a37599ffc1af1071899f6c74b73"}, - {file = "litellm-1.95.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:cb667f84f08520f32b076e03c7a3fa51bf3f7e8b641dade34ab046bf00314d6b"}, - {file = "litellm-1.95.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:1bdf7153557cc0851fa9477b137fde476c56d5de92a5778ecfc6c3a75439a4e1"}, - {file = "litellm-1.95.0-cp312-cp312-win_amd64.whl", hash = "sha256:62cc5d834e8223dbd16c9ad0b46c73354b6d67cc7fa0eba2764ce65b3b8c474f"}, - {file = "litellm-1.95.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9d80a9adc506bfce48145621d6649e3fd428407811eb00211bcce33344054701"}, - {file = "litellm-1.95.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:cf014ff515825ad49937b4cdf95616270789311db7841d16702e0a5b1ac5b067"}, - {file = "litellm-1.95.0-cp313-cp313-win_amd64.whl", hash = "sha256:c73df441153e585832d4e90e3717d17ae888b269daa71d723336369e81ef884b"}, - {file = "litellm-1.95.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:c8e712f95764a9a730f3aec9dff8be916973423411ca12a79a35c8bea3f7d5a4"}, - {file = "litellm-1.95.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:071a63c0e1d949bf7ed5e5c73843cb042a6e00324d3f214b13f8c6b90da6822d"}, - {file = "litellm-1.95.0-cp314-cp314-win_amd64.whl", hash = "sha256:c3684dcf16aefe98bd6f11586d60a9a92bb1bf7e85468a6a4ac28a65532fab3e"}, - {file = "litellm-1.95.0.tar.gz", hash = "sha256:0ef126d52c7a559f8353e50d60fd0d5e7e6c8767ad54df25ddaf79b9edca1afc"}, -] - -[package.dependencies] -aiohttp = ">=3.10,<4.0" -click = ">=8.0.0,<9.0" -fastuuid = ">=0.14.0,<1.0" -httpx = ">=0.28.0,<1.0" -importlib-metadata = ">=8.0.0,<9.0" -jinja2 = ">=3.1.6,<4.0" -jsonschema = ">=4.0.0,<5.0" -openai = ">=2.20.0,<3.0.0" -pydantic = ">=2.10.0,<3.0.0" -python-dotenv = ">=1.0.0,<2.0" -tiktoken = ">=0.8.0,<1.0" -tokenizers = ">=0.21.0,<1.0" - -[package.extras] -bedrock-realtime = ["aws-sdk-bedrock-runtime (>=0.7.0,<0.8.0) ; python_full_version >= \"3.12.0\""] -caching = ["diskcache (>=5.6.3,<6.0)"] -cli = ["inquirerpy (>=0.3.4,<1.0)", "pyyaml (>=6.0.3,<7.0)", "requests (>=2.32.0,<3.0)", "rich (>=13.9.4,<14.0)"] -extra-proxy = ["a2a-sdk (>=1.1.0,<2.0)", "azure-identity (>=1.25.2,<2.0)", "azure-keyvault-secrets (>=4.10.0,<5.0)", "google-cloud-iam (>=2.19.1,<3.0)", "google-cloud-kms (>=2.24.2,<3.0)", "prisma (>=0.11.0,<1.0)", "redisvl (>=0.4.1,<1.0)", "resend (>=2.23.0,<3.0)"] -google = ["google-cloud-aiplatform (>=1.133.0,<2.0)"] -grpc = ["grpcio (==1.78.0)"] -mlflow = ["mlflow (>=3.11.1,<4.0)"] -proxy = ["apscheduler (>=3.11.2,<4.0)", "azure-identity (>=1.25.2,<2.0)", "azure-storage-blob (>=12.28.0,<13.0)", "backoff (>=2.2.1,<3.0)", "boto3 (>=1.43.1,<2.0)", "cryptography (>=48.0.1,<49.0)", "expression (>=5.6.0,<6.0)", "fastapi (>=0.136.3,<1.0)", "fastapi-sso (>=0.19.0,<1.0)", "granian (>=2.7.4,<3.0)", "gunicorn (>=23.0.0,<24.0)", "inquirerpy (>=0.3.4,<1.0)", "litellm-enterprise (==0.1.52)", "litellm-proxy-extras (==0.4.81)", "mcp (>=1.28.1,<2.0)", "orjson (>=3.11.6,<4.0)", "polars (>=1.38.1,<2.0)", "pydantic-settings (>=2.14.1,<3.0)", "pyjwt (>=2.13.0,<3.0)", "pynacl (>=1.6.2,<2.0)", "pyroscope-io (>=0.8.16,<1.0) ; sys_platform != \"win32\"", "python-multipart (>=0.0.27,<1.0)", "pyyaml (>=6.0.3,<7.0)", "restrictedpython (>=8.1,<9.0)", "rich (>=13.9.4,<14.0)", "rq (>=2.7.0,<3.0)", "soundfile (>=0.12.1,<1.0)", "starlette (>=1.0.1,<2.0)", "uvicorn (>=0.33.0,<1.0)", "uvloop (>=0.21.0,<1.0) ; sys_platform != \"win32\"", "websockets (>=15.0.1,<16.0)"] -proxy-runtime = ["anthropic[vertex] (>=0.84.0,<1.0)", "azure-ai-contentsafety (>=1.0.0,<2.0)", "azure-storage-file-datalake (>=12.20.0,<13.0)", "ddtrace (>=4.8.2,<5.0)", "detect-secrets (>=1.5.0,<2.0)", "google-cloud-aiplatform (>=1.133.0,<2.0)", "google-genai (>=1.37.0,<2.0)", "grpcio (==1.78.0)", "langfuse (>=2.59.7,<3.0)", "llm-sandbox (>=0.3.39,<1.0)", "mangum (>=0.17.0,<1.0)", "opentelemetry-api (==1.28.0)", "opentelemetry-exporter-otlp (==1.28.0)", "opentelemetry-instrumentation-fastapi (==0.49b0)", "opentelemetry-sdk (==1.28.0)", "prometheus-client (>=0.20.0,<1.0)", "pypdf (>=6.12.0,<7.0)", "sentry-sdk (>=2.21.0,<3.0)"] -saml = ["python3-saml (>=1.16.0,<2.0)"] -semantic-router = ["aurelio-sdk (>=0.0.19,<1.0) ; python_full_version < \"3.14.0\"", "semantic-router (>=0.1.15,<1.0) ; python_full_version < \"3.14.0\""] -stt-nvidia-riva = ["audioread (>=3.0.1)", "numpy (>=1.26.0)", "nvidia-riva-client (>=2.15.0)", "soundfile (>=0.12.1)"] -utils = ["numpydoc (>=1.8.0,<2.0)"] +atomic-cache = ["atomicwrites"] +interegular = ["interegular (>=0.3.1,<0.4.0)"] +nearley = ["js2py"] +regex = ["regex"] [[package]] name = "llguidance" @@ -3377,7 +2716,7 @@ description = "Bindings for the Low-level Guidance (llguidance) Rust library for optional = true python-versions = ">=3.9" groups = ["main"] -markers = "(extra == \"rl\" or extra == \"async-rl\") and (platform_machine == \"x86_64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\")" +markers = "extra == \"vllm\" and (platform_machine == \"x86_64\" or platform_machine == \"arm64\" or platform_machine == \"aarch64\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\")" files = [ {file = "llguidance-1.3.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f7685222660a762e481ac633d49cc559c64980fe2ee59c8f932a5bb5cbc0c2c2"}, {file = "llguidance-1.3.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:098030ff0687261a3f1bd54cf21fe951fc861d56d37a0671250dd36677eaf224"}, @@ -3396,7 +2735,7 @@ description = "lightweight wrapper around basic LLVM functionality" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "llvmlite-0.44.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:9fbadbfba8422123bab5535b293da1cf72f9f478a65645ecd73e781f962ca614"}, {file = "llvmlite-0.44.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cccf8eb28f24840f2689fb1a45f9c0f7e582dd24e088dcf96e424834af11f791"}, @@ -3428,7 +2767,7 @@ description = "Enforce the output format (JSON Schema, Regex etc) of a language optional = true python-versions = "<4.0,>=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "lm_format_enforcer-0.11.3-py3-none-any.whl", hash = "sha256:cf586350875def1ae7a8fba84fcbbfc8371424b6c9d05c1fcba70aa233fbf06f"}, {file = "lm_format_enforcer-0.11.3.tar.gz", hash = "sha256:e68081c108719cce284a9bcc889709b26ffb085a1945b5eba3a12cfa96d528da"}, @@ -3447,7 +2786,7 @@ description = "Python logging made (stupidly) simple" optional = true python-versions = "<4.0,>=3.5" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"}, {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"}, @@ -3458,200 +2797,7 @@ colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} [package.extras] -dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==v0.910) ; python_version < \"3.6\"", "mypy (==v0.971) ; python_version == \"3.6\"", "mypy (==v1.13.0) ; python_version >= \"3.8\"", "mypy (==v1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] - -[[package]] -name = "lxml" -version = "6.1.3" -description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "lxml-6.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:40bcbd9f94166ffe925811e730607385cec959f42fb1bb7dad83748680465221"}, - {file = "lxml-6.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:05f5bce9af14fd1506997594bd81cee6d9c6b58ea80a39c058327aa6371ed9e9"}, - {file = "lxml-6.1.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ff88a92cafde90888511242d1c54afcc1a8adbb6dc0a88fa7f87e29e92400d4a"}, - {file = "lxml-6.1.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c00e26288784460885fe76e4d4b293573e0f791f52e6d60e27b42edf005922eb"}, - {file = "lxml-6.1.3-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:773062aec2f2e56b2b22d37054123f0de8a22a4688a0c3376c3fe42685f975cf"}, - {file = "lxml-6.1.3-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f6449672f9c93316deb5e2839e18931f468670e44d5bd9b1301a5a9655d45c07"}, - {file = "lxml-6.1.3-cp310-cp310-manylinux_2_28_i686.whl", hash = "sha256:ec295280f4b37769256da025acf5890370355ac589c27e89caae0b5e9eedc702"}, - {file = "lxml-6.1.3-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:5929d9df5e7e3379183be0e21f7d559618a5b61cb63280df6164019242e337ed"}, - {file = "lxml-6.1.3-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6e1eb8a4cbffd5553680ad96be6680e364710656eced73d1dc90ec489df599a3"}, - {file = "lxml-6.1.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:16148acd77ed1d8836a56db883af2f5eed720f9723088110b16a0d08582130a6"}, - {file = "lxml-6.1.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:23c366231259cd75ad06495174701afb3fcb36a92917fa47de2d1f1bd9d95739"}, - {file = "lxml-6.1.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:da85db328e507da922d586c3c7416ec360ec22e9cd9e0700691afacde0c81f53"}, - {file = "lxml-6.1.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0f17d83c48ee9dfd96abae3ac3e2108c76d2fc86ce96355e37b8da9f7f4ecc08"}, - {file = "lxml-6.1.3-cp310-cp310-win32.whl", hash = "sha256:7dd624c1eaa629ad44b59a1a0145fdf2d67895592dce94c9358b938b3d075e65"}, - {file = "lxml-6.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:18a4db52b5a7b53a3540b0b0f4123319334621ee8083d496de314d0bf06ff59a"}, - {file = "lxml-6.1.3-cp310-cp310-win_arm64.whl", hash = "sha256:0feebef8d0521188d0157f758356072e840173aa61ca45b8b3f87959ac283dd5"}, - {file = "lxml-6.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c66f858b82497173f73366795fc6ee8171620e75a338506d6b2e7bc16f5fca11"}, - {file = "lxml-6.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:032a0a97eed428bd143c75a11118238546424ceb2fa311cca5f073aa44658dc4"}, - {file = "lxml-6.1.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4a579dfb9c835f8ab47f4b8ed33440cbc75b806b73297208e6ec2a33e903740b"}, - {file = "lxml-6.1.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:49fbc2682a9306135b7ec49e93f97f9c26689b9b7f96ed2742d8d6497e994d13"}, - {file = "lxml-6.1.3-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea2c01cdb16dc12156e455007c406dfaaece0c89aa4ba0e3b47586779f951d41"}, - {file = "lxml-6.1.3-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:527195c188d7d0af748cd48d220ab8cdc5cb99be3d49ac4d9be7324d8abf9bc0"}, - {file = "lxml-6.1.3-cp311-cp311-manylinux_2_28_i686.whl", hash = "sha256:20384c2bbcbf87180c8c61eb60869699c1ec0cd09b62cfd13804022d860b0867"}, - {file = "lxml-6.1.3-cp311-cp311-manylinux_2_31_armv7l.whl", hash = "sha256:424aa5657141d306ba9ad1baab4b2c0a0719040075ee6c66aee9bb2dea2b5054"}, - {file = "lxml-6.1.3-cp311-cp311-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:4736e6c87e603146d8949d8501da621ad20c31015060d3fcf95ace2859f3e3e6"}, - {file = "lxml-6.1.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6374e9e382e5a98c9c5e66d41b357b470da1c54bce30f17f9dc4bcc58436cc1c"}, - {file = "lxml-6.1.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:22eec57e26c418cde02c051ce9914a365e52a7f135a565c6f0480242aeebab48"}, - {file = "lxml-6.1.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:8753b8d51dbc86fd335ee31fcf7f3658e9f5c016d4edfb23f76ad295f4b8c9d0"}, - {file = "lxml-6.1.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:207dfc3d47cf0e575e643bbc140dacc8863b39abaa1e5307cd64c7f2365b8a12"}, - {file = "lxml-6.1.3-cp311-cp311-win32.whl", hash = "sha256:18293f8a8d8b6a8e71ef37706b659e3846a4261232158167b1ddf35f6994f633"}, - {file = "lxml-6.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:7ae4949f212a53b007dbc355884fda122545c5764a54256c9217e419a62a6559"}, - {file = "lxml-6.1.3-cp311-cp311-win_arm64.whl", hash = "sha256:2123e5aa075ac20d23c7af489255efd129cbfe190dbe88fd42598cc9df3199b6"}, - {file = "lxml-6.1.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0c0710ac085a157b593c38fbcacd950f15c4afa8e2057527185875ab302752bc"}, - {file = "lxml-6.1.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:623c8799c17128753c65699f1c3aa32402657393a9ad6db09ed8b98ddf76611d"}, - {file = "lxml-6.1.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f683dc6300317700025e41d89a43e0276692ded16113a3c43eab704d605c58e5"}, - {file = "lxml-6.1.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:379f8a75cf6eb7eef0af074b55f49ab73b868388a98de14646abcdfa4564bb11"}, - {file = "lxml-6.1.3-cp312-cp312-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b37772102d44bb6628186accca3a121b1fa3a6b3d97518a8c29a5229ca4c0d0a"}, - {file = "lxml-6.1.3-cp312-cp312-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ddcf547bea2aee967d6a77779376a45e77e610e8465147a1f3d7e20d539d6e32"}, - {file = "lxml-6.1.3-cp312-cp312-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:909f4e927bb051f7740d6367285fc60cdcfdaf0258c2dba4ff5ba7eadadc250c"}, - {file = "lxml-6.1.3-cp312-cp312-manylinux_2_28_i686.whl", hash = "sha256:a5c18810318303ce9afb3f95e2ddb54834f96fa699a8600433fd5a93dcf44c56"}, - {file = "lxml-6.1.3-cp312-cp312-manylinux_2_31_armv7l.whl", hash = "sha256:3e42265103fb385d8642a78672edf376c6f7e1d3598a7a4f9cb1278f2f6b5f6f"}, - {file = "lxml-6.1.3-cp312-cp312-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:21402998e4b78e7cce237d2788841aaa21ac9a4d1574d04dc2d12ee41ae807b5"}, - {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:38fc4e4e4e084e0bd491949482527d406788045c546d4f8789e93fc527b91385"}, - {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5609efdb0d3c95499c00046bc53648b3482ec2175b5503d6e611b3f0555dc71d"}, - {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:97ce49699d87ebf8aad631b55d65b33219a4f1bfefbbf5bff19dc9af160aeaf9"}, - {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:48542c9acba9ff9450bd18d871d2c2c8787fdb283572b623d206f1b927cd7d9e"}, - {file = "lxml-6.1.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c55e71a9b1db1f107efb60da49c093689b74c5c31a708e5379e2fd9439d4fbb5"}, - {file = "lxml-6.1.3-cp312-cp312-win32.whl", hash = "sha256:b3ff39654f0ce6ebd4db154211136dbe7e8157bcc3bed2344c87f32c7c6ecb6c"}, - {file = "lxml-6.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:3e9a00d1c2c30936f7add097c41afc5da6556c580909104aafd382cac92a855c"}, - {file = "lxml-6.1.3-cp312-cp312-win_arm64.whl", hash = "sha256:1aeca87830c4fe649dcf93fe2b059525b71c72587f21be4ae4af7103082a79fa"}, - {file = "lxml-6.1.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3a48093cdb058a93af842ede9703520e810b05dcd0fc6d7190a06376c3bfb6bd"}, - {file = "lxml-6.1.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:887c021d9a977cff89cb273047c1352997b772a8908a25c21836861f69b92be1"}, - {file = "lxml-6.1.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:611a51e61c92f62345a50b0035df6fc0d678f9299f33728826d831598862f59d"}, - {file = "lxml-6.1.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b477912f42c5c33405a10c759d22f80cf5af043ae02d95b9d8e5e5bc555739ed"}, - {file = "lxml-6.1.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5cffe18571ccc51d742cd08cbb3f8b756de9311d18c7ea98f5d92f37b8fb60c2"}, - {file = "lxml-6.1.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:75cc6569e86be5785b6188ef1642670c6adbc984e81ec35e224842ecd9eefcc8"}, - {file = "lxml-6.1.3-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d85dfab42dd672f87a7f76e9de7172962aee69fa12044f0d6e1a23cbd53fb80e"}, - {file = "lxml-6.1.3-cp313-cp313-manylinux_2_28_i686.whl", hash = "sha256:42632b4024ab24a6b488f559ac851312509888b6b80ae2aa11cf29a646a0d245"}, - {file = "lxml-6.1.3-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:febd35ef45f603c2d74b74655efdbf45e14f55fc0aef4ac82b663ca829b283e0"}, - {file = "lxml-6.1.3-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a43b3bdf11e477dc7770609d3477316f974354dfc8425d596f64f471cc8daf6e"}, - {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d582042c69857c364e8153de6e18e0da9b7b515a6a8113caf69a6ec8e0520f2"}, - {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8e49a646acfab83c68974f4aa1d0a2acca9e88d7d627ae0fc13201b14b76d310"}, - {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0dee106e9aa97fb00541b1ed7827070564d0549c3d3fba8920e6b20fd980f748"}, - {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:dd5e90f34cffcfed97f36cf066325773d2b6021c60c29942e53a18b028501b1d"}, - {file = "lxml-6.1.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d9b3e7d71bf6acff341233417abbdface29c647e3113892d9aaedc02eb4aa2bc"}, - {file = "lxml-6.1.3-cp313-cp313-win32.whl", hash = "sha256:160fcf381f76c3aeac28a756bec44f48942a8f7245a87aa28e3a523b4d90cd87"}, - {file = "lxml-6.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:e477aca0bc0d19f3b4ae9e4f2a1cfd687c31bf772d78734910658186b40b2477"}, - {file = "lxml-6.1.3-cp313-cp313-win_arm64.whl", hash = "sha256:b1cc980905221a5d8b3c476330730b3adb40ff80add71ffbdb6215ba055656f1"}, - {file = "lxml-6.1.3-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:2bec13085dc8ef48a3fe62f7dfcacfeda2c785cdf19cc8eeda2bb9ed081da165"}, - {file = "lxml-6.1.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:4f4db7c7e954d289d71878938348b3d91b904a3e8210a11939359fb758a58e7d"}, - {file = "lxml-6.1.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2cae5d5c90a62d9139c512a0cb1aad1d182b022b5740daea2617eb5bf7fc658e"}, - {file = "lxml-6.1.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c6c0c13128a32eb04a51357e56a094e13aa8e6d3d1884de2e9ae923f6915e1a8"}, - {file = "lxml-6.1.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2221e88679d1351e9a40aaee54bc65679b9795bbd0160bc3d5e36b163344eb75"}, - {file = "lxml-6.1.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cfb398886a7eb4c719161c3efcff2a1248febc53a4d8e5072d2d8a87fed84ac9"}, - {file = "lxml-6.1.3-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a7eb78ba28b187e1e9203a55c60fcf70df2d22cb205fe6d51b9383d6097419f0"}, - {file = "lxml-6.1.3-cp314-cp314-manylinux_2_28_i686.whl", hash = "sha256:ea6b1e9105b4b24a34c722432d9fb578f9ed83af21fa1abda639011e0f22bbb6"}, - {file = "lxml-6.1.3-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:e8b17e23df3e827a69d25af70990ca2420e92668aaffaeeb3cd2351d7916a023"}, - {file = "lxml-6.1.3-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b7c37339d7e75cab9a123a04248e243cefefb302ad6db566ea0c77cbcde421e"}, - {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:83e3a51e7933db700a0da0db31849db3a24022d9970da9bb73001e1d0326fd92"}, - {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:9bde9ae026a55b9a192078dfa6e27dd0ca4a050171ab6272e92f97b757dfdf48"}, - {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:1a635e837b50a1819bebfedaac5916498ea024120969da8790500148fb0a894d"}, - {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d0c5c362bc94f1929dc7e96e715bbe7bd17037f802e6d8f0d1545df9133c0559"}, - {file = "lxml-6.1.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c59e4265608da6a041f54646ecc0c9ecdbb19aaf14c4c684bb6c2114998cc415"}, - {file = "lxml-6.1.3-cp314-cp314-win32.whl", hash = "sha256:2e62c569ec7531b679b184cbfe335c501c1d13c4b363560013019962eb630e6d"}, - {file = "lxml-6.1.3-cp314-cp314-win_amd64.whl", hash = "sha256:66299564c046bc7e0cc5de5106601eae907e9fa5904cd68a323380a8502f7861"}, - {file = "lxml-6.1.3-cp314-cp314-win_arm64.whl", hash = "sha256:ebd054ad1737a68fb7c5c073d405cef2b88bb824e294de3b4a4e995b47f0e376"}, - {file = "lxml-6.1.3-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:5a143e6207579de8baeded4eaac9134413200359f1969d636f0bfb98ee8c3c8f"}, - {file = "lxml-6.1.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:a1cec0f99b9b914d39176347a93b7610dc09324491aee1cbc57cd291a41a1d55"}, - {file = "lxml-6.1.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f6b9d2aad499c769ee8287609ab0e6de99d8bcea99c6e6c2e64945259fd52fb2"}, - {file = "lxml-6.1.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a23fefdb345b2d4d0ff2860571b5ff9a89a28b6a120f720e8fb0324d346626"}, - {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:545ccc14fb05485f48b4439ec35beb16d5b5280eb6c81c658bd4707a2a119414"}, - {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:93476b6514b373fc6ca67d26c442784f7807c86f00635bfe79f935c3eab2af17"}, - {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8db38ff3fb7aee7d6a82ae4da2eef1178656fe1216841fbd24870062a9d60473"}, - {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:25f4118c438f96bb466e83108506d03d5c31b1bd2387e83e5b070bda6ded9c37"}, - {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:1beb0f9909b26cee938df9ba56b15252a84429b1fc30ce6fca161390b9789a70"}, - {file = "lxml-6.1.3-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:3a27ac6c780c8b8a1cd231b58407634cafc1c4cc28cd6c7141362df0f36351e7"}, - {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a1932d7ce78a561367512c594fe66eac2b2ec9b9264cfd9b5f950622f4a116e2"}, - {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:7d0f5976aa2701996f759b30172925829867547bb073af0ae67d1307a0f0262c"}, - {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:c5e7ce578aa8a80910a72a8ca0bbea3baae10100827249001999726a788456d8"}, - {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d97c5227621af74b111882a290b10f371780a38eef9d9e730408fba2259b52fb"}, - {file = "lxml-6.1.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:da707f14ea3c35ee463d50acd596d6488e4b2b4ae7cf77a5bf93f55c023d63e8"}, - {file = "lxml-6.1.3-cp314-cp314t-win32.whl", hash = "sha256:9efe56a68179f3adc4de41861c9358931db03837c48dd5e1c78077b84dd07f3a"}, - {file = "lxml-6.1.3-cp314-cp314t-win_amd64.whl", hash = "sha256:c9389b3784b56c58d933b5e0aecdf28f901b073ff385358d8a7d40907f6e14b2"}, - {file = "lxml-6.1.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32a409be3190b088f960ac92bfedfbef2f86c49ff940765e1548177592d20026"}, - {file = "lxml-6.1.3-cp315-cp315-macosx_10_15_universal2.whl", hash = "sha256:6ea2f13dce778ca072ccee598bca46a092ce192e8fd907b6c1f0e52c800529a0"}, - {file = "lxml-6.1.3-cp315-cp315-macosx_10_15_x86_64.whl", hash = "sha256:c581b1d68b3845fb86c6b2983e755b29bf001461c59fa411d2c26a911b6559a9"}, - {file = "lxml-6.1.3-cp315-cp315-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e01125896585139453cab8cb235893644d8815d7509520da95ae3ee8d1c1f79"}, - {file = "lxml-6.1.3-cp315-cp315-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:290f66b97ede0e552e1cb44a0fd8a74f9753ee635b50830a0b122fb72788d015"}, - {file = "lxml-6.1.3-cp315-cp315-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73fc05988ed20809450474ba760a87c8ad4e455fc09783c02195e56ec634b41a"}, - {file = "lxml-6.1.3-cp315-cp315-manylinux_2_31_armv7l.whl", hash = "sha256:dc3a44689eea43eab836e5c98a8ab015dc2419987d1ea6eafc7c590cdff86bed"}, - {file = "lxml-6.1.3-cp315-cp315-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:209c3ccbfe35a04ac6d24f0611f9d1cbf8025d49991b14acd935236234d6c156"}, - {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:2f5b2a2b9811b853b39bfa41367c6d78747b8e3e80e07fc5a24aae295c1a4d7d"}, - {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_armv7l.whl", hash = "sha256:6a406d0b3cb207b0fa460ed4dc93e866f44f105da0169361cb18ff998a44c7f0"}, - {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_ppc64le.whl", hash = "sha256:53258656846f5c48996b882fb4b135885e088a3ad3d96b4bc0530f95124d1f69"}, - {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_riscv64.whl", hash = "sha256:aa633613ff907ea91b9b0489a1f0da1b8725d8c6ccec6b77e8a1c9c235044bb0"}, - {file = "lxml-6.1.3-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:90f709b9accab6b2e4d14f5c8718203877a0486bcb3afd74d8b539ecd1e961d4"}, - {file = "lxml-6.1.3-cp315-cp315-win32.whl", hash = "sha256:b4fc6b03b9d9d90557274f571ab30e7fbbfc527955536935d96f98b6817a86e4"}, - {file = "lxml-6.1.3-cp315-cp315-win_amd64.whl", hash = "sha256:33cadd956b667997e4de1635fce9541f2e8ede2038fcde8cf55aa14d571d1bad"}, - {file = "lxml-6.1.3-cp315-cp315-win_arm64.whl", hash = "sha256:8a330c0ee5fa318c7b5cbbaad882baeca3f570357e7eb25ab34bf31008150758"}, - {file = "lxml-6.1.3-cp315-cp315t-macosx_10_15_universal2.whl", hash = "sha256:0bf5a3e397df2ec4258eb5eea4c1ac6cf013ca1abd04a176903bff20a70021fe"}, - {file = "lxml-6.1.3-cp315-cp315t-macosx_10_15_x86_64.whl", hash = "sha256:13d22c0d57355366b393936acf6b98a5e0edeadddd3fccbc6a846c50a76b8741"}, - {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cad7617727a96d189bd6f979d0fadf765198c7934e85f4edaba9bf3ad919a300"}, - {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cae82b5ca24b0c2beedb269f6e2a96f466acd926879ab00ae19f1a65cbf9ffb0"}, - {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:69cafd61aea04ebb3502c93c2aaa568b12931ca0802231e0b5de76bf8b6e74bd"}, - {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_31_armv7l.whl", hash = "sha256:dc205732d593118cf701d986f40e9de7801bb2e371cb189ddbda9b7348f4d97e"}, - {file = "lxml-6.1.3-cp315-cp315t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:88e719b9437f148f7e1465df845c758dd1598618cbea3a2fd1e61a715542f2b2"}, - {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:40983eabefd13da003e68170928c7acc011f0d095eefce5871a3c71c9385fb9a"}, - {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_armv7l.whl", hash = "sha256:fad67b12ffe0f71e02b4932b04883cbc76a9072bbd30731409d3523cf058b011"}, - {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd11e7550d89e551a87dcec30f04b1fca32e86b68708aa01a4daa455d8605e5"}, - {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_riscv64.whl", hash = "sha256:ca0ec532ad2f5ba1e5ec120ac157769c57f01855b3d8bf37213f5d88abd9ba0a"}, - {file = "lxml-6.1.3-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:e99e09ab7741f1281e2677f4c0058c7f5267d182530b09c87e4f6aa26adf3887"}, - {file = "lxml-6.1.3-cp315-cp315t-win32.whl", hash = "sha256:ace1d2c83b2bd24db5940600541140e87a325e119cb32d5fa9ad720d7e76648e"}, - {file = "lxml-6.1.3-cp315-cp315t-win_amd64.whl", hash = "sha256:b49638355ea3bebba70da783ccbc630fd72afa16bc46c54474bfa1f9a915bbc6"}, - {file = "lxml-6.1.3-cp315-cp315t-win_arm64.whl", hash = "sha256:5a721a98c649855963811b59b55755b30566e7f7fc40bdc9803d66dee9f811cf"}, - {file = "lxml-6.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:13a620a3fcc20023f9e6ed5c383e00e826f1c2d5db554df2f67240760f9118e8"}, - {file = "lxml-6.1.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fbfb70ba01355251faf6b293171df49f73a88a1b6494db109ffea85442574458"}, - {file = "lxml-6.1.3-cp38-cp38-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:302f72413251c03f671e063c9414bed5dc8c927069e5abb69245521e51a4e81b"}, - {file = "lxml-6.1.3-cp38-cp38-manylinux_2_28_i686.whl", hash = "sha256:ce1f220114959941170e22b8ad44279f6dee2dcef7591814d01ae805dc058889"}, - {file = "lxml-6.1.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:170773d8a3cdc76259065523ddd978c44f9806e28605f08812e8f86783e44ac6"}, - {file = "lxml-6.1.3-cp38-cp38-win32.whl", hash = "sha256:92d96586376fb79a33474797186bf993250152ee5c32650b67db78d54b92e6f3"}, - {file = "lxml-6.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:d44442effeb8781f392340c5dc8c6716fba41dbeacb82fd4c0f09026fb5ff682"}, - {file = "lxml-6.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:869dfcd4d381cb0ea87085cc4f011b9171b494ef21e76ad8665f6d5e2d1dc8a1"}, - {file = "lxml-6.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6ba4fe5bfbef6811a8e49b3719cde373ad399006c0c1ac184b7297116ecbba5d"}, - {file = "lxml-6.1.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:61116cec57ed69aebc70f37a545eec095339bb829efbdabcfb97c51e9536e158"}, - {file = "lxml-6.1.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4e11e885e0704be185867fcf71b904d8f65d7d6877bc121f69870b0d0479ba7b"}, - {file = "lxml-6.1.3-cp39-cp39-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41e2d428110b408e963b6fb18f9bbf1f5c027b56bd4b498d54556476c0aeb1c3"}, - {file = "lxml-6.1.3-cp39-cp39-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa9fd1ee2a5dacfc41039ed49ffeeacfa75bafbd255b69f3b578e11897a0e623"}, - {file = "lxml-6.1.3-cp39-cp39-manylinux_2_28_i686.whl", hash = "sha256:7f75b9b9fec2a9c6b18095c81865580e795b1441c429e42d22fcc82a77f40039"}, - {file = "lxml-6.1.3-cp39-cp39-manylinux_2_31_armv7l.whl", hash = "sha256:cc669256d28736f7f3a149df5c380c50ace2692ba3e62203d10656fade4a2145"}, - {file = "lxml-6.1.3-cp39-cp39-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d077f21f4b16f0471353883748f126f62038760397c107bb9fad2ca94dc0dfb7"}, - {file = "lxml-6.1.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d9a0d12846d6ce434fb3857918eef4315ec9b4769deb020c75828798614bfcfd"}, - {file = "lxml-6.1.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:2b9b1325ca1c2a9a2dbb6eb913ae563313f2082ae60b03210f7e83ee80712274"}, - {file = "lxml-6.1.3-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:a2e3f70673a1d5b82f38255f777d26cd855bf2092b1436c4867464a7892f9238"}, - {file = "lxml-6.1.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c34ca1dc41bd86d9ff830d5bdf4e4a752bba6c54f7d2707027ce0eabd36084c9"}, - {file = "lxml-6.1.3-cp39-cp39-win32.whl", hash = "sha256:b50343241eb69fd85f7791cf8bcc7b1c4729826b7d59ba2f6b27db29638fa745"}, - {file = "lxml-6.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:0794e04ba343852c6d78e996c58ef4b8e579b4ecc72f8df0d4058bf843b4c96e"}, - {file = "lxml-6.1.3-cp39-cp39-win_arm64.whl", hash = "sha256:0ab2467e405e748d93495fb5568e74044802b8d3ff2b2a1607c3f78c6e982de5"}, - {file = "lxml-6.1.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4b061064b4a2fe8598a466d723d43dbcd5a610a5d5cfe02fb6226f5c17349f75"}, - {file = "lxml-6.1.3-pp310-pypy310_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8499d464de86fab0f102313cce32a9bed9ab1f06ec813cf025cb790964fbb765"}, - {file = "lxml-6.1.3-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9e67324961ac9bbe616cce5100514d2e34d88665aeb07071e8b16eac55d06d94"}, - {file = "lxml-6.1.3-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d12669a2c419b0e8dc423d23dea24bb82f6f9cb829f32e04674b0ba40322a7c"}, - {file = "lxml-6.1.3-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:97acecb11cbc411473f15b8d780df06d7a9f3a2aad9aca78364f56640c8fb70e"}, - {file = "lxml-6.1.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f8b9c8ceebae6387d0dc77f7f4dbbfbfc962dba2efbfe6877486075a480726b4"}, - {file = "lxml-6.1.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d2765c18ce303149ee804b1f3dad11232726dd0a702d73a15cf19179ac8cc962"}, - {file = "lxml-6.1.3-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7d5a748d12dd9b535e0a130f60dae9ddf0adafbabe61e7864f55c7436c84547a"}, - {file = "lxml-6.1.3-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:41096ec0740a58dad03d3ae0c7486d306d20becefb13ceb1649835ab3eb64167"}, - {file = "lxml-6.1.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:415e3a115c0d510e329020012834d1c0aa1c581ee53a218603e38abbc1dea70a"}, - {file = "lxml-6.1.3-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20428910dae17a1a93152a3ff2c0441d2f4932992c0797d65651dd0561f1792f"}, - {file = "lxml-6.1.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:bc8dd3d9c93e70c3df974a201ac2958b6d77b465d813c51d1f15fa8e645763ae"}, - {file = "lxml-6.1.3-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:3847e71a78cbbc1aff955dbbbaf2fff12153f611d3162c5beaa3395636cbc2f9"}, - {file = "lxml-6.1.3-pp39-pypy39_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe91993149523aa59941b9e3c90e2eb45f57ad014697aef6c8b13339a59c019e"}, - {file = "lxml-6.1.3-pp39-pypy39_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:71532ebf30be0048a45559b4fab15333fbaaf9042f658e878d918ecd0cf09805"}, - {file = "lxml-6.1.3-pp39-pypy39_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c1b50797ac246bb2942a04b6c0f69af0667aba7cf7535f39bbb1b3208fd5d128"}, - {file = "lxml-6.1.3-pp39-pypy39_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2bb7d703bed7ac893bf7f40d97b5d9279d35d2ce460624ca28929eab0d5a3d"}, - {file = "lxml-6.1.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:be5346653c0b0e34be96869ff9dbeba23860156f89a2896a64c64fb419260cb6"}, - {file = "lxml-6.1.3.tar.gz", hash = "sha256:45222d94ddd511536f3b2f7d9deae3b2339b4ce0f075f1ca25703b07cad9dd21"}, -] - -[package.extras] -cssselect = ["cssselect (>=0.7)"] -html-clean = ["lxml_html_clean"] -html5 = ["html5lib"] -htmlsoup = ["BeautifulSoup4"] +dev = ["Sphinx (==8.1.3) ; python_version >= \"3.11\"", "build (==1.2.2) ; python_version >= \"3.11\"", "colorama (==0.4.5) ; python_version < \"3.8\"", "colorama (==0.4.6) ; python_version >= \"3.8\"", "exceptiongroup (==1.1.3) ; python_version >= \"3.7\" and python_version < \"3.11\"", "freezegun (==1.1.0) ; python_version < \"3.8\"", "freezegun (==1.5.0) ; python_version >= \"3.8\"", "mypy (==0.910) ; python_version < \"3.6\"", "mypy (==0.971) ; python_version == \"3.6\"", "mypy (==1.13.0) ; python_version >= \"3.8\"", "mypy (==1.4.1) ; python_version == \"3.7\"", "myst-parser (==4.0.0) ; python_version >= \"3.11\"", "pre-commit (==4.0.1) ; python_version >= \"3.9\"", "pytest (==6.1.2) ; python_version < \"3.8\"", "pytest (==8.3.2) ; python_version >= \"3.8\"", "pytest-cov (==2.12.1) ; python_version < \"3.8\"", "pytest-cov (==5.0.0) ; python_version == \"3.8\"", "pytest-cov (==6.0.0) ; python_version >= \"3.9\"", "pytest-mypy-plugins (==1.9.3) ; python_version >= \"3.6\" and python_version < \"3.8\"", "pytest-mypy-plugins (==3.1.0) ; python_version >= \"3.8\"", "sphinx-rtd-theme (==3.0.2) ; python_version >= \"3.11\"", "tox (==3.27.1) ; python_version < \"3.8\"", "tox (==4.23.2) ; python_version >= \"3.8\"", "twine (==6.0.1) ; python_version >= \"3.11\""] [[package]] name = "markdown" @@ -3660,7 +2806,7 @@ description = "Python implementation of John Gruber's Markdown." optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"eval\" or extra == \"docs\"" +markers = "extra == \"docs\"" files = [ {file = "markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36"}, {file = "markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950"}, @@ -3674,16 +2820,16 @@ testing = ["coverage", "pyyaml"] name = "markdown-it-py" version = "2.2.0" description = "Python port of markdown-it. Markdown parsing, done right!" -optional = false +optional = true python-versions = ">=3.7" groups = ["main"] +markers = "extra == \"vllm\" or extra == \"tinker\" or extra == \"docs\"" files = [ {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, ] [package.dependencies] -linkify-it-py = {version = ">=1,<3", optional = true, markers = "extra == \"linkify\""} mdurl = ">=0.1,<1.0" [package.extras] @@ -3795,52 +2941,6 @@ files = [ {file = "markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698"}, ] -[[package]] -name = "math-verify" -version = "0.8.0" -description = "HuggingFace library for verifying mathematical answers" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "math_verify-0.8.0-py3-none-any.whl", hash = "sha256:31ca651296d817a9bb3fd58ca1fd0d192dcea709b1e5ecf2d0a4514c16f89087"}, - {file = "math_verify-0.8.0.tar.gz", hash = "sha256:3295e0adb94bfe553ff6e3189c44f1916a85aa24ab5d1900f2086a706e28f7c4"}, -] - -[package.dependencies] -latex2sympy2_extended = "1.10.2" - -[package.extras] -antlr4-11-0 = ["latex2sympy2_extended[antlr4-11-0]"] -antlr4-13-2 = ["latex2sympy2_extended[antlr4-13-2]"] -antlr4-9-3 = ["latex2sympy2_extended[antlr4-9-3]"] -dev = ["math-verify[format]", "math-verify[test]"] -format = ["ruff"] -inference = ["lighteval[math]"] -test = ["pytest"] - -[[package]] -name = "mcore-bridge" -version = "1.6.4" -description = "MCore-Bridge: Making Megatron training as simple as Transformers" -optional = true -python-versions = ">=3.8.0" -groups = ["main"] -markers = "extra == \"megatron\"" -files = [ - {file = "mcore_bridge-1.6.4-py3-none-any.whl", hash = "sha256:df8ab70f3a8122184833221af8f7756ff937bf980ee6fef6cbeaa3fcc1d00a73"}, - {file = "mcore_bridge-1.6.4.tar.gz", hash = "sha256:6df211f0e810d0d3d4be61de72bf68aa730c7da00a7ed5ecc18ffd1ec3563cf2"}, -] - -[package.dependencies] -megatron-core = ">=0.16,<0.20" -modelscope = "*" -peft = ">=0.11,<0.21" -safetensors = "*" -tqdm = "*" -transformers = ">=4.33,<5.17.0" - [[package]] name = "mcp" version = "1.26.0" @@ -3848,7 +2948,7 @@ description = "Model Context Protocol SDK" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "mcp-1.26.0-py3-none-any.whl", hash = "sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca"}, {file = "mcp-1.26.0.tar.gz", hash = "sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66"}, @@ -3882,7 +2982,7 @@ description = "Collection of plugins for markdown-it-py" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"client\" or extra == \"docs\"" +markers = "extra == \"docs\"" files = [ {file = "mdit-py-plugins-0.3.5.tar.gz", hash = "sha256:eee0adc7195e5827e17e02d2a258a2ba159944a0748f59c5099a4a27f78fcf6a"}, {file = "mdit_py_plugins-0.3.5-py3-none-any.whl", hash = "sha256:ca9a0714ea59a24b2b044a1831f48d817dd0c817e84339f20e7889f392d77c4e"}, @@ -3900,9 +3000,10 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" -optional = false +optional = true python-versions = ">=3.7" groups = ["main"] +markers = "extra == \"vllm\" or extra == \"tinker\" or extra == \"docs\"" files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -3945,7 +3046,7 @@ description = "Mistral-common is a library of common utilities for Mistral AI." optional = true python-versions = "<3.14,>=3.10.0" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "mistral_common-1.9.1-py3-none-any.whl", hash = "sha256:9e2b2520b6f67bac2e2bb06fcf985b7a1277b01938da2b7cda8cf0fdbfa92e91"}, {file = "mistral_common-1.9.1.tar.gz", hash = "sha256:550583d70a395c3586cfb748ffab53bd1d7c3409507f0efc0118bff30ffb26e9"}, @@ -4025,8 +3126,6 @@ files = [ [package.dependencies] numpy = [ {version = ">=1.23.3", markers = "python_version >= \"3.11\""}, - {version = ">=1.21.2", markers = "python_version == \"3.10\""}, - {version = ">=2.1.0", markers = "python_version >= \"3.13\""}, {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, ] @@ -4040,7 +3139,7 @@ description = "A framework for machine learning on Apple silicon." optional = true python-versions = ">=3.10" groups = ["main"] -markers = "(extra == \"rl\" or extra == \"async-rl\") and platform_machine == \"arm64\" and platform_system == \"Darwin\"" +markers = "extra == \"vllm\" and platform_machine == \"arm64\" and platform_system == \"Darwin\"" files = [ {file = "mlx-0.31.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:38680838e0dd9a621ed4adc5a9ed8b94aeb6a4798142fbe215b821b8c6b8fc36"}, {file = "mlx-0.31.0-cp310-cp310-macosx_15_0_arm64.whl", hash = "sha256:7aded590bcf6839307c3acc899e196936991f97b499ddbdd0cd3b228bf10792f"}, @@ -4086,7 +3185,7 @@ description = "LLMs with MLX and the Hugging Face Hub" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "(extra == \"rl\" or extra == \"async-rl\") and platform_machine == \"arm64\" and platform_system == \"Darwin\"" +markers = "extra == \"vllm\" and platform_machine == \"arm64\" and platform_system == \"Darwin\"" files = [ {file = "mlx_lm-0.29.1-py3-none-any.whl", hash = "sha256:440941b3054c2a2216e97615de584cc90fa1ea874782e20699b9895721fad8dc"}, {file = "mlx_lm-0.29.1.tar.gz", hash = "sha256:b99180d8f33d33a077b814e550bfb2d8a59ae003d668fd1f4b3fff62a381d34b"}, @@ -4115,7 +3214,7 @@ description = "A framework for machine learning on Apple silicon." optional = true python-versions = ">=3.10" groups = ["main"] -markers = "(extra == \"rl\" or extra == \"async-rl\") and platform_machine == \"arm64\" and platform_system == \"Darwin\"" +markers = "extra == \"vllm\" and platform_machine == \"arm64\" and platform_system == \"Darwin\"" files = [ {file = "mlx_metal-0.31.0-py3-none-macosx_14_0_arm64.whl", hash = "sha256:1c572a6e3634a63060c103b0c38ac309e2d217be15519e3d8f0d6b452bb015f5"}, {file = "mlx_metal-0.31.0-py3-none-macosx_15_0_arm64.whl", hash = "sha256:554dc7cb29e0ea5fb6941df42f11a1de385b095848e6183c7a99d7c1f1a11f5d"}, @@ -4129,7 +3228,7 @@ description = "Python toolkit for standardized model hosting container implement optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "model_hosting_container_standards-0.1.13-py3-none-any.whl", hash = "sha256:be307d4a988cc660df4e6bd8bdedb7917844bac940e332f9fd001cb385d7994c"}, {file = "model_hosting_container_standards-0.1.13.tar.gz", hash = "sha256:27a1333410dde2719286a300a2803e24fdde407baa91894eb845c0f268aa194d"}, @@ -4157,47 +3256,19 @@ files = [ ] [package.dependencies] -addict = [ - {version = "*", optional = true, markers = "extra == \"framework\""}, - {version = "*", optional = true, markers = "extra == \"datasets\""}, -] -attrs = [ - {version = "*", optional = true, markers = "extra == \"framework\""}, - {version = "*", optional = true, markers = "extra == \"datasets\""}, -] -datasets = [ - {version = ">=3.0.0,<=3.6.0", optional = true, markers = "extra == \"framework\""}, - {version = ">=3.0.0,<=3.6.0", optional = true, markers = "extra == \"datasets\""}, -] -einops = [ - {version = "*", optional = true, markers = "extra == \"framework\""}, - {version = "*", optional = true, markers = "extra == \"datasets\""}, -] +addict = {version = "*", optional = true, markers = "extra == \"framework\""} +attrs = {version = "*", optional = true, markers = "extra == \"framework\""} +datasets = {version = ">=3.0.0,<=3.6.0", optional = true, markers = "extra == \"framework\""} +einops = {version = "*", optional = true, markers = "extra == \"framework\""} filelock = "*" -oss2 = {version = "*", optional = true, markers = "extra == \"datasets\""} -Pillow = [ - {version = "*", optional = true, markers = "extra == \"framework\""}, - {version = "*", optional = true, markers = "extra == \"datasets\""}, -] -python-dateutil = [ - {version = ">=2.1", optional = true, markers = "extra == \"framework\""}, - {version = ">=2.1", optional = true, markers = "extra == \"datasets\""}, -] +Pillow = {version = "*", optional = true, markers = "extra == \"framework\""} +python-dateutil = {version = ">=2.1", optional = true, markers = "extra == \"framework\""} PyYAML = {version = ">=5.4", optional = true, markers = "extra == \"framework\""} requests = ">=2.25" -scipy = [ - {version = "*", optional = true, markers = "extra == \"framework\""}, - {version = "*", optional = true, markers = "extra == \"datasets\""}, -] +scipy = {version = "*", optional = true, markers = "extra == \"framework\""} setuptools = "*" -simplejson = [ - {version = ">=3.3.0", optional = true, markers = "extra == \"framework\""}, - {version = ">=3.3.0", optional = true, markers = "extra == \"datasets\""}, -] -sortedcontainers = [ - {version = ">=1.5.9", optional = true, markers = "extra == \"framework\""}, - {version = ">=1.5.9", optional = true, markers = "extra == \"datasets\""}, -] +simplejson = {version = ">=3.3.0", optional = true, markers = "extra == \"framework\""} +sortedcontainers = {version = ">=1.5.9", optional = true, markers = "extra == \"framework\""} tqdm = ">=4.64.0" transformers = {version = "*", optional = true, markers = "extra == \"framework\""} urllib3 = ">=1.26" @@ -4221,19 +3292,6 @@ science = ["Pillow", "PyYAML (>=5.4)", "addict", "attrs", "biopython", "datasets server = ["fastapi", "sse-starlette", "uvicorn"] tests = ["expecttest", "flake8", "isort (>=4.3.21)", "pre-commit", "yapf (==0.30.0)"] -[[package]] -name = "more-itertools" -version = "11.1.0" -description = "More routines for operating on iterables, beyond itertools" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "more_itertools-11.1.0-py3-none-any.whl", hash = "sha256:4b65538ae22f6fed0ce4874efd317463a7489796a0939fa66824dd542125a192"}, - {file = "more_itertools-11.1.0.tar.gz", hash = "sha256:48e8f4d9e7e5878571ecf6f2b4e57634f93cd474cc8cfbd2376f2d11b396e30d"}, -] - [[package]] name = "mpmath" version = "1.3.0" @@ -4259,7 +3317,7 @@ description = "MessagePack serializer" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "msgpack-1.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0051fffef5a37ca2cd16978ae4f0aef92f164df86823871b5162812bebecd8e2"}, {file = "msgpack-1.1.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a605409040f2da88676e9c9e5853b3449ba8011973616189ea5ee55ddbc5bc87"}, @@ -4332,7 +3390,7 @@ description = "A fast serialization and validation library, with builtin support optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "msgspec-0.20.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:23a6ec2a3b5038c233b04740a545856a068bc5cb8db184ff493a58e08c994fbf"}, {file = "msgspec-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cde2c41ed3eaaef6146365cb0d69580078a19f974c6cb8165cc5dcd5734f573e"}, @@ -4553,9 +3611,6 @@ files = [ {file = "multidict-6.7.1.tar.gz", hash = "sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d"}, ] -[package.dependencies] -typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} - [[package]] name = "multiprocess" version = "0.70.16" @@ -4605,58 +3660,10 @@ sphinx = ">=5,<7" [package.extras] code-style = ["pre-commit (>=3.0,<4.0)"] linkify = ["linkify-it-py (>=1.0,<2.0)"] -rtd = ["ipython", "pydata-sphinx-theme (==v0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.7.5,<0.8.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] +rtd = ["ipython", "pydata-sphinx-theme (==0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.7.5,<0.8.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=7,<8)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4,<0.4.0)"] -[[package]] -name = "narwhals" -version = "2.26.0" -description = "Extremely lightweight compatibility layer between dataframe libraries" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "narwhals-2.26.0-py3-none-any.whl", hash = "sha256:29326d74f107c347fd1009bd58e38d9f7c7c5b51e6de97bc93dbc325d9038b54"}, - {file = "narwhals-2.26.0.tar.gz", hash = "sha256:6b9cadca82f375c7e4cf584fdc86ca25da54827307a9c58f94547ee6104b82dd"}, -] - -[package.extras] -cudf = ["cudf-cu12 (>=24.10.0) ; sys_platform == \"linux\""] -dask = ["dask[dataframe] (>=2024.8)"] -duckdb = ["duckdb (>=1.1)"] -ibis = ["ibis-framework (>=6.0.0)", "packaging (>=21.3)", "pyarrow-hotfix (>=0.7)"] -modin = ["modin (>=0.22.0)"] -pandas = ["pandas (>=1.3.4)"] -polars = ["polars (>=0.20.4)"] -pyarrow = ["pyarrow (>=13.0.0)"] -pyspark = ["pyspark (>=3.5.0)"] -pyspark-connect = ["pyspark[connect] (>=3.5.0)"] -sql = ["narwhals[duckdb]", "sqlparse (>=0.5.5)"] -sqlframe = ["sqlframe (>=3.22.0,!=3.39.3)"] - -[[package]] -name = "networkx" -version = "3.4.2" -description = "Python package for creating and manipulating graphs and networks" -optional = false -python-versions = ">=3.10" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"}, - {file = "networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1"}, -] - -[package.extras] -default = ["matplotlib (>=3.7)", "numpy (>=1.24)", "pandas (>=2.0)", "scipy (>=1.10,!=1.11.0,!=1.11.1)"] -developer = ["changelist (==0.5)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] -doc = ["intersphinx-registry", "myst-nb (>=1.1)", "numpydoc (>=1.8.0)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.15)", "sphinx (>=7.3)", "sphinx-gallery (>=0.16)", "texext (>=0.6.7)"] -example = ["cairocffi (>=1.7)", "contextily (>=1.6)", "igraph (>=0.11)", "momepy (>=0.7.2)", "osmnx (>=1.9)", "scikit-learn (>=1.5)", "seaborn (>=0.13)"] -extra = ["lxml (>=4.6)", "pydot (>=3.0.1)", "pygraphviz (>=1.14)", "sympy (>=1.10)"] -test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] - [[package]] name = "networkx" version = "3.6.1" @@ -4664,7 +3671,6 @@ description = "Python package for creating and manipulating graphs and networks" optional = false python-versions = "!=3.14.1,>=3.11" groups = ["main"] -markers = "python_version >= \"3.11\"" files = [ {file = "networkx-3.6.1-py3-none-any.whl", hash = "sha256:d47fbf302e7d9cbbb9e2555a0d267983d2aa476bac30e90dfbe5669bd57f3762"}, {file = "networkx-3.6.1.tar.gz", hash = "sha256:26b7c357accc0c8cde558ad486283728b65b6a95d85ee1cd66bafab4c8168509"}, @@ -4688,7 +3694,7 @@ description = "Ninja is a small build system with a focus on speed" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "ninja-1.13.0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:fa2a8bfc62e31b08f83127d1613d10821775a0eb334197154c4d6067b7068ff1"}, {file = "ninja-1.13.0-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3d00c692fb717fd511abeb44b8c5d00340c36938c12d6538ba989fe764e79630"}, @@ -4711,34 +3717,6 @@ files = [ {file = "ninja-1.13.0.tar.gz", hash = "sha256:4a40ce995ded54d9dc24f8ea37ff3bf62ad192b547f6c7126e7e25045e76f978"}, ] -[[package]] -name = "nltk" -version = "3.10.3" -description = "Natural Language Toolkit" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "nltk-3.10.3-py3-none-any.whl", hash = "sha256:ff9598a8e20518ee0d557745890cc4435b9578489e2dcbc69c4f81fa060caf7c"}, - {file = "nltk-3.10.3.tar.gz", hash = "sha256:bb9327a461c3811c2fa4900e03840401f2126adfb30c0072827c433bd2444ea4"}, -] - -[package.dependencies] -click = "*" -defusedxml = "*" -joblib = "*" -regex = ">=2021.8.3" -tqdm = "*" - -[package.extras] -all = ["matplotlib", "numpy", "pyparsing", "python-crfsuite", "requests", "scikit-learn", "scipy", "twython"] -corenlp = ["requests"] -machine-learning = ["numpy", "python-crfsuite", "scikit-learn", "scipy"] -plot = ["matplotlib"] -tgrep = ["pyparsing"] -twitter = ["twython"] - [[package]] name = "numba" version = "0.61.2" @@ -4746,7 +3724,7 @@ description = "compiling Python code using LLVM" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "numba-0.61.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:cf9f9fc00d6eca0c23fc840817ce9f439b9f03c8f03d6246c0e7f0cb15b7162a"}, {file = "numba-0.61.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ea0247617edcb5dd61f6106a56255baab031acc4257bddaeddb3a1003b4ca3fd"}, @@ -4939,7 +3917,7 @@ description = "CUDNN FrontEnd python library" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "nvidia_cudnn_frontend-1.18.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:baa6fbc8e7c55f1c78c0374ed9a890e1cf81acaca0c92d6135d18a8e3c985244"}, {file = "nvidia_cudnn_frontend-1.18.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4bcca42259e358002c8867e3624a558f66cd5dff2cc6c3aafd860ef2f41730"}, @@ -5065,7 +4043,7 @@ description = "NVIDIA CUTLASS Python DSL" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "nvidia_cutlass_dsl-4.4.1-py3-none-any.whl", hash = "sha256:7b8ffa0117be35ef6c9a88f4462ee2a794efd0f7d9f65090e10a953e434fbfce"}, ] @@ -5083,7 +4061,7 @@ description = "NVIDIA CUTLASS Python DSL" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "nvidia_cutlass_dsl_libs_base-4.4.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:f8e3ecf646074bea34b301be283578806e02b712f277717f3dd1b28671aefa95"}, {file = "nvidia_cutlass_dsl_libs_base-4.4.1-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:fb2dc0039061fa4e03db6ffc54eaebc7a3b590f45463be461f048b819bb99efe"}, @@ -5107,7 +4085,7 @@ description = "Python Bindings for the NVIDIA Management Library" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" +markers = "extra == \"vllm\"" files = [ {file = "nvidia_ml_py-13.590.48-py3-none-any.whl", hash = "sha256:fd43d30ee9cd0b7940f5f9f9220b68d42722975e3992b6c21d14144c48760e43"}, {file = "nvidia_ml_py-13.590.48.tar.gz", hash = "sha256:8184d1be52914ac7f0991cd1c0d946c65dc88a840c754cd12c274b77b88760dd"}, @@ -5274,7 +4252,7 @@ description = "The official Python library for the openai API" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" +markers = "extra == \"vllm\"" files = [ {file = "openai-2.24.0-py3-none-any.whl", hash = "sha256:fed30480d7d6c884303287bde864980a4b137b60553ffbcf9ab4a233b7a73d94"}, {file = "openai-2.24.0.tar.gz", hash = "sha256:1e5769f540dbd01cb33bc4716a23e67b9d695161a734aff9c5f925e2bf99a673"}, @@ -5303,7 +4281,7 @@ description = "OpenAI's response format for its open-weight model series gpt-oss optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "openai_harmony-0.0.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:029ec25ca74abe48fdb58eb9fdd2a8c1618581fc33ce8e5653f8a1ffbfbd9326"}, {file = "openai_harmony-0.0.8-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4f709815924ec325b9a890e6ab2bbb0ceec8e319a4e257328eb752cf36b2efc"}, @@ -5333,7 +4311,7 @@ description = "A stats collection and distributed tracing framework" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "opencensus-0.11.4-py2.py3-none-any.whl", hash = "sha256:a18487ce68bc19900336e0ff4655c5a116daf10c1b3685ece8d971bddad6a864"}, {file = "opencensus-0.11.4.tar.gz", hash = "sha256:cbef87d8b8773064ab60e5c2a1ced58bbaa38a6d052c41aec224958ce544eff2"}, @@ -5351,7 +4329,7 @@ description = "OpenCensus Runtime Context" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "opencensus-context-0.1.3.tar.gz", hash = "sha256:a03108c3c10d8c80bb5ddf5c8a1f033161fa61972a9917f9b9b3a18517f0088c"}, {file = "opencensus_context-0.1.3-py2.py3-none-any.whl", hash = "sha256:073bb0590007af276853009fac7e4bab1d523c3f03baf4cb4511ca38967c6039"}, @@ -5364,7 +4342,7 @@ description = "Wrapper package for OpenCV python bindings." optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "opencv_python_headless-4.13.0.92-cp37-abi3-macosx_13_0_arm64.whl", hash = "sha256:1a7d040ac656c11b8c38677cc8cccdc149f98535089dbe5b081e80a4e5903209"}, {file = "opencv_python_headless-4.13.0.92-cp37-abi3-macosx_14_0_x86_64.whl", hash = "sha256:3e0a6f0a37994ec6ce5f59e936be21d5d6384a4556f2d2da9c2f9c5dc948394c"}, @@ -5386,7 +4364,7 @@ description = "OpenTelemetry Python API" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "(python_version >= \"3.11\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\") and (python_version == \"3.11\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"client\") and (extra == \"client\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\")" +markers = "extra == \"ray\"" files = [ {file = "opentelemetry_api-1.39.1-py3-none-any.whl", hash = "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950"}, {file = "opentelemetry_api-1.39.1.tar.gz", hash = "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c"}, @@ -5396,92 +4374,6 @@ files = [ importlib-metadata = ">=6.0,<8.8.0" typing-extensions = ">=4.5.0" -[[package]] -name = "opentelemetry-exporter-otlp" -version = "1.39.1" -description = "OpenTelemetry Collector Exporters" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"server\"" -files = [ - {file = "opentelemetry_exporter_otlp-1.39.1-py3-none-any.whl", hash = "sha256:68ae69775291f04f000eb4b698ff16ff685fdebe5cb52871bc4e87938a7b00fe"}, - {file = "opentelemetry_exporter_otlp-1.39.1.tar.gz", hash = "sha256:7cf7470e9fd0060c8a38a23e4f695ac686c06a48ad97f8d4867bc9b420180b9c"}, -] - -[package.dependencies] -opentelemetry-exporter-otlp-proto-grpc = "1.39.1" -opentelemetry-exporter-otlp-proto-http = "1.39.1" - -[[package]] -name = "opentelemetry-exporter-otlp-proto-common" -version = "1.39.1" -description = "OpenTelemetry Protobuf encoding" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"server\"" -files = [ - {file = "opentelemetry_exporter_otlp_proto_common-1.39.1-py3-none-any.whl", hash = "sha256:08f8a5862d64cc3435105686d0216c1365dc5701f86844a8cd56597d0c764fde"}, - {file = "opentelemetry_exporter_otlp_proto_common-1.39.1.tar.gz", hash = "sha256:763370d4737a59741c89a67b50f9e39271639ee4afc999dadfe768541c027464"}, -] - -[package.dependencies] -opentelemetry-proto = "1.39.1" - -[[package]] -name = "opentelemetry-exporter-otlp-proto-grpc" -version = "1.39.1" -description = "OpenTelemetry Collector Protobuf over gRPC Exporter" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"server\"" -files = [ - {file = "opentelemetry_exporter_otlp_proto_grpc-1.39.1-py3-none-any.whl", hash = "sha256:fa1c136a05c7e9b4c09f739469cbdb927ea20b34088ab1d959a849b5cc589c18"}, - {file = "opentelemetry_exporter_otlp_proto_grpc-1.39.1.tar.gz", hash = "sha256:772eb1c9287485d625e4dbe9c879898e5253fea111d9181140f51291b5fec3ad"}, -] - -[package.dependencies] -googleapis-common-protos = ">=1.57,<2.0" -grpcio = [ - {version = ">=1.63.2,<2.0.0", markers = "python_version < \"3.13\""}, - {version = ">=1.66.2,<2.0.0", markers = "python_version >= \"3.13\""}, -] -opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.39.1" -opentelemetry-proto = "1.39.1" -opentelemetry-sdk = ">=1.39.1,<1.40.0" -typing-extensions = ">=4.6.0" - -[package.extras] -gcp-auth = ["opentelemetry-exporter-credential-provider-gcp (>=0.59b0)"] - -[[package]] -name = "opentelemetry-exporter-otlp-proto-http" -version = "1.39.1" -description = "OpenTelemetry Collector Protobuf over HTTP Exporter" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"server\"" -files = [ - {file = "opentelemetry_exporter_otlp_proto_http-1.39.1-py3-none-any.whl", hash = "sha256:d9f5207183dd752a412c4cd564ca8875ececba13be6e9c6c370ffb752fd59985"}, - {file = "opentelemetry_exporter_otlp_proto_http-1.39.1.tar.gz", hash = "sha256:31bdab9745c709ce90a49a0624c2bd445d31a28ba34275951a6a362d16a0b9cb"}, -] - -[package.dependencies] -googleapis-common-protos = ">=1.52,<2.0" -opentelemetry-api = ">=1.15,<2.0" -opentelemetry-exporter-otlp-proto-common = "1.39.1" -opentelemetry-proto = "1.39.1" -opentelemetry-sdk = ">=1.39.1,<1.40.0" -requests = ">=2.7,<3.0" -typing-extensions = ">=4.5.0" - -[package.extras] -gcp-auth = ["opentelemetry-exporter-credential-provider-gcp (>=0.59b0)"] - [[package]] name = "opentelemetry-exporter-prometheus" version = "0.60b1" @@ -5489,7 +4381,7 @@ description = "Prometheus Metric Exporter for OpenTelemetry" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "opentelemetry_exporter_prometheus-0.60b1-py3-none-any.whl", hash = "sha256:49f59178de4f4590e3cef0b8b95cf6e071aae70e1f060566df5546fad773b8fd"}, {file = "opentelemetry_exporter_prometheus-0.60b1.tar.gz", hash = "sha256:a4011b46906323f71724649d301b4dc188aaa068852e814f4df38cc76eac616b"}, @@ -5500,42 +4392,6 @@ opentelemetry-api = ">=1.12,<2.0" opentelemetry-sdk = ">=1.39.1,<1.40.0" prometheus-client = ">=0.5.0,<1.0.0" -[[package]] -name = "opentelemetry-instrumentation" -version = "0.60b1" -description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"server\"" -files = [ - {file = "opentelemetry_instrumentation-0.60b1-py3-none-any.whl", hash = "sha256:04480db952b48fb1ed0073f822f0ee26012b7be7c3eac1a3793122737c78632d"}, - {file = "opentelemetry_instrumentation-0.60b1.tar.gz", hash = "sha256:57ddc7974c6eb35865af0426d1a17132b88b2ed8586897fee187fd5b8944bd6a"}, -] - -[package.dependencies] -opentelemetry-api = ">=1.4,<2.0" -opentelemetry-semantic-conventions = "0.60b1" -packaging = ">=18.0" -wrapt = ">=1.0.0,<2.0.0" - -[[package]] -name = "opentelemetry-instrumentation-logging" -version = "0.60b1" -description = "OpenTelemetry Logging instrumentation" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"server\"" -files = [ - {file = "opentelemetry_instrumentation_logging-0.60b1-py3-none-any.whl", hash = "sha256:f2e18cbc7e1dd3628c80e30d243897fdc93c5b7e0c8ae60abd2b9b6a99f82343"}, - {file = "opentelemetry_instrumentation_logging-0.60b1.tar.gz", hash = "sha256:98f4b9c7aeb9314a30feee7c002c7ea9abea07c90df5f97fb058b850bc45b89a"}, -] - -[package.dependencies] -opentelemetry-api = ">=1.12,<2.0" -opentelemetry-instrumentation = "0.60b1" - [[package]] name = "opentelemetry-proto" version = "1.39.1" @@ -5543,7 +4399,7 @@ description = "OpenTelemetry Python Proto" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" +markers = "extra == \"ray\"" files = [ {file = "opentelemetry_proto-1.39.1-py3-none-any.whl", hash = "sha256:22cdc78efd3b3765d09e68bfbd010d4fc254c9818afd0b6b423387d9dee46007"}, {file = "opentelemetry_proto-1.39.1.tar.gz", hash = "sha256:6c8e05144fc0d3ed4d22c2289c6b126e03bcd0e6a7da0f16cedd2e1c2772e2c8"}, @@ -5559,7 +4415,7 @@ description = "OpenTelemetry Python SDK" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" +markers = "extra == \"ray\"" files = [ {file = "opentelemetry_sdk-1.39.1-py3-none-any.whl", hash = "sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c"}, {file = "opentelemetry_sdk-1.39.1.tar.gz", hash = "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6"}, @@ -5577,7 +4433,7 @@ description = "OpenTelemetry Semantic Conventions" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" +markers = "extra == \"ray\"" files = [ {file = "opentelemetry_semantic_conventions-0.60b1-py3-none-any.whl", hash = "sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb"}, {file = "opentelemetry_semantic_conventions-0.60b1.tar.gz", hash = "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953"}, @@ -5587,90 +4443,13 @@ files = [ opentelemetry-api = "1.39.1" typing-extensions = ">=4.5.0" -[[package]] -name = "orjson" -version = "3.12.0" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "(python_version >= \"3.11\" or extra == \"async-rl\") and (extra == \"async-rl\" or extra == \"client\")" -files = [ - {file = "orjson-3.12.0-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:747843254519dd43b93eee3153a19e5a509334320c4d2f823ec879232db5c796"}, - {file = "orjson-3.12.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:7c2ad193c8004254f34b499f3bd2c80f043d10754aff2b38f93da574f4883f98"}, - {file = "orjson-3.12.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:bc7a872f03522d90e0429e6c0c5cd23084f767bedcb4c58048eec19294613344"}, - {file = "orjson-3.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18a87929f31d94a77f7dc93cf527e91f39ce7fe7813d588a4de2507efd32a387"}, - {file = "orjson-3.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9683ee9ea0659da64f36574ef675b8a86330c34c19ea75db1fb93c3ff99e0ef"}, - {file = "orjson-3.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:103b5db66aa53c1f9e88c2524be4f383e831ba7dfd5f9f5af6336a177c622f11"}, - {file = "orjson-3.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:bd57d79aefa3f84eec851d6de7a366795b9345cfaf17f82b4820430a7a5fa241"}, - {file = "orjson-3.12.0-cp310-cp310-win32.whl", hash = "sha256:3dbce9b6b3074b31a5d5dd322a9c4e5b16f206091ece4194c2e36952847a105e"}, - {file = "orjson-3.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:3bb17a06f9bd15237b3216c044209fe92597379124018cfc196fbb846cde64df"}, - {file = "orjson-3.12.0-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a94f0f0c6fcbb2b5bd9734c57a489c7584a732bbdf04a39e8c83b861e9d03e92"}, - {file = "orjson-3.12.0-cp311-cp311-macosx_15_0_arm64.whl", hash = "sha256:a696529ec96a90d9a5f9570207efe403c8b08f8e4aa2783ee3403511e2fdfa10"}, - {file = "orjson-3.12.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:e4ac5059baab4b3acbd99485de019ff8cda0fdf34b61fa74f7197a53db78bfe8"}, - {file = "orjson-3.12.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:8e29957429c35bbb5a185a119c523aa2428b7bbf1a293724c7b9375ed8f892a3"}, - {file = "orjson-3.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dce0166feb0a737ab84f598c9a338cbc0b764a036617aa686194f53c7eba0c3e"}, - {file = "orjson-3.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9caf3d09f47c3c70c4451ada20ef9bc4a4cdffa26f49862cf0a253b329aae2d5"}, - {file = "orjson-3.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b9dca132b1fda5565088e65a6b6e742285e0aeceb6fae549fa8863e16c7d3998"}, - {file = "orjson-3.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a791f793b287bbc135b8e87c34e35c8bfc693e2a8a620fab1ae682b925f9a32e"}, - {file = "orjson-3.12.0-cp311-cp311-win32.whl", hash = "sha256:31ed278a36304390adc3eec5d7f6fd593a7c3e99e5a06cd07866396c4b1b4710"}, - {file = "orjson-3.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb2539159dfe8d371914f354360fa50e4a577cc89222a3828b9650a5e5040252"}, - {file = "orjson-3.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:61318b6de893c7a9d9f3e5ecbadccbfc26a7eb417ccc7bbf0771de3b4d72f868"}, - {file = "orjson-3.12.0-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:aa3e43a6846e91d7bde3d5a9c66090fcd8744f569a9b6cffc5e1ca38f6a461c0"}, - {file = "orjson-3.12.0-cp312-cp312-macosx_15_0_arm64.whl", hash = "sha256:11edb4660a6680abee9788a3a9072208a2c96538cc1322bd79542065229d8e54"}, - {file = "orjson-3.12.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:2d3a9da945a4d96ae758fdaaca56742e6b73b6fd554c5d8876f252a6dad70b83"}, - {file = "orjson-3.12.0-cp312-cp312-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:92ffc09e07233a6ab6d4e067f7841edcbcc134cb4812155cf171ea5255a421d7"}, - {file = "orjson-3.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf44e374aadde77b1f6109f1030be51433eb61984379852766b6f4e187db7b1e"}, - {file = "orjson-3.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1192a7021b6d071aaf909864f6e924d6a2675ca360485b972b8401749311750b"}, - {file = "orjson-3.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:53c0c474a9d9aff9aebfc0c88de1f28f843d940e6e3a80729abdf6a20274356f"}, - {file = "orjson-3.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:532ff8cd4bd59a327a953a7dcde922c7fc25b85e29721bb8633265430d3a3873"}, - {file = "orjson-3.12.0-cp312-cp312-win32.whl", hash = "sha256:a6cf4b18e7de173f209f2084ffbd736dd72389a396326ee80a7022168be232e5"}, - {file = "orjson-3.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:010811c1b69773450a01cef97727a67b223242f350b77d4ca000e59a9ef2155a"}, - {file = "orjson-3.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:ad29eece0c601737f2a60edc2752a84e7a0785df3efb62e3012834700a5afe0d"}, - {file = "orjson-3.12.0-cp313-cp313-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a36ec60f1796f9a3f13e3b98390295e17a1c7c10155b448d264098bf9ee5900"}, - {file = "orjson-3.12.0-cp313-cp313-macosx_15_0_arm64.whl", hash = "sha256:ad0422b92d5195443a39f80c3bcf731cc2e00f153bd32063a47b73b057bd0f03"}, - {file = "orjson-3.12.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:5a0fdbc216388f653d3752ff310e710f59253bd4ed6a2bfb3f4f06b84714bbd8"}, - {file = "orjson-3.12.0-cp313-cp313-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:2eb5c56e534127b2b8fa38d2363c8b1b8190367ee0d1d16c041517d880843b94"}, - {file = "orjson-3.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:784106539f4b9d4b930e0b4eb8d45168507dae001945e71b4675a367f1e5e806"}, - {file = "orjson-3.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c680706fc8396d95e7c4c1f9482563f552137aef91b57237a3ad5aaf64629df"}, - {file = "orjson-3.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:83445adc40cba26d6d621185a45128ce455b766af368cad2ab64b970603a7978"}, - {file = "orjson-3.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:644d005bc82f917337a95ce270c9f6f92f9834c2bed7b1477572f8db00784222"}, - {file = "orjson-3.12.0-cp313-cp313-win32.whl", hash = "sha256:d8e78d3d93705e3d27cc17cdb209e44d7a8ea203010cac6ce9c7ffc1ae1996f1"}, - {file = "orjson-3.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:b85931be5b6763c31283805c9bdaae1ca03ad9f6f12a15f1cbf6745b907932c2"}, - {file = "orjson-3.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:6a31348d7dfa64cd9c78bd1f510ff44c48fe64d71094e6b90e364dba3b55949e"}, - {file = "orjson-3.12.0-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9e6fee342a48760e854d743e7a81534d8e2925a6f46e09f750cf56b50fd1de5d"}, - {file = "orjson-3.12.0-cp314-cp314-macosx_15_0_arm64.whl", hash = "sha256:8c3bb86dd10f39b3fbf434b7d5dc7cac77d6fc8ac572ae30a10731ede2c4b647"}, - {file = "orjson-3.12.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.whl", hash = "sha256:2bb3ce43203936072dd8b4917b01d3aecfc02329bfb42510cb7cfb24708adc9c"}, - {file = "orjson-3.12.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:6a2a79c89984dc719817d388c8709e0efc2a2795a934eaa746b4882eb6045adc"}, - {file = "orjson-3.12.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f06dd838d1e07d9b1de0932ec0485ec92c4d5f5d1ad4817a656268c3e88be1e1"}, - {file = "orjson-3.12.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6b11be792c3d2c6a4be2af4ebf97a68d0bf5f580aca6e86a418a354f6cc846a"}, - {file = "orjson-3.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:477ecaf6b9f88f873341b91fcc736119ca81b5e002a9f7f308ff5b4f2ce2a70e"}, - {file = "orjson-3.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f3c0683136acdc29afdf88a5bc2f7d3d0e34087788d1d63c0144b805a87a196f"}, - {file = "orjson-3.12.0-cp314-cp314-win32.whl", hash = "sha256:d39f3f5c3927e2dc0913fe5bbc1a2f6b1b9d1bba1de6358340d0ad0d0c00ca92"}, - {file = "orjson-3.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:0b1ac5bf6609b2716c7954011c5fef6254922df029f45d032ee4ebf5d363cbed"}, - {file = "orjson-3.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:50fae885cb073eac7556353ff3df93312b0d5137b0a5056b2bb63f97ed9a93c7"}, - {file = "orjson-3.12.0-cp315-cp315-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:01efac2074fffb4cb1ea3fab7861e9d0f2a26913854a972f5ac760525dbdaf6e"}, - {file = "orjson-3.12.0-cp315-cp315-macosx_15_0_arm64.whl", hash = "sha256:ed4ca42bd55955aa34deedcfdfd0e0c31abf51143aae158ae2bc3520b626e517"}, - {file = "orjson-3.12.0-cp315-cp315-manylinux_2_39_aarch64.whl", hash = "sha256:40f92192227505acca4e2533ce565f8e6b9535f7d0d09b0968452f18b7376b38"}, - {file = "orjson-3.12.0-cp315-cp315-manylinux_2_39_armv7l.whl", hash = "sha256:33efefcf5d88eaf400b47e2eba02f91f319bb9951be61ca500b7d536d3f2079d"}, - {file = "orjson-3.12.0-cp315-cp315-manylinux_2_39_i686.whl", hash = "sha256:8e386b0bc0ddd7cd2056f884b5a0af33592bd01ac66a7ca4b42a65a7e7774a13"}, - {file = "orjson-3.12.0-cp315-cp315-manylinux_2_39_x86_64.whl", hash = "sha256:58c58e1de0006ffb580368d6793c36c7b0b021db066479cf281bf5061e732328"}, - {file = "orjson-3.12.0-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:08231552159be266a7269555bd9f7c016aee7d9ad6dab06eb58796c5ccb7101c"}, - {file = "orjson-3.12.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:a15f9a891bce5f5cc5d210e3ad8614d4d1b489a56448c099d6d2a7168b2d954a"}, - {file = "orjson-3.12.0-cp315-cp315-win32.whl", hash = "sha256:03091c8a64db4be38746597ceea68f33c238e27acd9bfe99fb59420224ae7a55"}, - {file = "orjson-3.12.0-cp315-cp315-win_amd64.whl", hash = "sha256:2b7bcefb9f40fa242fa6b06377232c048e655747790829609168c01162f60578"}, - {file = "orjson-3.12.0-cp315-cp315-win_arm64.whl", hash = "sha256:859fc4196855890150bb08e649b30d2c93b249b3e3edd0d3bb2231abf8aa8adc"}, - {file = "orjson-3.12.0.tar.gz", hash = "sha256:d14203fb1aae2ad9b3d52f8a0e82aeb10197ef1c9bc61da7f358bd70b00123d5"}, -] - [[package]] name = "oss2" version = "2.13.1" description = "Aliyun OSS (Object Storage Service) SDK" -optional = true +optional = false python-versions = "*" groups = ["main"] -markers = "extra == \"eval\"" files = [ {file = "oss2-2.13.1.tar.gz", hash = "sha256:8548ea7d43326f6fd679bc8b79b3a2dfbfe9c6a60ed57e2410818fec57023dda"}, ] @@ -5690,7 +4469,7 @@ description = "Structured Text Generation in Rust" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "outlines_core-0.2.11-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:89d79d8454b321f60047541a896d410ca9db631d241960266c4fe839cf5cd1b1"}, {file = "outlines_core-0.2.11-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:44d581893f8644da02db7be11887229a40d26077cbdd22072ad1ed1db0ad0b2d"}, @@ -5738,19 +4517,6 @@ files = [ [package.extras] test = ["asv", "coverage[toml] (>=5.1)", "diff-cover", "maturin[patchelf]", "numba", "numpy", "pre-commit", "psutil", "pydantic", "pytest", "pytest-benchmark", "pytest-cov", "pytest-mock", "scipy", "torch"] -[[package]] -name = "overrides" -version = "7.7.0" -description = "A decorator to automatically detect mismatch when overriding a method." -optional = true -python-versions = ">=3.6" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, - {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, -] - [[package]] name = "packaging" version = "26.0" @@ -5763,103 +4529,6 @@ files = [ {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, ] -[[package]] -name = "pandas" -version = "2.3.3" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c"}, - {file = "pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a"}, - {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1"}, - {file = "pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838"}, - {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250"}, - {file = "pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4"}, - {file = "pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826"}, - {file = "pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523"}, - {file = "pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45"}, - {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66"}, - {file = "pandas-2.3.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b98560e98cb334799c0b07ca7967ac361a47326e9b4e5a7dfb5ab2b1c9d35a1b"}, - {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37b5848ba49824e5c30bedb9c830ab9b7751fd049bc7914533e01c65f79791"}, - {file = "pandas-2.3.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db4301b2d1f926ae677a751eb2bd0e8c5f5319c9cb3f88b0becbbb0b07b34151"}, - {file = "pandas-2.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:f086f6fe114e19d92014a1966f43a3e62285109afe874f067f5abbdcbb10e59c"}, - {file = "pandas-2.3.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d21f6d74eb1725c2efaa71a2bfc661a0689579b58e9c0ca58a739ff0b002b53"}, - {file = "pandas-2.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3fd2f887589c7aa868e02632612ba39acb0b8948faf5cc58f0850e165bd46f35"}, - {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecaf1e12bdc03c86ad4a7ea848d66c685cb6851d807a26aa245ca3d2017a1908"}, - {file = "pandas-2.3.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3d11d2fda7eb164ef27ffc14b4fcab16a80e1ce67e9f57e19ec0afaf715ba89"}, - {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a68e15f780eddf2b07d242e17a04aa187a7ee12b40b930bfdd78070556550e98"}, - {file = "pandas-2.3.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:371a4ab48e950033bcf52b6527eccb564f52dc826c02afd9a1bc0ab731bba084"}, - {file = "pandas-2.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:a16dcec078a01eeef8ee61bf64074b4e524a2a3f4b3be9326420cabe59c4778b"}, - {file = "pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713"}, - {file = "pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8"}, - {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d"}, - {file = "pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac"}, - {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c"}, - {file = "pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493"}, - {file = "pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee"}, - {file = "pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5"}, - {file = "pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21"}, - {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78"}, - {file = "pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110"}, - {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86"}, - {file = "pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc"}, - {file = "pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0"}, - {file = "pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593"}, - {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c"}, - {file = "pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b"}, - {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6"}, - {file = "pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3"}, - {file = "pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5"}, - {file = "pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec"}, - {file = "pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7"}, - {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450"}, - {file = "pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5"}, - {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788"}, - {file = "pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87"}, - {file = "pandas-2.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c503ba5216814e295f40711470446bc3fd00f0faea8a086cbc688808e26f92a2"}, - {file = "pandas-2.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a637c5cdfa04b6d6e2ecedcb81fc52ffb0fd78ce2ebccc9ea964df9f658de8c8"}, - {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:854d00d556406bffe66a4c0802f334c9ad5a96b4f1f868adf036a21b11ef13ff"}, - {file = "pandas-2.3.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bf1f8a81d04ca90e32a0aceb819d34dbd378a98bf923b6398b9a3ec0bf44de29"}, - {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:23ebd657a4d38268c7dfbdf089fbc31ea709d82e4923c5ffd4fbd5747133ce73"}, - {file = "pandas-2.3.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5554c929ccc317d41a5e3d1234f3be588248e61f08a74dd17c9eabb535777dc9"}, - {file = "pandas-2.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:d3e28b3e83862ccf4d85ff19cf8c20b2ae7e503881711ff2d534dc8f761131aa"}, - {file = "pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b"}, -] - -[package.dependencies] -numpy = {version = ">=1.22.4", markers = "python_version < \"3.11\""} -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] - [[package]] name = "pandas" version = "3.0.1" @@ -5867,7 +4536,6 @@ description = "Powerful data structures for data analysis, time series, and stat optional = false python-versions = ">=3.11" groups = ["main"] -markers = "python_version >= \"3.11\"" files = [ {file = "pandas-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de09668c1bf3b925c07e5762291602f0d789eca1b3a781f99c1c78f6cac0e7ea"}, {file = "pandas-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24ba315ba3d6e5806063ac6eb717504e499ce30bd8c236d8693a5fd3f084c796"}, @@ -5957,7 +4625,7 @@ description = "Parse partial JSON generated by LLM" optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "partial_json_parser-0.2.1.1.post7-py3-none-any.whl", hash = "sha256:145119e5eabcf80cbb13844a6b50a85c68bf99d376f8ed771e2a3c3b03e653ae"}, {file = "partial_json_parser-0.2.1.1.post7.tar.gz", hash = "sha256:86590e1ba6bcb6739a2dfc17d2323f028cb5884f4c6ce23db376999132c9a922"}, @@ -6112,117 +4780,12 @@ description = "A small Python package for determining appropriate platform-speci optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" +markers = "extra == \"ray\"" files = [ {file = "platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd"}, {file = "platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291"}, ] -[[package]] -name = "plotext" -version = "6.1.0" -description = "plotext plots directly on terminal" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"client\"" -files = [ - {file = "plotext-6.1.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:4fec26b86ad32b3597de5861cfbf0023bb5ae02250f0ca940b12b069bccf43e6"}, - {file = "plotext-6.1.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:bfafad58a20da6c279e722481b5c3e67a9c8c54bde722d414c5ceffe71b7c652"}, - {file = "plotext-6.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c035440296be20e539ee70d4de07290d84bb0c9017bb3bc5867a8b3f9cead56"}, - {file = "plotext-6.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e59f54cedfb56129e2aec1f885869fe13903fdd4e6f18a10301e71a7d5b9851c"}, - {file = "plotext-6.1.0-py3-none-win_amd64.whl", hash = "sha256:60c85326da5454db482c9b1357c9ba385bae4a05c9dd498ff604e80458e03e3b"}, - {file = "plotext-6.1.0.tar.gz", hash = "sha256:6b729ce6376c5c1c2152fe85e0449dcc54879d0923b3c6c8d1670108245c6f84"}, -] - -[package.extras] -image = ["pillow (>=8.4)"] -video = ["ffpyplayer (>=4.3.5)", "pillow (>=8.4)", "yt-dlp (>=2024.1.1)"] - -[[package]] -name = "plotly" -version = "7.0.0" -description = "An open-source interactive data visualization library for Python" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "plotly-7.0.0-py3-none-any.whl", hash = "sha256:78cbf7bd06d1b05bb3b8ec1b709864695229b55151b6f7530fbf55517ead6fdd"}, - {file = "plotly-7.0.0.tar.gz", hash = "sha256:08b21f1244a97e7a1a699833c4bb2678475aa108b3f1989886ed0b038ebfd849"}, -] - -[package.dependencies] -narwhals = ">=1.15.1" -packaging = "*" - -[package.extras] -dev = ["anywidget", "build", "colorcet", "fiona (<=1.9.6) ; python_version <= \"3.8\"", "geopandas", "inflect", "jupyter-builder", "jupyterlab", "kaleido (>=1.3.0)", "numpy (>=1.22)", "orjson", "pandas", "pdfrw", "pillow", "polars[timezone]", "pyarrow", "pytest", "pytz", "requests", "ruff (==0.11.12)", "scikit-image", "scipy", "statsmodels", "vaex ; python_version <= \"3.9\"", "xarray"] -dev-build = ["build", "jupyter-builder", "pytest", "requests", "ruff (==0.11.12)"] -dev-codegen = ["inflect", "pytest", "requests", "ruff (==0.11.12)"] -dev-core = ["pytest", "requests", "ruff (==0.11.12)"] -dev-optional = ["anywidget", "build", "colorcet", "fiona (<=1.9.6) ; python_version <= \"3.8\"", "geopandas", "inflect", "jupyter-builder", "jupyterlab", "kaleido (>=1.3.0)", "numpy (>=1.22)", "orjson", "pandas", "pdfrw", "pillow", "polars[timezone]", "pyarrow", "pytest", "pytz", "requests", "ruff (==0.11.12)", "scikit-image", "scipy", "statsmodels", "vaex ; python_version <= \"3.9\"", "xarray"] -dev-pandas1 = ["numpy (>=1,<2)", "pandas (>=1,<2)", "setuptools (<82)"] -dev-pandas2 = ["pandas (>=2,<3)"] -dev-pandas3 = ["pandas (>=3) ; python_version >= \"3.11\""] -express = ["numpy (>=1.22)"] -kaleido = ["kaleido (>=1.3.0)"] - -[[package]] -name = "pluggy" -version = "1.6.0" -description = "plugin and hook calling mechanisms for python" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"test\"" -files = [ - {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, - {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["coverage", "pytest", "pytest-benchmark"] - -[[package]] -name = "portalocker" -version = "4.3.2" -description = "Cross-platform file locking, with Redis, PID-file and bounded-semaphore locks" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "portalocker-4.3.2-py3-none-any.whl", hash = "sha256:42f0362e7343af78b25eb095c0cde300e746a0ab6647a835cc30764918490c93"}, - {file = "portalocker-4.3.2.tar.gz", hash = "sha256:8de4a1330f55b3c9a1d50ab1b70a765f2f136d6399ae206411117ed98c3b8e2b"}, -] - -[package.extras] -docs = ["furo", "sphinx (>=7)"] -redis = ["redis (>=5.0)"] -tests = ["coverage-conditional-plugin (>=0.9)", "fakeredis (>=2.31.0)", "portalocker[redis]", "pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-rerunfailures (>=15.1)", "pytest-timeout (>=2.1.0)", "types-pywin32 (>=310.0.0.20250429)", "typing-extensions (>=4.4)"] -win32 = ["pywin32 (>=226) ; sys_platform == \"win32\""] - -[[package]] -name = "prettytable" -version = "3.18.0" -description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "prettytable-3.18.0-py3-none-any.whl", hash = "sha256:b3346e0e6f79180833aebaac088ae926340586cf6d7d991b9eb125b65f72313a"}, - {file = "prettytable-3.18.0.tar.gz", hash = "sha256:439217116152244369caf3d9f1caf2f9fe29b03bd79e88d2928c8e718c95d680"}, -] - -[package.dependencies] -wcwidth = ">=0.3.5" - -[package.extras] -tests = ["pytest (>=9)", "pytest-cov", "pytest-lazy-fixtures"] - [[package]] name = "prometheus-client" version = "0.24.1" @@ -6230,7 +4793,7 @@ description = "Python client for the Prometheus monitoring system." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055"}, {file = "prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9"}, @@ -6248,7 +4811,7 @@ description = "Instrument your FastAPI app with Prometheus metrics" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "prometheus_fastapi_instrumentator-7.1.0-py3-none-any.whl", hash = "sha256:978130f3c0bb7b8ebcc90d35516a6fe13e02d2eb358c8f83887cdef7020c31e9"}, {file = "prometheus_fastapi_instrumentator-7.1.0.tar.gz", hash = "sha256:be7cd61eeea4e5912aeccb4261c6631b3f227d8924542d79eaf5af3f439cbe5e"}, @@ -6397,7 +4960,7 @@ description = "Beautiful, Pythonic protocol buffers" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "proto_plus-1.27.1-py3-none-any.whl", hash = "sha256:e4643061f3a4d0de092d62aa4ad09fa4756b2cbb89d4627f3985018216f9fefc"}, {file = "proto_plus-1.27.1.tar.gz", hash = "sha256:912a7460446625b792f6448bade9e55cd4e41e6ac10e27009ef71a7f317fa147"}, @@ -6416,7 +4979,7 @@ description = "" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "(python_version >= \"3.11\" or extra == \"async-rl\" or extra == \"rl\" or extra == \"server\" or extra == \"megatron\") and (extra == \"async-rl\" or extra == \"rl\" or extra == \"server\" or extra == \"megatron\" or extra == \"client\")" +markers = "extra == \"ray\" or extra == \"vllm\" or extra == \"megatron\"" files = [ {file = "protobuf-6.33.5-cp310-abi3-win32.whl", hash = "sha256:d71b040839446bac0f4d162e758bea99c8251161dae9d0983a3b88dee345153b"}, {file = "protobuf-6.33.5-cp310-abi3-win_amd64.whl", hash = "sha256:3093804752167bcab3998bec9f1048baae6e29505adaf1afd14a37bddede533c"}, @@ -6465,18 +5028,6 @@ files = [ dev = ["abi3audit", "black", "check-manifest", "colorama ; os_name == \"nt\"", "coverage", "packaging", "psleak", "pylint", "pyperf", "pypinfo", "pyreadline3 ; os_name == \"nt\"", "pytest", "pytest-cov", "pytest-instafail", "pytest-xdist", "pywin32 ; os_name == \"nt\" and implementation_name != \"pypy\"", "requests", "rstcheck", "ruff", "setuptools", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "validate-pyproject[all]", "virtualenv", "vulture", "wheel", "wheel ; os_name == \"nt\" and implementation_name != \"pypy\"", "wmi ; os_name == \"nt\" and implementation_name != \"pypy\""] test = ["psleak", "pytest", "pytest-instafail", "pytest-xdist", "pywin32 ; os_name == \"nt\" and implementation_name != \"pypy\"", "setuptools", "wheel ; os_name == \"nt\" and implementation_name != \"pypy\"", "wmi ; os_name == \"nt\" and implementation_name != \"pypy\""] -[[package]] -name = "pwinput" -version = "1.0.3" -description = "A cross-platform Python module that displays **** for password input. Works on Windows, unlike getpass. Formerly called stdiomask." -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "pwinput-1.0.3.tar.gz", hash = "sha256:ca1a8bd06e28872d751dbd4132d8637127c25b408ea3a349377314a5491426f3"}, -] - [[package]] name = "py-cpuinfo" version = "9.0.0" @@ -6484,23 +5035,10 @@ description = "Get CPU info with pure Python" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690"}, - {file = "py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5"}, -] - -[[package]] -name = "py-data-juicer" -version = "1.1.0" -description = "A One-Stop Data Processing System for Large Language Models." -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"data\"" -files = [ - {file = "py_data_juicer-1.1.0-py3-none-any.whl", hash = "sha256:27faf8ab1ee4a9597c09b4f9f18286a2292b1d7fb4ffe08b94ab5a1108489221"}, - {file = "py_data_juicer-1.1.0.tar.gz", hash = "sha256:675dca2b0fde9341c676351a29aec7cfa0a756608d64160a2745fe07e0fb4bf2"}, + {file = "py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5"}, ] [[package]] @@ -6510,7 +5048,7 @@ description = "" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "py_spy-0.4.1-py2.py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:809094208c6256c8f4ccadd31e9a513fe2429253f48e20066879239ba12cd8cc"}, {file = "py_spy-0.4.1-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:1fb8bf71ab8df95a95cc387deed6552934c50feef2cf6456bc06692a5508fd0c"}, @@ -6592,7 +5130,7 @@ description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "pyasn1-0.6.2-py3-none-any.whl", hash = "sha256:1eb26d860996a18e9b6ed05e7aae0e9fc21619fcee6af91cca9bad4fbea224bf"}, {file = "pyasn1-0.6.2.tar.gz", hash = "sha256:9b59a2b25ba7e4f8197db7686c09fb33e658b98339fadb826e9512629017833b"}, @@ -6605,7 +5143,7 @@ description = "A collection of ASN.1-based protocols modules" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "pyasn1_modules-0.4.2-py3-none-any.whl", hash = "sha256:29253a9207ce32b64c3ac6600edc75368f98473906e8fd1043bd6b5b1de2c14a"}, {file = "pyasn1_modules-0.4.2.tar.gz", hash = "sha256:677091de870a80aae844b1ca6134f54652fa2c8c5a52aa396440ac3106e941e6"}, @@ -6621,7 +5159,7 @@ description = "Fast Base64 encoding/decoding" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "pybase64-1.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f63aa7f29139b8a05ce5f97cdb7fad63d29071e5bdc8a638a343311fe996112a"}, {file = "pybase64-1.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f5943ec1ae87a8b4fe310905bb57205ea4330c75e2c628433a7d9dd52295b588"}, @@ -6847,7 +5385,7 @@ description = "ISO country, subdivision, language, currency and script definitio optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "pycountry-26.2.16-py3-none-any.whl", hash = "sha256:115c4baf7cceaa30f59a4694d79483c9167dbce7a9de4d3d571c5f3ea77c305a"}, {file = "pycountry-26.2.16.tar.gz", hash = "sha256:5b6027d453fcd6060112b951dd010f01f168b51b4bf8a1f1fc8c95c8d94a0801"}, @@ -6857,10 +5395,10 @@ files = [ name = "pycparser" version = "3.0" description = "C parser in Python" -optional = false +optional = true python-versions = ">=3.10" groups = ["main"] -markers = "(platform_python_implementation != \"PyPy\" or implementation_name == \"pypy\") and (extra == \"rl\" or extra == \"async-rl\" or implementation_name == \"pypy\") and implementation_name != \"PyPy\"" +markers = "platform_python_implementation != \"PyPy\" and implementation_name != \"PyPy\" and (extra == \"vllm\" or extra == \"ray\") or extra == \"vllm\" and implementation_name == \"pypy\"" files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, @@ -6870,10 +5408,9 @@ files = [ name = "pycryptodome" version = "3.23.0" description = "Cryptographic library for Python" -optional = true +optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["main"] -markers = "extra == \"eval\"" files = [ {file = "pycryptodome-3.23.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a176b79c49af27d7f6c12e4b178b0824626f40a7b9fed08f712291b6d54bf566"}, {file = "pycryptodome-3.23.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:573a0b3017e06f2cffd27d92ef22e46aa3be87a2d317a5abf7cc0e84e321bd75"}, @@ -7082,7 +5619,7 @@ description = "Extra Pydantic types." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "pydantic_extra_types-2.11.0-py3-none-any.whl", hash = "sha256:84b864d250a0fc62535b7ec591e36f2c5b4d1325fa0017eb8cda9aeb63b374a6"}, {file = "pydantic_extra_types-2.11.0.tar.gz", hash = "sha256:4e9991959d045b75feb775683437a97991d02c138e00b59176571db9ce634f0e"}, @@ -7109,7 +5646,7 @@ description = "Settings management using Pydantic" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237"}, {file = "pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025"}, @@ -7157,37 +5694,14 @@ doc = ["ablog (>=0.11.8)", "colorama", "graphviz", "ipykernel", "ipyleaflet", "i i18n = ["Babel", "jinja2"] test = ["pytest", "pytest-cov", "pytest-regressions", "sphinx[test]"] -[[package]] -name = "pyecharts" -version = "2.1.0" -description = "Python options, make charting easier" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "pyecharts-2.1.0-py3-none-any.whl", hash = "sha256:5cba0aa06af3d9390a1fed18aa4e76acd7bdfb323cdf131874f46eaf7e78c6c7"}, - {file = "pyecharts-2.1.0.tar.gz", hash = "sha256:077f8205390aea705b8cc0be9d0c09916a2c060e9e5c8d9c9d11b7d8f4bdc1da"}, -] - -[package.dependencies] -jinja2 = "*" -prettytable = "*" -simplejson = "*" - -[package.extras] -images = ["PIL"] -phantomjs = ["snapshot-phantomjs"] -pyppeteer = ["snapshot-pyppeteer"] -selenium = ["snapshot-selenium"] - [[package]] name = "pygments" version = "2.19.2" description = "Pygments is a syntax highlighting package written in Python." -optional = false +optional = true python-versions = ">=3.8" groups = ["main"] +markers = "extra == \"vllm\" or extra == \"tinker\" or extra == \"docs\"" files = [ {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, @@ -7203,7 +5717,7 @@ description = "JSON Web Token implementation in Python" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "pyjwt-2.11.0-py3-none-any.whl", hash = "sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469"}, {file = "pyjwt-2.11.0.tar.gz", hash = "sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623"}, @@ -7218,237 +5732,6 @@ dev = ["coverage[toml] (==7.10.7)", "cryptography (>=3.4.0)", "pre-commit", "pyt docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] tests = ["coverage[toml] (==7.10.7)", "pytest (>=8.4.2,<9.0.0)"] -[[package]] -name = "pylatexenc" -version = "2.11" -description = "Simple LaTeX parser providing latex-to-unicode and unicode-to-latex conversion" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "pylatexenc-2.11-py2.py3-none-any.whl", hash = "sha256:e78e7391d6c104f1ed150e21cfaa58016cdb50aa54406a2eecb793649ffdfdd0"}, - {file = "pylatexenc-2.11.tar.gz", hash = "sha256:305a072a99ce736246049c9da05841b9d718c0f7ea8888f5f596cf15cb621053"}, -] - -[[package]] -name = "pynvml" -version = "13.0.1" -description = "Python utilities for the NVIDIA Management Library" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"server\"" -files = [ - {file = "pynvml-13.0.1-py3-none-any.whl", hash = "sha256:e2b20e0a501eeec951e2455b7ab444759cf048e0e13a57b08049fa2775266aa8"}, - {file = "pynvml-13.0.1.tar.gz", hash = "sha256:1245991d9db786b4d2f277ce66869bd58f38ac654e38c9397d18f243c8f6e48f"}, -] - -[package.dependencies] -nvidia-ml-py = ">=12.0.0" - -[package.extras] -test = ["pytest (>=3.6)", "pytest-cov", "pytest-runner"] - -[[package]] -name = "pyqwest" -version = "0.10.0" -description = "A modern, high-performance HTTP client for Python and Rust." -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "python_version >= \"3.11\" and extra == \"client\"" -files = [ - {file = "pyqwest-0.10.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:aa492d5777dd145a60795ed95d9d4707a3cd1091fdcdfc93a82ac7fdc43ebacd"}, - {file = "pyqwest-0.10.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:59f3f16628e518c674102e7b5fcff2101bba6abb4f6737ec5fade9b9278e6a53"}, - {file = "pyqwest-0.10.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6e7db305a8318b1f3218053e87501f8f245ca8bd63e948e0282d04bf0883470"}, - {file = "pyqwest-0.10.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5c757cfac5f53c8671dcb4850d5fc4c4339ea3e90636331c9318f8e3ddabc06"}, - {file = "pyqwest-0.10.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:234b3f71e3f314d997c203d8cf829b7117edd041153f9c277d0060ab90134148"}, - {file = "pyqwest-0.10.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5637256a0dac0ef57e0eaa02b032014965e4a4c995e1deca1b1b97e6d1765f78"}, - {file = "pyqwest-0.10.0-cp310-abi3-win_amd64.whl", hash = "sha256:7ea761937acf3a00d1a7e70e982949d18946e5471d1419266ab3a78bbfa19759"}, - {file = "pyqwest-0.10.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a21f1f15252a8303623b4f17b9c6de595ace11b3ade07f2adb6d07121e8191aa"}, - {file = "pyqwest-0.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:eb472c6e5d6833ebfec79db310e426eb17b01ac64c0e2c251bd9192c0d2ee0c5"}, - {file = "pyqwest-0.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83578e24cccd5e0dc04d60a0af7bfb43325b5f22d03ff74ff79ed0ecf553b50d"}, - {file = "pyqwest-0.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bb511c434f79c641efb5573e5795e56dc972252f4b96e52a9636d4ece5231a4"}, - {file = "pyqwest-0.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1aaccd8a9db9430b2aedb5bad8ead80742cbc056b85c229516c70dc80539f906"}, - {file = "pyqwest-0.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:73d9eb438ab4a957a1ce0619d3af8c1c1126bfb9181033b123d792fcf4224531"}, - {file = "pyqwest-0.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:317a74d633abe3bc5bccabf479e069c515dab9e6a755274b0ccb1d8a5bbfede3"}, - {file = "pyqwest-0.10.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:3978e794b9cfd8eaa500fb5d7aee63bc6172c605efa0abc1f62d85485bc049e1"}, - {file = "pyqwest-0.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:715991fd4f04862cd7a9d7452daabcdbd74dff4dff55eb20c22d60382dc2a4ed"}, - {file = "pyqwest-0.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c04798bed79c1dfa0e5b0e30fb137124311083490d44d6dfbe068d3dd254349e"}, - {file = "pyqwest-0.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35b472877e73dd63fed089c2bc8fa198407f005c8c19e0a93f025ebefde01a81"}, - {file = "pyqwest-0.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:564ec360b7848b35e009038ffbca00466305a9708ab21829477f64aa8cad4c64"}, - {file = "pyqwest-0.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b5c80e88a5967c1cadb3237c450f91a84a3683f8838c8dca96f09fee3612e762"}, - {file = "pyqwest-0.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc3d80b402fb59dbe015e25993ac8147456fb231a4c949f92a89f31315ad50f9"}, - {file = "pyqwest-0.10.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:23a28beb55fa6d975949bffae4adfb69378f3229bb5cbd71231e95bf66f5b26c"}, - {file = "pyqwest-0.10.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e4415ae40b8eedb1713dab14d7f9fecc3f79d26f3206c561087b88b99d5ce24b"}, - {file = "pyqwest-0.10.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14b875d2273212d7fa8e4b755d8d736ffd226b1c707a9c0017dfdc8393a96eca"}, - {file = "pyqwest-0.10.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5071491e416ea54e3b95bf9ffbed0bd065b093cb96e10a75c3d8f2cbe3c9823"}, - {file = "pyqwest-0.10.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b68b5e68d513a4c63a072f8f40e38015160cf90bfbf7e8ef7c3935ca87e9e022"}, - {file = "pyqwest-0.10.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c48910d27820b9c46fcd001b0fe514a3cf47d4784f59512dcdb8c91c395f82e4"}, - {file = "pyqwest-0.10.0-cp314-cp314-win_amd64.whl", hash = "sha256:d03ba2cd17948b623a6210981d342eb122546d8a8e910ec77511aff4b1acdd00"}, - {file = "pyqwest-0.10.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:07a0eb595f4096232c2d22549b6e4612c1ecada7934e46462c2c37ce14a89cfb"}, - {file = "pyqwest-0.10.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:26401baf7dafc71c8d12d2e8389519d141e6f7c14094d0dd4cf9ec1d3b5555bd"}, - {file = "pyqwest-0.10.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5e3c436e041d8873ce5bb0fdcf9f9e86f5604e8f0ef9e03149efebd8cb474f6"}, - {file = "pyqwest-0.10.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09364115761579eabfc79d1e954cdb3ded508dac1903fac7285d4c6f058c683f"}, - {file = "pyqwest-0.10.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:559674a98a8b1217e1830ecd41c9905bf2b60983c6b8017063dfac199f00727c"}, - {file = "pyqwest-0.10.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f399a696392fff3db3eef0a18ef65b8a3b8396d129193487d966b8eb11006376"}, - {file = "pyqwest-0.10.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0f9163d6dd991bf1bf27308ba38ba021af660b15fffa47ebca98e41cf6f00309"}, - {file = "pyqwest-0.10.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cfcc7ba0229baa17831582befb046ace167b368140dae022d0b89b8d586ba12c"}, - {file = "pyqwest-0.10.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:eff9ccf427604d34c635954def07b6113d4754f968073eef2df40bdb80b05bf5"}, - {file = "pyqwest-0.10.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78662158093f9d5c742368f4dd9956aa595f44c6ac0860777c98853ddd5e1610"}, - {file = "pyqwest-0.10.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0879a3f0b37876372aa328b9fee956165db174c1ab72464146fe515f49399ddb"}, - {file = "pyqwest-0.10.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:850b8de6ade09a60bdb2f969871a177c2c304b594b2034ba3f5962c7bea75551"}, - {file = "pyqwest-0.10.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:399802647ea646c6ac9b5460e541b7c209b7a13563c667b2690ded2060185f2e"}, - {file = "pyqwest-0.10.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c26f3de1feb5d066d7a66802a47407a93ba043696064ad80beda4a0a4bf10056"}, - {file = "pyqwest-0.10.0.tar.gz", hash = "sha256:6c1a693be17d57d2c2eca4085e32c2809c53090c16719a907c90ebcf1f40dc01"}, -] - -[package.dependencies] -opentelemetry-api = ">=1.39.1" - -[[package]] -name = "pyroaring" -version = "1.0.3" -description = "Library for handling efficiently sorted integer sets." -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "pyroaring-1.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c10e4cfbe203a578c78808406af491e3615d5e46cf69a7709050243346cd68bc"}, - {file = "pyroaring-1.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cc329c62e504f2531c4008240f31736bcd2dee4339071f1eac0648068e6d17fa"}, - {file = "pyroaring-1.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8c7fb6ddf6ef31148f0939bc5c26b681d63df301ee1e372525012dd7bfe4a30a"}, - {file = "pyroaring-1.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd18446832ea04a7d33bd6b78270b0be14eabcda5937af3428d6cb3d2bf98e54"}, - {file = "pyroaring-1.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f0cbc766df2a24e28f23d69b66bbec64e691799219fd82c2f2236f03fc88e2e"}, - {file = "pyroaring-1.0.3-cp310-cp310-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:96a51e96f8f473381615f0f852f7238ad0a47f28e4a35e9f082468c5cfe4e9c3"}, - {file = "pyroaring-1.0.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:654af38b1f1c9bdc27b4f6d331fc5d91599df96e72a6df1886f4d95eea60ab29"}, - {file = "pyroaring-1.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6721036afa31c07bdcbb4fcafa166660cf9c2eac695dcd495f8778549fa55899"}, - {file = "pyroaring-1.0.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:0caa10f20329d09233fac6550b2adce4d9f173f748a9a9a5ea3b7033827dfe2d"}, - {file = "pyroaring-1.0.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f109be8af937e85c52cb920d3fd120db52b172f59460852d2e3d2e3d13a4f52a"}, - {file = "pyroaring-1.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ddc80bfcd313c7c524a2742d263e73cae088b6a611b77dcc46fa90c306f6dace"}, - {file = "pyroaring-1.0.3-cp310-cp310-win32.whl", hash = "sha256:5a183f5ec069757fe5b60e37f7c6fa8a53178eacf0d76601b739e2890edee036"}, - {file = "pyroaring-1.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:051bd9a66ce855a1143faa2b879ea6c6ca2905209e172ce9eedf79834897c730"}, - {file = "pyroaring-1.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:3043ff5c85375310ca3cd3e01944e03026e0ec07885e52dfabcfcd9dc303867f"}, - {file = "pyroaring-1.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:755cdac1f9a1b7b5c621e570d4f6dbcf3b8e4a1e35a66f976104ecb35dce4ed2"}, - {file = "pyroaring-1.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ebab073db620f26f0ba11e13fa2f35e3b1298209fba47b6bc8cb6f0e2c9627f9"}, - {file = "pyroaring-1.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:684fb8dffe19bdb7f91897c65eac6eee23b1e46043c47eb24288f28a1170fe04"}, - {file = "pyroaring-1.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:678d31fc24e82945a1bfb14816c77823983382ffea76985d494782aa2f058427"}, - {file = "pyroaring-1.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d815f624e0285db3669f673d1725cb754b120ec70d0032d7c7166103a96c96d"}, - {file = "pyroaring-1.0.3-cp311-cp311-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:57fd5b80dacb8e888402b6b7508a734c6a527063e4e24e882ff2e0fd90721ada"}, - {file = "pyroaring-1.0.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab26a7a45a0bb46c00394d1a60a9f2d57c220f84586e30d59b39784b0f94aee6"}, - {file = "pyroaring-1.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9232f3f606315d59049c128154100fd05008d5c5c211e48b21848cd41ee64d26"}, - {file = "pyroaring-1.0.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:f34b44b3ec3df97b978799f2901fefb2a48d367496fd1cde3cc5fe8b3bc13510"}, - {file = "pyroaring-1.0.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:25a83ec6bac3106568bd3fdd316f0fee52aa0be8c72da565ad02b10ae7905924"}, - {file = "pyroaring-1.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c17d4ec53b5b6b333d9a9515051213a691293ada785dc8c025d3641482597ed3"}, - {file = "pyroaring-1.0.3-cp311-cp311-win32.whl", hash = "sha256:d54024459ace600f1d1ffbc6dc3c60eb47cca3b678701f06148f59e10f6f8d7b"}, - {file = "pyroaring-1.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:c28750148ef579a7447a8cb60b39e5943e03f8c29bce8f2788728f6f23d1887a"}, - {file = "pyroaring-1.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:535d8deccbd8db2c6bf38629243e9646756905574a742b2a72ff51d6461d616c"}, - {file = "pyroaring-1.0.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:add3e4c78eb590a76526ecce8d1566eecdd5822e351c36b3697997f4a80ed808"}, - {file = "pyroaring-1.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ebaffe846cf4ba4f00ce6b8a9f39613f24e2d09447e77be4fa6e898bc36451b6"}, - {file = "pyroaring-1.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a9459f27498f97d08031a34a5ead230b77eb0ab3cc3d85b7f54faa2fd548acd6"}, - {file = "pyroaring-1.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2b2eb8bd1c35c772994889be9f7dda09477475d7aa1e2af9ab4ef18619326f6"}, - {file = "pyroaring-1.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d31f4c1c906f1af14ce61a3959d04a14a64c594f8a768399146a45bbd341f21f"}, - {file = "pyroaring-1.0.3-cp312-cp312-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53be988fc86698d56c11049bfe5113a2f6990adb1fa2782b29636509808b6aa7"}, - {file = "pyroaring-1.0.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7df84d223424523b19a23781f4246cc247fd6d821e1bc0853c2f25669136f7d0"}, - {file = "pyroaring-1.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:34a781f1f9766897f63ef18be129827340ae37764015b83fdcff1efb9e29136d"}, - {file = "pyroaring-1.0.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:1f414343b4ed0756734328cdf2a91022fc54503769e3f8d79bd0b672ea815a16"}, - {file = "pyroaring-1.0.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d16ae185c72dc64f76335dbe53e53a892e78115adc92194957d1b7ef74d230b9"}, - {file = "pyroaring-1.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f888447bf22dde7759108bfe6dfbeb6bbb61b14948de9c4cb6843c4dd57e2215"}, - {file = "pyroaring-1.0.3-cp312-cp312-win32.whl", hash = "sha256:fbbdc44c51a0a3efd7be3dbe04466278ce098fcd101aa1905849319042159770"}, - {file = "pyroaring-1.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:3b217c4b3ad953b4c759a0d2f9bd95316f0c345b9f7adb49e6ded7a1f5106bd4"}, - {file = "pyroaring-1.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:e6bcf838564c21bab8fe6c2748b4990d4cd90612d8c470c04889def7bb5114ea"}, - {file = "pyroaring-1.0.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:20bc947054b197d1baa76cd05d70b8e04f95b82e698266e2f8f2f4b36d764477"}, - {file = "pyroaring-1.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ba5909b4c66bb85cab345e2f3a87e5ce671509c94b8c9823d8db64e107cbe854"}, - {file = "pyroaring-1.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b744746ba5da27fad760067f12633f5d384db6a1e65648d00244ceacbbd87731"}, - {file = "pyroaring-1.0.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b16c2a2791a5a09c4b59c0e1069ac1c877d0df25cae3155579c7eac8844676e"}, - {file = "pyroaring-1.0.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7f68dfcf8d01177267f4bc06c4960fe8e39577470d1b52c9af8b61a72ca8767"}, - {file = "pyroaring-1.0.3-cp313-cp313-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:dba4e4700030182a981a3c887aa73887697145fc9ffb192f908aa59b718fbbdd"}, - {file = "pyroaring-1.0.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e26dd1dc1edba02288902914bdb559e53e346e9155defa43c31fcab831b55342"}, - {file = "pyroaring-1.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6eb98d2cacfc6d51c6a69893f04075e07b3df761eac71ba162c43b9b4c4452ad"}, - {file = "pyroaring-1.0.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a967e9eddb9485cbdd95d6371e3dada67880844d836c0283d3b11efe9225d1b7"}, - {file = "pyroaring-1.0.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b12ef7f992ba7be865f91c7c098fd8ac6c413563aaa14d5b1e2bcb8cb43a4614"}, - {file = "pyroaring-1.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:82ca5be174b85c40be7b00bc6bf39b2931a1b4a465f3af17ec6b9c48e9aa6fe0"}, - {file = "pyroaring-1.0.3-cp313-cp313-win32.whl", hash = "sha256:f758c681e63ffe74b20423695e71f0410920f41b075cee679ffb5bc2bf38440b"}, - {file = "pyroaring-1.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:428c3bb384fe4c483feb5cf7aa3aef1621fb0a5c4f3d391da67b2c4a43f08a10"}, - {file = "pyroaring-1.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:9c0c856e8aa5606e8aed5f30201286e404fdc9093f81fefe82d2e79e67472bb2"}, - {file = "pyroaring-1.0.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6321a95b5b2ba69aa32e920dd1aa7f8fc4fac55b75981978aa4f2378724dee27"}, - {file = "pyroaring-1.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:054eb6ef04ff9d2ed3ddd18ae21e5e51e02d0f8cdd7e5cb948648f77ddb04ea2"}, - {file = "pyroaring-1.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4d064aea3827e63eb60294ae3e6623e29613f5c8844869646d06f3735a425dd9"}, - {file = "pyroaring-1.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c84d5b17ef628c3956d9a79c2f78c5bea7dda6f7aeb01f34671034d2650b9efb"}, - {file = "pyroaring-1.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8038f7dd25eb83c277b8e0ea14c5e61f085cc76bd0c6b9f6679f1770e33541ec"}, - {file = "pyroaring-1.0.3-cp38-cp38-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:defc508ef7acaf58d07e603c55feda6742c4034f5262cfd616f92cc3adbc2815"}, - {file = "pyroaring-1.0.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd0831326971b0ffa08ccce79abe7c2450d5d9254804d855e23a8ba31f70351a"}, - {file = "pyroaring-1.0.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:03e063329481396cbb70f1ce8b8ca0f01d74a45ee9d908b6645b0282b23832b0"}, - {file = "pyroaring-1.0.3-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:7a1b1c82d2da0bedc7c22d4047bd62544ef0e25c6be86ccf4b9d1ccc38876ee8"}, - {file = "pyroaring-1.0.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:dd7f9e5b7366b8f9bafca2a0fcf83fa534a00cc12d4ca01e301d8662bcdb805c"}, - {file = "pyroaring-1.0.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a5a1db84e0952805223a7bf77eae58384b700a6b9affc53fb9772dddf868c712"}, - {file = "pyroaring-1.0.3-cp38-cp38-win32.whl", hash = "sha256:54cb0c2bddd330e22099773c4681aca90847265afe56a9201a92c1a758494261"}, - {file = "pyroaring-1.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:47d985293f861df1f2b03b41cef4fd3249c1c9608081750bcf3153051c2312d0"}, - {file = "pyroaring-1.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d46eb5db78b673d8d8ca83651a1cce1e15eec5a922f2951b1f61014463b72af5"}, - {file = "pyroaring-1.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ce202452de2b58bffa3eb02e27c681eefcfb54e27f8ef85b5c93ebaada50f3f3"}, - {file = "pyroaring-1.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:531b6ae56989b61742dde1b64fedc5537acc046cf04a333548322366c1bf3922"}, - {file = "pyroaring-1.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3035db9459bd8635a0145b4a9e3102869d621cb0b3648051115f06d31ffd1976"}, - {file = "pyroaring-1.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c8fb6b0ad0e8db1b9559b2da180b103b48adddf0e4f24404269e2a3b5db268d"}, - {file = "pyroaring-1.0.3-cp39-cp39-manylinux_2_24_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:8d5df95d9511bc83048da9348c7ab1c20f97ff4d95faf27ee1fdf2e8a96e200e"}, - {file = "pyroaring-1.0.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65d2d81e5aed7698fab23058db70fb2b65fad221090be037a0af498569109915"}, - {file = "pyroaring-1.0.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e195636034a0b62ec0e5325ed2f610f39cc8955ace3f47a5bc7f484159f02341"}, - {file = "pyroaring-1.0.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:bb7f2561e3ec26c3c869458431cbcba6b83f7e925b024460c136dbb5fadf3b31"}, - {file = "pyroaring-1.0.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:8e996939de01f448eb9448d91b47ab60bff0555c2a80d5c12a8405814072cd35"}, - {file = "pyroaring-1.0.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c656d62d0cf96ede0edc4e7d392889238777bdf88b32afd5d51c3cab016c29a0"}, - {file = "pyroaring-1.0.3-cp39-cp39-win32.whl", hash = "sha256:a7a7d14822c64841ae64e98309697e1631ebadba55ded33daa7cd16d1b487d11"}, - {file = "pyroaring-1.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:a86b88adbe0531b75f94f87279a6d4ee68e63335e29bbdab4400a05704fc2587"}, - {file = "pyroaring-1.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:1ed2e9c7af46052466b5fa0392fe540331474718d97b9756cefa23233bfdb3ea"}, - {file = "pyroaring-1.0.3.tar.gz", hash = "sha256:cd7392d1c010c9e41c11c62cd0610c8852e7e9698b1f7f6c2fcdefe50e7ef6da"}, -] - -[[package]] -name = "pytest" -version = "9.1.1" -description = "pytest: simple powerful testing with Python" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"test\"" -files = [ - {file = "pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c"}, - {file = "pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313"}, -] - -[package.dependencies] -colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} -exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} -iniconfig = ">=1.0.1" -packaging = ">=22" -pluggy = ">=1.5,<2" -pygments = ">=2.7.2" -tomli = {version = ">=1", markers = "python_version < \"3.11\""} - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-asyncio" -version = "1.4.0" -description = "Pytest support for asyncio" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"test\"" -files = [ - {file = "pytest_asyncio-1.4.0-py3-none-any.whl", hash = "sha256:933ca923a23075a87fb7070c0ec272a6848489824d887c85c812670932835aa1"}, - {file = "pytest_asyncio-1.4.0.tar.gz", hash = "sha256:c6c0d2259945122819f171a32ecea2c349ead889ee28176caaf492143424be42"}, -] - -[package.dependencies] -backports-asyncio-runner = {version = ">=1.1,<2", markers = "python_version < \"3.11\""} -pytest = ">=8.4,<10" -typing-extensions = {version = ">=4.12", markers = "python_version < \"3.13\""} - -[package.extras] -docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1)", "sphinx-tabs (>=3.5)"] -testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] - [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -7471,7 +5754,7 @@ description = "Python interpreter discovery" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "python_discovery-1.1.0-py3-none-any.whl", hash = "sha256:a162893b8809727f54594a99ad2179d2ede4bf953e12d4c7abc3cc9cdbd1437b"}, {file = "python_discovery-1.1.0.tar.gz", hash = "sha256:447941ba1aed8cc2ab7ee3cb91be5fc137c5bdbb05b7e6ea62fbdcb66e50b268"}, @@ -7492,7 +5775,7 @@ description = "Read key-value pairs from a .env file and set them as environment optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a"}, {file = "python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3"}, @@ -7508,7 +5791,7 @@ description = "JSON Log Formatter for the Python Logging Package" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2"}, {file = "python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f"}, @@ -7524,38 +5807,12 @@ description = "A streaming multipart parser for Python" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155"}, {file = "python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58"}, ] -[[package]] -name = "pytz" -version = "2026.3.post1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "pytz-2026.3.post1-py2.py3-none-any.whl", hash = "sha256:dd95840dd199baea12d9cc096a1d452caa6596a1c1e4b5f3dbd1541855d5e815"}, - {file = "pytz-2026.3.post1.tar.gz", hash = "sha256:2211d3fcf9a797d3405cac96ac7f61d80e6a644f72a3309607282fe8a2010c5d"}, -] - -[[package]] -name = "pyvers" -version = "0.2.3" -description = "A Python library for managing multiple versions of dependencies" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "pyvers-0.2.3-py3-none-any.whl", hash = "sha256:6f5b5612f2f4bd08caa49baa70fc5f875fc7da701a5385c13e244eea6b8114dd"}, - {file = "pyvers-0.2.3.tar.gz", hash = "sha256:c4b81c3a033963245e124cdecb052783c9c4cea3bb08c051833af1c44faa6283"}, -] - [[package]] name = "pywin32" version = "311" @@ -7563,7 +5820,7 @@ description = "Python for Window Extensions" optional = true python-versions = "*" groups = ["main"] -markers = "sys_platform == \"win32\" and (extra == \"rl\" or extra == \"async-rl\")" +markers = "extra == \"vllm\" and sys_platform == \"win32\"" files = [ {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, @@ -7674,9 +5931,10 @@ files = [ name = "pyzmq" version = "27.1.0" description = "Python bindings for 0MQ" -optional = false +optional = true python-versions = ">=3.8" groups = ["main"] +markers = "extra == \"vllm\"" files = [ {file = "pyzmq-27.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:508e23ec9bc44c0005c4946ea013d9317ae00ac67778bd47519fdf5a0e930ff4"}, {file = "pyzmq-27.1.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:507b6f430bdcf0ee48c0d30e734ea89ce5567fd7b8a0f0044a369c176aa44556"}, @@ -7782,7 +6040,7 @@ description = "Ray provides a simple, universal API for building distributed app optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "ray-2.54.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:a22937f09ee74a43171df338d84b45ef882c1c05748947ca9d5343a44d4b9379"}, {file = "ray-2.54.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:1e63e491155695d527513ffe9d33a6aeb3f3cdccb6309adadfd6f8dd7c0300f7"}, @@ -7802,71 +6060,34 @@ files = [ ] [package.dependencies] -aiohttp = [ - {version = ">=3.13.3", optional = true, markers = "extra == \"serve\""}, - {version = ">=3.13.3", optional = true, markers = "extra == \"default\""}, -] -aiohttp_cors = [ - {version = "*", optional = true, markers = "extra == \"serve\""}, - {version = "*", optional = true, markers = "extra == \"default\""}, -] +aiohttp = {version = ">=3.13.3", optional = true, markers = "extra == \"serve\""} +aiohttp_cors = {version = "*", optional = true, markers = "extra == \"serve\""} click = ">=7.0" -colorful = [ - {version = "*", optional = true, markers = "extra == \"serve\""}, - {version = "*", optional = true, markers = "extra == \"default\""}, -] +colorful = {version = "*", optional = true, markers = "extra == \"serve\""} cupy-cuda12x = {version = "*", optional = true, markers = "sys_platform != \"darwin\" and extra == \"cgraph\""} fastapi = {version = "*", optional = true, markers = "extra == \"serve\""} filelock = "*" -grpcio = [ - {version = ">=1.42.0", optional = true, markers = "extra == \"serve\""}, - {version = ">=1.42.0", optional = true, markers = "extra == \"default\""}, -] +grpcio = {version = ">=1.42.0", optional = true, markers = "extra == \"serve\""} jsonschema = "*" msgpack = ">=1.0.0,<2.0.0" -opencensus = [ - {version = "*", optional = true, markers = "extra == \"serve\""}, - {version = "*", optional = true, markers = "extra == \"default\""}, -] -opentelemetry-exporter-prometheus = [ - {version = "*", optional = true, markers = "extra == \"serve\""}, - {version = "*", optional = true, markers = "extra == \"default\""}, -] -opentelemetry-proto = [ - {version = "*", optional = true, markers = "extra == \"serve\""}, - {version = "*", optional = true, markers = "extra == \"default\""}, -] -opentelemetry-sdk = [ - {version = ">=1.30.0", optional = true, markers = "extra == \"serve\""}, - {version = ">=1.30.0", optional = true, markers = "extra == \"default\""}, -] +opencensus = {version = "*", optional = true, markers = "extra == \"serve\""} +opentelemetry-exporter-prometheus = {version = "*", optional = true, markers = "extra == \"serve\""} +opentelemetry-proto = {version = "*", optional = true, markers = "extra == \"serve\""} +opentelemetry-sdk = {version = ">=1.30.0", optional = true, markers = "extra == \"serve\""} packaging = ">=24.2" -prometheus_client = [ - {version = ">=0.7.1", optional = true, markers = "extra == \"serve\""}, - {version = ">=0.7.1", optional = true, markers = "extra == \"default\""}, -] +prometheus_client = {version = ">=0.7.1", optional = true, markers = "extra == \"serve\""} protobuf = ">=3.20.3" py-spy = [ {version = ">=0.2.0", optional = true, markers = "python_version < \"3.12\" and extra == \"serve\""}, - {version = ">=0.2.0", optional = true, markers = "python_version < \"3.12\" and extra == \"default\""}, {version = ">=0.4.0", optional = true, markers = "python_version >= \"3.12\" and extra == \"serve\""}, ] -pydantic = [ - {version = "<2.0.dev0 || >=2.12.dev0,<3", optional = true, markers = "extra == \"serve\""}, - {version = "<2.0.dev0 || >=2.12.dev0,<3", optional = true, markers = "extra == \"default\""}, -] +pydantic = {version = "<2.0.dev0 || >=2.12.dev0,<3", optional = true, markers = "extra == \"serve\""} pyyaml = "*" requests = "*" -smart_open = [ - {version = "*", optional = true, markers = "extra == \"serve\""}, - {version = "*", optional = true, markers = "extra == \"default\""}, -] +smart_open = {version = "*", optional = true, markers = "extra == \"serve\""} starlette = {version = "*", optional = true, markers = "extra == \"serve\""} uvicorn = {version = "*", extras = ["standard"], optional = true, markers = "extra == \"serve\""} -virtualenv = [ - {version = ">=20.0.24,<20.21.1 || >20.21.1", optional = true, markers = "extra == \"serve\""}, - {version = ">=20.0.24,<20.21.1 || >20.21.1", optional = true, markers = "extra == \"default\""}, -] +virtualenv = {version = ">=20.0.24,<20.21.1 || >20.21.1", optional = true, markers = "extra == \"serve\""} watchfiles = {version = "*", optional = true, markers = "extra == \"serve\""} [package.extras] @@ -7906,30 +6127,6 @@ commonmark = ">=0.8.1" docutils = ">=0.11" sphinx = ">=1.3.1" -[[package]] -name = "redis" -version = "8.1.0" -description = "Python client for Redis database and key-value store" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"server\"" -files = [ - {file = "redis-8.1.0-py3-none-any.whl", hash = "sha256:a4fe1aac3d3b3cc791d4b3d5931c5a956045dc951ee74d1c913ee3ac4d2ee9fb"}, - {file = "redis-8.1.0.tar.gz", hash = "sha256:6e1a19beef9225c83efd689c7e6b7da2d5215b1f42cd13b7fc3714d0a09c7b25"}, -] - -[package.dependencies] -async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} - -[package.extras] -circuit-breaker = ["pybreaker (>=1.4.0)"] -hiredis = ["hiredis (>=3.2.0)"] -jwt = ["pyjwt (>=2.13.0)"] -ocsp = ["cryptography (>=36.0.1)", "pyopenssl (>=20.0.1)", "requests (>=2.31.0)"] -otel = ["opentelemetry-api (>=1.39.1)", "opentelemetry-exporter-otlp-proto-http (>=1.39.1)", "opentelemetry-sdk (>=1.39.1)"] -xxhash = ["xxhash (>=3.6.0,<3.7.0)"] - [[package]] name = "referencing" version = "0.37.0" @@ -7937,7 +6134,7 @@ description = "JSON Referencing + Python" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231"}, {file = "referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8"}, @@ -8098,9 +6295,10 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "rich" version = "14.3.3" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -optional = false +optional = true python-versions = ">=3.8.0" groups = ["main"] +markers = "extra == \"vllm\" or extra == \"tinker\"" files = [ {file = "rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d"}, {file = "rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b"}, @@ -8120,7 +6318,7 @@ description = "Rich toolkit for building command-line applications" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "rich_toolkit-0.19.7-py3-none-any.whl", hash = "sha256:0288e9203728c47c5a4eb60fd2f0692d9df7455a65901ab6f898437a2ba5989d"}, {file = "rich_toolkit-0.19.7.tar.gz", hash = "sha256:133c0915872da91d4c25d85342d5ec1dfacc69b63448af1a08a0d4b4f23ef46e"}, @@ -8138,7 +6336,7 @@ description = "Python Bindings for the ignore crate" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "rignore-0.7.6-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f3c74a7e5ee77aea669c95fdb3933f2a6c7549893700082e759128a29cf67e45"}, {file = "rignore-0.7.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7202404958f5fe3474bac91f65350f0b1dde1a5e05089f2946549b7e91e79ec"}, @@ -8296,40 +6494,6 @@ files = [ {file = "rignore-0.7.6.tar.gz", hash = "sha256:00d3546cd793c30cb17921ce674d2c8f3a4b00501cb0e3dd0e82217dbeba2671"}, ] -[[package]] -name = "rouge-chinese" -version = "1.0.3" -description = "Python ROUGE Score Implementation for Chinese Language Task (official rouge score)" -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "rouge_chinese-1.0.3-py3-none-any.whl", hash = "sha256:afda22cb64f9a0f1d7a19e88d7cd9acfd2c1f5d45bf463ade7ecadf87f30624d"}, - {file = "rouge_chinese-1.0.3.tar.gz", hash = "sha256:4074de21b01a83ca6032fe6d6354c5f618a305da60c994294133be2abf030f4a"}, -] - -[package.dependencies] -six = "*" - -[[package]] -name = "rouge-score" -version = "0.1.2" -description = "Pure python implementation of ROUGE-1.5.5." -optional = true -python-versions = ">=3.7" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "rouge_score-0.1.2.tar.gz", hash = "sha256:c7d4da2683e68c9abf0135ef915d63a46643666f848e558a1b9f7ead17ff0f04"}, -] - -[package.dependencies] -absl-py = "*" -nltk = "*" -numpy = "*" -six = ">=1.14.0" - [[package]] name = "rpds-py" version = "0.30.0" @@ -8337,7 +6501,7 @@ description = "Python bindings to Rust's persistent data structures (rpds)" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "rpds_py-0.30.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:679ae98e00c0e8d68a7fda324e16b90fd5260945b45d3b824c892cec9eea3288"}, {file = "rpds_py-0.30.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4cc2206b76b4f576934f0ed374b10d7ca5f457858b157ca52064bdfc26b9fc00"}, @@ -8463,7 +6627,7 @@ description = "Pure-Python RSA implementation" optional = true python-versions = "<4,>=3.6" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "rsa-4.9.1-py3-none-any.whl", hash = "sha256:68635866661c6836b8d39430f97a996acbd61bfa49406748ea243539fe239762"}, {file = "rsa-4.9.1.tar.gz", hash = "sha256:e7bdbfdb5497da4c07dfd35530e1a902659db6ff241e39d9953cad06ebd0ae75"}, @@ -8472,32 +6636,6 @@ files = [ [package.dependencies] pyasn1 = ">=0.1.3" -[[package]] -name = "sacrebleu" -version = "2.6.0" -description = "Hassle-free computation of shareable, comparable, and reproducible BLEU, chrF, and TER scores" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "sacrebleu-2.6.0-py3-none-any.whl", hash = "sha256:3edc1531575cfe4ad04ce53491a9307e234af1c3f805a1f491cbec844229a8a8"}, - {file = "sacrebleu-2.6.0.tar.gz", hash = "sha256:91499b6cd46138d95154fff1e863c2f9be57e82f0c719d8dd718d0006cf6c566"}, -] - -[package.dependencies] -colorama = "*" -lxml = "*" -numpy = ">=1.17" -portalocker = "*" -regex = "*" -tabulate = ">=0.8.9" - -[package.extras] -dev = ["lxml-stubs", "mypy", "pytest", "setuptools", "types-tabulate", "wheel"] -ja = ["ipadic (>=1.0,<2.0)", "mecab-python3 (>=1.0.9,<2.0.0)"] -ko = ["mecab-ko (>=1.0.2,<2.0.0)", "mecab-ko-dic (>=1.0,<2.0)"] - [[package]] name = "safetensors" version = "0.7.0" @@ -8545,71 +6683,6 @@ testing = ["h5py (>=3.7.0)", "huggingface-hub (>=0.12.1)", "hypothesis (>=6.70.2 testingfree = ["huggingface-hub (>=0.12.1)", "hypothesis (>=6.70.2)", "pytest (>=7.2.0)", "pytest-benchmark (>=4.0.0)", "safetensors[numpy]", "setuptools-rust (>=1.5.2)"] torch = ["packaging", "safetensors[numpy]", "torch (>=1.10)"] -[[package]] -name = "scipy" -version = "1.15.3" -description = "Fundamental algorithms for scientific computing in Python" -optional = false -python-versions = ">=3.10" -groups = ["main"] -markers = "python_version == \"3.10\"" -files = [ - {file = "scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c"}, - {file = "scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253"}, - {file = "scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f"}, - {file = "scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92"}, - {file = "scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82"}, - {file = "scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40"}, - {file = "scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e"}, - {file = "scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c"}, - {file = "scipy-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13"}, - {file = "scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b"}, - {file = "scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba"}, - {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65"}, - {file = "scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1"}, - {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889"}, - {file = "scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982"}, - {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9"}, - {file = "scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594"}, - {file = "scipy-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb"}, - {file = "scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019"}, - {file = "scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6"}, - {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477"}, - {file = "scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c"}, - {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45"}, - {file = "scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49"}, - {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e"}, - {file = "scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539"}, - {file = "scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed"}, - {file = "scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759"}, - {file = "scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62"}, - {file = "scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb"}, - {file = "scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730"}, - {file = "scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825"}, - {file = "scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7"}, - {file = "scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11"}, - {file = "scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126"}, - {file = "scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163"}, - {file = "scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8"}, - {file = "scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5"}, - {file = "scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e"}, - {file = "scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb"}, - {file = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723"}, - {file = "scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb"}, - {file = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4"}, - {file = "scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5"}, - {file = "scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca"}, - {file = "scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf"}, -] - -[package.dependencies] -numpy = ">=1.23.5,<2.5" - -[package.extras] -dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"] -doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "matplotlib (>=3.5)", "myst-nb", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.0.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"] -test = ["Cython", "array-api-strict (>=2.0,<2.1.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] - [[package]] name = "scipy" version = "1.17.1" @@ -8617,7 +6690,6 @@ description = "Fundamental algorithms for scientific computing in Python" optional = false python-versions = ">=3.11" groups = ["main"] -markers = "python_version >= \"3.11\"" files = [ {file = "scipy-1.17.1-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:1f95b894f13729334fb990162e911c9e5dc1ab390c58aa6cbecb389c5b5e28ec"}, {file = "scipy-1.17.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:e18f12c6b0bc5a592ed23d3f7b891f68fd7f8241d69b7883769eb5d5dfb52696"}, @@ -8697,7 +6769,7 @@ description = "Unsupervised text tokenizer and detokenizer." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "sentencepiece-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e10fa50bdbaa5e2445dbd387979980d391760faf0ec99a09bd7780ff37eaec44"}, {file = "sentencepiece-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f27ae6deea72efdb6f361750c92f6c21fd0ad087445082770cc34015213c526"}, @@ -8777,7 +6849,7 @@ description = "Python client for Sentry (https://sentry.io)" optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "sentry_sdk-2.53.0-py2.py3-none-any.whl", hash = "sha256:46e1ed8d84355ae54406c924f6b290c3d61f4048625989a723fd622aab838899"}, {file = "sentry_sdk-2.53.0.tar.gz", hash = "sha256:6520ef2c4acd823f28efc55e43eb6ce2e6d9f954a95a3aa96b6fd14871e92b77"}, @@ -8841,7 +6913,7 @@ description = "A Python module to customize the process title" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "setproctitle-1.3.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cf555b6299f10a6eb44e4f96d2f5a3884c70ce25dc5c8796aaa2f7b40e72cb1b"}, {file = "setproctitle-1.3.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:690b4776f9c15aaf1023bb07d7c5b797681a17af98a4a69e76a1d504e41108b7"}, @@ -8952,7 +7024,7 @@ description = "Easily download, build, install, upgrade, and uninstall Python pa optional = false python-versions = ">=3.9" groups = ["main"] -markers = "python_full_version == \"3.13.0\" or python_version == \"3.12\"" +markers = "python_version == \"3.12\"" files = [ {file = "setuptools-80.10.2-py3-none-any.whl", hash = "sha256:95b30ddfb717250edb492926c92b5221f7ef3fbcc2b07579bcd4a27da21d0173"}, {file = "setuptools-80.10.2.tar.gz", hash = "sha256:8b0e9d10c784bf7d262c4e5ec5d4ec94127ce206e8738f29a437945fbc219b70"}, @@ -8974,6 +7046,7 @@ description = "Easily download, build, install, upgrade, and uninstall Python pa optional = false python-versions = ">=3.9" groups = ["main"] +markers = "python_version == \"3.11\"" files = [ {file = "setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0"}, {file = "setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb"}, @@ -8992,9 +7065,10 @@ type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.deve name = "shellingham" version = "1.5.4" description = "Tool to Detect Surrounding Shell" -optional = false +optional = true python-versions = ">=3.7" groups = ["main"] +markers = "extra == \"vllm\"" files = [ {file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"}, {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, @@ -9139,7 +7213,7 @@ description = "Utils for streaming large files (S3, HDFS, GCS, SFTP, Azure Blob optional = true python-versions = "<4.0,>=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "smart_open-7.5.1-py3-none-any.whl", hash = "sha256:3e07cbbd9c8a908bcb8e25d48becf1a5cbb4886fa975e9f34c672ed171df2318"}, {file = "smart_open-7.5.1.tar.gz", hash = "sha256:3f08e16827c4733699e6b2cc40328a3568f900cb12ad9a3ad233ba6c872d9fe7"}, @@ -9166,7 +7240,7 @@ description = "Sniff out which async library your code is running under" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"client\"" +markers = "extra == \"vllm\" or extra == \"tinker\"" files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -9475,7 +7549,7 @@ description = "SSE plugin for Starlette" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "sse_starlette-3.3.2-py3-none-any.whl", hash = "sha256:5c3ea3dad425c601236726af2f27689b74494643f57017cafcb6f8c9acfbb862"}, {file = "sse_starlette-3.3.2.tar.gz", hash = "sha256:678fca55a1945c734d8472a6cad186a55ab02840b4f6786f5ee8770970579dcd"}, @@ -9517,7 +7591,7 @@ description = "A system for controlling process state under UNIX" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "supervisor-4.3.0-py2.py3-none-any.whl", hash = "sha256:0bcb763fddafba410f35cbde226aa7f8514b9fb82eb05a0c85f6588d1c13f8db"}, {file = "supervisor-4.3.0.tar.gz", hash = "sha256:4a2bf149adf42997e1bb44b70c43b613275ec9852c3edacca86a9166b27e945e"}, @@ -9526,44 +7600,6 @@ files = [ [package.extras] test = ["pytest", "pytest-cov"] -[[package]] -name = "swanlab" -version = "0.10.0" -description = "Python library for streamlined tracking and management of AI training processes." -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "swanlab-0.10.0-py3-none-any.whl", hash = "sha256:5467143d68925ee0968e3409174fbf25958a7736b0c6f347c90aabaf257f9057"}, - {file = "swanlab-0.10.0.tar.gz", hash = "sha256:746ca2798a4ca40a5d0cb2535993b0f4c88348b7a182da813a4b45feda24eef9"}, -] - -[package.dependencies] -click = "*" -nvidia-ml-py = "*" -orjson = {version = "*", markers = "python_version > \"3.9\""} -platformdirs = ">=4.2.0" -protobuf = {version = ">=6.31.1,<7", markers = "python_version > \"3.9\" or sys_platform != \"linux\""} -psutil = ">=5.0.0" -pwinput = ">=1.0.3" -pydantic = ">=2.0,<3.0" -pydantic-settings = ">=2.8.1" -pyecharts = ">=2.0.0" -pyroaring = {version = ">=1.0.0,<1.0.4", markers = "python_version < \"3.14\""} -pyyaml = "*" -requests = ">=2.28.0" -rich = ">=13.6.0" -setuptools = "*" -urllib3 = ">=1.26.0" -watchdog = "*" -wrapt = ">=1.17.0" - -[package.extras] -dashboard = ["swanboard (==0.1.10b2)"] -media = ["imageio[ffmpeg]", "matplotlib", "moviepy", "numpy", "pillow", "rdkit (<=2023.9.6) ; python_version == \"3.9\"", "rdkit (>=2025.9.6) ; python_version > \"3.9\"", "soundfile"] -s3 = ["boto3 (>=1.35.49)"] - [[package]] name = "sympy" version = "1.14.0" @@ -9589,7 +7625,7 @@ description = "Pretty-print tabular data" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, @@ -9598,85 +7634,6 @@ files = [ [package.extras] widechars = ["wcwidth"] -[[package]] -name = "tensordict" -version = "0.14.2" -description = "TensorDict is a pytorch dedicated tensor container." -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "tensordict-0.14.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:9e4650b76d4e0672cf9c0320225b21434a589f4629d5836114019335875ffee9"}, - {file = "tensordict-0.14.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:b9963fdd3bdcfea7919eea15208d5730c7862bcb028efd26fb46b6072a2abc79"}, - {file = "tensordict-0.14.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:404f47a5d024e1215792a920d7a742402981e907bc8a0c86f374358e719fefb3"}, - {file = "tensordict-0.14.2-cp310-cp310-win_amd64.whl", hash = "sha256:45c851e2b884c2e63180d75a82599ccb343b816a4ab3da4b28290695726184df"}, - {file = "tensordict-0.14.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:e2ac08238d0404a7f17f938331918c9bea026123bc7df4c07f2ce52b3068953f"}, - {file = "tensordict-0.14.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:001c62b1b9b7305077f29ab4e1a06693f1a7add7bfb2cd42d03b2172f185d425"}, - {file = "tensordict-0.14.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:002ce1387d1b6bb2ee29affbb68aaae4c79fa8773137bef88534fc2fadefca2f"}, - {file = "tensordict-0.14.2-cp311-cp311-win_amd64.whl", hash = "sha256:0d1f8f949db128b896b9cb022de532d3d87902811d2751c11f52270a27eabd9a"}, - {file = "tensordict-0.14.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:0e8b65def0da306741d262976e7613afb2079e8b521b6be910edd8080a33c265"}, - {file = "tensordict-0.14.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:1553be455faf595bdc0e2b18649ca8791728ea13359805c22fe8c2aff6bd8fd0"}, - {file = "tensordict-0.14.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:0a748755bfb35db40123bcda67bfebac0138283d25deda76fe30be58ce10c247"}, - {file = "tensordict-0.14.2-cp312-cp312-win_amd64.whl", hash = "sha256:5e676f6048c4e3ad53de379469270545526d6a19badbc48bd5870b68c64e84f4"}, - {file = "tensordict-0.14.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c5e4aa2a4a8b4b1370828186836fad9605f2091a3fa3e009b15423d787aaed3"}, - {file = "tensordict-0.14.2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:7d79bf7bcbdf6b0686ba756debffe9b73de9686e9fa5923747538408f130df9d"}, - {file = "tensordict-0.14.2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:75a2a55f4633fbd3b82d158b2442e561bd595d48138ca473a2008e4e8689e640"}, - {file = "tensordict-0.14.2-cp313-cp313-win_amd64.whl", hash = "sha256:99a36acdc59eb162d3de214be464be2c85998f004b83ddb425aa23f74b92b6f6"}, - {file = "tensordict-0.14.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:10ae025f99e23dcec102652a9859c609122abac053fc3cd09ad999959d9069f2"}, - {file = "tensordict-0.14.2-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:4ec2d0d1ca4a61196deadb7a88584d9df47dc720ba45d00af15783396961295f"}, - {file = "tensordict-0.14.2-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:6d710cbc3091be3fee8d009492fb372df4c732e064495cf0ed5cdfacb5e168bd"}, - {file = "tensordict-0.14.2-cp314-cp314-win_amd64.whl", hash = "sha256:31512077ade1931b47b90be02a96ebfea23db28ab195c158bea01e11a0c71638"}, - {file = "tensordict-0.14.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:ad9c5a260b031145cd8a10a2fcdc5aa6c817c0e92cb80ec40bb140a0368b868a"}, - {file = "tensordict-0.14.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:595cdb56991ea6a7880af363f349299bb432041aa117fd8cdde76f0976f335a3"}, - {file = "tensordict-0.14.2-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:0482dd97ba526d4918f8920aaa3936f6fe32f2ed4682a714e779582eacba4c2c"}, - {file = "tensordict-0.14.2-cp314-cp314t-win_amd64.whl", hash = "sha256:68cba296f45c4eb98587644ce07902fbe75e064a2b738b8c5b2b590b8ea8f85b"}, -] - -[package.dependencies] -cloudpickle = "*" -importlib_metadata = "*" -numpy = "*" -orjson = {version = "*", markers = "python_version < \"3.13\""} -packaging = "*" -pyvers = ">=0.2.0,<0.3.0" -torch = "*" - -[package.extras] -dev = ["ninja", "pybind11 (>=2.13)"] -h5 = ["h5py (>=3.8)"] -onnx = ["onnx", "onnxruntime", "onnxscript"] -pandas = ["pandas (>=1.5)"] -parquet = ["pyarrow (>=10.0)"] -tabular = ["pandas (>=1.5)", "pyarrow (>=10.0)"] -tests = ["pytest", "pytest-benchmark", "pytest-instafail", "pytest-rerunfailures", "pyyaml"] -typecheck = ["mypy (>=1.0.0)"] -zarr = ["zarr (>=3.0) ; python_version >= \"3.11\""] - -[[package]] -name = "textual" -version = "8.2.8" -description = "Modern Text User Interface framework" -optional = true -python-versions = "<4.0,>=3.9" -groups = ["main"] -markers = "extra == \"client\"" -files = [ - {file = "textual-8.2.8-py3-none-any.whl", hash = "sha256:267375fd402dc8d981457212efa71f0e3365fd17bba144ba9bb3ed7563cb374a"}, - {file = "textual-8.2.8.tar.gz", hash = "sha256:3f106a9fbc73e39dd266c9712432087de78a6d644084c7c241d6a25c3169115b"}, -] - -[package.dependencies] -markdown-it-py = {version = ">=2.1.0", extras = ["linkify"]} -mdit-py-plugins = "*" -platformdirs = ">=3.6.0,<5" -pygments = ">=2.19.2,<3.0.0" -rich = ">=14.2.0" -typing-extensions = ">=4.4.0,<5.0.0" - -[package.extras] -syntax = ["tree-sitter (>=0.25.0) ; python_version >= \"3.10\"", "tree-sitter-bash (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-css (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-go (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-html (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-java (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-javascript (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-json (>=0.24.0) ; python_version >= \"3.10\"", "tree-sitter-markdown (>=0.3.0) ; python_version >= \"3.10\"", "tree-sitter-python (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-regex (>=0.24.0) ; python_version >= \"3.10\"", "tree-sitter-rust (>=0.23.0) ; python_version >= \"3.10\"", "tree-sitter-sql (>=0.3.11) ; python_version >= \"3.10\"", "tree-sitter-toml (>=0.6.0) ; python_version >= \"3.10\"", "tree-sitter-xml (>=0.7.0) ; python_version >= \"3.10\"", "tree-sitter-yaml (>=0.6.0) ; python_version >= \"3.10\""] - [[package]] name = "tiktoken" version = "0.12.0" @@ -9684,7 +7641,7 @@ description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"eval\" or extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "tiktoken-0.12.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3de02f5a491cfd179aec916eddb70331814bd6bf764075d39e21d5862e533970"}, {file = "tiktoken-0.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b6cfb6d9b7b54d20af21a912bfe63a2727d9cfa8fbda642fd8322c70340aad16"}, @@ -9754,15 +7711,15 @@ blobfile = ["blobfile (>=2)"] [[package]] name = "tinker" -version = "0.29.0" +version = "0.14.0" description = "The official Python SDK for the tinker API" optional = true python-versions = ">=3.11" groups = ["main"] -markers = "python_version >= \"3.11\" and extra == \"client\"" +markers = "extra == \"tinker\"" files = [ - {file = "tinker-0.29.0-py3-none-any.whl", hash = "sha256:d3a9edd08718edaa8d8f72fe4ffa2a7f1ae8da2967f35e1ab206988b86a1b1fb"}, - {file = "tinker-0.29.0.tar.gz", hash = "sha256:615ed096ff647addafd1637096e8c688ce1581b8132bb937426492d2c5c0d619"}, + {file = "tinker-0.14.0-py3-none-any.whl", hash = "sha256:b8e4dd2c77858e80177cb0b970c5d64a7dae085b67a711cc7e1d95352534c563"}, + {file = "tinker-0.14.0.tar.gz", hash = "sha256:554b30c43d9cf83b41eb07775a2a9f65eb2e77bed2cd79792bd8cd0d7693e717"}, ] [package.dependencies] @@ -9771,15 +7728,11 @@ click = ">=8.0.0" distro = ">=1.7.0,<2" httpx = {version = ">=0.23.0,<1", extras = ["http2"]} numpy = "*" -orjson = ">=3.10.0" -protobuf = ">=4.21" pydantic = ">=1.9.0,<3" -pyqwest = ">=0.4.1" rich = ">=13.0.0" sniffio = "*" transformers = "*" typing-extensions = ">=4.10,<5" -zstandard = ">=0.24.0" [package.extras] aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.8)"] @@ -9827,64 +7780,6 @@ dev = ["tokenizers[testing]"] docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] testing = ["datasets", "numpy", "pytest", "pytest-asyncio", "requests", "ruff", "ty"] -[[package]] -name = "tomli" -version = "2.4.1" -description = "A lil' TOML parser" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "python_version == \"3.10\" and (extra == \"rl\" or extra == \"async-rl\" or extra == \"test\")" -files = [ - {file = "tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30"}, - {file = "tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a"}, - {file = "tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076"}, - {file = "tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9"}, - {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c"}, - {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc"}, - {file = "tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049"}, - {file = "tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e"}, - {file = "tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece"}, - {file = "tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a"}, - {file = "tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085"}, - {file = "tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9"}, - {file = "tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5"}, - {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585"}, - {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1"}, - {file = "tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917"}, - {file = "tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9"}, - {file = "tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257"}, - {file = "tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54"}, - {file = "tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a"}, - {file = "tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897"}, - {file = "tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f"}, - {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d"}, - {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5"}, - {file = "tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd"}, - {file = "tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36"}, - {file = "tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd"}, - {file = "tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf"}, - {file = "tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac"}, - {file = "tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662"}, - {file = "tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853"}, - {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15"}, - {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba"}, - {file = "tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6"}, - {file = "tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7"}, - {file = "tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232"}, - {file = "tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4"}, - {file = "tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c"}, - {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d"}, - {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41"}, - {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c"}, - {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f"}, - {file = "tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8"}, - {file = "tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26"}, - {file = "tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396"}, - {file = "tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe"}, - {file = "tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f"}, -] - [[package]] name = "torch" version = "2.9.1" @@ -9960,7 +7855,7 @@ description = "An audio package for PyTorch" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "torchaudio-2.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd13541197e035338bd43225b2067532056486d357c661e12d49ace4fc37f8bb"}, {file = "torchaudio-2.9.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:31ec46b718b7caa0182221bfb42e2ad223947b752a996dcdc0388c34a678c966"}, @@ -10002,7 +7897,7 @@ description = "image and video datasets and models for torch deep learning" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"transformers\" or extra == \"vllm\"" files = [ {file = "torchvision-0.24.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ded5e625788572e4e1c4d155d1bbc48805c113794100d70e19c76e39e4d53465"}, {file = "torchvision-0.24.1-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:54ed17c3d30e718e08d8da3fd5b30ea44b0311317e55647cb97077a29ecbc25b"}, @@ -10065,35 +7960,6 @@ notebook = ["ipywidgets (>=6)"] slack = ["slack-sdk"] telegram = ["requests"] -[[package]] -name = "transferqueue" -version = "0.1.10" -description = "TransferQueue: An Asynchronous Streaming Data Management Module" -optional = true -python-versions = ">=3.10" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "transferqueue-0.1.10-py3-none-any.whl", hash = "sha256:a8efceb971fe57d52ac7ddd86d9a6ef63f1824819dddc2ea980a96b73ff2f8ea"}, -] - -[package.dependencies] -hydra-core = "*" -msgspec = "*" -numpy = "*" -omegaconf = "*" -prometheus_client = ">=0.20.0" -psutil = "*" -pyzmq = "*" -ray = {version = "*", extras = ["default"]} -tensordict = ">=0.10.0" - -[package.extras] -build = ["build"] -mooncake = ["cuda-python", "mooncake-transfer-engine (>=0.3.10.post2)"] -test = ["flake8", "pytest (>=7.0.0)", "pytest-asyncio (>=0.20.0)", "pytest-mock"] -yuanrong = ["openyuanrong-datasystem"] - [[package]] name = "transformer-engine" version = "2.12.0" @@ -10268,9 +8134,10 @@ tutorials = ["matplotlib", "pandas", "tabulate"] name = "typer" version = "0.24.1" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." -optional = false +optional = true python-versions = ">=3.10" groups = ["main"] +markers = "extra == \"vllm\"" files = [ {file = "typer-0.24.1-py3-none-any.whl", hash = "sha256:112c1f0ce578bfb4cab9ffdabc68f031416ebcc216536611ba21f04e9aa84c9e"}, {file = "typer-0.24.1.tar.gz", hash = "sha256:e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45"}, @@ -10316,7 +8183,7 @@ description = "Provider of IANA time zone data" optional = false python-versions = ">=2" groups = ["main"] -markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\" or python_version == \"3.10\"" +markers = "sys_platform == \"win32\" or sys_platform == \"emscripten\"" files = [ {file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"}, {file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"}, @@ -10347,7 +8214,7 @@ description = "The lightning-fast ASGI server." optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "uvicorn-0.41.0-py3-none-any.whl", hash = "sha256:29e35b1d2c36a04b9e180d4007ede3bcb32a85fbdfd6c6aeb3f26839de088187"}, {file = "uvicorn-0.41.0.tar.gz", hash = "sha256:09d11cf7008da33113824ee5a1c6422d89fbc2ff476540d69a34c87fab8b571a"}, @@ -10360,7 +8227,6 @@ h11 = ">=0.8" httptools = {version = ">=0.6.3", optional = true, markers = "extra == \"standard\""} python-dotenv = {version = ">=0.13", optional = true, markers = "extra == \"standard\""} pyyaml = {version = ">=5.1", optional = true, markers = "extra == \"standard\""} -typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""} uvloop = {version = ">=0.15.1", optional = true, markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and extra == \"standard\""} watchfiles = {version = ">=0.20", optional = true, markers = "extra == \"standard\""} websockets = {version = ">=10.4", optional = true, markers = "extra == \"standard\""} @@ -10375,7 +8241,7 @@ description = "Fast implementation of asyncio event loop on top of libuv" optional = true python-versions = ">=3.8.1" groups = ["main"] -markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and (extra == \"rl\" or extra == \"async-rl\")" +markers = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\" and (extra == \"vllm\" or extra == \"ray\")" files = [ {file = "uvloop-0.22.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ef6f0d4cc8a9fa1f6a910230cd53545d9a14479311e87e3cb225495952eb672c"}, {file = "uvloop-0.22.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7cd375a12b71d33d46af85a3343b35d98e8116134ba404bd657b3b1d15988792"}, @@ -10440,7 +8306,7 @@ description = "Virtual Python Environment builder" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"ray\"" files = [ {file = "virtualenv-21.1.0-py3-none-any.whl", hash = "sha256:164f5e14c5587d170cf98e60378eb91ea35bf037be313811905d3a24ea33cc07"}, {file = "virtualenv-21.1.0.tar.gz", hash = "sha256:1990a0188c8f16b6b9cf65c9183049007375b26aad415514d377ccacf1e4fb44"}, @@ -10451,7 +8317,6 @@ distlib = ">=0.3.7,<1" filelock = {version = ">=3.24.2,<4", markers = "python_version >= \"3.10\""} platformdirs = ">=3.9.1,<5" python-discovery = ">=1" -typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\""} [[package]] name = "vllm" @@ -10460,7 +8325,7 @@ description = "A high-throughput and memory-efficient inference and serving engi optional = true python-versions = "<3.14,>=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\"" files = [ {file = "vllm-0.16.0-cp38-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:dfaa14846608fd229dda9d372e2ad3f13854fd09147c2ba36b40579cf3c03804"}, {file = "vllm-0.16.0-cp38-abi3-manylinux_2_31_x86_64.whl", hash = "sha256:f066b2a2f8597a4a3ada8fbbfd122b59086864b2260ca42dc81bf9fb57af0c42"}, @@ -10539,50 +8404,6 @@ petit-kernel = ["petit-kernel"] runai = ["runai-model-streamer[gcs,s3] (>=0.15.3)"] tensorizer = ["tensorizer (==2.10.1)"] -[[package]] -name = "watchdog" -version = "6.0.0" -description = "Filesystem events monitoring" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"}, - {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"}, - {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"}, - {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"}, - {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"}, - {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"}, - {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"}, - {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"}, - {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"}, - {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"}, - {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"}, - {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"}, - {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"}, - {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"}, - {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"}, - {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"}, - {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"}, - {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"}, - {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"}, - {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"}, - {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"}, - {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"}, - {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"}, - {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"}, -] - -[package.extras] -watchmedo = ["PyYAML (>=3.10)"] - [[package]] name = "watchfiles" version = "1.1.1" @@ -10590,7 +8411,7 @@ description = "Simple, modern and high performance file watching and code reload optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "watchfiles-1.1.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:eef58232d32daf2ac67f42dea51a2c80f0d03379075d44a587051e63cc2e368c"}, {file = "watchfiles-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:03fa0f5237118a0c5e496185cafa92878568b652a2e9a9382a5151b1a0380a43"}, @@ -10706,19 +8527,6 @@ files = [ [package.dependencies] anyio = ">=3.0.0" -[[package]] -name = "wcwidth" -version = "0.8.3" -description = "Measures the displayed width of unicode strings in a terminal" -optional = true -python-versions = ">=3.8" -groups = ["main"] -markers = "extra == \"async-rl\"" -files = [ - {file = "wcwidth-0.8.3-py3-none-any.whl", hash = "sha256:d5b73dba6158a595ec9370350e7f2637bcac8d6c5e4fde34f30fcffb6103a5e4"}, - {file = "wcwidth-0.8.3.tar.gz", hash = "sha256:d128512515fbf4612e0ff21fd6380399210318b7b54a9af59dff8454cf9730eb"}, -] - [[package]] name = "websockets" version = "16.0" @@ -10726,7 +8534,7 @@ description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\"" +markers = "extra == \"vllm\" or extra == \"ray\"" files = [ {file = "websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a"}, {file = "websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0"}, @@ -10798,7 +8606,7 @@ description = "A small Python utility to set file creation time on Windows" optional = true python-versions = ">=3.5" groups = ["main"] -markers = "sys_platform == \"win32\" and (extra == \"rl\" or extra == \"async-rl\")" +markers = "extra == \"vllm\" and sys_platform == \"win32\"" files = [ {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, @@ -10807,109 +8615,93 @@ files = [ [package.extras] dev = ["black (>=19.3b0) ; python_version >= \"3.6\"", "pytest (>=4.6.2)"] -[[package]] -name = "word2number" -version = "1.1" -description = "Convert number words eg. three hundred and forty two to numbers (342)." -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "word2number-1.1.zip", hash = "sha256:70e27a5d387f67b04c71fbb7621c05930b19bfd26efd6851e6e0f9969dcde7d0"}, -] - [[package]] name = "wrapt" -version = "1.17.3" +version = "2.1.1" description = "Module for decorators, wrappers and monkey patching." optional = true -python-versions = ">=3.8" +python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"rl\" or extra == \"async-rl\" or extra == \"server\"" -files = [ - {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88bbae4d40d5a46142e70d58bf664a89b6b4befaea7b2ecc14e03cedb8e06c04"}, - {file = "wrapt-1.17.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b13af258d6a9ad602d57d889f83b9d5543acd471eee12eb51f5b01f8eb1bc2"}, - {file = "wrapt-1.17.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd341868a4b6714a5962c1af0bd44f7c404ef78720c7de4892901e540417111c"}, - {file = "wrapt-1.17.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f9b2601381be482f70e5d1051a5965c25fb3625455a2bf520b5a077b22afb775"}, - {file = "wrapt-1.17.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:343e44b2a8e60e06a7e0d29c1671a0d9951f59174f3709962b5143f60a2a98bd"}, - {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:33486899acd2d7d3066156b03465b949da3fd41a5da6e394ec49d271baefcf05"}, - {file = "wrapt-1.17.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e6f40a8aa5a92f150bdb3e1c44b7e98fb7113955b2e5394122fa5532fec4b418"}, - {file = "wrapt-1.17.3-cp310-cp310-win32.whl", hash = "sha256:a36692b8491d30a8c75f1dfee65bef119d6f39ea84ee04d9f9311f83c5ad9390"}, - {file = "wrapt-1.17.3-cp310-cp310-win_amd64.whl", hash = "sha256:afd964fd43b10c12213574db492cb8f73b2f0826c8df07a68288f8f19af2ebe6"}, - {file = "wrapt-1.17.3-cp310-cp310-win_arm64.whl", hash = "sha256:af338aa93554be859173c39c85243970dc6a289fa907402289eeae7543e1ae18"}, - {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:273a736c4645e63ac582c60a56b0acb529ef07f78e08dc6bfadf6a46b19c0da7"}, - {file = "wrapt-1.17.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5531d911795e3f935a9c23eb1c8c03c211661a5060aab167065896bbf62a5f85"}, - {file = "wrapt-1.17.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0610b46293c59a3adbae3dee552b648b984176f8562ee0dba099a56cfbe4df1f"}, - {file = "wrapt-1.17.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b32888aad8b6e68f83a8fdccbf3165f5469702a7544472bdf41f582970ed3311"}, - {file = "wrapt-1.17.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8cccf4f81371f257440c88faed6b74f1053eef90807b77e31ca057b2db74edb1"}, - {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8a210b158a34164de8bb68b0e7780041a903d7b00c87e906fb69928bf7890d5"}, - {file = "wrapt-1.17.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:79573c24a46ce11aab457b472efd8d125e5a51da2d1d24387666cd85f54c05b2"}, - {file = "wrapt-1.17.3-cp311-cp311-win32.whl", hash = "sha256:c31eebe420a9a5d2887b13000b043ff6ca27c452a9a22fa71f35f118e8d4bf89"}, - {file = "wrapt-1.17.3-cp311-cp311-win_amd64.whl", hash = "sha256:0b1831115c97f0663cb77aa27d381237e73ad4f721391a9bfb2fe8bc25fa6e77"}, - {file = "wrapt-1.17.3-cp311-cp311-win_arm64.whl", hash = "sha256:5a7b3c1ee8265eb4c8f1b7d29943f195c00673f5ab60c192eba2d4a7eae5f46a"}, - {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:ab232e7fdb44cdfbf55fc3afa31bcdb0d8980b9b95c38b6405df2acb672af0e0"}, - {file = "wrapt-1.17.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9baa544e6acc91130e926e8c802a17f3b16fbea0fd441b5a60f5cf2cc5c3deba"}, - {file = "wrapt-1.17.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6b538e31eca1a7ea4605e44f81a48aa24c4632a277431a6ed3f328835901f4fd"}, - {file = "wrapt-1.17.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:042ec3bb8f319c147b1301f2393bc19dba6e176b7da446853406d041c36c7828"}, - {file = "wrapt-1.17.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af60380ba0b7b5aeb329bc4e402acd25bd877e98b3727b0135cb5c2efdaefe9"}, - {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b02e424deef65c9f7326d8c19220a2c9040c51dc165cddb732f16198c168396"}, - {file = "wrapt-1.17.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:74afa28374a3c3a11b3b5e5fca0ae03bef8450d6aa3ab3a1e2c30e3a75d023dc"}, - {file = "wrapt-1.17.3-cp312-cp312-win32.whl", hash = "sha256:4da9f45279fff3543c371d5ababc57a0384f70be244de7759c85a7f989cb4ebe"}, - {file = "wrapt-1.17.3-cp312-cp312-win_amd64.whl", hash = "sha256:e71d5c6ebac14875668a1e90baf2ea0ef5b7ac7918355850c0908ae82bcb297c"}, - {file = "wrapt-1.17.3-cp312-cp312-win_arm64.whl", hash = "sha256:604d076c55e2fdd4c1c03d06dc1a31b95130010517b5019db15365ec4a405fc6"}, - {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a47681378a0439215912ef542c45a783484d4dd82bac412b71e59cf9c0e1cea0"}, - {file = "wrapt-1.17.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:54a30837587c6ee3cd1a4d1c2ec5d24e77984d44e2f34547e2323ddb4e22eb77"}, - {file = "wrapt-1.17.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:16ecf15d6af39246fe33e507105d67e4b81d8f8d2c6598ff7e3ca1b8a37213f7"}, - {file = "wrapt-1.17.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6fd1ad24dc235e4ab88cda009e19bf347aabb975e44fd5c2fb22a3f6e4141277"}, - {file = "wrapt-1.17.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0ed61b7c2d49cee3c027372df5809a59d60cf1b6c2f81ee980a091f3afed6a2d"}, - {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:423ed5420ad5f5529db9ce89eac09c8a2f97da18eb1c870237e84c5a5c2d60aa"}, - {file = "wrapt-1.17.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e01375f275f010fcbf7f643b4279896d04e571889b8a5b3f848423d91bf07050"}, - {file = "wrapt-1.17.3-cp313-cp313-win32.whl", hash = "sha256:53e5e39ff71b3fc484df8a522c933ea2b7cdd0d5d15ae82e5b23fde87d44cbd8"}, - {file = "wrapt-1.17.3-cp313-cp313-win_amd64.whl", hash = "sha256:1f0b2f40cf341ee8cc1a97d51ff50dddb9fcc73241b9143ec74b30fc4f44f6cb"}, - {file = "wrapt-1.17.3-cp313-cp313-win_arm64.whl", hash = "sha256:7425ac3c54430f5fc5e7b6f41d41e704db073309acfc09305816bc6a0b26bb16"}, - {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cf30f6e3c077c8e6a9a7809c94551203c8843e74ba0c960f4a98cd80d4665d39"}, - {file = "wrapt-1.17.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e228514a06843cae89621384cfe3a80418f3c04aadf8a3b14e46a7be704e4235"}, - {file = "wrapt-1.17.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5ea5eb3c0c071862997d6f3e02af1d055f381b1d25b286b9d6644b79db77657c"}, - {file = "wrapt-1.17.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:281262213373b6d5e4bb4353bc36d1ba4084e6d6b5d242863721ef2bf2c2930b"}, - {file = "wrapt-1.17.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dc4a8d2b25efb6681ecacad42fca8859f88092d8732b170de6a5dddd80a1c8fa"}, - {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:373342dd05b1d07d752cecbec0c41817231f29f3a89aa8b8843f7b95992ed0c7"}, - {file = "wrapt-1.17.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d40770d7c0fd5cbed9d84b2c3f2e156431a12c9a37dc6284060fb4bec0b7ffd4"}, - {file = "wrapt-1.17.3-cp314-cp314-win32.whl", hash = "sha256:fbd3c8319de8e1dc79d346929cd71d523622da527cca14e0c1d257e31c2b8b10"}, - {file = "wrapt-1.17.3-cp314-cp314-win_amd64.whl", hash = "sha256:e1a4120ae5705f673727d3253de3ed0e016f7cd78dc463db1b31e2463e1f3cf6"}, - {file = "wrapt-1.17.3-cp314-cp314-win_arm64.whl", hash = "sha256:507553480670cab08a800b9463bdb881b2edeed77dc677b0a5915e6106e91a58"}, - {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:ed7c635ae45cfbc1a7371f708727bf74690daedc49b4dba310590ca0bd28aa8a"}, - {file = "wrapt-1.17.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:249f88ed15503f6492a71f01442abddd73856a0032ae860de6d75ca62eed8067"}, - {file = "wrapt-1.17.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a03a38adec8066d5a37bea22f2ba6bbf39fcdefbe2d91419ab864c3fb515454"}, - {file = "wrapt-1.17.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5d4478d72eb61c36e5b446e375bbc49ed002430d17cdec3cecb36993398e1a9e"}, - {file = "wrapt-1.17.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223db574bb38637e8230eb14b185565023ab624474df94d2af18f1cdb625216f"}, - {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e405adefb53a435f01efa7ccdec012c016b5a1d3f35459990afc39b6be4d5056"}, - {file = "wrapt-1.17.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:88547535b787a6c9ce4086917b6e1d291aa8ed914fdd3a838b3539dc95c12804"}, - {file = "wrapt-1.17.3-cp314-cp314t-win32.whl", hash = "sha256:41b1d2bc74c2cac6f9074df52b2efbef2b30bdfe5f40cb78f8ca22963bc62977"}, - {file = "wrapt-1.17.3-cp314-cp314t-win_amd64.whl", hash = "sha256:73d496de46cd2cdbdbcce4ae4bcdb4afb6a11234a1df9c085249d55166b95116"}, - {file = "wrapt-1.17.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f38e60678850c42461d4202739f9bf1e3a737c7ad283638251e79cc49effb6b6"}, - {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:70d86fa5197b8947a2fa70260b48e400bf2ccacdcab97bb7de47e3d1e6312225"}, - {file = "wrapt-1.17.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:df7d30371a2accfe4013e90445f6388c570f103d61019b6b7c57e0265250072a"}, - {file = "wrapt-1.17.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:caea3e9c79d5f0d2c6d9ab96111601797ea5da8e6d0723f77eabb0d4068d2b2f"}, - {file = "wrapt-1.17.3-cp38-cp38-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:758895b01d546812d1f42204bd443b8c433c44d090248bf22689df673ccafe00"}, - {file = "wrapt-1.17.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02b551d101f31694fc785e58e0720ef7d9a10c4e62c1c9358ce6f63f23e30a56"}, - {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:656873859b3b50eeebe6db8b1455e99d90c26ab058db8e427046dbc35c3140a5"}, - {file = "wrapt-1.17.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a9a2203361a6e6404f80b99234fe7fb37d1fc73487b5a78dc1aa5b97201e0f22"}, - {file = "wrapt-1.17.3-cp38-cp38-win32.whl", hash = "sha256:55cbbc356c2842f39bcc553cf695932e8b30e30e797f961860afb308e6b1bb7c"}, - {file = "wrapt-1.17.3-cp38-cp38-win_amd64.whl", hash = "sha256:ad85e269fe54d506b240d2d7b9f5f2057c2aa9a2ea5b32c66f8902f768117ed2"}, - {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:30ce38e66630599e1193798285706903110d4f057aab3168a34b7fdc85569afc"}, - {file = "wrapt-1.17.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65d1d00fbfb3ea5f20add88bbc0f815150dbbde3b026e6c24759466c8b5a9ef9"}, - {file = "wrapt-1.17.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7c06742645f914f26c7f1fa47b8bc4c91d222f76ee20116c43d5ef0912bba2d"}, - {file = "wrapt-1.17.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7e18f01b0c3e4a07fe6dfdb00e29049ba17eadbc5e7609a2a3a4af83ab7d710a"}, - {file = "wrapt-1.17.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f5f51a6466667a5a356e6381d362d259125b57f059103dd9fdc8c0cf1d14139"}, - {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:59923aa12d0157f6b82d686c3fd8e1166fa8cdfb3e17b42ce3b6147ff81528df"}, - {file = "wrapt-1.17.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:46acc57b331e0b3bcb3e1ca3b421d65637915cfcd65eb783cb2f78a511193f9b"}, - {file = "wrapt-1.17.3-cp39-cp39-win32.whl", hash = "sha256:3e62d15d3cfa26e3d0788094de7b64efa75f3a53875cdbccdf78547aed547a81"}, - {file = "wrapt-1.17.3-cp39-cp39-win_amd64.whl", hash = "sha256:1f23fa283f51c890eda8e34e4937079114c74b4c81d2b2f1f1d94948f5cc3d7f"}, - {file = "wrapt-1.17.3-cp39-cp39-win_arm64.whl", hash = "sha256:24c2ed34dc222ed754247a2702b1e1e89fdbaa4016f324b4b8f1a802d4ffe87f"}, - {file = "wrapt-1.17.3-py3-none-any.whl", hash = "sha256:7171ae35d2c33d326ac19dd8facb1e82e5fd04ef8c6c0e394d7af55a55051c22"}, - {file = "wrapt-1.17.3.tar.gz", hash = "sha256:f66eb08feaa410fe4eebd17f2a2c8e2e46d3476e9f8c783daa8e09e0faa666d0"}, -] +markers = "extra == \"ray\"" +files = [ + {file = "wrapt-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7e927375e43fd5a985b27a8992327c22541b6dede1362fc79df337d26e23604f"}, + {file = "wrapt-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c99544b6a7d40ca22195563b6d8bc3986ee8bb82f272f31f0670fe9440c869"}, + {file = "wrapt-2.1.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b2be3fa5f4efaf16ee7c77d0556abca35f5a18ad4ac06f0ef3904c3399010ce9"}, + {file = "wrapt-2.1.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:67c90c1ae6489a6cb1a82058902caa8006706f7b4e8ff766f943e9d2c8e608d0"}, + {file = "wrapt-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:05c0db35ccffd7480143e62df1e829d101c7b86944ae3be7e4869a7efa621f53"}, + {file = "wrapt-2.1.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0c2ec9f616755b2e1e0bf4d0961f59bb5c2e7a77407e7e2c38ef4f7d2fdde12c"}, + {file = "wrapt-2.1.1-cp310-cp310-win32.whl", hash = "sha256:203ba6b3f89e410e27dbd30ff7dccaf54dcf30fda0b22aa1b82d560c7f9fe9a1"}, + {file = "wrapt-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:6f9426d9cfc2f8732922fc96198052e55c09bb9db3ddaa4323a18e055807410e"}, + {file = "wrapt-2.1.1-cp310-cp310-win_arm64.whl", hash = "sha256:69c26f51b67076b40714cff81bdd5826c0b10c077fb6b0678393a6a2f952a5fc"}, + {file = "wrapt-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c366434a7fb914c7a5de508ed735ef9c133367114e1a7cb91dfb5cd806a1549"}, + {file = "wrapt-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d6a2068bd2e1e19e5a317c8c0b288267eec4e7347c36bc68a6e378a39f19ee7"}, + {file = "wrapt-2.1.1-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:891ab4713419217b2aed7dd106c9200f64e6a82226775a0d2ebd6bef2ebd1747"}, + {file = "wrapt-2.1.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c8ef36a0df38d2dc9d907f6617f89e113c5892e0a35f58f45f75901af0ce7d81"}, + {file = "wrapt-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:76e9af3ebd86f19973143d4d592cbf3e970cf3f66ddee30b16278c26ae34b8ab"}, + {file = "wrapt-2.1.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ff562067485ebdeaef2fa3fe9b1876bc4e7b73762e0a01406ad81e2076edcebf"}, + {file = "wrapt-2.1.1-cp311-cp311-win32.whl", hash = "sha256:9e60a30aa0909435ec4ea2a3c53e8e1b50ac9f640c0e9fe3f21fd248a22f06c5"}, + {file = "wrapt-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:7d79954f51fcf84e5ec4878ab4aea32610d70145c5bbc84b3370eabfb1e096c2"}, + {file = "wrapt-2.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:d3ffc6b0efe79e08fd947605fd598515aebefe45e50432dc3b5cd437df8b1ada"}, + {file = "wrapt-2.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab8e3793b239db021a18782a5823fcdea63b9fe75d0e340957f5828ef55fcc02"}, + {file = "wrapt-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7c0300007836373d1c2df105b40777986accb738053a92fe09b615a7a4547e9f"}, + {file = "wrapt-2.1.1-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:2b27c070fd1132ab23957bcd4ee3ba707a91e653a9268dc1afbd39b77b2799f7"}, + {file = "wrapt-2.1.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b0e36d845e8b6f50949b6b65fc6cd279f47a1944582ed4ec8258cd136d89a64"}, + {file = "wrapt-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4aeea04a9889370fcfb1ef828c4cc583f36a875061505cd6cd9ba24d8b43cc36"}, + {file = "wrapt-2.1.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d88b46bb0dce9f74b6817bc1758ff2125e1ca9e1377d62ea35b6896142ab6825"}, + {file = "wrapt-2.1.1-cp312-cp312-win32.whl", hash = "sha256:63decff76ca685b5c557082dfbea865f3f5f6d45766a89bff8dc61d336348833"}, + {file = "wrapt-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:b828235d26c1e35aca4107039802ae4b1411be0fe0367dd5b7e4d90e562fcbcd"}, + {file = "wrapt-2.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:75128507413a9f1bcbe2db88fd18fbdbf80f264b82fa33a6996cdeaf01c52352"}, + {file = "wrapt-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ce9646e17fa7c3e2e7a87e696c7de66512c2b4f789a8db95c613588985a2e139"}, + {file = "wrapt-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:428cfc801925454395aa468ba7ddb3ed63dc0d881df7b81626cdd433b4e2b11b"}, + {file = "wrapt-2.1.1-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5797f65e4d58065a49088c3b32af5410751cd485e83ba89e5a45e2aa8905af98"}, + {file = "wrapt-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a2db44a71202c5ae4bb5f27c6d3afbc5b23053f2e7e78aa29704541b5dad789"}, + {file = "wrapt-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8d5350c3590af09c1703dd60ec78a7370c0186e11eaafb9dda025a30eee6492d"}, + {file = "wrapt-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2d9b076411bed964e752c01b49fd224cc385f3a96f520c797d38412d70d08359"}, + {file = "wrapt-2.1.1-cp313-cp313-win32.whl", hash = "sha256:0bb7207130ce6486727baa85373503bf3334cc28016f6928a0fa7e19d7ecdc06"}, + {file = "wrapt-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:cbfee35c711046b15147b0ae7db9b976f01c9520e6636d992cd9e69e5e2b03b1"}, + {file = "wrapt-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:7d2756061022aebbf57ba14af9c16e8044e055c22d38de7bf40d92b565ecd2b0"}, + {file = "wrapt-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4814a3e58bc6971e46baa910ecee69699110a2bf06c201e24277c65115a20c20"}, + {file = "wrapt-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:106c5123232ab9b9f4903692e1fa0bdc231510098f04c13c3081f8ad71c3d612"}, + {file = "wrapt-2.1.1-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1a40b83ff2535e6e56f190aff123821eea89a24c589f7af33413b9c19eb2c738"}, + {file = "wrapt-2.1.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:789cea26e740d71cf1882e3a42bb29052bc4ada15770c90072cb47bf73fb3dbf"}, + {file = "wrapt-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:ba49c14222d5e5c0ee394495a8655e991dc06cbca5398153aefa5ac08cd6ccd7"}, + {file = "wrapt-2.1.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ac8cda531fe55be838a17c62c806824472bb962b3afa47ecbd59b27b78496f4e"}, + {file = "wrapt-2.1.1-cp313-cp313t-win32.whl", hash = "sha256:b8af75fe20d381dd5bcc9db2e86a86d7fcfbf615383a7147b85da97c1182225b"}, + {file = "wrapt-2.1.1-cp313-cp313t-win_amd64.whl", hash = "sha256:45c5631c9b6c792b78be2d7352129f776dd72c605be2c3a4e9be346be8376d83"}, + {file = "wrapt-2.1.1-cp313-cp313t-win_arm64.whl", hash = "sha256:da815b9263947ac98d088b6414ac83507809a1d385e4632d9489867228d6d81c"}, + {file = "wrapt-2.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9aa1765054245bb01a37f615503290d4e207e3fd59226e78341afb587e9c1236"}, + {file = "wrapt-2.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:feff14b63a6d86c1eee33a57f77573649f2550935981625be7ff3cb7342efe05"}, + {file = "wrapt-2.1.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:81fc5f22d5fcfdbabde96bb3f5379b9f4476d05c6d524d7259dc5dfb501d3281"}, + {file = "wrapt-2.1.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:951b228ecf66def855d22e006ab9a1fc12535111ae7db2ec576c728f8ddb39e8"}, + {file = "wrapt-2.1.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ddf582a95641b9a8c8bd643e83f34ecbbfe1b68bc3850093605e469ab680ae3"}, + {file = "wrapt-2.1.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:fc5c500966bf48913f795f1984704e6d452ba2414207b15e1f8c339a059d5b16"}, + {file = "wrapt-2.1.1-cp314-cp314-win32.whl", hash = "sha256:4aa4baadb1f94b71151b8e44a0c044f6af37396c3b8bcd474b78b49e2130a23b"}, + {file = "wrapt-2.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:860e9d3fd81816a9f4e40812f28be4439ab01f260603c749d14be3c0a1170d19"}, + {file = "wrapt-2.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:3c59e103017a2c1ea0ddf589cbefd63f91081d7ce9d491d69ff2512bb1157e23"}, + {file = "wrapt-2.1.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9fa7c7e1bee9278fc4f5dd8275bc8d25493281a8ec6c61959e37cc46acf02007"}, + {file = "wrapt-2.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:39c35e12e8215628984248bd9c8897ce0a474be2a773db207eb93414219d8469"}, + {file = "wrapt-2.1.1-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:94ded4540cac9125eaa8ddf5f651a7ec0da6f5b9f248fe0347b597098f8ec14c"}, + {file = "wrapt-2.1.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da0af328373f97ed9bdfea24549ac1b944096a5a71b30e41c9b8b53ab3eec04a"}, + {file = "wrapt-2.1.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:4ad839b55f0bf235f8e337ce060572d7a06592592f600f3a3029168e838469d3"}, + {file = "wrapt-2.1.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0d89c49356e5e2a50fa86b40e0510082abcd0530f926cbd71cf25bee6b9d82d7"}, + {file = "wrapt-2.1.1-cp314-cp314t-win32.whl", hash = "sha256:f4c7dd22cf7f36aafe772f3d88656559205c3af1b7900adfccb70edeb0d2abc4"}, + {file = "wrapt-2.1.1-cp314-cp314t-win_amd64.whl", hash = "sha256:f76bc12c583ab01e73ba0ea585465a41e48d968f6d1311b4daec4f8654e356e3"}, + {file = "wrapt-2.1.1-cp314-cp314t-win_arm64.whl", hash = "sha256:7ea74fc0bec172f1ae5f3505b6655c541786a5cabe4bbc0d9723a56ac32eb9b9"}, + {file = "wrapt-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e03b3d486eb39f5d3f562839f59094dcee30c4039359ea15768dc2214d9e07c"}, + {file = "wrapt-2.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0fdf3073f488ce4d929929b7799e3b8c52b220c9eb3f4a5a51e2dc0e8ff07881"}, + {file = "wrapt-2.1.1-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0cb4f59238c6625fae2eeb72278da31c9cfba0ff4d9cbe37446b73caa0e9bcf7"}, + {file = "wrapt-2.1.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f794a1c148871b714cb566f5466ec8288e0148a1c417550983864b3981737cd"}, + {file = "wrapt-2.1.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:95ef3866631c6da9ce1fc0f1e17b90c4c0aa6d041fc70a11bc90733aee122e1a"}, + {file = "wrapt-2.1.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:66bc1b2446f01cbbd3c56b79a3a8435bcd4178ac4e06b091913f7751a7f528b8"}, + {file = "wrapt-2.1.1-cp39-cp39-win32.whl", hash = "sha256:1b9e08e57cabc32972f7c956d10e85093c5da9019faa24faf411e7dd258e528c"}, + {file = "wrapt-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:e75ad48c3cca739f580b5e14c052993eb644c7fa5b4c90aa51193280b30875ae"}, + {file = "wrapt-2.1.1-cp39-cp39-win_arm64.whl", hash = "sha256:9ccd657873b7f964711447d004563a2bc08d1476d7a1afcad310f3713e6f50f4"}, + {file = "wrapt-2.1.1-py3-none-any.whl", hash = "sha256:3b0f4629eb954394a3d7c7a1c8cca25f0b07cefe6aa8545e862e9778152de5b7"}, + {file = "wrapt-2.1.1.tar.gz", hash = "sha256:5fdcb09bf6db023d88f312bd0767594b414655d58090fc1c46b3414415f67fac"}, +] + +[package.extras] +dev = ["pytest", "setuptools"] [[package]] name = "xgrammar" @@ -10918,7 +8710,7 @@ description = "Efficient, Flexible and Portable Structured Generation" optional = true python-versions = "<4,>=3.8" groups = ["main"] -markers = "(extra == \"rl\" or extra == \"async-rl\") and (platform_machine == \"x86_64\" or platform_machine == \"aarch64\" or platform_machine == \"arm64\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\")" +markers = "extra == \"vllm\" and (platform_machine == \"x86_64\" or platform_machine == \"aarch64\" or platform_machine == \"arm64\" or platform_machine == \"s390x\" or platform_machine == \"ppc64le\")" files = [ {file = "xgrammar-0.1.29-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:fdc66e834b915cf956168ac086bd577f138261644b944e73d73f07085682a4d8"}, {file = "xgrammar-0.1.29-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48c5a5c60c5ca5ab09ff5ef9f6b382384a04b153bae5908006cd4f7d80d71e07"}, @@ -11251,18 +9043,6 @@ idna = ">=2.0" multidict = ">=4.0" propcache = ">=0.2.1" -[[package]] -name = "zhconv" -version = "1.4.3" -description = "A simple implementation of Simplified-Traditional Chinese conversion." -optional = true -python-versions = "*" -groups = ["main"] -markers = "extra == \"eval\"" -files = [ - {file = "zhconv-1.4.3.tar.gz", hash = "sha256:ad42d9057ca0605f8e41d62b67ca797f879f58193ee6840562c51459b2698c45"}, -] - [[package]] name = "zipp" version = "3.23.0" @@ -11270,7 +9050,7 @@ description = "Backport of pathlib-compatible object wrapper for zip files" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "(python_version >= \"3.11\" or extra == \"eval\" or extra == \"megatron\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\") and (python_version == \"3.11\" or extra == \"eval\" or extra == \"megatron\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"client\") and (extra == \"client\" or extra == \"rl\" or extra == \"async-rl\" or extra == \"server\" or extra == \"eval\" or extra == \"megatron\")" +markers = "extra == \"megatron\" or extra == \"ray\"" files = [ {file = "zipp-3.23.0-py3-none-any.whl", hash = "sha256:071652d6115ed432f5ce1d34c336c0adfd6a884660d1e9712a256d3d3bd4b14e"}, {file = "zipp-3.23.0.tar.gz", hash = "sha256:a07157588a12518c9d4034df3fbbee09c814741a33ff63c05fa29d26a2404166"}, @@ -11284,131 +9064,16 @@ enabler = ["pytest-enabler (>=2.2)"] test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more_itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] type = ["pytest-mypy"] -[[package]] -name = "zstandard" -version = "0.25.0" -description = "Zstandard bindings for Python" -optional = true -python-versions = ">=3.9" -groups = ["main"] -markers = "python_version >= \"3.11\" and extra == \"client\"" -files = [ - {file = "zstandard-0.25.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e59fdc271772f6686e01e1b3b74537259800f57e24280be3f29c8a0deb1904dd"}, - {file = "zstandard-0.25.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4d441506e9b372386a5271c64125f72d5df6d2a8e8a2a45a0ae09b03cb781ef7"}, - {file = "zstandard-0.25.0-cp310-cp310-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:ab85470ab54c2cb96e176f40342d9ed41e58ca5733be6a893b730e7af9c40550"}, - {file = "zstandard-0.25.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e05ab82ea7753354bb054b92e2f288afb750e6b439ff6ca78af52939ebbc476d"}, - {file = "zstandard-0.25.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:78228d8a6a1c177a96b94f7e2e8d012c55f9c760761980da16ae7546a15a8e9b"}, - {file = "zstandard-0.25.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:2b6bd67528ee8b5c5f10255735abc21aa106931f0dbaf297c7be0c886353c3d0"}, - {file = "zstandard-0.25.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4b6d83057e713ff235a12e73916b6d356e3084fd3d14ced499d84240f3eecee0"}, - {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9174f4ed06f790a6869b41cba05b43eeb9a35f8993c4422ab853b705e8112bbd"}, - {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:25f8f3cd45087d089aef5ba3848cd9efe3ad41163d3400862fb42f81a3a46701"}, - {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3756b3e9da9b83da1796f8809dd57cb024f838b9eeafde28f3cb472012797ac1"}, - {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:81dad8d145d8fd981b2962b686b2241d3a1ea07733e76a2f15435dfb7fb60150"}, - {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a5a419712cf88862a45a23def0ae063686db3d324cec7edbe40509d1a79a0aab"}, - {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e7360eae90809efd19b886e59a09dad07da4ca9ba096752e61a2e03c8aca188e"}, - {file = "zstandard-0.25.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:75ffc32a569fb049499e63ce68c743155477610532da1eb38e7f24bf7cd29e74"}, - {file = "zstandard-0.25.0-cp310-cp310-win32.whl", hash = "sha256:106281ae350e494f4ac8a80470e66d1fe27e497052c8d9c3b95dc4cf1ade81aa"}, - {file = "zstandard-0.25.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea9d54cc3d8064260114a0bbf3479fc4a98b21dffc89b3459edd506b69262f6e"}, - {file = "zstandard-0.25.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:933b65d7680ea337180733cf9e87293cc5500cc0eb3fc8769f4d3c88d724ec5c"}, - {file = "zstandard-0.25.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3f79487c687b1fc69f19e487cd949bf3aae653d181dfb5fde3bf6d18894706f"}, - {file = "zstandard-0.25.0-cp311-cp311-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:0bbc9a0c65ce0eea3c34a691e3c4b6889f5f3909ba4822ab385fab9057099431"}, - {file = "zstandard-0.25.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:01582723b3ccd6939ab7b3a78622c573799d5d8737b534b86d0e06ac18dbde4a"}, - {file = "zstandard-0.25.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5f1ad7bf88535edcf30038f6919abe087f606f62c00a87d7e33e7fc57cb69fcc"}, - {file = "zstandard-0.25.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:06acb75eebeedb77b69048031282737717a63e71e4ae3f77cc0c3b9508320df6"}, - {file = "zstandard-0.25.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9300d02ea7c6506f00e627e287e0492a5eb0371ec1670ae852fefffa6164b072"}, - {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfd06b1c5584b657a2892a6014c2f4c20e0db0208c159148fa78c65f7e0b0277"}, - {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f373da2c1757bb7f1acaf09369cdc1d51d84131e50d5fa9863982fd626466313"}, - {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6c0e5a65158a7946e7a7affa6418878ef97ab66636f13353b8502d7ea03c8097"}, - {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c8e167d5adf59476fa3e37bee730890e389410c354771a62e3c076c86f9f7778"}, - {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:98750a309eb2f020da61e727de7d7ba3c57c97cf6213f6f6277bb7fb42a8e065"}, - {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:22a086cff1b6ceca18a8dd6096ec631e430e93a8e70a9ca5efa7561a00f826fa"}, - {file = "zstandard-0.25.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:72d35d7aa0bba323965da807a462b0966c91608ef3a48ba761678cb20ce5d8b7"}, - {file = "zstandard-0.25.0-cp311-cp311-win32.whl", hash = "sha256:f5aeea11ded7320a84dcdd62a3d95b5186834224a9e55b92ccae35d21a8b63d4"}, - {file = "zstandard-0.25.0-cp311-cp311-win_amd64.whl", hash = "sha256:daab68faadb847063d0c56f361a289c4f268706b598afbf9ad113cbe5c38b6b2"}, - {file = "zstandard-0.25.0-cp311-cp311-win_arm64.whl", hash = "sha256:22a06c5df3751bb7dc67406f5374734ccee8ed37fc5981bf1ad7041831fa1137"}, - {file = "zstandard-0.25.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b3c3a3ab9daa3eed242d6ecceead93aebbb8f5f84318d82cee643e019c4b73b"}, - {file = "zstandard-0.25.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:913cbd31a400febff93b564a23e17c3ed2d56c064006f54efec210d586171c00"}, - {file = "zstandard-0.25.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:011d388c76b11a0c165374ce660ce2c8efa8e5d87f34996aa80f9c0816698b64"}, - {file = "zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dffecc361d079bb48d7caef5d673c88c8988d3d33fb74ab95b7ee6da42652ea"}, - {file = "zstandard-0.25.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7149623bba7fdf7e7f24312953bcf73cae103db8cae49f8154dd1eadc8a29ecb"}, - {file = "zstandard-0.25.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6a573a35693e03cf1d67799fd01b50ff578515a8aeadd4595d2a7fa9f3ec002a"}, - {file = "zstandard-0.25.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5a56ba0db2d244117ed744dfa8f6f5b366e14148e00de44723413b2f3938a902"}, - {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:10ef2a79ab8e2974e2075fb984e5b9806c64134810fac21576f0668e7ea19f8f"}, - {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aaf21ba8fb76d102b696781bddaa0954b782536446083ae3fdaa6f16b25a1c4b"}, - {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1869da9571d5e94a85a5e8d57e4e8807b175c9e4a6294e3b66fa4efb074d90f6"}, - {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:809c5bcb2c67cd0ed81e9229d227d4ca28f82d0f778fc5fea624a9def3963f91"}, - {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f27662e4f7dbf9f9c12391cb37b4c4c3cb90ffbd3b1fb9284dadbbb8935fa708"}, - {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99c0c846e6e61718715a3c9437ccc625de26593fea60189567f0118dc9db7512"}, - {file = "zstandard-0.25.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:474d2596a2dbc241a556e965fb76002c1ce655445e4e3bf38e5477d413165ffa"}, - {file = "zstandard-0.25.0-cp312-cp312-win32.whl", hash = "sha256:23ebc8f17a03133b4426bcc04aabd68f8236eb78c3760f12783385171b0fd8bd"}, - {file = "zstandard-0.25.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffef5a74088f1e09947aecf91011136665152e0b4b359c42be3373897fb39b01"}, - {file = "zstandard-0.25.0-cp312-cp312-win_arm64.whl", hash = "sha256:181eb40e0b6a29b3cd2849f825e0fa34397f649170673d385f3598ae17cca2e9"}, - {file = "zstandard-0.25.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ec996f12524f88e151c339688c3897194821d7f03081ab35d31d1e12ec975e94"}, - {file = "zstandard-0.25.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a1a4ae2dec3993a32247995bdfe367fc3266da832d82f8438c8570f989753de1"}, - {file = "zstandard-0.25.0-cp313-cp313-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:e96594a5537722fdfb79951672a2a63aec5ebfb823e7560586f7484819f2a08f"}, - {file = "zstandard-0.25.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bfc4e20784722098822e3eee42b8e576b379ed72cca4a7cb856ae733e62192ea"}, - {file = "zstandard-0.25.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:457ed498fc58cdc12fc48f7950e02740d4f7ae9493dd4ab2168a47c93c31298e"}, - {file = "zstandard-0.25.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:fd7a5004eb1980d3cefe26b2685bcb0b17989901a70a1040d1ac86f1d898c551"}, - {file = "zstandard-0.25.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8e735494da3db08694d26480f1493ad2cf86e99bdd53e8e9771b2752a5c0246a"}, - {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3a39c94ad7866160a4a46d772e43311a743c316942037671beb264e395bdd611"}, - {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:172de1f06947577d3a3005416977cce6168f2261284c02080e7ad0185faeced3"}, - {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c83b0188c852a47cd13ef3bf9209fb0a77fa5374958b8c53aaa699398c6bd7b"}, - {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1673b7199bbe763365b81a4f3252b8e80f44c9e323fc42940dc8843bfeaf9851"}, - {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0be7622c37c183406f3dbf0cba104118eb16a4ea7359eeb5752f0794882fc250"}, - {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:5f5e4c2a23ca271c218ac025bd7d635597048b366d6f31f420aaeb715239fc98"}, - {file = "zstandard-0.25.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f187a0bb61b35119d1926aee039524d1f93aaf38a9916b8c4b78ac8514a0aaf"}, - {file = "zstandard-0.25.0-cp313-cp313-win32.whl", hash = "sha256:7030defa83eef3e51ff26f0b7bfb229f0204b66fe18e04359ce3474ac33cbc09"}, - {file = "zstandard-0.25.0-cp313-cp313-win_amd64.whl", hash = "sha256:1f830a0dac88719af0ae43b8b2d6aef487d437036468ef3c2ea59c51f9d55fd5"}, - {file = "zstandard-0.25.0-cp313-cp313-win_arm64.whl", hash = "sha256:85304a43f4d513f5464ceb938aa02c1e78c2943b29f44a750b48b25ac999a049"}, - {file = "zstandard-0.25.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:e29f0cf06974c899b2c188ef7f783607dbef36da4c242eb6c82dcd8b512855e3"}, - {file = "zstandard-0.25.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:05df5136bc5a011f33cd25bc9f506e7426c0c9b3f9954f056831ce68f3b6689f"}, - {file = "zstandard-0.25.0-cp314-cp314-manylinux2010_i686.manylinux_2_12_i686.manylinux_2_28_i686.whl", hash = "sha256:f604efd28f239cc21b3adb53eb061e2a205dc164be408e553b41ba2ffe0ca15c"}, - {file = "zstandard-0.25.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:223415140608d0f0da010499eaa8ccdb9af210a543fac54bce15babbcfc78439"}, - {file = "zstandard-0.25.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e54296a283f3ab5a26fc9b8b5d4978ea0532f37b231644f367aa588930aa043"}, - {file = "zstandard-0.25.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ca54090275939dc8ec5dea2d2afb400e0f83444b2fc24e07df7fdef677110859"}, - {file = "zstandard-0.25.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e09bb6252b6476d8d56100e8147b803befa9a12cea144bbe629dd508800d1ad0"}, - {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a9ec8c642d1ec73287ae3e726792dd86c96f5681eb8df274a757bf62b750eae7"}, - {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a4089a10e598eae6393756b036e0f419e8c1d60f44a831520f9af41c14216cf2"}, - {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:f67e8f1a324a900e75b5e28ffb152bcac9fbed1cc7b43f99cd90f395c4375344"}, - {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:9654dbc012d8b06fc3d19cc825af3f7bf8ae242226df5f83936cb39f5fdc846c"}, - {file = "zstandard-0.25.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4203ce3b31aec23012d3a4cf4a2ed64d12fea5269c49aed5e4c3611b938e4088"}, - {file = "zstandard-0.25.0-cp314-cp314-win32.whl", hash = "sha256:da469dc041701583e34de852d8634703550348d5822e66a0c827d39b05365b12"}, - {file = "zstandard-0.25.0-cp314-cp314-win_amd64.whl", hash = "sha256:c19bcdd826e95671065f8692b5a4aa95c52dc7a02a4c5a0cac46deb879a017a2"}, - {file = "zstandard-0.25.0-cp314-cp314-win_arm64.whl", hash = "sha256:d7541afd73985c630bafcd6338d2518ae96060075f9463d7dc14cfb33514383d"}, - {file = "zstandard-0.25.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b9af1fe743828123e12b41dd8091eca1074d0c1569cc42e6e1eee98027f2bbd0"}, - {file = "zstandard-0.25.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4b14abacf83dfb5c25eb4e4a79520de9e7e205f72c9ee7702f91233ae57d33a2"}, - {file = "zstandard-0.25.0-cp39-cp39-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:a51ff14f8017338e2f2e5dab738ce1ec3b5a851f23b18c1ae1359b1eecbee6df"}, - {file = "zstandard-0.25.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3b870ce5a02d4b22286cf4944c628e0f0881b11b3f14667c1d62185a99e04f53"}, - {file = "zstandard-0.25.0-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:05353cef599a7b0b98baca9b068dd36810c3ef0f42bf282583f438caf6ddcee3"}, - {file = "zstandard-0.25.0-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:19796b39075201d51d5f5f790bf849221e58b48a39a5fc74837675d8bafc7362"}, - {file = "zstandard-0.25.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:53e08b2445a6bc241261fea89d065536f00a581f02535f8122eba42db9375530"}, - {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1f3689581a72eaba9131b1d9bdbfe520ccd169999219b41000ede2fca5c1bfdb"}, - {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d8c56bb4e6c795fc77d74d8e8b80846e1fb8292fc0b5060cd8131d522974b751"}, - {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:53f94448fe5b10ee75d246497168e5825135d54325458c4bfffbaafabcc0a577"}, - {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c2ba942c94e0691467ab901fc51b6f2085ff48f2eea77b1a48240f011e8247c7"}, - {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:07b527a69c1e1c8b5ab1ab14e2afe0675614a09182213f21a0717b62027b5936"}, - {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:51526324f1b23229001eb3735bc8c94f9c578b1bd9e867a0a646a3b17109f388"}, - {file = "zstandard-0.25.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89c4b48479a43f820b749df49cd7ba2dbc2b1b78560ecb5ab52985574fd40b27"}, - {file = "zstandard-0.25.0-cp39-cp39-win32.whl", hash = "sha256:1cd5da4d8e8ee0e88be976c294db744773459d51bb32f707a0f166e5ad5c8649"}, - {file = "zstandard-0.25.0-cp39-cp39-win_amd64.whl", hash = "sha256:37daddd452c0ffb65da00620afb8e17abd4adaae6ce6310702841760c2c26860"}, - {file = "zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b"}, -] - -[package.extras] -cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and python_version < \"3.14\"", "cffi (>=2.0.0b) ; platform_python_implementation != \"PyPy\" and python_version >= \"3.14\""] - [extras] -async-rl = ["TransferQueue", "math-verify", "ray", "swanlab", "vllm"] -client = ["httpx", "openai", "plotext", "textual", "tinker"] -data = ["py-data-juicer"] docs = ["docutils", "myst_parser", "recommonmark", "sphinx", "sphinx-book-theme", "sphinx-copybutton", "sphinx-rtd-theme", "sphinx_markdown_tables", "sphinxcontrib-mermaid"] -eval = ["evalscope"] -megatron = ["mcore_bridge", "megatron-core", "transformer-engine"] -rl = ["ray", "vllm"] -server = ["opentelemetry-api", "opentelemetry-exporter-otlp", "opentelemetry-instrumentation-logging", "opentelemetry-sdk", "psutil", "pynvml", "redis"] -test = ["hypothesis", "pytest", "pytest-asyncio"] +kernels = ["kernels"] +megatron = ["megatron-core", "transformer-engine"] +ray = ["ray"] +tinker = ["tinker"] +transformers = ["accelerate", "torch", "torchvision"] +vllm = ["vllm"] [metadata] lock-version = "2.1" -python-versions = ">=3.10,<=3.13" -content-hash = "2d8b26118c2aa4ef455e5e6983c89df8abc28279fb59146b867ccb9d31441b02" +python-versions = ">=3.11,<3.13" +content-hash = "6bc839d412edaa773717488aaf25cb1e5b663f305e3f9945d9f92fe1524160d2" diff --git a/pyproject.toml b/pyproject.toml index 3641f275..4b52c9c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ client = [ "plotext>=5.2.0", "openai>=1.0.0", "httpx>=0.25.0", - "tinker==0.29.0; python_version >= '3.11'", + "tinker==0.16.1", ] server = [ "redis>=5.0", diff --git a/src/twinkle/server/sampler/tinker_handlers.py b/src/twinkle/server/sampler/tinker_handlers.py index 02cef849..10b636db 100644 --- a/src/twinkle/server/sampler/tinker_handlers.py +++ b/src/twinkle/server/sampler/tinker_handlers.py @@ -8,7 +8,6 @@ import os import traceback -import uuid from collections.abc import Callable from fastapi import Depends, FastAPI, Request from tinker import types @@ -29,17 +28,16 @@ def _sampled_sequence(*, stop_reason, tokens, logprobs): return types.SampledSequence( stop_reason=stop_reason, - sequence_id=uuid.uuid4().hex, - _tokens_list=tokens, - _logprobs_list=logprobs, + tokens=tokens, + logprobs=logprobs, ) def _sample_response(*, sequences, prompt_logprobs, topk_prompt_logprobs): return types.SampleResponse( sequences=sequences, - _prompt_logprobs_list=prompt_logprobs, - _topk_prompt_logprobs_list=topk_prompt_logprobs, + prompt_logprobs=prompt_logprobs, + topk_prompt_logprobs=topk_prompt_logprobs, ) diff --git a/tests/server/contract/client_api_baseline.json b/tests/server/contract/client_api_baseline.json index 243a0567..44672f77 100644 --- a/tests/server/contract/client_api_baseline.json +++ b/tests/server/contract/client_api_baseline.json @@ -417,27 +417,6 @@ "required": true, "schema": { "$defs": { - "DmelChunk": { - "additionalProperties": false, - "properties": { - "dmel": { - "format": "binary", - "title": "Dmel", - "type": "string" - }, - "type": { - "const": "dmel", - "default": "dmel", - "title": "Type", - "type": "string" - } - }, - "required": [ - "dmel" - ], - "title": "DmelChunk", - "type": "object" - }, "EncodedTextChunk": { "additionalProperties": false, "properties": { @@ -558,9 +537,6 @@ }, { "$ref": "#/$defs/ImageChunk" - }, - { - "$ref": "#/$defs/DmelChunk" } ] }, @@ -690,18 +666,6 @@ "default": null, "title": "Prompt Logprobs" }, - "record_stability_info": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Record Stability Info" - }, "sampling_params": { "$ref": "#/$defs/SamplingParams" }, @@ -734,11 +698,6 @@ "title": "Topk Prompt Logprobs", "type": "integer" }, - "topk_sample_logprobs": { - "default": 0, - "title": "Topk Sample Logprobs", - "type": "integer" - }, "type": { "const": "sample", "default": "sample", @@ -1112,30 +1071,59 @@ "name": "body", "required": true, "schema": { - "properties": { - "forward_input": { + "$defs": { + "Datum": { + "additionalProperties": false, + "properties": { + "loss_fn_inputs": { + "additionalProperties": { + "$ref": "#/$defs/TensorData" + }, + "title": "Loss Fn Inputs", + "type": "object" + }, + "model_input": { + "$ref": "#/$defs/ModelInput" + } + }, + "required": [ + "loss_fn_inputs", + "model_input" + ], + "title": "Datum", + "type": "object" + }, + "EncodedTextChunk": { + "additionalProperties": false, + "properties": { + "tokens": { + "items": { + "type": "integer" + }, + "title": "Tokens", + "type": "array" + }, + "type": { + "const": "encoded_text", + "default": "encoded_text", + "title": "Type", + "type": "string" + } + }, + "required": [ + "tokens" + ], + "title": "EncodedTextChunk", + "type": "object" + }, + "ForwardBackwardInput": { + "additionalProperties": false, "properties": { "data": { "items": { - "properties": { - "loss_fn_input_spans": { - "pythonType": "'Optional[ProvenanceSpans]'" - }, - "loss_fn_inputs": { - "pythonType": "'LossFnInputs'" - }, - "model_input": { - "pythonType": "'ModelInput'" - }, - "model_input_spans": { - "pythonType": "'Optional[ProvenanceSpans]'" - } - }, - "required": [ - "model_input" - ], - "type": "object" + "$ref": "#/$defs/Datum" }, + "title": "Data", "type": "array" }, "loss_fn": { @@ -1145,36 +1133,202 @@ "ppo", "cispo", "dro" - ] + ], + "title": "Loss Fn", + "type": "string" }, "loss_fn_config": { "anyOf": [ { "additionalProperties": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] + "type": "number" }, "type": "object" }, { "type": "null" } - ] + ], + "default": null, + "title": "Loss Fn Config" } }, "required": [ "data", "loss_fn" ], + "title": "ForwardBackwardInput", + "type": "object" + }, + "ImageAssetPointerChunk": { + "additionalProperties": false, + "properties": { + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "location": { + "title": "Location", + "type": "string" + }, + "type": { + "const": "image_asset_pointer", + "default": "image_asset_pointer", + "title": "Type", + "type": "string" + } + }, + "required": [ + "format", + "location" + ], + "title": "ImageAssetPointerChunk", + "type": "object" + }, + "ImageChunk": { + "additionalProperties": false, + "properties": { + "data": { + "format": "binary", + "title": "Data", + "type": "string" + }, + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "type": { + "const": "image", + "default": "image", + "title": "Type", + "type": "string" + } + }, + "required": [ + "data", + "format" + ], + "title": "ImageChunk", + "type": "object" + }, + "ModelInput": { + "additionalProperties": false, + "properties": { + "chunks": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/EncodedTextChunk" + }, + { + "$ref": "#/$defs/ImageAssetPointerChunk" + }, + { + "$ref": "#/$defs/ImageChunk" + } + ] + }, + "title": "Chunks", + "type": "array" + } + }, + "required": [ + "chunks" + ], + "title": "ModelInput", + "type": "object" + }, + "TensorData": { + "additionalProperties": false, + "properties": { + "data": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "items": { + "type": "number" + }, + "type": "array" + } + ], + "title": "Data" + }, + "dtype": { + "enum": [ + "int64", + "float32" + ], + "title": "Dtype", + "type": "string" + }, + "shape": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Shape" + } + }, + "required": [ + "data", + "dtype" + ], + "title": "TensorData", "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "forward_input": { + "$ref": "#/$defs/ForwardBackwardInput" }, "model_id": { + "title": "Model Id", "type": "string" }, "seq_id": { @@ -1185,13 +1339,16 @@ { "type": "null" } - ] + ], + "default": null, + "title": "Seq Id" } }, "required": [ "forward_input", "model_id" ], + "title": "ForwardRequest", "type": "object" } } @@ -1213,31 +1370,60 @@ "name": "body", "required": true, "schema": { - "properties": { - "forward_backward_input": { + "$defs": { + "Datum": { + "additionalProperties": false, "properties": { - "data": { - "items": { - "properties": { - "loss_fn_input_spans": { - "pythonType": "'Optional[ProvenanceSpans]'" - }, - "loss_fn_inputs": { - "pythonType": "'LossFnInputs'" - }, - "model_input": { - "pythonType": "'ModelInput'" - }, - "model_input_spans": { - "pythonType": "'Optional[ProvenanceSpans]'" - } - }, - "required": [ - "model_input" - ], - "type": "object" + "loss_fn_inputs": { + "additionalProperties": { + "$ref": "#/$defs/TensorData" }, - "type": "array" + "title": "Loss Fn Inputs", + "type": "object" + }, + "model_input": { + "$ref": "#/$defs/ModelInput" + } + }, + "required": [ + "loss_fn_inputs", + "model_input" + ], + "title": "Datum", + "type": "object" + }, + "EncodedTextChunk": { + "additionalProperties": false, + "properties": { + "tokens": { + "items": { + "type": "integer" + }, + "title": "Tokens", + "type": "array" + }, + "type": { + "const": "encoded_text", + "default": "encoded_text", + "title": "Type", + "type": "string" + } + }, + "required": [ + "tokens" + ], + "title": "EncodedTextChunk", + "type": "object" + }, + "ForwardBackwardInput": { + "additionalProperties": false, + "properties": { + "data": { + "items": { + "$ref": "#/$defs/Datum" + }, + "title": "Data", + "type": "array" }, "loss_fn": { "enum": [ @@ -1246,36 +1432,202 @@ "ppo", "cispo", "dro" - ] + ], + "title": "Loss Fn", + "type": "string" }, "loss_fn_config": { "anyOf": [ { "additionalProperties": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] + "type": "number" }, "type": "object" }, { "type": "null" } - ] + ], + "default": null, + "title": "Loss Fn Config" } }, "required": [ "data", "loss_fn" ], + "title": "ForwardBackwardInput", + "type": "object" + }, + "ImageAssetPointerChunk": { + "additionalProperties": false, + "properties": { + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "location": { + "title": "Location", + "type": "string" + }, + "type": { + "const": "image_asset_pointer", + "default": "image_asset_pointer", + "title": "Type", + "type": "string" + } + }, + "required": [ + "format", + "location" + ], + "title": "ImageAssetPointerChunk", + "type": "object" + }, + "ImageChunk": { + "additionalProperties": false, + "properties": { + "data": { + "format": "binary", + "title": "Data", + "type": "string" + }, + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "type": { + "const": "image", + "default": "image", + "title": "Type", + "type": "string" + } + }, + "required": [ + "data", + "format" + ], + "title": "ImageChunk", + "type": "object" + }, + "ModelInput": { + "additionalProperties": false, + "properties": { + "chunks": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/EncodedTextChunk" + }, + { + "$ref": "#/$defs/ImageAssetPointerChunk" + }, + { + "$ref": "#/$defs/ImageChunk" + } + ] + }, + "title": "Chunks", + "type": "array" + } + }, + "required": [ + "chunks" + ], + "title": "ModelInput", + "type": "object" + }, + "TensorData": { + "additionalProperties": false, + "properties": { + "data": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "items": { + "type": "number" + }, + "type": "array" + } + ], + "title": "Data" + }, + "dtype": { + "enum": [ + "int64", + "float32" + ], + "title": "Dtype", + "type": "string" + }, + "shape": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Shape" + } + }, + "required": [ + "data", + "dtype" + ], + "title": "TensorData", "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "forward_backward_input": { + "$ref": "#/$defs/ForwardBackwardInput" }, "model_id": { + "title": "Model Id", "type": "string" }, "seq_id": { @@ -1286,13 +1638,16 @@ { "type": "null" } - ] + ], + "default": null, + "title": "Seq Id" } }, "required": [ "forward_backward_input", "model_id" ], + "title": "ForwardBackwardRequest", "type": "object" } } @@ -1358,18 +1713,6 @@ "SupportedModel": { "description": "Information about a model supported by the server.", "properties": { - "max_context_length": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Max Context Length" - }, "model_name": { "anyOf": [ { @@ -1381,30 +1724,6 @@ ], "default": null, "title": "Model Name" - }, - "sampleable": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sampleable" - }, - "trainable": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Trainable" } }, "title": "SupportedModel", @@ -1466,107 +1785,39 @@ "schema": { "additionalProperties": false, "properties": { - "base_model": { + "model_id": { + "title": "Model Id", + "type": "string" + }, + "optimizer": { + "title": "Optimizer", + "type": "boolean" + }, + "path": { + "title": "Path", + "type": "string" + }, + "seq_id": { "anyOf": [ { - "type": "string" + "type": "integer" }, { "type": "null" } ], "default": null, - "title": "Base Model" - }, - "model_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Model Id" - }, - "model_seq_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Model Seq Id" - }, - "optimizer": { - "title": "Optimizer", - "type": "boolean" - }, - "path": { - "title": "Path", - "type": "string" - }, - "seq_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Seq Id" - }, - "session_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Session Id" + "title": "Seq Id" }, "type": { "const": "load_weights", "default": "load_weights", "title": "Type", "type": "string" - }, - "user_metadata": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "User Metadata" - }, - "weights_access_token": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Weights Access Token" } }, "required": [ + "model_id", "path", "optimizer" ], @@ -1743,11 +1994,6 @@ "title": "Model Id", "type": "string" }, - "overwrite": { - "default": false, - "title": "Overwrite", - "type": "boolean" - }, "path": { "anyOf": [ { @@ -1789,21 +2035,6 @@ "default": "save_weights", "title": "Type", "type": "string" - }, - "user_metadata": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "User Metadata" } }, "required": [ @@ -1890,21 +2121,6 @@ "default": "save_weights_for_sampler", "title": "Type", "type": "string" - }, - "user_metadata": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "User Metadata" } }, "required": [ @@ -2235,10 +2451,6 @@ "title": "Platform", "type": "string" }, - "process_uuid": { - "title": "Process Uuid", - "type": "string" - }, "sdk_version": { "title": "Sdk Version", "type": "string" @@ -2252,8 +2464,7 @@ "events", "platform", "sdk_version", - "session_id", - "process_uuid" + "session_id" ], "title": "TelemetrySendRequest", "type": "object" @@ -2317,8 +2528,7 @@ "checkpoint_type": { "enum": [ "training", - "sampler", - "external" + "sampler" ], "title": "Checkpoint Type", "type": "string" @@ -2361,21 +2571,6 @@ "tinker_path": { "title": "Tinker Path", "type": "string" - }, - "user_metadata": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "User Metadata" } }, "required": [ @@ -2549,8 +2744,7 @@ "checkpoint_type": { "enum": [ "training", - "sampler", - "external" + "sampler" ], "title": "Checkpoint Type", "type": "string" @@ -2593,21 +2787,6 @@ "tinker_path": { "title": "Tinker Path", "type": "string" - }, - "user_metadata": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "User Metadata" } }, "required": [ @@ -2738,8 +2917,7 @@ "checkpoint_type": { "enum": [ "training", - "sampler", - "external" + "sampler" ], "title": "Checkpoint Type", "type": "string" @@ -2782,21 +2960,6 @@ "tinker_path": { "title": "Tinker Path", "type": "string" - }, - "user_metadata": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "User Metadata" } }, "required": [ @@ -2862,7 +3025,7 @@ "statusCode": 200 } }, - "/training_runs/{run_id}/checkpoints/{checkpoint_id:path}": { + "/training_runs/{run_id}/checkpoints/{checkpoint_id}": { "DELETE": { "body": [], "cookies": [], @@ -2890,7 +3053,7 @@ "statusCode": 200 } }, - "/training_runs/{run_id}/checkpoints/{checkpoint_id:path}/publish": { + "/training_runs/{run_id}/checkpoints/{checkpoint_id}/publish": { "POST": { "body": [], "cookies": [], @@ -2956,7 +3119,7 @@ "statusCode": 200 } }, - "/twinkle/checkpoint_path/{run_id}/{checkpoint_id:path}": { + "/twinkle/checkpoint_path/{run_id}/{checkpoint_id}": { "GET": { "body": [], "cookies": [], @@ -3692,7 +3855,7 @@ "statusCode": 200 } }, - "/twinkle/training_runs/{run_id}/checkpoints/{checkpoint_id:path}": { + "/twinkle/training_runs/{run_id}/checkpoints/{checkpoint_id}": { "DELETE": { "body": [], "cookies": [], @@ -4080,21 +4243,6 @@ "request_id": { "title": "Request Id", "type": "string" - }, - "sample_sequence_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sample Sequence Ids" } }, "required": [ @@ -4114,30 +4262,59 @@ "name": "body", "required": true, "schema": { - "properties": { - "forward_input": { + "$defs": { + "Datum": { + "additionalProperties": false, + "properties": { + "loss_fn_inputs": { + "additionalProperties": { + "$ref": "#/$defs/TensorData" + }, + "title": "Loss Fn Inputs", + "type": "object" + }, + "model_input": { + "$ref": "#/$defs/ModelInput" + } + }, + "required": [ + "loss_fn_inputs", + "model_input" + ], + "title": "Datum", + "type": "object" + }, + "EncodedTextChunk": { + "additionalProperties": false, + "properties": { + "tokens": { + "items": { + "type": "integer" + }, + "title": "Tokens", + "type": "array" + }, + "type": { + "const": "encoded_text", + "default": "encoded_text", + "title": "Type", + "type": "string" + } + }, + "required": [ + "tokens" + ], + "title": "EncodedTextChunk", + "type": "object" + }, + "ForwardBackwardInput": { + "additionalProperties": false, "properties": { "data": { "items": { - "properties": { - "loss_fn_input_spans": { - "pythonType": "'Optional[ProvenanceSpans]'" - }, - "loss_fn_inputs": { - "pythonType": "'LossFnInputs'" - }, - "model_input": { - "pythonType": "'ModelInput'" - }, - "model_input_spans": { - "pythonType": "'Optional[ProvenanceSpans]'" - } - }, - "required": [ - "model_input" - ], - "type": "object" + "$ref": "#/$defs/Datum" }, + "title": "Data", "type": "array" }, "loss_fn": { @@ -4147,53 +4324,222 @@ "ppo", "cispo", "dro" - ] + ], + "title": "Loss Fn", + "type": "string" }, "loss_fn_config": { "anyOf": [ { "additionalProperties": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] + "type": "number" }, "type": "object" }, { "type": "null" } - ] + ], + "default": null, + "title": "Loss Fn Config" } }, "required": [ "data", "loss_fn" ], + "title": "ForwardBackwardInput", "type": "object" }, - "model_id": { - "type": "string" - }, - "seq_id": { - "anyOf": [ - { - "type": "integer" + "ImageAssetPointerChunk": { + "additionalProperties": false, + "properties": { + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" }, - { - "type": "null" + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "location": { + "title": "Location", + "type": "string" + }, + "type": { + "const": "image_asset_pointer", + "default": "image_asset_pointer", + "title": "Type", + "type": "string" } - ] + }, + "required": [ + "format", + "location" + ], + "title": "ImageAssetPointerChunk", + "type": "object" + }, + "ImageChunk": { + "additionalProperties": false, + "properties": { + "data": { + "format": "binary", + "title": "Data", + "type": "string" + }, + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "type": { + "const": "image", + "default": "image", + "title": "Type", + "type": "string" + } + }, + "required": [ + "data", + "format" + ], + "title": "ImageChunk", + "type": "object" + }, + "ModelInput": { + "additionalProperties": false, + "properties": { + "chunks": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/EncodedTextChunk" + }, + { + "$ref": "#/$defs/ImageAssetPointerChunk" + }, + { + "$ref": "#/$defs/ImageChunk" + } + ] + }, + "title": "Chunks", + "type": "array" + } + }, + "required": [ + "chunks" + ], + "title": "ModelInput", + "type": "object" + }, + "TensorData": { + "additionalProperties": false, + "properties": { + "data": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "items": { + "type": "number" + }, + "type": "array" + } + ], + "title": "Data" + }, + "dtype": { + "enum": [ + "int64", + "float32" + ], + "title": "Dtype", + "type": "string" + }, + "shape": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Shape" + } + }, + "required": [ + "data", + "dtype" + ], + "title": "TensorData", + "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "forward_input": { + "$ref": "#/$defs/ForwardBackwardInput" + }, + "model_id": { + "title": "Model Id", + "type": "string" + }, + "seq_id": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Seq Id" } }, "required": [ "forward_input", "model_id" ], + "title": "ForwardRequest", "type": "object" } } @@ -4220,21 +4566,6 @@ "request_id": { "title": "Request Id", "type": "string" - }, - "sample_sequence_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sample Sequence Ids" } }, "required": [ @@ -4254,69 +4585,264 @@ "name": "body", "required": true, "schema": { - "properties": { - "forward_backward_input": { + "$defs": { + "Datum": { + "additionalProperties": false, + "properties": { + "loss_fn_inputs": { + "additionalProperties": { + "$ref": "#/$defs/TensorData" + }, + "title": "Loss Fn Inputs", + "type": "object" + }, + "model_input": { + "$ref": "#/$defs/ModelInput" + } + }, + "required": [ + "loss_fn_inputs", + "model_input" + ], + "title": "Datum", + "type": "object" + }, + "EncodedTextChunk": { + "additionalProperties": false, + "properties": { + "tokens": { + "items": { + "type": "integer" + }, + "title": "Tokens", + "type": "array" + }, + "type": { + "const": "encoded_text", + "default": "encoded_text", + "title": "Type", + "type": "string" + } + }, + "required": [ + "tokens" + ], + "title": "EncodedTextChunk", + "type": "object" + }, + "ForwardBackwardInput": { + "additionalProperties": false, "properties": { "data": { "items": { - "properties": { - "loss_fn_input_spans": { - "pythonType": "'Optional[ProvenanceSpans]'" + "$ref": "#/$defs/Datum" + }, + "title": "Data", + "type": "array" + }, + "loss_fn": { + "enum": [ + "cross_entropy", + "importance_sampling", + "ppo", + "cispo", + "dro" + ], + "title": "Loss Fn", + "type": "string" + }, + "loss_fn_config": { + "anyOf": [ + { + "additionalProperties": { + "type": "number" }, - "loss_fn_inputs": { - "pythonType": "'LossFnInputs'" + "type": "object" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Loss Fn Config" + } + }, + "required": [ + "data", + "loss_fn" + ], + "title": "ForwardBackwardInput", + "type": "object" + }, + "ImageAssetPointerChunk": { + "additionalProperties": false, + "properties": { + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "location": { + "title": "Location", + "type": "string" + }, + "type": { + "const": "image_asset_pointer", + "default": "image_asset_pointer", + "title": "Type", + "type": "string" + } + }, + "required": [ + "format", + "location" + ], + "title": "ImageAssetPointerChunk", + "type": "object" + }, + "ImageChunk": { + "additionalProperties": false, + "properties": { + "data": { + "format": "binary", + "title": "Data", + "type": "string" + }, + "expected_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "default": null, + "title": "Expected Tokens" + }, + "format": { + "enum": [ + "png", + "jpeg" + ], + "title": "Format", + "type": "string" + }, + "type": { + "const": "image", + "default": "image", + "title": "Type", + "type": "string" + } + }, + "required": [ + "data", + "format" + ], + "title": "ImageChunk", + "type": "object" + }, + "ModelInput": { + "additionalProperties": false, + "properties": { + "chunks": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/EncodedTextChunk" + }, + { + "$ref": "#/$defs/ImageAssetPointerChunk" }, - "model_input": { - "pythonType": "'ModelInput'" + { + "$ref": "#/$defs/ImageChunk" + } + ] + }, + "title": "Chunks", + "type": "array" + } + }, + "required": [ + "chunks" + ], + "title": "ModelInput", + "type": "object" + }, + "TensorData": { + "additionalProperties": false, + "properties": { + "data": { + "anyOf": [ + { + "items": { + "type": "integer" + }, + "type": "array" + }, + { + "items": { + "type": "number" }, - "model_input_spans": { - "pythonType": "'Optional[ProvenanceSpans]'" - } - }, - "required": [ - "model_input" - ], - "type": "object" - }, - "type": "array" + "type": "array" + } + ], + "title": "Data" }, - "loss_fn": { + "dtype": { "enum": [ - "cross_entropy", - "importance_sampling", - "ppo", - "cispo", - "dro" - ] + "int64", + "float32" + ], + "title": "Dtype", + "type": "string" }, - "loss_fn_config": { + "shape": { "anyOf": [ { - "additionalProperties": { - "anyOf": [ - { - "type": "number" - }, - { - "type": "string" - } - ] + "items": { + "type": "integer" }, - "type": "object" + "type": "array" }, { "type": "null" } - ] + ], + "default": null, + "title": "Shape" } }, "required": [ "data", - "loss_fn" + "dtype" ], + "title": "TensorData", "type": "object" + } + }, + "additionalProperties": false, + "properties": { + "forward_backward_input": { + "$ref": "#/$defs/ForwardBackwardInput" }, "model_id": { + "title": "Model Id", "type": "string" }, "seq_id": { @@ -4327,13 +4853,16 @@ { "type": "null" } - ] + ], + "default": null, + "title": "Seq Id" } }, "required": [ "forward_backward_input", "model_id" ], + "title": "ForwardBackwardRequest", "type": "object" } } @@ -4360,21 +4889,6 @@ "request_id": { "title": "Request Id", "type": "string" - }, - "sample_sequence_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sample Sequence Ids" } }, "required": [ @@ -4545,41 +5059,9 @@ "schema": { "additionalProperties": false, "properties": { - "base_model": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Base Model" - }, "model_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Model Id" - }, - "model_seq_id": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Model Seq Id" + "title": "Model Id", + "type": "string" }, "optimizer": { "title": "Optimizer", @@ -4601,51 +5083,15 @@ "default": null, "title": "Seq Id" }, - "session_id": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Session Id" - }, "type": { "const": "load_weights", "default": "load_weights", "title": "Type", "type": "string" - }, - "user_metadata": { - "anyOf": [ - { - "additionalProperties": true, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "User Metadata" - }, - "weights_access_token": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Weights Access Token" } }, "required": [ + "model_id", "path", "optimizer" ], @@ -4676,21 +5122,6 @@ "request_id": { "title": "Request Id", "type": "string" - }, - "sample_sequence_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sample Sequence Ids" } }, "required": [ @@ -4808,21 +5239,6 @@ "request_id": { "title": "Request Id", "type": "string" - }, - "sample_sequence_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sample Sequence Ids" } }, "required": [ @@ -4848,11 +5264,6 @@ "title": "Model Id", "type": "string" }, - "overwrite": { - "default": false, - "title": "Overwrite", - "type": "boolean" - }, "path": { "anyOf": [ { @@ -4894,21 +5305,6 @@ "default": "save_weights", "title": "Type", "type": "string" - }, - "user_metadata": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "User Metadata" } }, "required": [ @@ -4941,21 +5337,6 @@ "request_id": { "title": "Request Id", "type": "string" - }, - "sample_sequence_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sample Sequence Ids" } }, "required": [ @@ -5034,21 +5415,6 @@ "default": "save_weights_for_sampler", "title": "Type", "type": "string" - }, - "user_metadata": { - "anyOf": [ - { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - { - "type": "null" - } - ], - "default": null, - "title": "User Metadata" } }, "required": [ @@ -5081,21 +5447,6 @@ "request_id": { "title": "Request Id", "type": "string" - }, - "sample_sequence_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sample Sequence Ids" } }, "required": [ @@ -5158,21 +5509,6 @@ "request_id": { "title": "Request Id", "type": "string" - }, - "sample_sequence_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sample Sequence Ids" } }, "required": [ @@ -6948,27 +7284,6 @@ "required": true, "schema": { "$defs": { - "DmelChunk": { - "additionalProperties": false, - "properties": { - "dmel": { - "format": "binary", - "title": "Dmel", - "type": "string" - }, - "type": { - "const": "dmel", - "default": "dmel", - "title": "Type", - "type": "string" - } - }, - "required": [ - "dmel" - ], - "title": "DmelChunk", - "type": "object" - }, "EncodedTextChunk": { "additionalProperties": false, "properties": { @@ -7089,9 +7404,6 @@ }, { "$ref": "#/$defs/ImageChunk" - }, - { - "$ref": "#/$defs/DmelChunk" } ] }, @@ -7221,18 +7533,6 @@ "default": null, "title": "Prompt Logprobs" }, - "record_stability_info": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Record Stability Info" - }, "sampling_params": { "$ref": "#/$defs/SamplingParams" }, @@ -7265,11 +7565,6 @@ "title": "Topk Prompt Logprobs", "type": "integer" }, - "topk_sample_logprobs": { - "default": 0, - "title": "Topk Sample Logprobs", - "type": "integer" - }, "type": { "const": "sample", "default": "sample", @@ -7308,21 +7603,6 @@ "request_id": { "title": "Request Id", "type": "string" - }, - "sample_sequence_ids": { - "anyOf": [ - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ], - "default": null, - "title": "Sample Sequence Ids" } }, "required": [ diff --git a/tests/server/contract/client_api_harness.py b/tests/server/contract/client_api_harness.py index 919639bb..59d4ac5a 100644 --- a/tests/server/contract/client_api_harness.py +++ b/tests/server/contract/client_api_harness.py @@ -27,6 +27,7 @@ import dataclasses import json +import re import sys import types as pytypes from collections.abc import Callable, Mapping, Sequence @@ -155,11 +156,11 @@ def _type_contract(annotation: Any, seen: frozenset[str] = frozenset()) -> Any: def _parameter_contract(field: Any) -> dict[str, Any]: - annotation = getattr(field.field_info, 'annotation', field.type_) + field_info = field.field_info return { 'name': field.alias, - 'required': bool(field.required), - 'schema': _type_contract(annotation), + 'required': bool(field_info.is_required()), + 'schema': _type_contract(field_info.annotation), } @@ -188,7 +189,8 @@ def _extract_app_surface(app: FastAPI) -> dict[str, Any]: 'statusCode': route.status_code or 200, } for method in sorted(route.methods & _HTTP_METHODS): - paths.setdefault(route.path, {})[method] = operation + client_path = re.sub(r'{([^}:]+):[^}]+}', r'{\1}', route.path) + paths.setdefault(client_path, {})[method] = operation return {'paths': paths} diff --git a/tests/server/model/test_twinkle_async_inputs.py b/tests/server/model/test_twinkle_async_inputs.py index 7a13b73c..3221394a 100644 --- a/tests/server/model/test_twinkle_async_inputs.py +++ b/tests/server/model/test_twinkle_async_inputs.py @@ -63,6 +63,9 @@ async def schedule_task_and_wait(self, task, **kwargs): self.scheduled.append(kwargs) return await task() + async def call_backend(self, fn, /, *args, admit=True, **kwargs): + return fn(*args, **kwargs) + @pytest.mark.asyncio async def test_forward_backward_resolves_multiple_data_refs_and_field_kwargs() -> None: diff --git a/tests/server/sampler/test_tinker_handlers.py b/tests/server/sampler/test_tinker_handlers.py index 77a15ce6..1c072762 100644 --- a/tests/server/sampler/test_tinker_handlers.py +++ b/tests/server/sampler/test_tinker_handlers.py @@ -75,5 +75,4 @@ async def test_tinker_asample_allows_base_model_session_without_model_path(): assert isinstance(response, types.SampleResponse) assert response.sequences[0].tokens == [1, 2] - assert response.sequences[0].sequence_id assert management.sampler.adapter_paths == [None] diff --git a/tests/server/sampler/test_twinkle_async_rows.py b/tests/server/sampler/test_twinkle_async_rows.py index 30b7016b..234437be 100644 --- a/tests/server/sampler/test_twinkle_async_rows.py +++ b/tests/server/sampler/test_twinkle_async_rows.py @@ -1,5 +1,7 @@ from __future__ import annotations +from types import SimpleNamespace + import pytest from fastapi import FastAPI from starlette.requests import Request @@ -67,6 +69,7 @@ def __init__(self): self.enabled = True self.scheduled = [] self.put_rows = None + self._task_queue_config = SimpleNamespace(effective_execution_timeout=60.0) async def _on_request_start(self, _request): return 'token' @@ -75,6 +78,9 @@ async def schedule_task_and_wait(self, task, **kwargs): self.scheduled.append(kwargs) return await task() + async def call_backend(self, fn, /, *args, admit=True, **kwargs): + return fn(*args, **kwargs) + def submit_generation(self, submission_id, inputs, params, **kwargs): self.submission_id = submission_id self.inputs = inputs From 4bc9bebae8886efd65f857271f8c5cbe825ec662 Mon Sep 17 00:00:00 2001 From: Yunnglin Date: Wed, 16 Sep 2026 12:27:55 +0000 Subject: [PATCH 14/14] fix(server): harden tinker GRPO execution guarantees --- src/twinkle/loss/grpo.py | 12 +++-- .../sampler/vllm_sampler/vllm_sampler.py | 8 ++++ src/twinkle/server/sampler/tinker_handlers.py | 10 +++- tests/loss/test_grpo_gkd.py | 21 ++++++++ tests/server/README.md | 27 ----------- tests/server/conftest.py | 11 ++++- tests/server/integration/e2e_helpers.py | 27 +++++++++-- .../integration/test_nccl_safe_tinker_e2e.py | 48 +++++++++++++++---- .../integration/test_nccl_safe_twinkle_e2e.py | 20 +++++++- tests/server/sampler/test_tinker_handlers.py | 3 ++ 10 files changed, 140 insertions(+), 47 deletions(-) delete mode 100644 tests/server/README.md diff --git a/src/twinkle/loss/grpo.py b/src/twinkle/loss/grpo.py index e146edee..2bf8d39f 100644 --- a/src/twinkle/loss/grpo.py +++ b/src/twinkle/loss/grpo.py @@ -202,14 +202,16 @@ def _pad_and_align_to_batch( elif n_sample == n_pos: # Response-only form (e.g. old_logps from vLLM). result[i, pos] = sample - elif n_sample >= seq_len: - # Full-sequence form (e.g. ref_logps right-padded with ignore-value). - result[i, pos] = sample[:seq_len][mask[i]] + elif n_pos == 0 or (n_sample > 0 and pos[-1].item() < n_sample): + # Variable-length full-sequence form. The processor right-pads the + # batch, but per-sample RL fields from Tinker remain unpadded. They + # are valid when every selected mask position exists in this row. + result[i, pos] = sample[pos] else: raise AssertionError(f'data/mask length mismatch at sample {i}: ' f'n_pos={n_pos}, n_sample={n_sample}, seq_len={seq_len} ' - '(expected n_sample == n_pos for response-only form, ' - 'or n_sample >= seq_len for full-sequence form)') + '(expected n_sample == n_pos for response-only form, or all masked positions ' + 'to exist in the per-sample full-sequence form)') return result diff --git a/src/twinkle/sampler/vllm_sampler/vllm_sampler.py b/src/twinkle/sampler/vllm_sampler/vllm_sampler.py index fe68b9d7..6438fa66 100644 --- a/src/twinkle/sampler/vllm_sampler/vllm_sampler.py +++ b/src/twinkle/sampler/vllm_sampler/vllm_sampler.py @@ -251,6 +251,14 @@ async def _sample_single( else: feat['input_ids'] = response.prompt_token_ids feat['labels'] = [-100] * len(response.prompt_token_ids) + # A sampling prompt (e.g. a tinker ModelInput) carries input_ids but no labels; + # concat_input_feature would then derive a zero-length prefix completion_mask + # and raise. The prompt is pure context, so materialise aligned all-context + # labels when they are missing or length-mismatched. Present, aligned labels are + # left untouched (preserving provenance), and the logprobs-only path -- which + # never concatenates -- is not touched. + if not logprobs_only and 'input_ids' in feat and len(feat.get('labels') or []) != len(feat['input_ids']): + feat['labels'] = [-100] * len(feat['input_ids']) sequences = [] for seq in response.sequences: if logprobs_only: diff --git a/src/twinkle/server/sampler/tinker_handlers.py b/src/twinkle/server/sampler/tinker_handlers.py index 10b636db..3f879001 100644 --- a/src/twinkle/server/sampler/tinker_handlers.py +++ b/src/twinkle/server/sampler/tinker_handlers.py @@ -99,6 +99,10 @@ async def _do_sample(): top_p=body.sampling_params.top_p, top_k=body.sampling_params.top_k, stop=body.sampling_params.stop, + # tinker 0.16.1 has no SamplingParams.logprobs field, but its + # SampledSequence contract and GRPO training require one + # chosen-token logprob per generated token. + logprobs=1, ) # A resolved checkpoint is either a LoRA adapter dir (has @@ -131,8 +135,12 @@ async def _do_sample(): flattened = [float(lp_list[0][1]) for lp_list in seq.logprobs if lp_list] except (IndexError, TypeError): flattened = [] - if flattened and len(flattened) == len(seq.logprobs): + if len(flattened) == len(seq.tokens): logprobs = flattened + else: + raise RuntimeError( + f'Sampler returned {len(flattened)} logprobs for {len(seq.tokens)} generated ' + 'tokens; refusing to return a misaligned Tinker SampledSequence.') tinker_sequences.append( _sampled_sequence( stop_reason=seq.stop_reason, diff --git a/tests/loss/test_grpo_gkd.py b/tests/loss/test_grpo_gkd.py index 3d0f5512..1f9daa70 100644 --- a/tests/loss/test_grpo_gkd.py +++ b/tests/loss/test_grpo_gkd.py @@ -82,6 +82,27 @@ def test_grpo_list_advantages(self): result = loss_fn(inputs, outputs, old_logps=old_logps, advantages=adv_list) assert torch.isfinite(result['loss']) + def test_pad_variable_length_full_sequence_rows(self): + """Unpadded per-sample rows align against a right-padded batch mask.""" + mask = torch.tensor([ + [False, True, True, False, False], + [False, False, True, True, True], + ]) + rows = [ + [-9.0, 0.1, 0.2], + [-9.0, -9.0, 0.3, 0.4, 0.5], + ] + + got = GRPOLoss()._pad_and_align_to_batch(rows, mask, mask.device, torch.float32) + + assert torch.equal(got[0], torch.tensor([0.0, 0.1, 0.2, 0.0, 0.0])) + assert torch.equal(got[1], torch.tensor([0.0, 0.0, 0.3, 0.4, 0.5])) + + def test_pad_rejects_full_sequence_missing_a_masked_position(self): + mask = torch.tensor([[False, False, True, True, True]]) + with pytest.raises(AssertionError, match='all masked positions'): + GRPOLoss()._pad_and_align_to_batch([[0.1, 0.2, 0.3, 0.4]], mask, mask.device, torch.float32) + def test_grpo_weights_sequences_equally(self): labels = torch.tensor([ [1, -100, -100], diff --git a/tests/server/README.md b/tests/server/README.md deleted file mode 100644 index 49adf2cb..00000000 --- a/tests/server/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Server test notes - -## Mock backend evidence boundary (spec T8.4 / R9#10) - -`server/model/backends/mock_model.py` is a stand-in backend for tests that must run -without a GPU or a real Ray-distributed model. Two properties bound what a test using -it can prove: - -1. **Every method takes `**kwargs` and performs no argument validation.** A test that - drives the mock backend therefore **cannot** be used as evidence for request/argument - validation behavior — the mock accepts anything. -2. **It never enters a real collective.** The mock does no NCCL communication, so a test - using it **cannot** be used as evidence for NCCL behavior (asymmetric failure, - collective mis-pairing, ReduceScatter, etc.). - -What the mock backend *can* evidence is exactly the parts that do not depend on the -backend's internals: the **dispatch path** (that a call reaches the backend via -`call_backend` / the task queue) and the **timeout / admission mechanisms** themselves -(that a slow or leaked call is bounded and the event loop stays responsive). - -Tests that need to prove validation or NCCL behavior are the GPU-gated end-to-end tests -under `tests/server/integration/test_nccl_safe_*_e2e.py` (run only with -`TWINKLE_TEST_GPU_E2E=1` against a real server configured with the test execution timeout). - -The contract suite covers all five apps and recursively snapshots request and response -types. Tinker compatibility assertions follow the 0.29.0 SDK wire values. The blocking -boundary suite uses a real serial Ray actor for the health-probe timing case. diff --git a/tests/server/conftest.py b/tests/server/conftest.py index 4ac4d24f..fea2e62c 100644 --- a/tests/server/conftest.py +++ b/tests/server/conftest.py @@ -1,5 +1,5 @@ # Copyright (c) ModelScope Contributors. All rights reserved. -"""Shared Ray runtime + per-test isolation for ``tests/server`` (state, cli, ...). +"""Shared Ray runtime, per-test isolation, and evidence boundaries. ``RayActorBackend`` is a forwarding wrapper around a detached Ray actor; instantiating one without an initialized Ray runtime raises @@ -12,6 +12,15 @@ of the actor wrapper. To keep tests independent we clear that actor's store before each test function. Tests that pin a non-default ``key_prefix`` get their own actor; this fixture intentionally leaves those alone. + +Evidence boundary (spec T8.4 / R9#10): every mock-model backend method accepts +``**kwargs`` without argument validation, and the mock enters no real collective. +A mock-backed test therefore proves neither request/argument validation nor NCCL +behavior (asymmetric failure, collective mis-pairing, ReduceScatter, etc.). It may +prove only backend dispatch, task-queue behavior, timeout/admission mechanisms, +and event-loop responsiveness. Validation and NCCL claims require the GPU-gated +``test_nccl_safe_*_e2e.py`` tests against a real server. The contract suite covers +all five apps; Tinker compatibility follows the pinned 0.16.1 SDK wire values. """ from __future__ import annotations diff --git a/tests/server/integration/e2e_helpers.py b/tests/server/integration/e2e_helpers.py index 9d3073ba..2eca95f0 100644 --- a/tests/server/integration/e2e_helpers.py +++ b/tests/server/integration/e2e_helpers.py @@ -22,7 +22,9 @@ MODEL_ID = f'ms://{BASE_MODEL}' BASE_URL = os.environ.get('TWINKLE_SERVER_URL', 'http://localhost:9000') API_KEY = 'EMPTY_API_KEY' -TIMEOUT = 120 # seconds per operation before declaring hang +TIMEOUT = float(os.environ.get('TWINKLE_TEST_OPERATION_TIMEOUT', '120')) +# Per-operation hang threshold. PPU Megatron cold JIT can exceed 300s; callers may +# raise this without weakening the default CI/GPU bound. GRADIENT_ACCUMULATION_STEPS = 2 # Megatron requires GA >= 2 @@ -66,6 +68,17 @@ def log(msg: str) -> None: # Dataset Factories # ═══════════════════════════════════════════════════════════════════════════ + +def _local_arrow_dataset(path: str, data_slice): + """Load selected rows from cached Arrow without hub metadata access.""" + from datasets import Dataset as HFDataset + from twinkle.dataset import Dataset, DatasetMeta + + source = HFDataset.from_file(path) + indices = [index % len(source) for index in data_slice] + return Dataset(DatasetMeta(data=source.select(indices))) + + def create_sft_dataset(data_slice=range(100)): """Create SelfCognition SFT dataset (small slice for speed).""" from twinkle.dataloader import DataLoader @@ -83,7 +96,11 @@ def create_dpo_dataset(data_slice=range(50)): from twinkle.dataset import Dataset, DatasetMeta from twinkle.preprocessor import EmojiDPOProcessor - dataset = Dataset(DatasetMeta('ms://hjh0119/shareAI-Llama3-DPO-zh-en-emoji', data_slice=data_slice)) + local_arrow = os.environ.get('TWINKLE_TEST_DPO_ARROW') + if local_arrow: + dataset = _local_arrow_dataset(local_arrow, data_slice) + else: + dataset = Dataset(DatasetMeta('ms://hjh0119/shareAI-Llama3-DPO-zh-en-emoji', data_slice=data_slice)) dataset.set_template('Qwen3_5Template', model_id=MODEL_ID, max_length=1024) dataset.map(EmojiDPOProcessor, init_args={'system': 'You are a helpful assistant.'}) dataset.encode() @@ -97,7 +114,11 @@ def create_grpo_dataset(data_slice=range(50)): system_prompt = ('You are a helpful math assistant. Solve the problem with minimal but correct reasoning ' 'and put your final answer within \\boxed{}.') - dataset = Dataset(DatasetMeta('ms://modelscope/gsm8k', subset_name='main', split='train', data_slice=data_slice)) + local_arrow = os.environ.get('TWINKLE_TEST_GRPO_ARROW') + if local_arrow: + dataset = _local_arrow_dataset(local_arrow, data_slice) + else: + dataset = Dataset(DatasetMeta('ms://modelscope/gsm8k', subset_name='main', split='train', data_slice=data_slice)) dataset.set_template('Qwen3_5Template', model_id=MODEL_ID, max_length=2048, enable_thinking=False) dataset.map(GSM8KProcessor(system=system_prompt)) dataset.encode(add_generation_prompt=True) diff --git a/tests/server/integration/test_nccl_safe_tinker_e2e.py b/tests/server/integration/test_nccl_safe_tinker_e2e.py index 4846a2bc..155f2738 100644 --- a/tests/server/integration/test_nccl_safe_tinker_e2e.py +++ b/tests/server/integration/test_nccl_safe_tinker_e2e.py @@ -31,6 +31,11 @@ SERVER_URL = os.environ.get('TWINKLE_SERVER_URL', 'http://localhost:9000') EXECUTION_TIMEOUT = float(os.environ.get('TWINKLE_TEST_EXECUTION_TIMEOUT', '30')) TIMEOUT = EXECUTION_TIMEOUT + 15 +# The `global_rank=` attribution is added by `nccl_safe_megatron`, which decorates +# only the Megatron backend; the transformers backend carries no such annotation +# (its former silent-degradation decorator was removed by R6#3). Gate the rank-attribution assertion +# on the backend so this file is safe under TWINKLE_TEST_BACKEND=transformers. +BACKEND = os.environ.get('TWINKLE_TEST_BACKEND', 'megatron') def _init_client(): @@ -83,11 +88,23 @@ def test_failure_is_terminal_then_valid_request_succeeds(): assert caught.value.category is types.RequestErrorCategory.Server assert time.time() - start < TIMEOUT, 'malformed request must fail fast, not hang (NCCL)' - # Recovery: a subsequent valid request on the same deployment must succeed. + # Recovery: megatron commits the DDP reducer inside its fused forward_backward, so + # a subsequent valid request must succeed. The tinker transformers path runs + # forward()/loss/backward() separately; a mid-iteration loss failure leaves DDP's + # reducer half-finished and poisons the next request, so the spec only guarantees a + # *terminal* response there (R6#14), not success. (tinker 0.16.1 exposes no GA knob.) good = [_make_datum() for _ in range(4)] - result = tc.forward_backward(good, 'importance_sampling').result() - assert result is not None - tc.optim_step(types.AdamParams(learning_rate=1e-5)).result() + if BACKEND == 'megatron': + result = tc.forward_backward(good, 'importance_sampling').result() + assert result is not None + tc.optim_step(types.AdamParams(learning_rate=1e-5)).result() + else: + try: + result = tc.forward_backward(good, 'importance_sampling').result(timeout=TIMEOUT) + assert result is not None + tc.optim_step(types.AdamParams(learning_rate=1e-5)).result() + except RequestFailedError as exc: + assert exc.category is types.RequestErrorCategory.Server def test_partial_rank_failure_is_terminal_then_recovers(): @@ -101,9 +118,24 @@ def test_partial_rank_failure_is_terminal_then_recovers(): with pytest.raises(RequestFailedError) as caught: tc.forward_backward(batch, 'importance_sampling').result(timeout=TIMEOUT) assert caught.value.category is types.RequestErrorCategory.Server - assert 'global_rank=' in str(caught.value) + # Megatron attributes the failure to a global rank via nccl_safe_megatron; the + # transformers backend has no such annotation (R6#3 removed its old decorator). + if BACKEND == 'megatron': + assert 'global_rank=' in str(caught.value) assert time.time() - start < TIMEOUT - result = tc.forward_backward([_make_datum() for _ in range(4)], 'importance_sampling').result() - assert result is not None - tc.optim_step(types.AdamParams(learning_rate=1e-5)).result() + # See the recovery note above: success is required only where forward_backward + # commits the DDP reducer atomically (megatron). On transformers a terminal + # loud failure is acceptable (spec R6#14) -- the guarantee is no hang. + if BACKEND == 'megatron': + result = tc.forward_backward([_make_datum() for _ in range(4)], 'importance_sampling').result() + assert result is not None + tc.optim_step(types.AdamParams(learning_rate=1e-5)).result() + else: + try: + result = tc.forward_backward([_make_datum() for _ in range(4)], + 'importance_sampling').result(timeout=TIMEOUT) + assert result is not None + tc.optim_step(types.AdamParams(learning_rate=1e-5)).result() + except RequestFailedError as exc: + assert exc.category is types.RequestErrorCategory.Server diff --git a/tests/server/integration/test_nccl_safe_twinkle_e2e.py b/tests/server/integration/test_nccl_safe_twinkle_e2e.py index 5eed7141..29b89be4 100644 --- a/tests/server/integration/test_nccl_safe_twinkle_e2e.py +++ b/tests/server/integration/test_nccl_safe_twinkle_e2e.py @@ -31,6 +31,12 @@ EXECUTION_TIMEOUT = float(os.environ.get('TWINKLE_TEST_EXECUTION_TIMEOUT', '30')) TIMEOUT = EXECUTION_TIMEOUT + 15 ADAPTER_NAME = 'loud-failure-test' +# The `global_rank=` attribution is added by `nccl_safe_megatron`, which decorates +# only the Megatron backend; the transformers backend's forward_backward carries no +# such annotation (its former silent-degradation decorator was removed by R6#3). Gate the +# rank-attribution assertion on the backend so this file is safe to run under the +# integration-e2e SKILL's TWINKLE_TEST_BACKEND=transformers path. +BACKEND = os.environ.get('TWINKLE_TEST_BACKEND', 'megatron') def _init_client(): @@ -43,7 +49,11 @@ def _init_client(): model.add_adapter_to_model( adapter_name=ADAPTER_NAME, config=LoraConfig(r=16, target_modules=['q_proj', 'v_proj']), - gradient_accumulation_steps=1, + # GA>=2 (repo convention, see e2e_helpers): with GA=1 every backward syncs + # DDP immediately, so a mid-iteration failure can leave the reducer + # half-finished and poison the next request. GA=2 runs accumulation steps + # under no_sync, keeping the recovery request clean. + gradient_accumulation_steps=2, ) model.set_loss('GRPOLoss', init_args={'epsilon': 0.2}) model.set_optimizer('Adam', lr=1e-5) @@ -83,7 +93,13 @@ def test_failure_is_terminal_then_valid_request_succeeds(): with pytest.raises(Exception) as caught: model.forward_backward( inputs=bad_features, adapter_name=ADAPTER_NAME, old_logps=bad_old_logps, advantages=bad_adv) - assert 'global_rank=' in str(caught.value) + message = str(caught.value) + # The failure must be loud and descriptive (not a silent zero-loss success): + # the deliberate old_logps/completion length mismatch surfaces on both backends. + assert 'mismatch' in message, message + # Megatron additionally attributes the failure to a global rank via nccl_safe_megatron. + if BACKEND == 'megatron': + assert 'global_rank=' in message, message assert time.time() - start < TIMEOUT, 'malformed request must fail fast, not hang (NCCL)' good_features, good_old_logps, good_adv = _make_inputs() diff --git a/tests/server/sampler/test_tinker_handlers.py b/tests/server/sampler/test_tinker_handlers.py index 1c072762..e6fe1596 100644 --- a/tests/server/sampler/test_tinker_handlers.py +++ b/tests/server/sampler/test_tinker_handlers.py @@ -20,6 +20,7 @@ class _DummySampler: def __init__(self): self.adapter_paths = [] + self.sampling_params = [] def set_template(self, *args, **kwargs): return None @@ -29,6 +30,7 @@ def reset_prefix_cache(self): def sample(self, inputs, sampling_params=None, adapter_name='', *, adapter_path=None, **kwargs): self.adapter_paths.append(adapter_path) + self.sampling_params.append(sampling_params) return [ SampleResponse( sequences=[SampledSequence( @@ -76,3 +78,4 @@ async def test_tinker_asample_allows_base_model_session_without_model_path(): assert isinstance(response, types.SampleResponse) assert response.sequences[0].tokens == [1, 2] assert management.sampler.adapter_paths == [None] + assert management.sampler.sampling_params[0].logprobs == 1