詳説：GPT-3を利用して任意の文書を解析する


検索エンジン、そして今ではChatGPTのようなAIアシスタントにより、私たちはインターネットから関連情報を取得するための強力なツールを手に入れました。しかし、組織においては、会議の議事録、法律文書、製品仕様書、技術文書、研究開発報告書、業務手順書などの非公開文書から情報を抽出することも必要です。

この記事の内容：
- 一連の文書に対して、**GPT-3**と"***retrieve-then-read***"パイプラインを使用した**簡単な質問応答システムの構築方法**を紹介します。
- **Dataiku Webサイト上の技術文書**を対象として、手法の**実践的な**適用方法・適用例を説明します。
- 皆様それぞれの用途にも再利用可能な**Dataikuプロジェクト**を紹介します。


## 自己回帰言語モデルとGPT-3
近年の言語モデルは、単語並び順の尤度を計算するために学習したニューラルネットワークであるともいえます。とくに***自己回帰言語モデル***では、先行するすべての*トークン*（単語または単語の一部）が与えられたときに、次のトークンの確率を推定します。

自己回帰言語モデルで最も有名なのは、2020年5月にOpenAIが[発表した](https://arxiv.org/abs/2005.14165)**GPT-3**です。GPT-3は驚異的なスケールで学習されました。GPT-3は1750億のパラメータを持ち、その学習データセットは5000億トークン近くあります（一方で、Wikipediaのトークンは30億）。その結果、GPT-3は次のトークンを予測するためだけに訓練されたにもかかわらず、質問応答、要約、翻訳、分類など、**さまざまな自然言語処理タスク**を追加の訓練なしに効果的に実行することができるようになりました。この汎化は、推論時に例を与えるかどうかにより、[ゼロショット学習または少数ショット学習](https://arxiv.org/abs/2005.14165)と呼ばれます。

これらの能力を活用する鍵は、**正しいプロンプト**（モデルがその後完成させる最初のテキスト）を、一度に1つのトークンずつ提供することです。次の図は、質問応答タスクのプロンプトとGPT-3による補完の流れを示しています。

*GPT-3を活用したナイーブな質問応答パイプライン*
![user question.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196881/202c737f-fa02-f866-daa4-30bb807cf23c.png)

OpenAIは最近、2021年6月までに収集したコーパスで学習し、さまざまなタスクを微調整したGPT-3モデルの改良版である**GPT-3.5**をリリースしました。以下では説明を簡単にするため、これらすべてのモデルを総称して「GPT-3」を使用します。


## Retrieve-Then-Read パイプライン
上記の質問応答の例では、モデルはアシスタントとエキスパートの両方の役割を果たします。つまり、質問を解釈し、自身の知識に基づいて回答を作成します。しかし、この知識は限定的であり、特に最近の文書や非公開の文書には対応していません。幸いなことに、GPT-3は**retrieve-then-readパイプライン**を用いることで、有用なアシスタントになることができます。

例えば、ある特定の文書のコレクションをもとに回答を得たいとします。下の図に示すように、retrieve-then-readパイプラインは次のステップを実行します。

1. ユーザーから質問を受け取る。
2. 質問と意味的に最も類似した文章を文書のコレクションから取得する。
3. 質問と取得した文章を含むプロンプトを作成する。
4. GPT-3にプロンプトを送信する。

*Retrieve-then-readパインプライン*
![Retrieve-then-read pipeline .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196881/3da0c9ba-7ddc-b369-a226-655a4748ecc5.png)


このようにすることで、言語モデルが正確な回答を作成するために必要な情報を提供可能と考えられます。もちろん、実現レベルは文書の集まりから適切な文章を抽出する能力に依存します。この**セマンティック検索**は、次のような方法で実現できます。

<br>
<br>


前処理（文書が次に更新されるまでに、一度だけ実行）：
- 文書からテキストを抽出する。
- テキストを小さな塊（チャンク）に分割する。（無関係な情報を含まず、かつプロンプトサイズの制限内に収めるため、通常1〜数段落の大きさとなる。）
- 各チャンクに埋め込まれた情報を、あらかじめ学習させた類似度モデル、もしくはBM25のようなBag of Words取得関数で計算する。
- これらの埋め込み情報をインデックス化し、高速な類似性検索を可能にする。（オプション）
<br>

次に、各質問に対して：
- 質問の埋め込み情報を計算する。
- この情報に最も類似した埋め込み情報を持つK個のチャンクを探索する。
<br>

詳細については、[セマンティック検索](https://medium.com/data-from-the-trenches/semantic-search-an-overlooked-nlp-superpower-b67c4b1b119a)に関する以前のブログ記事をお読みください。


## Dataikuの技術文書から回答を抽出する

*プロトタイプ画面のスクリーンショット*
![dftt-Feb-10-2023-04-13-37-9856-PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196881/51c90da7-fe0c-12d8-d1ef-aa5267b36c71.png)


ここで、**具体的な例**に目を向けてみましょう。Dataikuのユーザーや管理者が利用できるドキュメントは、2,000以上の公開ウェブページから構成されます。これは、Dataikuの豊富な機能と多用途性を証明するものです。しかしこれは同時に、特定の答えを見つけることが難しいということでもあります。

これらの文書はインターネット上で公開されているため、標準的な検索エンジンを利用できます。しかし、せいぜい関連するウェブページを特定できる程度で、正確な答えを見つけるかどうかは利用者次第です。一方、ChatGPTは答えを導き出してくれるため、この労力を軽減できます。しかし、ChatGPTのレポジトリは古いドキュメントのスナップショットのみを参照しているため、最新のDataikuバージョンには対応していないという制約があります。とはいえ、GPT-3によるretrieve-then-readパイプラインの実験に適したユースケースであるとも言えます。それでは、実際に行った内容を説明します。

- **コンテンツの抽出とフォーマット化：** Dataikuの[技術文書](https://doc.dataiku.com/dss/latest/)、[ナレッジベース](https://knowledge.dataiku.com/latest/)、[開発者ガイド](https://developer.dataiku.com/latest/)、およびDataikuプラグインの[説明](https://www.dataiku.com/product/plugins/)の全ページを自動的にダウンロードし、解析しました。HTMLページの構造（例えば、セクションやサブセクションの見出し、コードサンプルやテーブルに対応する部分）を保持するために、マークダウン形式でコンテンツを抽出しました。
- **チャンキング：** まず、ページ内のセクションとサブセクションを使ってテキストを分割し、各パートを最大約800文字のチャンクに分割しました。マークダウンの形式を崩さないように（特にコードセクションやテーブルについては）、いくつかの前処理と後処理による変換を行いました。各チャンクに現在のセクションまたはサブセクションの見出しを自動的に追加し、より情報量が多く、自己完結できるようにしました。また、完全な重複を削除しました。これは重要です。なぜなら、プロンプトに後から追加する抽出項目の数は、関連する事実を薄めたり除外したりしないように制限する必要があるからです。最終的に、約17,000個のチャンクを作成しました。
- **埋め込み情報の計算：** 事前に学習させた意味類似度 DistilBERTモデルを用いて、チャンクの埋め込み情報を計算しました。ベクトル数は少ないため、FAISSのようなインデックス技術は使用しませんでした。
- **プロンプトの作成：** Dataikuの利用を前提とした質問であるため、以下のようにシンプルな質問と回答のプロンプトを使用しました

`prompt_template = """Use the following extracts of the Dataiku DSS documentation to answer the question at the end. If you don't know the answer, just say that you don't know.`
`- - - - -`
`Dataiku DSS documentation:`
`{context}`
`- - - - -`
`Question: I am a Dataiku DSS user. {question}`
`Answer: """`

- **GPT-3への問合せ：** [text-davinci-003](https://platform.openai.com/docs/models/gpt-3)を活用しました。OpenAIによると、このモデルは「最も能力の高いGPT-3モデル」であり、「特定の対象者向けの要約やクリエイティブなコンテンツ生成など、コンテンツの理解を多く必要とするアプリケーション」に最適なオプションです。
- **答えの表示：** 答えは、対応する「ソース」（出典）と共にユーザーに提示されます。これらのソースはGPT-3が提供するものではありません。これは、検索された文章（retrieve-then-readパイプラインのステップ2参照）のうち、答えと意味的に最も類似している段落に過ぎません。さらに、ユーザーが有用な回答や無駄な回答にフラグを立てることができるようにしたので、このフィードバックが将来の設計選択指針となり、潜在的な機能低下を防ぐのに役立つと考えています。

非常にシンプルな方法でありながら、この方法はすでに満足のいく結果をもたらしています。多くの質問に対して、回答は正確で、よく練られ、簡潔です。下の表はその例です。また、提供されたソースも、ほとんどが適切なものです。

*正しい回答の例*
![Screen Shot 2023-02-10 at 11.16.33 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196881/e180b72c-cd70-ddd7-6951-2cb002d2905d.png)


**間違った回答**もあります。以下はその例です。正しい回答を補足・追記しています。

*間違った回答の例*
![Screen Shot 2023-02-10 at 11.16.41 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1196881/a970aba3-e971-9a1a-5f1e-956e02519548.png)

## 改善の可能性
より多くの実運用とフィードバックを重ねることで、不正確な回答の理由をより深く理解でき、最初のプロトタイプに対する改良を検討することが可能と考えられます。例えば、以下のような内容です。

- 本当の答えが現在の文書のどこにもないことが頻繁にある場合、**新しい文書を追加**することが明確な選択肢となります。しかし、実際には新しい文書が十分に正確で、簡潔で、最新であることを確認する必要があります。プロンプトの長さが限られている（text-davinci-003の場合、4,097トークン）ため、新しいチャンクを追加する際には、重複や重複に近いものが多くなることは避けなければいけません。
- 適切な答えを導く情報が現在の文書に存在するがプロンプトには含まれていない場合、**関連する文章をより適切に抽出**することに焦点を当てる必要があります。その場合、セマンティック類似度モデルを文書コーパスに合わせて微調整したり、BM25のようなスパースモデリングを組み合わせたり、より正確だが計算量の多い[クロス・エンコーダー](https://www.sbert.net/examples/applications/cross-encoder/README.html)を代替手段として使用するなどの手段で実現できます。
- 正解につながる情報がすべてプロンプトに含まれているにもかかわらず、GPT-3がそれを解釈できない場合、「***プロンプト・エンジニアリング***」が有効です。そのための方法としては、満足のいく答えの例をいくつか示す([少数ショット学習](https://arxiv.org/abs/2005.14165))、[chain-of-thought](https://arxiv.org/abs/2201.11903), [self-ask](https://arxiv.org/abs/2210.03350), [demonstrate-search-predict](https://arxiv.org/abs/2212.14024)などの手法を利用して、推論モデルをより明確化する、複数の答えを生成して最も一貫性のあるものを選ぶ（[自己一貫性](https://arxiv.org/abs/2203.11171)）などが考えられます。


## おわりに
GPT-3のような最新の言語モデルにより、**特定の文書コレクションに基づく簡易的な質問応答システムを構築し、適切な結果を得ることは容易になりました**。質問と答えのペアのデータセットを作成する必要はありません。必要なのは文書そのものだけです。

しかし、さまざまな手法で精度を高めることができても、**誤解を招いたり、不適切な回答をしたりするリスク**は常に存在します。利用者はこのようなリスクについて知らされるべきであり、このようなリスクを許容できる状況に限定してシステムを利用する必要があります。

このブログ記事で紹介したプロトタイプを含むDataikuプロジェクトは、[Dataikuのプロジェクトギャラリー](https://gallery.dataiku.com/projects/EX_QUESTION_ANSWERING/)で公開されており、自由に[ダウンロード](https://downloads.dataiku.com/public/dss-samples/EX_QUESTION_ANSWERING/)できます。前処理のDataiku技術文書に特化したWebスクレイピング部分を除けば、ご自身の用途に合わせて、ほとんど**再利用可能**です。主な提供機能を以下に示します。

- チャンキング処理
- 各チャンクの埋め込み情報計算
- 利用者が質問し、回答を受け取るためのWebアプリケーション
- 利用者が有用・無効の評価を与えた回答を可視化するWebアプリケーション

また、[Natural Language Generationプラグイン](https://www.dataiku.com/product/plugins/nlp-nlg-tasks/)を活用することで、DataikuプロジェクトのフローでGPT-3を活用することができます。



## Data From the Trenchesのテクニカルコンテンツをさらに読む
[こちら](https://medium.com/data-from-the-trenches)から、Dataikuの社内エキスパートによる高度なデータサイエンスに関するさまざまな情報を得ることができます。

<br>
<br>
<br>


*原文： [Digging Through the Minutiae: Query Your Documents With GPT-3](https://blog.dataiku.com/query-your-documents-with-gpt-3)*