feat: extend discoverability through CLI - #2032
Conversation
Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
Originally we've used the dataset name. These two are usually identical, but for benchmarks with non-standard config location the output from `gym list command` was not usable as value for `--benchmark` flag in other commands. This commit fixes it. Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
…gwarmstrong conversly to search_dir config field, env var allows to pass extra dirs deep into the code, including rollouts colletion, prompt templates, config paths and env.yaml loading. also it is propagated to any spawned process Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
…ogging too Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
…1264 from @gwarmstrong) Signed-off-by: Marta Stepniewska-Dziubinska <martas@nvidia.com>
a4c46b4 to
8c19560
Compare
| yield | ||
| return | ||
| original = os.environ.get(NEMO_GYM_EXTRA_ROOTS_ENV_VAR_NAME) | ||
| value = os.pathsep.join(search_dirs) |
There was a problem hiding this comment.
Should --search-dir add to NEMO_GYM_EXTRA_ROOTS instead of replacing it?
For example:
export NEMO_GYM_EXTRA_ROOTS=/plugins/common
gym eval run --search-dir /plugins/experiment ...During this command, /plugins/common is no longer searched. I expected the order to be /plugins/experiment, /plugins/common, cwd, then the Gym install.
There was a problem hiding this comment.
makes sense, I will modify this part
| roots into the env (see nemo_gym.cli.main). With no extra roots this is just ``append(PARENT_DIR)``, as | ||
| before. | ||
| """ | ||
| for root in [*_extra_roots(), PARENT_DIR]: |
There was a problem hiding this comment.
Could file lookup and Python imports share the same root-ordering logic?
component_search_roots() gives extra roots priority over PARENT_DIR, but _augment_sys_path() can leave PARENT_DIR before the extra roots because it was already added to sys.path. This means a plugin can win during file resolution but lose during Python import when Gym contains a module with the same import name.
Is there a way for both resolvers to use the same ordered roots, so their precedence cannot diverge over time?
There was a problem hiding this comment.
Good catch.
I wonder if I should just ensure that PARENT_DIR is at the end, or in general that the extra roots are added before any other paths. I think the order should be: 1) extra roots, 2) original sys.path excluding PARENT_DIR, 3) PARENT_DIR. What do you think?
There was a problem hiding this comment.
done in ee0c74c, let me know if the ordering should be different
| merged: Dict[str, _T] = {} | ||
| for entries in per_root: | ||
| for name, entry in entries.items(): | ||
| merged.setdefault(name, entry) |
There was a problem hiding this comment.
Could list/search and named selection use the same rule for duplicate names?
This code keeps the first match, but _asset_config_path() reports an error when the same name exists in two roots. A component can therefore appear in gym list but fail when selected by name.
Either rule seems reasonable, but using the same rule in both places would be clearer.
There was a problem hiding this comment.
Good point. I think I'll modify _asset_config_path to pick up the first one and maybe print a warning to the user
| if not benchmarks_dir.is_dir(): | ||
| return [] | ||
| config_paths = [benchmarks_dir / p for p in glob("**/*.yaml", root_dir=benchmarks_dir, recursive=True)] | ||
| return sorted(p for p in config_paths if "type: benchmark" in p.read_text(errors="ignore")) |
There was a problem hiding this comment.
This only recognizes the exact text type: benchmark. Valid YAML such as type: "benchmark" or type : benchmark is skipped. I tested both cases.
Could we parse the YAML here, or make the check accept normal YAML formatting differences?
There was a problem hiding this comment.
I'll try with yaml parsing and if it doesn't work for any reason - extend the pattern here
There was a problem hiding this comment.
done in 97b5c9d I went with yaml and if the loading errors out we treat the config as potential benchmark. then all non-benchmarks fail to load and are filtered with a warning inside _load_benchmarks_from_config_paths
| # `gym search [<type>] <query>`: an optional component type plus the query. The query is surfaced to the | ||
| # chosen listing command as the reserved `query` config key; the type only picks which command to run | ||
| # (see `_search`). A lone positional is the query, defaulting to benchmarks — backward compatible. | ||
| _SEARCHABLE_TYPES = { |
There was a problem hiding this comment.
Should datasets be included here too?
There was a problem hiding this comment.
This one is tricky - datasets are not really an independent concept in Gym, they are tightly coupled with benchmarks, envs and resources servers. But we want to make them separate (#2036) and I think this will be the right moment to add gym list and gym search commands for them
| _cwd_path = Path.cwd() / _input_path | ||
| _input_path = _cwd_path if _cwd_path.exists() else PARENT_DIR / _input_path | ||
| # Search NEMO_GYM_EXTRA_ROOTS, cwd, then the install root. | ||
| _input_path = _resolve_under_cwd_or_install(config.input_jsonl_fpath) |
There was a problem hiding this comment.
Could skills.path use this resolver too?
A few lines above, load_skill_directory(config.skills.path) calls _resolve_skills_path(), which only checks cwd and the Gym install. This means --search-dir /plugins/my-plugin can resolve the input path here, but it cannot resolve skills.path=skills from the same plugin.
There was a problem hiding this comment.
Good catch, will fix
|
This PR got too big so I replaced it with stack. Comments from @gwarmstrong will be addressed in #2061 |
Implementes #1582