Lets build a full stack application to call Stable Diffusion AI model. We will first build the backend then frontend. Backend includes: 1) SageMaker 2) Lambda 3) Api Gateway. And Frontend includes react web app deployed in Amplify.
# Clone the repository to your local machine
git clone https://github.com/rupeshtiwari/amplify-react-stabledapp.git
# Go to the project folder
cd amplify-react-stabledapp
# Install npm dependencies with exact versions from package-lock.json file
npm ci
# Run the react app
npm start
Table of Contents
- Stable Diffusion Generative AI Fullstack Application
- Demo
- Architecture Diagram
- How to run this project locally?
- Build Backend
- Build Frontend
- References
- Create SageMaker Domain may take more than 30 mins.
- Create profile
Now we have a SageMaker model endpoint. Let’s look at how we call it from Lambda. We use the SageMaker runtime API action and the Boto3 sagemaker-runtime.invoke_endpoint().
Select Runtime Python 3.7
and use x86_64 architecture.
Add below permissions to AWSLambdaBasicExecutionRole
"Version": "2012-10-17",
"Statement": [
// add this one for S3 bucket and sagemaker invocation
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"sagemaker:InvokeEndpoint",
"s3:*"
],
"Resource": "*"
},
{
"Sid": "VisualEditor2",
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:us-east-1:605024711850:*"
},
{
"Sid": "VisualEditor3",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents",
"s3:*"
],
"Resource": "arn:aws:logs:us-east-1:605024711850:log-group:/aws/lambda/invoke-text-to-image-stable-diffusion-model:*"
}
]
}
create bucket called as stabled
Environment variables (2)
The environment variables below are encrypted at rest with the default Lambda service key.
Key
Value
AWS_SM_EP jumpstart-example-infer-model-txt2img-s-2023-02-16-01-51-11-187
OUT_S3_BUCKET_NAME testbucket-rupesh
Go to configuration->General Configuration->Timeout Edit and change to 10min
- Add
AWSLambda-Python37-SciPy1x
layer fornumpy
- Add
Matplotlib
layer
import boto3
import io
import json
import numpy as np
import matplotlib.pyplot as plt
import uuid
import os
endpoint_name = os.environ['AWS_SM_EP']
s3 = boto3.resource('s3', region_name='us-east-1')
bucket_name = os.environ['OUT_S3_BUCKET_NAME']
s3_client = boto3.client('s3', region_name='us-east-1')
def query_endpoint(text):
runtime = boto3.client('runtime.sagemaker')
encoded_text = json.dumps(text).encode("utf-8")
response = runtime.invoke_endpoint(
EndpointName=endpoint_name, ContentType='application/x-text', Body=encoded_text, Accept='application/json')
return response
def parse_response(query_response):
response_dict = json.loads(query_response['Body'].read())
return response_dict['generated_image'], response_dict['prompt']
def upload_image(img, prmpt):
print('uploading image')
plt.figure(figsize=(12, 12))
plt.imshow(np.array(img))
plt.axis('off')
plt.title(prmpt)
img_data = io.BytesIO()
plt.savefig(img_data, format='png')
img_data.seek(0)
image_name = prmpt+str(uuid.uuid4())+'.png'
s3.Object(bucket_name, image_name).put(
Body=img_data, ContentType='image/png')
return s3_client.generate_presigned_url(ClientMethod='get_object', Params={'Bucket': bucket_name, 'Key': image_name}, ExpiresIn=1000)
def lambda_handler(event, context):
print("Received event: "+json.dumps(event, indent=2))
data = json.loads(json.dumps(event))
text = data['data']
print(text)
response = query_endpoint(text)
img, prmpt = parse_response(response)
# Display hallucinated image
url = upload_image(img, prmpt)
return {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
},
'body': url
}
You can create an API by following these steps:
- On the API Gateway console, choose the REST API
- Choose Build.
- Select New API.
- For API name¸ enter a name (for example, BreastCancerPredition).
- Leave Endpoint Type as Regional.
- Choose Create API.
- On the Actions menu, choose Create resource.
- Enter a name for the resource (for example, predictbreastcancer).
- After the resource is created, on the Actions menu, choose Create Method to create a POST method.
- For Integration type, select Lambda Function.
- For Lambda function, enter the function you created.
When the setup is complete, you can deploy the API to a stage
- On the Actions menu, choose Deploy API.
- Create a new stage called test.
- Choose Deploy.
This step gives you the invoke URL.
For more information on creating an API with API Gateway, see Creating a REST API in Amazon API Gateway. In addition, you can make the API more secure using various methods.
Now that you have an API and a Lambda function in place, let’s look at the test data.
- Use the POST request
https://mko6b9drb2.execute-api.us-east-1.amazonaws.com/test/stabled
- Use body
{"data":"vanilla cake"}
- Send it will take around 20-25 sec to get you pre-signed url for image.
The easiest way to create a React application is by using the command create-react-app. Install this package using the following command in your command prompt or terminal:
👉 Make sure you have npm installed.
npx create-react-app stabledapp
cd stabledapp
npm start
-
Create a new GitHub repo for your app with this name
amplify-react-stabledapp
Description:Stable Diffusion from Stability AI and AWS Sagemaker. Full stack application with AWS API gateway and Amplify React App
-
Open a new terminal and navigate back to your app's root folder, for example,
stabledapp
-
Using create-react-app will automatically initialize the git repo and make an initial commit.
git init git add . git commit -m "initial commit" git remote add origin [email protected]:username/reponame.git git branch -M main git push -u origin main
In this step, you will connect the GitHub repository you just created to the AWS Amplify service. This will enable you to build, deploy, and host your app on AWS.
-
In the AWS Amplify service console, select Get Started under Amplify Hosting.
-
Select GitHub as the repository service and select Continue.
-
Authenticate with GitHub and return to the Amplify console. Choose the repository and main branch you created earlier, then select Next.
-
Accept the default build settings and select Next.
-
Review the final details and choose Save and deploy.
-
AWS Amplify will now build your source code and deploy your app at
https://...amplifyapp.com.
-
Once the build completes, select the thumbnail to see your web app up and running live. https://main.d32ou2x1stz40z.amplifyapp.com/
In this step, you will make some changes to the code using your text editor and push the changes to the main branch of your app.
- Edit src/App.js with the code below and save.
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1>Hello from V2</h1>
</header>
</div>
);
}
export default App;
- Push the changes to GitHub in the command prompt (Windows) or terminal (macOS) to automatically kick off a new build:
git add .
git commit -m “changes for v2”
git push origin main
- Once the build is complete, select the thumbnail in the AWS Amplify console to view your updated app.
- https://aws.amazon.com/blogs/machine-learning/call-an-amazon-sagemaker-model-endpoint-using-amazon-api-gateway-and-aws-lambda/
- https://aws.amazon.com/getting-started/hands-on/build-react-app-amplify-graphql/module-one/?e=gs2020&p=build-a-react-app-intro
- https://www.youtube.com/watch?v=IwHt_QpIa8A ( convert in to mobile app using capacitor)