themis-eval 0.2.3__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- themis/__init__.py +5 -2
- themis/_version.py +14 -1
- themis/api.py +83 -145
- themis/backends/storage.py +5 -0
- themis/cli/commands/info.py +2 -11
- themis/cli/main.py +231 -40
- themis/comparison/engine.py +7 -13
- themis/core/entities.py +4 -0
- themis/evaluation/metric_pipeline.py +12 -0
- themis/evaluation/pipeline.py +22 -0
- themis/evaluation/pipelines/__init__.py +4 -0
- themis/evaluation/pipelines/composable_pipeline.py +55 -0
- themis/evaluation/pipelines/standard_pipeline.py +16 -0
- themis/experiment/__init__.py +2 -2
- themis/experiment/cache_manager.py +15 -1
- themis/experiment/definitions.py +1 -1
- themis/experiment/orchestrator.py +21 -11
- themis/experiment/share.py +264 -0
- themis/experiment/storage.py +345 -298
- themis/generation/router.py +22 -4
- themis/generation/runner.py +16 -1
- themis/presets/benchmarks.py +602 -17
- themis/server/app.py +38 -26
- themis/session.py +125 -0
- themis/specs/__init__.py +7 -0
- themis/specs/execution.py +26 -0
- themis/specs/experiment.py +33 -0
- themis/specs/storage.py +18 -0
- themis/storage/__init__.py +6 -0
- themis/storage/experiment_storage.py +7 -0
- {themis_eval-0.2.3.dist-info → themis_eval-1.0.0.dist-info}/METADATA +47 -34
- {themis_eval-0.2.3.dist-info → themis_eval-1.0.0.dist-info}/RECORD +35 -28
- {themis_eval-0.2.3.dist-info → themis_eval-1.0.0.dist-info}/WHEEL +1 -1
- themis/experiment/builder.py +0 -151
- themis/experiment/export_csv.py +0 -159
- {themis_eval-0.2.3.dist-info → themis_eval-1.0.0.dist-info}/licenses/LICENSE +0 -0
- {themis_eval-0.2.3.dist-info → themis_eval-1.0.0.dist-info}/top_level.txt +0 -0
themis/generation/router.py
CHANGED
|
@@ -2,22 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import Mapping
|
|
5
|
+
from typing import Mapping, Tuple, Union
|
|
6
6
|
|
|
7
7
|
from themis.core import entities as core_entities
|
|
8
8
|
from themis.interfaces import ModelProvider
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
ProviderKey = Union[str, Tuple[str, str]]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _model_key(provider: str, identifier: str) -> str:
|
|
15
|
+
return f"{provider}:{identifier}"
|
|
16
|
+
|
|
17
|
+
|
|
11
18
|
class ProviderRouter(ModelProvider):
|
|
12
19
|
"""Dispatches generation tasks to concrete providers by model identifier."""
|
|
13
20
|
|
|
14
|
-
def __init__(self, providers: Mapping[
|
|
15
|
-
|
|
21
|
+
def __init__(self, providers: Mapping[ProviderKey, ModelProvider]):
|
|
22
|
+
normalized: dict[str, ModelProvider] = {}
|
|
23
|
+
|
|
24
|
+
for key, provider in providers.items():
|
|
25
|
+
if isinstance(key, tuple):
|
|
26
|
+
provider_name, model_id = key
|
|
27
|
+
normalized[_model_key(provider_name, model_id)] = provider
|
|
28
|
+
else:
|
|
29
|
+
normalized[str(key)] = provider
|
|
30
|
+
|
|
31
|
+
self._providers = normalized
|
|
16
32
|
|
|
17
33
|
def generate(
|
|
18
34
|
self, task: core_entities.GenerationTask
|
|
19
35
|
) -> core_entities.GenerationRecord: # type: ignore[override]
|
|
20
|
-
provider = self._providers.get(task.model.identifier)
|
|
36
|
+
provider = self._providers.get(_model_key(task.model.provider, task.model.identifier))
|
|
37
|
+
if provider is None:
|
|
38
|
+
provider = self._providers.get(task.model.identifier)
|
|
21
39
|
if provider is None:
|
|
22
40
|
known = ", ".join(sorted(self._providers)) or "<none>"
|
|
23
41
|
raise RuntimeError(
|
themis/generation/runner.py
CHANGED
|
@@ -26,6 +26,7 @@ class GenerationRunner:
|
|
|
26
26
|
[core_entities.GenerationTask], strategies.GenerationStrategy
|
|
27
27
|
]
|
|
28
28
|
| None = None,
|
|
29
|
+
execution_backend: object | None = None,
|
|
29
30
|
max_parallel: int = 1,
|
|
30
31
|
max_retries: int = 3,
|
|
31
32
|
retry_initial_delay: float = 0.5,
|
|
@@ -36,6 +37,7 @@ class GenerationRunner:
|
|
|
36
37
|
self._strategy_resolver = strategy_resolver or (
|
|
37
38
|
lambda task: strategies.SingleAttemptStrategy()
|
|
38
39
|
)
|
|
40
|
+
self._execution_backend = execution_backend
|
|
39
41
|
self._max_parallel = max(1, max_parallel)
|
|
40
42
|
self._max_retries = max(1, int(max_retries))
|
|
41
43
|
self._retry_initial_delay = max(0.0, retry_initial_delay)
|
|
@@ -53,7 +55,20 @@ class GenerationRunner:
|
|
|
53
55
|
return
|
|
54
56
|
|
|
55
57
|
logger.info(f"Runner: Starting execution of {len(task_list)} tasks with {self._max_parallel} workers")
|
|
56
|
-
|
|
58
|
+
|
|
59
|
+
if self._execution_backend is not None:
|
|
60
|
+
logger.info("Runner: Using custom execution backend")
|
|
61
|
+
backend = self._execution_backend
|
|
62
|
+
try:
|
|
63
|
+
for result in backend.map(
|
|
64
|
+
self._execute_task, task_list, max_workers=self._max_parallel
|
|
65
|
+
):
|
|
66
|
+
yield result
|
|
67
|
+
except Exception as e:
|
|
68
|
+
logger.error(f"Runner: Execution backend failed: {e}")
|
|
69
|
+
raise
|
|
70
|
+
return
|
|
71
|
+
|
|
57
72
|
if self._max_parallel <= 1:
|
|
58
73
|
logger.info("Runner: Using sequential execution (1 worker)")
|
|
59
74
|
for i, task in enumerate(task_list, 1):
|