ChatGPT:公的保険FAQ302件の追加学習手法の比較(Fine-tuning vs Embedding/Retrieval/Grounding)
ChatGPTの欠点としてよく言われることに、最新の情報に対応していない(2021年9月まで)ことや、時には流れるように嘘をつくことが挙げられます。
この欠点を解消する画期的な仕組みとしてChatGPT Pluginが2023年3月24日にリリースされました。
以下は元Stripe CTOで、現OpenAI CTOであるGreg Brockmanのツイートで、WEB検索(Browsing)のPluginを有効にした時のデモ動画です。
動画ではChatGPTに「ChatGPT pluginの発表に対するHacker News(HN)からの反応は?」と尋ねています。すると、ChatGPTは自身でWEB検索を行ってHacker Newsの記事を参照し、出典を明示しながら回答してくれています。WEB検索を行うことができれば、最新の情報に回答できない欠点は解消されます。
WEB検索(Browsing)以外にもRetrievalというPluginが発表されています。Retrievalを用いれば、ChatGPTが個人や企業のファイル・メール・メモ等のデータをもとに回答することが可能になります。企業の独自データをもとに回答させることができれば、ChatGPTが"知ったかぶり"で嘘をつくことも防げます。
BtoBのソフトウェア企業がChatGPTを利用したサービスを展開する時、ChatGPTプラグインは扱いづらいです。全てのインターフェースがChatGPTによって支配されるためです。
そのため、企業の自社サービスのインターフェースにChatGPTのAPIを統合する方法が理想的です。自社の独自データを活用しながらユーザーとの自然な対話を実現できます。
さて、ChatGPTに自社の独自データを追加学習・参照させる手法にはどのようなものがあり、どれが最も優れているのでしょうか?
本記事では主な手法として考えられるFine-tuningとEmbedding/Retrieval/Groundingを比較検証しました。
事前準備①:公的保険アドバイザー協会のFAQ302件を用意
検証に用いるデータは公的保険アドバイザー協会様にご協力いただいて用意しました。公的保険アドバイザー協会とは、下記を事業目的としている協会です。
公的保険から始まるファイナンシャル・プランニングや保険サービスを定着させることを目指しています。
公的保険アドバイザーの公式HPのFAQに存在するFAQ44件と、会員限定のFAQ258件を学習データとして用います。
OpenAIでFine-tuningしやすいように、PromptとCompletionの2つのカラムからなるCSVを作成しました。FAQの質問をPrompt列に、回答をCompletion列に入力します。
公的保険アドバイザー協会様のご厚意で公式HPのFAQ44件分のCSVファイルを以下においておきます。
このCSVファイルをダウンロードして利用していただけたら、以降に載せているGoogle Colabのコードを実行可能です。(データはHPに公開されている44件のみですので、後述する結果と同じにはならないことをご了承ください。)
事前準備②:ChatGPTの回答精度を確認
追加学習の効果を検証するため、事前にChatGPTに公的保険に関する質問をしてみます。多くの方が気になっているであろう
「将来本当に年金はもらえるのですか?」
という質問をChatGPTに投げかけてみました。
GPT-3.5の回答は以下の通りです。
GPT-3.5の回答は、多くの国々の状況を抽象的に説明するだけで、いまいち参考にならなさそうです。
GPT-4の回答は以下の通りです。
GPT-4の回答は、多くの国々の状況を説明した上で、日本の年金制度にも言及しており、なおかつ一個人へのアドバイスまで含まれています。
この回答もなかなか良さそうですが、独自データを追加学習させることで精度は向上するでしょうか?
手法分類:独自データの追加学習手法
独自データを追加学習させるには大きく分けて2つの手法が考えられます。
A. Fine-tuning
B. Embedding/Retrieval/Grounding
以下に2つの手法を説明し、その結果を比較します。
A. Fine-tuning:302件では十分な精度が得られなさそう
Fine-tuningとは?
Fine-tuningとはGPT-3を独自データを用いて追加学習させることです。
GPT-3はそれ自体が約45TBのテキストデータを事前学習しています。学習データは、非営利団体Common Crawlが公開している世界中のWEBサイトをクローリングしたデータがもとになっています。
WEBサイトのクローリングデータにも公的保険に関する情報は含まれているでしょうが、公的保険に特化したデータではありません。公的保険に関するデータだけを追加学習させることで、精度向上が図れるかを検証します。
実行コード
以下にGoogle Colaboratoryで実行可能なコードをおいておきます。
※この後もコードを載せていますが、私はエンジニアではないのでコードが汚くてもご容赦ください🙏🏻 ChatGPTに全面協力してもらい、動くことを優先してコードを書きました。
コードを上から順に実行していけば、どなたでも結果を確認できます。OpenAIのAPI Keyの箇所はご自身のものに書き換えてください。
大まかな処理のステップは下記の通りです。
OpenAI toolsを用いて、CSVファイルをJSONLファイルに変換
JSONLファイルをOpenAIにアップロードしてfile_idを取得する
file_idを指定して、Fine-tuningを実行し、fine_tune_idを取得する(Fine-tuningの実行には1時間ぐらいかかります)
Fine-tuningの実行状況を確認し、実行が完了していたら、fine_tuned_model_idを取得する
fine_tuned_model_idを指定して、Fine-tune済のモデルにプロンプトを送り、回答を得る
以下の記事のコードを参考にさせていただいています。
結果
Fine-tuningさせたモデルに「将来本当に年金はもらえるのですか?」という問いかけをしたところ、回答は以下の通りでした
支離滅裂な回答になってしまっており、GPT-3.5に聞いた時よりも回答の精度は悪化しています。
他にもFAQに存在しているような内容を質問してみましたが、同様に回答が支離滅裂になってしまいました。
302件ではFine-tuningを行うにはデータ量が不十分なのかもしれません。
また、Fine-tuningの度にかかる費用と時間も痛いところです。Fine-tuningをする度に、302件のデータで一回あたり$20円、約1時間かかりました。
回答精度をあげるためには「どういったデータを増やしていけば良いのか」「どのようにデータをクレンジングすれば良いのか」などを分析していきたいところですが、Fine-tuningする度にそれなりの費用と時間がかかってしまうと、改善を進めづらいです。
B. Embedding/Retrieval/Grounding:質問を検索するのが精度が高そう
Embedding/Retrieval/Groundingとは?
Embedding/Retrieval/Groundingなど、いくつかの言葉で言及される手法は、Fine-tuningのように追加学習させる訳ではありません。
下記画像のように、ユーザーからの質問に対して、事前に外部情報を取得しておき、その結果と質問をGPTに与えて回答を得る手法です。
上記図のように、例えばユーザーから「2023年のWBC優勝国はどこ?」という質問があった場合、GPTは2021年9月までのデータしか学習していないため回答ができません。
そこで、こういった質問があった場合には、GPTにクエリを投げる前に、bing APIを用いて「WBC 2023 優勝国」というクエリでWEB検索を行い、結果を取得しておきます。
ユーザーからの「2023年のWBC優勝国はどこ?」という質問と、「WBC 2023 優勝国」をWEB検索した結果を、セットでプロンプトとしてGPTになげて最終的な回答文を生成してもらうという仕組みです。
この例ではWEB検索を行っていますが、WEB検索の代わりに企業の独自データを検索すれば、そのデータをもとにした自然な回答を行わせることが可能です。
この手法をOpenAIはRetireivalと呼んでおり、MicrosoftはGroundingと呼んでいるようです。
Embeddingという言葉もこの手法を言及する際によく出てきますが、Embedding自体は独自データのドキュメント検索をする際に、検索対象と検索クエリをベクトル化することを意味します。
ドキュメント検索の手法はベクトル検索だけではないので、下記の図に記載のように検索エンジン(セマンティック検索)を用いても構いません。
ベクトル検索で質問を検索するか?回答を検索するか?
今回は、OpenAIのEmbeddingのためのAPIであるtext-embedding-ada-002を用いて、ベクトル検索を行います。具体的には検索対象であるFAQのテキストデータをベクトル化しておきます。検索クエリもベクトル化し、FAQと最も類似度が高いものを検索結果として利用します。
さらに、FAQの質問と回答のどちらを検索対象とするかで2つのやり方があります。
例えば、FAQ検索システムであるHelpfeelでは、下記の図の通り、質問に当たる回答を探すのではなく、質問の言葉から「質問を探す」仕組みにすることで、精度を向上させていると記載があります。
実行コード(回答を検索)
まずはユーザーからの質問で、FAQの回答を検索する手法を確認します。
FAQの回答の中でユーザーからの質問と最も類似度が高いものを利用して、回答を生成します。FAQの質問は全く使いません。
以下にGoogle Colabで実行可能なコードを載せておきます。
コードの処理の大まかなステップは以下の通りです。
検索対象のFAQの回答に対して、text-embedding-ada-002を用いてEmbeddingを行ってベクトル化
ユーザーからの質問に対して、同様にtext-embedding-ada-002を用いてEmbeddingを行ってベクトル化
ベクトル化されたFAQの回答とユーザーからの質問を照らし合わせて、最もコサイン類似度の高い回答を特定
選ばれた回答とユーザーからの元々の質問をもとに、gpt-3.5-turboを用いて、自然な回答文を生成
結果(回答を検索)
「将来本当に年金はもらえるのですか?」という質問に対して、以下のような回答が得られました。
年金支給額がどういう要因で変動するのかを教えてくれました。かなり具体度の高い回答になったのではないでしょうか。
実行コード(質問を検索)
次はユーザーからの質問で、FAQの質問を検索する手法です。
まずユーザーからの質問と最も類似度が高いFAQの質問を特定します。その質問に対応する回答を結果として利用します。
質問との類似度を取ったほうが、精度が高くなるだろうという想定です。
前述したHelpfeelの検索手法も同様のステップを踏んでいます。
以下にGoogle Colabで実行可能なコードを載せておきます。
コードの処理の大まかなステップは以下の通りです。
検索対象のFAQの質問に対して、text-embedding-ada-002を用いてEmbeddingを行ってベクトル化
ユーザーからの質問に対して、同様にtext-embedding-ada-002を用いてEmbeddingを行ってベクトル化
ベクトル化されたFAQの質問とユーザーからの質問を照らし合わせて、最もコサイン類似度の高い質問を特定
選ばれた質問に対応する回答とユーザーからの元々の質問をもとに、gpt-3.5-turboを用いて、自然な回答文を生成
コード自体はほとんど変わらないのですが、回答ではなく最も類似度の高い質問を検索し、それに対応する回答から、最終的な回答文を生成しています。
結果(質問を検索)
「将来本当に年金はもらえるのですか?」という質問に対して、以下のような回答が得られました。
年金制度の加入義務や自前保障を準備することの困難さへの言及があり、最後に年金加入を勧めるという、最も精度の高い回答になりました。
Embeddingの価格は1000トークンあたり$0.0004で、Fine-tuningの1000トークンあたり$0.03と比べると75分の1です。302件のデータにEmbeddingを行っても、1回あたり$1もかからず、処理も数分で完了します。Fine-tuningに比べると遥かに精度の改善は進めやすそうです。
また必要に応じて出典となったFAQを示すことも可能です。回答の精度が十分に担保できない中でも、出典を示すことができればサービス化しやすくなります。
まとめ
OpenAI CTOであるGreg Brockmanは下記のツイートの通り「LLMのプラグインではRetrievalが最も主流になるだろう。どんな組織でも AI によってデータを検索を可能にするからだ。」と述べています。
今回、Fine-tuningとEmbedding/Retrieval/Groundingを比較してみて、Greg Brockmanの言う通り、少ないデータ件数でも費用を抑えて精度を高められるEmbedding/Retrieval/Groundingに可能性を感じました。
さらなる精度向上のためのチャレンジ
さらにEmbedding/Retrieval/Groundingで精度を高めるには以下の手法が考えられます。
最も類似度の高い検索結果だけでなく、上位の何件かの検索結果を組み合わせて回答を生成する
最後の自然言語生成のプロンプトを工夫する
また、何よりも、検索対象となるFAQのデータの量と質を向上させることで、精度向上が図れるでしょう。
今回は公的保険に関する専門的なQ&Aのデータのみを用いましたが、ユーザーからの幅広い質問に備えるとすれば、日本年金機構や厚生労働省のHPからデータを収集しておくと良さそうです。
一般的な企業の独自データの追加学習に必要になること
今回は独自データがFAQであったため、元からデータが質問と回答に分かれていました。また回答もほどよい文章量になっていました。
一方で、多くの企業の独自データは質問と回答には分かれていないでしょう。また文章の長さも様々かと思います。
従って、以下2つの前処理が必要です。
適切な文章量で元データを分割(チャンク化)
検索対象となる文章から、質問を生成
最適なチャンクデータ長の探索や、ドキュメントからのQA生成を行うLangChainのQAGenerationChainの実行なども行われていますし、QAの評価を行う仕組みも出てきているようなので、色々と組み合わせて最適化していくと良さそうです。
長文をお読みいただきまして、ありがとうございました!