Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions IaC/AmazonBedRock/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# AWS BedRock and LEX2 Agents

# *BTW: I am actively looking for a DevOps/Clod Engineer job. Please considering me !*



## Overview

This project demonstrates the use of Terraform to create AWS BedRock and LEX2 agents and establish communication between them.
Also, Lambda function will be envoked everytime if the LLM will faile to get the answer from the existed Knowledge Base (located on S3)
The goal is to automate the provisioning and configuration of these resources to facilitate seamless interaction.

## Prerequisites
Before you begin, ensure you have the following:
- An AWS account with appropriate permissions.
- Terraform installed on your local machine.
- AWS CLI configured with your credentials.
- Basic knowledge of Terraform and AWS services.
- The S3 bucket with some materials which Knowledge Base will use as a source (RAG)


## Project Structure
The project directory is organized as follows:

├── ai_lambda.tf
├── genai-lambda-package.zip
├── lex2-bot.tf
├── lex2-intent.tf
├── main.tf
├── outputs.tf
├── provider.tf
├── README.md
└── variables.tf
61 changes: 61 additions & 0 deletions IaC/AmazonBedRock/ai_lambda.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
locals {
ai_function_source = "./genai-lambda-package.zip"
src_bucket = "demo-kb-usw2-lex-web-ui"
}

resource "aws_s3_object" "ai_function" {
bucket = local.src_bucket
key = "${filemd5(local.ai_function_source)}.zip"
source = local.ai_function_source
}

module "ai_lambda_function" {
source = "terraform-aws-modules/lambda/aws"

function_name = "genai-demo-lambda"
description = "lambda function to interact with AI"
handler = "index.lambda_handler"
runtime = "python3.12"
timeout = "240"

publish = true
environment_variables = {
PROJECT = "vpatoka-poc",
FallbackIntent = "genai-demo-lambda"
}

create_package = false
s3_existing_package = {
bucket = local.src_bucket
key = aws_s3_object.ai_function.id
}

attach_policy_statements = true
policy_statements = {
cloud_watch = {
effect = "Allow",
actions = ["cloudwatch:PutMetricData"],
resources = ["*"]
},
lambda = {
effect = "Allow",
actions = ["lambda:InvokeFunction"],
resources = ["*"]
},
ai = {
effect = "Allow",
actions = ["bedrock:InvokeModel"],
resources = ["arn:aws:bedrock:*::foundation-model/*"]
}
}
}

# Gives an external source Lex permission to access the Lambda function.
# We need our bot to be able to invoke a lambda function when
# we attempt to fulfill our intent.
resource "aws_lambda_permission" "allow_lex" {
statement_id = "AllowExecutionFromLex"
action = "lambda:InvokeFunction"
function_name = "${module.ai_lambda_function.lambda_function_name}"
principal = "lex.amazonaws.com"
}
Binary file added IaC/AmazonBedRock/genai-lambda-package.zip
Binary file not shown.
109 changes: 109 additions & 0 deletions IaC/AmazonBedRock/lex2-bot.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
data "aws_partition" "current" {}

resource "aws_iam_role" "VladsBot" {
name = "vpatoka-ai-poc"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "lexv2.amazonaws.com"
}
},
]
})
}

resource "aws_iam_role_policy" "special_lex2_policy" {
name = "SpecialAmazoLex2Policy_${var.kb_name}"
role = aws_iam_role.VladsBot.name
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [ "iam:AttachRolePolicy", "iam:PutRolePolicy", "iam:GetRolePolicy" ]
Effect = "Allow"
Resource = "arn:${local.partition}:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexBots*"
},
{
Action = "iam:ListRoles"
Effect = "Allow"
Resource = "*"
},
{
#Sid = "Permissions to invoke Lambda
Action = "lambda:InvokeFunction"
Effect = "Allow"
Resource = "*"
},
{
#Sid = "Permissions to invoke Amazon Bedrock foundation models"
Action = "bedrock:InvokeModel"
Effect = "Allow"
#Resource = data.aws_bedrock_foundation_model.kb.model_arn
Resource = "arn:${local.partition}:bedrock:${local.region}::foundation-model/${var.response_foundation_model}"
},
{
#Sid = "Permissions to access knowledge base in Amazon Bedrock"
Action = "bedrock:Retrieve"
Effect = "Allow"
Resource = "arn:${local.partition}:bedrock:*:${local.account_id}:knowledge-base/*"
}
]
})
}

resource "aws_iam_role_policy_attachment" "VladsBot" {
role = aws_iam_role.VladsBot.name
policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/AmazonLexFullAccess"
}

resource "aws_lexv2models_bot" "VladsBot" {
name = "vpatoka-ai-poc"
idle_session_ttl_in_seconds = 300
role_arn = aws_iam_role.VladsBot.arn

data_privacy {
child_directed = false
}
}

resource "aws_lexv2models_bot_locale" "VladsBot" {
locale_id = "en_US"
bot_id = aws_lexv2models_bot.VladsBot.id
bot_version = "DRAFT"
n_lu_intent_confidence_threshold = 0.4

voice_settings {
voice_id = "Danielle"
engine = "neural"
}
}

resource "aws_lexv2models_bot_version" "VladsBot" {
bot_id = aws_lexv2models_bot.VladsBot.id
locale_specification = {
(aws_lexv2models_bot_locale.VladsBot.locale_id) = {
source_bot_version = "DRAFT"
}
}
}


/* Alternative way to create LEX v2 Bot
Another option is to use the AWS CLI in Terraform through local execution provisioners.
While this method can work effectively, it requires the AWS CLI to be installed on the host executing Terraform,
which might introduce additional dependencies.
*/

/*
resource "null_resource" "create-endpoint" {
provisioner "local-exec" {
command = " aws lexv2-models create-bot --bot-name "vpatoka-ai-poc" --role-arn <role> --data-privacy <value> --cli-input-json file://<file.json>"
}
}

*/
70 changes: 70 additions & 0 deletions IaC/AmazonBedRock/lex2-intent.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Generic Custom Intent needs to be presented
resource "aws_lexv2models_intent" "Newintent" {
bot_id = aws_lexv2models_bot.VladsBot.id
bot_version = aws_lexv2models_bot_locale.VladsBot.bot_version
name = "Newintent"
locale_id = aws_lexv2models_bot_locale.VladsBot.locale_id

#dialog_code_hook {
# enabled = true
#}

sample_utterance {
utterance = "Hello"
}
sample_utterance {
utterance = "Howdy"
}
sample_utterance {
utterance = "Hi"
}
sample_utterance {
utterance = "Bonjour"
}
}

/*
Amazon Lex V2 offers a built-in AMAZON.QnAIntent that you can add to your bot.
This intent harnesses generative AI capabilities from Amazon Bedrock by recognizing customer questions and
searching for an answer from the following knowledge stores
(for example, Can you provide me details on the baggage limits for my international flight?).
This feature reduces the need to configure questions and answers using task-oriented dialogue within Amazon Lex V2 intents.
This intent also recognizes follow-up questions
(for example, What about domestic flight?) based on the conversation history and provides the answer accordingly.
*/
#resource "aws_lexv2models_intent" "QnAIntent" {
# bot_id = aws_lexv2models_bot.VladsBot.id
# bot_version = aws_lexv2models_bot_locale.VladsBot.bot_version
# name = "QnAIntent"
# locale_id = aws_lexv2models_bot_locale.VladsBot.locale_id
#
# parent_intent_signature = "AMAZON.QnAIntent"
#
# QnAIntentConfiguration {
# dataSourceConfiguration = {
# bedrockKnowledgeStoreConfiguration = {
# "bedrockKnowledgeBaseArn" = "${aws_bedrockagent_knowledge_base.demo_kb.arn}"
# }
# }
# }
#
#}

# Update Bot with tweaked intents and alias to use Lambda
resource "null_resource" "VladsBot" {
depends_on = [aws_lexv2models_bot_version.VladsBot]

triggers = {
bot_id = aws_lexv2models_bot.VladsBot.id
locale_id = aws_lexv2models_bot_locale.VladsBot.locale_id
latest_version = aws_lexv2models_bot_version.VladsBot.bot_version
lambda_arn = "${module.ai_lambda_function.lambda_function_arn}"

always_run = timestamp()
}

provisioner "local-exec" {
#command = "./bot_update.sh ${aws_lexv2models_bot.VladsBot.id} ${aws_lexv2models_bot_locale.VladsBot.locale_id} ${aws_lexv2models_bot_version.VladsBot.bot_version} '${module.ai_lambda_function.lambda_function_arn}'"
command = "./bot_update.sh ${aws_lexv2models_bot.VladsBot.id} ${aws_lexv2models_bot_locale.VladsBot.locale_id} 'DRAFT' '${module.ai_lambda_function.lambda_function_arn}' ${aws_bedrockagent_knowledge_base.demo_kb.arn}"
}
}
Loading