※ こちらはミツモアAdvent Calendar 2022の2日目の記事です。
こんにちは、ミツモア データチームの藤井(@yuki_meetsmore_87910)です。
今回は、ミツモアで社内向けチャットボットを導入した話をします。特に、DialogFlow CX(GCP)をSlack threadでやりとりできるようにするためには、どうbotを構築したのかを中心にご紹介したいと思います。
目次
導入の背景
ミツモアではサービスの成長に伴い、dev support(開発チームへの問い合わせ対応)とカスタマーサポートの負荷が次第に増えている状況があり、日に日に悲鳴が上がってくるようになっていました。
それぞれどのような負荷があるかというと
dev support
- 開発業務との兼任でサポート対応をしている。そのため、問い合わせがたくさんくること自体が負荷。また、特定の領域に対しては専門のチームが最終的には対応するため
カスタマーサポート
- 複雑になってきているプロダクトのため、返答するために細かい条件別の正しい回答を素早く得ることができない
- 幅広い問い合わせがあるため、若手がスムーズに業務を遂行できない
そのため、データチームとしてチャットボットを導入し
- 問い合わせ発生 → bot分類 → bot内で解決もしくは分類後の解決案候補の提示
を実現することで少しでも負荷を減らすことを目的として活動を開始しました。
チャットボットサービスの比較
導入にあたって主に3つのサービスを比較しました。
- AWS LEX
- DialogFlow ES(GCP)
- DialogFlow CX(GCP)
比較の際考慮したポイントとして
- 返答時の精度が十分か?
- 導入コスト
- 運用コスト
の3つを比較しました。
1.返答時の精度が十分か?
使用した感想ですが、チャットの会話にブレが大きいとき、反応パターンの登録内容がざっくりしている場合でも、DialogFlowCXだと大まかな意味を組みとって推測してくれている感じがあります。
体感としては
DialogFlow CX >> DialogFlow ES == AWS LEX
2.導入コスト
スレッドでの会話をしない場合 DialogFlow ES == AWS LEX >>DialogFlow CX スレッドでの会話をする場合 DialogFlow ES == AWS LEX ==DialogFlow CX
もともとのDialogFlowの初期機能としてDialogFlow ES/AWS LEXには Slackインテグレーション機能がついています。
一方デフォルト機能はあまり完成度ととしては高くなく、Slackへのスレッドへの返信ではなくチャネルへの返信となってしまい、実用性としては不十分でした
自前でSlackとのインテグレーションを実施する場合、どれもコストは変わらないものと思われます。
3.運用コスト
運用コスト=1回あたりの実行×実行回数+固定コスト+メンテナンス工数
とした際に今回は固定コストはほぼ0かつ実行回数もそこまで多くはないので
メンテナンスコストによる人件費/工数の方が重要でした。
botの変更/管理を実施する場合はDialogFlow CXがもっとも手間が少なく、他のサービスでは次のような傾向がありました
DialogFlow ES:
応答の階層構造が深くなった際に(コンソールで実施する場合)操作がしずらい/語句間の衝突が階層を無視して起こることがあり、チャットに投げる質問/答えを何度も調整する必要があります。
AWS LEX: バックエンド処理などでlambdaで作成しないといけない処理が思いの他多く、更新が大変になると思われます。
そのため運用コストは
DialogFlow CX << DialogFlow ES << AWS LEX
上記を考慮し維持管理が楽かつ精度のよさそうなDialogFlow CXを最終的に使用することにしました。
DialogFlow CXの導入
全体的な構成としてはシンプルで
CloudFunction上にデプロイしたgo製のサーバーがSlack APIとDiaogFlowの通信を受け持つ形で
Slack上での会話を処理し、DialogFlowAPIに適宜リクエストを投げています。
DialogFlowの構築をDialogFlowそのものの構築とSlackAPI側とに分けて紹介していきます。
go 製のサーバーは基本的には以下ライブラリ/ツールを使用しつつ作成しました。
DialogFlow CXの構築
まずDialogFlow CXの構築を紹介します。
構築方法
以下DialogFlowの構築の際にいくつか関連用語が出てくるが、おおよそ以下の意味で使用します。
- routes(ルート): 分岐
- intent(インテント): ユーザーの発話がどの分岐に該当するかを決定するもの。分岐する際に使用する設定。
- flow(フロー): 会話をどのように分岐させていくかの一連の流れ。DialogFlowでは会話分岐の一部分を切り出してflowとして定義できる。
- fulfillments(フルフィルメント): ある分岐に至った際に実行される処理
- version(バージョン): flowごとに設定できるバージョン
- environment(エンバイロメント): 各バージョンをまとめたものをenvironmentとして定義でき、それぞれurlで指定してアクセスできる。
DialogFlowのAPIを有効化しDialogFlowのプロジェクトを作成すると下のような画面が見える。
DialogFlowとの会話が開始されるとStartの分岐が実行される。
ここで設定したroutes内のintentで指定した分岐がまず実行されることとなる。
new intent ボタンを押しintentを設定していく。
intentにその分岐を起動したいtraining phraseをいれる。(割とざっくりいれてもよしなに解釈してくれます)
fulfillmentにその分岐で実行したいボットからの応答を入力し、
next pageの欄で次に移動したい分岐を入力する。(フローにも分岐できます)
この処理を繰り返しチャットボットを作成します。
運用上の設定
上記作成し、そのまま何も指定せずにアクセスすると下書きが実行されることとなります。このままでは間違って変更した場合でも勝手に本番に反映されてしまうのでflowの編集が終わった時点でversionを設定し、実験用のenvironmentと本番用environmentを作成しました。environmentの切り替えはアクセスするurlを変更することで可能です。
イメージ
https://dialogflow.googleapis.com/v3/projects/"my-project-id"/locations/us/agents/"my-agent-id"/environments/"my_environment_id"/sessions/"my-session-id
Slack botの構築
続いて、Slack botの構築の紹介をします
Slack側
基本的には
github.com
のReadMeに従うことで進めていくことが可能です。
主要な設定として取得してサーバー設定(token.go)に入れる必要のあるもの:
- Bot token: OAuth & Permissionsの上部から取得可能(xoxb-....みたいなものです)
- Signing Secret: Basic Informationから取得可能
設定する必要のあるもの
- Subscribe to bot events - Event subscription: Slackからどのイベントの発生を受け取るかで以下を設定する
- Scope - OAuth & Permissions; botの権限で以下を設定する。
- Redirect URLs - OAuth & Permissions: cloud functionのURLを入力
- Request URL Event subscription: cloud functionのURLを入力
サーバー側
token.goの編集
また既存のものを使用する場合以下の課題があります。
- 会話がスレッド単位でなく個人単位(同じスレッド内で返信しても各ユーザーそれぞれ別の会話として認識されます)
- メンションが飛ばない
会話がスレッド単位でなく個人単位
ざっくり説明するとSlack handler.go内のsessionIdをuserからThreadTimeStampに変更することで解消できます。
# Slack handler.go dialogflowcxReq = DialogFlowCXRequest{ userInput: text, sessionId: user, credentialsPath: slackReq.credentials, }
メンションが飛ばない
共通設定
下記のようにメンションを飛ばす際、既存の設定ではメンションのコマンドまでエスケープされてしまうので、メンション箇所<@user_id>のエスケープを解除する必要があります
ユーザーにメンションを飛ばす場合
<@user_name> -> <@user_id>
user_nameでなくidをSlackのweb版から該当ユーザーをクリックし、そのurlから取得する必要がある
チームにメンションを飛ばす場合
<@team_name> -> <!subteam^teamID>
user_nameでなくidをSlackのweb版から該当ユーザーをクリックし、そのurlから取得する必要がある
導入した結果
部分的にはチャットボットでサポートができるようになりました!
よかった点の1つは、複雑な分岐のQAの場合、どの分岐を辿ってきたのかも合わせてbotがリマインドするように作成したことでした。カスタマーサポートからは次のようなコメントをいただきました!!
分からないことの答えだけではなく、順を追って確認でき、次自分で確認するときにどこを見たらよいかもわかるので勉強になってます!
・・・とはいえ、まだまだ全然解決できていない部分はたくさんあります。
理由としては、
- botで対応できている範囲がまだ狭い
- 回避策がまだまだ不十分
が大きな理由としてありました。主にドキュメントが乏しいことによるQA一覧の不足から発生しているため、これからもbotを経由で完結しなかった問い合わせデータなどを集約し、負担の大きそうな部分から整理してbot化を進めていきたいと思います。
最後に
ミツモアでは会社の4つのバリューのうちの1つであるテクノロジーでシンプルにを実現するために、日々このような活動も推進しています!! ご興味がある方はぜひ気軽に面談しましょう。