From 132fac3f7b780cd6a6e5fe870ba90d024ba57bf2 Mon Sep 17 00:00:00 2001 From: macielcalebe Date: Wed, 28 Aug 2024 09:41:15 -0300 Subject: [PATCH] Deployed a68dca1 with MkDocs version: 1.5.2 --- 404.html | 42 + about/index.html | 42 + classes/01-intro/aps01_part_1/index.html | 46 +- classes/01-intro/aps01_part_2/index.html | 42 + classes/01-intro/intro/index.html | 42 + classes/02-api/api_deploy/index.html | 42 + classes/03-batch/aps02_sql/index.html | 44 +- classes/03-batch/data_formats/index.html | 48 +- classes/03-batch/db_tool/index.html | 42 + classes/03-batch/dot_env/index.html | 42 + classes/03-batch/intro/index.html | 52 +- classes/03-batch/practicing/index.html | 46 +- classes/03-batch/sql/index.html | 42 + classes/04-int01/faq/index.html | 42 + classes/04-int01/int01/index.html | 42 + classes/05-docker/docker/index.html | 42 + classes/05-docker/intro/index.html | 42 + classes/05-docker/s3/index.html | 46 +- classes/06-message-broker/celery/index.html | 49 + classes/06-message-broker/intro/index.html | 44 +- classes/06-message-broker/rabbitmq/index.html | 48 +- classes/07-lambda/api_gateway/index.html | 596 ++++++++++++ classes/07-lambda/api_gateway_lambda.png | Bin 0 -> 77733 bytes classes/07-lambda/aps03_lambda/index.html | 580 ++++++++++++ classes/07-lambda/aws_lambda/index.html | 557 +++++++++++ classes/07-lambda/lambda-layers-diagram.png | Bin 0 -> 71382 bytes .../07-lambda/lambda_and_docker/index.html | 717 +++++++++++++++ classes/07-lambda/lambda_layer/index.html | 863 ++++++++++++++++++ .../07-lambda/lambda_practicing/index.html | 724 +++++++++++++++ classes/07-lambda/lambda_quotas/index.html | 485 ++++++++++ .../07-lambda/sa_lambda_function/index.html | 618 +++++++++++++ .../07-lambda/sentiment_analysis/index.html | 550 +++++++++++ contributions/index.html | 42 + deadlines/index.html | 42 + index.html | 42 + sitemap.xml.gz | Bin 127 -> 127 bytes 36 files changed, 6724 insertions(+), 19 deletions(-) create mode 100644 classes/07-lambda/api_gateway/index.html create mode 100644 classes/07-lambda/api_gateway_lambda.png create mode 100644 classes/07-lambda/aps03_lambda/index.html create mode 100644 classes/07-lambda/aws_lambda/index.html create mode 100644 classes/07-lambda/lambda-layers-diagram.png create mode 100644 classes/07-lambda/lambda_and_docker/index.html create mode 100644 classes/07-lambda/lambda_layer/index.html create mode 100644 classes/07-lambda/lambda_practicing/index.html create mode 100644 classes/07-lambda/lambda_quotas/index.html create mode 100644 classes/07-lambda/sa_lambda_function/index.html create mode 100644 classes/07-lambda/sentiment_analysis/index.html diff --git a/404.html b/404.html index 91e2e5f..25e530e 100644 --- a/404.html +++ b/404.html @@ -352,6 +352,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/about/index.html b/about/index.html index dd641fe..5013c58 100644 --- a/about/index.html +++ b/about/index.html @@ -380,6 +380,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/01-intro/aps01_part_1/index.html b/classes/01-intro/aps01_part_1/index.html index b9b5812..ceb9770 100644 --- a/classes/01-intro/aps01_part_1/index.html +++ b/classes/01-intro/aps01_part_1/index.html @@ -400,6 +400,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + @@ -569,7 +611,7 @@

    Task 01: Opening

    -
    +

    Question 2

    Explain, in general terms, what is the model predicting?

    @@ -588,7 +630,7 @@

    Task 01: Opening

    -
    +

    Question 3

    Considering the everything.ipynb notebook, what is the target variable used in training the model?

    diff --git a/classes/01-intro/aps01_part_2/index.html b/classes/01-intro/aps01_part_2/index.html index 32149da..cbea58f 100644 --- a/classes/01-intro/aps01_part_2/index.html +++ b/classes/01-intro/aps01_part_2/index.html @@ -376,6 +376,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/01-intro/intro/index.html b/classes/01-intro/intro/index.html index db80629..a0cdf8f 100644 --- a/classes/01-intro/intro/index.html +++ b/classes/01-intro/intro/index.html @@ -372,6 +372,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/02-api/api_deploy/index.html b/classes/02-api/api_deploy/index.html index eb8bf53..7f33cef 100644 --- a/classes/02-api/api_deploy/index.html +++ b/classes/02-api/api_deploy/index.html @@ -384,6 +384,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/03-batch/aps02_sql/index.html b/classes/03-batch/aps02_sql/index.html index 06c05c3..b0a474f 100644 --- a/classes/03-batch/aps02_sql/index.html +++ b/classes/03-batch/aps02_sql/index.html @@ -384,6 +384,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + @@ -570,7 +612,7 @@

    TASK 1: Query file for analytica

    For now...

    For now, keep saving and reading the model in the models folder!

    -
    +

    Question 5

    Why should we avoid using * in production queries?

    diff --git a/classes/03-batch/data_formats/index.html b/classes/03-batch/data_formats/index.html index face31a..00a3c65 100644 --- a/classes/03-batch/data_formats/index.html +++ b/classes/03-batch/data_formats/index.html @@ -384,6 +384,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + @@ -473,7 +515,7 @@

    CSV

    Lack of Data Compression: CSV files do not provide built-in data compression. As a result, they can occupy a lot of disk space.

    -
    +

    Question 1

    In ML, where large datasets are common, give some examples where increased storage requirements can become a concern.

    @@ -679,7 +721,7 @@

    Exercises

    -
    +

    Question 8

    What are your conclusions?

    @@ -696,7 +738,7 @@

    Exercises

    For example, when performing column and row filters, pandas generally needs to read the entire file into memory first before it can apply the filter.

    On the other hand, Apache Spark does not need to read the entire parquet file to filter by a column, thanks to its ability to perform predicate pushdown and the efficient structure of the parquet format.

    -
    +

    Question 9

    What predicate pushdown means?!

    diff --git a/classes/03-batch/db_tool/index.html b/classes/03-batch/db_tool/index.html index 8041523..4762b7f 100644 --- a/classes/03-batch/db_tool/index.html +++ b/classes/03-batch/db_tool/index.html @@ -372,6 +372,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/03-batch/dot_env/index.html b/classes/03-batch/dot_env/index.html index 87f3164..3f4cca1 100644 --- a/classes/03-batch/dot_env/index.html +++ b/classes/03-batch/dot_env/index.html @@ -368,6 +368,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/03-batch/intro/index.html b/classes/03-batch/intro/index.html index 368fd02..f9fbf38 100644 --- a/classes/03-batch/intro/index.html +++ b/classes/03-batch/intro/index.html @@ -372,6 +372,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + @@ -482,7 +524,7 @@

    What is batch prediction?

    Doing batch prediction

    In the first class, when we saw how to standardize a data science project, there were specific folders for data storage, notebooks and source code.

    -
    +

    Question 2

    Would the data.csv file be used during training? How would you deal with data?

    @@ -497,7 +539,7 @@

    Doing batch prediction

    If the model doensn't exists, we need data to train it! So, probably yes!

    -
    +

    Question 3

    During the phase of model construction, would this data.csv file change? Explain it.

    @@ -513,7 +555,7 @@

    Doing batch prediction

    Assuming enough data, it would be transformed (feature engineering, feature selection) but would remain the same during training in the phase of model construction.

    -
    +

    Question 4

    After model deployment:

    @@ -535,7 +577,7 @@

    Doing batch prediction

    We'll deal with retraining in the next classes, but it's important to start thinking about it!

    -
    +

    Question 5

    What about when we deploy the model and need to predict with it?

    @@ -552,7 +594,7 @@

    Doing batch prediction

    Absolutely not! In the first class we did this for simplicity. We would like to make predictions on new data.

    -
    +

    Question 6

    Still on prediction in new data: assuming that the model reads a batch of data from a file called predict.csv, would this file remain the same (have the same records) every time the predict script is called?

    diff --git a/classes/03-batch/practicing/index.html b/classes/03-batch/practicing/index.html index 7b0cd41..8844338 100644 --- a/classes/03-batch/practicing/index.html +++ b/classes/03-batch/practicing/index.html @@ -392,6 +392,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + @@ -979,7 +1021,7 @@

    Task 5: Making predictions

    Done! Whenever there is a new file that must be predicted, just call the predict.py script, informing which model to be used and the path of the file with the data! Then, the model will read this batch of information and perform the prediction.

    Extra questions!

    Categorical variables

    -
    +

    Question 7

    Are there categorical variables in the training data? If yes, which ones?

    @@ -1017,7 +1059,7 @@

    OOT validation

    Tip! 1

    Once you decide the model is good enough, you can retrain with the whole base (January to July) and deploy this new version of the model!

    -
    +

    Question 9

    Explain when is it a good idea to use OOT and what would be the consequences if you don't!

    diff --git a/classes/03-batch/sql/index.html b/classes/03-batch/sql/index.html index 72da24c..5da8d72 100644 --- a/classes/03-batch/sql/index.html +++ b/classes/03-batch/sql/index.html @@ -360,6 +360,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/04-int01/faq/index.html b/classes/04-int01/faq/index.html index 80a1474..c04b2e5 100644 --- a/classes/04-int01/faq/index.html +++ b/classes/04-int01/faq/index.html @@ -368,6 +368,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/04-int01/int01/index.html b/classes/04-int01/int01/index.html index 67955ef..a36fd1e 100644 --- a/classes/04-int01/int01/index.html +++ b/classes/04-int01/int01/index.html @@ -360,6 +360,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/05-docker/docker/index.html b/classes/05-docker/docker/index.html index 7608c2f..a25b404 100644 --- a/classes/05-docker/docker/index.html +++ b/classes/05-docker/docker/index.html @@ -376,6 +376,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/05-docker/intro/index.html b/classes/05-docker/intro/index.html index 60197ce..02c274f 100644 --- a/classes/05-docker/intro/index.html +++ b/classes/05-docker/intro/index.html @@ -372,6 +372,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/classes/05-docker/s3/index.html b/classes/05-docker/s3/index.html index 046d860..fc1d309 100644 --- a/classes/05-docker/s3/index.html +++ b/classes/05-docker/s3/index.html @@ -376,6 +376,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + @@ -617,7 +659,7 @@

    Submit file

    Refactoring

    In the previous class (SQL) we made a version of the project that uses a PostgreSQL server as the data source.

    -
    +

    Question 7

    Do you consider that S3 could serve as a data source for model training/predict? Explain.

    @@ -634,7 +676,7 @@

    Refactoring

    But the model pickles were always only stored locally in the models folder.

    -
    +

    Question 8

    Do you consider that S3 could serve as storage for model pickles? Explain.

    diff --git a/classes/06-message-broker/celery/index.html b/classes/06-message-broker/celery/index.html index 13e114d..608d509 100644 --- a/classes/06-message-broker/celery/index.html +++ b/classes/06-message-broker/celery/index.html @@ -388,6 +388,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + @@ -650,6 +692,13 @@

    References

    + + Próximo + Aws lambda + +
    diff --git a/classes/06-message-broker/intro/index.html b/classes/06-message-broker/intro/index.html index 45ee324..ec9c867 100644 --- a/classes/06-message-broker/intro/index.html +++ b/classes/06-message-broker/intro/index.html @@ -376,6 +376,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + @@ -414,7 +456,7 @@

    Message Broker

    Suppose that, for some deliveries, he recommends sending a message explaining the situation (reason for the delay). This sending (Telegram, Email, WhatsApp) will not be done by the ML model and will require calling an extra application.

    An alternative is to add the model's predict result to a queue, so that the sending application (Telegram, Email, WhatsApp) handles the messages according to their availability. The application responsible for managing this queue is the message broker.

    -
    +

    Question 1

    Could the message broker be used to create a queue of JSON from customers for a model to process? For example: diff --git a/classes/06-message-broker/rabbitmq/index.html b/classes/06-message-broker/rabbitmq/index.html index 8cd03a7..8788c00 100644 --- a/classes/06-message-broker/rabbitmq/index.html +++ b/classes/06-message-broker/rabbitmq/index.html @@ -376,6 +376,48 @@ + +

  • + 07 - Lambda Functions + +
  • + + @@ -469,7 +511,7 @@

    Create docker-compose.yml

    Docker Compose allows defining and running multiple Docker containers using a Compose file that describes the whole application. It makes it easy to collaborate on multi-container apps.

    For now our application will only contain RabbitMQ, but it costs nothing to practice!

    -
    +

    Question 2

    Explain what this section means:

    @@ -738,7 +780,7 @@

    Consume messages

    -
    +

    Question 14

    Change the callback function to: @@ -765,7 +807,7 @@

    Consume messages

    Due to auto_ack=False, if the consumer dies before notifying that the message was correctly processed, then the message is automatically redistributed to other consumers (or waits in the queue if there are no free consumers).

    -
    +

    Question 15

    Can you think of some situations where the use of auto_ack=True is indicated?

    diff --git a/classes/07-lambda/api_gateway/index.html b/classes/07-lambda/api_gateway/index.html new file mode 100644 index 0000000..e579a96 --- /dev/null +++ b/classes/07-lambda/api_gateway/index.html @@ -0,0 +1,596 @@ + + + + + + + + + Api gateway - MLOps & Interviews + + + + + + + + + + + + + + + + +
    +
    + + +
    + + + + + + + +
    +
    + +
    + +
    +
      + + + +
    • Classes
    • + + + +
    • 07 - Lambda Functions
    • + + + +
    • Part 1
    • + + +
    • +
    + + +
    + +
    +

    API Gateway

    +

    API

    +

    We will add an API service. Thus, every time there is a call to the API endpoint, whether through the browser or an application, the Lambda function will be triggered.

    +

    This will be the schematic drawing:

    +

    +

    Create API

    +
    +

    Question 1

    + +

    Change API name (some new name) and function name (created on previous page).

    +
    + + +
    + +
    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +import random
    +import string
    +
    +
    +load_dotenv()
    +
    +lambda_function_name = "" # Example: sayHello_<INSPER_USERNAME>
    +api_gateway_name = "" # Example: api_hello_<INSPER_USERNAME>"
    +
    +id_num = "".join(random.choices(string.digits, k=7))
    +
    +api_gateway = boto3.client(
    +    "apigatewayv2",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +lambda_function = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +lambda_function_get = lambda_function.get_function(FunctionName=lambda_function_name)
    +
    +print(lambda_function_get)
    +
    +api_gateway_create = api_gateway.create_api(
    +    Name=api_gateway_name,
    +    ProtocolType="HTTP",
    +    Version="1.0",
    +    RouteKey="ANY /", # Here you can change to GET POST and provide route like "GET /hello"
    +    Target=lambda_function_get["Configuration"]["FunctionArn"],
    +)
    +
    +api_gateway_permissions = lambda_function.add_permission(
    +    FunctionName=lambda_function_name,
    +    StatementId="api-gateway-permission-statement-" + id_num,
    +    Action="lambda:InvokeFunction",
    +    Principal="apigateway.amazonaws.com",
    +)
    +
    +print("API Endpoint:", api_gateway_create["ApiEndpoint"])
    +
    +
    +

    Question 2

    +
    +

    access the provided endpoint to check if the API works!

    +
    + + +
    +
    +
    +

    Show APIs

    +

    To list the APIs registered in the account, use:

    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +api_gateway = boto3.client(
    +    "apigatewayv2",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +response = api_gateway.get_apis(MaxResults="2000")
    +
    +# Show APIs name and endpoint
    +print("APIs:")
    +for api in response["Items"]:
    +    print(f"- {api['Name']} ({api['ApiEndpoint']})")
    +
    +
    +

    Question 3

    +
    +

    Make sure your API is on the list

    +
    + + +
    +
    +
    +

    Practicing

    +
    +

    Question 4

    +
    +

    To practice, you should create a lambda function that returns the number of words in a sentence.

    +

    You must create a POST /word-count route that receives a phrase in the body of the request.

    +
    + + +
    +
    +
    + + +
    + + +
    + +
    + + + + + \ No newline at end of file diff --git a/classes/07-lambda/api_gateway_lambda.png b/classes/07-lambda/api_gateway_lambda.png new file mode 100644 index 0000000000000000000000000000000000000000..793e4e91a11ef961ec1194616d5ae63aaddfafab GIT binary patch literal 77733 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 z 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 literal 0 HcmV?d00001 diff --git a/classes/07-lambda/aps03_lambda/index.html b/classes/07-lambda/aps03_lambda/index.html new file mode 100644 index 0000000..2c1ca3e --- /dev/null +++ b/classes/07-lambda/aps03_lambda/index.html @@ -0,0 +1,580 @@ + + + + + + + + + Aps03 lambda - MLOps & Interviews + + + + + + + + + + + + + + + + +
    +
    + + +
    + + + + + + + +
    +
    + +
    + +
    +
      + + +
    • +
    + + +
    + +
    +

    APS 03

    +

    In this assignment, we are going to create a new version of the work from the API class.

    +

    Accept assignment

    +

    All assignments delivery will be made using Git repositories. Access the link below to accept the invitation and start working on the third assignment.

    +

    Invitation link

    +

    Clone repository

    +

    Clone your private repository:

    +
    +

    Question 1

    +
    +

    Create a .gitignore and make sure the .env is in it!

    +
    + + +
    +
    +
    +

    Start working!

    +

    Our goal is to transform the predict route from class 02 into a lambda function. In other words, assume the model is already trained and that the model pickle can be embedded in the Docker image.

    +
    +

    Important!

    +

    Realize that we will no longer be using FastAPI. We will create a lambda function that has a handler for predict, then we will create an API Gateway that exposes the lambda function.

    +
    +
    +

    Question 2

    +
    +

    Create the .py file with the function handler.

    +
    + + +
    +
    +
    +
    +

    Question 3

    +
    +

    Create the requirements.txt file with the dependencies.

    +
    + + +
    +
    +
    +
    +

    Question 4

    +
    +

    Create the Dockerfile

    +
    +

    Tip! 1

    +

    In order to install lightgbm, you will need to install some dependencies on the system. So, before RUN pip install -r requirements.txt you can add:

    +
    # Install system dependencies
    +RUN yum install -y libstdc++ cmake gcc-c++ && \
    +    yum clean all && \
    +    rm -rf /var/cache/yum
    +
    +# Install the specified packages
    +RUN pip install -r requirements.txt
    +
    +
    +
    + + +
    +
    +
    +
    +

    Question 5

    +
    +

    Create the Docker image

    +
    + + +
    +
    +
    +
    +

    Question 6

    +
    +

    Test the Docker image locally

    +
    + + +
    +
    +
    +
    +

    Question 7

    +
    +

    Create a new repository aps03_<INSPER_USERNAME> in ECR

    +
    + + +
    +
    +
    +
    +

    Question 8

    +
    +

    Tag and push your image to the ECR repository

    +
    + + +
    +
    +
    +
    +

    Question 9

    +
    +

    Create a lambda function associated with your image

    +
    + + +
    +
    +
    +
    +

    Question 10

    +
    +

    Test the lambda function

    +
    + + +
    +
    +
    +
    +

    Question 11

    +
    +

    Create an API Gateway and test it.

    +

    Leave in the README an example of how to test your API Gateway (curl command or Python code).

    +
    + + +
    +
    +
    +
    +

    Question 12

    +
    +

    Commit and push: mission accomplished!

    +
    + + +
    +
    +
    + + +
    + + +
    +
    + +
    +
    + + + + + \ No newline at end of file diff --git a/classes/07-lambda/aws_lambda/index.html b/classes/07-lambda/aws_lambda/index.html new file mode 100644 index 0000000..5e02234 --- /dev/null +++ b/classes/07-lambda/aws_lambda/index.html @@ -0,0 +1,557 @@ + + + + + + + + + Aws lambda - MLOps & Interviews + + + + + + + + + + + + + + + + +
    +
    + + +
    + + + + + + + +
    +
    + +
    + +
    +
      + + + +
    • Classes
    • + + + +
    • 07 - Lambda Functions
    • + + + +
    • Part 1
    • + + +
    • +
    + + +
    + +
    +

    AWS Lambda

    +

    FaaS

    +

    Function as a Service (FaaS) refers to a cloud computing model that allows developers to build and run applications and functions without having to worry about infrastructure management.

    +

    With FaaS, developers are able to deploy their code in the form of stateless functions or event handlers that can be invoked on-demand or in response to events.

    +
    +

    Info!

    +

    FaaS is considered a form of serverless computing. The FaaS platform takes care of:

    +
      +
    • Underlying servers
    • +
    • Operating systems and platforms
    • +
    • Scaling and operating the application
    • +
    +

    Making it simple for developers to focus only on writing code for their specific business logic or tasks.

    +
    +

    Market solutions

    +

    The main providers of FaaS platforms include:

    +
      +
    • +

      AWS Lambda

      +
    • +
    • +

      Google Cloud Functions

      +
    • +
    • +

      Microsoft Azure Functions

      +
    • +
    +

    We will work with AWS Lambda!

    +

    AWS Lambda

    +

    AWS Lambda is Amazon's flagship serverless computing platform that runs your code on high-availability compute infrastructure and performs all the administration of the compute resources.

    +

    The Lambda functions can be triggered by various events like changes to an S3 bucket or database tables, calls from API Gateway or third party applications, or on a schedule.

    +

    Advantages

    +

    Some reasons why Lambda functions should be considered to deploy ML applications:

    +
      +
    • +

      Scalability: Lambda can automatically scale up or down to handle varying loads. This is important for ML models that may see bursty traffic or need to handle prediction requests at scale.

      +
    • +
    • +

      Event-driven: Lambda functions can be easily triggered by events like incoming data. This makes it simple to run ML predictions every time new data comes in without managing servers.

      +
    • +
    • +

      Pay-per-use: with Lambda, you only pay for the compute resources used to run your code. This saves costs for ML workloads that may be intermittent or only needed during model training cycles.

      +
    • +
    • +

      No servers to manage: Lambda handles all the infrastructure maintenance, so you can focus on coding your ML logic without worrying about servers, scaling, availability etc.

      +
    • +
    • +

      Deployment flexibility: you can host complex ML pipelines or prediction code on Lambda. Models can also be deployed as REST APIs using API Gateway for low-latency predictions.

      +
    • +
    +

    Disadvantages

    +

    AWS Lambda may not always be the best choice for ML applications due to:

    +
      +
    • +

      Limited memory/compute: Lambda functions have strict memory limits ranging from 128MB to 10240MB. ML models often require much more RAM.

      +
    • +
    • +

      Cold start: when a Lambda function hasn't been invoked in awhile, the first invocation takes longer due to container initialization. This may not be suitable for real-time ML inferences.

      +
    • +
    • +

      Stateful dependencies: Lambda functions are stateless by design. Supporting stateful dependencies like databases for ML model training is challenging.

      +
    • +
    • +

      Long-running workloads: ML model training typically involves batch processing large datasets over long periods which exceeds Lambda's 15 minute timeout limit.

      +
    • +
    • +

      GPU/TPU support: Lambda doesn't support hardware accelerators like GPUs which are essential for many deep learning workloads.

      +
    • +
    + + +
    + + +
    + +
    + + + + + \ No newline at end of file diff --git a/classes/07-lambda/lambda-layers-diagram.png b/classes/07-lambda/lambda-layers-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..dbbba2ec951ead3c5e37f53dd6802b5fa2787454 GIT binary patch literal 71382 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 + + + + + + + + Lambda and docker - MLOps & Interviews + + + + + + + + + + + + + + + + +

    +
    + + +
    + + + + + + + +
    +
    + +
    + +
    +
      + + +
    • +
    + + +
    + +
    +

    Lambda and Docker

    +

    Introduction

    +

    We saw in previous classes why Docker is important for ML. In this class, we will see how to create Docker images and deploy Lambda functions from them.

    +

    Create Function

    +

    Consider the following lambda function code:

    +
    import sys
    +
    +def hello_from_docker(event, context):
    +    return {
    +        "created_by": "your name",
    +        "message": "Hello World!",
    +        "version": sys.version
    +    }
    +
    +

    Our goal is to deploy this function with Docker + Lambda.

    +
    +

    Important!

    +

    Create a folder for today's class and store the suggested files in the root of this folder

    +
    +
    +

    Question 1

    +
    +

    Save the source code above in lambda_function.py file.

    +
    + + +
    +
    +
    +
    +

    Question 2

    +
    +

    Create a requirements.txt with some dummy dependencies like textblob or pandas.

    +
    +

    For now, we will not use these dependencies, they will only serve as an example for the tasks at the end of the class.

    +
    +
    + + +
    +
    +
    +

    Create Image

    +
    +

    Question 3

    +
    +

    Create a file Dockerfile with the content:

    +
    +

    Notice:

    +
      +
    • The image used
    • +
    • The dependencies
    • +
    • The file with the handler
    • +
    +

    See more images Here

    +
    +
    FROM public.ecr.aws/lambda/python:3.10
    +
    +# Copy requirements.txt
    +COPY requirements.txt ${LAMBDA_TASK_ROOT}
    +
    +# Copy function code
    +COPY lambda_function.py ${LAMBDA_TASK_ROOT}
    +
    +# Install the specified packages
    +RUN pip install -r requirements.txt
    +
    +# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
    +CMD [ "lambda_function.hello_from_docker" ]
    +
    +
    + + +
    +
    +
    +

    Let's name the image lambda-ex-image and give it the test tag:

    +
    + +
    $ docker build --platform linux/amd64 -t lambda-ex-image:test .
    +
    + +
    + +

    Test locally

    +

    Before deploying, let's test the function locally Start the Docker image with the `docker run`` command.

    +
    + +
    $ docker run -p 9500:8080 lambda-ex-image:test
    +
    + +
    + +

    Let's make a request with:

    +

    +

    + +
    $ curl "http://localhost:9500/2015-03-31/functions/function/invocations" -d '{}'
    +
    + +
    +

    + +

    If that doesn't work, try:

    +

    +

    + +
    $ curl "http://localhost:9500/2015-03-31/functions/function/invocations" -d "{}"
    +
    + +
    +

    + +
    +

    Tip! 1

    +

    If you prefer, make the request from Python with the requests library!

    +
    +

    Container Registry

    +

    The Amazon Elastic Container Registry (ECR) is a fully managed service that allows you to store, manage, and deploy container images. With ECR, you can securely store and manage your Docker container images.

    +

    Let's upload our image to ECR. But first, we need to create a container repository:

    +
    +

    Atention!

    +

    Change the repository_name variable.

    +

    Provide a name in the pattern test1-mlops-<INSPER_USERNAME>

    +
    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Provide a name like test1-mlops-<INSPER_USERNAME>
    +repository_name = "test1-mlops-xxxxx"
    +
    +# Create a Boto3 client for ECR
    +ecr_client = boto3.client(
    +    "ecr",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +response = ecr_client.create_repository(
    +    repositoryName=repository_name,
    +    imageScanningConfiguration={"scanOnPush": True},
    +    imageTagMutability="MUTABLE",
    +)
    +
    +print(response)
    +
    +print(f"\nrepositoryArn: {response['repository']['repositoryArn']}")
    +print(f"repositoryUri: {response['repository']['repositoryUri']}")
    +
    +
    +

    Important!

    +

    Write down the repositoryUri

    +
    +

    Upload Image to ECR

    +

    Before uploading our Docker image to ECR, we need to configure the AWS Command Line Interface (AWS CLI).

    +
    +

    Install!

    +

    See how to install Here

    +
    +

    The AWS CLI can be used to interact with AWS via the command line, similar to what we are doing with boto3 in Python.

    +

    For now, we will use the AWS CLI to enable authentication to docker.

    +

    After installing, run and provide the authentication keys for our account.

    +

    +

    + +
    $ aws configure
    +
    + +
    +

    + +

    Let's authenticate and login to ECR using the Docker CLI:

    +
    +

    Atention!

    +

    Change the <AWS_ACCOUNT_ID> for the <AWS_ACCOUNT_ID> used during classes, for example 123456789012

    +
    +
    + +
    $ aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin AWS_ACCOUNT_ID.dkr.ecr.us-east-2.amazonaws.com
    +
    + +
    + +


    +Then, we will run the docker tag command to tag our local Docker image into your Amazon ECR repository as the latest version by doing:

    +
    +

    Atention!

    +

    Provide the <REPOSITORY_URI> from before.

    +

    Example of <REPOSITORY_URI> (notice the AWS_ACCOUNT_ID, AWS_REGION and REPOSITORY_NAME):

    +

    AWS_ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/REPOSITORY_NAME

    +
    +
    + +
    $ docker tag lambda-ex-image:test REPOSITORY_URI:latest
    +
    + +
    + +


    +And push image to ECR with:

    +
    +

    Atention!

    +

    Provide the <REPOSITORY_URI> from before.

    +

    Example of <REPOSITORY_URI> (notice the AWS_ACCOUNT_ID, AWS_REGION and REPOSITORY_NAME):

    +

    AWS_ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/REPOSITORY_NAME

    +
    +

    +

    + +
    $ docker push REPOSITORY_URI:latest
    +
    + +
    +

    + +

    Create Function

    +

    Now we can create the lambda function from the image already stored in the ECR.

    +

    To do this, run:

    +
    +

    Atention!

    +

    Change the function_name and image_uri.

    +

    The image_uri will follow the pattern <repositoryUri>:<imageTag>, for example: 123456789012.dkr.ecr.us-east-2.amazonaws.com/test1-mlops-joaoxr:latest

    +
    +

    Tip! 2

    +

    You can copy the image_uri from the last docker push command!

    +
    +
    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Provide function name: "ex_docker_<INSPER_USERNAME>"
    +function_name = ""
    +
    +# Provide Image URI from before
    +image_uri = ""
    +
    +lambda_role_arn = os.getenv("AWS_LAMBDA_ROLE_ARN")
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +response = lambda_client.create_function(
    +    FunctionName=function_name,
    +    PackageType="Image",
    +    Code={"ImageUri": image_uri},
    +    Role=lambda_role_arn,
    +    Timeout=30,  # Optional: function timeout in seconds
    +    MemorySize=128,  # Optional: function memory size in megabytes
    +)
    +
    +print("Lambda function created successfully:")
    +print(f"Function Name: {response['FunctionName']}")
    +print(f"Function ARN: {response['FunctionArn']}")
    +
    +
    +

    Question 4

    +
    +

    Use the codes from the previous class as a reference and test the function.

    +

    Call the lambda function directly, without creating an API in API Gateway.

    +
    + + +
    +
    +
    +

    Proceed to the APS!

    +

    References

    + + + +
    + + +
    +
    + +
    +
    + + + + + \ No newline at end of file diff --git a/classes/07-lambda/lambda_layer/index.html b/classes/07-lambda/lambda_layer/index.html new file mode 100644 index 0000000..c4890c3 --- /dev/null +++ b/classes/07-lambda/lambda_layer/index.html @@ -0,0 +1,863 @@ + + + + + + + + + Lambda layer - MLOps & Interviews + + + + + + + + + + + + + + + + +
    +
    + + +
    + + + + + + + +
    +
    + +
    + +
    +
      + + +
    • +
    + + +
    + +
    +

    Lambda Layer

    +

    Introduction

    +

    A AWS Lambda layer is a ZIP file that contains supplementary code, such as library dependencies.

    +

    The main advantages of using Lambda layers are:

    +
      +
    • +

      Reduce size of deployment packages: Rather than packaging function dependencies directly with your function code, isolate dependencies into reusable layers. This keeps deployment packages small and organized.

      +
    • +
    • +

      Separete core function logic from dependencies: Using layers allows function logic and dependencies to evolve separately. Layers facilitate independent management, where dependencies can be revised without touching function code. This allows deployment packages for your functions to focus solely on application logic without the bloat of bundled dependencies.

      +
    • +
    • +

      Share dependencies across multiple functions: By building dependencies into layers, those components can then be associated with multiple functions simultaneously (layers are reusable). Once a layer is established, any function configuration can reference and inherit its dependencies, rather than requiring redundant inclusion in each deployment package definition.

      +
    • +
    +

    Check the diagram for a comparison of the model without versus with the use of layers.

    +

    +
    +

    Tip! 1

    +

    Lambda layers provide a convenient and effective way to package code libraries for sharing with Lambda functions in your account.

    +
    +
    +
    +
    +
    +
    +

    Creating the ZIP with dependencies

    +

    Let's create a ZIP file with our project's dependencies and create a layer from it.

    +

    As you are probably in a Windows environment (and to standardize the class), we will use Ubuntu Docker and create dependencies from it.

    +

    To start a container in interactive mode, use:

    +
    + +
    $ docker run -it ubuntu
    +
    + +
    + +


    +
    +

    Atention!

    +

    The next commands will be executed inside the container!

    +
    +

    Then, install the version of Python used by your Lambda functions and the ZIP:

    +
    + +
    $ apt update
    +$ apt install python3.10 python3-pip zip
    +
    + +
    + +


    +

    Create a folder to store the dependencies and install then:

    +
    + +
    $ mkdir -p layer/python/lib/python3.10/site-packages
    +$ pip3 install textblob -t layer/python/lib/python3.10/site-packages
    +
    + +
    + +


    +

    Create the ZIP with dependencies:

    +
    + +
    $ cd layer
    +$ zip -r polarity_layer_package.zip *
    +
    + +
    + +


    +

    Check the results:

    +
    + +
    $ ls -la
    +total 5820
    +drwxr-xr-x 3 root root    4096 Sep 08 15:02 ./
    +drwxr-xr-x 1 root root    4096 Sep 08 15:00 ../
    +-rw-r--r-- 1 root root 5945036 Sep 08 15:02 polarity_layer_package.zip
    +drwxr-xr-x 3 root root    4096 Sep 08 15:00 python/
    +
    + +
    + +


    +
    +

    Atention!

    +

    The next commands will be executed outside the container!

    +
    +

    Now, let's extract the ZIP out of the container! To do this, we need to find out the container ID: and call the docker cp command.

    +
    + +
    $ docker ps -a
    +CONTAINER ID   IMAGE                       COMMAND
    +ba7a7aba2b95   ubuntu                      "/bin/bash"
    +
    + +
    + +


    +

    With the container ID, we then call the docker cp command: docker cp <Container-ID:path_of_zip_on_container> <path_where_you_want_to_copy_the_zip>

    +

    For example:

    +
    + +
    $ docker cp ba7a7aba2b95:/layer/polarity_layer_package.zip ./
    +
    + +
    + +


    +

    Create Layer

    +

    Now that we have the ZIP with the dependencies, let's create the layer with:

    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Provide a name following the pattern `layer_polarity_<YOUR_INSPER_USERNAME>`
    +layer_name = ""
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +# Read the contents of the zip file that you want to deploy
    +with open("polarity_layer_package.zip", "rb") as f:
    +    zip_to_deploy = f.read()
    +
    +
    +lambda_response = lambda_client.publish_layer_version(
    +    LayerName=layer_name,
    +    Description="Layer with textblob for polarity",
    +    Content={"ZipFile": zip_to_deploy},
    +)
    +
    +print("Layer ARN:\n", lambda_response["LayerArn"])
    +print("Layer LayerVersionArn:\n", lambda_response["LayerVersionArn"])
    +
    +
    +

    Important!

    +

    Copy the LayerVersionArn as it will be used.

    +
    +

    Assign Layer

    +

    Let's link the Lambda function we created to the layer. To do this:

    +
    +

    Important!

    +

    Provide the layer_version_arn and function_name copied previously.

    +
    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Provide ARN and function name
    +layer_version_arn = (
    +    "xxxxxxxxxxx"
    +)
    +function_name = "xxxxxxx"
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +# Get the current configuration of the Lambda function
    +response = lambda_client.get_function(FunctionName=function_name)
    +
    +# Retrieve the existing layers
    +layers = (
    +    response["Configuration"]["Layers"] if "Layers" in response["Configuration"] else []
    +)
    +
    +print("Existing layers:")
    +print(layers)
    +
    +# Append the layer ARN to the existing layers
    +layers.append(layer_version_arn)
    +
    +# Update the function configuration with the new layers
    +lambda_response = lambda_client.update_function_configuration(
    +    FunctionName=function_name, Layers=layers
    +)
    +
    +# Print response
    +print("Lambda response:\n", lambda_response)
    +
    +

    Check if worked!

    +
    +

    Question! 1

    +
    +

    Call the Lambda function, as we did here and check if it works. What was the result obtained?

    +
    + + + +
    +
    +
    +

    Answer!

    +

    Response: +

    {
    +    "error": "No body provided yet"
    +}
    +

    +

    So the textblob seems to be being imported and the error is not sending the JSON with the data in the request.

    +
    +
    +

    Create API Gateway

    +

    Let's create an API with:

    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +import random
    +import string
    +
    +
    +load_dotenv()
    +
    +# Provide function name and ARN copied previously
    +lambda_function_name = ""
    +lambda_arn = ""
    +
    +# Provide a name following the pattern `demo_polarity_<YOUR_INSPER_USERNAME>`
    +api_gateway_name = "demo-polarity-xxxxxxxx"
    +
    +id_num = "".join(random.choices(string.digits, k=7))
    +
    +api_gateway = boto3.client(
    +    "apigatewayv2",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +lambda_function = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +lambda_function_get = lambda_function.get_function(FunctionName=lambda_function_name)
    +
    +print(lambda_function_get)
    +
    +api_gateway_create = api_gateway.create_api(
    +    Name=api_gateway_name,
    +    ProtocolType="HTTP",
    +    Version="1.0",
    +    RouteKey="POST /polarity", # Create a /polarity POST route
    +    Target=lambda_function_get["Configuration"]["FunctionArn"],
    +)
    +
    +api_gateway_permissions = lambda_function.add_permission(
    +    FunctionName=lambda_function_name,
    +    StatementId="api-gateway-permission-statement-" + id_num,
    +    Action="lambda:InvokeFunction",
    +    Principal="apigateway.amazonaws.com",
    +)
    +
    +print("API Endpoint:", api_gateway_create["ApiEndpoint"])
    +
    +
    +

    Important!

    +

    Copy the endpoint and edit in the following code.

    +
    +

    And test by sending any text to obtain its polarity:

    +
    import requests
    +
    +# Change the endpoint
    +url_endpoint = "https://xxxxxxxxxx.execute-api.us-east-2.amazonaws.com"
    +
    +url = f"{url_endpoint}/polarity"
    +
    +# Change the phrase
    +body = {"phrase": "This was the worst movie I watched this year, horrible!"}
    +
    +resp = requests.post(url, json=body)
    +
    +print(f"status code: {resp.status_code}")
    +print(f"text: {resp.text}")
    +
    +
    +

    Question! 2

    +
    +

    Check if the result was as expected:

    +
    {
    +    "phrase": "This was the worst movie I watched this year, horrible!",
    +    "polarity": "-1.0",
    +    "sentiment": "Negative sentiment"
    +}
    +
    +
    + + +
    +
    +
    +

    Cleaning

    +

    If you have finished the class, delete the resources created in API Gateway and Lambda.

    +
    +

    Tip! 2

    +

    After deleting, use the listing commands (from the previous class) to check that there is in fact no other resource created by you!

    +
    +

    Deleting API Gateway:

    +
    +

    Cuidado

    +

    Provide the api_gateway_name copied previously.

    +
    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +import random
    +import string
    +
    +
    +load_dotenv()
    +
    +# Provide API Gateway name used previously
    +api_gateway_name = "demo-polarity-xxxxxxx"
    +
    +api_gateway = boto3.client(
    +    "apigatewayv2",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +
    +response = api_gateway.get_apis(MaxResults="2000")
    +api_gateway_id = None
    +for item in response["Items"]:
    +    if item["Name"] == api_gateway_name:
    +        api_gateway_id = item["ApiId"]
    +        break
    +
    +# Delete the API Gateway
    +if api_gateway_id:
    +    api_gateway.delete_api(ApiId=api_gateway_id)
    +    print(f"API Gateway '{api_gateway_name}' deleted successfully.")
    +else:
    +    print(f"API Gateway '{api_gateway_name}' not found.")
    +
    +

    Deleting Lambda function:

    +
    +

    Cuidado

    +

    Provide the function_name copied previously.

    +
    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Provide function name
    +function_name = "get_polarity_xxxxxxxx"
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +# Delete the Lambda function
    +lambda_client.delete_function(FunctionName=function_name)
    +
    +print(f"Lambda function {function_name} deleted successfully")
    +
    +

    Deleting the layer:

    +
    +

    Cuidado

    +

    Provide the layer_name copied previously.

    +
    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Provide layer name
    +layer_name = "layer_polarity_xxxxx"
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +# Fetch the layer version ARN based on the layer name
    +response = lambda_client.list_layer_versions(
    +    CompatibleRuntime="python3.10",  # Provide the compatible runtime of the layer
    +    LayerName=layer_name,
    +)
    +
    +if "LayerVersions" in response:
    +    layer_versions = response["LayerVersions"]
    +
    +    # Delete each layer version
    +    for version in layer_versions:
    +        lambda_client.delete_layer_version(
    +            LayerName=layer_name, VersionNumber=version["Version"]
    +        )
    +
    +    print(f"Deleted all versions of layer '{layer_name}'.")
    +else:
    +    print(f"No layer with the name '{layer_name}' found.")
    +
    +

    References

    + + + +
    + + +
    +
    + +
    +
    + + + + + \ No newline at end of file diff --git a/classes/07-lambda/lambda_practicing/index.html b/classes/07-lambda/lambda_practicing/index.html new file mode 100644 index 0000000..7e5480e --- /dev/null +++ b/classes/07-lambda/lambda_practicing/index.html @@ -0,0 +1,724 @@ + + + + + + + + + Lambda practicing - MLOps & Interviews + + + + + + + + + + + + + + + + +
    +
    + + +
    + + + + + + + +
    +
    + +
    + +
    +
      + + + +
    • Classes
    • + + + +
    • 07 - Lambda Functions
    • + + + +
    • Part 1
    • + + +
    • +
    + + +
    + +
    +

    AWS Lambda - Practicing

    +

    Let's create our own function in AWS Lambda.

    +

    Create Folder

    +
    +

    Question 1

    +
    +

    Create a new folder and store all the source code in it!

    +
    + + +
    +
    +
    +

    Create .env

    +
    +

    Question 2

    +
    +

    Create an .env file containing the variables: +

    AWS_ACCESS_KEY_ID="XXXXXXXXXXXXXX"
    +AWS_SECRET_ACCESS_KEY="aaaaaaaaaaaaaaaaaaaaaaaaaaa"
    +AWS_REGION="xx-xxxx-2"
    +AWS_LAMBDA_ROLE_ARN="arn:xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    +

    +
    +

    Tip! 1

    +

    Ask the professor for the new credentials!

    +
    +
    + + +
    +
    +
    +

    Create function

    +
    +

    Question 3

    +
    +

    Create a file called my_lambda.py containing the function that will run on AWS.

    +

    For now, we'll make a simple function that responds with a fixed JSON!

    +

    Source code: +

    def say_hello(event, context):
    +    return {
    +        "created_by": "your name",
    +        "message": "Hello World!"
    +    }
    +

    +
    +

    Tip! 2

    +

    The function say_hello will be our handler function.

    +
    +
    + + +
    +
    +
    +

    Create ZIP

    +
    +

    Question 4

    +
    +

    Create a file called my_lambda.zip that is the compression my_lambda.py.

    +
    + + +
    +
    +
    +

    Show functions

    +

    Let's use this code to list the functions available in our account:

    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +
    +# Call the list_functions API to retrieve all Lambda functions
    +response = lambda_client.list_functions(MaxItems=1000)
    +
    +# Extract the list of Lambda functions from the response
    +functions = response["Functions"]
    +
    +print(f"You have {len(functions)} Lambda functions")
    +
    +
    +# Print the name of each Lambda function
    +if len(functions) > 0:
    +    print("Here are their names:")
    +
    +for function in functions:
    +    function_name = function["FunctionName"]
    +    print(function_name)
    +
    +
    +

    Question 5

    +
    +

    Run the Python code and check out the functions currently available in our account!

    +
    + + +
    +
    +
    +

    Create Lambda Function

    +

    Let's create a lambda function with:

    +
    +

    Atention!

    +

    Change the function_name variable.

    +

    Provide a name in the pattern sayHello_<YOUR_INSPER_USERNAME>

    +
    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Provide function name: sayHello_<YOUR_INSPER_USERNAME>
    +function_name = ""
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +# Lambda basic execution role
    +lambda_role_arn = os.getenv("AWS_LAMBDA_ROLE_ARN")
    +
    +# Read the contents of the zip file that you want to deploy
    +# Inside the "my_lambda.zip" there is a "my_lambda.py" file with the
    +# "say_hello" function code
    +with open("my_lambda.zip", "rb") as f:
    +    zip_to_deploy = f.read()
    +
    +lambda_response = lambda_client.create_function(
    +    FunctionName=function_name,
    +    Runtime="python3.9",
    +    Role=lambda_role_arn,
    +    Handler="my_lambda.say_hello", # Python file DOT handler function
    +    Code={"ZipFile": zip_to_deploy},
    +)
    +
    +print("Function ARN:", lambda_response["FunctionArn"])
    +
    +
    +

    Question 6

    +
    +

    Run the Python code to create the function. Then write down the returned ARN

    +
    +
    + + +
    +
    +
    +
    +

    Question 7

    +
    +

    Rerun the code to display the existing functions in the account.

    +

    Check that your function was created correctly.

    +
    + + +
    +
    +
    +

    Check if worked

    +

    Let's check if the function worked:

    +
    +

    Atention!

    +

    Change the function_name variable.

    +
    +
    import boto3
    +import os
    +import io
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +# Lambda function name
    +# Provide function name: sayHello_<YOUR_INSPER_USERNAME>
    +function_name = ""
    +
    +try:
    +    # Invoke the function
    +    response = lambda_client.invoke(
    +        FunctionName=function_name,
    +        InvocationType="RequestResponse",
    +    )
    +
    +    payload = response["Payload"]
    +
    +    txt = io.BytesIO(payload.read()).read().decode("utf-8")
    +    print(f"Response:\n{txt}")
    +
    +except Exception as e:
    +    print(e)
    +
    +
    +

    Question 8

    +
    +

    Make sure the function returns the expected result

    +
    + + +
    +
    +
    +

    This code provides a way to check if the lambda function works. However, when integrating it with other applications, its execution would probably depend on an event such as the creation of a file on S3 or an API call.

    +

    Let's check out how to use API Gateway to create an API for our Lambda function.

    + + +
    + + +
    + +
    + + + + + \ No newline at end of file diff --git a/classes/07-lambda/lambda_quotas/index.html b/classes/07-lambda/lambda_quotas/index.html new file mode 100644 index 0000000..017cdb1 --- /dev/null +++ b/classes/07-lambda/lambda_quotas/index.html @@ -0,0 +1,485 @@ + + + + + + + + + Lambda quotas - MLOps & Interviews + + + + + + + + + + + + + + + + +
    +
    + + +
    + + + + + + + +
    +
    + +
    + +
    +
      + + +
    • +
    + + +
    + +
    +

    Lambda Quotas

    +

    In the last classes we saw how to create functions that run serverless, that is, we don't need to worry about the infrastructure needed to execute the functions.

    +

    Ideally, we would like to run any function, with any time and memory requirement on AWS Lambda. But there are limits.

    +
    +

    Question 1

    +
    +

    Do you know of any quotas that limit the execution of AWS lambda functions?

    +
    +
    + + +
    +
    +
    +

    Resposta

    +

    You can see the quotas Here

    +
    +
    +

    Considering ML applications, it is common for them to use packages such as sklearn, XGBoost, lightgbm, pandas, etc. Since dependencies need to be packaged in ZIP, it is common to use hundreds of MiB or a few GiB.

    +
    +

    Question 2

    +
    +

    Note the "Deployment package (.zip file archive) size" topic. What is the file size limit for a ZIP we want to deploy?

    +
    + + + +
    +
    +
    +

    Resposta

    +

    250MB

    +
    +
    +
    +

    Question 3

    +
    +

    Is there any alternative that we have already seen in class to solve the problem?

    +
    + + + +
    +
    +
    +

    Resposta

    +

    We could split the code into several layer, but notice that there is also limits for number of function layers.

    +

    Take a look at Container image code package size quota. Well, it turns out that we can also deploy functions to AWS lambda using containers! As the limit in this case is 10GB, we are able to deploy packages with dependencies larger than the ZIP limit.

    +
    +
    +

    Advance to the next topic to continue exploring this topic.

    + + +
    + + +
    +
    + +
    +
    + + + + + \ No newline at end of file diff --git a/classes/07-lambda/sa_lambda_function/index.html b/classes/07-lambda/sa_lambda_function/index.html new file mode 100644 index 0000000..3615a14 --- /dev/null +++ b/classes/07-lambda/sa_lambda_function/index.html @@ -0,0 +1,618 @@ + + + + + + + + + Sa lambda function - MLOps & Interviews + + + + + + + + + + + + + + + + +
    +
    + + +
    + + + + + + + +
    +
    + +
    + +
    +
      + + +
    • +
    + + +
    + +
    +

    Lambda Function for Sentment Analysis (SA)

    +

    Let's create a lambda function that uses the textblob library to return the polarity of a text.

    +

    Create source code

    +
    +

    Question 1

    +
    +

    Create a file polarity.py containing a Lambda function get_polarity that receives a JSON in the request body and returns a JSON containing:

    +
      +
    • The received sentence itself
    • +
    • The polarity returned by TextBlob
    • +
    • The feeling of the sentence.
        +
      • If the polarity is below -0.8, consider it as negative sentiment.
      • +
      • If the polarity is between -0.8 and 0.2, consider it neutral sentiment.
      • +
      • If the polarity is above 0.2, consider it as positive sentiment.
      • +
      +
    • +
    +

    Once finished, check your code with the official answer provided below.

    +
    + + +
    +
    +
    +
    +Official answer for polarity.py +
    from textblob import TextBlob
    +import json
    +
    +
    +def get_polarity(event, context):
    +    # Provide a body for the request!
    +    if "body" not in event:
    +        return {"error": "No body provided"}
    +
    +    # Get the raw posted JSON
    +    raw_json = event["body"]
    +
    +    # Load it into a Python dict
    +    body = json.loads(raw_json)
    +
    +    if "phrase" not in body:
    +        return {"error": "No phrase provided"}
    +
    +    phrase = body["phrase"]
    +
    +    # Create a TextBlob object of the phrase
    +    blob = TextBlob(phrase)
    +
    +    # Get the polarity score
    +    polarity = blob.polarity
    +
    +    # Create a response object with the phrase and polarity
    +    res = {"phrase": phrase, "polarity": str(polarity)}
    +
    +    # Determine the sentiment
    +    if polarity > 0.2:
    +        res["sentiment"] = "Positive sentiment"
    +    elif polarity >= -0.8:
    +        res["sentiment"] = "Neutral sentiment"
    +    else:
    +        res["sentiment"] = "Negative sentiment"
    +
    +    return res
    +
    +
    +
    +

    Question 2

    +
    +

    Do as in the last class, create a ZIP of your Python file to deploy to AWS Lambda.

    +
    + + +
    +
    +
    +

    Create Lambda function

    +
    +

    Atention!

    +

    Change the function_name variable.

    +

    Provide a name in the pattern get_polarity_<YOUR_INSPER_USERNAME>

    +
    +
    import boto3
    +import os
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Lambda function name
    +# Provide a name in the pattern `get_polarity_<YOUR_INSPER_USERNAME>`
    +function_name = ""
    +
    +# Lambda basic execution role
    +lambda_role_arn = os.getenv("AWS_LAMBDA_ROLE_ARN")
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +# Read the contents of the zip file that you want to deploy
    +with open("polarity.zip", "rb") as f:
    +    zip_to_deploy = f.read()
    +
    +lambda_response = lambda_client.create_function(
    +    FunctionName=function_name,
    +    Runtime="python3.10", # Change the runtime if you want!
    +    Role=lambda_role_arn,
    +    Handler="polarity.get_polarity",  # function get_polarity inside polarity.py
    +    Code={"ZipFile": zip_to_deploy},
    +)
    +
    +print("Function ARN:", lambda_response["FunctionArn"])
    +
    +

    Check if worked

    +

    Before creating the API, let's check if the Lambda function works correctly!

    +

    To do this, let's make a direct call to the function with:

    +
    +

    Atention!

    +

    Change the function_name variable with the same name as before.

    +
    +
    import boto3
    +import os
    +import io
    +from dotenv import load_dotenv
    +
    +load_dotenv()
    +
    +# Lambda function name
    +function_name = ""
    +
    +# Create a Boto3 client for AWS Lambda
    +lambda_client = boto3.client(
    +    "lambda",
    +    aws_access_key_id=os.getenv("AWS_ACCESS_KEY_ID"),
    +    aws_secret_access_key=os.getenv("AWS_SECRET_ACCESS_KEY"),
    +    region_name=os.getenv("AWS_REGION"),
    +)
    +
    +
    +try:
    +    # Invoke the function
    +    response = lambda_client.invoke(
    +        FunctionName=function_name,
    +        InvocationType="RequestResponse",
    +    )
    +
    +    payload = response["Payload"]
    +
    +    txt = io.BytesIO(payload.read()).read().decode("utf-8")
    +    print(f"Response:\n{txt}")
    +except Exception as e:
    +    print(e)
    +
    +
    +

    Question 3

    +
    +

    The call must not have worked. What error is returned?

    +
    + + + +
    +
    +
    +

    Answer!

    +

    Among others: +

    {
    +    "errorMessage": "Unable to import module 'polarity': No module named 'textblob'"
    +}
    +

    +
    +
    +

    This occurred because our function depends on a library textblob that is not available in the environment where it is being executed.

    +

    Runtime dependencies

    +

    In AWS Lambda, when our Python code depends on another package or module, two options are:

    +
      +
    1. Include the dependencies in the ZIP
    2. +
    3. Use Lambda layer
    4. +
    +

    Let's work with the second option! Proceed to the next topic.

    + + +
    + + +
    +
    + +
    +
    + + + + + \ No newline at end of file diff --git a/classes/07-lambda/sentiment_analysis/index.html b/classes/07-lambda/sentiment_analysis/index.html new file mode 100644 index 0000000..d035fef --- /dev/null +++ b/classes/07-lambda/sentiment_analysis/index.html @@ -0,0 +1,550 @@ + + + + + + + + + Sentiment analysis - MLOps & Interviews + + + + + + + + + + + + + + + + +
    +
    + + +
    + + + + + + + +
    +
    + +
    + +
    +
      + + +
    • +
    + + +
    + +
    +

    Sentiment Analysis

    +

    Remembering

    +

    In the last class we saw how to build Lambda functions in AWS.

    +

    We chose the API Gateway service to expose our Lambda functions. Thus, the function is triggered whenever the user makes a request to an endpoint.

    +

    +
    +

    Info!

    +

    AWS Lambda allows machine learning models to be deployed and hosted serverlessly.

    +
    +

    Looking back at the examples we did, they involved a function that returned a fixed JSON and a lambda function that counted the number of words in a sentence. No ML for now!

    +

    Let's use this class to build more complex examples using AWS Lambda!

    +
    +
    +
    +
    +
    +

    Sentiment Analysis

    +

    Sentiment analysis (SA) is the process of determining whether a given phrase is positive, negative or neutral.

    +

    It can be applied to analyze feedback, reviews, survey responses, social media posts and more to gauge public opinion on certain topics.

    +
    +

    Question 1

    +
    +

    How can we represent the sentiment of a text as a variable in a database?

    +
    +
    + + +
    +
    +
    +

    Answer!

    +

    We can represent it as a continuous score, for example, in the range [-1,1]``, where-1.0represents a very negative text and1.0` represents a very positive text.

    +

    Another option is to use categorical variables, such as:

    +
      +
    • Very negative
    • +
    • Negative
    • +
    • Neutral
    • +
    • Positive
    • +
    • Very positive
    • +
    +
    +
    +
    +

    Question 2

    +
    +

    Is it possible to predict the sentiment of a sentence without using ML algorithms? Can you think of any way?

    +
    +
    + + +
    +
    +
    +

    Answer!

    +

    One of the simplest ways is to create fixed rules. For example, count how many times a word like disappointed occurs in text. A high occurrence may indicate negativity!

    +

    Another way is to create two lists of words: one of negative words and another of positive words. We count how many words we have from each list in the sentence we are analyzing, and if we have more positive words, we say the text has positive sentiment, otherwise we say it has negative sentiment.

    +

    Furthermore, we can ask an expert to provide weights for words, for example, hate could have a weight of -0.9 while cool could have a weight of 0.4. Thus, we can compute whether in total we have a predominant positive or negative weight.

    +

    See more Here

    +
    +
    +
    +

    Question 3

    +
    +

    Have you trained or have any idea how to train an ML model for sentiment analysis? Explain how.

    +
    +
    + + +
    +
    +
    +

    Answer!

    +

    Considering a manually classified database, we can pre-process the text, removing punctuations and stop-words. Then we can tokenize the text and train a Naive Bayes classifier. You probably did this in Ciência dos dados (you created the Python code to calculate probabilities yourself) and Megadados (using Spark) courses.

    +

    See more Here and Here.

    +
    +
    +

    Instead of training our own sentiment analysis model, we will use a ready-made library that already provides this functionality.

    +

    Textblob library

    +

    We chose to use the textblob library for sentiment analysis. It provides a series of features such as:

    +
      +
    • Calculation of n-grams.
    • +
    • Tokenization
    • +
    • Spelling Correction
    • +
    • Sentiment Analysis
    • +
    • etc.
    • +
    +

    See the documentation here and here.

    +

    Let's see an example of how to use the library. But first, do the installation:

    +
    + +
    $ pip install textblob
    +
    + +
    + +


    +Let's use textblob to obtain the polarity of three different texts:

    +
    from textblob import TextBlob
    +
    +text1 = "What a damn company. You guys are the worst, you can't meet the deadline."
    +text2 = "Hello everybody"
    +text3 = "I am so happy to be here"
    +
    +blob1 = TextBlob(text1)
    +blob2 = TextBlob(text2)
    +blob3 = TextBlob(text3)
    +
    +print(f"Polarity of text1: {blob1.polarity}")
    +print(f"Polarity of text2: {blob2.polarity}")
    +print(f"Polarity of text3: {blob3.polarity}")
    +
    +
    +

    Tip! 1

    +

    Here it is the repository of textblob: https://github.com/sloria/textblob

    +
    +

    Run this code locally and test it with other sentences. Then proceed to the next topic.

    + + +
    + + +
    +
    + +
    +
    + + + + + \ No newline at end of file diff --git a/contributions/index.html b/contributions/index.html index 95f201f..c535e38 100644 --- a/contributions/index.html +++ b/contributions/index.html @@ -360,6 +360,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/deadlines/index.html b/deadlines/index.html index 486bb73..3fb96db 100644 --- a/deadlines/index.html +++ b/deadlines/index.html @@ -360,6 +360,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/index.html b/index.html index 10e9a23..ecb2b47 100644 --- a/index.html +++ b/index.html @@ -364,6 +364,48 @@ + +
  • + 07 - Lambda Functions + +
  • + + diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 002548468205daae2215f03400398eeed322e457..06d580f4a41b03d77b82dca7dccfd925825e717b 100644 GIT binary patch delta 13 Ucmb=gXP58h;CL-{ej