【Bedrock編】FAQがAIの力でパワーアップ！誰でもナレッジ情報を自由自在に活用できる仕組みをAmazon Bedrock（RAG）+ LangChain + GASで構築

# はじめに
こんにちは！CBcloudのRyoです:grinning:

私の所属するCBcloudでは、物流ラストワンマイルの配送プラットフォーム「ピックゴー」を運用しており、荷物を送りたい方、荷物を届けてくれる方を24時間365日、サービスを通してつなげています！

https://pickgo.town/?utm_source=google&utm_medium=cpc&utm_campaign=brand&utm_id=749340152&utm_term=pickgo&af_pid=google&af_c=brand&gad_source=1&gclid=CjwKCAjwyJqzBhBaEiwAWDRJVBRiSmk6aRJqjngMWLKe1uuwT-EGw6Ktv9Vu7EG8o7545efU0FJaeBoCKuMQAvD_BwE

今回は前回投稿したこちらの記事の続きとなります

https://qiita.com/joeharada/private/8770005457aae9cad420

前記事では少しGASをお見せしただけですが、GASはLambdaを使ってAIからレスポンスを受け取っています
今回はそのLambda編に入る前に、Amazon Bedrcokをどのように使ってAIとやりとりしているかを先に解説していきます

# 前回のおさらい
![](https://storage.googleapis.com/zenn-user-upload/b3f0350f3a8e-20240614.png)

![](https://storage.googleapis.com/zenn-user-upload/e57c2f90c1c9-20240610.png)

前回の記事では機械学習をするAIではなく、使うデータを限定して作るAIをスプレッドシートで使えるようにしたという内容でした

今回は、実際にAIと対話できるサービスを作成し、AIがデータを検索してその情報を基に応答を生成する手法である**RAG**（Retrieval-Augmented Generation）を活用しながら、Amazon Bedrockを使う方法について解説します

# 各用語の説明
## RAGについて
RAGについてざっくり説明します
詳しい説明についてはRAGの元となる論文を日本語訳して解説してくれている記事があったので載せておきます

https://zenn.dev/knowledgesense/articles/47de9ead8029ba


RAGとは質問から関連する外部のデータを引っ張ってきて、それを元にAIが回答を出力するという大規模言語モデル（LLM）を使う手法のことです
RAGを使うことで文章を生成する前に取ってきた情報の中から生成させたりすることで、精度を担保し生成過程も明確になるといった流行の手法です

## Amazon Bedrcok
大手AI企業からの高性能な基盤モデルを借りて生成AIアプリケーションを構築ができるフルマネージドサービスです
今回はオンデマンドでモデルをお借りしているので使った分だけ料金がかかる形態になってます

https://aws.amazon.com/jp/bedrock/?gclid=CjwKCAjwjqWzBhAqEiwAQmtgT352qya3OVtjnQ3_KCGBzmYH5kgtYMSWHuegi-hWVzqFlfNuWRodKRoCeuwQAvD_BwE&trk=38cc0cc4-7da9-4785-9231-aba910a719d1&sc_channel=ps&ef_id=CjwKCAjwjqWzBhAqEiwAQmtgT352qya3OVtjnQ3_KCGBzmYH5kgtYMSWHuegi-hWVzqFlfNuWRodKRoCeuwQAvD_BwE:G:s&s_kwcid=AL!4422!3!692062154795!p!!g!!bedrock!21048268290!157173581017

## Amazon Bedrock for Knowledge base
前述したRAGをBedrcokを使えるようにする機能です
何ができるの？というのは実装部分で詳しく説明していきます


https://aws.amazon.com/jp/bedrock/knowledge-bases/

# 事前準備
今回使うのは以下になります
 - AWS
     - Amazon Bedrock及びナレッジベース
     - Lambda（別記事で解説）
     - S3
     - 他IAMやSecretManagerなど
 - Vector DBのPinecone
 - Google Apps Script（別記事で解説）



## AWS

### Aamazon S3
先に準備として今回AIに使ってもらう知識ベースを作成してS3に保存しておく必要があります
今回使うデータはtxtファイルのQ&A方式でデータを使用します



```PickgoWiki.txt
{
  "document": {
    "topic": "ピックゴーについて",
    "sections": [
      {
        "question": ピックゴーとは何ですか？",
        "answer": "PickGo（ピックゴー）はCBcloud株式会社が提供する配送プラットフォームです。"
      }
    ]
  }
}

```

上記のような形でテキストファイルと専用のバケットを作成し、ファイルをあげ、S3 URIをメモしておいてください

### Aamazon Bedrcok

#### ①使うモデルの申請
![スクリーンショット 2024-06-11 16.58.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/18c0d144-df07-6c45-e924-688cb3fb0575.png)

Aamazon Bedrcokは**リージョンによって使えるモデルが限定されています**
今回使うモデルはClaude 3 Sonnetを使用するのでリージョンは米国東部（バージニア北部）のus-east-1で設定を行います

https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/models-regions.html

まず初めに使うモデルのリクエスト申請を行います　前述した通りClaude 3 Sonnetを使います
リクエスト申請をしてもモデルに質問しない限り料金は発生しないので心配ありません

![スクリーンショット 2024-06-11 17.07.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/1a5b2594-e40e-9d2e-adcb-2b85f5e42703.png)


他のモデルを使う場合は料金も合わせて確認してください

そして今回はナレッジベースを使用するのでメインの応答して使うAIモデルとは別に**Embeddings用のモデルも同時に申請しておく必要があります**

今回はデフォルトの無難Titan Embeddings G1 - Textを使います

![スクリーンショット 2024-06-11 17.12.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/3b6491c4-2ba6-7c1f-ea68-8ecc8b43bf42.png)

2つを選択してリクエストを行ってください

もっと安く使いたい！取り敢えず低予算で試したい！とかであれば料金表を確認しつつ選定してください（ただしモデルによっては日本語全然喋ってくれないなどあるかも）

https://aws.amazon.com/jp/bedrock/pricing/

基本的に申請はClaude 3なら4~5分も掛からず許可されます


#### ②チャットプレイグラウンドで確認してみる

モデルが使えるようになったらサイドバーのチャットからモデルを選んで応答を確認してみます
モデルを選択で先ほどリクエストしたClaude 3 Sonnetを選択します

![スクリーンショット 2024-06-11 17.26.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/83d9e085-5425-4b6a-9a88-c77da96bae34.png)

![スクリーンショット 2024-06-11 17.16.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/668f85ec-af8b-dc66-b43f-7cd6ee8432b6.png)


早速これからAIに命令（プロンプト）していくのですが、その前に設定の長さ(最大長、用は出力文字数)を2000から100ぐらいに設定しておきます
出力の文字が多ければ多いほどお金がかかってしまうので、念の為設定しておくといいでしょう


![スクリーンショット 2024-06-11 17.17.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/6ccf50fe-fa32-5578-0fa3-fbd3e8043808.png)


![スクリーンショット 2024-06-11 17.18.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/676dd201-5453-0c7a-c82c-36726c430c8f.png)

では試しにプロンプトを入力して実行してみます

![スクリーンショット 2024-06-11 17.22.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/0c9e5f34-bba0-f39e-f175-f024ae57f411.png)

無事出力が帰ってきたら成功です

これからナレッジベースの設定を行い、知識をアップデートさせていきます
比較用に今の段階でPickGoについて聞いてみましょう

![](https://storage.googleapis.com/zenn-user-upload/5ab7724591ca-20240617.png)

入力した質問にそれっぽく答えてしまうハルシネーション（幻覚）が発生していますね
100文字制限なので途中で文字が止まってますが、おそらくPick&Goと認識していることからPickとGoで持って移動すると捉えたのでしょう




#### ③ナレッジベースの設定を行う
次にナレッジベースの設定を行います
サイドバーのナレッジベースを選択し、ナレッジベースを作成していきます
![スクリーンショット 2024-06-11 17.24.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/1661e4a5-fe1a-5f43-b2cb-098e9dfc607d.png)

作成を始めるとまず初めに名前とロールの設定を行います
ロール関連について後述するので一旦新規で作成しそのまま進めていきます

![スクリーンショット 2024-06-11 17.29.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/95c70c96-bd94-fd3e-0691-4c3130247afd.png)


次にデータソースを指定します　ここでは事前準備で作成したS3のURIを入れてください
![スクリーンショット 2024-06-11 17.30.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/c7600896-abf4-21f5-ba59-b033a83e6216.png)

事前準備で作成したtxtファイル以外にも情報が使えますが、使える拡張機能を予め確認しておくと良いでしょう（最初にtxtではなくjsonを入れて一度失敗しました）

https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/knowledge-base-ds.html

次に埋め込みモデルとベクトルサーバーを設定します

![スクリーンショット 2024-06-12 16.23.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/e9265fb9-d9ea-aa44-5d1e-b39d38315c15.png)

埋め込みモデルというのは、先ほどS3に設定した追加情報データを**Embedding**する為のものです
埋め込みモデルについて説明する前にEmbeddingについて解説します

Embeddingとは私たち認識できる文章（Text）を**ベクトル**に変換することを指します

> https://aws.amazon.com/jp/blogs/machine-learning/getting-started-with-amazon-titan-text-embeddings/

![ml-15931-image001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/9737ae73-d687-28d6-19c9-72c3aa69eb34.png)

なぜベクトルに変換するかというと、わたしたちが普段会話している言語（自然言語）の場合、数値情報ではないためコンピュータにとって扱いが難しいデータです　自然言語をベクトルに変換することで、AIが迅速にデータを見つけられるようになるんですね

例えば大規模なデータセットがある情報やリアルタイムな検索が必要になるシナリオにおいて予め追加情報データをベクトル化しておくことでAIが迅速に必要情報を見つけることができるようになります


そして自然言語（追加情報データ）をベクトル化したデータは、ベクトルサーバーと呼ばれるところに保存します
ベクトルサーバー自体はBedrockとは別で用意しなければならないので、この画面ではベクトル化する為に必要なAIとベクトル化されたデータを保存するDBの2つを設定する必要があるんですね

![ml-15931-image003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/1b43af9f-8f7e-bcea-3b7e-a169da9695c6.jpeg)


では文章のベクトル化に使うモデル（通称埋め込みモデル）を選んでいきましょう
①のモデルの申請で行った通りTitan Embeddings G1 - Text v1.2を使います
比較的通常のモデルより安いのはありがたいですね

そしてこの**ベクトルの次元**の**1536**は覚えておきましょう
あとでベクトルサーバーを設定する際に必要になります
この次元数はそのまんまの意味で、配列の長さになります　ベクトル化する際にどれくらいの長さで変換するかは埋め込みモデルによって異なるので注意しましょう

![スクリーンショット 2024-06-12 16.30.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/e69be905-3f61-351f-12f5-873c516903b3.png)

続いてベクトルサーバーを設定します
ここでは作成したベクトルストアを選択にし、Pineconeを選択します

![スクリーンショット 2024-06-12 16.34.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2986335/00c97681-ca25-77d7-4b69-f31779997073.png)

ここで必要な情報を設定する必要があるので、Pineconeの設定をしにいきましょう


##### Pineconeの設定を行う

Pineconeは前述したベクトルサーバーを貸してくれるサービスで、無料枠として1インデックスまでなら無料で使用できます

必要情報を登録しておきましょう

https://www.pinecone.io/

あとはわかりやすい参考資料があったのでこちらで設定を行い、ベクトル次元数を合わせてインデックスを作成してください

https://qiita.com/miu_crescent/items/b913683ff202ca34b019

登録と設定が終われば、元のAWSの画面に戻り　エンドポイントURL,認証情報シークレットARNを設定しましょう

またメタデータフィールドマッピングのテキストフィールドは、前述したQ&Aが入ります
ここにはそのままtextと入れ、Bedrockマネージドメタデータフィールドもmetadataと入れます

これなんだろう？と私も思ったので調べたんですがどうやらここでメタデータのフィルタリングなるものができるとかどうとか

これについて解説してくれている資料があったので載せておきます（おそらく次のフェーズで触るかも）

https://dev.classmethod.jp/articles/knowledge-bases-for-amazon-bedrock-metadata-filtering/

項目を入れてそのまま作成を押します

#### Pineconeに同期する

ナレッジベースを作成しただけだとまだAIはドキュメントを参照することはできません
ナレッジベースの作成ができたら、データソースより最初に作られたデータソースを選択して同期してください

![](https://storage.googleapis.com/zenn-user-upload/e2fd2aa5d003-20240614.png)

（画像はデータソース5となっていますが気にしないでください）


同期を押して最終同期時間が更新され、無事同期できたら準備完了です

![](https://storage.googleapis.com/zenn-user-upload/2be1496c95fb-20240614.png)


### 実際にナレッジベースAIを使ってみる

では実際に今追加したナレッジベースを持つAIにPickGoについて聞いてみましょう
画面右サイドバーにナレッジベースのテストが存在しているので、ここで質問を行うことで同期されているかテストできます

![](https://storage.googleapis.com/zenn-user-upload/a46d55371b00-20240617.png)


質問をすると、無事同期できていたので取り込んだ通りに答えてくれました

![](https://storage.googleapis.com/zenn-user-upload/8c580751db20-20240617.png)

ナレッジベースから回答を得た場合、情報のソースが得られるので文面最後の[1]をクリックしてみましょう

![](https://storage.googleapis.com/zenn-user-upload/b84c7ef70d72-20240617.png)

取り込んだtxtデータが表示されていたら成功です


## 終わりに

以上がナレッジベースを使ったAI作成の流れとなります
ナレッジベースを使うことでAIが知らない情報を取り込ませ、ハルシネーションを防ぐことができるので非常に有用な機能ですね

しかし、知らない情報を取り込ませるだけではAIチャット機能としてはまだ足りません
わからない問題を「わからないので有人対応に切り替えますか」と言ったり「もしかしてこちらのことですか」とより人間との対話に近い形で実装していくにはナレッジベースだけでは足りないです

次はこういった返答やAIの役割を設定できる **Agents for Amazon Bedrock** や、実際にコードで制御を行う **LangChain** を使ってよりAIをパワーアップさせていきましょう

今回は以上となりますのでそちらの記事も上がり次第合わせてご確認ください！