Skip to content

Commit 494afbb

Browse files
authored
Merge pull request #2700 from nareshrajaram2017/nareshrajaram2017-feature-apigw-lambda-bedrock-nova-terraform
New serverless pattern - apigw-lambda-bedrock-nova-terraform
2 parents 48fc942 + 8e7718b commit 494afbb

12 files changed

+609
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# Serverless Generative AI with Amazon Bedrock Nova Micro
2+
3+
## Overview
4+
5+
This pattern demonstrates how to create a serverless API leveraging Amazon Bedrock Nova Micro through AWS Lambda. The solution uses an Amazon API Gateway REST endpoint to process requests and return AI-generated responses using Nova Micro's text-to-text capabilities.
6+
7+
Learn more about this pattern at [Serverless Land Patterns](https://serverlessland.com/patterns/apigw-lambda-bedrock-nova-terraform).
8+
9+
Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
10+
11+
## Requirements
12+
13+
* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
14+
* [Enable Access To Nova Models](https://docs.aws.amazon.com/nova/latest/userguide/getting-started-console.html) and follow item 2 under the Prerequisites to request access to Amazon Nova Micro model
15+
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
16+
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
17+
* [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started) installed
18+
19+
## Deployment Instructions
20+
21+
1. Clone the project to your local working directory
22+
23+
```sh
24+
git clone https://github.com/aws-samples/serverless-patterns/
25+
```
26+
27+
2. Change the working directory to this pattern's directory
28+
29+
```sh
30+
cd serverless-patterns/apigw-lambda-bedrock-nova-terraform
31+
```
32+
33+
3. From the command line, run each of the command mentioned in the create_lambda_layer.sh file, this file contains the commands to create the Lambda Layer as well zip the bedrock_integration.py which invokes the Amazon Nova model.
34+
35+
4. From the command line, initialize terraform to to downloads and installs the providers defined in the configuration:
36+
```
37+
terraform init
38+
```
39+
40+
5. From the command line, apply the configuration in the main.tf file:
41+
```
42+
terraform apply
43+
```
44+
45+
6. During the prompts:
46+
- Enter yes
47+
48+
## How it works
49+
50+
The pattern creates an API Gateway endpoint that accepts POST requests containing prompts. These requests are forwarded to a Lambda function which processes the input and interacts with Amazon Bedrock's Nova Micro model.
51+
52+
Key components:
53+
54+
* API Gateway REST API endpoint
55+
* Lambda function with Nova Micro integration
56+
* IAM roles and policies for Lambda and Bedrock access
57+
* Lambda layer for boto3 dependencies
58+
* Nova Micro Request Format:
59+
```
60+
61+
{
62+
"system": [
63+
{
64+
"text": "You are a helpful AI assistant that provides accurate and concise information."
65+
}
66+
],
67+
"messages": [
68+
{
69+
"role": "user",
70+
"content": [
71+
{
72+
"text": "<your-prompt>"
73+
}
74+
]
75+
}
76+
],
77+
"inferenceConfig": {
78+
"maxTokens": 1024,
79+
"temperature": 0.7,
80+
"topP": 0.9,
81+
"topK": 50,
82+
"stopSequences": []
83+
}
84+
}
85+
86+
```
87+
88+
## Testing
89+
90+
Using Curl:
91+
92+
```
93+
curl -X POST \
94+
-H "Content-Type: application/json" \
95+
-d '{"prompt": "What are the key benefits of using AWS services?"}' \
96+
https://YOUR-API-ENDPOINT/dev/generate_content
97+
98+
```
99+
100+
## Viewing Test Results
101+
```
102+
{
103+
"generated-text": "<Model generated response>"
104+
}
105+
```
106+
107+
## Cleanup
108+
109+
1. Change directory to the pattern directory:
110+
```sh
111+
cd serverless-patterns/apigw-lambda-bedrock-nova-terraform
112+
```
113+
114+
2. Delete all created resources
115+
```sh
116+
terraform destroy
117+
```
118+
119+
3. During the prompts:
120+
* Enter yes
121+
122+
4. Confirm all created resources has been deleted
123+
```sh
124+
terraform show
125+
```
126+
127+
## Reference
128+
129+
- [Amazon Bedrock Nova Models](https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-nova.html)
130+
- [AWS Lambda with API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-with-lambda-integration.html)
131+
- [Amazon API Gateway REST APIs](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html)
132+
133+
----
134+
Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
135+
136+
SPDX-License-Identifier: MIT-0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
resource "aws_api_gateway_rest_api" "generate_content_api" {
2+
name = "generate-content-api"
3+
}
4+
5+
resource "aws_api_gateway_resource" "generate_content" {
6+
rest_api_id = aws_api_gateway_rest_api.generate_content_api.id
7+
parent_id = aws_api_gateway_rest_api.generate_content_api.root_resource_id
8+
path_part = "generate_content"
9+
}
10+
11+
resource "aws_api_gateway_method" "generate_content_post" {
12+
rest_api_id = aws_api_gateway_rest_api.generate_content_api.id
13+
resource_id = aws_api_gateway_resource.generate_content.id
14+
http_method = "POST"
15+
authorization = "NONE"
16+
}
17+
18+
resource "aws_api_gateway_integration" "lambda_integration" {
19+
rest_api_id = aws_api_gateway_rest_api.generate_content_api.id
20+
resource_id = aws_api_gateway_resource.generate_content.id
21+
http_method = aws_api_gateway_method.generate_content_post.http_method
22+
23+
integration_http_method = "POST"
24+
type = "AWS_PROXY"
25+
uri = aws_lambda_function.content_generation.invoke_arn
26+
}
27+
28+
resource "aws_api_gateway_deployment" "api_deployment" {
29+
rest_api_id = aws_api_gateway_rest_api.generate_content_api.id
30+
31+
depends_on = [
32+
aws_api_gateway_integration.lambda_integration
33+
]
34+
35+
lifecycle {
36+
create_before_destroy = true
37+
}
38+
}
39+
40+
resource "aws_api_gateway_stage" "dev" {
41+
deployment_id = aws_api_gateway_deployment.api_deployment.id
42+
rest_api_id = aws_api_gateway_rest_api.generate_content_api.id
43+
stage_name = "dev"
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
{
2+
"title": "Serverless Generative AI with Amazon Bedrock Nova Micro",
3+
"description": "This pattern demonstrates how to create a serverless API leveraging Amazon Bedrock Nova Micro through AWS Lambda.",
4+
"language": "Python",
5+
"level": "200",
6+
"framework": "Terraform",
7+
"introBox": {
8+
"headline": "How it works",
9+
"text": [
10+
"An Amazon API Gateway REST endpoint accepts POST requests containing prompts. These requests are automatically routed to an AWS Lambda function, which processes the input and interacts with Amazon Bedrock Nova Micro.",
11+
"The Lambda function formats the request according to the model's requirements, invokes the model, and returns the generated response through API Gateway. This serverless architecture ensures scalability and cost-effectiveness, as you only pay for actual API calls and compute time."
12+
]
13+
},
14+
"gitHub": {
15+
"template": {
16+
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-lambda-bedrock-nova-terraform",
17+
"templateURL": "apigw-lambda-bedrock-nova-terraform",
18+
"projectFolder": "apigw-lambda-bedrock-nova-terraform",
19+
"templateFile": "main.tf"
20+
}
21+
},
22+
"resources": {
23+
"bullets": [
24+
{
25+
"text": "Amazon API Gateway REST APIs",
26+
"link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/welcome.html"
27+
},
28+
{
29+
"text": "AWS Lambda Function Integration",
30+
"link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started-with-lambda-integration.html"
31+
},
32+
{
33+
"text": "Amazon Bedrock Nova Models",
34+
"link": "https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-nova.html"
35+
}
36+
]
37+
},
38+
"deploy": {
39+
"text": [
40+
"terraform init",
41+
"terraform plan",
42+
"terraform apply"
43+
]
44+
},
45+
"testing": {
46+
"text": [
47+
"Test the API endpoint using curl:",
48+
"<code>curl -X POST -H \"Content-Type: application/json\" -d '{\"prompt\": \"What are the key benefits of using AWS services?\"}' https://YOUR-API-ENDPOINT/dev/generate_content<code>",
49+
""
50+
]
51+
},
52+
"cleanup": {
53+
"text": [
54+
"<code>terraform destroy<code>",
55+
"<code>terraform show<code>"
56+
]
57+
},
58+
"authors": [
59+
{
60+
"name": "Naresh Rajaram",
61+
"image": "",
62+
"bio": "Senior Partner Solutions Architect, AWS",
63+
"linkedin": "nareshrajaram"
64+
}
65+
],
66+
"patternArch": {
67+
"icon1": {
68+
"x": 20,
69+
"y": 50,
70+
"service": "apigw",
71+
"label": "API Gateway REST API"
72+
},
73+
"icon2": {
74+
"x": 50,
75+
"y": 50,
76+
"service": "lambda",
77+
"label": "AWS Lambda"
78+
},
79+
"icon3": {
80+
"x": 80,
81+
"y": 50,
82+
"service": "bedrock",
83+
"label": "Amazon Bedrock"
84+
},
85+
"line1": {
86+
"from": "icon1",
87+
"to": "icon2"
88+
},
89+
"line2": {
90+
"from": "icon2",
91+
"to": "icon3"
92+
}
93+
}
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import json
2+
import boto3
3+
import botocore
4+
5+
# Create Bedrock Runtime client
6+
bedrock = boto3.client(
7+
service_name='bedrock-runtime',
8+
region_name='us-east-1',
9+
endpoint_url='https://bedrock-runtime.us-east-1.amazonaws.com'
10+
)
11+
12+
def lambda_handler(event, context):
13+
try:
14+
# Handle both direct Lambda invocation and API Gateway requests
15+
if isinstance(event, dict):
16+
if 'body' in event:
17+
body = json.loads(event["body"])
18+
else:
19+
body = event
20+
else:
21+
return {
22+
'statusCode': 400,
23+
'body': json.dumps({
24+
'error': 'Invalid input format'
25+
})
26+
}
27+
28+
# Extract the prompt
29+
prompt = body.get("prompt")
30+
if not prompt:
31+
return {
32+
'statusCode': 400,
33+
'body': json.dumps({
34+
'error': 'Prompt is required'
35+
})
36+
}
37+
38+
print("Prompt = " + prompt)
39+
40+
# Create the request body for Nova Micro
41+
request_body = json.dumps({
42+
"system": [
43+
{
44+
"text": "You are a helpful AI assistant that provides accurate and concise information."
45+
}
46+
],
47+
"messages": [
48+
{
49+
"role": "user",
50+
"content": [
51+
{
52+
"text": prompt
53+
}
54+
]
55+
}
56+
],
57+
"inferenceConfig": {
58+
"maxTokens": 1024,
59+
"temperature": 0.7,
60+
"topP": 0.9,
61+
"topK": 50,
62+
"stopSequences": []
63+
}
64+
})
65+
66+
# Invoke Bedrock API with Nova Micro model
67+
try:
68+
response = bedrock.invoke_model(
69+
body=request_body,
70+
modelId='amazon.nova-micro-v1:0',
71+
accept='application/json',
72+
contentType='application/json'
73+
)
74+
75+
# Parse the response body
76+
response_body = json.loads(response['body'].read())
77+
print("Nova Micro Response:", response_body)
78+
79+
# Extract text from the nested response structure
80+
generated_text = response_body.get('output', {}).get('message', {}).get('content', [{}])[0].get('text', '')
81+
82+
return {
83+
'statusCode': 200,
84+
'headers': {
85+
'Content-Type': 'application/json',
86+
'Access-Control-Allow-Origin': '*'
87+
},
88+
'body': json.dumps({
89+
'generated-text': generated_text
90+
})
91+
}
92+
93+
except botocore.exceptions.ClientError as e:
94+
print(f"Bedrock API Error: {str(e)}")
95+
return {
96+
'statusCode': 500,
97+
'headers': {
98+
'Content-Type': 'application/json',
99+
'Access-Control-Allow-Origin': '*'
100+
},
101+
'body': json.dumps({
102+
'error': f"Bedrock API Error: {str(e)}"
103+
})
104+
}
105+
106+
except Exception as e:
107+
print(f"Error: {str(e)}")
108+
import traceback
109+
print(f"Traceback: {traceback.format_exc()}")
110+
return {
111+
'statusCode': 500,
112+
'headers': {
113+
'Content-Type': 'application/json',
114+
'Access-Control-Allow-Origin': '*'
115+
},
116+
'body': json.dumps({
117+
'error': str(e),
118+
'traceback': traceback.format_exc()
119+
})
120+
}

0 commit comments

Comments
 (0)