このビデオでは、LangChainとFAISSベクターストアを使用して、PDFファイルのチャットとクエリを行う方法について説明します。
公開日:2023年4月26日
※動画を再生してから、インタビューを読むのがオススメです。
はい。
このビデオでは、LangChainを使って、PDFファイルとチャットしたり、クエリーを行うことについて見ていきます。
そして、それ以上に重要なのは、これからビデオで紹介する多くのことに使用する、さまざまな要素を紹介することです。
これがゲームプランであり、ここで理解すべき重要なことです。
単純な質問Aを行い、それをプロンプトの文脈に反映させることはできますが、プロンプトが4,000トークン、あるいはGPT-4では8,000トークンに制限されているとしたら、それはまだ非常に有限なものです。
そして、それを本として成立させようとすると、そううまくはいきません。
そこで今回は、ベクトルストア、エンベッディング、クエリや検索を使った情報取得など、PDFファイルを使ったチャットに関連する新しい事柄を紹介します。
この仕組みは、ドキュメントを用意し、私が選んだドキュメントはこれです。
これはリード・ホフマンがGPT-4とAIについてまとめた本を出したもので、彼は実際にGPT-4を使ってこの本を書いているのですが、彼がお金を稼ぐためにこの本を出したとは思えません。
彼は基本的に、アマゾンで注文するか、無料のPDFをダウンロードできるようにしています。
私たちがここでやったこともまさにそうです。
無料のPDFをダウンロードしたところ、かなりのページ数があることがお分かりいただけると思います。
これから、このPDFをクエリや会話に使えるように変換していきます。
まず最初に、PDFファイルを読み込み、ドキュメントを塊に分割します。
そして、ベクターストアを構築し、そのベクターストアにクエリを発行するというものです。
つまり、検索エンジンと同じように、ベクターストアにあるものを探すのです。
しかし、キーワードで検索するのではなく、意味的な意味を通して検索します。
埋め込みの概念については、ビデオで紹介したいと思いますが、これから行うのは、この中の各チャンクに対して埋め込みを作り、その埋め込みをベクトルにすることです。
この埋め込みはベクトルになるのですが、このベクトルは非常に大きなものになります。
そのベクトルは、そのチャンクに含まれるすべての情報を代表するものになります。
ですから、ある情報に関して質問をする場合、質問を埋め込むと、後ほど紹介しますが、独立した質問ができることになります。
それを埋め込むと、ベクトルストアに送られます。ベクトルストアは、私たちが欲しい情報に最も関連性のある情報の塊を返します。
そして、質問と一緒に言語モデルに渡されます。
そして、言語モデルは基本的に、これらを読んで、答えは何だろうかと判断します。
このようなセマンティック検索という考え方は、新しいものではありません。
ずっと以前からあるものです。
また、大規模な言語モデルを使ってテキストの一部を照会するというアイデアも、ずっと前からあるものです。
そのため、Squadのような有名なデータセットがあり、BERTのようなモデルをトレーニングしてこのようなことをやっていました。
そして、これはモデルがかなりうまくできることがわかりました。
コンテキストにテキストを与えると、後でプロンプトを見て、これがどのように行われるかを確認することができます。
そして、そのテキストに目を通し、何が質問と関連しているのかを調べ、それに対する答えを返すことができます。
ここでやるべきことは、いくつかあります。
基本的には、文書を読み込み、文書を分割します。
埋め込みを作成する。
それをベクターストアに格納します。
ベクターストアとは、データベースのようなものです。
そして、基本的にはLangChainを使ってチェーンを作ります。チェーンは、クエリを受け取り、ベクターストアを調べ、情報を取り戻し、それをチェーンに取り込み、最後にそれを組み合わせて答えを出すことができます。
さて、ここにダウンロード用のデータがあり、最初に取り込むものがあります。
まず最初に、PDFリーダーを用意しました。
このPDFリーダーがベストだとは言いません。他のビデオでは、他のPDFリーダーの使い方なども紹介しますが、このビデオはすべてがシンプルであることが特徴です。
私が使っているエンベッディングは、OpenAIのエンベッディングです。
今後のビデオでは、これらの埋め込みにお金を払う必要がなく、OpenAIを使う無料の方法を紹介する予定です。
テキストスプリッターと、ベクターストアが必要です。
そしてこのベクターストアでは、FICEやface hereというライブラリを使って、メモリに保存しておくだけです。
なるほど。
まず最初に、PDFを読み込む。
そこで、PDFリーダーを用意しました。
PDFを読み込むと、基本的にテキストが表示され、テキストは1つの長い文字列としてここに表示されていることがわかります。
このテキストが何文字あるのか見てみると、ほぼ36万文字あることがわかります。
最初の100文字だけを見てみると、このように表示されることがわかります。
さて、書式が良くないことがお分かりでしょうか?
変なところに空白があったり、そんな感じです。
このように、時間をかけてデータを取り込む方法をいろいろと試していくことになります。
そして、それはプロジェクトごとに異なるでしょう。
あるプロジェクトでは、本当に基本的な方法でうまくいくでしょう。
また、Instructureというライブラリを使いたいプロジェクトもあります。
AWSやGoogleクラウドのAPIを使いたいプロジェクトもあるでしょう。
そうですね。
でも、そのテキストは今持ってきました。
次は、それを基本的に分割します。
ここではテキストスプリッターを用意しましたが、これは最も基本的なスプリッターです。
文字通り、文字数で分割しています。
つまり、チャンクサイズを1000文字とし、その上をまたぐということです。
では、どういうことかというと
つまり、オーバーラップが発生するということです。
もし、私がいくつかの文章を書いたとしたら、最初の2つの文章に私が話していることの半分が書かれているとします。
そして、分割して、その半分が2つ目の文章にあったとします。
つまり、50個の文章があったとして、最後の2つの文章に重要な情報があり、それが次の塊の最初の2つの文章に続いている。
このような場合、それを防ぐために、このムービングウィンドウがあります。
つまり、各チャンクサイズで200文字のオーバーラップが発生することになります。
つまり、テキストの多くは、あるいはテキストの一部は、複数のチャンクに表示されることになります。
しかし、その意味全体を汲み取って埋め込みを行うわけですから、チャンクごとに異なることになります。
だから、それぞれのチャンクにはそれぞれの意味合いがあるのですが、万が一、何かが重なるようなことがあっても、それをキャッチできるようにしたいのです。
そのため、データの内容に応じて、さまざまな戦略があります。
ここではごくわずかな重なりを使っていますが、重なりはあったほうがいいでしょう。
オーバーラップを使わない人もいますが、オーバーラップはあったほうがいいでしょう。
また、ある種のものについては、意味の変化が非常に速い場合、500のオーバーラップが必要かもしれません。つまり、最初の1000を取り、500から500に移動し、1000から100から1500に移動するのです。
そうですね。
そうなると当然、チャンクの数が多くなります。
そのため、得られるチャンクの数と、自分にとってよい重なり具合とのバランスをとる必要があるのです。
なるほど。
では、これで完成です。
この後、448種類のテキストやミニドキュメントができあがりました。
20番目の文章を見ると、明らかに前の文章の半分から始まっているのがわかります。
このように、たくさんの情報が入っていることがわかります。
別のものを見てみると、そこには別の情報が含まれていることがわかります。
つまり、これは塊に分割されているのです。
次に、これらの情報を埋め込むための埋め込みを行います。
ここでは、基本的にOpenAIの埋め込みを使用します。
つまり、ここに来てこれを見ると、これがエンベッディングになるという設定になっているわけです。
そして、基本的にはこのFICEライブラリを使い、テキストから指示することになります。
テキストを渡して、エンベッディングメーカーを渡すと、これがエンベッディングメーカーです。
そして、これを見ると、これを作成した後、実際に埋め込み関数を見ることができることがわかります。
すると、なるほど、確かにOpenAIを使っていることがわかります。
使っているモデルは、テキスト埋め込み、Ada 002であることがわかります。
その他、いくつかの重要な情報を得ることができます。
さて、もしこれをテストしたいのであれば、私が「GPT-4はソーシャルメディアをどう変えるか?
これはクエリで、このクエリをdoc searchに渡すと、ここでは類似性マッチング検索を使っています。
つまり、これに最も近いものを探しているのです。
このように、さまざまな類似検索を利用することができます。
おそらく、これが最も一般的な使用方法でしょう。
なるほど。
今後、ベクトルストアに焦点を当てながら、このようなものをいくつか見ていくことにしましょう。
しかし、ここではクエリを渡しています。
デフォルトでは、これに最も近い4つのドキュメントを返します。
そして、最初に返ってきた結果を見ると、確かにソーシャルメディアが言及されていることがわかります。
ここで、最初に返ってきた結果を見ると、ソーシャルメディアが言及されていることがわかります。
つまり、意味的に良い情報が返ってきていることがわかります。
そして、この情報は言語モデルチェーンに渡され、今後の活動に活用される予定です。
なるほど。
では次に、実際にチェーンを構築してみましょう。
ここでは基本的に1つの文書を読み込んだだけですが、複数の文書を読み込んで、同じように送り込むこともできます。
そして、それらをまとめてチャンクするのですが、これは結構なことです。
そのようなことも可能です。
また、ドキュメントを読み込んで、ベクターストアの一部で異なるメタデータを保存することも可能です。
なるほど。
基本に戻りましょう。
平易な質問応答チェーンを用意しました。
これは基本的にロードQAチェーンだけです。
OpenAIを使用しているだけです。
ここでは様々なモデルを試すことができますが、ここで使用しているチェーンのタイプはstuffです。
stuffとは、文字通り、すべてを1つの呼び出しに詰め込むということです。
理想的には、この中に詰め込むのは、4,000トークン未満にすることです。
次に、プロンプトを作成します。
これをコピーして、ここに貼り付けると表示されるようになります。
これがプロンプトです。「次の文脈の一部を使って、質問に答えてください。
最後に、答えがわからなければ、わからないと言えばいいのですが、わからないと言うだけで、答えを作ろうとしないでください。
これがデータベースやベクターストアからのすべてのものの行き先となります。
クエリもここに入れることになります。
そして、これに答えようとします。
このように、下に降りてきてクエリを出すと、このように表示されます。
では、このように少しずつやってみましょう。
この本の著者は誰ですか?
このクエリをベクトルストアに渡すと、類似性検索が行われます。
そうすると、文書が返ってきます。
そして、その文書を言語モデルチェーンに渡します。
そして、クエリも同じように渡します。
すると、答えが返ってきます。
この答えが完璧に正しいわけではありません。
著者はReid Hoffmanで、これは正解でした。
これはなかなかいい。
そして、2番目の著者は、本を見るとGPT-4でした。
GPT-4とリード・ホフマンの本です。
ということは、その一部は理解できたということですね。
でも、明らかに著者という言葉から、「ああ、2人じゃなきゃダメなんだ」と感じたんです。
だから、GPT-4をそこに入れなかったのでしょう。
一番近い人物を探したのです。
ただ、これが実際にやっていることは、ベクトルストアの入力を使っているということを示すためです。
同じクエリでも、ベクターには別のクエリを渡すとします。
今週は雨が降りましたか?
というクエリに、「今週は雨が降りましたか」というクエリに答える4つのドキュメントを入力します。
そして、その書類を渡して、「この本の著者は誰ですか」という問い合わせをします。
すると、本の著者は指定された文脈では特定されないという答えが返ってきます。
つまり、ベクトルストアは有用な情報を返すようにしたい、ということです。
ドキュメントの量を少なくしすぎないようにすることです。
なぜなら、答えは3番目や4番目、時には5番目のドキュメントにあることもあるからです。
そのため、このような場合にも対応できるようにしたいものです。
このように、実際にこの数字を設定することができます。
これまで4個だったものを全部入れてみましたが、これはデフォルトだからです。
実際に設定したい場合は、ここで設定することができます。
6とかに変更することも可能です。
stuffメソッドでは、これから説明するように、非常に限られた量のものしか入れることができません。
ですから、いきなり「Kは20に等しい」といって、検索上位20件を返すと、トークンの数が多すぎることになります。
そして、このようなエラーが発生するのです。
このモデルの最大文脈長は4,097ですが、あなたは5,300を要求しました。
このようなエラーが発生することがおわかりいただけると思います。
そこで、これを回避する方法のひとつが、チェーンの種類を変更することです。
このようなチェーンの種類については、以前にもビデオで紹介しました。
いろいろなものがありますね。
Stuffは、すべてを入れるところです。
MapReduceは、基本的に1つ1つを並列で行うことができます。
そして、基本的にそれぞれでこれを実行します。
しかし、その分APIを大量に呼び出すことになりかねません。
だから、使えるものはいつでも使った方がいいんです。その方がコストがかからないから。
MapRerankの方ですが、こちらを見てみましょう。
ここでは基本的に、OpenAIとは何者か?
と質問し、10クエリを返してもらいました。
返ってくるのは単純な答えだけではないことがお分かりいただけると思います。
このように、それぞれの質問に対して、言語モデルを呼び出しています。
そして、それぞれの答えが返され、あるいは得られた答えが返されているのがわかると思います。
そして、それを採点しています。
最終的な出力テキストを見ると、OpenAIは人類の利益のために人工知能ツールを開発し、共有する研究組織であることがわかります。
そして、中間ステップを見ると、返ってきたそれぞれの事柄と、それに付けられたスコアが表示されています。
つまり、返ってきたもの一つひとつをもとに、答えを作り出しているのです。
この本ではOpenAIのことがたくさん出てきますが、80点、90点、100点のものもあります。
このように、OpenAIはテクノロジーに特化した企業であることがわかります。
そのため、おそらく2つ、1つ、または3つの100を選び、それらを統合して出力しているのでしょう。
この方法でプロンプトを見ると、実はプロンプトが異なっていることがわかります。
プロンプトは基本的に、これが質問、これが答えのヘルプ、これがスコア、そしてこれがすべてをマージするためのものであることを示すものであることがわかります。
また、「より高いスコアを獲得した場合は、そのスコアに注意する必要がある」という例も示されています。
このように、OpenAIにはいくつかの基本的な変化が見られます。
OpenAIの基本的な操作方法には、いくつかの変更があります。
ベクトルストアへの問い合わせとLLMへの問い合わせを別々に行うのではなく、すべてを1つのチェーンにまとめることができます。
つまり、ここでは基本的に検索QAチェーンを使い始めているのです。
これは、リトリーバー(retriever)を使用するものです。
すでに持っているリトリーバー、すでに設定したドキュメント検索を、リトリーバーとして、類似性でパス、4でパスして、戻ってきたいドキュメントの数でパスします。
そして、これをチェーンタイプからレトリーバーQAに渡すことができます。
ここで使う型はstuffです。
retrieverに渡すと、ソース・ドキュメントがここに戻ってきます。
ここで、「OpenAIとは何ですか」と聞いてみるとわかります。
と尋ねると、結果が返ってきます。
これが、先ほどと同じような答えです。
そして、その答えがどこから来たのか、ソース・ドキュメントを返します。
このように、他の質問をすると、このような答えが返ってくることがわかります。
もし、そのすべてを必要としないのであれば、問題はありません。
クエリーを入れて、その結果を返すだけです。
ここで、「GPT-4はクリエイティビティにとってどんな意味があるのだろう」と考えてみました。
そして、「GPT-4は文脈に沿った検索を提供することで、人間の創造性を増幅させることができる」という結果が、これに対する素晴らしい答えを与えてくれていることがわかります。
この本を見ると、目次にあったものをもとに質問を選んでいるのですが、それで、これらの質問のいくつかに答えられるのでしょうか?
ですから、ぜひこれで遊んでみて、何ができて、何ができないかを感じ取ってください。
このトリックの1つは、本当に明白なことでも、実はこの本にはあまり出てこないということです。
この本は誰によって書かれたのだろうかと考えると、この本の中に飛び込んでくるのはわかるのですが、誰によって書かれたのかについてはあまり言及されていません。
リード・ホフマンがGPT-4についてほんの少し書いているだけなんです。
つまり、リード・ホフマンの部分があるのは確かなんです。
しかし、私の推測では、GPT-4が本を書くような人、あるいは自分自身の著者であるとは考えていなかったようです。
もう1つ、お見せしましょう。
アメリカのジャーナリズムにとって、この20年間はどのようなものでしたか?
という質問です。
アメリカのジャーナリズム業界にとって、この20年間は困難なものでしたね。
そして、それに対する完全な答えを教えてくれるのです。
ここでジャーナリズムをクリックすると、確かにアメリカのジャーナリズム業界にとって、この20年間はほとんど悪いニュースばかりであったことがわかります。
つまり、これはその章の一部を要約したもので、クエリを使ってベクトルストアに情報を取りに行き、それを引き戻してまとめています。
そして、戻ってきた上位4つの結果に基づいて、答えを導き出したのです。
おそらくこれらの結果はすべてその章から得られたものでしょうが、そうではないかもしれません。
ですから、生産用に何かを作る場合、ベクターストアが何を返しているのかを確認することが大きなポイントになります。
そうすれば、LLMの問題がエラーの原因なのか、それともベクターストアが正しい情報を返してくれないことが原因なのか、すぐに突き止めることができるのです。
ジャーナリストはGPTをどのように使えばいいのでしょうか。
そして最後に、ちょっとくだらない質問をしてみました。
BeagleBardとは何ですか?
これはこの本のどこにも書いてありません。
つまり、モデルがうまくいっていれば、文脈にそぐわない質問をされたときに、「これにはいい答えがありません」「これは私の答えではありません」と答えるはずだということです。
これについては良い答えがありません、あるいはこれは文脈や文書のどれにも記載されていません。
このように、基本的なQ&Aを、さまざまなチェーンを使って行うことができます。
ここでも重要なのは、文書の分割、チャンク化、埋め込み、ベクターストアへの埋め込みです。
そして、クエリの部分では、LangChainを使って、基本的にベクトルストアを検索し、関連するドキュメントを取得し、それをLLMルックアップに提供するのです。
次のビデオでは、この基本的なセットアップでできる、よりファンシーなことを見ていきます。
これらはすべて、何らかのベクトルストアやツール、何かを照会する方法、そしてその文脈を大規模な言語モデルに戻す方法を使うことになります。
いずれにせよ、質問がある場合は、以下のコメント欄に記入してください。
もしこの記事が役に立ったら、クリックして購読してください。
次のビデオでお話します。
それでは、また。