WEBVTT 00:00.440 --> 00:03.560 JupyterLabの素晴らしい世界へようこそ。 00:03.560 --> 00:06.830 そして2週目に入った。 00:07.490 --> 00:09.110 3日目。 00:09.260 --> 00:11.990 このノートを出して 00:11.990 --> 00:18.080 そこで今回は、 チャットボットとしても知られる会話型AIについて、 さっそくご紹介しよう。 00:18.110 --> 00:24.680 まずはいつものようにインポートし、 環境変数を設定する。 00:24.680 --> 00:27.620 そして OpenAI を初期化する。 00:27.650 --> 00:29.840 今回はOpenAIを使う。 00:30.020 --> 00:34.310 そして、 もしそうしたければ、 他のモデルに乗り換える練習として持っていてもいい。 00:34.670 --> 00:38.510 では、 基本的なシステムメッセージから始めよう。 00:38.510 --> 00:40.340 あなたは役に立つアシスタントだ。 00:40.970 --> 00:41.480 分かった。 00:41.510 --> 00:45.800 さて、 メッセージの構造について少し話をしたい。 00:45.980 --> 00:54.200 まず最初に、 OpenAIへのプロンプトメッセージの構造を思い出してください。 00:54.320 --> 00:58.700 ええと、 これはもう何度も見てきたことだから、 私が説明するのに飽き飽きしただろうね。 00:58.700 --> 00:59.350 あれだ。 00:59.350 --> 01:00.010 もう1度だけ。 01:00.010 --> 01:00.730 よくご存知でしょう。 01:00.760 --> 01:09.220 システムにユーザーを与える辞書のリストで、 アシスタントが応答し、 次にユーザーが応答するといった具合だ。 01:09.220 --> 01:12.910 そして、 他にも何かあると言ったのを覚えているかもしれないが、 今はまだだ。 01:12.910 --> 01:13.990 システム・ユーザー・アシスタント。 01:13.990 --> 01:14.650 ユーザーアシスタント。 01:14.680 --> 01:16.960 ユーザーアシスタントユーザーなど。 01:17.470 --> 01:21.430 さて、 これからchatという関数を書きます。 01:21.430 --> 01:27.400 チャット機能には、 メッセージと履歴の2つの入力がある。 01:27.430 --> 01:34.930 Messageは、 チャットが応答する必要のある、 現在の、 あー、 質問されているメッセージを表す。 01:34.960 --> 01:41.050 そして歴史は、 以前のすべてのメッセージ、 以前のすべてのやりとりの履歴を持っている。 01:41.050 --> 01:45.520 そして歴史の構造はこうなる。 01:45.550 --> 01:50.140 リスト、 リストからなるリストになるだろう。 01:50.140 --> 01:58.920 そして、 このようなサブリストは、 単にユーザーの発言とアシスタントの返答、 ユーザーの発言とアシスタントの返答などである。 01:59.340 --> 02:02.730 では、 なぜそんなことをお願いしているのか? 02:02.760 --> 02:08.340 なぜ、 このような引数で、 このような関数を書こうとするのか? 02:08.340 --> 02:16.710 その答えは、 Gradioがチャット・ユーザー・インターフェースで使うことを期待している特定のタイプの機能だからです。 02:16.710 --> 02:22.260 だからGradioは、 メッセージを受け取るchatという関数を書くことを期待しているのだ。 02:22.260 --> 02:28.590 この構造体で履歴を取り、 次のレスポンス、 つまりこのチャットに対するレスポンスを返す。 02:28.590 --> 02:30.390 だから、 そういう形式を考えているんだ。 02:30.390 --> 02:39.420 この関数の仕事は、 このようなスタイルのメッセージをこのように変換することだ。 02:39.420 --> 02:47.940 そこで、 この構造を1行ずつ繰り返し、 上にあるような構造を構築する必要がある。 02:47.970 --> 02:49.710 それが理解できればいいのだが......。 02:49.710 --> 02:53.400 そうでなくても、 それがどんなものかをお見せすれば納得していただけるだろう。 02:53.400 --> 02:56.730 そこで、 chatという関数を定義している。 02:56.760 --> 03:03.450 入力されたメッセージに応答するために得たメッセージを受け取り、 以前のメッセージの履歴を受け取る。 03:03.480 --> 03:09.090 そこでまず、 メッセージのリストを設定する。 03:09.090 --> 03:12.870 そして、 一番最初にシステム・プロンプトを入力する。 03:12.900 --> 03:17.010 もちろん、 その後は歴史を反復することになる。 03:17.040 --> 03:20.460 ヒストリーの各要素は、 2つの値を持つリストの1つである。 03:20.460 --> 03:24.000 だから、 それをユーザー・メッセージ・アシスタントのメッセージに展開するんだ。 03:24.000 --> 03:28.470 そして、 ユーザーのメッセージとアシスタントのメッセージを追加する。 03:28.530 --> 03:30.390 その都度、 その都度。 03:30.390 --> 03:38.310 つまり、 履歴の各行がこのリストでは2行になる。 03:38.310 --> 03:40.650 1つはユーザー用、 もう1つはアシスタント用だ。 03:40.770 --> 03:42.480 それが完全に意味をなしていることを願うよ。 03:42.480 --> 03:43.050 今すぐだ。 03:43.200 --> 03:44.250 そうでなければ、 いつでもできる。 03:44.280 --> 03:45.240 まあ、 その必要はない。 03:45.270 --> 03:47.370 いつでもprint文を入れられると言おうとしたんだ。 03:47.430 --> 03:50.160 ええと、 私には先見の明があったので、 自分でいくつかのプリント文を入れたんだ。 03:50.160 --> 03:51.180 だから、 これを見ることになる。 03:51.210 --> 03:54.980 履歴を印刷し、 メッセージを印刷します。 03:54.980 --> 03:57.170 だから、 それも見ることができる。 03:57.530 --> 04:05.120 次の行は、 このチャットではお馴染みのメソッドで、 この時点で、 この関数、 すみません、 04:05.150 --> 04:14.300 この時点で、 メッセージのセットを受け取り、 それを使ってOpenAIを呼び出します。 04:14.300 --> 04:17.810 だから、 OpenAIチャットのドットコンプリートやドットクリエイトをやっているんだ。 04:17.810 --> 04:22.970 モデルを渡し、 メッセージを渡し、 結果をストリームしてくださいと言うつもりだ。 04:22.970 --> 04:23.810 そうかもしれない。 04:23.810 --> 04:27.200 そして、 私たちはそれを通過し、 返答を得る。 04:27.440 --> 04:30.170 ええと、 つまり、 これは実際には機能ではないんだ。 04:30.170 --> 04:35.900 私たちは一つひとつ答えを出していくので、 本当にジェネレーターなんだ。 04:36.800 --> 04:37.280 オーケー。 04:37.280 --> 04:49.850 つまり、 先ほどのスライドにあったような、 インスタント・メッセージのようなユーザー・インターフェースを作りたいのです。 04:49.850 --> 04:54.580 だから、 次から次へとやってくるメッセージをどうキャンバスに描くか、 04:54.580 --> 05:01.360 その方法を考えなければならない。 05:01.420 --> 05:06.430 ええと、 このチャットメッセージから返ってくる反応からするとね。 05:06.940 --> 05:10.300 ええと、 お気づきになったかどうかわかりませんが、 私はもちろん嘘をついています。 05:10.300 --> 05:11.770 本当に簡単なことだよ。 05:11.770 --> 05:12.910 本当に簡単なことだよ。 05:12.910 --> 05:14.470 一本の線になる。 05:15.310 --> 05:21.460 Gradioにはチャット・インターフェイスというものが付属していて、 チャット・インターフェイスは、 05:21.460 --> 05:25.540 このような構造を持つ1つの関数を想定しています。 05:25.540 --> 05:34.240 もしあなたが、 メッセージと履歴をこの特殊なフォーマットで受け取る関数を書いたのなら、 Gradioにとってそれはたった1行のコードに過ぎない。 05:34.480 --> 05:36.670 ええと、 本当にそんなに簡単なことなのか見てみよう。 05:36.670 --> 05:42.610 チャット・ジェネレーターを定義するために、 忘れずに実行する必要がある。 05:42.610 --> 05:46.510 そしてインターフェイスを立ち上げる。 05:46.510 --> 05:47.770 そしてここにある。 05:47.770 --> 05:49.890 これが私たちのチャット・インターフェースです。 05:50.190 --> 05:53.730 別ウインドウで表示させよう。 05:53.730 --> 05:55.830 そして、 こう言うんだ。 05:55.830 --> 05:56.970 こんにちは。 05:59.070 --> 06:00.000 こんにちは。 06:00.030 --> 06:01.410 本日はどのようなご用件でしょうか? 06:01.530 --> 06:05.220 ネクタイを買いたい。 06:06.780 --> 06:09.270 どんなネクタイをお探しですか? 06:09.300 --> 06:11.730 色や柄、 素材は決まっていますか? 06:12.210 --> 06:14.160 ええと、 それでお分かりいただけたと思う。 06:14.430 --> 06:22.830 でも、 赤のネクタイはクラシックなチョイスだよ。 06:22.830 --> 06:24.510 ここでは、 いくつかのオプションを紹介しよう。 06:24.510 --> 06:26.340 そこに答えがある。 06:26.820 --> 06:35.940 この会話には文脈があり、 その前に何があったかを知っている。 06:35.970 --> 06:43.800 そしてもうひとつ、 私たちが最初に話しかけたときからの記憶があるかのように感じるのは、 ちょっとした錯覚だ。 06:43.800 --> 06:45.180 そして私はネクタイを買いたいと言った。 06:45.210 --> 06:52.410 私たちが交流するたびに、 そのチャットメソッド、 ファンクションジェネレーター、 私は最終的にそれを正しく理解する。 06:52.440 --> 06:55.290 そのチャットジェネレーターが呼ばれている。 06:55.470 --> 06:58.860 そして、 通過しているのはこれまでの歴史のすべてだ。 06:58.860 --> 07:03.720 そして、 そのメッセージのセットを構築し、 それがOpenAIに送信される。 07:03.750 --> 07:07.470 だから、 それぞれの通話に対して、 全履歴が提供される。 07:07.470 --> 07:10.980 だからこそ、 その前の文脈がある。 07:10.980 --> 07:17.970 LLMが、 GPT4が、 30年前に私たちがそう言ったことを覚えているかのようではない。 07:17.970 --> 07:20.520 ただ、 コールがあるたびに、 すべてをパスするんだ。 07:20.520 --> 07:22.080 もうお分かりだろう。 07:22.080 --> 07:26.010 だから、 くどくどと書いてしまって申し訳ないんだけど、 本当に大事なことだと思うんだ。 07:26.400 --> 07:35.130 ええと、 そうだ、 下にprint文がいくつかあるのを覚えているだろう。 07:35.130 --> 07:41.700 最後に歴史がどうのこうのと言ったが、 これはグラディオが送ってくれたものだ。 07:41.730 --> 07:48.500 私たちが言ったこと、 言ったこと、 言ったこと、 言ったこと。 07:48.890 --> 07:56.480 そして、 それをGPT 4ゼロの正しいフォーマットに変換したんだ。 07:56.510 --> 07:57.950 ええと、 GPTフォーミニ。 07:58.100 --> 08:02.000 私たちは、 それを役割システムの内容のリストに変換したんだ。 08:02.000 --> 08:03.110 君は役に立つアシスタントだ。 08:03.110 --> 08:05.360 そしてユーザーは、 こんにちは、 と言った。 08:05.360 --> 08:07.910 するとアシスタントは、 「こんにちは、 今日はどのようなご用件でしょうか? 08:07.910 --> 08:08.540 などなど。 08:08.540 --> 08:11.450 だから、 そういうことにしたんだ。 08:12.530 --> 08:18.530 さて、 先に進む前にちょっと余談をさせてもらうが、 これは重要な余談だ。 08:18.530 --> 08:20.420 だから、 これは私だけがしゃべっているのではない。 08:20.420 --> 08:24.230 これは、 私が君たちに種を蒔きたいことなんだ。 08:24.230 --> 08:31.670 後で触れることになるが、 重要なポイントだ。 08:31.730 --> 08:33.590 そうでなければ、 そうあるべきだ。 08:33.800 --> 08:42.020 ええと、 だから、 この構造、 このシステム・ユーザー・アシスタント・ユーザーについて、 あなたは考えているかもしれません。 08:42.140 --> 08:43.480 ああ、 これもそうだ。 08:43.510 --> 08:49.960 LLMでは、 このようなことは構造化されているのでしょうか? 08:49.960 --> 09:00.160 このデータをLLMに提供するとき、 私たちは何らかの形で、 辞書のような、 辞書のリストのような形で提供されているのでしょうか? 09:00.280 --> 09:04.300 というのも、 Llmsはトークンを取るだけだと思っていたからだ。 09:04.300 --> 09:08.290 トークンのリストを受け取り、 次のトークンを生成する。 09:08.290 --> 09:13.990 では、 この辞書などのリストは、 トークンの世界にどのように変換されるのでしょうか? 09:13.990 --> 09:16.300 そして、 もしあなたがそのような考えを持っているなら、 それは素晴らしい考えだろう。 09:16.300 --> 09:17.680 ああ、 とてもいいね。 09:17.680 --> 09:29.290 答えは簡単で、 トークンがGPT4LLMに渡されるだけです。 09:29.290 --> 09:39.760 何が起こるかというと、 OpenAIはこれを一連のトークンに変え、 これがシステムプロンプトの始まりであることを説明する特別なトークン、 09:39.760 --> 09:44.430 特別な方法を持っている。 09:44.430 --> 09:47.670 これがユーザーとアシスタンス対応の始まりである。 09:47.670 --> 09:59.010 そして、 そのマークアップ全体をトークン化し、 LLMに情報を伝える特別なプレースホルダートークンを含む。 09:59.010 --> 10:01.410 システム・プロンプト・モードに切り替えます。 10:01.410 --> 10:02.880 これがシステムプロンプトのテキストだ。 10:02.880 --> 10:04.500 そして今、 システム・プロンプト・モードから抜け出した。 10:04.530 --> 10:07.410 今はユーザーメッセージなどをやっている。 10:07.410 --> 10:11.460 つまり、 この構造はOpenAI APIに送るものだ。 10:11.490 --> 10:13.980 それをトークンに変換する。 10:13.980 --> 10:19.470 そして、 そのトークンがLLMに送られ、 次のトークンを予測する。 10:19.950 --> 10:24.300 と言われるかもしれない。 10:24.300 --> 10:35.340 しかし、 LLMはどのようにして、 この特別なトークンがシステムメッセージを意味することを知り、 それをその高レベル指令と解釈するのだろうか? 10:35.340 --> 10:39.180 また、 このトークンはユーザー、 このトークンはアシスタントを意味する、 などということをどうやって知るのだろうか。 10:39.210 --> 10:43.740 何がその能力を与えているのか、 それは何らかの形でアーキテクチャに組み込まれているのか? 10:44.040 --> 10:46.590 それに対するとてもシンプルな答えがある。 10:46.590 --> 10:49.530 いや、 そう訓練されているからだよ。 10:49.560 --> 10:54.270 そのような構造で、 何百万もの例で、 たくさんのデータで訓練されている。 10:54.270 --> 11:00.300 そして、 システム指示の中で特定の指示が与えられると、 最も可能性の高い次のトークン、 最も可能性の高いレスポンスは、 11:00.300 --> 11:07.440 そのシステム・プロンプトに従ったものになることを、 トレーニングを通じて学習している。 11:07.470 --> 11:09.510 単純化しすぎましたね。 11:09.510 --> 11:14.940 シェフのようなテクニックのようなものとか、 そういうニュアンスがあるんだ。 11:14.940 --> 11:18.570 このようなことをすべて知っている人は、 それを聞いて、 ああ、 ちょっと単純化しすぎだが、 一般的な考え方だ、 11:18.570 --> 11:19.770 と言うだろう。 11:19.770 --> 11:21.090 基本的な考え方だ。 11:21.090 --> 11:24.540 この構造はAPI構造の一種である。 11:24.540 --> 11:27.390 これが、 私たちがやりたいことをOpenAIに伝える方法です。 11:27.390 --> 11:31.170 そしてOpenAIはその構造をトークンに変える。 11:31.170 --> 11:38.390 つまり、 最初のステップに進むために、 グラディオはこのようなフォーマットでデータを提供してくれる。 11:38.420 --> 11:48.680 それをこのフォーマットにマッピングしてOpenAIに送り、 OpenAIがそれをトークンに変換する。 11:48.680 --> 11:54.740 それは、 これまでの会話全体について、 すべてについて、 会話全体を取得するたびにLLMに入り、 11:54.740 --> 12:04.400 その次に来る可能性が最も高いトークンのシーケンスを生成することだ。 12:04.490 --> 12:12.770 そして、 それがアシスタンスレスポンスとして私たちに返される。 12:12.980 --> 12:15.860 だから、 かなり長いサイドバーだったことに気づいた。 12:15.860 --> 12:18.740 非常に重要で、 基礎となる理解だ。 12:18.740 --> 12:22.190 そして、 私たちが、 特にオープンソースモデルに注目するときには、 またこの話に戻ることになるだろう。 12:22.190 --> 12:28.190 そして、 私たちは実際にこのような生成されたトークンや特別なトークンを目にすることになる。 12:28.340 --> 12:35.780 それでは、 このチャットボットの構築を進める次のビデオまで、 このビデオを一時停止します。