AWSTemplateFormatVersion: 2010-09-09 Transform: - AWS::Serverless-2016-10-31 Parameters: BotName: Type: String Description: Prefix to add to Lex resource names Default: InvoiceBot MinLength: 3 MaxLength: 32 AllowedPattern: ^[a-zA-Z\._]+$ ConstraintDescription: "Must conform with the permitted Lex Bot name pattern.\ \ \n" Resources: DetectTextAsyncJob: Type: AWS::Serverless::Function Properties: Handler: lambda/create_texttract_detect_text_async_job.handler Runtime: python3.7 CodeUri: s3://aws-bigdata-blog/artifacts/aws-textract-comprehend-lex-chatbot/lambda.zip Description: '' MemorySize: 512 Timeout: 30 Environment: Variables: SNS_TOPIC_ARN: Ref: TexttractAsyncJobSNSTopic SNS_ROLE_ARN: Fn::GetAtt: - TextractSNSTopicRole - Arn Role: Fn::GetAtt: - DetectTextAsyncJobRole - Arn Events: BucketEvent1: Type: S3 Properties: Bucket: Ref: SourceImageBucket Events: - s3:ObjectCreated:* DetectTextAsyncJobRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole DetectTextAsyncJobRolePolicy: Type: AWS::IAM::ManagedPolicy Properties: Path: / PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - s3:GetObject Resource: arn:aws:s3:::*meaningful-conve*/* - Effect: Allow Action: - textract:StartDocumentTextDetection Resource: '*' Roles: - Ref: DetectTextAsyncJobRole SourceImageBucket: Type: AWS::S3::Bucket Properties: BucketName: Fn::Sub: meaningful-conve-ip-bkt-${AWS::Region}-${AWS::AccountId} TextractSNSTopicRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - textract.amazonaws.com Action: - sts:AssumeRole Path: / Policies: - PolicyName: root PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: sns:Publish Resource: arn:aws:sns:*:*:*Textract* TexttractAsyncJobSNSTopic: Type: AWS::SNS::Topic Properties: TopicName: TextractAsyncJobCompletionNotify KmsMasterKeyId: alias/aws/sns ExtractTextFromAsyncJobOutput: Type: AWS::Serverless::Function Properties: Handler: lambda/extract_text_from_textract_async_job_output.handler Runtime: python3.7 CodeUri: s3://aws-bigdata-blog/artifacts/aws-textract-comprehend-lex-chatbot/lambda.zip Description: '' MemorySize: 512 Timeout: 30 Environment: Variables: OUT_PUT_S3_BUCKET: Ref: OutputTextBucket Role: Fn::GetAtt: - ExtractTextAsyncJobOutputRole - Arn Events: SNSEvent: Type: SNS Properties: Topic: Ref: TexttractAsyncJobSNSTopic ExtractTextAsyncJobOutputRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole ExtractTextAsyncJobOutputRolePolicies: Type: AWS::IAM::ManagedPolicy Properties: Path: / PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - textract:GetDocumentTextDetection Resource: '*' - Effect: Allow Action: - s3:PutObject Resource: arn:aws:s3:::*meaningful-conve*/* Roles: - Ref: ExtractTextAsyncJobOutputRole LexLambaFunction: Type: AWS::Serverless::Function Properties: Handler: lambda/meaningful-conversations-lex-lambda.lambda_handler Runtime: python3.7 CodeUri: s3://aws-bigdata-blog/artifacts/aws-textract-comprehend-lex-chatbot/lambda.zip Description: '' MemorySize: 512 Timeout: 30 Environment: Variables: S3_BUCKET: Ref: OutputTextBucket Role: Fn::GetAtt: - LexLambaFunctionRole - Arn LexLambaFunctionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole LexLambaFunctionRolePolicy: Type: AWS::IAM::ManagedPolicy Properties: Path: / PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - comprehend:DetectEntities - comprehend:DetectKeyPhrases Resource: '*' - Effect: Allow Action: - s3:* Resource: - arn:aws:s3:::*meaningful-conve*/* - arn:aws:s3:::*meaningful-conve* Roles: - Ref: LexLambaFunctionRole OutputTextBucket: Type: AWS::S3::Bucket Properties: BucketName: Fn::Sub: meaningful-conve-op-bkt-${AWS::Region}-${AWS::AccountId} LambdaToCreateLexBot: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: python3.7 InlineCode: | import logging import json import boto3 import time import io lexclient = boto3.client('lex-models') s3 = boto3.resource('s3') DEFAULT_LOGGING_LEVEL = logging.INFO logging.basicConfig( format='[%(levelname)s] %(message)s', level=DEFAULT_LOGGING_LEVEL ) logger = logging.getLogger(__name__) logger.setLevel(DEFAULT_LOGGING_LEVEL) BOT_DEFINITION_FILENAME = '/tmp/InvoiceBot.zip' BOT_EXPORT_FILENAME = 'bot-definition-export.json' s3.Bucket('aws-bigdata-blog').download_file('artifacts/aws-textract-comprehend-lex-chatbot/InvoiceBot.zip', '/tmp/InvoiceBot.zip') def create_bot(): with open(BOT_DEFINITION_FILENAME, 'rb') as file_data: bytes_content = file_data.read() response = lexclient.start_import( payload=bytes_content, resourceType='BOT', mergeStrategy='OVERWRITE_LATEST') print("Import id is"+response['importId']) import_status = lexclient.get_import( importId=response['importId']) while import_status['importStatus'] =='IN_PROGRESS': import_status = lexclient.get_import(importId=response['importId']) print("Bot creation is in progress") if import_status['importStatus'] == 'COMPLETE': return "SUCCESS" else: return "FAILURE" def delete_bot(bot_name=None): bot_aliases = lexclient.get_bot_aliases(botName=bot_name)['BotAliases'] for alias in bot_aliases: print("Deleting Alias"+alias) response = lexclient.delete_bot_alias(name=alias,botName=bot_name) time.sleep(5) response = lexclient.delete_bot(name=bot_name) return "SUCCESS" def handler(event, context): """ CloudFormation Custom Resource Lambda Handler """ import cfnresponse request_type = event.get('RequestType') resource_properties = event.get('ResourceProperties') bot_name= resource_properties.get('BotName') response_status = cfnresponse.SUCCESS response = {} response_id = event.get('RequestId') reason = request_type error = '' should_delete = resource_properties.get('ShouldDelete', True) if (request_type in ['Create', 'Update']): try: print("here2") response['status']=create_bot() if response['status'] =="SUCCESS": print("Job succeded\n") response_status = cfnresponse.SUCCESS else: response_status = cfnresponse.FAILED print("Job Failed\n") except Exception as e: error = 'failed to {} bot: {}'.format(request_type, e) pass if (request_type == 'Delete' and should_delete != 'false'): try: response['status']=delete_bot(bot_name) if response['status'] =="SUCCESS": print("Job succeded\n") response_status = cfnresponse.SUCCESS else: response_status = cfnresponse.FAILED print("Delete Failed\n") except Exception as e: error = 'failed to delete bot: {}'.format(e) pass if error: logger.error(error) response_status = cfnresponse.FAILED reason = error if bool(context): cfnresponse.send( event, context, response_status, response, response_id, reason ) Description: '' MemorySize: 512 Timeout: 30 Policies: - AmazonLexFullAccess - AmazonS3FullAccess LexBot: Type: Custom::LexBot Properties: ServiceToken: Fn::GetAtt: - LambdaToCreateLexBot - Arn BotName: Ref: BotName ShouldDelete: 'true' CodeBuildDeploy: Type: AWS::CloudFormation::Stack Properties: TemplateURL: https://s3.amazonaws.com/aws-bigdata-blog/artifacts/aws-lex-web-ui/artifacts/templates/codebuild-deploy.yaml Parameters: CodeBuildName: lex-web-ui SourceBucket: aws-bigdata-blog SourceObject: artifacts/aws-lex-web-ui/artifacts/src.zip CustomResourceCodeObject: artifacts/aws-lex-web-ui/artifacts/custom-resources.zip CleanupBuckets: 'true' BotName: Ref: BotName BotAlias: $LATEST ParentOrigin: '' WebAppConfBotInitialText: Welcome to InvoiceBot. You can ask me to provide your invoice summary, or details of your invoices, or your invoice notes WebAppConfBotInitialSpeech: Welcome to InvoiceBot. You can ask me to provide your invoice summary, or details of your invoices, or your invoice notes WebAppConfNegativeFeedback: Thumbs down WebAppConfPositiveFeedback: Thumbs up WebAppConfHelp: Help WebAppConfToolbarTitle: InvoiceBot ShouldEnableCognitoLogin: 'false' ReInitSessionAttributesOnRestart: 'false' EnableMarkdownSupport: 'true' ShouldLoadIframeMinimized: 'false' ShowResponseCardTitle: 'true' ConnectContactFlowId: ' ' ConnectInstanceId: ' ' ConnectPromptForNameMessage: ' ' ConnectWaitForAgentMessage: ' ' ConnectWaitForAgentMessageIntervalInSeconds: 1 ConnectAgentJoinedMessage: ' ' ConnectAgentLeftMessage: ' ' ConnectChatEndedMessage: ' ' ConnectLiveChatTerms: ' ' CognitoIdentityPoolId: Fn::If: - NeedsCognito - Fn::GetAtt: - CognitoIdentityPool - Outputs.CognitoIdentityPoolId - '' CognitoAppUserPoolClientId: Fn::If: - NeedsCognito - Fn::GetAtt: - CognitoIdentityPool - Outputs.CognitoUserPoolClientId - UserMustSupply CognitoUserPoolId: Fn::If: - NeedsCognito - Fn::GetAtt: - CognitoIdentityPool - Outputs.CognitoUserPoolId - UserMustSupply Timestamp: 600 CognitoIdentityPool: Type: AWS::CloudFormation::Stack Condition: NeedsCognito Properties: TemplateURL: https://s3.amazonaws.com/aws-bigdata-blog/artifacts/aws-lex-web-ui/artifacts/templates/cognito.yaml Parameters: CognitoIdentityPoolName: Lex Web UI LexBotName: Ref: BotName CognitoIdentityPoolConfig: Type: AWS::CloudFormation::Stack Condition: NeedsCognito Properties: TemplateURL: https://s3.amazonaws.com/aws-bigdata-blog/artifacts/aws-lex-web-ui/artifacts/templates/cognitouserpoolconfig.yaml Parameters: Timestamp: 1655687000 WebAppUrl: Fn::If: - NeedsParentOrigin - Fn::GetAtt: - CodeBuildDeploy - Outputs.WebAppBase - '' WebAppPath: /parent.html CodeBuildProjectName: Fn::GetAtt: - CodeBuildDeploy - Outputs.CodeBuildProject CognitoUserPool: Fn::GetAtt: - CognitoIdentityPool - Outputs.CognitoUserPoolId CognitoUserPoolClient: Fn::GetAtt: - CognitoIdentityPool - Outputs.CognitoUserPoolClientId Conditions: NeedsCognito: Fn::Equals: - '' - '' NeedsParentOrigin: Fn::Equals: - '' - '' Outputs: CognitoIdentityPoolId: Condition: NeedsCognito Description: Cognito Identity Pool Id Value: Fn::GetAtt: - CognitoIdentityPool - Outputs.CognitoIdentityPoolId AssetsUploadBucket: Value: Fn::Sub: https://console.aws.amazon.com/s3/home?region=${AWS::Region}&bucket=${SourceImageBucket} Description: Name of the S3 bucket where the pdfs or images are uploaded for text extraction ExtractedTextfilesBucket: Value: Fn::Sub: https://console.aws.amazon.com/s3/home?region=${AWS::Region}&bucket=${OutputTextBucket} Description: Name of the S3 bucket where the files with extracted text are uploaded LexLambaFunctionArn: Description: 'Use this Lambda function for the Lex Intent FullfillmentActivity ' Value: Fn::GetAtt: - LexLambaFunction - Arn LexUIWebAppUrl: Description: 'URL of the stand-alone sample web application. This page will be available after the pipeline/deployment completes. ' Value: Fn::GetAtt: - CodeBuildDeploy - Outputs.WebAppUrl CodeBuildUrl: Description: 'Monitor the pipeline URL to see when the application has been fully built and deployed. ' Value: Fn::Sub: https://console.aws.amazon.com/codebuild/home?region=${AWS::Region}#/projects/${CodeBuildDeploy.Outputs.CodeBuildProject}/view