WEBVTT 00:00.620 --> 00:07.640 さて、 JupyterLabのこのセッションは、 ついにベクトルを直接見ることができるということで、 期待に胸を膨らませていることだろう。 00:07.670 --> 00:15.710 だから、 あなたが5週目のフォルダに入っていて、 3日目に入っていて、 これまで以上に私についてきてくれることを願っている。 00:15.710 --> 00:20.960 今回はビジュアルが重要で、 何が起こっているのかを実感できるだろうからね。 00:20.960 --> 00:25.940 だから、 これは前日の重複にさらに追加しただけだ。 00:25.940 --> 00:33.380 まずはインポートをいくつか用意し、 そのインポートにこれから取り組む特別なものを追加した。 00:33.380 --> 00:33.920 今日は 00:33.920 --> 00:41.960 OpenAIのエンベッディングをインポートします。 これはLang Lang chain OpenAIパッケージの一部です。 00:42.230 --> 00:45.860 ラングチェーンchromaからクロマをインポートする。 00:46.130 --> 00:50.690 t-SNEと呼ばれるものについてはこれから説明します。 00:50.690 --> 00:59.720 それからPlotlyのもので、 素敵な図を作成することができます。 00:59.720 --> 01:01.750 インポートを全部やろう。 01:02.380 --> 01:07.120 よし、 定数を調べてみよう。 01:07.120 --> 01:09.040 環境変数を持ってくる。 01:09.040 --> 01:11.440 もちろん、 これはもうお馴染みだろう。 01:11.470 --> 01:14.440 ナレッジベースを読み込むためにローダーを使っている。 01:14.440 --> 01:20.920 テキスト分割ツールを使ってチャンク(123個)を作っている。 01:20.920 --> 01:27.730 そして、 契約、 製品、 従業員、 会社の4つのフォルダごとにチャンクがある。 01:28.300 --> 01:35.110 そこで、 エンベッディングと自動エンコーディングLMSについて、 もう1度思い出していただきたいのですが、 01:35.110 --> 01:40.030 これまでのコースのほとんどで、 自動回帰LMSについてお話ししてきました。 01:40.060 --> 01:49.660 今回は、 入力全体を受け取り、 それを使って1つの出力(この場合はベクトル)を作成するオートエンコーディングLMSについて初めて見ていく。 01:50.140 --> 01:53.890 そして、 自動エンコーディングのアラームの例がバートだ。 01:53.920 --> 01:56.380 これからこれを使う。 01:56.410 --> 01:58.000 OpenAIのエンベッディング。 01:58.210 --> 01:59.280 それを実行しよう。 01:59.520 --> 02:00.420 オーケー。 02:00.420 --> 02:05.010 クロマはこれからクロマ・データ・ストアを作るところだ。 02:05.310 --> 02:10.770 そして、 もしすでにデータベースがある場合は、 削除するか空にするために、 この小さなセクションをここに入れました。 02:10.800 --> 02:15.480 そうしないと、 このコードを実行するたびに、 また別のベクトルが追加され、 ある種の重複したベクトル・セットとなり、 02:15.480 --> 02:17.520 混乱することになる。 02:17.520 --> 02:20.760 これはデータベースをリフレッシュするのに役立つ。 02:20.760 --> 02:27.090 すでに1度実行したことがある人なら想像がつくと思うが、 私はすでに1度か2度実行しているので、 これは私にとって便利なものだ。 02:27.360 --> 02:28.890 削除します。 02:29.400 --> 02:41.340 このフォルダーの中にあるvector db umは、 DB名で、 DB名がvector DBであることを示すために一番上に設定した定数だ。 02:41.370 --> 02:45.480 SQLiteをベースにしている。 02:45.510 --> 02:49.440 この中に入ってみると、 SQLiteが使われているのがわかるだろう。 02:49.440 --> 02:56.730 つまり、 あなたが選んだデータベース名の中に、 さまざまなファイルが並んでいるだけなのだ。 02:56.730 --> 02:58.730 この場合はベクトルdb。 02:59.660 --> 03:06.170 それでは、 ベクターデータベースを作成し、 ベクターを入れてみましょう。 03:06.170 --> 03:08.930 そして、 私はここでまたグラディオの瞬間を迎えることになる。 03:08.930 --> 03:14.870 ドキュメントの束をベクトル化し、 それをベクトル化してベクトル・データベースに保存するプロセスは、 03:14.870 --> 03:21.740 それなりに高度なもので、 少なくとも数セルは必要だと思うかもしれない。 03:21.980 --> 03:27.200 しかし、 もちろん、 1つのセルで、 1行のコードでできることがわかるだろう。 03:27.200 --> 03:34.010 そしてそれはもちろん、 ラング・チェインが素晴らしいグルーコードをたくさん用意してくれたおかげだ。 03:34.040 --> 03:39.560 手作業でそれを繰り返し、 それぞれの埋め込みを、 それぞれのチャンクをベクトルに変換し、 03:39.560 --> 03:46.970 それをクロマに保存するのは、 実際にはそれほど難しいことではない。 03:47.060 --> 03:50.870 うーん、 でも、 こうやってひとつにまとめられたら、 もっとシンプルになるよね。 03:50.870 --> 03:55.490 そして、 これのもうひとつの素晴らしいところは、 別のベクター・データ・ストアを試してみても、 03:55.490 --> 04:01.630 ラング・チェーンからインポートされた別のベクター・ストアを使うだけで同じことができるということです。 04:01.630 --> 04:06.700 でも、 この1行を走らせてみたら走った。 04:06.700 --> 04:11.200 そして、 ベクターストアは123のドキュメントで作られている。 04:11.200 --> 04:14.800 123個のチャンクがあったのだから。 04:14.800 --> 04:21.040 だから、 ベクター・データ・ストアに同じ数のドキュメントがあるのはいいことだ。 04:21.520 --> 04:26.950 Chromeを作成して戻ってきたベクターストアオブジェクトに、 04:26.950 --> 04:35.860 チャンク、 埋め込み(OpenAIの埋め込み)、 そしてデータベース名を渡しました。 04:35.860 --> 04:40.060 この3つは私たちが提供したもので、 まったく理にかなっている。 04:40.090 --> 04:42.820 ベクターストアを作るために必要なことはこれだけだ。 04:42.820 --> 04:51.220 そして、 このベクターストアは、 underscore collection dot countを呼び出して、 ベクターストア内のドキュメント数を取得することができる。 04:51.850 --> 05:04.380 そこで、 これらのベクトルが何次元かを調べ、 これでコレクションからベクトルを取得できるようにしよう。 05:04.410 --> 05:11.640 つまり、 このアンダースコア・コレクションをベクター・ストアから呼び出すと、 コレクションが生成されます。 05:11.640 --> 05:14.040 そこでドットゲットを呼び出せばいい。 05:14.070 --> 05:15.300 制限内でパスできる。 05:15.300 --> 05:16.380 欲しいのは1つだけだ。 05:16.380 --> 05:20.550 ベクトルそのものであるエンベッディングを持ち帰らせたいのだ。 05:20.760 --> 05:26.490 その大きさを見てみよう。 05:26.490 --> 05:30.180 寸法は1536。 05:30.180 --> 05:34.920 つまり、 1536の数字がこの塊を構成している。 05:34.920 --> 05:38.850 では、 これを印刷できるように自分で見てみよう。 05:38.850 --> 05:43.260 埋め込みのサンプルを印刷してみましょう。 05:43.890 --> 05:44.430 すごい。 05:44.430 --> 05:45.810 たくさんの数字だ。 05:46.080 --> 05:48.000 つまり、 数字の羅列だ。 05:48.030 --> 05:51.360 あなたや私にとっては無意味なことだ。 05:51.540 --> 05:54.770 ええと、 でもこの数字は何らかの形で 05:55.460 --> 06:02.450 私たちは、 これらの数字が何らかの形で、 その数字に関連するチャンクの意味を反映していると見ている。 06:02.450 --> 06:03.230 いずれ分かることだ。 06:03.650 --> 06:06.560 すぐにチャンクと関連付ける。 06:07.370 --> 06:09.140 だから、 トンデモナイ数字なんだ。 06:09.140 --> 06:17.480 これは1536個の数字で、 1536次元空間の座標を表していると解釈できる。 06:17.720 --> 06:28.790 そして、 その座標は、 ベクトル空間において近い位置にある、 似たような座標を持つ他のベクトルが同じような意味を持つように選ばれている。 06:28.790 --> 06:30.740 それがこの構想のすべてだ。 06:30.980 --> 06:34.940 では、 ちょっとイメージしてみよう。 06:34.940 --> 06:37.640 そうすれば、 このようなコメントもなくなるだろう。 06:37.640 --> 06:46.070 これは、 舞台裏で何が起こっているのかを本当に調査することができる、 素晴らしい、 ええと、 ええと、 ええと、 いい方法になるだろう。 06:46.070 --> 06:53.320 だから、 Collectiongettyを呼び出して、 エンベッディング、 ドキュメント、 メタデータを求めることができる。 06:53.320 --> 06:56.320 それができたら、 ベクターを置くことができる。 06:56.320 --> 07:04.720 埋め込みをベクターの配列に入れ、 docタイプをdocタイプというものに入れる。 07:04.720 --> 07:07.960 それから、 見ての通り、 いくつかの色を作るつもりだ。 07:07.990 --> 07:10.300 だから、 これは準備のためのプレワークにすぎない。 07:10.600 --> 07:22.360 今ひとつ問題なのは、 人間には3次元以上のものを視覚化する能力がないということだ。 07:22.360 --> 07:27.610 つまり、 1536次元で何かを視覚化することは、 実に難しいことなのだ。 07:27.670 --> 07:34.360 でも、 幸運なことに、 投影法とか、 次元を2次元に縮小して、 07:34.360 --> 07:41.290 多次元表現に忠実であるように、 可能な限り物事を分離できるようにする方法とか、 07:41.290 --> 07:47.680 いろいろなテクニックがあるんだ。 07:47.680 --> 07:57.780 だから、 これらすべての次元で離れているものを、 2次元に投影してもまだかなり離れているようにしようとする。 07:58.290 --> 07:59.340 そういうことだ。 07:59.370 --> 08:04.710 そのためのテクニックはいろいろあるが、 ここでは割愛する。 08:04.710 --> 08:09.660 これはt-SNEと呼ばれるもので、 T-distributed Stochastic 08:09.660 --> 08:14.670 Neighbor embeddingの略です。 08:15.150 --> 08:19.710 何次元がいい? 08:19.740 --> 08:24.630 千差万別なものを二次元に投影してほしい。 08:24.630 --> 08:29.790 そしてこのランダム・ステートは、 ランダム・シードを設定する方法であり、 これを呼び出すたびに同じものが得られるので、 08:29.790 --> 08:33.210 これを再現できる。 08:33.450 --> 08:41.400 そして、 このt-SNEオブジェクトのfit transformメソッドを呼び出すだけで、 縮小されたベクトルを得ることができます。 08:41.820 --> 08:49.770 それから、 素晴らしいライブラリplotlyを使って散布図を作っています。 08:49.890 --> 08:56.170 そして、 これはすべて、 コピー&ペーストして好きなように再利用できるコードのようなものなんだ。 08:56.170 --> 09:01.720 でも、 ここで設定したドキュメントの種類によってマーカーの色を変えたり、 09:01.720 --> 09:14.560 ポップアップ・テキストでチャンク自体の最初の100文字を表示させたりしています。 09:14.560 --> 09:20.050 つまり、 ここで見たいのは、 ベクター・データベースでドキュメントがどのように見えるか、 ということだ。 09:20.050 --> 09:25.810 そして、 これらの異なるベクトルそれぞれについて、 どのような文書であるかによって色分けする。 09:25.810 --> 09:27.850 そして、 テキストにカーソルを合わせる。 09:27.850 --> 09:33.100 だから、 このチャンクが表すテキストの断片を少し読むことができる。 09:33.100 --> 09:34.600 だから、 これがうまくいくかどうか見てみよう。 09:34.600 --> 09:35.800 それはとてもクールだ。 09:36.370 --> 09:37.420 もちろん、 効果があることは知っている。 09:37.420 --> 09:38.470 もう試したよ。 09:38.530 --> 09:39.580 これだ。 09:39.610 --> 09:40.420 オーケー。 09:40.420 --> 09:42.040 では、 私たちは何を見ているのか。 09:42.670 --> 09:53.370 つまり、 私たちは多次元ベクトルを2次元に投影して可視化したものを見ているのであって、 X軸とY軸に特別な意味はない。 09:53.370 --> 09:59.100 いろいろなポイントを分散させる最善の方法なんだ。 09:59.190 --> 10:01.560 さて、 いくつか気になることがある。 10:01.560 --> 10:07.500 ここに見える緑の点は従業員を表している。 10:07.530 --> 10:10.350 赤い点がそれを表している。 10:10.530 --> 10:17.730 従業員というのは、 従業員の文書から抜き出したテキストのかたまりという意味だ。 10:17.760 --> 10:22.020 赤いのは契約書から出てくるテキストの塊。 10:22.050 --> 10:28.830 青は製品ドキュメントから、 黄色はアバウトなドキュメントから。 10:29.760 --> 10:36.900 さて、 OpenAIのエンベッディングは、 テキストの塊をベクトル化するときに、 10:36.930 --> 10:44.850 ドキュメントタイプを知らなかった。 10:44.850 --> 10:46.830 メタデータは伝えていない。 10:46.830 --> 10:52.190 夏の従業員、 夏の製品、 夏の契約ということは伝えていない。 10:52.190 --> 10:55.580 テキストの塊を渡して、 これをベクターに変換してくれ、 と言っただけだ。 10:55.580 --> 10:57.500 それしかなかった。 10:57.770 --> 11:04.880 だから、 そのチャンクに基づいて、 これらのチャンクがベクトル空間で分離され、 空間内の異なる領域を占めるというのは、 11:04.880 --> 11:10.730 ある意味不思議なことなんだ。 11:10.910 --> 11:16.070 内容や象徴する意味という点では、 11:16.070 --> 11:20.630 ある程度似ているからね。 11:20.630 --> 11:26.570 契約はこっちで、 製品はこっちだ。 11:26.690 --> 11:37.100 契約情報の一部が、 商品と同じ近辺にあるように見えるかもしれない。 11:37.100 --> 11:39.290 そして、 それは一瞬驚くかもしれない。 11:39.290 --> 11:41.210 何かが間違っているように見えるかもしれない。 11:41.210 --> 11:48.010 しかし、 そうではなく、 これらの塊にカーソルを合わせると、 これが契約書の特定のテキストの塊であり、 11:48.010 --> 11:53.170 そのクライアントが契約した主な機能が記述されていることがわかる。 11:53.380 --> 11:56.260 そこにテキストを入力してください。 11:56.290 --> 12:02.920 2行目のテキストと書いてあるところにカーソルを合わせると、 それがベクター空間のその場所に置かれたチャンクから抽出されたもので、 12:02.920 --> 12:10.420 1つのAIパワーのマッチングから始まっているのがわかると思います。 12:10.660 --> 12:12.250 そして、 ここでもう一つ探してみよう。 12:12.610 --> 12:17.620 ええと、 AIを使ったリスク評価機能です。 12:17.800 --> 12:19.420 同じことだよ。 12:19.870 --> 12:28.420 つまり、 契約には機能的な情報も含まれているということだ。 12:28.420 --> 12:35.980 そしてその機能は、 他の製品情報と同じようなベクトル空間に存在する。 12:35.980 --> 12:38.800 だから、 あー、 理解してもらえるといいんだけど。 12:38.830 --> 12:49.290 空間上の適切な位置と文書の背後にある意味を結びつけるのが、 これまた不気味なくらいうまいんだ。 12:49.590 --> 12:59.520 そして最後のポイントは、 これは言い過ぎかもしれないが、 本当にこういうことだと思う。 12:59.550 --> 13:04.260 会社に関する3つの文書があることにお気づきだろう。 13:04.440 --> 13:07.380 この3人が真ん中だね。 13:07.410 --> 13:10.290 彼らはこれらの異なる文書のちょうど真ん中にいる。 13:10.290 --> 13:23.370 それは、 従業員や契約、 製品に関連する情報も含まれているからだと思う。 13:23.580 --> 13:28.080 ええと、 それはすべてに関連する中心的な情報なんだ。 13:28.080 --> 13:34.950 だからこそ、 他のすべての情報の真ん中にあるような場所にあるんだ。 13:35.400 --> 13:37.350 それはとても魅力的なことだ。 13:37.350 --> 13:41.280 深読みしすぎかもしれないが、 私にはそう見える。 13:41.400 --> 13:48.770 ベクター・データベースに好きなテキストのかたまりを入れて試してみるのもいい。 13:48.860 --> 13:57.080 ここで読み込んだドキュメントに、 他のドキュメントを追加することができる。 13:57.080 --> 14:02.360 ファイルを直接指定するか、 14:02.360 --> 14:08.690 テキストを追加するか、 14:08.690 --> 14:25.940 既存のドキュメントにテキストを追加するだけです。 14:26.060 --> 14:28.220 それが全体のアイデアなんだ。 14:28.730 --> 14:33.140 この2D表現は本当にクールだった。 14:33.140 --> 14:35.420 ええと、 2Dで表現するよりもいいものがありますか? 14:35.450 --> 14:36.320 もちろんある。 14:36.350 --> 14:40.040 3D表現があり、 それが次にやることだ。 14:40.220 --> 14:51.140 2という数字を3という数字に変えるだけで、 ベクトルを3Dで視覚化することができる。 14:51.170 --> 14:52.280 それほど単純なことではなかった。 14:52.310 --> 14:59.480 ここに3Dも入れなければならなかったし、 他のベクターもいじらなければならなかった。 14:59.480 --> 15:02.510 そして、 タイトルも2Dから3Dに変更しなければならなかった。 15:02.690 --> 15:04.910 とにかく、 これがどう見えるか見てみよう。 15:04.910 --> 15:06.170 これだ。 15:06.440 --> 15:13.010 これが、 2Dではなく3Dに投影されたベクトルです。 15:13.160 --> 15:17.990 ええと、 まずお気づきになるかもしれないのは、 実は、 これは映画のように、 3Dが必ずしも2Dより優れているわけではない、 15:17.990 --> 15:23.090 稀な時代のひとつだということです。 15:23.300 --> 15:27.200 ちょっとごちゃごちゃしているように見えるね。 15:27.200 --> 15:28.790 ちょっと見づらいけど。 15:28.820 --> 15:31.100 黄色が真ん中にあるようにまた見える。 15:31.220 --> 15:34.910 そして、 緑、 赤、 青がはっきりと分かれている。 15:34.910 --> 15:40.610 しかし、 以前見たように、 予想通り、 いくつか組み合わされたものもある。 15:40.640 --> 15:46.360 でも、 これのいいところは、 積極的に、 あー、 インタラクティブにこれで遊ぶことができるんだ。 15:46.390 --> 15:48.310 このように回転させることができる。 15:49.060 --> 15:50.260 そうだろう? 15:50.260 --> 15:55.150 そして、 これを使うことで、 どのようにレイアウトされているかを把握することができる。 15:55.150 --> 15:59.830 そして、 両者の間に区別があることを感じさせてくれる。 16:00.130 --> 16:07.540 うーん、 でも、 2Dの表現ほど明確ではないことは認めざるを得ないね。 16:07.630 --> 16:10.780 あー、 それにしても、 いい感じだね。 16:10.780 --> 16:13.900 カーソルを合わせると、 ポイントの背後にある意味を見ることができる。 16:13.900 --> 16:26.410 もちろん、 前回と同じように、 黄色はすべての真ん中に位置しているように見える。 16:26.800 --> 16:36.970 3Dで表現するのも楽しいけど、 2Dの方がもう少しわかりやすい部分もあるかもしれない。 16:37.360 --> 16:43.310 とにかく、 これでベクトルを使った遊びは終わりですが、 大きな収穫があります。 それは、 これらの図を見て、 16:43.310 --> 16:50.930 さまざまなテキストのかたまりを調べるだけでなく、 あなた自身のテキストのかたまりを追加することです。 16:50.960 --> 16:55.970 簡単な方法は、 ドキュメントをナレッジ・ベース・ディレクトリに置くことだ。 16:55.970 --> 16:58.040 そうするだけで、 すぐにうまくいく。 16:58.130 --> 17:06.260 しかし、 単にドキュメントをそこにドロップするのではなく、 ラング・チェイン・コードを使ってチャンクを追加するために、 テキスト・ローダー・クラスを弄ることもできる。 17:06.260 --> 17:12.800 しかし、 チャンクを入れたら、 ベクタースペースのどこに配置されるかを見て、 それがどのように機能するか感覚をつかんでほしい。 17:12.830 --> 17:17.480 あるいは、 ナレッジ・ベース・ディレクトリを丸ごと置き換えて、 別の名前に変更し、 17:17.480 --> 17:28.430 新しいディレクトリを作成し、 その中に非常に単純なものを入れるだけで、 ドキュメントがベクター・スペース内のさまざまな場所にどのように配置されるかを実験することができます。 17:28.790 --> 17:39.170 これは超重要な宿題で、 次のパート、 つまり本格的にボロを出すときのいい基礎になるからだ。 17:39.200 --> 17:41.000 まず、 スライドに戻ろう。