diff --git a/.github/workflows/providers-list-deps.yml b/.github/workflows/providers-list-deps.yml index 88659dbe3..a2e8a87c9 100644 --- a/.github/workflows/providers-list-deps.yml +++ b/.github/workflows/providers-list-deps.yml @@ -102,4 +102,4 @@ jobs: USE_COPY_NOT_MOUNT: "true" LLAMA_STACK_DIR: "." run: | - uv run llama stack list-deps src/llama_stack/distributions/ci-tests/build.yaml + uv run llama stack list-deps src/llama_stack/distributions/ci-tests/run.yaml diff --git a/.github/workflows/test-external.yml b/.github/workflows/test-external.yml index a99719718..fed3967ee 100644 --- a/.github/workflows/test-external.yml +++ b/.github/workflows/test-external.yml @@ -44,14 +44,14 @@ jobs: - name: Print distro dependencies run: | - uv run --no-sync llama stack list-deps tests/external/build.yaml + uv run --no-sync llama stack list-deps tests/external/run-byoa.yaml - name: Build distro from config file run: | uv venv ci-test source ci-test/bin/activate uv pip install -e . - LLAMA_STACK_LOGGING=all=CRITICAL llama stack list-deps tests/external/build.yaml | xargs -L1 uv pip install + LLAMA_STACK_LOGGING=all=CRITICAL llama stack list-deps tests/external/run-byoa.yaml | xargs -L1 uv pip install - name: Start Llama Stack server in background if: ${{ matrix.image-type }} == 'venv' diff --git a/docs/docs/providers/external/external-providers-guide.mdx b/docs/docs/providers/external/external-providers-guide.mdx index dc813c75b..3d013f720 100644 --- a/docs/docs/providers/external/external-providers-guide.mdx +++ b/docs/docs/providers/external/external-providers-guide.mdx @@ -222,22 +222,21 @@ def get_provider_spec() -> ProviderSpec: [ramalama-stack](https://github.com/containers/ramalama-stack) is a recognized external provider that supports installation via module. -To install Llama Stack with this external provider a user can provider the following build.yaml: +To install Llama Stack with this external provider a user can provider the following run.yaml: ```yaml version: 2 -distribution_spec: - description: Use (an external) Ramalama server for running LLM inference - container_image: null - providers: - inference: - - provider_type: remote::ramalama - module: ramalama_stack==0.3.0a0 -image_type: venv -image_name: null -additional_pip_packages: -- aiosqlite -- sqlalchemy[asyncio] +image_name: ramalama +apis: +- inference +providers: + inference: + - provider_id: ramalama + provider_type: remote::ramalama + module: ramalama_stack==0.3.0a0 + config: {} +server: + port: 8321 ``` No other steps are required beyond installing dependencies with `llama stack list-deps | xargs -L1 uv pip install` and then running `llama stack run`. The CLI will use `module` to install the provider dependencies, retrieve the spec, etc. diff --git a/src/llama_stack/cli/stack/_list_deps.py b/src/llama_stack/cli/stack/_list_deps.py index 82bef1a4f..f11ce486a 100644 --- a/src/llama_stack/cli/stack/_list_deps.py +++ b/src/llama_stack/cli/stack/_list_deps.py @@ -11,15 +11,9 @@ from pathlib import Path import yaml from termcolor import cprint -from llama_stack.cli.stack.utils import ImageType from llama_stack.core.build import get_provider_dependencies -from llama_stack.core.datatypes import ( - BuildConfig, - BuildProvider, - DistributionSpec, -) +from llama_stack.core.datatypes import Provider, StackRunConfig from llama_stack.core.distribution import get_provider_registry -from llama_stack.core.stack import replace_env_vars from llama_stack.log import get_logger from llama_stack_api import Api @@ -72,7 +66,7 @@ def run_stack_list_deps_command(args: argparse.Namespace) -> None: try: from llama_stack.core.utils.config_resolution import Mode, resolve_config_or_distro - config_file = resolve_config_or_distro(args.config, Mode.BUILD) + config_file = resolve_config_or_distro(args.config, Mode.RUN) except ValueError as e: cprint( f"Could not parse config file {args.config}: {e}", @@ -84,9 +78,7 @@ def run_stack_list_deps_command(args: argparse.Namespace) -> None: with open(config_file) as f: try: contents = yaml.safe_load(f) - contents = replace_env_vars(contents) - build_config = BuildConfig(**contents) - build_config.image_type = "venv" + run_config = StackRunConfig(**contents) except Exception as e: cprint( f"Could not parse config file {config_file}: {e}", @@ -95,7 +87,7 @@ def run_stack_list_deps_command(args: argparse.Namespace) -> None: ) sys.exit(1) elif args.providers: - provider_list: dict[str, list[BuildProvider]] = dict() + provider_list: dict[str, list[Provider]] = dict() for api_provider in args.providers.split(","): if "=" not in api_provider: cprint( @@ -114,8 +106,9 @@ def run_stack_list_deps_command(args: argparse.Namespace) -> None: ) sys.exit(1) if provider_type in providers_for_api: - provider = BuildProvider( + provider = Provider( provider_type=provider_type, + provider_id=provider_type.split("::")[1], module=None, ) provider_list.setdefault(api, []).append(provider) @@ -126,20 +119,16 @@ def run_stack_list_deps_command(args: argparse.Namespace) -> None: file=sys.stderr, ) sys.exit(1) - distribution_spec = DistributionSpec( - providers=provider_list, - description=",".join(args.providers), - ) - build_config = BuildConfig(image_type=ImageType.VENV.value, distribution_spec=distribution_spec) + run_config = StackRunConfig(providers=provider_list, image_name="providers-run") - normal_deps, special_deps, external_provider_dependencies = get_provider_dependencies(build_config) + normal_deps, special_deps, external_provider_dependencies = get_provider_dependencies(run_config) normal_deps += SERVER_DEPENDENCIES # Add external API dependencies - if build_config.external_apis_dir: + if run_config.external_apis_dir: from llama_stack.core.external import load_external_apis - external_apis = load_external_apis(build_config) + external_apis = load_external_apis(run_config) if external_apis: for _, api_spec in external_apis.items(): normal_deps.extend(api_spec.pip_packages) diff --git a/src/llama_stack/core/build.py b/src/llama_stack/core/build.py index 630b2a47f..757763bd1 100644 --- a/src/llama_stack/core/build.py +++ b/src/llama_stack/core/build.py @@ -9,7 +9,7 @@ import sys from pydantic import BaseModel from termcolor import cprint -from llama_stack.core.datatypes import BuildConfig +from llama_stack.core.datatypes import BuildConfig, StackRunConfig from llama_stack.core.distribution import get_provider_registry from llama_stack.distributions.template import DistributionTemplate from llama_stack.log import get_logger @@ -36,13 +36,13 @@ class ApiInput(BaseModel): def get_provider_dependencies( - config: BuildConfig | DistributionTemplate, + config: StackRunConfig, ) -> tuple[list[str], list[str], list[str]]: """Get normal and special dependencies from provider configuration.""" if isinstance(config, DistributionTemplate): config = config.build_config() - providers = config.distribution_spec.providers + providers = config.providers additional_pip_packages = config.additional_pip_packages deps = [] diff --git a/src/llama_stack/core/datatypes.py b/src/llama_stack/core/datatypes.py index 1e29690ff..245491332 100644 --- a/src/llama_stack/core/datatypes.py +++ b/src/llama_stack/core/datatypes.py @@ -517,6 +517,7 @@ can be instantiated multiple times (with different configs) if necessary. """, ) storage: StorageConfig = Field( + default_factory=StorageConfig, description="Catalog of named storage backends and references available to the stack", ) @@ -534,6 +535,11 @@ can be instantiated multiple times (with different configs) if necessary. description="Configuration for the HTTP(S) server", ) + additional_pip_packages: list[str] = Field( + default_factory=list, + description="Additional pip packages to install in the distribution. These packages will be installed in the distribution environment.", + ) + external_providers_dir: Path | None = Field( default=None, description="Path to directory containing external provider implementations. The providers code and dependencies must be installed on the system.",