👁️‍🗨️

Slackで社内文書検索 4/4回(任意のLLMによる回答生成編)

開発の流れは以下の通りです。
💡
開発の流れ
  1. Slack APIアプリの作成と設定
  1. Vertex AI Searchのアプリの作成とデータストアの自動更新
  1. Slackからのコマンドとメッセージの受信
  1. 任意のLLMによる回答生成
今回は任意のLLMによる回答生成について説明していきます。
Cloud Functionsのファンクションの作成やコードだけが見たい方はこちら

概要

今回は以下の処理のうち、Pub/Subからイベントを受け取って、ユーザに返答するまでの処理の説明をします。

任意のLLMによる回答生成

今回の見出しが任意のLLMとなっているのは、コマンドによってLLMを指定して回答を生成するようにしているからです。コマンドは「Slackで社内文書検索 1/4回(Slack APIアプリの作成と設定編)」の記事で示しましたが、再度示しておきます。
コマンド説明備考
/palm2回答生成に使うLLMモデルを「PaLM2」にする。コマンドに続けて質問文を送る。
/gpt-3回答生成に使うLLMモデルを「GPT-3.5」にする。コマンドに続けて質問文を送る。
/gpt-4回答生成に使うLLMモデルを「GPT-4」にする。コマンドに続けて質問文を送る。
回答生成では、Vertex AI Searchのアプリを用いて、メッセージ(質問)に対する関連資料を検索し、任意のLLMモデルを使ってその資料の内容を参考に質問に関連する回答を生成します。
回答生成の処理の概要を以下に示します。

1. イベントを受け取る

Pub/Subからイベントを受け取る部分は、Cloud Functionsでファンクションを作成する際にトリガーとしてPub/Subを指定することで実現にします。
設定方法はこちらで説明しています。
受け取ったイベントからメッセージとコマンドを取り出すには以下のように関数を定義します。

2. 資料を検索する

ここではVertex AI Searchのアプリを使って、質問に関連のある資料を検索します。
今回はLangChainのRetrieversのGoogleVertexAISearchRetrieverを用いてVertex AI Searchの検索機能を実装しました。
GoogleVertexAISearchRetrieverを呼び出す際にたくさん引数を渡しますが、今回はmax_documentsに注目して説明します。その他の引数の説明についてはこちらをご覧ください。
max_documentsは検索結果として表示する資料の数を指定するものになります。今回は1にしていますが、データストアが大規模になるにつれ、関連資料が増えてくると考えられるので、将来的には複数の資料を引用して回答生成することも視野に入れています。
上記のresultには参考資料のURLやその資料の要約などが含まれていますが、要約の精度があまり良くなかったので、今回はURLのみを利用します。
また、documentではURLから資料の名前(例:○○.pdf)を取り出しています。

3. 資料をロードする

ここでは、検索してきた資料の内容をロードします。
今回は、LangChainのDocument loadersのGCSFileLoaderを用いて、ファイルをロードします。
関数の中で、資料検索とファイルのロードをしています。

4. 回答生成

ここでは、PaLM2とGPT-3.5、GPT-4の3つのLLMで回答を生成します。
今回は、LangChainのChainsを用いて回答を生成します。回答生成の処理は以下のようになります。PaLM2ではStuff、GPT-3.5、GPT-4ではMap Reduceという方法をとります。
回答生成の処理
  • GPT-3.5とGPT-4
    • GPT-3.5、GPT-4では回答生成に、load_summarize_chainを用います。
      load_summarize_chainを用いることで、Map Reduceを簡単に実装できます。
      処理の流れを簡単に説明します。まず、参考資料を分割して、それぞれの資料から回答生成に必要そうな情報を抽出します(下のコードのPROMPT)。次に、分割された資料から抽出した情報から回答生成を行います(下のコードのCOMBINE_PROMPT)。
      以下にコードを示します。

回答生成と返信をするファンクション

以上の説明を踏まえてファンクションを作成します。
今回作成するファンクションの作成方法は前々回の記事と変わらないので、こちらを参照してください。ただし、前回の記事と異なる部分があります。その部分は以下に従ってください。
📌
変更内容
  1. トリガー
    1. HTTPS
      1. 未認証の呼び出しを許可を選択
    2. トリガーの追加
      1. 説明
        1. トリガーを追加を選択します。
        1. Pub/Subトリガーを選択します。
        1. イベントで「google.cloud.pubsub.topic.v1.messagePublished」を選択します。
        1. Cloud Pub/Sub トピックを選択してくださいで前回の記事で作成したトピックを選択します。
        1. トリガーを保存を選択します。
  1. ランタイム環境変数
    1. 以下の4つを追加
      1. 名前
        PROJECT_IDGoogle Cloud のプロジェクトID
        BUCKET_IDGCSのバケット名 (gs:// は不要)
        DATA_STORE_IDVertex AI SearchのアプリのデータストアのID
        OPENAI_API_KEYOPENAIのAPIキー
        SLACK_BOT_TOKENアプリの認証に用いるトークン
        SLACK_SIGNNG_SECRETリクエストの認証に用いるサイン
        WEBHOOK_URLSlackのワークスペースのチャンネルに返信するのに用いる
        SLACK_BOT_TOKEN
        1. Slack APIのページに移動
        1. 作成したアプリを選択
        1. サイドバーのOAuth & Permissonsを選択
        1. OAuth Tokens for Your WorkspaceBot User OAuth Tokenをコピー
        SLACK_SIGNNG_SECRET
        1. Slack APIのページに移動
        1. 作成したアプリを選択
        1. サイドバーのBasic Informationを選択
        1. App CredentialsSigning SecretShowを押す
        WEBHOOK_URL
        1. Slack APIのページに移動
        1. 作成したアプリを選択
        1. サイドバーのIncoming Webhooksを選択
        1. Webhook URLs for Your WorkspaceWebhook URLから今回のSlack APIアプリのインストール先のチャンネルに対応したWebhook URLをコピーします。
  1. main.py
    1. code
  1. requirements.txt
    1. code
  1. エントリポイント
    1. send_slack_messageに変更
 
以上でファンクションの作成は終了です!
回答のクオリティについては、PaLM2はVertex AI Searchのアプリのデータストアの中の資料にない内容を質問するとハルシネーションが起きてしまいました。
また、PaLM2は出力の大きさが比較的小さいため、GPT-3.5やGPT-4に比べ、ざっくりとした回答になりました。
GPT-3.5、GPT-4に関しては、申し分ないクオリティの回答を生成する上に、私が行った実験の中ではハルシネーションは起こしませんでした。

最後に

今回は任意のLLMによる回答生成の説明をしました。これで、Slackで社内文書検索システムシリーズは終了になります。今後の展望としては、参考資料を増やして回答生成を行ったり、PaLM2を活用できるプロンプトやパイプラインを探していきたいです。

参考