From 0cc07311890c00feb5bbd40f5052c8a84a88aa65 Mon Sep 17 00:00:00 2001 From: Michael Anstis Date: Mon, 19 May 2025 13:01:28 +0100 Subject: [PATCH] fix: Pass external_config_dir to BuildConfig (#2190) # What does this PR do? The `external_config_dir` configuration parameter is not being passed to the `BuildConfig` for `LlamaStackAsLibraryClient`. This prevents _plugin_ providers from being loaded when `llama-stack` is uses as a library. [//]: # (If resolving an issue, uncomment and update the line below) [//]: # (Closes #[issue-number]) ## Test Plan I ran `LlamaStackAsLibraryClient` with a configuration file that contained `external_config_dir` and related configuration. It does not work without this change: _external_ providers are not resolved. It does work with this change :+1: [//]: # (## Documentation) --- llama_stack/cli/stack/_build.py | 10 +++++----- llama_stack/distribution/datatypes.py | 11 ++++++++++- llama_stack/distribution/library_client.py | 1 + 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/llama_stack/cli/stack/_build.py b/llama_stack/cli/stack/_build.py index 25a234bbe..4c6f82d1b 100644 --- a/llama_stack/cli/stack/_build.py +++ b/llama_stack/cli/stack/_build.py @@ -12,6 +12,7 @@ import shutil import sys import textwrap from functools import lru_cache +from importlib.abc import Traversable from pathlib import Path import yaml @@ -250,11 +251,10 @@ def run_stack_build_command(args: argparse.Namespace) -> None: sys.exit(1) if args.run: - run_config = Path(run_config) config_dict = yaml.safe_load(run_config.read_text()) config = parse_and_maybe_upgrade_config(config_dict) - if not os.path.exists(str(config.external_providers_dir)): - os.makedirs(str(config.external_providers_dir), exist_ok=True) + if not os.path.exists(config.external_providers_dir): + os.makedirs(config.external_providers_dir, exist_ok=True) run_args = formulate_run_args(args.image_type, args.image_name, config, args.template) run_args.extend([str(os.getenv("LLAMA_STACK_PORT", 8321)), "--config", run_config]) run_command(run_args) @@ -264,7 +264,7 @@ def _generate_run_config( build_config: BuildConfig, build_dir: Path, image_name: str, -) -> str: +) -> Path: """ Generate a run.yaml template file for user to edit from a build.yaml file """ @@ -343,7 +343,7 @@ def _run_stack_build_command_from_build_config( image_name: str | None = None, template_name: str | None = None, config_path: str | None = None, -) -> str: +) -> Path | Traversable: image_name = image_name or build_config.image_name if build_config.image_type == LlamaStackImageType.CONTAINER.value: if template_name: diff --git a/llama_stack/distribution/datatypes.py b/llama_stack/distribution/datatypes.py index 783a48de3..446a88ca0 100644 --- a/llama_stack/distribution/datatypes.py +++ b/llama_stack/distribution/datatypes.py @@ -340,8 +340,17 @@ class BuildConfig(BaseModel): default=None, description="Name of the distribution to build", ) - external_providers_dir: str | None = Field( + external_providers_dir: Path | None = Field( default=None, description="Path to directory containing external provider implementations. The providers packages will be resolved from this directory. " "pip_packages MUST contain the provider package name.", ) + + @field_validator("external_providers_dir") + @classmethod + def validate_external_providers_dir(cls, v): + if v is None: + return None + if isinstance(v, str): + return Path(v) + return v diff --git a/llama_stack/distribution/library_client.py b/llama_stack/distribution/library_client.py index 8e5445874..34e041cbe 100644 --- a/llama_stack/distribution/library_client.py +++ b/llama_stack/distribution/library_client.py @@ -226,6 +226,7 @@ class AsyncLlamaStackAsLibraryClient(AsyncLlamaStackClient): distribution_spec=DistributionSpec( providers=provider_types, ), + external_providers_dir=self.config.external_providers_dir, ) print_pip_install_help(build_config) else: