お問い合わせ
6 分で読むことができます。

【AWS Kendra, Bedrock】AWSでRAGアプリケーションを作成してみた - ②

執筆者 Budo Ogimoto 更新日時 2024年6月04日

はじめに


この記事では、AWSを利用してRAGを搭載したチャットシステムを構築する方法を紹介します。
また、この記事で紹介している内容は5/21, 22, 23にグランドニッコー東京 台場で開催された「ガートナー データ&アナリティクス サミット 2024」に出展しました。

ガートナー データ&アナリティクス サミット2024
東京で開催されるガートナー データ&アナリティクス サミット2024でCDAOとデータ&アナリティクスのリーダーのためのインサイト、戦略、フレームワークを探求しましょう。ご登録はこちら
https://www.gartner.com/jp/conferences/apac/data-analytics-japan

こちら、シリーズものの記事になっており、初回の記事はこちらから読めますので、初回の記事から是非ご一読いただければと思います。

ドキュメントをS3に配置


準備の為に上記項目で入手したドキュメントをS3に配置します。
S3のバケットを作成して以下の画像の様にテキストファイルを配置します。

Index用ロールを作成


KendraからS3を扱う為にKendra用のロールを作成します。
今回は検証用なので、S3のフルコントロールを付与しますが、サービスとして機能させる場合はバケットレベルでの最小権限を付与する必要があるかと思います。
以下、付与している権限の例です。

画像上にカスタマー管理の権限もある為、そちらもJSON形式で表記していきます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData"
            ],
            "Resource": "*",
            "Condition": {
                "StringEquals": {
                    "cloudwatch:namespace": "AWS/Kendra"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup"
            ],
            "Resource": [
                "arn:aws:logs:[Region]:[Account-ID]:log-group:/aws/kendra/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogStreams",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": [
                "arn:aws:logs:[Region]:[Account-ID]:log-group:/aws/kendra/*:log-stream:*"
            ]
        }
    ]
}

Index作成


次にAmazon KendraでのIndex(ベクトルDB)を作成します。
コンソールでAmazon Kendraにアクセスします。

「Create an Index」をクリックすると以下のIndexの作成画面に遷移します。

「Index name」には任意の名前を入力します。
「IAM role」は先ほど作成したロールを指定します。
設定が完了しましたら「Next」をクリックします。

次はアクセスコントロールの項目を設定します。
今回は特に設定を行いません。

設定項目としては、以下の通りです。

  • Access control setting

    Indexアクセス時にセキュリティトークンをチェックする設定にするかどうかの項目
    Yesにすると以下の画面が出てきてトークンの種類が選べます。

  • User-group expansion

    AWS IAM Identity Centerを利用したアクセス制限をかけることができます。
    例えば、とある部署には見せたくないドキュメントがあればドキュメントにタグをつけてAWS IAM Identity Centerのユーザーグループとタグの紐づけが可能です。
    Kendraを呼び出す際にIAMユーザーが必要なので特定のユーザーグループに属する人には、Kendraの検索結果には載せないという設定ができます。

続いてIndexのエディションを選択します。

Kendraには、エディションが二つあり、「Developer edition」と「Enterprise edition」があります。

以下、各エディションの違いです。

Developer edition

  • 10,000件のドキュメントを保存可能
  • 一日当り4,000件のクエリが利用可能
  • データソースを5件利用可能
  • アベイラビリティゾーン 1
  • 無料枠あり(最初30 日間で最大 750 時間)
  • 基本料金:1.125 USD/時間(=810 USD/月)

Enterprise edition

  • 100,000件のドキュメントを保存可能
  • 一日当り8,000件のクエリが利用可能
  • データソースを50件利用可能
  • アベイラビリティゾーン 3
  • 無料枠なし
  • 基本料金:1.4 USD/時間(=1,008 USD/月)

利用可能なドキュメント件数や料金も異なってくるので、必要に応じて設定してください。

今回は、Developer editionを選択します。

最後は確認画面になります。

「Create」をクリックするとIndexが作成されます。
クリック後、作成には30分程度時間が掛かるのでご注意ください。

ドキュメントの同期


続いてドキュメントの同期を行います。

KendraはIndexというベクトルDBにドキュメントを格納する必要があります。
コンソールから作成したIndexの概要を開き「Add data sources」をクリックします。

クリックするとデータソースを選択する画面に遷移します。

ここではS3だけでなく、boxやconfluence等他のコネクタもあります。
今回は「Amazon S3 connector」を選択します。

選択するとデータソース設定画面に移ります。

「Data source name」は任意の名前を入力します。
「Default language of source documents」はデータソース内の言語を設定します。
ここでは、Japanese(ja)を選択します。
設定後、「Next」をクリックします。

次にアクセスとセキュリティ設定を行います。
「IAM role」は、前項で作成したロールを設定します。
「Configure VPC and security group - optional」はVPC経由でドキュメントをロードする場合に設定します。

続いて、ロードするS3を選択します。
「Sync scope」では、ドキュメントを配置しているS3を指定します。
「Sync mode」は、「Sync scope」で指定した範囲内で更新があった場合の同期の方法を設定します。
以下、同期方法です。

  • Full sync

    変更に関係なく全ドキュメントを読み込みます。

  • New, modified, or deleted content sync

    変更された差分のみ読み込み、削除を行います。

「Sync run schedule」は同期のスケジュール設定を行います。
これらを設定後「Next」をクリックします。

次は、ドキュメントに対するメタデータの設定になります。
こちらはS3を設定しているので「s3_document_id」のみですが、他のコネクタですとドキュメントに対するメタデータを設定できます。
今回はこのまま「Next」をクリックします。

最後は、確認の画面になります。

「Add data source」をクリックするとデータソースが作成されます。
作成されると下記の画像のような画面に遷移します。

画面に遷移したら、「Sync Now」をクリックするとS3に配置されたドキュメントの読み込みが始まります。
完了すると下記の画像のような画面となります。

これで、Amazon Kendraの準備が完了しました。

おわりに


本記事では、Amazon Kendraが利用できるようにIndexの作成解説を行いました。
次の記事では、Amazon Bedrockを有効化して、簡単なChatbotシステムを作成していきます。
次の記事もご一読頂ければ幸いです。

Topics: Python AI AWS Amzaon Kendra Amazon Bedrock
3 分で読むことができます。

【AWS Kendra, Bedrock】AWSでRAGアプリケーションを作成してみた - ①

執筆者 Budo Ogimoto 更新日時 2024年6月04日

はじめに


この記事では、AWSを利用してRAGを搭載したチャットシステムを構築する方法を紹介します。
また、この記事で紹介している内容は5/21, 22, 23にグランドニッコー東京 台場で開催された「ガートナー データ&アナリティクス サミット 2024」に出展しました。

ガートナー データ&アナリティクス サミット2024
東京で開催されるガートナー データ&アナリティクス サミット2024でCDAOとデータ&アナリティクスのリーダーのためのインサイト、戦略、フレームワークを探求しましょう。ご登録はこちら
https://www.gartner.com/jp/conferences/apac/data-analytics-japan

RAGについて


RAG(Retrieval-Augmented Generation)とは、生成モデルとベクトルDBを組み合わせたアプローチ方法を指します。

基本的な構成は下記の画像の様になります。

事前にベクトルDBに生成モデルに参照させたいドキュメントをベクトル化しておきます。
ユーザーの入力文より類似した文を検索することで生成モデルが回答文を生成する為の参考文を検索します。
付随情報を参照するようなプロンプトを入力文と共に入力することで回答文を生成します。

このような構成にすることで、プロンプトの調整次第ですが付随情報の内容のみを参照させて回答させることができます。

RAGの利点としては以下のような点が挙げられます。

  • ハルシネーションの防止

    生成モデルを利用する上での注意点であるハルシネーション(生成モデルの嘘)を参考文の情報のみを参照させることで防止ができます。
    また、定期的にベクトルDBを更新することで最新情報のキャッチアップが可能です。

  • 生成モデルの調整コストカット

    生成モデルに専門性を持たせる際にファインチューニングや強化学習を行う必要がありますがRAGに於いては参照先のベクトルDBを切り替えることで対応可能です。

システムの構成


今回構築していくRAGの構成を解説します。
構成としては、下記のようになっています。

構成自体は単純で、ユーザーの入出力を制御するEC2内のアプリケーションをPythonで構築して、ベクトルDBをAmazon Kendraとし、生成AIをAmazon Bedrockを介してClaude v3 Haikuとする形になっています。

肝心の参考文に関しては、Notion内にあるISL Knowledgeの記事全件を読み込んでいます。
よって、今回のRAGはISLの技術力の集合知を表すものになるかと思います。

ドキュメントの収集


今回はNotionからAPIを利用して全件の記事を収集します。

まずは、全記事の概要データを収集します。
下記のPythonコードで実行します。

import requests
import json
import numpy as np
import pandas as pd
from tqdm import tqdm

# トークン情報
NOTION_ACCESS_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
NOTION_DATABASE_ID = 'XXXXXXXXXXXXXXXXXXXX'


# 各変数
loop_cnt = 1
has_more = True
data = []
all_titles = []
authors = []
create_times = []
article_ids = []
urls = []
statuses = []
tag_sets = []
author_emails = []
next_cursor = None


# APIでデータベース内のデータを全件取得
while has_more:
    url = f"https://api.notion.com/v1/databases/{NOTION_DATABASE_ID}/query"
    headers = {
        'Authorization': 'Bearer ' + NOTION_ACCESS_TOKEN,
        'Notion-Version': '2021-05-13',
        'Content-Type': 'application/json',
    }
    payload = {'page_size': 100} if loop_cnt == 1 else {'page_size': 100, 'start_cursor': next_cursor}
    result_json = requests.post(url, headers=headers, data=json.dumps(payload))
    data += result_json.json().get('results')
    has_more = result_json.json().get('has_more')
    next_cursor = result_json.json().get('next_cursor')
    print('loop: {}'.format(loop_cnt))
    loop_cnt += 1

# 取得したデータを保存
with open('notion_knowledge_data.json', 'w')as f:
    json.dump(data, f, indent=1)

# 各記事の情報を収集
for record in tqdm(data):
    status = record['properties']['Status']['status']['name']
    url = record['url']
    article_id = record['id']
    try:
        title = record['properties']['Knowledge']['title'][0]['plain_text']
    except IndexError:
        title = ''
    try:
        author = record['properties']['Author']['created_by']['name']
    except KeyError:
        author = 'unknown'
    try:
        author_email = record['properties']['Author']['created_by']['person']['email']
    except KeyError:
        author_email = 'unknown'
    create_time = record['properties']['CreateTime']['created_time']
    tags = '&&'.join([x['name'] for x in record['properties']['Tag']['multi_select']])
    article_ids.append(article_id)
    all_titles.append(title)
    authors.append(author)
    create_times.append(create_time)
    urls.append(url)
    statuses.append(status)
    tag_sets.append(tags)
    author_emails.append(author_email)


# データフレーム化して保存
df = pd.DataFrame(
    np.array([[i for i in range(len(all_titles))], all_titles, authors, author_emails, create_times, urls, article_ids, statuses, tag_sets]).T,
    columns=[
		    'index', 'title', 'author',
		    'author_email', 'create_time', 'url',
		    'article_id', 'status', 'tags'
    ]
)
df.to_csv('notion_knowledges.csv', index=False, encoding='utf_8_sig')

今回は継続的にドキュメント内容を更新させるわけではないので、上記のスクリプトのみとなっています。
実際に運用する場合は、差分を取りに行くlambda等を作成して更新するスクリプトを仕込む必要があります。

おわりに


本記事では、構築するシステムの概要とAmazon Kendraに格納するドキュメントの収集をNotionから行いました。
次回の記事からは、Amazon KendraのベクトルDBに当たるIndexを作成していきます。
次回の記事もご一読頂けますと幸いです。

Topics: Python AI AWS Amzaon Kendra Amazon Bedrock
3 分で読むことができます。

#30DaysOfStreamlit Day30 Streamlit アプリ作成の技術

執筆者 Budo Ogimoto 更新日時 2023年12月19日

はじめに


この記事では、#30DaysOfStreamlitの内容の紹介を行います。
#30DaysOfStreamlitについてはコチラの記事を参照してください。

Topics: Python streamlit
7 分で読むことができます。

#30DaysOfStreamlit Day29 Zero-shot学習モデルでのテキスト分類器

執筆者 Budo Ogimoto 更新日時 2023年12月19日

はじめに


この記事では、#30DaysOfStreamlitの内容の紹介を行います。
#30DaysOfStreamlitについてはコチラの記事を参照してください。

Topics: Python streamlit
6 分で読むことができます。

#30DaysOfStreamlit Day28 SHAPアプリケーション構築

執筆者 Budo Ogimoto 更新日時 2023年12月19日

はじめに


この記事では、#30DaysOfStreamlitの内容の紹介を行います。
#30DaysOfStreamlitについてはコチラの記事を参照してください。

Topics: Python streamlit
4 分で読むことができます。

#30DaysOfStreamlit Day27 Streamlit Elements を使用してドラッグ可能でサイズ変更可能なダッシュボードを構築する

執筆者 Budo Ogimoto 更新日時 2023年12月19日

はじめに


この記事では、#30DaysOfStreamlitの内容の紹介を行います。
#30DaysOfStreamlitについてはコチラの記事を参照してください。

Topics: Python streamlit
2 分で読むことができます。

#30DaysOfStreamlit Day26 Bored API アプリを構築して API を使用する方法

執筆者 Budo Ogimoto 更新日時 2023年12月19日

はじめに


この記事では、#30DaysOfStreamlitの内容の紹介を行います。
#30DaysOfStreamlitについてはコチラの記事を参照してください。

Topics: Python streamlit
2 分で読むことができます。

#30DaysOfStreamlit Day25 st.session_state

執筆者 Budo Ogimoto 更新日時 2023年12月19日

はじめに


この記事では、#30DaysOfStreamlitの内容の紹介を行います。
#30DaysOfStreamlitについてはコチラの記事を参照してください。

Topics: Python streamlit
2 分で読むことができます。

#30DaysOfStreamlit Day24 st.cache_data, cache_resource

執筆者 Budo Ogimoto 更新日時 2023年12月19日

はじめに


この記事では、#30DaysOfStreamlitの内容の紹介を行います。
#30DaysOfStreamlitについてはコチラの記事を参照してください。

Topics: Python streamlit
2 分で読むことができます。

#30DaysOfStreamlit Day23 st.experimental_get_query_params

執筆者 Budo Ogimoto 更新日時 2023年12月19日

はじめに


この記事では、#30DaysOfStreamlitの内容の紹介を行います。
#30DaysOfStreamlitについてはコチラの記事を参照してください。

Topics: Python streamlit