ChatGPTを使って新たなマッチング体験を創出する
はじめに
こんにちは、Unlaceのフロントエンドを開発している岩下です。
Unlaceは、オンラインカウンセリングサービスを提供するプラットフォームです。プロのカウンセラーと、悩みや問題を抱えるクライエントを結びつけ、適切なソリューションを見つけるお手伝いをしています。
今回は、先日公開されたChatGPTのAPIを使ったUnlaceの新機能「Searchlight」について紹介します。
実装の細かな解説というより、ChatGPTの活用法の一つとして読んでいただければと思います。
Searchlightとは?
Searchlightを一言で表すと「カウンセリングケースを検索する機能」となります。
ただし、従来のキーワードによる検索や条件フィルタリングとは違い、悩みの内容を文章として入力するだけで、似た悩みを抱えた他の人がどのようなカウンセラーに相談しているのかを検索することができます。
これまでデータとして活用できていなかった過去のカウンセリングケースをマッチングの質向上に用いることで、クライエントはより自分に合ったカウンセラーを見つけることができるようになりました。
ここからは、Searchlightの仕組みについて少し詳しく見ていきます。
Searchlightは大きく分けると「カウンセリングのケース化」と「主訴解析&類似ケースの検索」の2つの要素から構成されています。
Searchlightの仕組み: ①カウンセリングのケース化
Unlaceではカウンセラーとクライエントのやりとりはテキストチャットで行われます。そのため、カウンセリング事例はテキストデータとして蓄積されています。
ChatGPTを使ってこのテキストデータから主訴を抽出し、ケースとして保存します。
主訴の抽出
主訴を抽出する際は、類似度の計算で利用しやすいよう文章に一定の規則性を持たせる必要があります。
表現に揺らぎがあったり、構成がバラバラだと、類似度の計算で幅が出やすくなってきます。
この要件を満たすため、次の3つのポイントに注意しています。
余分な情報を取り除く
今回はモデルに gpt-3.5-turbo
を採用したため、入出力合わせて4096トークンまでの制限があります。カウンセリングはその期間にも依りますが、この制限を超えてしまうものが殆どのため、コンテキストとして全てのやりとりを与えることはできません。
また、カウンセリング中は主訴とはあまり関係のないやりとりも多く、全文をChatGPTへ入力しても悩みや顧客の状況を端的に表した要約にはなりません。
そのため、検索での利用を目的とする場合はChatGPTへ与える情報をある程度絞り込んだほうが良い結果が得られます。
誰の・いつの発言だけを与えるかなど、プロンプトの調整と合わせて精度においては非常に重要となります。
規則性を持たせる
文章に一定の規則性を持たせるため、主訴は抽出した後に一定のルールで再構成するようChatGPTに指示しています。
このようにすることで、クライエントがケースを読み易く、また類似度計算の安定性も増すため、プロンプトの調整には割と時間を費やしました。
どういったプロンプトにするか、というのはサービスの属性にも依るため詳細は割愛しますが、ChatGPTへの指示に「客観的な文章にしてください」と含めるのはとても効果的でした。
個人情報をマスクする
カウンセリング事例のテキストデータには、クライエント個人を特定できる情報が含まれていることが多くあります。
OpenAIの規約では、APIに渡したデータはモデルの学習やサービスの提供で利用されることは無い、と明記されてはいますが、だとしてもカウンセリングのようなセンシティブなデータをそのまま渡すことは好ましくありません。
そのため、弊社では個人情報(氏名・住所・メールアドレスなど)は予め事前に処理した上でAPIへ入力しています。
また、前述した事前処理では弾けなかった「個人情報ではないが個人の類推ができうる情報」[1]は、ChatGPTからの出力後に人間の目による確認を挟むことで対応しました。
主訴の保存
抽出した主訴をEmbeddingして、検索で利用するためベクトルデータベースに保存します。
今回は、EmbeddingにOpenAIのEmbeddingsAPIを、ベクトルデータベースにWeaviateを選択しました。
Embedding
EmbeddingsAPIは入力した文章をベクトルとして返却してくれるAPIです。
一般にEmbeddingは文章の意味をベクトル化するために用いられますが、ベクトルの距離が近いほど意味が近いという性質を持つため、類似度計算にも利用できます。
利用できるモデルには第1世代と第2世代のものがあり、OpenAIはほとんどのタスクにおいて text-embedding-ada-002
を推奨しているため、こちらを利用しました。
ベクトルDB
Embeddingした文章は単なるベクトルのためRDB等に保存することもできますが、検索時の利便性を考えベクトルデータベースに保存することにしました。
ベクトルの最近傍探索はコサイン類似度を総当りで計算することでも実現可能ですが、その量に応じて計算量やメモリ使用量が増加していきます。
ベクトルデータベースはベクトルの近似最近傍探索を高速に行うためのデータベースで、検索時の計算量やメモリ使用量を抑えることができます。
今回はWeaviateというベクトルデータベースとして機能するオープンソースのソフトウェアを選択しました。
DockerイメージのほかSaaSも提供していて、本番環境ではこちらを利用しています。
比較対象としてGoogleのVertex AI Matching EngineやPineconeなどを検討しましたが、 今回はベクトルの近似最近傍探索ができれば良いので、GoのSDKの充実度や費用を考慮した上でWeaviateを採用しました。
またWeaviateはデフォルトでOpenAIの各種APIと連携する機能を持っているため、今後予定しているSearchlight以外の機能実装時にもOpenAIが提供する機能との連携がし易いことも選定理由の一つでした。
Searchlightの仕組み: ②主訴抽出&類似ケースの検索
クライエントが入力した悩みの具体的な内容をケースと同様のルールで処理して主訴を抽出し、 ケースとの類似度を計算して類似ケースを検索します。
主訴抽出
クライエントが入力した文章から、ケース化と同様の指示を与えてChatGPTで主訴を抽出していきます。
こちらの作業はユーザーのアプリ利用中にリアルタイムで完了させる必要があるため、ChatGPT APIのstreamパラメータを利用して逐次結果をSSEから受け取るなど、ユーザーにストレスを感じさせない工夫をしています。
類似ケースの検索
Weaviateに保存したケースの主訴のベクトルと、クライエントが入力した悩みから抽出した主訴のベクトルのコサイン類似度を計算します。
近似最近傍探索による類似度の計算は、あくまで近似のため正確な値を計算することはできませんが、テストした限りでは十分な精度で類似度を判定できているようでした。
また、コサイン類似度で上位数件まで絞ったあと、それをコンテキストとしてChatGPTに再度類似度を尋ねることで、より精度の高い類似度を出力する試みをしています。
補足事項
PoCによる事前効果検証
Searchlightの実装にあたって、前述した仕組みによる類似度の判定が「人が読んで似ていると感じる」程度に納得度のあるものなのか、事前に検証する必要がありました。
そこで、初めに数百件のデータを用いて簡単なアプリを作り、社内で触ってもらうことで事前効果検証を行いました。
このPoCにより、類似度の精度の確認はもとより、検索結果が特定のカウンセラーへ偏る問題や、検索速度がUXに与える影響など、様々なフィードバックなどを得ることができました。
GPT-4を選択しなかった理由
GPT-4は、GPT-3.5 Turboと比較して要約タスクの精度が高くなっています。
実際にGPT-4を使用して主訴を抽出すると、文章がより自然に生成されることが確認できました。
しかし、あまりにも端的にまとまり過ぎていて読み応えがないと感じる部分もありました。
また、GPT-4はGPT-3.5 Turboと比べて実行に非常に時間がかかり、現時点ではリアルタイムでの利用には適していないと感じました。
事前処理であるカウンセリングのケース化だけでもGPT-4で実行できないか検討しましたが、同じプロンプトでもGPT-3.5 Turboとは大きくテイストが異なる文章が生成されるため、類似度の判定への影響が懸念されました。
これらの理由を総合的に判断し、今回はGPT-3.5 Turboを採用することにしました。
特許の出願について
弊社ではこの仕組みに関して特許を出願していますが、それは悪意を持った第三者から後出しで圧力を受けることを回避するためだけを目的としたものであり、仕組みの独占を目指すものではありません。
ぜひ、参考にしていただければ幸いです。
まとめ
ChatGPTを使うことで、NLPを専門としないエンジニアでもSearchlightのような機能を実装する事ができるようになりました。
まだまだ改善の余地はありますが、今後も機能の拡張や精度の向上を図っていきたいと思います。
Unlaceでは引き続き、クライエントとカウンセラー双方がよりよい体験を得られるサービスを提供していくため、様々な技術に挑戦していきます。
-
メンタルヘルスケアサービスを運営している会社の経営者、といった情報 ↩︎
Discussion