Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
10 changes: 10 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
echo """
venv/
*.pyc
__pycache__
.git
.env
*.egg-info
dist/
build/
""" > .dockerignore
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -204,5 +204,4 @@ cython_debug/
models/
configs/
.pdm-python
.magemaker_configs
.env.save
63 changes: 48 additions & 15 deletions Dockerfile-server
Original file line number Diff line number Diff line change
@@ -1,22 +1,55 @@
# Use an official Python runtime as a parent image
FROM python:3.12-slim
FROM python:3.11-slim

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
build-essential \
unzip \
nano \
vim \
gnupg \
lsb-release \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*

# Set the working directory in the container
# Set working directory
WORKDIR /app

# Copy the project files to the working directory
COPY . .
# Copy your magemaker package
COPY . /app/

# Install PDM and use it to install dependencies
RUN pip install --no-cache-dir pdm \
&& pdm install --no-interactive
# Install package and dependencies
RUN pip install --no-cache-dir -e .

# Expose port 8000 to the outside world
EXPOSE 8000
# Install AWS CLI
RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \
&& unzip awscliv2.zip \
&& ./aws/install \
&& rm awscliv2.zip \
&& rm -rf aws

# Run uvicorn when the container launches
CMD ["pdm", "run", "uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]
# Install Google Cloud SDK
RUN curl https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-458.0.0-linux-x86_64.tar.gz -o google-cloud-sdk.tar.gz \
&& tar -xf google-cloud-sdk.tar.gz \
&& ./google-cloud-sdk/install.sh --quiet \
&& rm google-cloud-sdk.tar.gz

# Install Azure CLI
RUN mkdir -p /etc/apt/keyrings && \
curl -sLS https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | tee /etc/apt/keyrings/microsoft.gpg > /dev/null && \
chmod go+r /etc/apt/keyrings/microsoft.gpg && \
echo "deb [arch=`dpkg --print-architecture` signed-by=/etc/apt/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/azure-cli.list && \
apt-get update && \
apt-get install -y azure-cli && \
rm -rf /var/lib/apt/lists/*

# Add Google Cloud SDK to PATH
ENV PATH $PATH:/app/google-cloud-sdk/bin

# Copy and setup entrypoint
COPY magemaker/docker/entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh

ENTRYPOINT ["entrypoint.sh"]
CMD ["bash"]
14 changes: 14 additions & 0 deletions magemaker/docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
set -e

# Setup AWS credentials if mounted
if [ -f "/root/.aws/credentials" ]; then
export AWS_SHARED_CREDENTIALS_FILE="/root/.aws/credentials"
fi

# Setup GCP credentials if mounted
if [ -f "/root/.config/gcloud/application_default_credentials.json" ]; then
export GOOGLE_APPLICATION_CREDENTIALS="/root/.config/gcloud/application_default_credentials.json"
fi

exec "$@"
15 changes: 12 additions & 3 deletions magemaker/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ class Actions(StrEnum):
# set AWS_REGION in env
os.environ["AWS_REGION"] = "us-west-2"


NC='\033[0m'
YELLOW='\033[1;33m'
GREEN='\033[0;32m'
RED='\033[0;31m'


def deploy_huggingface_model(deployment: Deployment, model: Model):
Expand Down Expand Up @@ -129,9 +132,15 @@ def query_endpoint(endpoint, query):
if config:
config = (config.deployment, config.models[0])
make_query_request(name, query, config)

print('Config for this model not found, try another model')
return

else:
expected_path = os.path.join(os.getcwd(), 'configs', f"{name}.yml")
print(f"[red]Config for this model not found![/red]")
print(f"Expected config location: [green]{expected_path}[/green]")
print(f"[yellow]Please ensure config file exists before querying.[/yellow]")
return

if provider == 'VertexAI':
endpoint_id = resource_name.split('/')[-1]
query_vertexai_endpoint_rest(endpoint_id, query.query)
Expand Down
49 changes: 48 additions & 1 deletion magemaker/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import sys
import traceback
from magemaker.schemas.query import Query
from magemaker.version import VERSION
import yaml
logging.getLogger("sagemaker.config").setLevel(logging.WARNING)
Expand All @@ -12,7 +13,7 @@
from magemaker.schemas.deployment import Deployment
from magemaker.schemas.model import Model, ModelSource
import subprocess
from magemaker.main import main, deploy_model
from magemaker.main import main, deploy_model, query_endpoint

RED='\033[0;31m' #red
NC='\033[0m' # No Color
Expand All @@ -26,6 +27,10 @@ def runner():
# os.system("bash setup.sh")
if '--version' not in sys.argv:
print(f"{GREEN}magemaker v{VERSION}{NC}")

if os.path.exists('.env'):
from dotenv import load_dotenv
load_dotenv()

parser = argparse.ArgumentParser(
description="Create, deploy, query against models.",
Expand Down Expand Up @@ -70,6 +75,11 @@ def runner():
choices=['aws', 'gcp', 'azure', 'all'],
help="Specify the cloud provider for configuration and deployment"
)
parser.add_argument(
"--query",
help="path to YAML query configuration file",
type=str
)
if len(sys.argv) == 1:
# just for the case of magemaker
# parser.print_help()
Expand Down Expand Up @@ -142,6 +152,38 @@ def runner():

quit()

if args.query is not None:
try:
with open(args.query) as config:
configuration = yaml.safe_load(config)

# Extract deployment and model info
deployment = configuration.get('deployment')
model = configuration.get('models')[0]
query_text = configuration.get('query')

if not all([deployment, model, query_text]):
print(f"[red]Error: Invalid query configuration. Required fields missing.[/red]")
sys.exit(1)

endpoint = (
deployment['endpoint_name'], # name
'Sagemaker' if deployment['destination'] == 'aws' else deployment['destination'], # provider
'' # resource_name
)


query = Query(query=query_text)


query_endpoint(endpoint, query)
sys.exit(0)

except Exception as e:
print(f"[red]Error reading query configuration: {str(e)}[/red]")
sys.exit(1)


main(args, loglevel)

if __name__ == '__main__':
Expand Down Expand Up @@ -192,6 +234,11 @@ def runner():
choices=['aws', 'gcp', 'azure'],
help="Specify the cloud provider for configuration and deployment"
)
parser.add_argument(
"--query",
help="path to YAML query configuration file",
type=str
)
args = parser.parse_args()

cmd = ["bash", "scripts/preflight.sh"]
Expand Down
11 changes: 9 additions & 2 deletions magemaker/sagemaker/create_model.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import os
from dotenv import dotenv_values
from rich.table import Table
from sagemaker import image_uris, model_uris, script_uris
Expand All @@ -20,7 +21,9 @@
from magemaker.huggingface import HuggingFaceTask
from magemaker.huggingface.hf_hub_api import get_hf_task


NC='\033[0m' # No Color
YELLOW='\033[1;33m'
GREEN='\033[0;32m'

def deploy_huggingface_model_to_sagemaker(deployment, model):
HUGGING_FACE_HUB_TOKEN = dotenv_values(".env").get("HUGGING_FACE_HUB_KEY")
Expand Down Expand Up @@ -93,6 +96,10 @@ def deploy_huggingface_model_to_sagemaker(deployment, model):

print_success(
f"{model.id} is now up and running at the endpoint [blue]{predictor.endpoint_name}")

config_path = os.path.join(os.getcwd(), 'configs', f"{predictor.endpoint_name}.yml")
print(f"\n{YELLOW}Important:{NC} Configuration saved at: {GREEN}{config_path}{NC}")
print(f"You'll need this path for querying the model later.")

write_config(deployment, model)
return predictor
Expand Down Expand Up @@ -215,4 +222,4 @@ def create_and_deploy_jumpstart_model(deployment: Deployment, model: Model):
print_success(
f"{model.id} is now up and running at the endpoint [blue]{predictor.endpoint_name}")

return predictor
return predictor
2 changes: 1 addition & 1 deletion magemaker/sagemaker/delete_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ def delete_sagemaker_model(endpoint_names: List[str] = None):
# Add validation / error handling
for endpoint in endpoint_names:
print(f"Deleting [blue]{endpoint}")
sagemaker_client.delete_endpoint(EndpointName=endpoint)
sagemaker_client.delete_endpoint(EndpointName=endpoint)
2 changes: 1 addition & 1 deletion magemaker/sagemaker/fine_tune_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,4 @@ def get_hyperparameters_for_model(training: Training, model: Model):
if training.hyperparameters is not None:
hyperparameters.update(
(k, v) for k, v in training.hyperparameters.model_dump().items() if v is not None)
return hyperparameters
return hyperparameters
2 changes: 1 addition & 1 deletion magemaker/sagemaker/query_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,4 +202,4 @@ def test(endpoint_name: str):
text2 = 'simply stupid , irrelevant and deeply , truly , bottomlessly cynical '

for text in [text1, text2]:
query_sagemaker_endpoint(endpoint_name, text.encode('utf-8'))
query_sagemaker_endpoint(endpoint_name, text.encode('utf-8'))
83 changes: 51 additions & 32 deletions magemaker/scripts/preflight.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,43 +25,60 @@ log_error() {
# Configuration functions
configure_aws() {
echo "Configuring AWS..."
echo "you need to create an aws user with access to Sagemaker"
echo "if you don't know how to do that follow this doc https://docs.google.com/document/d/1NvA6uZmppsYzaOdkcgNTRl7Nb4LbpP9Koc4H_t5xNSg/edit?usp=sharing"


# green
if ! command -v aws &> /dev/null
then
OS="$(uname -s)"
case "${OS}" in
Linux*)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
;;
Darwin*)
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
;;
*)
echo "Unsupported OS: ${OS}. See https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"
exit 1
;;
esac
fi
if [ -f ".env" ] && grep -q "AWS_ACCESS_KEY_ID" ".env" && grep -q "AWS_SECRET_ACCESS_KEY" ".env"; then
echo -e "${GREEN}Using AWS credentials from .env file${NC}"
export $(grep "AWS_" .env | xargs)

aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
aws configure set default.region $AWS_DEFAULT_REGION

else
echo "you need to create an aws user with access to Sagemaker"
echo "if you don't know how to do that follow this guide https://magemaker.slashml.com/configuration/AWS"

if ! command -v aws &> /dev/null
then
OS="$(uname -s)"
case "${OS}" in
Linux*)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
;;
Darwin*)
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
;;
*)
echo "Unsupported OS: ${OS}. See https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"
exit 1
;;
esac
fi

# echo green that press enter if you have already done this
echo -e "${GREEN}Press enter in the following configuration steps if you have already done this${NC}"
echo -e "${GREEN}Press enter in the following configuration steps if you have already done this${NC}"

aws configure set region us-east-1 && aws configure
touch .env
read -p "AWS Access Key ID: " aws_access_key_id
read -p "AWS Secret Access Key: " aws_secret_access_key
read -p "Default region name: " aws_region

echo "AWS_ACCESS_KEY_ID=$aws_access_key_id" >> .env
echo "AWS_SECRET_ACCESS_KEY=$aws_secret_access_key" >> .env
echo "AWS_DEFAULT_REGION=$aws_region" >> .env
echo -e "${GREEN}AWS credentials saved to .env file${NC}"

if ! grep -q "SAGEMAKER_ROLE" .env
then
aws configure set aws_access_key_id $aws_access_key_id
aws configure set aws_secret_access_key $aws_secret_access_key
aws configure set default.region $aws_region
fi

if ! grep -q "SAGEMAKER_ROLE" .env
then
# bash ./setup_role.sh
bash "$SCRIPT_DIR/setup_role.sh"
fi
bash "$SCRIPT_DIR/setup_role.sh"
fi
}


Expand All @@ -70,7 +87,7 @@ fi
configure_gcp() {
echo "Configuring GCP..."
echo "you need to create a GCP service account with access to GCS and vertex ai"
echo "if you don't know how to do that follow this doc https://docs.google.com/document/d/1NvA6uZmppsYzaOdkcgNTRl7Nb4LbpP9Koc4H_t5xNSg/edit?usp=sharing"
echo "if you don't know how to do that follow this doc https://magemaker.slashml.com/configuration/GCP"

if ! command -v gcloud &> /dev/null
then
Expand Down Expand Up @@ -153,6 +170,8 @@ fi
# AZURE
configure_azure() {
echo "Configuring Azure..."
echo "you need to create a Azure service account"
echo "if you don't know how to do that follow this doc https://magemaker.slashml.com/configuration/Azure"
echo "Checking for Azure CLI installation..."
if ! command -v az &> /dev/null
then
Expand Down
Loading
Loading