社内チャットボットを作るにあたって考えたこと　～③ナレッジベース～

# はじめに
2024年8月頃からAWS上でBedrockを使って社内向け生成AIチャットボットを作っています。
初めて生成AIを使ってみたところで色々考える点があったので、メモとして残しておくことにしました。

生成AI技術が日々すごいスピードで進歩しているので既に古い技術になっていそうなのと、そもそも初心者が書いておりますで、あまり技術的な参考にはならないと思いますが、ポエム的な感じ？でお読みいただけたら幸いです。

# 考えたこと③　ナレッジベース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569502/c815715b-ba69-c142-0fb0-ff9fba6e40f3.png)

今回はナレッジベースをお題としました。Amazon BedrockでRAGを実現するにはKnowledgeBaseを構築する必要があり、それには下記の要素を構成していく必要があります。
それぞれについて考えたことを書きたいと思います。

- データソース
- チャンキング戦略
- 埋め込みモデル
- ベクトルデータベース

### データソース

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569502/136df8e2-6fef-86e9-1c30-d99f5d26bcc9.png)
S3を選択しました。S3以外のデータソースがまだPreview版であるため一択でしたが、今後Sharepointとの連携も試してみたいと思っています。（仕組み的にはSharepointに置いたファイルをそのまま読み込ませたい）

### チャンキング戦略
チャンキング戦略は思い返すと、今回のQAチャットボットを構成するにあたって一番重要な項目だった気がします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569502/036cdd33-5f57-18ae-8b53-d5d5c36a325f.png)

開発当初はチャンキング戦略の理解は全くなく、、、デフォルトやなんとなく意味合い的に区切ってくれたらいいやと思い、セマンティックチャンキングにしていました。

しかし、開発を進めるうちに以下のような課題にぶち当たりました。

- 回答が途中で途切れるケースがある
- 登録してあるQAデータと微妙に違う文言で回答する

チャットボットに読み込ませるQAデータは、下記の例のように1行ずつ質問と答えセットのレコードのデータとしており、チャットボットの回答として望んでいたのは、回答列の内容をそのまま出すという形でした。
（※一般的な例としてAIで作成したもので、弊社の規約から作成したものではありません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569502/9fbf32bb-d2d8-3527-8873-05e67e93b7ae.png)

この事象はプロンプトのせいなのだろうと考えて、色々と指示を変えたりして、精度はあがってきたもののいまいち解決せず、最終的に辿り着いたのがチャンキング戦略でした。

結論として採用したのは、QAデータを **1行ごとにファイル分割** して、 **チャンキング戦略を「チャンキングなし」** としたことでした。


例えば、「交通費について教えて」というあいまいな質問を投げた場合
- 「セマンティックチャンキング」での回答結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569502/ac2233c0-83dc-0084-21ee-cccced29b778.png)

- ファイル分割＋「チャンキングなし」での回答結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569502/4ba27b09-d4d2-205e-f80e-cca4820f5d00.png)

セマンティックチャンキングだと質問したい内容と別のデータも混ざってチャンクされてしまっていますが、チャンキングなしにすると、ソースチャンクとしてすっきりしたものが提示されるようになり、これによって課題は解決できました。

- 回答が途中で途切れるケースがある
ファイル分割した単位で区切られるため、途中で区切られるケースはなくなりました。
改行コードやHTMLタグが入っているケースで区切られることが多かったのですが、別のデータとして判断されてしまっていたのだろうと思います。
- 登録してあるQAデータと微妙に違う文言で回答する
チャンクに該当の内容のみ入っているため、余計な言い換えなどはなくなりました。
別のデータと混ざってたことでノイズのある回答文を作ってしまっていたのではないかと推測しています。

私たちのチャットボットには「ファイル分割＋チャンキングなし」がいい結果に繋がりました。この課題の解決の他にも回答精度があがったり、データとして扱いやすくなったり、色んなメリットがありました。

##### 参考にしたサイト
https://zenn.dev/kun432/scraps/c3d65c44e60755

### 埋め込みモデル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569502/9f5a6ecc-d3ba-1c8f-92fe-c55bb004bb4d.png)

「Amazon Titan Embeddings G1 - Text」と「Cohere Embed Multilingual」の比較になりました。
比較テストを行った結果として、Cohereのほうが若干精度良いかな程度の差を感じました。例えばハルシネーション回数だったり、回答とするソースの選択の妥当性だったり。ただ、あまり多くの件数で比較していないのであまり変わらないのかなとも思ったりもしています。
コスト的にもCohereのほうが安価だったので、総合的にCohereを採用しました。
（2024/12現在はTitan Text Embeddings V2が安価で使えるようですね）

|モデル|入力トークン 1,000 個あたりの価格|
|:----|----:|
|Amazon Titan Text Embeddings|0.0002 USD|
|Cohere Embed - Multilingual|0.0001 USD|

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

### ベクトルデータベース

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569502/56224cac-178b-2a90-5bbc-fadd974265cf.png)

「Amazon OpenSearch Serverless」「Amazon Aurora」「Pinecone」から検討しました。

まず、AWSサービスを使いたいという理由で「Amazon OpenSearch Serverless」「Amazon Aurora」の2択になり、ランニングコストの観点で「Amazon Aurora」にしました。インスタンスタイプとしては、サーバレスが良かったので、Serverless v2にしました。

ベクトルDBの検討にあたっては、一番コストがかかる所という意識があり、社内利用で安くという点では特に __使わない時間帯に停止できる__ 点でコストメリットが高かったので、停止制御のできる「Amazon Aurora Serverless v2」を選択したということになります。

今後もし高機能をつけていくようならハイブリット検索を使えるAmazon OpenSearch Serverlessも検討したいと思います。

なお、Amazon EventBridge Schedulerで平日業務時間だけ起動するというような制御にしましたが、自動停止できるようになったとのことで、こちらも今後試してみたいと思います。

https://dev.classmethod.jp/articles/amazon-aurora-serverless-v2-supports-acu0-pause-resume/


##### 参考にしたサイト
https://qiita.com/hayao_k/items/45e59c1c2a183c27b20d

https://qiita.com/pooooon/items/6817bd4e4d67c99eda89


## 考えた結果
ナレッジベースについては考えるところが非常に多かったです。特にチャンキング戦略が今回のチャットボットでは肝になりました。データの持ち方によって変わってくると思いますし、Advanced parsingも使えるようになったとのことで、今後も比較しながら使っていくものを決めていきたいと思います。
- データソース　⇒　Amazon S3　
- チャンキング戦略　⇒　ファイル分割＋チャンキングなし
- 埋め込みモデル　⇒　Cohere Embed Multilingual
- ベクトルデータベース　⇒　Amazon Aurora Serverless v2

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569502/6bab6798-1c72-e9f6-6a9d-94ff8fb8ff00.png)
（あまり考え無しに絵を作っていったのでぐちゃっとなってきました・・・）