はじめに
AWS re:Invent 2023 でGAとなったKnowledge Bases for Amazon BedrockとAgents for Amazon Bedrockを使用するとS3バケットに配置したオブジェクトを対象としたRAGが簡単に構築できるということで、試してみました。Bedrockのコンソールで試すだけでなく、Agents for Amazon Bedrock(以下、Agents)をチャットボットで呼び出すSlack Appも作ってみました。
本記事では、Vector storeにPinecone(Free Plan)を使用します。Knowledge Bases for Amazon Bedrock(以下、knowledge base)のVectore database作成画面ではデフォルトでOpenSearch ServerlessにVector storeが構築される流れになっていますが、時間単位の課金で思わぬ費用が発生しないようPineconeを選択しました。
今回は、FIAとJAFモータースポーツのサイトで公開されているF1世界選手権の技術規則書と競技規則書をもとにRAGを作成し、F1のレギュレーションについて応答するチャットボットを作成します。
デモ画面
Agentsのレスポンスに参照ファイルのパスと参照箇所が含まれていれば、それらも出力できます。もちろん、会話の履歴を踏まえた回答が得られます。
参照元に同じ内容が2回出力されていますが、おそらく参照した2箇所が含まれる広い範囲をレスポンスしているためこのようになっているのだと思います。
(ボットの名前にbacklogと入っていますが、今回はbacklogは関係ありません。)
構成図
- PDFなどのファイルをS3バケットにアップロード
- knowledge baseが埋め込みを作成し、Pineconeに登録/更新
- SlackからのクエリをAgentsが受け取る
- Agentsはknowledge baseと対話し、クエリを送る。
- knowledge baseはクエリに応じて意味的に最も関連性の高いコンテンツをPineconeから取得しAgentsに返す
- クエリの結果をSlackに返す
参考情報
前提条件
- 以下のリソースを作成・削除・変更できる権限をもつAWSユーザーを利用すること
- AWS IAM
- AWS Lambda
- AWS CloudFormation
- AWS Secrets Manager
- Amazon API Gateway
- Amazon S3
- Amazon CloudWatch Logs
- Amazon Bedrock
- 使用するAWSリージョンは、us-east-1 (記事執筆時点でknowledge baseとAgentsが利用可能なリージョンがus-east-1,us-west-2のみのため)
- Slack Appを作成するためのアカウントや権限を持っている
- Pineconeにサインイン可能なアカウント(Google, Github, Microsoftのいずれか)を持っている
環境構築
以降の手順は、Pinecone as a Knowledge Base for Amazon Bedrockの記事を参考にしました。記事に書かれている手順に従って進めていきます。
PineconeのサインアップとIndexの作成
Pineconeのサイトにアクセスし、Get Started
(もしくは画面右上の Sign Up Free
)からアカウント作成画面に進みます。
Google, Github, Microsoftのいずれかのアカウントでログインします。もしくは、メールアドレスを入力しアカウントを作成します。
質問に回答しサインアップを完了させます。どれを選択してもよいと思いますが、今回は以下のとおり選択しました。
質問 | 回答 |
---|---|
Waht is your goal? | Personal Lerning and development |
What are you making? | Chatbot application |
What is your preferred coding launguage? | Pyhon |
Create IndexをクリックしてIndexを作成します。
入力/選択項目 | 内容 |
---|---|
Name | 任意のIndex名。 使用可能な文字は小文字、数字、ハイフンのみ |
Dimensions | 1536 |
Metric | cosine |
Pod Type | starter |
後ほど作成するknowledge baseの埋め込みモデルTitan Embeddings G1 - Text v1.2
が1536次元のため、Indexを1536次元で作成します。Pod Typeは、Free Planではstarterのみ選択可能です。Free Planは作成可能なIndex数が1個なので、別のIndexを作成する場合は既存のものを削除するか上位プランの契約が必要です。
Indexの作成が完了すると、このようにIndexes画面にHOSTアドレスが、API Keys画面にAPIキーが表示されます。Environmentがawsではなくgcpとなっていますが、Free Planではこの選択しかできません。HOSTアドレスとAPIキーがあればknowledge baseから接続できるので、Environmentは気にしなくてよさそうです。
HOSTアドレスは後ほど作成するknowledge baseの設定で使用します。
PineconeのAPI KeyをSecrets Managerに登録
AWS Secrets Managerを開き、シークレットの登録を行います。
入力/選択項目 | 内容 |
---|---|
シークレットのタイプ | その他のシークレットのタイプ |
キー | apiKey |
値 | PineconeのAPIキー |
シークレットの名前と説明を入力します。
ローテーションの設定はすべてデフォルトのままにします。
シークレットの作成が完了すると、Secret ARNが発行されます。
Secret ARNは後ほど作成するknowledge baseの設定で使用します。
Bedrock環境構築
Knowledge Bases for Amazon Bedrock
ファイルをS3バケットにアップロード
任意のS3バケットにファイルをアップロードします。knowledge baseをus-east-1に作成するためリージョン間の通信費用を考慮し、S3バケットのリージョンもus-east-1としたほうが良いと思います。
knowledge baseがサポートするファイルフォーマットは、Set up your data for ingestionに記載されています。
引用すると以下のとおりです。また、1ファイルあたりの最大ファイルサイズは50MBです。
- Plain text (.txt)
- Markdown (.md)
- HyperText Markup Language (.html)
- Microsoft Word document (.doc/.docx)
- Comma-separated values (.csv)
- Microsoft Excel spreadsheet (.xls/.xlsx)
- Portable Document Format (.pdf)
ここでは、JAFモータースポーツのサイト内の国際モータースポーツ諸規則などで公開されているFIAレース世界選手権等規則書のなかから2023年競技規則_日本語版_20230425
と2023年技術規則_日本語版_20230425
の2つのPDFファイルを、FIAのサイト内のREGULATIONSで公開されているFIA FORMULA ONE WORLD CHAMPIONSHIPのドキュメントのなかからFIA 2023 Formula 1 Sporting Regulations - Issue 8 - 2023-12-06
とFIA 2023 Formula 1 Technical Regulations - Issue 7 - 2023-08-31
をそれぞれS3バケットにアップロードしています。
knowledge baseを作成
knowledge baseを開き、knowledge baseを作成します。
入力/選択項目 | 内容 |
---|---|
Knowledge base name | 任意のknowledge base名 |
Runtime role | Create and use a new service role |
ロールは新規に作成します。以前に作成したknowledge baseのロールが存在していても、Use an existing service roleで既存のロールが選択肢に表示されませんでした。
データソースとして、ファイルをアップロードしたS3バケットを指定します。
入力/選択項目 | 内容 |
---|---|
Data source name | 任意のデータソース名 |
S3 URI | S3バケットのURI |
Chunking strategy | Default chunking |
S3バケットのURIは、直接URIを入力するか、Browse S3
をクリックしてバケット一覧からバケットを選択することで入力できます。
Chunking strategyは、チャンク分割の設定を選択します。knowledge base作成後に設定を変更することができないため、この時点で選択が必要です。それぞれどのように分割するのかはプルダウンメニュー内に記載されています。また、Set up your data for ingestionにも記載があります。
Vectore storeの設定
つづいて、Vector storeを設定します。
埋め込みモデルは、Titan Embeddings G1 - Text v1.2
のみ利用可能です。PineconeのIndexを作成する際に設定した Dimensions: 1536 はここに明記されています。
入力/選択項目 | 内容 |
---|---|
Select how you want to create your vector store | Choose a vector store you have created |
Select an existing database | Pinecone |
By selecting "Pinecone"... | ✓ |
Connection String | PineconeのIndexのHOSTアドレス |
Credentials secret ARN | PineconeのAPIキーを登録したSecretsのARN |
Text field | Vector databaseのテキストフィールドの任意の名前。 text など |
Bedrock-managed metadata field | Vector databaseのメタデータフィールドの任意の名前。 metadata など |
By selecting "Pinecone"... の項目は、AWSがユーザーに代わってサードバーティーのソースにアクセスすることを許可することに同意する旨が書かれています。
knowledge baseは作成されましたが、まだS3バケットのデータはPineconeに登録されていません。作成したknowledge baseのData Sourceの項目に移動し、Sync
ボタンをクリックします。S3バケット内のデータに追加/更新があった場合も同様にSyncを実行します。
Statusが Ready となれば完了です。PineconeのIndex画面にアクセスすると、このようにデータが登録されていることが分かります。
Agents for Amazon Bedrock
Agentsの設定
Agentsを開き、Agentを作成します。
入力/選択項目 | 内容 |
---|---|
Agent name | 任意のAgents名 |
Agent description | Agentsの説明文 |
User Input | Yes |
IAM Permissins | 新規にロールを作成する場合は、Create and use a new service role。既存のロールを利用する場合は Use an existing service role |
Idle session timeout | 30 Minutes |
"User Input" は、Agentsが回答するための十分な情報がない場合に、ユーザーに追加の情報を求めることができるかを選択します。Yes,Noのどちらを選択しても良いのですが、Yesのほうが会話らしくなると思います。
"Idle session timeout"は、入力が何もない状態でセッションを維持する時間。セッションが有効な間であれば、以前の会話履歴を引き継いで会話を続けることができます。
Agentsが使用する言語モデルを選択します。記事執筆時点では、Anthropic社の"Claude instant V1","Claude instant V2", "Claude instant V2.1"のみが選択可能です。
"Amazon Titan Express"というモデルが近々公開されるようです。
"Instructions for the Agent"には、エージェントが実行するタスクについて明確かつ具体的な指示を入力します。スタイルやトーンを指示することも可能なので、特定の口調や語尾で会話するように指示することができるようです。
Add Action groupsの設定はスキップします。APIスキーマとそれを処理するLambda関数を指定することでOpenAI APIのFunction Callingと同じようなことが実現できるようです。
Agentsが連携するknowledge baseを選択し、それをいつ使用するのかどういった情報が含まれているのかをAgentsに伝えるための指示を入力します。
入力/選択項目 | 内容 |
---|---|
Select knowledge base | 先ほど作成したknowledge baseを選択 |
knowledge base instructions for Agent | Agentsがknowledge baseと対話する際の指示を定義 |
今回の例では使用するknowledge baseはひとつだけですが、Add another knowledge baseを操作することで複数のknowledge baseをひとつのAgentsに紐付けることができます。
Agentsの設定が完了すると、概要がこのように表示されます。APIからAgentsを呼び出す際にID
を使用します。 AgentsのIDは後述のSecret Managerのシークレット登録に使用します。
右上のEditからAgentsの設定を変更することができます。
Agentsの動作確認
画面右にあるTest playgroundを使用すると、Agentsとのチャットを試す事ができます。この例では、S3バケットに置いたPDFドキュメントの内容について質問し、Agentsが応答しています。"もう少し詳細に説明してください。"という問い合わせに対して、会話履歴を踏まえた応答が得られました。
Agents エイリアスの作成
AgentsをAPIから呼び出す際は、Agents本体ではなくエイリアスを使用します。そこで、Agentsに対するエイリアスを作成します。
右上のCreateから新規作成画面に進みます。
エイリアスの情報を入力します。
入力/選択項目 | 内容 |
---|---|
Alias name | 任意のエイリアス名 |
Description | エイリアスの説明文 |
Create a new version and associate it to this alias. / Use an existing version to associate this alias. | エイリアスを新しいバージョンと既存バージョンのどちらに紐付けるか |
エイリアスを作成すると、バージョンとともに以下のようにリストが表示されます。APIからAgentsを呼び出す際にAlias ID
を使用します。 Alias IDは後述のSecret Managerのシークレット登録に使用します。
knowledge baseの設定変更は、Working draftの項目から行えます。なかでもAdvanced promptsでは、言語モデルに対して前処理や後処理の詳細な指示テンプレートを上書き/拡張できます。
設定を変更した際はplaygroundで動作確認が行ったあと、エイリアスを作成します。
開発環境構築
作業環境のOSバージョン
Windows 11上のWSLでUbuntu 23.04を動かしています。
$ cat /etc/os-release | grep PRETTY_NAME
PRETTY_NAME="Ubuntu 23.04"
Python環境
$ python3 --version
Python 3.11.6
$ python3 -m venv .venv
source .venv/bin/activate
$ pip3 install --upgrade pip
$ pip3 --version
pip 23.3.1 from /home/xxx/.venv/lib/python3.11/site-packages/pip (python 3.11)
AWS環境構築
aws configureコマンドでデフォルトのリージョンやクレデンシャルを設定するか、もしくは~/.aws/configや~/.aws/credentialsを用意します。
AWS SAM CLIインストール
AWS上でサーバーレスアプリケーションを構築、実行するAWS SAMを使用します。
Installing the AWS SAM CLI の手順に従い、AWS SAM CLIをインストールします。今回はx86_64環境でLinux OSを使用するため、x86_64 - command line installerの手順を実行します。
$ sam --version
SAM CLI, version 1.107.0
version 1.104.0 ~ 1.106.0ではビルド時に不必要なWarningメッセージが出力されるため修正パッチが適用された1.107.0を使用します。
Slack Appの作成
Slac APIを開き、From scratchからSlack Appを作成します。ここでは、App Nameをaws-sam-bedrock-slack-rag
とします。
Basic Information画面のApp Credentialsに表示されているクレデンシャルはSlackSigningSecret
として次のSecret Managerのシークレット登録に使用します。
OAuth & Permissions画面のOAuth Tokens for Your WorkspaceにあるBot User OAuth Tokenは、SlackBotToken
として次のSecret Managerのシークレット登録に使用します。
OAuth & Permissions画面のBot Token Scopesにapp_mentions:readとchat:writeを追加します。
シークレット情報をSecret Managerに登録
あらたにシークレットを作成し、ここまでの手順で作成した以下のシークレット情報を登録します。
シークレットキー | 値 |
---|---|
SlackSigningSecret | 前項のSlackのSigning Secret |
SlackBotToken | 前項のSlackのBot User OAuth Token |
BedrockAgentId | AgentsのID |
BedrockAgentAliasId | AgentsのエイリアスID |
アプリケーションの構築
ディレクトリ構造は以下のとおりです。
.
├── bedrock_slack_rag_app
│ ├── __init__.py
│ ├── app.py
│ └── requirements.txt
├── samconfig.toml
└── template.yaml
__init__.py
は空のファイルです。
requirements.txtは以下のとおりです。
slack-bolt
slack-sdk
boto3
template.yaml (長いので折りたたんでいます。クリックして展開)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Slack Bedrock Assitant.
Resources:
BedrockAssitantFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: bedrock_slack_rag_app/
Handler: app.lambda_handler
Runtime: python3.11
Role: !GetAtt LambdaRole.Arn
Timeout: 300
MemorySize: 384
Architectures:
- x86_64
Environment:
Variables:
SECRET_NAME: 'Bedrock-sam-secrets' # Name of the secret in Secrets Manager
REGION_NAME: 'us-east-1' # Region of the secret in Secrets Manager
Events:
Slack:
Type: Api
Properties:
Method: POST
Path: /slack/events
Layers:
# https://docs.aws.amazon.com/systems-manager/latest/userguide/ps-integration-lambda-extensions.html#ps-integration-lambda-extensions-add
- arn:aws:lambda:us-east-1:177933569100:layer:AWS-Parameters-and-Secrets-Lambda-Extension:11
LambdaRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: bedrock-slack-rag-app-lambda-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: allow-lambda-invocation
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- lambda:InvokeFunction
- lambda:InvokeAsync
Resource: "*"
- PolicyName: SecretsManagerPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: 'secretsmanager:GetSecretValue' # Required for Lambda to retrieve the secret
Resource: "*"
- PolicyName: allow-bedrock-access
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- bedrock:InvokeModel
- bedrock:InvokeModelWithResponseStream
Resource: "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-v2"
- PolicyName: allow-bedrock-agent-access
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- bedrock:InvokeAgent
Resource: "*"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
BacklogAssitantLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${BedrockAssitantFunction}
RetentionInDays: 14 # Optional. Default retention is 30 days.
Outputs:
BedrockAssitantApi:
Description: "The URL of Slack Event Subscriptions"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/slack/events"
BedrockAssitantFunction:
Description: "Bedrock Assistant Lambda Function ARN"
Value: !GetAtt BedrockAssitantFunction.Arn
BedrockAssitantFunctionIamRole:
Description: "Implicit IAM Role created for Bedrock Assistant function"
Value: !GetAtt LambdaRole.Arn
AWS SAM テンプレートファイル(template.yaml)に、作成するAWSリソースを定義します。Lambda関数用ロールやLambdaの環境変数、API Gatewayの設定が含まれます。
Lambda関数からSecrets ManagerにアクセスするためにはAWSレイヤーが必要で、手動で追加する場合は以下の画面でAWS-Parameters-and-Secrets-Lambda-Extension
を選択し、バージョンは11とします(11以外に選択肢がない)。
template.ymlで定義する場合は、LayersにAWS Parameters and Secrets Lambda ExtensionのARNを設定します。ARNは、以下のドキュメントに記載されています。
ほかにも、LambdaからBedrockやSecrets Managerを扱うためのポリシー設定を行っています。EnvironmentにあるSECRET_NAME
とREGION_NAME
にはそれぞれ先ほど作成したSecrets Managerのシークレットの名前とリージョンを設定します。IAMポリシーの定義においてResource: "*"
としていますが、本番環境などでは許可するリソースを特定したほうがよいでしょう。例えば、AgentsのResourceを特定する場合は以下のように指定します。
Resource: "arn:aws:bedrock:{Region}:{AWS Account ID}:agent-alias/{Agents ID}/{Agents Alias}"
samconfig.toml (長いので折りたたんでいます。クリックして展開)
# More information about the configuration file can be found here:
# https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
version = 0.1
[default]
[default.global.parameters]
stack_name = "bedrock-slack-rag-app"
[default.build.parameters]
cached = true
parallel = true
[default.validate.parameters]
lint = true
[default.deploy.parameters]
capabilities = "CAPABILITY_NAMED_IAM"
confirm_changeset = true
resolve_s3 = true
region = "us-east-1"
[default.package.parameters]
resolve_s3 = true
[default.sync.parameters]
watch = true
[default.local_start_api.parameters]
warm_containers = "EAGER"
[default.local_start_lambda.parameters]
warm_containers = "EAGER"
SAM CLIの実行設定ファイル(samconfig.toml)に、SAM CLIを実行する際の設定を定義します。AWS SAMのチュートリアル: Hello World アプリケーションのデプロイを実行した際に作成されるsamconfig.tomlをもとにしています。今回の例では、以下の点を変更しています。
-
[default.global.parameters]
セクションのstack_nameを"sam-app"から"bedrock-slack-rag-appt"に変更 -
[default.deploy.parameters]
セクションにregion指定を追加 -
[default.deploy.parameters]
セクションのcapabilitiesを"CAPABILITY_IAM"から"CAPABILITY_NAMED_IAM"に変更
app.py (長いので折りたたんでいます。クリックして展開)
import ast
import json
import logging
import os
import re
import boto3
from botocore.config import Config
from botocore.exceptions import ClientError
from slack_bolt import App
from slack_bolt.adapter.aws_lambda import SlackRequestHandler
SlackRequestHandler.clear_all_log_handlers()
logging.basicConfig(
format="%(asctime)s [%(levelname)s] %(message)s",
level=logging.INFO
)
logger = logging.getLogger(__name__)
class SecretsManager:
def __init__(self, secret_name, region_name):
self.secret_name = secret_name
self.region_name = region_name
self.client = boto3.client(
service_name='secretsmanager',
region_name=region_name
)
def get_secret(self, key):
try:
get_secret_value_response = self.client.get_secret_value(
SecretId=self.secret_name
)
except ClientError as e:
raise e
secret_data = get_secret_value_response['SecretString']
secret = ast.literal_eval(secret_data)
return secret[key]
secrets_manager = SecretsManager(
secret_name=os.environ.get("SECRET_NAME"),
region_name=os.environ.get("REGION_NAME")
)
app = App(
signing_secret=secrets_manager.get_secret("SlackSigningSecret"),
token=secrets_manager.get_secret("SlackBotToken"),
process_before_response=True,
)
def agent_client(message, session_id):
agetn_id = secrets_manager.get_secret("BedrockAgentId")
agent_alias_id = secrets_manager.get_secret("BedrockAgentAliasId")
enable_trace = False
client = boto3.client(
service_name='bedrock-agent-runtime',
region_name="us-east-1",
config=Config(
read_timeout=180,
)
)
response = client.invoke_agent(
inputText=message,
agentId=agetn_id,
agentAliasId=agent_alias_id,
sessionId=session_id,
enableTrace=enable_trace,
)
event_stream = response['completion']
data, uri, text, references = "", "", "", ""
try:
for event in event_stream:
if 'chunk' in event:
data = event['chunk']['bytes'].decode("utf-8")
# Check if 'attribution' and 'citations' exist in 'chunk'
if 'attribution' in event['chunk']:
for citation in event['chunk']['attribution']['citations']:
# Check if 'retrievedReferences' exist in 'citation'
if 'retrievedReferences' in citation:
for refs in citation['retrievedReferences']:
if 'location' in refs:
uri = refs['location']['s3Location']['uri']
if 'content' in refs:
text = refs['content']['text']
references += uri + "\n" + text[:100].replace('\n', '') + "...\n\n"
if 'trace' in event:
logger.info(json.dumps(event['trace'], indent=2))
except Exception as e:
raise Exception("Error in processing response: ", e) from e
return data + "\n\n" + "参照元:\n" + references if references else data
def handle_app_mentions(event, say):
thread_ts = event["ts"]
userid = event["user"]
message = re.sub("<@.*>", "", event["text"])
say("\n\nお待ちください...", thread_ts=thread_ts)
if "thread_ts" in event:
thread_ts = event["thread_ts"]
response = agent_client(message, thread_ts)
say(f"<@{userid}> {response}", thread_ts=thread_ts)
def respond_to_slack_within_3_seconds(ack):
ack()
app.event("app_mention")(
ack=respond_to_slack_within_3_seconds,
lazy=[handle_app_mentions]
)
def lambda_handler(event, context):
logging.info(json.dumps(event))
retry_counts = event.get("multiValueHeaders", {}).get("X-Slack-Retry-Num", [0])
if retry_counts[0] != 0:
logging.info("Skip slack retrying(%s).", retry_counts)
return {}
slack_handler = SlackRequestHandler(app=app)
return slack_handler.handle(event, context)
ボットプログラムの本体です。Bolt for Python を使ったアプリをAWS Lambda上で動かしやすくするためのLazy Listenersを利用しています。SlackのクレデンシャルやAgentsのIDなどはSecrets Managerから取得しています。
ビルド
template.yamlがあるディレクトリで、ビルドコマンドを実行します。
$ sam build
ビルドに成功すると、以下のようなメッセージが表示されます。
Starting Build use cache
Manifest is not changed for (BedrockAssitantFunction), running incremental build
Building codeuri: /home/xxx/aws-sam-bedrock-slack-rag-app/bedrock_slack_rag_app runtime: python3.11 metadata: {} architecture:
x86_64 functions: BedrockAssitantFunction
Running PythonPipBuilder:CopySource
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {{stack-name}} --watch
[*] Deploy: sam deploy --guided
デプロイ
ビルドでエラーがなければsam deployコマンドを実行し、デプロイを行います。
$ sam deploy
デプロイが成功すると、以下のような情報がコンソールに出力されます。
CloudFormation outputs from deployed stack
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Key BedrockAssitantApi
Description The URL of Slack Event Subscriptions
Value https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/slack/events
Key BedrockAssitantFunction
Description Bedrock Assistant Lambda Function ARN
Value arn:aws:lambda:us-east-1:xxxxxxxxxxxx:function:bedrock-slack-rag-app-BedrockAssitantFunction-xxxxxxxxxxxx
Key BedrockAssitantFunctionIamRole
Description Implicit IAM Role created for Bedrock Assistant function
Value arn:aws:iam::xxxxxxxxxxxx:role/bedrock-slack-rag-app-lambda-role
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Slack Appの設定
メンションイベントに応答するために、Event Subscriptions画面のSubscribe to bot eventsにapp_mentionを追加します。
Event Subscriptions画面のEnable EventsをOnにし、Request URLにさきほど出力されたURL https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/slack/events を入力します。
Verified✓
と表示されれば、正しいURLが入力されたことになります。レスポンスが得られるようになるまで時間がかかる場合があります。正しいURLを入力しているにもかかわらずVerifiedとならない場合は、時間をおいて再試行します。
設定を追加後、画面最下部にあるSave Changesをクリックし内容を保存します。
Slack Workspaseにアプリをインストール
Install App画面のInstall to Workspaceをクリックし、Slack AppをWorkspaceにインストールします。
インストールに成功すると、Thank you!画面が表示されます。Slackアプリをインストールしている場合はclick here
のリンク、Webブラウザを使用している場合は、this link
をクリックしてSlackを開きます。
動作確認
任意のチャンネンルに、@aws-sam-bedrock-slack-rag
(Slack Appの作成時に設定した名前)を招待し、メンション形式で依頼をポストします。動作しない場合のログやOpenAI APIが返すレスポンスは CloudWatch Logs に出力されているログが参考になります。
作成したリソースの削除
最後に、作成したアプリケーションを削除する手順です。リソースを削除するには sam delete コマンドを実行します。
$ sam delete
まとめ
Knowledge Bases for Amazon BedrockとAgents for Amazon bedrock、Pineconeを使うことでRAGを手軽に構築できました。Vector Databaseを構築しAgentsで応答を試す工程まではノーコードで構築できるため、手元のPDFやWordドキュメントに対して生成AIがどのような応答を示すのか容易に試すことができます。knowledge baseにはあらかじめ前処理や後処理、応答のプロンプトが設定済みなので、複雑なプロンプトを意識しなくてよいのも利点です。もちろん、カスタマイズもできるため、より高度な利用も可能です。
少し手を加えて、S3オブジェクトの更新をトリガーにしてknowledge baseのSyncを実行するような仕組みを入れると、最新の情報に対してAgentsが応答するようなこともできそうです。
また、Agentsに対してboto3クライアントで接続できるため、既存のアプリケーションから呼び出したり、今回のようにチャットボットを作ったり用途はいろいろとありそうです。
記事執筆時点では、knowledge baseの埋め込みモデルやAgentsの言語モデルが限定されているため、日本語のドキュメントに対する応答が不自然に感じるところもありました。この点は、今後AWS側で改善されると期待しています。