Slack AI のようなものを自作する - 検索機能編
はじめに
本日はSlack AI[1]のようなものを自作するというテーマでブログを書きます。Slack AI が出てから時間が立っているので旬なネタではないかもしれませんが、ここで供養したいと思います。Slack AI には多くの機能がありますが、今回はその中でも検索機能を模倣した自作プロジェクトについてお話しします。
免責事項
- 本ブログの情報は公開日時点のものです。
モチベーション
フローデータをうまく活用したい
Slackの情報はどちらかというと「フローデータ」として流れていく性質のものです。しかし、長年使い続けていると、その中に貴重なナレッジが蓄積され、非常に有用な資産となることがあります。そこで、このフローデータをうまく活用するために、Slack AIのような検索機能を自作し、効率的に情報を再利用したいというモチベーションがあります。
Slack のデフォルトの検索機能に満足できない
もちろん、Slack にも検索機能がデフォルトで搭載されていますが、正直ベースで不十分です。キーワードやユーザーで絞り込みつつ、たくさんの投稿を確認する必要があるケースがあり、シームレスに知りたい情報にアクセスできません。
コストは抑えたい
現在の Slack AI はワークスペース全体にライセンスが付与される形態となっており、大規模な組織ではコストが高くつきがちです。実際にはAIを必要としないユーザーにもライセンスを提供しなければならず、その分コスト負担が増してしまいます。自作することで、このコストを削減することができるのではないかという期待もあります。
実装方式の検討
Slack AIの検索機能を模倣するためには、いくつかの実装方法が考えられます。ここでは、検討した4つの実装方法を紹介します。
実装方法1. 検索サービスにSlackのメッセージを全てインデックスする
Amazon Kendra、Azure AI Search、Google Vertex AI Search などの検索サービスやデータベースに、Slackのパブリックチャンネルのメッセージを連携し、インデックスを作成する方法です。この方法では、必要に応じてベクトル検索などを組み込むことで、高度な検索機能を実現することが可能です。Azure AI Search を利用の場合はデータコネクタなどが用意されておらず、それも自作する必要がありますが、Amazon Kendra[2] 、Google Vertex AI Search[3] (これは試してない)では、コネクタが用意されており、簡単にデータを蓄積することができます。
全てのデータを対象とできるメリットもありながら、デメリットとしてはコスト的な部分があります。当然、データ量が増えればインフラのコストが上がっていくので、あまりコストメリットがでない可能性があります。また、Slackでtimesなどをやっている会社は、timesに大量の雑談が流れてくる可能性があります。これは、業務に関する情報を探したい場合のノイズになる懸念があります。場合によっては、高度な検索手法を使っても検索精度があがらないなどの懸念があります。
よくあるtimesの投稿
実装方法2. 検索サービスにSlackのメッセージを一部インデックスする
全てのメッセージをインデックスするのではなく、一部のデータのみをインデックスする方法です。Slackのデータは多くの無関係な情報も含んでいるため、すべてをインデックスすると精度が低下したり、コストが高くなる可能性があります。そのため、「ナレッジ」と見なされるメッセージにスタンプを押すことで、そのメッセージだけをインデックスするアプローチを検討しました。
実装方法3. Slack の Search API を使う
Slack には Search API [4] が用意されているため、それを利用する方法も考えられます。ユーザーが質問を入力した際に、OpenAI の Function Coding(Structured Output)を使って検索クエリを生成し、その結果をもとにユーザーへ回答します。この方法ではインデックスを自前で構築する必要がないためコストが最も安く、常に最新のデータをリアルタイムで検索できるという利点があります。
一方でデメリットとしては、SlackのSearch APIはリッチな検索手法ではありません。検索仕様についての情報はみつかりませんでしたが、おそらくただのキーワード検索を利用している(注意:筆者推測)ため「こんばんわ」と「こんばんは」や「Defender for Endpoint」と「MDE」といった表記揺れには弱いという傾向があります。もちろん、OpenAI の Function Coding(Structured Output)を使っての検索クエリ生成で複数検索キーワードを生成するということも考えられますが、実装方法1で言及したように検索対象のデータが汚いと限界があります。
実装方法4. Notion AIを使う
Notion AI を利用して Slack のデータをインデックスし、回答を生成する方法も考えられます。Notion AI は Slack のデータだけでなく、他の情報源も統合してインデックスを作成し、それに基づいた回答を提供することができます。SlackとNotionを連携させることで、より広範な情報を検索対象にできる点が利点です。
一方で、デメリットとしては、Notion AIでインデックスできるSlackのデータは過去1年分のパブリックチャンネルかつ、外部と共有していない(Slack Connect)チャンネルのみです[5]。正直、この範囲では物足りなさがあります。また、Notion AIもワークスペース全体での契約が必要なため、コストを下げるという目的から考えると
採用した実装方法
実装方法 | メリット | デメリット |
---|---|---|
1. 検索サービスに全メッセージをインデックス | 高度な検索機能を実現可能。 | データ量が多くなるとコストが高い。精度が下がる可能性 |
2. 一部メッセージをインデックス | コストが抑えられる。必要な情報だけを効率的にインデックス可能 | インデックス対象の選定が必要。見落としの可能性 |
3. SlackのSearch APIを使用 | インデックス構築が不要。常に最新のデータをリアルタイム検索可能 | 検索精度が他の手段に比べて低くなる傾向がある |
4. Notion AIを使用 | Slack以外のデータも統合して検索可能。広範な情報を対象にできる | Notion AIの契約が必要。インデックス対象が広がりすぎる可能性 |
以上の実装方法のメリット・デメリットを比較した結果、今回採用したのは「実装方法2」です。理由としては、全メッセージをインデックスする方法ではコストが高くなる割には検索の精度が上がらない点です。例えば、実装方法1のようにAmazon Kendora を立てて、Slack のデータをインデックスすると、Developer Edition で$810/月(約10万円ちょっと)、Enterprise Edition だと$1008/月(約15万円)です。[6] もちろん、他の用途で使うことも考えられるものの、Slack単体ではペイしなさそうな印象をうけます。
また既に「helpme-helpyou」チャンネルなど特定のチャンネルにナレッジが集中していたので、ひたすらスタンプを押すことで効率的に必要な情報だけをインデックスできる状況でした。今後の運用としても、ナレッジとして残したい「神投稿」を厳選してインデックスすることで、綺麗なインデックスを維持できる期待を込めてこれを選定しています。
実装のポイント
データ蓄積部分
データ蓄積部分では、Function Coding(Structured Output)を使ってデータを構造化し、蓄積しています。「ナレッジ追加」というスタンプを用意し、それが押されたメッセージをトリガーにしてスレッド全体を取得します。そのスレッドを「タイトル」「質問」「回答」「URL」などの形式でデータ保存します。このデータはAzure AI Searchに保存し、カスタムスキルを使ってベクトルデータに変換する仕組みです。
AIによる回答生成部分
AIによる回答生成部分は非常にシンプルです。ユーザーがボットにメンションをつけて質問をすると、その質問に対してAzure AI Seach で検索を行い、最も関連性が高い情報をピックアップします。さらにFunction Codingを通じてリランキングを行った後、Azure OpenAIに情報を渡して回答を生成します。
また、以下のように回答に利用したURLを渡すことで、ユーザーが検証可能としました。
コスト
最後にコストの話をします。コストとはいっても、皆様ご存じの通り、AIの部分はトークン課金で見積もりが難しいのですが、50人程度で利用した実績値を共有します。
- Azure OpenAI(GPT-4o-miniを利用):数百円/月(1回の実行で1円以下
- Azure AI Seach Basic プラン:1万ちょい/月
Azure AI Search は Standerd にしたりするとコストは上がりますが、Basicの利用だけではそこまで高額になることはありません。法人のお財布からすると安いものだと思います。
終わりに
今回はSlack AIの検索機能を模倣して自作する取り組みについて紹介しました。今後、余裕があれば他のSlack AIの機能についても自作する取り組みを進めていきたいと思います。
Discussion