Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/providers-list-deps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions .github/workflows/test-external.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
25 changes: 12 additions & 13 deletions docs/docs/providers/external/external-providers-guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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 <distro> | 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.
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ dependencies = [
"asyncpg", # for metadata store
"sqlalchemy[asyncio]>=2.0.41", # server - for conversations
"starlette>=0.49.1",
"psycopg2-binary",
]

[project.optional-dependencies]
Expand Down
31 changes: 10 additions & 21 deletions src/llama_stack/cli/stack/_list_deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,9 @@
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

Expand Down Expand Up @@ -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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mode.RUN is not relevant anymore, is it?

except ValueError as e:
cprint(
f"Could not parse config file {args.config}: {e}",
Expand All @@ -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}",
Expand All @@ -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(
Expand All @@ -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)
Expand All @@ -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)
Expand Down
11 changes: 4 additions & 7 deletions src/llama_stack/core/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from pydantic import BaseModel
from termcolor import cprint

from llama_stack.core.datatypes import BuildConfig
from llama_stack.core.datatypes import StackRunConfig
from llama_stack.core.distribution import get_provider_registry
from llama_stack.distributions.template import DistributionTemplate
from llama_stack.log import get_logger
Expand All @@ -36,14 +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
additional_pip_packages = config.additional_pip_packages
providers = config.providers

deps = []
external_provider_deps = []
Expand Down Expand Up @@ -81,12 +80,10 @@ def get_provider_dependencies(
else:
normal_deps.append(package)

normal_deps.extend(additional_pip_packages or [])

return list(set(normal_deps)), list(set(special_deps)), list(set(external_provider_deps))


def print_pip_install_help(config: BuildConfig):
def print_pip_install_help(config: StackRunConfig):
normal_deps, special_deps, _ = get_provider_dependencies(config)

cprint(
Expand Down
5 changes: 1 addition & 4 deletions src/llama_stack/core/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ class StackRunConfig(BaseModel):
""",
)
storage: StorageConfig = Field(
default_factory=StorageConfig,
description="Catalog of named storage backends and references available to the stack",
)

Expand Down Expand Up @@ -625,10 +626,6 @@ class BuildConfig(BaseModel):
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.",
)
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_apis_dir: Path | None = Field(
default=None,
description="Path to directory containing external API implementations. The APIs code and dependencies must be installed on the system.",
Expand Down
16 changes: 1 addition & 15 deletions src/llama_stack/core/library_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@

from llama_stack.core.build import print_pip_install_help
from llama_stack.core.configure import parse_and_maybe_upgrade_config
from llama_stack.core.datatypes import BuildConfig, BuildProvider, DistributionSpec
from llama_stack.core.request_headers import PROVIDER_DATA_VAR, request_provider_data_context
from llama_stack.core.resolver import ProviderRegistry
from llama_stack.core.server.routes import RouteImpls, find_matching_route, initialize_route_impls
Expand Down Expand Up @@ -266,20 +265,7 @@ async def initialize(self) -> bool:
file=sys.stderr,
)
if self.config_path_or_distro_name.endswith(".yaml"):
providers: dict[str, list[BuildProvider]] = {}
for api, run_providers in self.config.providers.items():
for provider in run_providers:
providers.setdefault(api, []).append(
BuildProvider(provider_type=provider.provider_type, module=provider.module)
)
providers = dict(providers)
build_config = BuildConfig(
distribution_spec=DistributionSpec(
providers=providers,
),
external_providers_dir=self.config.external_providers_dir,
)
print_pip_install_help(build_config)
print_pip_install_help(self.config)
else:
prefix = "!" if in_notebook() else ""
cprint(
Expand Down
5 changes: 0 additions & 5 deletions src/llama_stack/distributions/ci-tests/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,3 @@ distribution_spec:
batches:
- provider_type: inline::reference
image_type: venv
additional_pip_packages:
- aiosqlite
- asyncpg
- psycopg2-binary
- sqlalchemy[asyncio]
3 changes: 0 additions & 3 deletions src/llama_stack/distributions/dell/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,3 @@ distribution_spec:
- provider_type: remote::tavily-search
- provider_type: inline::rag-runtime
image_type: venv
additional_pip_packages:
- aiosqlite
- sqlalchemy[asyncio]
3 changes: 0 additions & 3 deletions src/llama_stack/distributions/meta-reference-gpu/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,3 @@ distribution_spec:
- provider_type: inline::rag-runtime
- provider_type: remote::model-context-protocol
image_type: venv
additional_pip_packages:
- aiosqlite
- sqlalchemy[asyncio]
3 changes: 0 additions & 3 deletions src/llama_stack/distributions/nvidia/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,3 @@ distribution_spec:
files:
- provider_type: inline::localfs
image_type: venv
additional_pip_packages:
- aiosqlite
- sqlalchemy[asyncio]
3 changes: 0 additions & 3 deletions src/llama_stack/distributions/oci/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,3 @@ distribution_spec:
files:
- provider_type: inline::localfs
image_type: venv
additional_pip_packages:
- aiosqlite
- sqlalchemy[asyncio]
3 changes: 0 additions & 3 deletions src/llama_stack/distributions/open-benchmark/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,3 @@ distribution_spec:
- provider_type: inline::rag-runtime
- provider_type: remote::model-context-protocol
image_type: venv
additional_pip_packages:
- aiosqlite
- sqlalchemy[asyncio]
5 changes: 0 additions & 5 deletions src/llama_stack/distributions/starter-gpu/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,3 @@ distribution_spec:
batches:
- provider_type: inline::reference
image_type: venv
additional_pip_packages:
- aiosqlite
- asyncpg
- psycopg2-binary
- sqlalchemy[asyncio]
5 changes: 0 additions & 5 deletions src/llama_stack/distributions/starter/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,3 @@ distribution_spec:
batches:
- provider_type: inline::reference
image_type: venv
additional_pip_packages:
- aiosqlite
- asyncpg
- psycopg2-binary
- sqlalchemy[asyncio]
1 change: 0 additions & 1 deletion src/llama_stack/distributions/starter/starter.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ def get_distribution_template(name: str = "starter") -> DistributionTemplate:
container_image=None,
template_path=None,
providers=providers,
additional_pip_packages=list(set(PostgresSqlStoreConfig.pip_packages() + PostgresKVStoreConfig.pip_packages())),
run_configs={
"run.yaml": base_run_settings,
"run-with-postgres-store.yaml": postgres_run_settings,
Expand Down
29 changes: 0 additions & 29 deletions src/llama_stack/distributions/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,7 @@
StorageBackendType,
)
from llama_stack.core.storage.kvstore.config import SqliteKVStoreConfig
from llama_stack.core.storage.kvstore.config import get_pip_packages as get_kv_pip_packages
from llama_stack.core.storage.sqlstore.sqlstore import SqliteSqlStoreConfig
from llama_stack.core.storage.sqlstore.sqlstore import get_pip_packages as get_sql_pip_packages
from llama_stack.core.utils.dynamic import instantiate_class_type
from llama_stack.core.utils.image_types import LlamaStackImageType
from llama_stack.providers.utils.inference.model_registry import ProviderModelEntry
Expand Down Expand Up @@ -322,33 +320,7 @@ class DistributionTemplate(BaseModel):

available_models_by_provider: dict[str, list[ProviderModelEntry]] | None = None

# we may want to specify additional pip packages without necessarily indicating a
# specific "default" inference store (which is what typically used to dictate additional
# pip packages)
additional_pip_packages: list[str] | None = None

def build_config(self) -> BuildConfig:
additional_pip_packages: list[str] = []
for run_config in self.run_configs.values():
run_config_ = run_config.run_config(self.name, self.providers, self.container_image)

# TODO: This is a hack to get the dependencies for internal APIs into build
# We should have a better way to do this by formalizing the concept of "internal" APIs
# and providers, with a way to specify dependencies for them.

storage_cfg = run_config_.get("storage", {})
for backend_cfg in storage_cfg.get("backends", {}).values():
store_type = backend_cfg.get("type")
if not store_type:
continue
if str(store_type).startswith("kv_"):
additional_pip_packages.extend(get_kv_pip_packages(backend_cfg))
elif str(store_type).startswith("sql_"):
additional_pip_packages.extend(get_sql_pip_packages(backend_cfg))

if self.additional_pip_packages:
additional_pip_packages.extend(self.additional_pip_packages)

# Create minimal providers for build config (without runtime configs)
build_providers = {}
for api, providers in self.providers.items():
Expand All @@ -368,7 +340,6 @@ def build_config(self) -> BuildConfig:
providers=build_providers,
),
image_type=LlamaStackImageType.VENV.value, # default to venv
additional_pip_packages=sorted(set(additional_pip_packages)),
)

def generate_markdown_docs(self) -> str:
Expand Down
3 changes: 0 additions & 3 deletions src/llama_stack/distributions/watsonx/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,3 @@ distribution_spec:
files:
- provider_type: inline::localfs
image_type: venv
additional_pip_packages:
- aiosqlite
- sqlalchemy[asyncio]
3 changes: 0 additions & 3 deletions tests/external/ramalama-stack/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,3 @@ distribution_spec:
module: ramalama_stack==0.3.0a0
image_type: venv
image_name: ramalama-stack-test
additional_pip_packages:
- aiosqlite
- sqlalchemy[asyncio]
2 changes: 2 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading