Skip to content

Commit

Permalink
Bola/revert everything (#857)
Browse files Browse the repository at this point in the history
* Revert "Move build configuration script to truss (#847)"

This reverts commit 7271f87.

* Revert "Refactor `truss.server` out of templates to run as normal python program (#829)"

This reverts commit 8b1bf5d.
  • Loading branch information
bolasim authored Mar 7, 2024
1 parent 09b3f5c commit b911be8
Show file tree
Hide file tree
Showing 73 changed files with 520 additions and 365 deletions.
4 changes: 2 additions & 2 deletions poetry.lock

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

6 changes: 1 addition & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
[tool.poetry]
name = "truss"
version = "0.10.0rc1"
version = "0.9.3"
description = "A seamless bridge from model development to model delivery"
license = "MIT"
readme = "README.md"
authors = ["Pankaj Gupta <pankaj@baseten.co>", "Phil Howes <phil@baseten.co>"]
include = ["*.txt", "*.Dockerfile", "*.md"]
repository = "https://github.com/basetenlabs/truss"
keywords = ["MLOps", "AI", "Model Serving", "Model Deployment", "Machine Learning"]
packages = [{include = "truss", format = "wheel"}]

[tool.poetry.urls]
"Homepage" = "https://truss.baseten.co"
Expand Down Expand Up @@ -43,7 +42,6 @@ inquirerpy = "^0.3.4"
google-cloud-storage = "2.10.0"
loguru = ">=0.7.2"
uvloop = "^0.19.0"
pathspec = ">=0.9.0"


[tool.poetry.group.builder.dependencies]
Expand All @@ -65,8 +63,6 @@ huggingface_hub = ">=0.19.4"
google-cloud-storage = "2.10.0"
boto3 = "^1.26.157"
loguru = ">=0.7.2"
pathspec = ">=0.9.0"
typer = "^0.9.0"

[tool.poetry.dev-dependencies]
ipython = "^7.16"
Expand Down
File renamed without changes.
2 changes: 0 additions & 2 deletions truss/build/__init__.py

This file was deleted.

63 changes: 0 additions & 63 deletions truss/build/configure.py

This file was deleted.

17 changes: 4 additions & 13 deletions truss/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from truss.remote.remote_cli import inquire_model_name, inquire_remote_name
from truss.remote.remote_factory import USER_TRUSSRC_PATH, RemoteFactory
from truss.truss_config import Build, ModelServer
from truss.truss_handle import TrussHandle

logging.basicConfig(level=logging.INFO)

Expand Down Expand Up @@ -167,14 +166,8 @@ def build(target_directory: str, build_dir: Path, tag) -> None:
@click.option(
"--attach", is_flag=True, default=False, help="Flag for attaching the process"
)
@click.option(
"--cache/--no-cache",
is_flag=True,
default=True,
help="Flag for caching build or not",
)
@error_handling
def run(target_directory: str, build_dir: Path, tag, port, attach, cache) -> None:
def run(target_directory: str, build_dir: Path, tag, port, attach) -> None:
"""
Runs the docker image for a Truss.
Expand All @@ -190,9 +183,7 @@ def run(target_directory: str, build_dir: Path, tag, port, attach, cache) -> Non
click.confirm(
f"Container already exists at {urls}. Are you sure you want to continue?"
)
tr.docker_run(
build_dir=build_dir, tag=tag, local_port=port, detach=not attach, cache=cache
)
tr.docker_run(build_dir=build_dir, tag=tag, local_port=port, detach=not attach)


@truss_cli.command()
Expand Down Expand Up @@ -455,7 +446,7 @@ def predict(
def push(
target_directory: str,
remote: str,
model_name: Optional[str],
model_name: str,
publish: bool = False,
trusted: bool = False,
promote: bool = False,
Expand Down Expand Up @@ -593,7 +584,7 @@ def cleanup() -> None:
truss.build.cleanup()


def _get_truss_from_directory(target_directory: Optional[str] = None) -> TrussHandle:
def _get_truss_from_directory(target_directory: Optional[str] = None):
"""Gets Truss from directory. If none, use the current directory"""
if target_directory is None:
target_directory = os.getcwd()
Expand Down
49 changes: 47 additions & 2 deletions truss/constants.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import os
import pathlib

TRUSS_PACKAGE_DIR = pathlib.Path(__file__).resolve().parent
from typing import Set

SKLEARN = "sklearn"
TENSORFLOW = "tensorflow"
Expand All @@ -16,18 +15,32 @@
CODE_DIR = pathlib.Path(BASE_DIR, "truss")

TEMPLATES_DIR = pathlib.Path(CODE_DIR, "templates")
SERVER_CODE_DIR: pathlib.Path = TEMPLATES_DIR / "server"
TRITON_SERVER_CODE_DIR: pathlib.Path = TEMPLATES_DIR / "triton"
TRTLLM_TRUSS_DIR: pathlib.Path = TEMPLATES_DIR / "trtllm"
SHARED_SERVING_AND_TRAINING_CODE_DIR_NAME = "shared"
SHARED_SERVING_AND_TRAINING_CODE_DIR: pathlib.Path = (
TEMPLATES_DIR / SHARED_SERVING_AND_TRAINING_CODE_DIR_NAME
)
CONTROL_SERVER_CODE_DIR: pathlib.Path = TEMPLATES_DIR / "control"

SUPPORTED_PYTHON_VERSIONS = {"3.8", "3.9", "3.10", "3.11"}


# Alias for TEMPLATES_DIR
SERVING_DIR: pathlib.Path = TEMPLATES_DIR

REQUIREMENTS_TXT_FILENAME = "requirements.txt"
USER_SUPPLIED_REQUIREMENTS_TXT_FILENAME = "user_requirements.txt"
BASE_SERVER_REQUIREMENTS_TXT_FILENAME = "base_server_requirements.txt"
SERVER_REQUIREMENTS_TXT_FILENAME = "server_requirements.txt"
SYSTEM_PACKAGES_TXT_FILENAME = "system_packages.txt"

FILENAME_CONSTANTS_MAP = {
"config_requirements_filename": REQUIREMENTS_TXT_FILENAME,
"user_supplied_requirements_filename": USER_SUPPLIED_REQUIREMENTS_TXT_FILENAME,
"base_server_requirements_filename": BASE_SERVER_REQUIREMENTS_TXT_FILENAME,
"server_requirements_filename": SERVER_REQUIREMENTS_TXT_FILENAME,
"system_packages_filename": SYSTEM_PACKAGES_TXT_FILENAME,
}

Expand All @@ -47,6 +60,38 @@
TRUSS_DIR = "truss_dir"
TRUSS_HASH = "truss_hash"

HUGGINGFACE_TRANSFORMER_MODULE_NAME: Set[str] = set({})

# list from https://scikit-learn.org/stable/developers/advanced_installation.html
SKLEARN_REQ_MODULE_NAMES: Set[str] = {
"numpy",
"scipy",
"joblib",
"scikit-learn",
"threadpoolctl",
}

XGBOOST_REQ_MODULE_NAMES: Set[str] = {"xgboost"}

# list from https://www.tensorflow.org/install/pip
# if problematic, lets look to https://www.tensorflow.org/install/source
TENSORFLOW_REQ_MODULE_NAMES: Set[str] = {
"tensorflow",
}

LIGHTGBM_REQ_MODULE_NAMES: Set[str] = {
"lightgbm",
}

# list from https://pytorch.org/get-started/locally/
PYTORCH_REQ_MODULE_NAMES: Set[str] = {
"torch",
"torchvision",
"torchaudio",
}

MLFLOW_REQ_MODULE_NAMES: Set[str] = {"mlflow"}

INFERENCE_SERVER_PORT = 8080

HTTP_PUBLIC_BLOB_BACKEND = "http_public"
Expand Down
72 changes: 61 additions & 11 deletions truss/contexts/image_builder/serving_image_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,28 @@
from typing import Any, Dict, List, Optional, Tuple, Type

import boto3
import yaml
from botocore import UNSIGNED
from botocore.client import Config
from google.cloud import storage
from huggingface_hub import get_hf_file_metadata, hf_hub_url, list_repo_files
from huggingface_hub.utils import filter_repo_objects
from truss.constants import (
BASE_SERVER_REQUIREMENTS_TXT_FILENAME,
BASE_TRTLLM_REQUIREMENTS,
CONTROL_SERVER_CODE_DIR,
FILENAME_CONSTANTS_MAP,
MODEL_DOCKERFILE_NAME,
REQUIREMENTS_TXT_FILENAME,
SERVER_CODE_DIR,
SERVER_DOCKERFILE_TEMPLATE_NAME,
SERVER_REQUIREMENTS_TXT_FILENAME,
SHARED_SERVING_AND_TRAINING_CODE_DIR,
SHARED_SERVING_AND_TRAINING_CODE_DIR_NAME,
SYSTEM_PACKAGES_TXT_FILENAME,
TEMPLATES_DIR,
TRTLLM_BASE_IMAGE,
TRTLLM_TRUSS_DIR,
TRUSS_PACKAGE_DIR,
USER_SUPPLIED_REQUIREMENTS_TXT_FILENAME,
)
from truss.contexts.image_builder.cache_warmer import (
Expand All @@ -48,6 +54,9 @@
load_trussignore_patterns,
)

BUILD_SERVER_DIR_NAME = "server"
BUILD_CONTROL_SERVER_DIR_NAME = "control"

CONFIG_FILE = "config.yaml"
USER_TRUSS_IGNORE_FILE = ".truss_ignore"
GCS_CREDENTIALS = "service_account.json"
Expand Down Expand Up @@ -311,15 +320,7 @@ def prepare_image_build_dir(
data_dir = build_dir / config.data_dir # type: ignore[operator]

def copy_into_build_dir(from_path: Path, path_in_build_dir: str):
# using default ignore patterns ignores the `build` dir in truss
copy_tree_or_file(from_path, build_dir / path_in_build_dir, ignore_files=False) # type: ignore[operator]

# Copy truss package from the context builder image to build dir
copy_into_build_dir(TRUSS_PACKAGE_DIR, "truss/")
copy_into_build_dir(
TRUSS_PACKAGE_DIR.parent / "pyproject.toml", "./pyproject.toml"
)
copy_into_build_dir(TRUSS_PACKAGE_DIR.parent / "README.md", "./README.md")
copy_tree_or_file(from_path, build_dir / path_in_build_dir) # type: ignore[operator]

truss_ignore_patterns = []
if (truss_dir / USER_TRUSS_IGNORE_FILE).exists():
Expand Down Expand Up @@ -350,6 +351,10 @@ def copy_into_build_dir(from_path: Path, path_in_build_dir: str):
)
config.requirements.extend(BASE_TRTLLM_REQUIREMENTS)

# Override config.yml
with (build_dir / CONFIG_FILE).open("w") as config_file:
yaml.dump(config.to_dict(verbose=True), config_file)

external_data_files: list = []
data_dir = Path("/app/data/")
if self._spec.external_data is not None:
Expand All @@ -366,8 +371,50 @@ def copy_into_build_dir(from_path: Path, path_in_build_dir: str):
config, truss_dir, build_dir
)

# Copy inference server code
copy_into_build_dir(SERVER_CODE_DIR, BUILD_SERVER_DIR_NAME)
copy_into_build_dir(
SHARED_SERVING_AND_TRAINING_CODE_DIR,
BUILD_SERVER_DIR_NAME + "/" + SHARED_SERVING_AND_TRAINING_CODE_DIR_NAME,
)

# Copy control server code
if config.live_reload:
copy_into_build_dir(CONTROL_SERVER_CODE_DIR, BUILD_CONTROL_SERVER_DIR_NAME)
copy_into_build_dir(
SHARED_SERVING_AND_TRAINING_CODE_DIR,
BUILD_CONTROL_SERVER_DIR_NAME
+ "/control/"
+ SHARED_SERVING_AND_TRAINING_CODE_DIR_NAME,
)

# Copy base TrussServer requirements if supplied custom base image
base_truss_server_reqs_filepath = SERVER_CODE_DIR / REQUIREMENTS_TXT_FILENAME
if config.base_image:
copy_into_build_dir(
base_truss_server_reqs_filepath, BASE_SERVER_REQUIREMENTS_TXT_FILENAME
)

# Copy model framework specific requirements file
server_reqs_filepath = (
TEMPLATES_DIR / model_framework_name / REQUIREMENTS_TXT_FILENAME
)
should_install_server_requirements = file_is_not_empty(server_reqs_filepath)
if should_install_server_requirements:
copy_into_build_dir(server_reqs_filepath, SERVER_REQUIREMENTS_TXT_FILENAME)

with open(base_truss_server_reqs_filepath, "r") as f:
base_server_requirements = f.read()

# If the user has provided python requirements,
# append the truss server requirements, so that any conflicts
# are detected and cause a build failure. If there are no
# requirements provided, we just pass an empty string,
# as there's no need to install anything.
user_provided_python_requirements = (
spec.requirements_txt if spec.requirements else ""
base_server_requirements + spec.requirements_txt
if spec.requirements
else ""
)
if spec.requirements_file is not None:
copy_into_build_dir(
Expand All @@ -381,6 +428,7 @@ def copy_into_build_dir(from_path: Path, path_in_build_dir: str):

self._render_dockerfile(
build_dir,
should_install_server_requirements,
model_files,
use_hf_secret,
cached_files,
Expand All @@ -390,6 +438,7 @@ def copy_into_build_dir(from_path: Path, path_in_build_dir: str):
def _render_dockerfile(
self,
build_dir: Path,
should_install_server_requirements: bool,
model_files: Dict[str, Any],
use_hf_secret: bool,
cached_files: List[str],
Expand Down Expand Up @@ -425,6 +474,7 @@ def _render_dockerfile(

hf_access_token = config.secrets.get(HF_ACCESS_TOKEN_SECRET_NAME)
dockerfile_contents = dockerfile_template.render(
should_install_server_requirements=should_install_server_requirements,
base_image_name_and_tag=base_image_name_and_tag,
should_install_system_requirements=should_install_system_requirements,
should_install_requirements=should_install_python_requirements,
Expand Down
Loading

0 comments on commit b911be8

Please sign in to comment.