nemo-evaluator-launcher 0.1.41__py3-none-any.whl → 0.1.56__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.
- nemo_evaluator_launcher/api/functional.py +55 -5
- nemo_evaluator_launcher/cli/ls_task.py +280 -0
- nemo_evaluator_launcher/cli/ls_tasks.py +208 -55
- nemo_evaluator_launcher/cli/main.py +17 -2
- nemo_evaluator_launcher/cli/run.py +41 -1
- nemo_evaluator_launcher/common/container_metadata/__init__.py +61 -0
- nemo_evaluator_launcher/common/container_metadata/intermediate_repr.py +530 -0
- nemo_evaluator_launcher/common/container_metadata/loading.py +1126 -0
- nemo_evaluator_launcher/common/container_metadata/registries.py +824 -0
- nemo_evaluator_launcher/common/container_metadata/utils.py +63 -0
- nemo_evaluator_launcher/common/helpers.py +44 -28
- nemo_evaluator_launcher/common/mapping.py +341 -155
- nemo_evaluator_launcher/common/printing_utils.py +18 -12
- nemo_evaluator_launcher/executors/lepton/executor.py +26 -8
- nemo_evaluator_launcher/executors/local/executor.py +6 -2
- nemo_evaluator_launcher/executors/slurm/executor.py +141 -9
- nemo_evaluator_launcher/package_info.py +1 -1
- nemo_evaluator_launcher/resources/all_tasks_irs.yaml +17016 -0
- nemo_evaluator_launcher/resources/mapping.toml +62 -354
- {nemo_evaluator_launcher-0.1.41.dist-info → nemo_evaluator_launcher-0.1.56.dist-info}/METADATA +2 -1
- {nemo_evaluator_launcher-0.1.41.dist-info → nemo_evaluator_launcher-0.1.56.dist-info}/RECORD +25 -18
- {nemo_evaluator_launcher-0.1.41.dist-info → nemo_evaluator_launcher-0.1.56.dist-info}/WHEEL +0 -0
- {nemo_evaluator_launcher-0.1.41.dist-info → nemo_evaluator_launcher-0.1.56.dist-info}/entry_points.txt +0 -0
- {nemo_evaluator_launcher-0.1.41.dist-info → nemo_evaluator_launcher-0.1.56.dist-info}/licenses/LICENSE +0 -0
- {nemo_evaluator_launcher-0.1.41.dist-info → nemo_evaluator_launcher-0.1.56.dist-info}/top_level.txt +0 -0
|
@@ -18,6 +18,13 @@ from dataclasses import dataclass
|
|
|
18
18
|
|
|
19
19
|
from simple_parsing import field
|
|
20
20
|
|
|
21
|
+
from nemo_evaluator_launcher.common.printing_utils import (
|
|
22
|
+
bold,
|
|
23
|
+
cyan,
|
|
24
|
+
grey,
|
|
25
|
+
magenta,
|
|
26
|
+
)
|
|
27
|
+
|
|
21
28
|
|
|
22
29
|
@dataclass
|
|
23
30
|
class Cmd:
|
|
@@ -28,20 +35,101 @@ class Cmd:
|
|
|
28
35
|
action="store_true",
|
|
29
36
|
help="Print output as JSON instead of table format",
|
|
30
37
|
)
|
|
38
|
+
from_container: str = field(
|
|
39
|
+
default="",
|
|
40
|
+
help="Load tasks from container image (e.g., nvcr.io/nvidia/eval-factory/simple-evals:25.10). "
|
|
41
|
+
"If provided, extracts framework.yml from container and lists tasks on-the-fly instead of using mapping.toml",
|
|
42
|
+
)
|
|
31
43
|
|
|
32
44
|
def execute(self) -> None:
|
|
33
45
|
# Import heavy dependencies only when needed
|
|
34
46
|
import json
|
|
35
47
|
|
|
36
|
-
|
|
48
|
+
if self.from_container:
|
|
49
|
+
# Load tasks from container
|
|
50
|
+
from nemo_evaluator_launcher.common.container_metadata import (
|
|
51
|
+
load_tasks_from_container,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
tasks = load_tasks_from_container(self.from_container)
|
|
56
|
+
except ValueError as e:
|
|
57
|
+
from nemo_evaluator_launcher.common.logging_utils import logger
|
|
58
|
+
|
|
59
|
+
logger.error(
|
|
60
|
+
"Failed to load tasks from container",
|
|
61
|
+
container=self.from_container,
|
|
62
|
+
error=str(e),
|
|
63
|
+
)
|
|
64
|
+
return
|
|
65
|
+
except Exception as e:
|
|
66
|
+
from nemo_evaluator_launcher.common.logging_utils import logger
|
|
67
|
+
|
|
68
|
+
logger.error(
|
|
69
|
+
"Failed to load tasks from container",
|
|
70
|
+
container=self.from_container,
|
|
71
|
+
error=str(e),
|
|
72
|
+
exc_info=True,
|
|
73
|
+
)
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
if not tasks:
|
|
77
|
+
from nemo_evaluator_launcher.common.logging_utils import logger
|
|
78
|
+
|
|
79
|
+
logger.error(
|
|
80
|
+
"No tasks found in container",
|
|
81
|
+
container=self.from_container,
|
|
82
|
+
)
|
|
83
|
+
return
|
|
37
84
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
85
|
+
# Convert TaskIntermediateRepresentation to format expected by get_tasks_list()
|
|
86
|
+
# Build data structure matching get_tasks_list() output format
|
|
87
|
+
data = []
|
|
88
|
+
for task in tasks:
|
|
89
|
+
# Extract endpoint types from defaults
|
|
90
|
+
endpoint_types = (
|
|
91
|
+
task.defaults.get("target", {})
|
|
92
|
+
.get("api_endpoint", {})
|
|
93
|
+
.get("type", "chat")
|
|
94
|
+
)
|
|
95
|
+
if isinstance(endpoint_types, str):
|
|
96
|
+
endpoint_types = [endpoint_types]
|
|
97
|
+
|
|
98
|
+
data.append(
|
|
99
|
+
[
|
|
100
|
+
task.name, # task
|
|
101
|
+
",".join(endpoint_types)
|
|
102
|
+
if isinstance(endpoint_types, list)
|
|
103
|
+
else endpoint_types, # endpoint_type
|
|
104
|
+
task.harness, # harness
|
|
105
|
+
task.container, # container
|
|
106
|
+
getattr(task, "container_arch", "") or "", # arch
|
|
107
|
+
task.description, # description
|
|
108
|
+
]
|
|
109
|
+
)
|
|
110
|
+
else:
|
|
111
|
+
# Default behavior: load from mapping.toml via get_tasks_list()
|
|
112
|
+
from nemo_evaluator_launcher.api.functional import get_tasks_list
|
|
113
|
+
|
|
114
|
+
# TODO(dfridman): modify `get_tasks_list` to return a list of dicts in the first place
|
|
115
|
+
data = get_tasks_list()
|
|
116
|
+
|
|
117
|
+
headers = [
|
|
118
|
+
"task",
|
|
119
|
+
"endpoint_type",
|
|
120
|
+
"harness",
|
|
121
|
+
"container",
|
|
122
|
+
"arch",
|
|
123
|
+
"description",
|
|
124
|
+
]
|
|
41
125
|
supported_benchmarks = []
|
|
42
126
|
for task_data in data:
|
|
43
|
-
|
|
44
|
-
|
|
127
|
+
if len(task_data) < len(headers):
|
|
128
|
+
raise ValueError(
|
|
129
|
+
f"Invalid task row shape: expected at least {len(headers)} columns, got {len(task_data)}"
|
|
130
|
+
)
|
|
131
|
+
# Backwards/forwards compat: allow extra columns and ignore them.
|
|
132
|
+
supported_benchmarks.append(dict(zip(headers, task_data[: len(headers)])))
|
|
45
133
|
|
|
46
134
|
if self.json:
|
|
47
135
|
print(json.dumps({"tasks": supported_benchmarks}, indent=2))
|
|
@@ -49,11 +137,55 @@ class Cmd:
|
|
|
49
137
|
self._print_table(supported_benchmarks)
|
|
50
138
|
|
|
51
139
|
def _print_table(self, tasks: list[dict]) -> None:
|
|
52
|
-
"""Print tasks grouped by harness and container in table format."""
|
|
140
|
+
"""Print tasks grouped by harness and container in table format with colorized output."""
|
|
53
141
|
if not tasks:
|
|
54
142
|
print("No tasks found.")
|
|
55
143
|
return
|
|
56
144
|
|
|
145
|
+
def _truncate(s: str, max_len: int) -> str:
|
|
146
|
+
s = s or ""
|
|
147
|
+
if max_len <= 0:
|
|
148
|
+
return ""
|
|
149
|
+
if len(s) <= max_len:
|
|
150
|
+
return s
|
|
151
|
+
if max_len <= 3:
|
|
152
|
+
return s[:max_len]
|
|
153
|
+
return s[: max_len - 3] + "..."
|
|
154
|
+
|
|
155
|
+
def _infer_arch(container: str, container_tasks: list[dict]) -> str:
|
|
156
|
+
# Prefer explicit arch from task IRs.
|
|
157
|
+
for t in container_tasks:
|
|
158
|
+
a = (t.get("arch") or "").strip()
|
|
159
|
+
if a:
|
|
160
|
+
return a
|
|
161
|
+
|
|
162
|
+
# Heuristic fallback: look for common suffixes in tag.
|
|
163
|
+
c = (container or "").lower()
|
|
164
|
+
if "arm64" in c or "aarch64" in c:
|
|
165
|
+
return "arm"
|
|
166
|
+
if "amd64" in c or "x86_64" in c:
|
|
167
|
+
return "amd"
|
|
168
|
+
return "unknown"
|
|
169
|
+
|
|
170
|
+
def _infer_registry(container: str) -> str:
|
|
171
|
+
try:
|
|
172
|
+
from nemo_evaluator_launcher.common.container_metadata.utils import (
|
|
173
|
+
parse_container_image,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
registry_type, _registry_url, _repo, _ref = parse_container_image(
|
|
177
|
+
container
|
|
178
|
+
)
|
|
179
|
+
return str(registry_type)
|
|
180
|
+
except Exception:
|
|
181
|
+
# Best-effort fallback for unknown formats.
|
|
182
|
+
c = (container or "").lower()
|
|
183
|
+
if "nvcr.io/" in c or c.startswith("nvcr.io"):
|
|
184
|
+
return "nvcr"
|
|
185
|
+
if "gitlab" in c:
|
|
186
|
+
return "gitlab"
|
|
187
|
+
return ""
|
|
188
|
+
|
|
57
189
|
# Group tasks by harness and container
|
|
58
190
|
grouped = defaultdict(lambda: defaultdict(list))
|
|
59
191
|
for task in tasks:
|
|
@@ -70,67 +202,88 @@ class Cmd:
|
|
|
70
202
|
if j > 0:
|
|
71
203
|
print() # Spacing between containers
|
|
72
204
|
|
|
73
|
-
# Prepare task table first to get column widths
|
|
74
|
-
task_headers = ["task", "endpoint_type"]
|
|
75
205
|
rows = []
|
|
76
206
|
for task in container_tasks:
|
|
77
|
-
rows.append(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
for i in range(len(task_headers))
|
|
86
|
-
]
|
|
87
|
-
|
|
88
|
-
# Calculate minimum table width based on task columns
|
|
89
|
-
min_table_width = sum(widths) + len(widths) + 1
|
|
207
|
+
rows.append(
|
|
208
|
+
{
|
|
209
|
+
"task": str(task.get("task", "")),
|
|
210
|
+
"endpoint": str(task.get("endpoint_type", "")),
|
|
211
|
+
"description": str(task.get("description", "")),
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
rows.sort(key=lambda r: r["task"].lower())
|
|
90
215
|
|
|
91
216
|
# Calculate required width for header content
|
|
92
217
|
harness_line = f"harness: {harness}"
|
|
93
218
|
container_line = f"container: {container}"
|
|
219
|
+
arch_line = f"arch: {_infer_arch(container, container_tasks)}"
|
|
220
|
+
registry_line = f"registry: {_infer_registry(container)}"
|
|
94
221
|
header_content_width = (
|
|
95
|
-
max(
|
|
222
|
+
max(
|
|
223
|
+
len(harness_line),
|
|
224
|
+
len(container_line),
|
|
225
|
+
len(arch_line),
|
|
226
|
+
len(registry_line),
|
|
227
|
+
)
|
|
228
|
+
+ 4
|
|
96
229
|
) # +4 for "| " and " |"
|
|
97
230
|
|
|
98
|
-
#
|
|
99
|
-
|
|
231
|
+
# Limit separator width to prevent overflow on small terminals
|
|
232
|
+
# Use terminal width if available, otherwise cap at 120 characters
|
|
233
|
+
import shutil
|
|
100
234
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
235
|
+
try:
|
|
236
|
+
terminal_width = shutil.get_terminal_size().columns
|
|
237
|
+
separator_width = min(terminal_width - 2, 160) # -2 safety margin
|
|
238
|
+
except Exception:
|
|
239
|
+
# Fallback if terminal size can't be determined
|
|
240
|
+
separator_width = 120
|
|
105
241
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
242
|
+
separator_width = max(separator_width, min(header_content_width, 160))
|
|
243
|
+
|
|
244
|
+
# Table columns (keep compact and stable).
|
|
245
|
+
col_task = 36
|
|
246
|
+
col_endpoint = 14
|
|
247
|
+
sep = " "
|
|
248
|
+
fixed = col_task + col_endpoint + len(sep) * 2
|
|
249
|
+
col_desc = max(20, separator_width - fixed)
|
|
250
|
+
|
|
251
|
+
# Print combined header with harness and container info - colorized
|
|
252
|
+
# Keys: magenta, Values: cyan (matching logging utils)
|
|
253
|
+
print(bold("=" * separator_width))
|
|
254
|
+
print(f"{magenta('harness:')} {cyan(str(harness))}")
|
|
255
|
+
print(f"{magenta('container:')} {cyan(str(container))}")
|
|
256
|
+
arch = _infer_arch(container, container_tasks)
|
|
257
|
+
registry = _infer_registry(container)
|
|
258
|
+
print(f"{magenta('arch:')} {cyan(str(arch))}")
|
|
259
|
+
if registry:
|
|
260
|
+
print(f"{magenta('registry:')} {cyan(str(registry))}")
|
|
118
261
|
|
|
119
262
|
# Print task table header separator
|
|
120
|
-
print(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
263
|
+
print()
|
|
264
|
+
print(
|
|
265
|
+
bold(
|
|
266
|
+
f"{'task':<{col_task}}{sep}"
|
|
267
|
+
f"{'endpoint':<{col_endpoint}}{sep}"
|
|
268
|
+
f"{'description':<{col_desc}}"
|
|
269
|
+
)
|
|
270
|
+
)
|
|
271
|
+
print(bold("-" * separator_width))
|
|
272
|
+
|
|
273
|
+
# Print task rows - use grey for task descriptions
|
|
274
|
+
for r in rows:
|
|
275
|
+
line = (
|
|
276
|
+
f"{_truncate(r['task'], col_task):<{col_task}}{sep}"
|
|
277
|
+
f"{_truncate(r['endpoint'], col_endpoint):<{col_endpoint}}{sep}"
|
|
278
|
+
f"{_truncate(r['description'], col_desc):<{col_desc}}"
|
|
279
|
+
)
|
|
280
|
+
print(grey(line))
|
|
281
|
+
|
|
282
|
+
print(bold("-" * separator_width))
|
|
283
|
+
# Show task count - grey for count text
|
|
132
284
|
task_count = len(rows)
|
|
133
|
-
|
|
134
|
-
print("
|
|
285
|
+
task_word = "task" if task_count == 1 else "tasks"
|
|
286
|
+
print(f" {grey(f'{task_count} {task_word} available')}")
|
|
287
|
+
print(bold("=" * separator_width))
|
|
135
288
|
|
|
136
289
|
print()
|
|
@@ -24,6 +24,7 @@ import nemo_evaluator_launcher.cli.info as info
|
|
|
24
24
|
import nemo_evaluator_launcher.cli.kill as kill
|
|
25
25
|
import nemo_evaluator_launcher.cli.logs as logs
|
|
26
26
|
import nemo_evaluator_launcher.cli.ls_runs as ls_runs
|
|
27
|
+
import nemo_evaluator_launcher.cli.ls_task as ls_task
|
|
27
28
|
import nemo_evaluator_launcher.cli.ls_tasks as ls_tasks
|
|
28
29
|
import nemo_evaluator_launcher.cli.run as run
|
|
29
30
|
import nemo_evaluator_launcher.cli.status as status
|
|
@@ -49,6 +50,7 @@ def is_verbose_enabled(args) -> bool:
|
|
|
49
50
|
"tasks_alias",
|
|
50
51
|
"tasks",
|
|
51
52
|
"runs",
|
|
53
|
+
"task",
|
|
52
54
|
"export",
|
|
53
55
|
]
|
|
54
56
|
for subcmd in subcommands:
|
|
@@ -159,6 +161,14 @@ def create_parser() -> ArgumentParser:
|
|
|
159
161
|
)
|
|
160
162
|
ls_runs_parser.add_arguments(ls_runs.Cmd, dest="runs")
|
|
161
163
|
|
|
164
|
+
# ls task (task details)
|
|
165
|
+
ls_task_parser = ls_sub.add_parser(
|
|
166
|
+
"task",
|
|
167
|
+
help="Show task details",
|
|
168
|
+
description="Show detailed information about a specific task",
|
|
169
|
+
)
|
|
170
|
+
ls_task_parser.add_arguments(ls_task.Cmd, dest="task")
|
|
171
|
+
|
|
162
172
|
# Export subcommand
|
|
163
173
|
export_parser = subparsers.add_parser(
|
|
164
174
|
"export",
|
|
@@ -220,12 +230,17 @@ def main() -> None:
|
|
|
220
230
|
args.kill.execute()
|
|
221
231
|
elif args.command == "ls":
|
|
222
232
|
# Dispatch nested ls subcommands
|
|
223
|
-
if args.ls_command
|
|
224
|
-
#
|
|
233
|
+
if args.ls_command == "tasks":
|
|
234
|
+
# When explicitly "ls tasks", use args.tasks (has correct from_container)
|
|
235
|
+
args.tasks.execute()
|
|
236
|
+
elif args.ls_command is None:
|
|
237
|
+
# When just "ls" (no subcommand), use args.tasks_alias
|
|
225
238
|
if hasattr(args, "tasks_alias"):
|
|
226
239
|
args.tasks_alias.execute()
|
|
227
240
|
else:
|
|
228
241
|
args.tasks.execute()
|
|
242
|
+
elif args.ls_command == "task":
|
|
243
|
+
args.task.execute()
|
|
229
244
|
elif args.ls_command == "runs":
|
|
230
245
|
args.runs.execute()
|
|
231
246
|
elif args.command == "export":
|
|
@@ -77,6 +77,15 @@ class Cmd:
|
|
|
77
77
|
alias=["-n", "--dry-run"],
|
|
78
78
|
metadata={"help": "Do not run the evaluation, just print the config."},
|
|
79
79
|
)
|
|
80
|
+
tasks: list[str] = field(
|
|
81
|
+
default_factory=list,
|
|
82
|
+
action="append",
|
|
83
|
+
nargs="?",
|
|
84
|
+
alias=["-t"],
|
|
85
|
+
metadata={
|
|
86
|
+
"help": "Run only specific tasks from the config. Example: -t ifeval -t gsm8k"
|
|
87
|
+
},
|
|
88
|
+
)
|
|
80
89
|
config_output: str | None = field(
|
|
81
90
|
default=None,
|
|
82
91
|
alias=["--config-output"],
|
|
@@ -85,12 +94,31 @@ class Cmd:
|
|
|
85
94
|
},
|
|
86
95
|
)
|
|
87
96
|
|
|
97
|
+
def _parse_requested_tasks(self) -> list[str]:
|
|
98
|
+
"""Parse -t arguments into a list of task names.
|
|
99
|
+
|
|
100
|
+
Handles None values that can be appended when using nargs="?" with action="append".
|
|
101
|
+
"""
|
|
102
|
+
requested_tasks = []
|
|
103
|
+
for task_arg in self.tasks:
|
|
104
|
+
# Skip None or empty values (can happen with nargs="?")
|
|
105
|
+
if not task_arg:
|
|
106
|
+
continue
|
|
107
|
+
task_name = task_arg.strip()
|
|
108
|
+
if task_name and task_name not in requested_tasks:
|
|
109
|
+
requested_tasks.append(task_name)
|
|
110
|
+
return requested_tasks
|
|
111
|
+
|
|
88
112
|
def execute(self) -> None:
|
|
89
113
|
# Import heavy dependencies only when needed
|
|
90
114
|
import yaml
|
|
91
115
|
from omegaconf import OmegaConf
|
|
92
116
|
|
|
93
|
-
from nemo_evaluator_launcher.api.functional import
|
|
117
|
+
from nemo_evaluator_launcher.api.functional import (
|
|
118
|
+
RunConfig,
|
|
119
|
+
filter_tasks,
|
|
120
|
+
run_eval,
|
|
121
|
+
)
|
|
94
122
|
|
|
95
123
|
# Validate config_mode value
|
|
96
124
|
if self.config_mode not in ["hydra", "raw"]:
|
|
@@ -104,6 +132,9 @@ class Cmd:
|
|
|
104
132
|
"--config-mode=raw requires --config to be specified. Raw mode loads config files directly."
|
|
105
133
|
)
|
|
106
134
|
|
|
135
|
+
# Parse requested tasks if -t is specified
|
|
136
|
+
requested_tasks = self._parse_requested_tasks() if self.tasks else None
|
|
137
|
+
|
|
107
138
|
# Load configuration either from Hydra or directly from a config file
|
|
108
139
|
if self.config_mode == "raw" and self.config:
|
|
109
140
|
# Validate that raw config loading is not used with other config options
|
|
@@ -147,6 +178,15 @@ class Cmd:
|
|
|
147
178
|
hydra_overrides=self.override,
|
|
148
179
|
)
|
|
149
180
|
|
|
181
|
+
# Apply task filtering if -t is specified
|
|
182
|
+
if requested_tasks:
|
|
183
|
+
config = filter_tasks(config, requested_tasks)
|
|
184
|
+
logger.info(
|
|
185
|
+
"Running filtered tasks",
|
|
186
|
+
count=len(config.evaluation.tasks),
|
|
187
|
+
tasks=[t.name for t in config.evaluation.tasks],
|
|
188
|
+
)
|
|
189
|
+
|
|
150
190
|
try:
|
|
151
191
|
invocation_id = run_eval(config, self.dry_run)
|
|
152
192
|
except Exception as e:
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
#
|
|
16
|
+
"""Container metadata management: registries, intermediate representations, and loading."""
|
|
17
|
+
|
|
18
|
+
from nemo_evaluator_launcher.common.container_metadata.intermediate_repr import (
|
|
19
|
+
HarnessIntermediateRepresentation,
|
|
20
|
+
TaskIntermediateRepresentation,
|
|
21
|
+
load_harnesses_and_tasks_from_tasks_file,
|
|
22
|
+
load_tasks_from_tasks_file,
|
|
23
|
+
)
|
|
24
|
+
from nemo_evaluator_launcher.common.container_metadata.registries import (
|
|
25
|
+
DockerRegistryHandler,
|
|
26
|
+
create_authenticator,
|
|
27
|
+
)
|
|
28
|
+
from nemo_evaluator_launcher.common.container_metadata.utils import (
|
|
29
|
+
parse_container_image,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"DockerRegistryHandler",
|
|
34
|
+
"create_authenticator",
|
|
35
|
+
"HarnessIntermediateRepresentation",
|
|
36
|
+
"TaskIntermediateRepresentation",
|
|
37
|
+
"load_harnesses_and_tasks_from_tasks_file",
|
|
38
|
+
"load_tasks_from_tasks_file",
|
|
39
|
+
"parse_container_image",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
# Optional imports:
|
|
43
|
+
# `loading` pulls in `nemo_evaluator` (and deps like `pydantic`). Keep IR-only
|
|
44
|
+
# workflows (e.g., docs autogen) usable without requiring the full stack.
|
|
45
|
+
try:
|
|
46
|
+
from nemo_evaluator_launcher.common.container_metadata.loading import ( # noqa: F401
|
|
47
|
+
extract_framework_yml,
|
|
48
|
+
load_tasks_from_container,
|
|
49
|
+
parse_framework_to_irs,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
__all__.extend(
|
|
53
|
+
[
|
|
54
|
+
"extract_framework_yml",
|
|
55
|
+
"load_tasks_from_container",
|
|
56
|
+
"parse_framework_to_irs",
|
|
57
|
+
]
|
|
58
|
+
)
|
|
59
|
+
except ModuleNotFoundError:
|
|
60
|
+
# Allow importing this package for IR-only workflows (docs autogen, etc.)
|
|
61
|
+
pass
|