この記事について

Amazon Bedrockでお馴染みの、Knowledge Base for Amazon Bedrock(以下Knowledge Baseと表記)という機能と、Agents for Amazon Bedrock(以下Agentsと表記)という機能を使用して、Streamlitと組み合わせたチャットボット構築を試してみた記事です。
前編では、Knowledge Base・Agentsの基礎的な概念やチャットボットの全体像についてお伝えしました。詳細は下記前編記事をご覧ください。

この記事についてAmazon Bedrockでお馴染みの、Knowledge Bases for Amazon Bedrock(以下Knowledge Baseと表記)という機能と、Agents for Amazon Bedrock(以下Agentsと表記)という機能を使用して、Streamlitと組み合わせたチャットボット構築を試してみた記事で...

後編である今回は、実際の構築手順について解説いたします。

前提の確認

前編の記事で解説したように、以下の要件を満たすようなチャットボットを作成します。

  • ナレッジベースのデータに関する質問は、ナレッジベースの情報に基づいて回答する
  • ナレッジベースのデータソース(S3)には、経済産業省の下記記事を格納しておく
    デジタルガバナンス・コード3.0~DX経営による企業価値向上に向けて~
    デジタルガバナンス・コード2.0
  • 特定のタスクに関する指示があれば、AgentがLambda関数のトリガーとなり、処理を行わせて回答させる
  • 今回は、「AWSの生成AIに関するニュース」に関する質問が来た際に、生成AIニュースを紹介させる
  • ナレッジベース外、かつタスクに無関係な質問や指示は、LLMのもつ一般的な知識で回答させる。
  • 例えば、単に「日本の首都はどこですか」のような、一般的な質問が来た際に、生成AIの基盤モデルの持つ知識を駆使して、回答させるということになります。

手順

※動作検証環境
Windows 10/Python3.12/Streamlit1.34.0

STEP0 Pineconeで、ベクトルインデックスを作成する

今回は、ベクトルDBとしてPineconeを使用します。Pineconeは、AWS Marketplace経由で利用することができます。(Pineconeの公式サイトから直接作成することもできますが、Marketplace経由で作成する方法について記載します。)

AWS Marketplaceにて、Pineconeを検索すると、Pinecone Vector Database - Pay As You Go Pricingというものがあるので、選択します。

その後の画面で、Subscribeボタンを押下します。

どういった形でも構いませんが、アカウント作成の必要があるため、アカウントを作成します。

アカウント作成が完了したら、画面左部のIndexsを押下し、Create indexというボタンから、indexを作成します。

Configurationの部分で、indexの次元数と、Metricを指定します。
Setup by model という部分から、任意のモデルを選択することで、自動的に選択される形となっています。今回はCohere-embed-multilingual-v3.0を選択しました。

API keysのメニューを選択し、Create API keyを押下することでAPIキーを発行できます。
任意の名前で、作成して問題ありません。今回は、testkeyという名前で作成しました。

上記が完了したら、
indexのHostのURLと、API KeyのValueをメモしておきます。
API Keyを発行したら、Secrets Managerに保存します。保存の手順の説明は省きますが、apiキーを保存した際のシークレットのARNを控えておきます。

STEP1 Knowledge Baseの設定

Bedrockのコンソールのメニューから、ナレッジベースを選択します。
まずはナレッジベースを作成します。基本的にこだわりがなければデフォルト値のままで作成で問題ないかと思います。
データソースはS3を指定します。(※Knowledge Baseでは、今の所正式版として提供されているのはS3のみであるようです)

次に、データソースの詳細を指定します。読み込み対象となるドキュメントが配置されているS3のロケーションを指定します。

ベクトルデータベースはPineconeを選択します。
Pineconeを選択する場合、エンドポイントURLと、認証情報シークレットARNを追加で入力する必要があります。
そこで、先ほどのメモが活きてきます。
先ほど控えたindexのHostのURL→エンドポイントのURL、
Secrets Managerに保存したシークレットの値が認証情報シークレットARNになります。

上記を以てKnowledge Baseの設定は完了です。

STEP2 Agentの作成

エージェントを作成から、エージェントの作成を行います。

作成が完了したらこのような画面になるかと思います。

STEP3 AgentにKnowledge Baseの追加、 Action Groupの追加

【Knowledge Baseの追加】
Agentの編集画面から、Step1で作成したKnowledge Baseの追加を行います。
その際、Knowledge base instructions for agentの部分で指示を書くことがポイントです。
ナレッジベース関する質問がされた場合は文書に基づいて回答、それ以外の場合は一般的な知識に基づき回答させる指示を与えます。

【Action Group の追加】
Action Groupの追加を行います。
Action group typeは Define with function details、Action Group InvocationはQuick create a new lambda functionを選択します。こうすることで、Agentsに実行してほしいタスクをLambdaで定義することができます。

さらに、Parametesの部分では、
※エージェントがLambda関数を使用するためにLambda関数にリソースベースのポリシーをアタッチして、エージェントがLambda関数にアクセスできるようにする必要があります。

STEP4 Lambda関数の作成

作成されたLambda関数を編集します。編集後のコードはこのような形です。
https://aws.amazon.com/jp/blogs/news/category/artificial-intelligence/generative-ai/
こちらのURLから、最新の3件の記事を取得し
「生成AI」、「Generative AI」など生成AIに関するキーワードが記事に含まれていれば抽出対象にし、レスポンスとして返却します。

import json
import requests
from bs4 import BeautifulSoup
def lambda_handler(event, context):
    url = "https://aws.amazon.com/jp/blogs/news/category/artificial-intelligence/generative-ai/"
    # HTMLを取得
    response = requests.get(url)
    soup = BeautifulSoup(response.text, "html.parser")
    keywords = ['生成AI', 'Generative AI', 'AI', '人工知能', '機械学習', '深層学習']
    articles = soup.select("article.blog-post")[:3] # 最新の3件を取得

    # 取得結果を格納する配列
    result = []

    # 各記事の要素を取得、配列に追加
    for article in articles:
        title = article.select_one("h2.blog-post-title").text.strip()
        link = article.select_one("h2.blog-post-title a")["href"]
        date = article.select_one("footer.blog-post-meta").text.strip()
        if any(keyword in title for keyword in keywords):
            result.append({"title": title, "link": link, "date": date})
        contents = json.dumps(result, ensure_ascii=False)

     # Agentに返却するレスポンスの作成
     function = event['function']
     body = {'body': contents}
     response_body = {
        "TEXT": {
            "body": json.dumps(body, ensure_ascii=False)
        }
     }
     action_response = {
       'actionGroup': event['actionGroup'],
        'function': function,
        'functionResponse': {
            'responseBody': response_body
         }
     }
     return {
         'messageVersion': '1.0',
         'response': action_response
     }

action_response = {
  'actionGroup': event['actionGroup'],
  'function': function,
  'functionResponse': {
      'responseBody': response_body
   }
}

この部分では、Lambda関数がAgentに返すレスポンスの中身を記載しています。
レスポンスの形式は 事前に決まっているのでその形式に合わせます。詳細はこちらの記事をご覧ください。

※今回は外部ライブラリを使用するため事前にLambda Layerを作成しておく必要があります。
Amazon Bedrock 生成AIアプリ開発入門 [AWS深掘りガイド] p299 Lambdaレイヤーを作成するを参照させていただきました。

ターミナルで下記を実行します。

mkdir python
pip install requests==2.27.1 BeautifulSoup4==4.12.3 -t ./python
zip -r Layer.zip python/

これでpython という必要なライブラリが入ったフォルダをzip化できたのでこれをLayer作成画面にてアップロードします。
レイヤーを作成する過程で、互換性のあるランタイムを選択する部分がありますが、私が動作確認を行ったのはpython 3.12なので、同じく python 3.12を選択しました。

STEP5 Streamlitのサンプルアプリをローカル起動し、動作確認

今回は、amazon-bedrock-agent-test-uiというOSSを使用させていただきました。READMEに起動方法が記載されているので、それを参考にローカル起動します。
なお、事前にBEDROCK_AGENT_ID(エージェントID)と、BEDROCK_AGENT_ALIAS_ID(エージェントのエイリアスのID)を環境変数に設定しておく必要があります。いずれもAgent編集の画面で確認できます。

設定が完了したら、下記コマンドを実行し、アプリケーションをローカル起動します。

$ streamlit run app.py --server.port=8080 --server.address=localhost

起動に成功すると、ブラウザが立ち上がり、チャットのページが表示されます。(タイトルは元のものから変えています)
画面左部から、Traceが確認できます。Traceの詳細は[Point]の項をご覧ください。

実際に質問をしてみた結果がこちらです。3つの質問を行いました。質問と回答は以下のようになりました。(※なお、回答は毎回この通りになるとは限りません。)

①AWSの生成AIニュースに関する質問

Q.AWSの生成AIニュースを3件紹介して
A.
▪️ファミリーマートは生成AIを活用して、システム運用業務の効率化を目指しています。具体的には、AIがシステムログを分析し、障害の原因を特定したり、対処方法を提案したりすることで、運用業務の自動化を進めています。この取り組みにより、人員コストの削減や運用コストの削減が可能となります。
▪️参照元: https://aws.amazon.com/jp/blogs/news/familymart-ai-system-operation-improvement/

▪️生成AIを企業のプロダクション環境で安心して利用できるようにするため、ネットワーク境界でのセキュリティ対策が重要です。AWS WAFやAWS Shieldなどのサービスを活用することで、不正アクセスからの保護や、DDoS攻撃への対策が可能です。
▪️参照元: https://aws.amazon.com/jp/blogs/news/network-perimeter-security-protections-for-generative-ai/

▪️AWS Summit Japan 2024でPartyRock展示会において、生成AIの様々な活用事例が紹介されました。例えば、ドキュメント作成の自動化や画像生成による新規デザインの支援など、生成AIが業務の効率化や創造的な作業に与える影響が強調されました。
▪️参照元: https://aws.amazon.com/jp/blogs/news/aws-summit-japan-partyrock-gen-ai-paths-to-business-application/

②デジタルガバナンスコードに関する質問(ナレッジベース内の文書に関する質問)

Q.デジタルガバナンスコードについて教えて
A.デジタルガバナンス・コードとは、企業がデジタルトランスフォーメーション(DX)を推進し、企業価値を向上させるための指針となるものです。主な内容は以下の通りです:

- DXによる新たな価値の創出やビジネスモデルの加速化を目指すこと
- ITシステムの活用による経営効率の向上とリスクマネジメントの強化
- 組織全体的にDXに取り組むこと

デジタルガバナンス・コードは、情報化促進法と密接に関連しており、コードの主な構成要素は以下の通りです:
1. ビジョン・ビジネスモデル
1. 戦略(組織づくり、人材、企業文化、ITシステム、デジタル技術活用環境の整備など)
1. 成果と重要な成果指標

③一般的な質問

Q.日本の首都はどこですか
A.日本の首都は東京です。東京は日本の経済の中心であり、政治・経済の中心でもあります。東京は日本で最も人口が多い都市であり、多くの企業の本社も東京に所在しています。人口は約1,400万人と日本で最も人口が多い都市です。

以上の結果から、期待する結果が返ってくることを確認し、Knowledge Baseと、Agentを組み合わせたRAGチャットとして機能していることが確認できました🙌

Point

Amazon Bedrockには Traceという機能があります。
ざっくり説明すると、これは「Agentがどういった道筋でその回答を導き出したのか」を辿ることができる機能」になります。
トレースステップという箇所で閲覧できます。
様々が出力がありますが、基本的には”rationale":{"text":XXXX....}の値(画像の枠で囲った部分)を確認すると、Agentが下した判断を知ることができます。

それぞれの質問をした際の、Traceを確認してみましょう。
①AWSの生成AIニュースに関する質問

②デジタルガバナンスコードに関する質問(ナレッジベース内の文書に関する質問)

③一般的な質問

上記のように、質問内容によって、Agentがどのように回答するべきかを判断していることが確認できました。

後編まとめ

タイトルにもあるように本記事では、Amazon Bedrock Knowledge Bases/Agentsと Streamlitを組み合わせてRAGチャットボット構築の手順について解説いたしました。

いろいろ書きましたが、ポイントは3つです。

  • Action Groupを設定することで、Agentにさせたい特定のタスクを定義することができる
  • Agent向けの指示をしてあげることで、生成AIに判断をさせることができる
  • Traceを確認することで、Agentの推論ステップを確認することができる

GUI上で操作ができる部分が多く、またベクトルDBはPinecone、フロントエンドはStreamlitにを採用することで、比較的安価かつ少ない労力でチャットボットが構築できるな、と感じました。
費用面に関しては、
AWS Marketplace の Pinecone を Amazon Bedrock のナレッジベースとして利用する(出典:AWS)によれば、

初期アップロードされたベクトルデータのレコード数が 100 万レコード、月間のクエリ回数、書き込み回数がいずれも 1 万回でメタデータのサイズが 500 バイトである場合の月間コストは、 3.82 ドルと試算されています

という記載もあり、データ数が多くなってもベクトルDBの利用料を抑えることができるようですね。

今回の記事は、料金面にはあまり触れませんでしたが、ベクトルDBによって利用料にどのくらい差分が出るのか、についても気になるので、調査してみたいなと思いました。

参考文献・参考サイト

AWS公式サイト

AWS ブログ

出典

経済産業省資料