forked from phoenix-oss/llama-stack-mirror
Ensure llama stack build --config <> --image-type <> works (#879)
Fix the issues brought up in https://github.com/meta-llama/llama-stack/issues/870 Test all combinations of (conda, container) vs. (template, config) combos.
This commit is contained in:
parent
7de46e40f9
commit
891bf704eb
5 changed files with 66 additions and 37 deletions
|
@ -115,6 +115,8 @@ def run_stack_build_command(
|
||||||
f"Using conda environment {image_name}",
|
f"Using conda environment {image_name}",
|
||||||
color="green",
|
color="green",
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
image_name = f"llamastack-{name}"
|
||||||
|
|
||||||
cprint(
|
cprint(
|
||||||
textwrap.dedent(
|
textwrap.dedent(
|
||||||
|
@ -171,11 +173,22 @@ def run_stack_build_command(
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
_run_stack_build_command_from_build_config(build_config, image_name=image_name)
|
if build_config.image_type == ImageType.container.value and not args.image_name:
|
||||||
|
cprint(
|
||||||
|
"Please specify --image-name when building a container from a config file",
|
||||||
|
color="red",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
_run_stack_build_command_from_build_config(
|
||||||
|
build_config, image_name=image_name, config_path=args.config
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _generate_run_config(
|
def _generate_run_config(
|
||||||
build_config: BuildConfig, build_dir: Path, image_name: str
|
build_config: BuildConfig,
|
||||||
|
build_dir: Path,
|
||||||
|
image_name: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Generate a run.yaml template file for user to edit from a build.yaml file
|
Generate a run.yaml template file for user to edit from a build.yaml file
|
||||||
|
@ -227,8 +240,9 @@ def _generate_run_config(
|
||||||
to_write = json.loads(run_config.model_dump_json())
|
to_write = json.loads(run_config.model_dump_json())
|
||||||
f.write(yaml.dump(to_write, sort_keys=False))
|
f.write(yaml.dump(to_write, sort_keys=False))
|
||||||
|
|
||||||
|
# this path is only invoked when no template is provided
|
||||||
cprint(
|
cprint(
|
||||||
f"You can now edit {run_config_file} and run `llama stack run {image_name}`",
|
f"You can now run your stack with `llama stack run {run_config_file}`",
|
||||||
color="green",
|
color="green",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -237,6 +251,7 @@ def _run_stack_build_command_from_build_config(
|
||||||
build_config: BuildConfig,
|
build_config: BuildConfig,
|
||||||
image_name: Optional[str] = None,
|
image_name: Optional[str] = None,
|
||||||
template_name: Optional[str] = None,
|
template_name: Optional[str] = None,
|
||||||
|
config_path: Optional[str] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
if build_config.image_type == ImageType.container.value:
|
if build_config.image_type == ImageType.container.value:
|
||||||
if template_name:
|
if template_name:
|
||||||
|
@ -263,7 +278,10 @@ def _run_stack_build_command_from_build_config(
|
||||||
f.write(yaml.dump(to_write, sort_keys=False))
|
f.write(yaml.dump(to_write, sort_keys=False))
|
||||||
|
|
||||||
return_code = build_image(
|
return_code = build_image(
|
||||||
build_config, build_file_path, image_name, template_name=template_name
|
build_config,
|
||||||
|
build_file_path,
|
||||||
|
image_name,
|
||||||
|
template_or_config=template_name or config_path,
|
||||||
)
|
)
|
||||||
if return_code != 0:
|
if return_code != 0:
|
||||||
return
|
return
|
||||||
|
@ -277,7 +295,7 @@ def _run_stack_build_command_from_build_config(
|
||||||
with importlib.resources.as_file(template_path) as path:
|
with importlib.resources.as_file(template_path) as path:
|
||||||
run_config_file = build_dir / f"{template_name}-run.yaml"
|
run_config_file = build_dir / f"{template_name}-run.yaml"
|
||||||
shutil.copy(path, run_config_file)
|
shutil.copy(path, run_config_file)
|
||||||
# Find all ${env.VARIABLE} patterns
|
|
||||||
cprint("Build Successful!", color="green")
|
cprint("Build Successful!", color="green")
|
||||||
else:
|
else:
|
||||||
_generate_run_config(build_config, build_dir, image_name)
|
_generate_run_config(build_config, build_dir, image_name)
|
||||||
|
|
|
@ -78,12 +78,15 @@ class StackRun(Subcommand):
|
||||||
|
|
||||||
config_file = Path(args.config)
|
config_file = Path(args.config)
|
||||||
has_yaml_suffix = args.config.endswith(".yaml")
|
has_yaml_suffix = args.config.endswith(".yaml")
|
||||||
|
template_name = None
|
||||||
|
|
||||||
if not config_file.exists() and not has_yaml_suffix:
|
if not config_file.exists() and not has_yaml_suffix:
|
||||||
# check if this is a template
|
# check if this is a template
|
||||||
config_file = (
|
config_file = (
|
||||||
Path(REPO_ROOT) / "llama_stack" / "templates" / args.config / "run.yaml"
|
Path(REPO_ROOT) / "llama_stack" / "templates" / args.config / "run.yaml"
|
||||||
)
|
)
|
||||||
|
if config_file.exists():
|
||||||
|
template_name = args.config
|
||||||
|
|
||||||
if not config_file.exists() and not has_yaml_suffix:
|
if not config_file.exists() and not has_yaml_suffix:
|
||||||
# check if it's a build config saved to conda dir
|
# check if it's a build config saved to conda dir
|
||||||
|
@ -120,7 +123,12 @@ class StackRun(Subcommand):
|
||||||
importlib.resources.files("llama_stack")
|
importlib.resources.files("llama_stack")
|
||||||
/ "distribution/start_container.sh"
|
/ "distribution/start_container.sh"
|
||||||
)
|
)
|
||||||
run_args = [script, config.container_image]
|
image_name = (
|
||||||
|
f"distribution-{template_name}"
|
||||||
|
if template_name
|
||||||
|
else config.container_image
|
||||||
|
)
|
||||||
|
run_args = [script, image_name]
|
||||||
else:
|
else:
|
||||||
current_conda_env = os.environ.get("CONDA_DEFAULT_ENV")
|
current_conda_env = os.environ.get("CONDA_DEFAULT_ENV")
|
||||||
image_name = args.image_name or current_conda_env
|
image_name = args.image_name or current_conda_env
|
||||||
|
|
|
@ -10,7 +10,7 @@ import sys
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from termcolor import cprint
|
from termcolor import cprint
|
||||||
|
@ -107,9 +107,9 @@ def build_image(
|
||||||
build_config: BuildConfig,
|
build_config: BuildConfig,
|
||||||
build_file_path: Path,
|
build_file_path: Path,
|
||||||
image_name: str,
|
image_name: str,
|
||||||
template_name: Optional[str] = None,
|
template_or_config: str,
|
||||||
):
|
):
|
||||||
container_image = (
|
container_base = (
|
||||||
build_config.distribution_spec.container_image or "python:3.10-slim"
|
build_config.distribution_spec.container_image or "python:3.10-slim"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -119,16 +119,14 @@ def build_image(
|
||||||
normal_deps += SERVER_DEPENDENCIES
|
normal_deps += SERVER_DEPENDENCIES
|
||||||
|
|
||||||
if build_config.image_type == ImageType.container.value:
|
if build_config.image_type == ImageType.container.value:
|
||||||
if not template_name:
|
|
||||||
raise ValueError("template_name is required for container builds")
|
|
||||||
|
|
||||||
script = str(
|
script = str(
|
||||||
importlib.resources.files("llama_stack") / "distribution/build_container.sh"
|
importlib.resources.files("llama_stack") / "distribution/build_container.sh"
|
||||||
)
|
)
|
||||||
args = [
|
args = [
|
||||||
script,
|
script,
|
||||||
template_name,
|
template_or_config,
|
||||||
container_image,
|
image_name,
|
||||||
|
container_base,
|
||||||
str(build_file_path),
|
str(build_file_path),
|
||||||
str(BUILDS_BASE_DIR / ImageType.container.value),
|
str(BUILDS_BASE_DIR / ImageType.container.value),
|
||||||
" ".join(normal_deps),
|
" ".join(normal_deps),
|
||||||
|
|
|
@ -12,22 +12,22 @@ TEST_PYPI_VERSION=${TEST_PYPI_VERSION:-}
|
||||||
PYPI_VERSION=${PYPI_VERSION:-}
|
PYPI_VERSION=${PYPI_VERSION:-}
|
||||||
BUILD_PLATFORM=${BUILD_PLATFORM:-}
|
BUILD_PLATFORM=${BUILD_PLATFORM:-}
|
||||||
|
|
||||||
if [ "$#" -lt 5 ]; then
|
if [ "$#" -lt 6 ]; then
|
||||||
# This only works for templates
|
# This only works for templates
|
||||||
echo "Usage: $0 <template_name> <container_base> <pip_dependencies> <host_build_dir> [<special_pip_deps>]" >&2
|
echo "Usage: $0 <template_or_config> <image_name> <container_base> <build_file_path> <host_build_dir> <pip_dependencies> [<special_pip_deps>]" >&2
|
||||||
echo "Example: $0 fireworks python:3.9-slim 'fastapi uvicorn' /path/to/build/dir" >&2
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
special_pip_deps="$6"
|
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
template_name="$1"
|
template_or_config="$1"
|
||||||
container_base=$2
|
image_name="$2"
|
||||||
build_file_path=$3
|
container_base="$3"
|
||||||
host_build_dir=$4
|
build_file_path="$4"
|
||||||
pip_dependencies=$5
|
host_build_dir="$5"
|
||||||
|
pip_dependencies="$6"
|
||||||
|
special_pip_deps="$7"
|
||||||
|
|
||||||
|
|
||||||
# Define color codes
|
# Define color codes
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
|
@ -147,14 +147,16 @@ RUN pip install --no-cache $models_mount
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# if template_or_config ends with .yaml, it is not a template and we should not use the --template flag
|
||||||
|
if [[ "$template_or_config" != *.yaml ]]; then
|
||||||
add_to_container << EOF
|
add_to_container << EOF
|
||||||
|
ENTRYPOINT ["python", "-m", "llama_stack.distribution.server.server", "--template", "$template_or_config"]
|
||||||
# This would be good in production but for debugging flexibility lets not add it right now
|
|
||||||
# We need a more solid production ready entrypoint.sh anyway
|
|
||||||
#
|
|
||||||
ENTRYPOINT ["python", "-m", "llama_stack.distribution.server.server", "--template", "$template_name"]
|
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
else
|
||||||
|
add_to_container << EOF
|
||||||
|
ENTRYPOINT ["python", "-m", "llama_stack.distribution.server.server"]
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
printf "Containerfile created successfully in $TEMP_DIR/Containerfile\n\n"
|
printf "Containerfile created successfully in $TEMP_DIR/Containerfile\n\n"
|
||||||
cat $TEMP_DIR/Containerfile
|
cat $TEMP_DIR/Containerfile
|
||||||
|
@ -174,7 +176,9 @@ if command -v selinuxenabled &>/dev/null && selinuxenabled; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set version tag based on PyPI version
|
# Set version tag based on PyPI version
|
||||||
if [ -n "$TEST_PYPI_VERSION" ]; then
|
if [ -n "$PYPI_VERSION" ]; then
|
||||||
|
version_tag="$PYPI_VERSION"
|
||||||
|
elif [ -n "$TEST_PYPI_VERSION" ]; then
|
||||||
version_tag="test-$TEST_PYPI_VERSION"
|
version_tag="test-$TEST_PYPI_VERSION"
|
||||||
elif [[ -n "$LLAMA_STACK_DIR" || -n "$LLAMA_MODELS_DIR" ]]; then
|
elif [[ -n "$LLAMA_STACK_DIR" || -n "$LLAMA_MODELS_DIR" ]]; then
|
||||||
version_tag="dev"
|
version_tag="dev"
|
||||||
|
@ -184,8 +188,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add version tag to image name
|
# Add version tag to image name
|
||||||
build_name="distribution-$template_name"
|
image_tag="$image_name:$version_tag"
|
||||||
image_tag="$build_name:$version_tag"
|
|
||||||
|
|
||||||
# Detect platform architecture
|
# Detect platform architecture
|
||||||
ARCH=$(uname -m)
|
ARCH=$(uname -m)
|
||||||
|
|
|
@ -30,8 +30,8 @@ if [ $# -lt 3 ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
build_name="$1"
|
image_name="$1"
|
||||||
container_image="localhost/distribution-$build_name"
|
container_image="localhost/$image_name"
|
||||||
shift
|
shift
|
||||||
|
|
||||||
yaml_config="$1"
|
yaml_config="$1"
|
||||||
|
@ -76,13 +76,15 @@ if [ -n "$LLAMA_CHECKPOINT_DIR" ]; then
|
||||||
CONTAINER_OPTS="$CONTAINER_OPTS --gpus=all"
|
CONTAINER_OPTS="$CONTAINER_OPTS --gpus=all"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
version_tag="latest"
|
|
||||||
if [ -n "$PYPI_VERSION" ]; then
|
if [ -n "$PYPI_VERSION" ]; then
|
||||||
version_tag="$PYPI_VERSION"
|
version_tag="$PYPI_VERSION"
|
||||||
elif [ -n "$LLAMA_STACK_DIR" ]; then
|
elif [ -n "$LLAMA_STACK_DIR" ]; then
|
||||||
version_tag="dev"
|
version_tag="dev"
|
||||||
elif [ -n "$TEST_PYPI_VERSION" ]; then
|
elif [ -n "$TEST_PYPI_VERSION" ]; then
|
||||||
version_tag="test-$TEST_PYPI_VERSION"
|
version_tag="test-$TEST_PYPI_VERSION"
|
||||||
|
else
|
||||||
|
URL="https://pypi.org/pypi/llama-stack/json"
|
||||||
|
version_tag=$(curl -s $URL | jq -r '.info.version')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$CONTAINER_BINARY run $CONTAINER_OPTS -it \
|
$CONTAINER_BINARY run $CONTAINER_OPTS -it \
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue