简介:
小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案,帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践,并应用到自己的日常工作里。
本次介绍的是如何利用亚马逊云科技一系列热门AI和云原生服务,如Amazon Bedrock、Amazon Kendra,开发一个AI对话机器人,本文将通过真实样例和场景帮助大家0基础学会AI核心技能。本架构设计全部采用了云原生Serverless架构,提供可扩展和安全的AI解决方案。通过Amazon API Gateway、AWS Amplify和AWS Lambda将应用程序与AI模型Mistral 7B集成,并利用Amazon Titan向量模型和向量库Kendra和RAG增强对话机器人和用户交互的内容。
本方案的解决方案架构图如下:
本方案主要服务介绍:
Amazon Bedrock
Amazon Bedrock 是亚马逊云科技上的生成式AI托管平台,专为开发者打造,用于快速构建和部署AI模型。它支持多种基础模型,简化了AI应用的开发过程。Bedrock的优势在于其高度可扩展性和易用性,帮助开发者快速从概念到产品,降低AI模型的开发门槛。
Amazon Kendra
Amazon Kendra 是一款智能搜索向量库,利用机器学习技术提供精准的搜索结果。它能够集成多个数据源,提供自然语言处理功能,帮助在RAG场景下提高信息检索效率。Kendra 的优势在于其智能的语义搜索和强大的数据集成能力,为用户提供直观的搜索体验。
AWS Amplify
AWS Amplify 是一个全面的开发平台,支持Web和移动应用的构建、部署和托管。它提供了丰富的工具和服务,如认证、存储、API等,简化了应用的开发流程。Amplify 的优势在于其无缝的集成和自动化SDLC扣成能力,使开发者能够快速构建高质量的应用。
Amazon API Gateway
Amazon API Gateway 是一种托管服务,允许开发者轻松创建、发布、维护和保护API。它提供了流量控制、授权、访问控制等功能,支持RESTful和WebSocket API。API Gateway 的优势在于其高效的流量管理和安全性,适用于各种用户规模的网页应用。
Amazon Cognito
Amazon Cognito 是一款用户身份验证和管理服务,支持用户注册、登录和访问控制。它能够与社交媒体登录、企业身份验证集成,简化用户管理流程。Cognito 的优势在于其强大的安全性和可扩展性,帮助开发者轻松实现用户身份验证功能。
AWS Lambda
AWS Lambda 是一种无服务器计算服务,允许开发者在无需管理服务器(Serverless)的情况下运行代码。Lambda 自动扩展,按实际计算时间和使用的计算资源收费,支持多种编程语言。其优势在于节省运维成本、提高开发效率和灵活的扩展能力,非常适合事件驱动的应用程序。
本方案包括的内容:
使用 Amazon Kendra 为文档建立索引以实现高效检索,并通过Kendra API 进行向量检索获取相关内容。
使用 AWS Amplify 和 Amazon CloudFront 作为前端服务器,托管聊天机器人应用程序。
通过 Amazon API Gateway 调用 AWS Lambda 函数,以获取向量库检索和后端大模型推理,进行 RAG(Retrieve and Generate)和提示工程。
学习设计提示词,并利用提示词调和 Amazon Kendra API 返回的文档搜索内容调用 Amazon Bedrock 上的大模型。
项目搭建具体步骤:
1. 首先我们进入Amazon Kendra
2. 建立Index索引,用于加快搜素效率
3. 为索引起名“kendra-index”,并选择Kendra需要访问的权限,其他配置选择模型后创建索引
4.接下来我们为向量库添加数据源,点击“Add Data Source”
5. 选择S3作为数据源
6. 为数据源配置一个昵称“kendra-data-source”,并选择文档语言为英文
7. 为访问数据源配置对应IAM权限
8. 选择保存文件的S3存储桶
9. 配置读取文档并向量化的模式和频率,最后点击添加数据源
10. 接下来我们打开自己偏好的CDE,运行下述BASH脚本部署我们的前端、后端、大模型服务、向量库基础设施。
#!/bin/bash
echo "Preparing Cloud9 for project deploymnet"
sudo yum install -y jq
echo "Update node js to version 16"
source "$HOME/.nvm/nvm.sh"
nvm install 16
nvm use 16
node --version
echo "Set region"
export AWS_REGION=$(curl -s 169.254.169.254/latest/dynamic/instance-identity/document | jq -r '.region')
echo "AWS Region is $AWS_REGION"
echo "Build the backend code using sam build"
sam build
echo "Export S3 bucket name and Kendra index which are created as part of Startup CFN stack"
export S3BucketName=$(aws s3api list-buckets --query "Buckets[?contains(Name, 'kendra-docs')].Name" --output text)
export LabBucketName=$(aws s3api list-buckets --query "Buckets[?contains(Name, 'lab-code')].Name" --output text)
export KendraIndexID=$(aws kendra list-indices --query "IndexConfigurationSummaryItems[?contains(Name, 'kendra-index')].Id" --output text)
export LAMBDA_ROLE_ARN=$(aws iam list-roles --query "Roles[?contains(RoleName, 'LambdaDeploymentRole')].Arn" --output text)
export SAMStackName="sam-bedrock-stack"
echo $SAMStackName
echo "Copy toml file and replace the parameters"
cp tools/samconf.toml samconfig.toml
# Replace values in .//samconfig.toml
sed -Ei "s|<KendraIndexId>|${KendraIndexID}|g" ./samconfig.toml
sed -Ei "s|<S3BucketName>|${S3BucketName}|g" ./samconfig.toml
sed -Ei "s|<LabBucketName>|${LabBucketName}|g" ./samconfig.toml
sed -Ei "s|<SAMStackName>|${SAMStackName}|g" ./samconfig.toml
sed -Ei "s|<AWS_REGION>|${AWS_REGION}|g" ./samconfig.toml
sed -Ei "s|<LambdaRole>|${LAMBDA_ROLE_ARN}|g" samconfig.toml
echo "Deploy app with sam deploy"
sam deploy
echo "Export few more parameters"
export BedrockApiUrl=$(aws cloudformation describe-stacks --stack-name ${SAMStackName} --query "Stacks[0].Outputs[?OutputKey=='BedrockApiUrl'].OutputValue" --output text)
export UserPoolId=$(aws cognito-idp list-user-pools --query "UserPools[?contains(Name, 'ChatbotUserPool')].Id" --max-results 1 --output text)
export UserPoolClientId=$(aws cognito-idp list-user-pool-clients --user-pool-id ${UserPoolId} --query "UserPoolClients[?contains(ClientName, 'ChatbotUserPoolClient')].ClientId" --output text)
echo "Gateway endpoint: $BedrockApiUrl"
echo "Cognito user pool id: $UserPoolId"
echo "Cognito client id: $UserPoolClientId"
# Replace values in ./backend/samconfig.toml
sed -Ei "s|<ApiGatewayUrl>|${BedrockApiUrl}|g" ./frontend/src/main.js
sed -Ei "s|<CognitoUserPoolId>|${UserPoolId}|g" ./frontend/src/main.js
sed -Ei "s|<UserPoolClientId>|${UserPoolClientId}|g" ./frontend/src/main.js
#Install Ampliyfy and build frontend
echo "Install Ampliyfy and build frontend"
cd ~/environment/serverless-chatbot-code/frontend
npm i -S @vue/cli-service
npm i -g @aws-amplify/cli
npm install
npm run build
cp ~/.aws/credentials ~/.aws/config
#Amplify initialization
echo "Amplify initialization"
mv dist build
amplify init --yes
echo "Add hosting, hit enter key if it prompts for action, use default"
amplify add hosting parameters.json
echo "Publish the amplify project"
amplify publish --yes
11. 在本方案中,我们使用的是AWS SAM (Serverless Application Model)代码定义基础设施(IaC)创建云端资源。我们会在控制台中看到所有创建的资源信息,在亚马逊云科技平台上会创建对应的CloudFormation Stack堆栈,CloudFormation是亚马逊云科技的IaC服务。
12.部署成功后,该脚本会返回AI机器人服务的网页URL
13. 打开URL后,我们可以看到对话机器人的前端界面
14. 接下来我们创建一个Lambda函数,可以命名为“CognitoUserCreateFunction”,复制以下代码,利用用户管理服务Cognito创建一个网页用户
import boto3
import json
import secrets
import string
import os
REGION = os.environ['AWS_REGION']
ChatbotUserPool = os.getenv("Cognito_UserPool", None)
ChatbotUserPoolClient = os.getenv("Cognito_ClientID", None)
secrets_name = os.getenv("SECRET_ID", 'ui-credentials')
user_id = os.getenv("USER_ID", 'bedrock')
cognitoidentityserviceprovider = boto3.client('cognito-idp', region_name=REGION)
def generate_random_password(length=12):
# Define character sets
lowercase_letters = string.ascii_lowercase
uppercase_letters = string.ascii_uppercase
digits = string.digits
special_characters = '!$@'
# Ensure that the password includes at least one special character
special_char = secrets.choice(special_characters)
# Calculate the remaining length of the password
remaining_length = length - 1
# Generate the rest of the password with a mix of characters
password_characters = (
secrets.choice(lowercase_letters) +
secrets.choice(uppercase_letters) +
secrets.choice(digits) +
''.join(secrets.choice(lowercase_letters + uppercase_letters + digits + special_characters) for _ in range(remaining_length - 3))
)
# Shuffle the characters to make the password random
password_list = list(password_characters)
secrets.SystemRandom().shuffle(password_list)
shuffled_password = ''.join(password_list)
# Add the special character back at a random position
position = secrets.randbelow(length)
password = shuffled_password[:position] + special_char + shuffled_password[position:]
return password
def create_secret(password):
# Initialize the AWS Secrets Manager client
client = boto3.client('secretsmanager')
# Store the user ID and password in a dictionary
secret_data = {
'user_id': user_id,
'password': password
}
# Create or update the secret in Secrets Manager
try:
response = client.create_secret(
Name=secrets_name,
SecretString=str(secret_data)
)
print("Secret created successfully!")
except client.exceptions.ResourceExistsException:
# If the secret already exists, update it
response = client.update_secret(
SecretId=secrets_name,
SecretString=str(secret_data)
)
print("Secret updated successfully!")
def lambda_handler(event, context):
status_msg = 'SUCCESS'
try:
password = generate_random_password()
create_secret(password)
try:
cognitoidentityserviceprovider.admin_create_user(
UserPoolId = ChatbotUserPool,
Username = user_id,
UserAttributes = [
{"Name": "name", "Value": user_id}
]
)
except Exception as e1:
print('cognito user exist already')
cognitoidentityserviceprovider.admin_set_user_password(
UserPoolId = ChatbotUserPool,
Username = user_id,
Password = password,
Permanent=True
)
status_msg = 'SUCCESS'
except Exception as e:
print('Error: ' + str(e))
status_msg = 'FAILED'
print('Successfully created user')
15. 运行代码后,我们成功创建了一个新的用户“bedrock”,在secret manager密码管理服务中可以获取用户的密码
16. 利用账户和密码登录刚刚展示的对话机器人网页
17. 最后我们就可以在对话机器人中和大模型实现问答了,本场景是未使用RAG的场景
18. 再次测试RAG场景
我们为机器人首先预定义提示词
Human:You are an intelligent AI advisor, and provide answers to questions by using fact based information.
Use the following pieces of information to provide a concise answer to the question enclosed in <question> tags.
Look for the contextual information enclosed in <context> tags.
If you don't know the answer, just say that you don't know, don't try to make up an answer.
<context>{context}</context>
<question>{question}</question>
The response should be specific and use facts only.Assistant:
我们在聊天框中提问“What is federal funds rate as of April 2024?”,机器人成功从文档中提取相关信息,回复了我们的问题
以上就是在亚马逊云科技上使用大语言模型、向量库和RAG技术搭建云原生AI对话机器人的解决方案。欢迎大家关注小李哥,未来获取更多国际前沿的生成式AI开发方案。