DIVX ブログ

catch-img

RAGで答えます!社内規程を活用したAIチャットボット改善


目次[非表示]

  1. 1.はじめに
  2. 2.チャットボットに答えてほしいこと
  3. 3.社内規程を追加してRAGの回答精度をあげよう
    1. 3.1.データをどのように保存するか
      1. 3.1.1.前提:ベクトルデータベースの選定
      2. 3.1.2.メタデータの検討
      3. 3.1.3.チャンキングの検討
      4. 3.1.4.データのフォーマットの検討
    2. 3.2.どのように検索するか
      1. 3.2.1.クエリベースのドキュメント検索
      2. 3.2.2.閾値の調整
    3. 3.3.どんな回答を生成してもらうか
      1. 3.3.1.LLMの大敵 ハルシネーションをプロンプトで抑える
      2. 3.3.2.フューショットプロンプティングの検討
      3. 3.3.3.temperatureの指定
  4. 4.回答精度はあがったのか?
  5. 5.おわりに


はじめに

こんにちは!株式会社divxエンジニアの橋本です。


私の所属するチームでは、OpenAIのAPIを活用したAIチャットツールを開発しています。こちらは社内で使用されているツールであるため、社内情報について回答するチャットボット機能も搭載しています。RAGの構成を取り入れたこの機能は、独自の社内情報について回答が可能です。
今回はここに社内規程を追加して、社内のみなさんがさらに快適に業務を進めるお手伝いをしようという試みをご紹介します。

チャットボットに答えてほしいこと

社内規程とは、企業が独自に定めたルールやガイドラインのことを指します。具体的には、就業規則、組織規程や稟議規程、個人情報保護規程などが、それぞれの会社で定められているはずです。多くのものは以下のような構成で書かれているのではないでしょうか。

【規程例】


法律の専門家であれば読み慣れた形式かもしれませんが、やや堅い文体で書かれたこれらの規則に対して「とっつきにくい」、「わかりにくい」、「そもそもどこを読めば知りたいことがわかるの?」と感じる人は私だけではないと思います。チャットボットには以下の条件を満たした親切な回答をして欲しいところです。

【社内規程チャットボットへの要望】

  • わかりやすく答えてほしい
  • 知りたいことがどこに書いてあるか教えて欲しい

  • 正確な情報を提供し、間違ったことは言わないでほしい

この要望を実現するために、以下のアプローチを検証していきます。

社内規程を追加してRAGの回答精度をあげよう

基本的なRAGの構成を、図で表すと以下のようになります。
図はAWSがRAG(検索拡張生成)に関する概要を掲載している こちらのリンクから引用しました。 【参考URL:https://aws.amazon.com/jp/what-is/retrieval-augmented-generation/


ユーザーがシステムにメッセージを入力するところから、AIモデルから回答が返されるまでの流れのなかで、今回は下記の3点について意図した回答を生成させるための工夫をおこなっていきます。

  • データをどのように保存するか
  • どのように検索するか

  • どんな回答を生成してもらうか


データをどのように保存するか


図に示す赤枠部分に社内情報が蓄積されており、ユーザーの質問の答えとして参照に値すると思われる文書をこちらから検索してくる形になります。
まずはここに社内規程を追加していきます。


前提:ベクトルデータベースの選定

社内情報を保存するベクトルデータベースには、OSSのChromaDBを採用しました。
選定にあたっては弊社のAI基礎研究チームに事前に検証をしてもらいました。OpenAIの埋め込みモデルに対応していることはもちろんですが、以下にあげる多くのメリットがあったことが選定の理由です。常にRAGの精度向上の検証を行えるよう、研究に取り組みやすいカスタマイズ性も今回の決め手のひとつです。


【メリット】

  • カスタマイズ性が高い
    • データ構造を揃えるよう前処理を行えれば、どんなデータでも保存可能
    • デプロイ先の処理性能や容量を自由に設定可能
    • やろうと思えばChromaインスタンスに独自の処理を入れることも可能
  • コストが低い
    • AWS kendra利用した場合に比較するとの3%以下に抑えられる

  • 処理時間が短い
    • AI回答の前に、ドキュメント取得処理が0.62秒プラスされるだけ

メタデータの検討

データは次のセクション「どのように検索するか」について考慮し、検索しやすいデータ構造に変換して保存していく必要があります。
chromaDBに保存するドキュメントには、metadataとしてオプションの辞書リストを指定して、追加情報を一緒に保存することができます。

  • 規程名(ドキュメントのタイトルに同じ)
  • ドキュメントの最終更新日

  • 参照URL(GoogleDriveに保存している書類の共有リンク

が確実に含まれるようにしました。


チャンキングの検討


ドキュメントの効率的な検索・参照のため、社内規程もチャンキングを行うことにしました。
固定長チャンキング、意味ベースのチャンキングなど、様々な手法がありますが、規程の場合は前の章に出した例のように第一章、第◯条・・・といった構造がとられることがほとんどです。
章ごとにチャンキングする方針としました。


データのフォーマットの検討

追加する規程文書はPDFファイルで作成してあるため、テキストを抽出したうえで保存する必要があります。また章ごとにチャンキングしやすいことを考慮するとマークダウン形式が良さそう、といったんこの方向で検証を行いました。
ところが1点、マークダウン形式の課題が出てきました。
規程文書内に表が添付されているケースです。マークダウンはテキストのフォーマットには便利な反面、表の表現には限界があり、別のフォーマットを検討する必要性があります。表が添付された箇所に関しては回答精度がいまひとつ、むしろプレーンテキストのほうが良い回答が得られる・・・という場合さえあり、迷った結果、結論、マークダウンと表の注釈テキストを組み合わせる形を試すことにしました。
今回のPDFのドキュメント変換・保存に「使ってみよう!」と採用したDoclingというライブラリ、こちらで変換したDocumentだと表の部分がtable要素として抽出できることがとても役立ちました。

  1. PDFをDoclingのドキュメントに変換
  2. Doclingドキュメントのtable要素部分(PDFの表の箇所)を取り出し、AIに表の行ごとの注釈を作成してもらう

  3. 表の部分を注釈に差し替えてマークダウンに変換

この段取りでマークダウンと表の注釈テキストを組み合わせた形でデータを保存することで、回答精度を一定程度良好に保つことができました。


※注意いただきたい点として、Doclingドキュメントで抽出する表の列や行が2〜3行でおさまっているぶんには問題ないのですが、それ以上のサイズの表や複雑な構造の表になってくると抽出の精度が必ずしも良好とは言えないケースもあるようです。各自ご確認ください。


どのように検索するか



クエリベースのドキュメント検索

前提として「データをどのように保存するか」の章で保存したドキュメントは「ベクトル埋め込み」として保存されます。今回はOpenAIのtext-embedding-3-largeモデルを使用しました。自然言語処理において、テキストデータ(単語、文、段落など)を機械が扱いやすい数値形式(ベクトル)に変換することを「埋め込み」と呼びます。
ここで使用されるベクトル値は、クエリとして与えられた入力のベクトル値との距離(例えば、コサイン類似度やユークリッド距離)を計算することで、どのドキュメントがクエリに最も関連しているかを判断する役割を果たします。
ベクトル検索は、単なる文字検索ではなく、意味的な類似性を考慮して情報を検索できることがメリットです。文脈や関連性の高いドキュメントを検索することができます。


閾値の調整

検索結果からさらに類似度が指定された閾値よりも小さいドキュメントを返します。ここでは値が小さければ小さいほど、検索に使用した質問文に近いことを表します。
ここで一定の類似度に満たないドキュメントは、こちらで指定した閾値でフィルタリングをかけます。関連性が高いドキュメントのみを結果として得られます。


どんな回答を生成してもらうか


LLMの大敵 ハルシネーションをプロンプトで抑える

ここまでの実装時点で、まだハルシネーションの課題が残っていました。
社内文書に記載のない事柄であるにもかかわらず、一般論的な回答を生成し、あたかもそのような規程があるかのようなレスポンスをする場合が発生していることに気付きました。
このようなケースをを回避すべく、図に示す④基盤モデルにメッセージを送る時に付け加えるプロンプトにひとひねり加えました。ここの章で改修するプロンプトとは、図中の①でユーザーが入力したメッセージ部分に使用されるプロンプトではなく、社内情報チャットボットを使用する時だけ内部的に使用する④の箇所でモデルに送信するプロンプトを指します。以下のように修正を行い、改善が見られました。


【改修前】

messages = [
                (
                    "system",
                    (
                        "system",
                       "あなたは有能なアシスタントです。回答に参照先のURLを含めないでください。",
                    ),
                ),
                (
                    "user",
                    〜〜 略 〜〜
                ),
            ]


【改修後】

                (
                    "system",
                    (
                        "あなたは社内文書に基づいて質問に回答するチャットボットです。提供された文書以外の情報は使用せず、不明な点があればその旨を伝えてください。"
                        "以下の条件を満たすように回答してください。\n"
                        "1. 回答に参照先のURLを含めないこと。\n"
                        "2. 参照ドキュメント内に「不明」や情報の欠損がある場合、"
                        "一般論を述べるのではなく、参照元の資料を確認するようユーザーに促すこと。"
                        "3. 規程やドキュメントに記載のない事柄については一般論を述べるのではなく、"
                        "参照元の資料を確認するようユーザーに促すこと。"
                    ),
                ),
                (
                    "user",
                    〜〜 略 〜〜
                ),
            ]

ここにおけるsystemとはシステムメッセージを指し、メッセージを受け取ったAIモデルが応答で使用するペルソナ、つまり役割や専門性を明確に指定できます。モデルが遵守すべきルールやガイドラインを設定するのも効果的です。OpenAIが公開しているPrompt engineeringのガイドの戦略: 明確な指示を書くことのセクションなど(https://platform.openai.com/docs/guides/prompt-engineering)を参照するのもおすすめです。


基盤モデルのトレーニングには時間もコストもかかりますし、まして今回はユースケースが自社内に限られます。追加データによるモデルのファインチューニングを検討する前に、まずはプロンプトによって意図した回答を得ることは、限られた時間やコストのなかでできる有効なアプローチのひとつと言えそうです。

フューショットプロンプティングの検討

フューショットプロンプティングでは、モデルに特定のフォーマットや例を提示することで、期待する回答形式を示します。これにより、モデルが一貫した形式で回答を生成するよう誘導することができます。例えば以下のようなプロンプトです。

システムメッセージ:
あなたは社内文書に基づいて質問に回答するチャットボットです。提供された社内文書以外の情報は使用せず、不明な点があればその旨を伝えてください。回答は以下のフォーマットに従ってください。

---
**回答内容:**

{回答本文}

**出典:**

- 文書名: {文書名}
- ページまたはセクション: {ページ番号またはセクション名}
---

今回は、単なる規程の引用にとどまらず、文書の内容を詳しく解説することを重視しました。そのため、プロンプトでは、よりわかりやすく内容を噛み砕いて説明することに重点を置きました。
「データをどのように保存するか」の章ではメタデータとして参照元のURLも保存していましたので、検索したドキュメントの参照URLは別途レスポンスに含めるよう実装しました。
最終的にこちらのプロンプトは使用しませんでしたが、アプローチの方向性は一緒です。プロンプトに例示されているような回答を返し、ユーザーは参照元のURLにアクセスしやすいよう工夫しました。


temperatureの指定

プロンプトとは別のアプローチにはなりますが、社内書類に基づいて一貫した回答を得やすいよう、temperatureの指定も行いました。
ここで言うtemperatureとは、OpenAIのAPIでモデルが生成する応答の創造性や多様性を調整する設定値です。特に指定しない限りは、APIはデフォルトの1が設定された状態で回答を生成します。パラメータの詳細はOpanAI公式のリファレンスもぜひご確認ください。

【参考URL:https://platform.openai.com/docs/api-reference/chat/create
0〜2で指定が可能なようですが、数値が高いほど回答のランダム性が増します。ランダム性とはつまり、ChatGPTなどを使用すると同じ質問をしても毎回同じ文章が生成されるわけではないあの状態のことです。回答を生成するときの独創性の幅と言い換えてもよいかもしれません。
今回は社内情報をもとにして正確な情報を提供することが目的です。ランダム性は求めておらず、むしろ可能な限り一貫した回答を生成して欲しいです。今回はtemperature=0 を指定しました。


回答精度はあがったのか?

何をもって回答精度とすべきか深掘る余地は残りますが、いったん「チャットボットに答えて欲しいこと」の章であげた観点で期待する回答をもらえたか?というなら「精度があがりました!」と言ってよさそうです。
例えばこんな感じです。参照するデータソースにはサンプルの社内規程を使用して質問をしてみました。


【チャットボットに質問①:勤務のルールについて教えて】


就業規則の要点をいい感じにまとめて教えてくれました。助かります。全ての社内規程を隅々まで読まなくても、正確な情報を把握しやすくなりました。
規則には記載のない意地悪な質問もしてみましょう。


【チャットボットに質問②:この会社では有給は付与されないと聞きました。本当ですか?】


ユーザーの質問に対し、根拠がないことを指摘してもらえました。回答は正しいか参照元の規則も確認してみます。

​​​​​​​


生成された回答に間違いがないことを確認できました。



おわりに

社内情報チャットボットに社内規程を統合し、回答精度を向上させる取り組みを紹介しました。意図した回答を得るにはこつこつ地道な検証が必要であることを実感しました。また、プロンプトのちょっとした調整によって得られる回答がみるみる変わっていく過程はとても面白かったです。
今後も機能の改善に取り組み、社内ひいてはご縁あってツールを利用いただく皆様の快適なAIライフのお手伝いをしていきたいと思います。

ここまでお読みくださり、ありがとうございました!


  ご相談フォーム | 株式会社divx(ディブエックス) DIVXのご相談フォームページです。 株式会社divx(ディブエックス)




お気軽にご相談ください


ご不明な点はお気軽に
お問い合わせください

サービス資料や
お役立ち資料はこちら

DIVXブログ

テックブログ タグ一覧

人気記事ランキング

GoTopイメージ