From 1dc5fed04f5c411f8c2d92043cba0e10b36aaf22 Mon Sep 17 00:00:00 2001 From: krao14 Date: Tue, 6 Aug 2024 00:39:17 -0700 Subject: [PATCH 1/6] New serverless pattern-lambda-kendra-bedrock-cdk-python --- kendra-bedrock-cdk-python/README.md | 71 ++++++ kendra-bedrock-cdk-python/app.py | 229 ++++++++++++++++++ kendra-bedrock-cdk-python/cdk.json | 62 +++++ .../example-pattern.json | 57 +++++ .../images/architecture.png | Bin 0 -> 21738 bytes kendra-bedrock-cdk-python/requirements.txt | 2 + .../dataSourceSync/dataSourceSyncLambda.py | 26 ++ .../invokeBedrockLambda.py | 56 +++++ 8 files changed, 503 insertions(+) create mode 100644 kendra-bedrock-cdk-python/README.md create mode 100644 kendra-bedrock-cdk-python/app.py create mode 100644 kendra-bedrock-cdk-python/cdk.json create mode 100644 kendra-bedrock-cdk-python/example-pattern.json create mode 100644 kendra-bedrock-cdk-python/images/architecture.png create mode 100644 kendra-bedrock-cdk-python/requirements.txt create mode 100644 kendra-bedrock-cdk-python/src/dataSourceSync/dataSourceSyncLambda.py create mode 100644 kendra-bedrock-cdk-python/src/invokeBedrockLambda/invokeBedrockLambda.py diff --git a/kendra-bedrock-cdk-python/README.md b/kendra-bedrock-cdk-python/README.md new file mode 100644 index 000000000..6dbee76b2 --- /dev/null +++ b/kendra-bedrock-cdk-python/README.md @@ -0,0 +1,71 @@ +# AWS Lambda to Amazon Kendra to Amazon Bedrock + +This pattern contains a sample stack that utilizes an AWS Lambda function to retrieve documents from an Amazon Kendra index and then pass it to Amazon Bedrock to generate a response. The pattern includes usage of the Amazon S3 data source connector. + +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 for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. + +## Requirements +* [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. +* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured +* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +* [AWS CDK CLI](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html) (AWS CDK) installed +* [Request Amazon Bedrock Model Access for Anthropic Claude models on Amazon Bedrock](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) +* [Create an S3 Bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html) and [upload documents](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html) that you want to be indexed. If you already have an S3 bucket with data that you want to crawl, you can skip this step. Note down the name of the S3 bucket for later use. + +## Deployment Instructions +1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: + ``` + git clone https://github.com/aws-samples/serverless-patterns + ``` +1. Change directory to the pattern directory: + ``` + cd kendra-bedrock-cdk-python + ``` +1. From the command line, use AWS CDK to deploy the AWS resources for the pattern as specified in the app.py file: + ``` + cdk deploy --parameters S3DSBucketName=${YourS3BucketName} + ``` + +1. Note the outputs from the CDK deployment process. These contain the resource names and/or ARNs which are used for testing. + +# How it works +Please refer to the architecture diagram below: + +![End to End Architecture](images/architecture.png) + +Here's a breakdown of the steps: + +**AWS Lambda:** Two AWS Lambda functions are created. `DataSourceSync` crawls and indexes the content. `InvokeBedrockLambda` invokes the specified model by passing the retrieved content from Amazon Kendra as context to the generative AI model. + +**Amazon Kendra:** An Amazon Kendra index is created with a S3 data source connector. When a the `InvokeBedrockLambda` function is called, documents are retrieved from the Amazon Kendra index. + +**Amazon Bedrock:** Documents retrieved from the Amazon Kendra index are sent to Amazon Bedrock which responds with a generated response. + +## Testing + +CLI Lambda invoke with test event: + +```bash +aws lambda invoke --function-name INVOKE_LAMBDA_FUNCTION_ARN --payload '{"question": "Value" }' output.txt +``` + +The output.txt will contain the response generated by Amazon Bedrock. + +Example JSON Lambda test event: + +``` +{ + "question": "Value" +} +``` + +## Cleanup + +1. Delete the stack + ```bash + cdk destroy + ``` +---- +Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 \ No newline at end of file diff --git a/kendra-bedrock-cdk-python/app.py b/kendra-bedrock-cdk-python/app.py new file mode 100644 index 000000000..627e97c43 --- /dev/null +++ b/kendra-bedrock-cdk-python/app.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python3 +import os + +import aws_cdk as cdk + +from aws_cdk import ( + # Duration, + Stack, + aws_iam as iam, + aws_kendra as kendra, + aws_lambda as lambda_, + aws_s3 as s3, + RemovalPolicy, + Duration, + CfnParameter, + CfnOutput, + triggers + +) + +from constructs import Construct + +class BedrockKendraStack(Stack): + def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: + super().__init__(scope, construct_id, **kwargs) + + # Define parameters + model_id_param = CfnParameter( + self, "ModelId", + type="String", + default="anthropic.claude-instant-v1", + allowed_values=[ + "anthropic.claude-instant-v1", + "anthropic.claude-3-sonnet-20240229-v1:0", + "anthropic.claude-3-haiku-20240307-v1:0", + "anthropic.claude-v2" + ], + description="Enter the Model Id of the Anthropic LLM" + ) + + s3_bucket_name_param = CfnParameter( + self, "S3DSBucketName", + type="String", + description="Enter the S3 bucket name where the contents you want to be indexed are stored." + ) + + kendra_edition_param = CfnParameter( + self, "KendraEdition", + type="String", + default="DEVELOPER_EDITION", + allowed_values=[ + "DEVELOPER_EDITION", + "ENTERPRISE_EDITION" + ], + description="Kendra edition (DEVELOPER_EDITION, ENTERPRISE_EDITION)" + ) + + # Use the parameter values in your stack + model_id = model_id_param.value_as_string + s3_bucket_name = s3_bucket_name_param.value_as_string + kendra_edition = kendra_edition_param.value_as_string + + # Create Kendra index role + kendra_index_role = iam.Role( + self, "KendraIndexRole", + assumed_by=iam.ServicePrincipal("kendra.amazonaws.com"), + role_name=f"{construct_id}-KendraIndexRole", + managed_policies=[ + iam.ManagedPolicy.from_aws_managed_policy_name("CloudWatchLogsFullAccess") + ] + ) + + # Create Kendra index + kendra_index = kendra.CfnIndex( + self, "KendraIndex", + name=f"{construct_id}-KendraIndex", + role_arn=kendra_index_role.role_arn, + edition=kendra_edition + ) + + # Create Kendra data source role + kendra_ds_role = iam.Role( + self, "KendraDSRole", + assumed_by=iam.ServicePrincipal("kendra.amazonaws.com"), + role_name=f"{construct_id}-DocsDSRole", + managed_policies=[ + iam.ManagedPolicy.from_aws_managed_policy_name("CloudWatchLogsFullAccess")], + inline_policies={ + "KendraDataSourcePolicy": iam.PolicyDocument( + statements=[ + iam.PolicyStatement( + actions=["kendra:BatchPutDocument", "kendra:BatchDeleteDocument"], + resources=[kendra_index.attr_arn] + ) + ] + ), + "S3DataSourcePolicy": iam.PolicyDocument( + statements=[ + iam.PolicyStatement( + actions=["s3:GetObject"], + resources=[f"arn:aws:s3:::{s3_bucket_name}/*"] + ) + ] + ), + "ListBucketPolicy": iam.PolicyDocument( + statements=[ + iam.PolicyStatement( + actions=["s3:ListBucket"], + resources=[f"arn:aws:s3:::{s3_bucket_name}"] + ) + ] + ) + } + ) + + # Create Kendra S3 data source + kendra_ds = kendra.CfnDataSource( + self, "KendraDS", + index_id=kendra_index.attr_id, + name=f"{construct_id}-KendraS3DS", + type='S3', + data_source_configuration=kendra.CfnDataSource.DataSourceConfigurationProperty( + s3_configuration=kendra.CfnDataSource.S3DataSourceConfigurationProperty( + bucket_name=s3_bucket_name)), + role_arn=kendra_ds_role.role_arn + ) + + # Add dependency + kendra_ds.node.add_dependency(kendra_index) + + # Create a role for the DataSourceSyncLambda + data_source_sync_lambda_role = iam.Role( + self, "DataSourceSyncLambdaRole", + assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"), + managed_policies=[ + iam.ManagedPolicy.from_aws_managed_policy_name("CloudWatchLogsFullAccess")], + inline_policies={ + "KendraDataSourceSyncPolicy": iam.PolicyDocument( + statements=[ + iam.PolicyStatement( + actions=[ + "kendra:StartDataSourceSyncJob", + "kendra:StopDataSourceSyncJob" + ], + resources=[ + kendra_index.attr_arn, + f"{kendra_index.attr_arn}/*"] + ) + ] + ) + } + ) + + # Lambda function for initiating data source sync + data_source_sync_lambda = lambda_.Function( + self, "DataSourceSyncLambda", + runtime=lambda_.Runtime.PYTHON_3_12, + code=lambda_.Code.from_asset("src/dataSourceSync"), + handler="dataSourceSyncLambda.lambda_handler", + timeout=Duration.minutes(15), + memory_size=1024, + role = data_source_sync_lambda_role, + environment={ + "INDEX_ID": kendra_index.attr_id, + "DS_ID": kendra_ds.attr_id + } + ) + + # Trigger data source sync lambda + triggers.Trigger(self, "data_source_sync_lambda_trigger", + handler=data_source_sync_lambda, + timeout=Duration.minutes(10), + invocation_type=triggers.InvocationType.EVENT + ) + + # Create the IAM role + invoke_bedrock_lambda_role = iam.Role( + self, "InvokeBedRockLambdaRole", + assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"), + managed_policies=[ + iam.ManagedPolicy.from_aws_managed_policy_name("CloudWatchLogsFullAccess") + ], + inline_policies={ + "InvokeBedRockPolicy": iam.PolicyDocument( + statements=[ + iam.PolicyStatement( + actions=["bedrock:InvokeModel"], + resources=[f"arn:aws:bedrock:{self.region}::foundation-model/{model_id}"] + ) + ] + ), + "KendraRetrievalPolicy": iam.PolicyDocument( + statements=[ + iam.PolicyStatement( + actions=["kendra:Retrieve"], + resources=[kendra_index.attr_arn] + ) + ] + ) + } + ) + + # Lambda function for invoking Bedrock + invoke_bedrock_lambda = lambda_.Function( + self, "InvokeBedrockLambda", + runtime=lambda_.Runtime.PYTHON_3_12, + code=lambda_.Code.from_asset("src/invokeBedrockLambda"), + handler="invokeBedrockLambda.lambda_handler", + timeout=Duration.seconds(120), + memory_size=3008, + role = invoke_bedrock_lambda_role, + tracing=lambda_.Tracing.ACTIVE, + environment={ + "INDEX_ID": kendra_index.attr_id, + "MODEL_ID": model_id + } + ) + + # Output values + CfnOutput(self, "KendraIndexRoleArn", value=kendra_index_role.role_arn, description="Kendra index role ARN") + CfnOutput(self, "KendraIndexID", value=kendra_index.attr_id, description="Kendra index ID") + CfnOutput(self, "KendraS3DataSourceArn", value=kendra_ds.attr_arn, description="Kendra S3 data source ARN") + CfnOutput(self, "DataSourceSyncLambdaArn", value=data_source_sync_lambda.function_arn, description="Data source sync lambda function ARN") + CfnOutput(self, "InvokeBedrockLambdaArn", value=invoke_bedrock_lambda.function_arn, description="Invoke bedrock lambda function ARN") + +app = cdk.App() +BedrockKendraStack(app, "BedrockKendraStack") + +app.synth() diff --git a/kendra-bedrock-cdk-python/cdk.json b/kendra-bedrock-cdk-python/cdk.json new file mode 100644 index 000000000..eb79b783a --- /dev/null +++ b/kendra-bedrock-cdk-python/cdk.json @@ -0,0 +1,62 @@ +{ + "app": "python3 app.py", + "watch": { + "include": [ + "**" + ], + "exclude": [ + "README.md", + "cdk*.json", + "requirements*.txt", + "source.bat", + "**/__init__.py", + "**/__pycache__", + "tests" + ] + }, + "context": { + "@aws-cdk/aws-lambda:recognizeLayerVersion": true, + "@aws-cdk/core:checkSecretUsage": true, + "@aws-cdk/core:target-partitions": [ + "aws", + "aws-cn" + ], + "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, + "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, + "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, + "@aws-cdk/aws-iam:minimizePolicies": true, + "@aws-cdk/core:validateSnapshotRemovalPolicy": true, + "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, + "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, + "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, + "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, + "@aws-cdk/core:enablePartitionLiterals": true, + "@aws-cdk/aws-events:eventsTargetQueueSameAccount": true, + "@aws-cdk/aws-iam:standardizedServicePrincipals": true, + "@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true, + "@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true, + "@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true, + "@aws-cdk/aws-route53-patters:useCertificate": true, + "@aws-cdk/customresources:installLatestAwsSdkDefault": false, + "@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true, + "@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true, + "@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true, + "@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true, + "@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true, + "@aws-cdk/aws-redshift:columnId": true, + "@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true, + "@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true, + "@aws-cdk/aws-apigateway:requestValidatorUniqueId": true, + "@aws-cdk/aws-kms:aliasNameRef": true, + "@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true, + "@aws-cdk/core:includePrefixInUniqueNameGeneration": true, + "@aws-cdk/aws-efs:denyAnonymousAccess": true, + "@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true, + "@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true, + "@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true, + "@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true, + "@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true, + "@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true, + "@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true + } +} diff --git a/kendra-bedrock-cdk-python/example-pattern.json b/kendra-bedrock-cdk-python/example-pattern.json new file mode 100644 index 000000000..194875a84 --- /dev/null +++ b/kendra-bedrock-cdk-python/example-pattern.json @@ -0,0 +1,57 @@ +{ + "title": "Lambda to Kendra to Bedrock", + "description": "AWS Lambda function to retrieve documents from an Amazon Kendra index and pass it to Amazon Bedrock for a generated response.", + "language": "Python", + "level": "200", + "framework": "CDK", + "introBox": { + "headline": "How it works", + "text": [ + "AWS Lambda: Two AWS Lambda functions are created. DataSourceSync Lambda function crawls and indexes the content. InvokeBedrockLambda AWS Lambda function that invokes the specified model by passing the retrieved content from Amazon Kendra as context to the generative AI model.", + "Amazon Kendra: An Amazon Kendra index is created with a S3 data source. When a the InvokeBedrockLambda function is called, documents are retrieved from the Amazon Kendra index.", + "Amazon Bedrock: Documents retrieved from the Amazon Kendra index are sent to Amazon Bedrock which responds with a generated response." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/kendra-bedrock-cdk-python", + "templateURL": "serverless-patterns/kendra-bedrock-cdk-python", + "projectFolder": "kendra-bedrock-cdk-python", + "templateFile": "app.py" + } + }, + "resources": { + "bullets": [ + { + "text": "Amazon Kendra - Enterprise Search Engine", + "link": "https://aws.amazon.com/kendra/" + }, + { + "text": "Amazon Bedrock - Generative AI", + "link": "https://aws.amazon.com/bedrock/" + } + ] + }, + "deploy": { + "text": [ + "cdk deploy BedrockKendraStack --parameters S3DSBucketName=${YourS3BucketName}" + ] + }, + "testing": { + "text": [ + "See the GitHub repo for detailed testing instructions." + ] + }, + "cleanup": { + "text": [ + "Delete the stack: cdk destroy." + ] + }, + "authors": [ + { + "name": "Kruthi Jayasimha Rao", + "bio": "Kruthi is a Partner Solutions Architect specializing in AI and ML. She provides technical guidance to AWS Partners in following best practices to build secure, resilient, and highly available solutions in the AWS Cloud.", + "linkedin": "https://www.linkedin.com/in/kruthi-jayasimha-rao-132a78167" + } + ] +} \ No newline at end of file diff --git a/kendra-bedrock-cdk-python/images/architecture.png b/kendra-bedrock-cdk-python/images/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..ca866a6a1caffc2997f45a1dd5ec12b037fbc13f GIT binary patch literal 21738 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 literal 0 HcmV?d00001 diff --git a/kendra-bedrock-cdk-python/requirements.txt b/kendra-bedrock-cdk-python/requirements.txt new file mode 100644 index 000000000..0b75fe75d --- /dev/null +++ b/kendra-bedrock-cdk-python/requirements.txt @@ -0,0 +1,2 @@ +aws-cdk-lib==2.110.0 +constructs>=10.0.0,<11.0.0 diff --git a/kendra-bedrock-cdk-python/src/dataSourceSync/dataSourceSyncLambda.py b/kendra-bedrock-cdk-python/src/dataSourceSync/dataSourceSyncLambda.py new file mode 100644 index 000000000..cd7183f5d --- /dev/null +++ b/kendra-bedrock-cdk-python/src/dataSourceSync/dataSourceSyncLambda.py @@ -0,0 +1,26 @@ + +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 + +import json +import logging +import boto3 +import os + +logger = logging.getLogger() +logger.setLevel(logging.INFO) + +INDEX_ID = os.environ['INDEX_ID'] +DS_ID = os.environ['DS_ID'] +AWS_REGION = os.environ['AWS_REGION'] +KENDRA = boto3.client('kendra') + +def start_data_source_sync(dsId, indexId): + logger.info(f"start_data_source_sync(dsId={dsId}, indexId={indexId})") + resp = KENDRA.start_data_source_sync_job(Id=dsId, IndexId=indexId) + logger.info(f"response:" + json.dumps(resp)) + +def lambda_handler(event, context): + logger.info("Received event: %s" % json.dumps(event)) + start_data_source_sync(DS_ID, INDEX_ID) + return diff --git a/kendra-bedrock-cdk-python/src/invokeBedrockLambda/invokeBedrockLambda.py b/kendra-bedrock-cdk-python/src/invokeBedrockLambda/invokeBedrockLambda.py new file mode 100644 index 000000000..d06757360 --- /dev/null +++ b/kendra-bedrock-cdk-python/src/invokeBedrockLambda/invokeBedrockLambda.py @@ -0,0 +1,56 @@ +import os +import boto3 +import json +# retrieves kendra index id +kendra_index_id = os.environ['INDEX_ID'] +region = os.environ['AWS_REGION'] +model_id = os.environ['MODEL_ID'] +def kendra_retrieve_document(question): + """ + This function takes in the question from the user, and retrieves relevant passages based on default PageSize of 10. + :param question: The question the user is asking. + :return: Returns the context to be sent to the LLM and document URIs to be returned as relevant data sources. + """ + kendra_client = boto3.client('kendra') + documents = kendra_client.retrieve(IndexId=kendra_index_id, QueryText=question) + text = "" + uris = set() + if len(documents['ResultItems']) > 0: + for i in range(len(documents['ResultItems'])): + text += documents['ResultItems'][i]['Content'] + "\n" + uris.add(documents['ResultItems'][i]['DocumentURI']) + return (text, uris) +def invokeLLM(question, context): + """ + This function takes in the question from the user, along with the Kendra responses as context to generate an answer + for the user on the frontend. + :param question: The question the user is asking . + :param context: The context to be sent to the LLM to generate a better + answer. + :return: Returns the final answer that will be provided to the end-user of the application who asked the original + question. + """ + # Setup Bedrock client + bedrock = boto3.client('bedrock-runtime') + # body of data with parameters that is passed into the bedrock invoke model request + body = json.dumps({"max_tokens": 350, + "system": "You are a truthful AI assistant. Your goal is to provide informative and substantive responses to queries based on the documents provided. If you do not know the answer to a question, you truthfully say you do not know.", + "messages": [{"role": "user", "content": "Answer this user query:" + question + "with the following context:" + context}], + "anthropic_version": "bedrock-2023-05-31", + "temperature":0, + "top_k":250, + "top_p":0.999}) + # Invoking the bedrock model + response = bedrock.invoke_model(body=body, + modelId=model_id) + response_body = json.loads(response.get('body').read()) + answer = response_body.get('content') + # returning the answer as a final result, which ultimately gets returned to the end user + return answer + +def lambda_handler(event, context): + question = event['question'] + context = kendra_retrieve_document(question) + llm_response = invokeLLM(question, context[0]) + answer = llm_response[0]['text'] +"\n" + "*Relevant links:* " + "\n" + "\n".join(context[1]) + return answer \ No newline at end of file From 668a14adc4b42275b92bfedff2d572919857d7cd Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 23 Aug 2024 17:06:39 +0200 Subject: [PATCH 2/6] Create kendra-bedrock-cdk-python --- .../kendra-bedrock-cdk-python | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 kendra-bedrock-cdk-python/kendra-bedrock-cdk-python diff --git a/kendra-bedrock-cdk-python/kendra-bedrock-cdk-python b/kendra-bedrock-cdk-python/kendra-bedrock-cdk-python new file mode 100644 index 000000000..ed9a57e5b --- /dev/null +++ b/kendra-bedrock-cdk-python/kendra-bedrock-cdk-python @@ -0,0 +1,83 @@ +{ + "title": "Lambda to Kendra to Bedrock", + "description": "AWS Lambda function to retrieve documents from an Amazon Kendra index and pass it to Amazon Bedrock for a generated response.", + "language": "Python", + "level": "200", + "framework": "CDK", + "introBox": { + "headline": "How it works", + "text": [ + "AWS Lambda: Two AWS Lambda functions are created. DataSourceSync Lambda function crawls and indexes the content. InvokeBedrockLambda AWS Lambda function that invokes the specified model by passing the retrieved content from Amazon Kendra as context to the generative AI model.", + "Amazon Kendra: An Amazon Kendra index is created with a S3 data source. When a the InvokeBedrockLambda function is called, documents are retrieved from the Amazon Kendra index.", + "Amazon Bedrock: Documents retrieved from the Amazon Kendra index are sent to Amazon Bedrock which responds with a generated response." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/kendra-bedrock-cdk-python", + "templateURL": "serverless-patterns/kendra-bedrock-cdk-python", + "projectFolder": "kendra-bedrock-cdk-python", + "templateFile": "app.py" + } + }, + "resources": { + "bullets": [ + { + "text": "Amazon Kendra - Enterprise Search Engine", + "link": "https://aws.amazon.com/kendra/" + }, + { + "text": "Amazon Bedrock - Generative AI", + "link": "https://aws.amazon.com/bedrock/" + } + ] + }, + "deploy": { + "text": [ + "cdk deploy BedrockKendraStack --parameters S3DSBucketName=${YourS3BucketName}" + ] + }, + "testing": { + "text": ["See the GitHub repo for detailed testing instructions."] + }, + "cleanup": { + "text": ["Delete the stack: cdk destroy."] + }, + "authors": [ + { + "name": "Kruthi Jayasimha Rao", + "bio": "Kruthi is a Partner Solutions Architect specializing in AI and ML. She provides technical guidance to AWS Partners in following best practices to build secure, resilient, and highly available solutions in the AWS Cloud.", + "linkedin": "kruthi-jayasimha-rao-132a78167" + } + ], + "patternArch": { + "icon1": { + "x": 20, + "y": 50, + "service": "lambda", + "label": "AWS Lambda" + }, + "icon2": { + "x": 50, + "y": 50, + "service": "kendra", + "label": "Amazon Kendra" + }, + "icon3": { + "x": 80, + "y": 50, + "service": "bedrock", + "label": "Amazon Bedrock" + }, + "line1": { + "from": "icon1", + "to": "icon2", + "label": "" + }, + "line2": { + "from": "icon2", + "to": "icon3", + "label": "" + } + } +} From 2a2cec3a4647c544647fb5f2d27fa81e73818b9b Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 23 Aug 2024 17:07:06 +0200 Subject: [PATCH 3/6] Delete kendra-bedrock-cdk-python/kendra-bedrock-cdk-python --- .../kendra-bedrock-cdk-python | 83 ------------------- 1 file changed, 83 deletions(-) delete mode 100644 kendra-bedrock-cdk-python/kendra-bedrock-cdk-python diff --git a/kendra-bedrock-cdk-python/kendra-bedrock-cdk-python b/kendra-bedrock-cdk-python/kendra-bedrock-cdk-python deleted file mode 100644 index ed9a57e5b..000000000 --- a/kendra-bedrock-cdk-python/kendra-bedrock-cdk-python +++ /dev/null @@ -1,83 +0,0 @@ -{ - "title": "Lambda to Kendra to Bedrock", - "description": "AWS Lambda function to retrieve documents from an Amazon Kendra index and pass it to Amazon Bedrock for a generated response.", - "language": "Python", - "level": "200", - "framework": "CDK", - "introBox": { - "headline": "How it works", - "text": [ - "AWS Lambda: Two AWS Lambda functions are created. DataSourceSync Lambda function crawls and indexes the content. InvokeBedrockLambda AWS Lambda function that invokes the specified model by passing the retrieved content from Amazon Kendra as context to the generative AI model.", - "Amazon Kendra: An Amazon Kendra index is created with a S3 data source. When a the InvokeBedrockLambda function is called, documents are retrieved from the Amazon Kendra index.", - "Amazon Bedrock: Documents retrieved from the Amazon Kendra index are sent to Amazon Bedrock which responds with a generated response." - ] - }, - "gitHub": { - "template": { - "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/kendra-bedrock-cdk-python", - "templateURL": "serverless-patterns/kendra-bedrock-cdk-python", - "projectFolder": "kendra-bedrock-cdk-python", - "templateFile": "app.py" - } - }, - "resources": { - "bullets": [ - { - "text": "Amazon Kendra - Enterprise Search Engine", - "link": "https://aws.amazon.com/kendra/" - }, - { - "text": "Amazon Bedrock - Generative AI", - "link": "https://aws.amazon.com/bedrock/" - } - ] - }, - "deploy": { - "text": [ - "cdk deploy BedrockKendraStack --parameters S3DSBucketName=${YourS3BucketName}" - ] - }, - "testing": { - "text": ["See the GitHub repo for detailed testing instructions."] - }, - "cleanup": { - "text": ["Delete the stack: cdk destroy."] - }, - "authors": [ - { - "name": "Kruthi Jayasimha Rao", - "bio": "Kruthi is a Partner Solutions Architect specializing in AI and ML. She provides technical guidance to AWS Partners in following best practices to build secure, resilient, and highly available solutions in the AWS Cloud.", - "linkedin": "kruthi-jayasimha-rao-132a78167" - } - ], - "patternArch": { - "icon1": { - "x": 20, - "y": 50, - "service": "lambda", - "label": "AWS Lambda" - }, - "icon2": { - "x": 50, - "y": 50, - "service": "kendra", - "label": "Amazon Kendra" - }, - "icon3": { - "x": 80, - "y": 50, - "service": "bedrock", - "label": "Amazon Bedrock" - }, - "line1": { - "from": "icon1", - "to": "icon2", - "label": "" - }, - "line2": { - "from": "icon2", - "to": "icon3", - "label": "" - } - } -} From c98f18bb2728b44ca84194088afe064067ce0c20 Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 23 Aug 2024 17:07:25 +0200 Subject: [PATCH 4/6] Create kendra-bedrock-cdk-python.json --- .../kendra-bedrock-cdk-python.json | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 kendra-bedrock-cdk-python/kendra-bedrock-cdk-python.json diff --git a/kendra-bedrock-cdk-python/kendra-bedrock-cdk-python.json b/kendra-bedrock-cdk-python/kendra-bedrock-cdk-python.json new file mode 100644 index 000000000..ed9a57e5b --- /dev/null +++ b/kendra-bedrock-cdk-python/kendra-bedrock-cdk-python.json @@ -0,0 +1,83 @@ +{ + "title": "Lambda to Kendra to Bedrock", + "description": "AWS Lambda function to retrieve documents from an Amazon Kendra index and pass it to Amazon Bedrock for a generated response.", + "language": "Python", + "level": "200", + "framework": "CDK", + "introBox": { + "headline": "How it works", + "text": [ + "AWS Lambda: Two AWS Lambda functions are created. DataSourceSync Lambda function crawls and indexes the content. InvokeBedrockLambda AWS Lambda function that invokes the specified model by passing the retrieved content from Amazon Kendra as context to the generative AI model.", + "Amazon Kendra: An Amazon Kendra index is created with a S3 data source. When a the InvokeBedrockLambda function is called, documents are retrieved from the Amazon Kendra index.", + "Amazon Bedrock: Documents retrieved from the Amazon Kendra index are sent to Amazon Bedrock which responds with a generated response." + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/kendra-bedrock-cdk-python", + "templateURL": "serverless-patterns/kendra-bedrock-cdk-python", + "projectFolder": "kendra-bedrock-cdk-python", + "templateFile": "app.py" + } + }, + "resources": { + "bullets": [ + { + "text": "Amazon Kendra - Enterprise Search Engine", + "link": "https://aws.amazon.com/kendra/" + }, + { + "text": "Amazon Bedrock - Generative AI", + "link": "https://aws.amazon.com/bedrock/" + } + ] + }, + "deploy": { + "text": [ + "cdk deploy BedrockKendraStack --parameters S3DSBucketName=${YourS3BucketName}" + ] + }, + "testing": { + "text": ["See the GitHub repo for detailed testing instructions."] + }, + "cleanup": { + "text": ["Delete the stack: cdk destroy."] + }, + "authors": [ + { + "name": "Kruthi Jayasimha Rao", + "bio": "Kruthi is a Partner Solutions Architect specializing in AI and ML. She provides technical guidance to AWS Partners in following best practices to build secure, resilient, and highly available solutions in the AWS Cloud.", + "linkedin": "kruthi-jayasimha-rao-132a78167" + } + ], + "patternArch": { + "icon1": { + "x": 20, + "y": 50, + "service": "lambda", + "label": "AWS Lambda" + }, + "icon2": { + "x": 50, + "y": 50, + "service": "kendra", + "label": "Amazon Kendra" + }, + "icon3": { + "x": 80, + "y": 50, + "service": "bedrock", + "label": "Amazon Bedrock" + }, + "line1": { + "from": "icon1", + "to": "icon2", + "label": "" + }, + "line2": { + "from": "icon2", + "to": "icon3", + "label": "" + } + } +} From 319815e9846ffff5c0ab8a39566b18bf2f5c68af Mon Sep 17 00:00:00 2001 From: Kruthi Rao <108151318+krao14@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:01:40 -0700 Subject: [PATCH 5/6] Update kendra-bedrock-cdk-python/README.md Co-authored-by: Marco --- kendra-bedrock-cdk-python/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kendra-bedrock-cdk-python/README.md b/kendra-bedrock-cdk-python/README.md index 6dbee76b2..52c87400f 100644 --- a/kendra-bedrock-cdk-python/README.md +++ b/kendra-bedrock-cdk-python/README.md @@ -66,6 +66,6 @@ Example JSON Lambda test event: cdk destroy ``` ---- -Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: MIT-0 \ No newline at end of file From 704b902a7eb8659bb2f13ab3368e9cf00822448a Mon Sep 17 00:00:00 2001 From: Kruthi Rao <108151318+krao14@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:05:15 -0700 Subject: [PATCH 6/6] Update kendra-bedrock-cdk-python/README.md Co-authored-by: Marco --- kendra-bedrock-cdk-python/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/kendra-bedrock-cdk-python/README.md b/kendra-bedrock-cdk-python/README.md index 52c87400f..828e7d33f 100644 --- a/kendra-bedrock-cdk-python/README.md +++ b/kendra-bedrock-cdk-python/README.md @@ -46,7 +46,12 @@ Here's a breakdown of the steps: CLI Lambda invoke with test event: ```bash -aws lambda invoke --function-name INVOKE_LAMBDA_FUNCTION_ARN --payload '{"question": "Value" }' output.txt +payload_base64=$(echo -n '{"question": "Value"}' | base64) + +aws lambda invoke \ + --function-name INVOKE_LAMBDA_FUNCTION_ARN \ + --payload "$payload_base64" \ + output.txt ``` The output.txt will contain the response generated by Amazon Bedrock.