AWS入門ブログリレー2024〜Agents for Amazon Bedrock編〜

3日連続でお届けしている「Amazon Bedrockシリーズ入門ブログリレー」の最後のエントリです。Amazon Bedrockは奥が深いですしアップデートも早いので、しっかりキャッチアップしましょう!
2024.04.24

みなさん、こんにちは!
福岡オフィスの青柳です。

当エントリは弊社AWS事業本部による『AWS入門ブログリレー 2024』の30日目のエントリです。

このブログリレーの企画は、普段AWSサービスについて最新のネタ・深い/細かいテーマを主に書き連ねてきたメンバーの手によって、 今一度初心に返って、基本的な部分を見つめ直してみよう、解説してみようというコンセプトが含まれています。

AWSをこれから学ぼう!という方にとっては文字通りの入門記事として、またすでにAWSを活用されている方にとってもAWSサービスの再発見や2024年のサービスアップデートのキャッチアップの場となればと考えておりますので、ぜひ最後までお付合い頂ければ幸いです。

では、さっそくいってみましょう。今回のテーマは『Agents for Amazon Bedrock』です。

当記事は「2024年4月23日」時点の情報に基づき執筆しています。

また、Agents for Amazon Bedrockは記事執筆時点では以下のリージョンのみに対応しています。

  • バージニア北部リージョン (us-east-1)
  • オレゴンリージョン (us-west-2)

「Amazon Bedrock初めて」の方はまずこちら

Agents for Amazon Bedrockは、AWSの生成AIサービス「Amazon Bedrock」の拡張機能・サブ機能の一つです。

もし、まだAmazon Bedrock自体をよく理解していない・初めてという方は、まず「AWS入門ブログリレー 2024」のAmazon Bedrock関連エントリから読み進めることをオススメします。

生成AIにおける「エージェント」とは

「チャット=質問に答えてもらう」以上のことを生成AIに行わせたい

生成AIにおいて恐らく最も多い利用形態は「チャット」ではないかと思います。

膨大な情報を使って学習した言語モデルを使って、いろいろな質問に答えてもらうことができます。

  • 「予算と好みを伝えると、旅行先と旅行行程を提案してくれる」
  • 「文章を入力すると、校正した結果を返してくれる」

生成AIによって、「調べ物」や「チェック」など人間が行うと労力と時間が掛かっていた作業を、楽に速く行ってもらうことができます。

でも、人間が本当にやりたいことって、次のようなことなのではないでしょうか?

  • 「提案してもらった旅行先について、宿や交通機関の空き状況を調べて、予約まで行って欲しい」
  • 「フォルダの全ての文書ファイルから校正チェックが必要なファイルを探して、校正した内容に書き換えて欲しい」

このような作業を自動的に行なわせようとすると、従来の手法では以下のような仕組みを考えて実行する必要がありました。

  • 生成AIへ質問した回答をJSON形式などで出力してもらい、別システムへ入力して処理を行う
  • バッチ処理などの実行結果から対象物のリストを抽出して、リストの要素毎に生成AIのAPIを呼び出して処理を行う

このような手法は、他システムが処理を行えるように正確なフォーマットで生成AIに出力させたり、生成AIが理解できるような様式で処理対象リストを用意することが難しく、調整の手間が掛かってしまうことも少なくありませんでした。

自律的にタスクを処理してくれる「エージェント」

そこで登場した概念が「エージェント」です。

エージェントとは、与えたタスクや課題に対して都度 細かな指示を与えずとも、自分で「行うべき行動」を考え、実際に行動を実行し、与えられたタスクや課題を最終的に遂行/解決する能力を持たせたものです。

とは言っても、エージェントが世界のありとあらゆるタスクや課題を遂行/解決できる能力を持っている訳ではありません。

予め、与えるタスクや課題を遂行/解決するために必要な「道具」(Tool) を人間の手で用意してあげる必要があります。 エージェントは手を使って道具を使える訳ではありませんので、ここで言う「道具」は、実際には「API」や「関数」(Function) という形で用意されます。

また、エージェントが「行うべき行動」を考えるのは大規模言語モデル (LLM) を使った推論によって行いますが、「与えられた要求に対して、どのような順番で考え、情報を整理して、最終的な結論を導けばよいのか」については、人間が「指示内容」「シナリオ」として用意する必要があります。

このように、エージェントが人間の要求に対応できるようにするための「準備」が必要であるものの、一度準備してしまえば、プロンプトエンジニアリングやプログラム開発のスキルを持たない一般利用者であってもエージェントと自然言語による会話を行うことによりタスクを実行してもらうことができるという訳です。

Amazon Bedrockの拡張機能としての「エージェント」

生成AIにおける「エージェント」を実装する手法として一般的なのは、「LangChain」などのフレームワークが提供するモジュールを組み合わせてアプリケーションを開発するという方法です。

フレームワークが提供するエージェントのためのモジュールは多種多様なものが用意されており、モジュールの選定とそれらを呼び出すプログラムコード次第で柔軟な開発を行うことが可能です。

一方、AWSが提供する「Agents for Amazon Bedrock」には、以下のような特徴があります。

  • エージェントが動作する上で必要となる「推論」「ツール実行」などの処理を実装するプログラムコードを開発する必要が無く、ユーザーは「推論を行わせるためのプロンプトの記述」「実行させたいツールの準備」などに注力することができる
  • エージェントに実行させる「ツール」は、Lambda関数として実装し、AWS各サービスと容易に連係して様々な処理を行わせることができる
  • エージェントの作成や設定変更をマネジメントコンソールのGUIで簡便に行うことができる (AWS CLIなども使えます)
  • エージェントのテストを行い、タスク遂行の各ステップでの「推論」や「ツール実行」の過程をトレースして詳細に確認することができる (これもマネジメントコンソール上から行えます)
  • 作成したエージェントは、エージェント単位でAWS REST APIやAWS SDKから呼び出すことが可能であり、シンプルなプログラムコード記述でアプリケーションに組み込むことができる

Agents for Amazon Bedrockの利用イメージ

「Agents for Amazon Bedrock」の実際の利用イメージを見てみましょう。

今回は、AWSがGitHubで公開している「Amazon Bedrock Samples」のサンプルのうちの一つをAWS環境にデプロイして、動作を確認してみました。

なお、サンプルの通りにデプロイすると、英語での会話には上手く対応してくれますが、日本語での問い掛けには上手く対応してもらえませんでした。(筆者の環境では)

そこで、サンプルをベースにプロンプトやAPI定義などを日本語に書き換えたところ、なんとか日本語に対応してくれるようになりました。 ただし、使用しているデータは日本語化していないため、入力する名前が「Jane Smith」だったりする点はご了承ください。

サンプルの概要

今回使用したサンプルがどのようなものなのか、簡単に説明しましょう。

まず、エージェントに対する「タスク遂行のための指示・シナリオ」として、以下のようなテキストが与えられています。(原文は英語)

あなたは顧客の靴の購入を支援するエージェントです。
名前に基づいて顧客IDや好みのアクティビティなどの顧客の詳細を取得します。
次に、顧客の好みのアクティビティにマッチする靴に最適なアクティビティの在庫を確認します。
靴の在庫情報に基づいて、靴ID、スタイルの説明、色を含む応答を生成します。
複数のマッチが存在する場合は、それらすべてをユーザーに表示します。
顧客が靴の注文を希望したら、選択された靴IDと、最初に取得した顧客詳細の顧客IDを使って、靴を注文します。

また、タスク遂行に必要な「ツール」として、以下のようなAPIが与えられています。

  • 顧客の名前から顧客情報を取得するAPI
  • 条件に合う靴の在庫を取得するAPI
  • 靴IDと顧客IDを指定して注文を行うAPI

また、APIがアクセスする「顧客DB」や「在庫DB」などが用意されています。 (サンプルでは簡易的なDBとしてSQLiteが使用されていました)

サンプルの動作確認

サンプルのデプロイが完了しましたら、「テスト」画面からチャット入力してみます。

「靴を探しているのですが」という問い掛けに対して、エージェントは「顧客は靴の注文を希望している」「まず、顧客のIDや好みを調べる必要がある」と考え、顧客に名前を尋ねてきます。

顧客が名前を答えると、エージェントは「名前をキーにして顧客情報を取得」「顧客の好みや足のサイズに合った靴の在庫状況を調べる」と思考・行動して、得られた結果 (お勧めする靴のリスト) を顧客に提示します。

顧客が「靴ID」を指定して注文したい旨を伝えると、エージェントは「注文API」を呼び出して注文を実行します。

このように、自然な会話の流れの中で、エージェントは用意されたタスクを顧客の要望に沿った内容で実行することができる訳です。

Agents for Amazon Bedrockの構成と処理の流れ

ここからはAgents for Amazon Bedrockの中身・仕組みについて解説していきます。

Agents for Amazon Bedrockの大まかな構成と処理の流れは、下図のようになります。

この図で表される処理の流れは、ユーザーとエージェントの1回 (1往復) の会話のやり取りで発生する処理です。

エージェントがタスク遂行や課題解決を行うために会話を何往復か繰り返す場合、その都度、図のような処理が発生することになります。

繰り返される会話のやり取りでエージェントが文脈に沿った対応を行えるようにするために、エージェント内で会話履歴を記憶しています。 (この会話履歴の記憶先・保存先は外部から見えないようになっており、プロンプト内で引用することは可能ですが、会話履歴へ直接アクセスすることはできません)

エージェントの処理の流れ

エージェントの1回の処理は、大きく以下の3つのフェーズに分かれます。

  • 前処理
  • オーケストレーション
  • 後処理

前処理

「前処理」フェーズは、エージェントの処理の本体である「オーケストレーション」を行う前に、ユーザーの入力内容をチェックする役割を持ちます。

デフォルトの動作では、以下のようなチェックを行います。

・倫理観点のチェック
・倫理的に問題のある内容でないかどうか
・悪意や攻撃のチェック
・エージェントの内部ロジックを調べようとする指示でないかどうか
・エージェントの対応可能範囲かチェック
・エージェントが実行可能なアクションや検索可能なナレッジベースの範囲で対応できる内容かどうか

もし、チェックの結果「受付不可」と判断された場合は、「オーケストレーション」フェーズに進まずに、「後処理」フェーズのみ実行して処理を終了します。

オーケストレーション

「オーケストレーション」フェーズでは、タスクや課題の遂行/解決に必要な数々の処理ステップを実行します。

デフォルトの動作では、以下のような処理を行います。

・ユーザーの要求を満たすために何をすればよいか考える
・実行できるアクションを使えば要求は満たせるか?
・検索可能なナレッジベースを使って調べれば要求は満たせるか?
・考えた結果に基づいて行動を行う
・アクションを実行して結果を得る
・ナレッジベースを検索して結果を得る
・得られた結果からユーザーへの回答を生成する

これらの処理は、一度に行うのではなく、オーケストレーションの1ステップにつき上記うちの1つの処理を行います。

1ステップの処理を行った後、終了判定を行います。

ユーザーに提示できる回答がまだ得られていない場合は、再度オーケストレーションの処理を行い、次に行うべき「推論」「行動」をエージェントが考えます。

回答が得られた場合、あるいは、これ以上先に進むためにはユーザーの追加入力が必要と判断した場合は、オーケストレーションの処理を終了して「後処理」フェーズへ進みます。

後処理

「後処理」フェーズは、「オーケストレーション」フェーズの出力結果を最終的に補正する役割を持ちます。

デフォルトの動作では、以下のような処理を行います。 (なお、デフォルト設定では「後処理」自体が無効になっており、以下は後処理を有効にした場合のデフォルト処理の内容です)

・悪意や攻撃からの防御
・エージェントの内部ロジックが明らかになってしまう内容があれば、補正する
・これまでの会話履歴との整合性
・過去の会話履歴を踏まえた回答内容にする

こうして「後処理」が行われた結果の出力が、最終的な回答としてユーザーへ提示されます。

エージェントの構成要素/設定項目

エージェントの構成要素あるいは設定項目を以下に列挙します。(細かな設定項目は省略しています)

構成要素/設定項目 概要
エージェントリソースロール エージェントに割り当てられるIAMロール (AWSサービスロール)
(必須設定)
基礎モデルの指定 エージェントが推論や回答生成を行う時に使用するモデルの指定
(必須設定)
エージェントへの「指示」 エージェントがタスク遂行や課題解決を行うための指示を記述したテキスト
(必須設定)
アクショングループの定義 タスク遂行/課題解決のために実行するアクション群の定義
(オプションだが、実質的に必須)
ナレッジベースの関連付け タスク遂行/課題解決のために参照するナレッジベースの指定
(オプション)
詳細プロンプト エージェントの推論・回答生成などの動作を決定する設定群
(デフォルトのまま利用 or カスタマイズして利用)

エージェントリソースロール

エージェントに割り当てるIAMロール (AWSサービスロール) です。

IAMロールにアタッチした許可ポリシーによって、エージェントが他のAWSリソースを使用するために必要となるアクセス権限を設定します。

例えば、以下のようなアクセス権限を設定します。

  • 基礎モデルを呼び出すためのアクセス権限 (bedrock:InvokeModel)
  • ナレッジベースを検索するためのアクセス権限 (bedrock:Retrieve)
  • S3に格納した「OpenAPIスキーマ」を参照するためのアクセス権限 (s3:GetObject) (※)

(※ OpenAPIスキーマについては、後ほど「アクショングループ」の項目で説明します)

許可ポリシーの定義方法の詳細は、下記ドキュメントページを参照してください。
Create a service role for Agents for Amazon Bedrock - Amazon Bedrock

なお、後述する「アクショングループ」を定義する場合、アクションの実装であるLambda関数を呼び出すためのアクセス権限は「エージェントリソースロール」では管理せず、Lambda関数の「リソースベースポリシー」で設定します。 (詳細は「アクショングループの定義方法」の項目で説明します)

基礎モデルの指定

エージェントが推論や回答生成を行う時に使用するモデルを指定します。

処理ステップ毎に別々のモデルを指定するようなことはできず、一律で同じモデルが使用されます。

記事執筆時点 (2024/04/23) では、以下の基礎モデルが選択可能です。

  • Anthropic Claude Instant v1
  • Anthropic Claude v2.0
  • Anthropic Claude v2.1
  • Anthropic Claude 3 Sonnet v1 (2024/04/23に追加)
  • Anthropic Claude 3 Haiku v1 (2024/04/23に追加)

最新のサポート対象モデルは、AWS公式ドキュメントで確認してください。
Supported regions and models for Agents for Amazon Bedrock - Amazon Bedrock

エージェントへの「指示」

エージェントがタスク遂行や課題解決を行うための指示を記述します。

形式はプレーンテキストで、文字数は40〜1200文字に収める必要があります。

例えば、以下のようなテキストになります。(Amazon Bedrock Samplesに用意されているサンプルから引用・再掲)

あなたは顧客の靴の購入を支援するエージェントです。
名前に基づいて顧客IDや好みのアクティビティなどの顧客の詳細を取得します。
次に、顧客の好みのアクティビティにマッチする靴に最適なアクティビティの在庫を確認します。
靴の在庫情報に基づいて、靴ID、スタイルの説明、色を含む応答を生成します。
複数のマッチが存在する場合は、それらすべてをユーザーに表示します。
顧客が靴の注文を希望したら、選択された靴IDと、最初に取得した顧客詳細の顧客IDを使って、靴を注文します。

アクショングループの定義

タスク遂行/課題解決のために実行するアクション群を定義します。 一つの「アクショングループ」は複数のアクション (「API」または「関数 (Function)」) で構成されます。

アクショングループの設定はオプションとなっており、デフォルトでは未設定となっています。

複数のアクショングループを登録することが可能で、最大で5個の有効化された (=利用できる状態の) アクショングループを登録することが可能です。 また、有効・無効を合わせて最大20個のアクショングループを登録することができます。

アクショングループの定義は、以下の要素で構成されます。

・Lambda関数
・アクションの動作を実装する
・簡易スキーマ/OpenAPIスキーマ
・アクションが何をできるかの説明や、入出力パラメーターの仕様を記述する

Lambda関数は言ってみれば「アクションの実体」であり、具体的に処理させたい内容をコードで実装します。

一方、簡易スキーマ/OpenAPIスキーマは「エージェントがアクションの仕様を理解して、必要な時に実行を選択することができる」ようにするためのものです。

エージェントは、ユーザーから与えられたタスクや課題を遂行/解決するための「行うべき行動」を推論する際に、アクショングループの定義を参照して「どのアクショングループ・アクションを使うべきか、どのようなパラメーターを与えればよいか」を考えた上で、アクションを実行します。

アクショングループの定義方法の詳細については、後ほど「アクショングループの定義方法」の項目で解説します。

ナレッジベースの関連付け

タスク遂行/課題解決のために参照するナレッジベースを指定します。

ナレッジベースの設定はオプションとなっており、デフォルトでは未設定となっています。

複数のナレッジベースを関連付けることが可能で、最大で2つまでのナレッジベースを指定することができます。

指定できるナレッジベースは、エージェントと同じAWSアカウント・リージョンで作成した「Knowledge bases for Amazon Bedrock」のナレッジベースです。

「Knowledge bases for Amazon Bedrock」の詳細は、下記ブログ記事を参照してください。

詳細プロンプト

「詳細プロンプト」の設定画面では、エージェントの推論・回答生成などの動作を決定する詳細な設定群が用意されています。

通常の利用では設定を変更する必要はありませんが、エージェントの動作を詳細にカスタマイズしたい場合は、ここから設定を行います。

詳細プロンプトの設定対象は、以下の4つあります。

  • 前処理
  • オーケストレーション
  • ナレッジベースの回答生成
  • 後処理

「前処理」「オーケストレーション」「後処理」は、「エージェントの処理の流れ」で説明した各フェーズに該当します。

「ナレッジベースの回答生成」は、エージェントがタスクや課題の遂行/解決のためにナレッジベースを検索した際、検索結果から回答を生成する処理のことを指します。 (いわゆる「RAG」(Retrieval-Augmented Generation) の「G」(Generation) にあたる処理)

詳細プロンプトの設定項目には、以下のものがあります。

・プロンプトテンプレート
・エージェントが基礎モデルを使って処理を行う際の詳細な指示を記述します
・基礎モデルの設定
・「Temperature」「Top-P」「TopK」などのパラメーターを調整します
・パーサーLambda関数
・基礎モデルによる処理結果を入力して、チェック・補正・整形などの処理を行います

例えば、「前処理」のプロンプトテンプレートには、ユーザーの入力内容をチェックするための具体的な指示内容が記述されています。

詳細プロンプトのカスタマイズは、各設定対象 (「前処理」「オーケストレーション」etc.) 毎に個別に行うことができます。

カスタマイズを行うには、詳細プロンプトの「上書き」スイッチをオンにします。 これによって、デフォルトの設定の代わりにカスタマイズした設定が適用されます。

カスタマイズを行うにあたっては、エージェントの処理方式についての深い理解と、プロンプトテンプレートやパーサーLambda関数の仕様の把握が必要となります。 難易度は高いと思いますので、最初はデフォルト状態で利用することをお勧めします。

設定方法の詳細は公式ドキュメントを参照してください。
Advanced prompts in Amazon Bedrock - Amazon Bedrock

アクショングループの定義方法

「エージェントの構成要素/設定項目」にてアクショングループの概要を説明しましたが、もう少し詳しく解説したいと思います。

アクショングループの定義方法には、大きく次の2通りの方法があります。

  • 「簡易スキーマ」と「Lambda関数」の組み合わせによる定義
  • 「OpenAPIスキーマ」と「Lambda関数」の組み合わせによる定義

なお、「簡易スキーマ」による定義方法は、本日 (2024/04/23) に新機能としてサービスアップデートが公開されたものです。
Agents for Amazon Bedrock: Introducing a simplified creation and configuration experience | AWS News Blog

簡易スキーマによる定義

以下のようなJSON形式で「関数 (Function) の名前」「説明」「パラメーター」の定義を記述します。

{
  "name": "GetCustomerInfo",
  "description": "",
  "parameters": [
    {
      "name": "CustomerName",
      "description": "Customer's name",
      "required": "True",
      "type": "String",
      "tableIndex": 0
    },
    {
      "name": "CustomerAddress",
      "description": "Customer's address",
      "required": "False",
      "type": "String",
      "tableIndex": 1
    }
  ]
}

JSONによる記述の他に、GUIでの設定にも対応しています。

1つのアクショングループに対して、最大で3つの「関数」(Function) を定義することができます。 1つの関数は「顧客情報の取得」など1つの機能に相当します。

※ 記事執筆時点 (2024/04/23) では、AWS公式ドキュメントに「簡易スキーマによる定義」のページがまだ用意されていないようです。

OpenAPIスキーマによる定義

OpenAPI形式で「API操作」の定義を記述します。 (「Swagger」と言った方が通りが良いかもしれません)

OpenAPIスキーマは、YAML形式またはJSON形式で記述できます。 (以下はYAML形式で記述した例です)

openapi: 3.0.0
info:
  title: Insurance Claims Automation API
  version: 1.0.0
  description: APIs for managing insurance claims by pulling a list of open claims, identifying outstanding paperwork for each claim, and sending reminders to policy holders.
paths:
  /claims:
    get:
      summary: Get a list of all open claims
      description: Get the list of all open insurance claims. Return all the open claimIds.
      operationId: getAllOpenClaims
      responses:
        "200":
          description: Gets the list of all open insurance claims for policy holders
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    claimId:
                      type: string
                      description: Unique ID of the claim.
・・・

OpenAPIスキーマには最大5つのAPI操作を含めることができます。

例えば上記のOpenAPIスキーマの例ですと、パス/claimsに対するgetのAPI操作について記述されています。 同様のAPI操作が5つまで記述できるということです。

マネジメントコンソールではGUIによるスキーマ記述のUIは提供されていませんが、一般的なSwagger Editorを使って作成したOpenAPIスキーマのYAML/JSONファイルをS3経由でインポートすることが可能です。

OpenAPIスキーマの定義方法については、AWS公式ドキュメントページを参照してください。
Define OpenAPI schemas for your agent's action groups in Amazon Bedrock - Amazon Bedrock

Lambda関数

「簡易スキーマによる定義」「OpenAPIスキーマによる定義」どちらの場合であっても、1つのアクショングループで定義できるLamda関数は1つのみです。

1つのLambda関数の中に、複数の「Function」あるいは「API」の実行コードを記述することになります。

例えば「データベースの参照や更新」「社内システムとの連係」「インターネット経由でSaaSやAPIサービスへのアクセス」など、Lamda関数コードの記述次第で、さまざまな処理を行わせることができます。

コード記述の際の注意点として、Lambda関数の入力 (イベント構造体) および出力 (戻り値) の仕様は厳密に決められており、仕様通りにコードを記述しなければ、アクショングループは正しく動作しません。

Lambda関数のコード記述方法については、AWS公式ドキュメントページを参照してください。
Define Lambda functions for your agent's action groups in Amazon Bedrock - Amazon Bedrock

なお、エージェントがアクショングループで定義したLambda関数を呼び出せるようにするためには、Lambda関数の「リソースベースポリシー」を設定する必要があります。

リソースベースポリシーの設定方法については、AWS公式ドキュメントページを参照してください。
Resource-based policy to allow Amazon Bedrock to invoke an action group Lambda function

アプリケーションからのエージェントの利用

作成した「Agents for Amazon Bedrock」のエージェントは、マネジメントコンソールから「テスト」としてチャットの動作を確認することができます。

一方、実際のアプリケーションに「エージェント」を組み込んで利用する際には、AWS APIやAWS SDKを用いてプログラムを開発する必要があります。

作成したエージェントを呼び出すAPIとしてInvokeAgentが用意されています。

今回は、具体的なアプリケーションの開発方法については解説しませんが、AWS API/AWS SDKの利用方法については下記のリファレンスを参照してください。

InvokeAgent - Amazon Bedrock

AgentsforBedrockRuntime - Boto3 1.34.89 documentation

おわりに

以上、『AWS 入門ブログリレー 2024』の30日目のエントリ『Agents for Amazon Bedrock』編でした。

Amazon Bedrockは、使用できるモデルの追加や、各種機能の新規追加・アップデートが頻繁に行われています。 (当ブログの執筆中にも、Agents for Amazon Bedrockの複数のアップデートがリリースされて、チェックするのが大変でした)

3日間に渡ってお届けした「Amazon Bedrockシリーズ入門ブログリレー」で、Amazon Bedrockの基礎と最新アップデートを是非キャッチアップしてください。

次回、4月24日は弊社川原征大による「AWS Config編」です!