社内FAQ生成AIチャットボットの精度を高めるために工夫した3つのポイント

元気しとーと？ 博多に住んどうUiPathプリシェールス @ManabuTechばい。
（お元気でしょうか？ 博多に在住しておりますUiPathプリセールスManabuTech です）

以前、自社ナレッジに対する質問に対しても回答可能な「生成AIチャットボット」を展示した際に、生成AIアプリケーションを作ってみて分かった、生成AIアプリを社内で利用する際に気を付けるべき6つのポイントを紹介しました。

https://qiita.com/ManabuTech/items/425d1625d6585eca5a34

FAQチャットボットが社内情報を用いて回答するために、事前に情報をベクトル化しておくRAGの構成で環境を構築していますが、回答の際にハルシネーション（でっちあげ）が発生する場合がありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2577004/3ce97b2c-1f34-969e-6c80-68f8605b64b2.png)

私はUiPathのAI CenterにLangChainを利用したPythonスクリプトをデプロイしていますが、バックエンドサーバーに同じようにデプロイしている方、Microsoft CognitiveSearchを利用して社内FAQチャットボット環境を構築しようとしている方も同じ悩みを抱えているのかなと思います。今回は精度を上げるために行った3つのポイントを紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2577004/6145df2a-3c8f-d13a-aa13-83ce59b725a2.png)

## ハルシネーションの原因と対策

ハルシネーション（でっちあげ）のパターン別に対策をこうじました。
ちなみに、ブース展示用のアプリケーションのため、そこまでチューニングはできておりません。

### 社内情報か一般的な質問か誤判定

LangChainのエージェント機能、OpenAIのFunctionCallingを用いることで、生成AIに社内情報に関する質問か、一般的な生成AIが回答できるようにしていました。

しかし、一般的な内容に対して、社内情報を検索してしまったり逆に一般的な内容で問い合わせてしまったりと正しく判定できないことがありました。

この問題を解決する手法としては、Fuction Callingやエージェントから呼び出す関数の概要欄を詳しく説明することで精度を向上させることもできるかもしれませんが、100%にはならないかと思います。

チャットボット使用者が、質問に「社内情報から」というワードを入れるようなルールで乗り切ることもできるかもしれませんが、使用者にルールを課すのであれば、チャットアプリ側に社内、一般質問か選べるようにして良いかと思います。


### 参照ファイルが異なる

社内情報ファイルを増やしていくと、ファイル数に応じてハルシネーションの割合が多くなりました。
例えば、人事関連の質問を行っているのに別の経理関連のファイルを参照してしまうなどです。

経理用の質問に回答してくれるチャットボット、人事用の質問に回答してくれるチャットボットなどアプリを分けるようにした方がいいのではないかと考えています。
ローコード開発ツールの「UiPath Apps」でフロントエンドのWebアプリケーションを作成していますが、生成AIのチャットの前に質問したい分野を絞るなどしなければならないと思いました。FAQ一覧を表示することで同じような質問をせずに費用を抑制することもできるのかなと思います。

ユーザー：質問したい分野を選択する
Webアプリ：FAQ一覧とチャット項目を表示する
ユーザー：FAQに無ければ生成AIにチャットする
Webアプリ：回答を表示


### そもそも精度が上がらない

最後に、社外や分野の選択をしたとしても、そもそも精度が上がらないという問題もあるかと思います。
これはチャンクの分割単位が大きすぎるためだと思います。

社内情報を扱えるようにするRAGでは、以下のようなフローをたどります。

事前準備
・ドキュメントを読み込む
・ドキュメントをチャンクという単位に分割する
・チャンクをベクトル化してベクトルDBに保存する

質問時
・質問をベクトル化する
・ベクトル化した質問に類似する文言をベクトルDBから引っ張ってくる
・類似文章をもとに生成AIに回答を促す

ファイルを単純にアップロードすると、分割する長さと分割する文字列に従って分割されます。
例えば、改行が2つ連続する場合に分割するなど処理が行われ、分割する長さを超えないようにマージされます。
ノーコードで環境構築できるものだと簡単に環境を構築できますが、この辺りまでカスタマイズができないかもしれません。

チャンクの中に質問文と回答文があり、他の情報が入っていない形式が望ましいです。
しかし、通常の文章ではこの形式になっていないため、FAQのようなデータが必要になってきます。

UiPathの製品群で構築する構成の場合、社内にあるFAQページやFAQファイルをRPAが定期的に取得してくる運用にしています。
生成AIアプリ用にデータを用意するのは大変なので、RPAに処理を任せて運用負担を減らします。
こうすることで、現在の運用は変えなくていいので、生成AIのチャットボット導入が容易に進みます。

Sharepointなどで、FAQサイトなどを作っていた場合は、UiPathだとデータスクレイピングで表形式データを一括で簡単に取得できます。Sharepointや共有サーバーのファイルなどもUiPathのRPAであれば簡単に取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2577004/750fead3-1b02-f443-3925-15c45162f8f0.png)

これをExcelなどを使用してデータにして生成AIチャットボットがアクセスできる場所に配置します。
この際に区切り文字を入れておくことで、各行単位でチャンク分割が行え、質問と回答が入った理想的なチャンクになります。この処理もUiPathのRPAであれば簡単にできますので、UiPathのワークフローが作れる人であれば簡単に情報を追加することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2577004/40a53f67-b42f-ede5-4c26-ad731b9b1118.png)

デプロイするバックエンドのPythonスクリプト側で同一の区切り文字列を指定して分割します。
精度向上のために、このFAQ形式のデータを見に行って生成AIの回答のスコアが75%未満であれば、FAQ形式ではない単純に格納されたファイルを参照する仕組みにしています。
FAQサイトなんて運用していないよという方は、生成AIの質問と回答の履歴からFAQを作っていくと、精度が向上していくと思います。UiPathではDataServiceにデータを保持して、質問と回答が正しいかをチェックしてFAQを作る処理をRPAで組むことも可能ですので、少しずつFAQを手間なく作っていくことがいいのではないかと思います。

## さいごに

Cognitive Search など、ローコードでプログラムを書かずにFAQチャットボットを作ろうとすると、カスタマイズできる範囲が狭い。プログラミングでやるとカスタマイズはできるのですが、スキルが必要でメンテナンスが大変になるというジレンマがあります。

今回はRPAなどのローコードの技術を使って、チャンク分割しやすいように整形する仕組み、回答履歴からFAQを作る仕組みを作りました。

この分野はかなり技術の進歩が速いので、簡単に精度を上げることができるサービスが出てくることもあるとは思いますが、サービスの拡充を待たずに柔軟にカスタマイズできるというのもRPA、ローコードを使うメリットかなと思います。