JupyterLabの素晴らしい世界へようこそ｡
そして2週目に入った｡
3日目｡
このノートを出して
そこで今回は､ チャットボットとしても知られる会話型AIについて､ さっそくご紹介しよう｡
まずはいつものようにインポートし､ 環境変数を設定する｡
そして OpenAI を初期化する｡
今回はOpenAIを使う｡
そして､ もしそうしたければ､ 他のモデルに乗り換える練習として持っていてもいい｡
では､ 基本的なシステムメッセージから始めよう｡
あなたは役に立つアシスタントだ｡
分かった｡
さて､ メッセージの構造について少し話をしたい｡
まず最初に､ OpenAIへのプロンプトメッセージの構造を思い出してください｡
ええと､ これはもう何度も見てきたことだから､ 私が説明するのに飽き飽きしただろうね｡
あれだ｡
もう1度だけ｡
よくご存知でしょう｡
システムにユーザーを与える辞書のリストで､ アシスタントが応答し､ 次にユーザーが応答するといった具合だ｡
そして､ 他にも何かあると言ったのを覚えているかもしれないが､ 今はまだだ｡
システム・ユーザー・アシスタント｡
ユーザーアシスタント｡
ユーザーアシスタントユーザーなど｡
さて､ これからchatという関数を書きます｡
チャット機能には､ メッセージと履歴の2つの入力がある｡
Messageは､ チャットが応答する必要のある､ 現在の､ あー､ 質問されているメッセージを表す｡
そして歴史は､ 以前のすべてのメッセージ､ 以前のすべてのやりとりの履歴を持っている｡
そして歴史の構造はこうなる｡
リスト､ リストからなるリストになるだろう｡
そして､ このようなサブリストは､ 単にユーザーの発言とアシスタントの返答､ ユーザーの発言とアシスタントの返答などである｡
では､ なぜそんなことをお願いしているのか？
なぜ､ このような引数で､ このような関数を書こうとするのか？
その答えは､ Gradioがチャット・ユーザー・インターフェースで使うことを期待している特定のタイプの機能だからです｡
だからGradioは､ メッセージを受け取るchatという関数を書くことを期待しているのだ｡
この構造体で履歴を取り､ 次のレスポンス､ つまりこのチャットに対するレスポンスを返す｡
だから､ そういう形式を考えているんだ｡
この関数の仕事は､ このようなスタイルのメッセージをこのように変換することだ｡
そこで､ この構造を1行ずつ繰り返し､ 上にあるような構造を構築する必要がある｡
それが理解できればいいのだが......｡
そうでなくても､ それがどんなものかをお見せすれば納得していただけるだろう｡
そこで､ chatという関数を定義している｡
入力されたメッセージに応答するために得たメッセージを受け取り､ 以前のメッセージの履歴を受け取る｡
そこでまず､ メッセージのリストを設定する｡
そして､ 一番最初にシステム・プロンプトを入力する｡
もちろん､ その後は歴史を反復することになる｡
ヒストリーの各要素は､ 2つの値を持つリストの1つである｡
だから､ それをユーザー・メッセージ・アシスタントのメッセージに展開するんだ｡
そして､ ユーザーのメッセージとアシスタントのメッセージを追加する｡
その都度､ その都度｡
つまり､ 履歴の各行がこのリストでは2行になる｡
1つはユーザー用､ もう1つはアシスタント用だ｡
それが完全に意味をなしていることを願うよ｡
今すぐだ｡
そうでなければ､ いつでもできる｡
まあ､ その必要はない｡
いつでもprint文を入れられると言おうとしたんだ｡
ええと､ 私には先見の明があったので､ 自分でいくつかのプリント文を入れたんだ｡
だから､ これを見ることになる｡
履歴を印刷し､ メッセージを印刷します｡
だから､ それも見ることができる｡
次の行は､ このチャットではお馴染みのメソッドで､ この時点で､ この関数､ すみません､
この時点で､ メッセージのセットを受け取り､ それを使ってOpenAIを呼び出します｡
だから､ OpenAIチャットのドットコンプリートやドットクリエイトをやっているんだ｡
モデルを渡し､ メッセージを渡し､ 結果をストリームしてくださいと言うつもりだ｡
そうかもしれない｡
そして､ 私たちはそれを通過し､ 返答を得る｡
ええと､ つまり､ これは実際には機能ではないんだ｡
私たちは一つひとつ答えを出していくので､ 本当にジェネレーターなんだ｡
オーケー｡
つまり､ 先ほどのスライドにあったような､ インスタント・メッセージのようなユーザー・インターフェースを作りたいのです｡
だから､ 次から次へとやってくるメッセージをどうキャンバスに描くか､
その方法を考えなければならない｡
ええと､ このチャットメッセージから返ってくる反応からするとね｡
ええと､ お気づきになったかどうかわかりませんが､ 私はもちろん嘘をついています｡
本当に簡単なことだよ｡
一本の線になる｡
Gradioにはチャット・インターフェイスというものが付属していて､ チャット・インターフェイスは､
このような構造を持つ1つの関数を想定しています｡
もしあなたが､ メッセージと履歴をこの特殊なフォーマットで受け取る関数を書いたのなら､ Gradioにとってそれはたった1行のコードに過ぎない｡
ええと､ 本当にそんなに簡単なことなのか見てみよう｡
チャット・ジェネレーターを定義するために､ 忘れずに実行する必要がある｡
そしてインターフェイスを立ち上げる｡
そしてここにある｡
これが私たちのチャット・インターフェースです｡
別ウインドウで表示させよう｡
そして､ こう言うんだ｡
こんにちは｡
本日はどのようなご用件でしょうか？
ネクタイを買いたい｡
どんなネクタイをお探しですか？
色や柄､ 素材は決まっていますか？
ええと､ それでお分かりいただけたと思う｡
でも､ 赤のネクタイはクラシックなチョイスだよ｡
ここでは､ いくつかのオプションを紹介しよう｡
そこに答えがある｡
この会話には文脈があり､ その前に何があったかを知っている｡
そしてもうひとつ､ 私たちが最初に話しかけたときからの記憶があるかのように感じるのは､ ちょっとした錯覚だ｡
そして私はネクタイを買いたいと言った｡
私たちが交流するたびに､ そのチャットメソッド､ ファンクションジェネレーター､ 私は最終的にそれを正しく理解する｡
そのチャットジェネレーターが呼ばれている｡
そして､ 通過しているのはこれまでの歴史のすべてだ｡
そして､ そのメッセージのセットを構築し､ それがOpenAIに送信される｡
だから､ それぞれの通話に対して､ 全履歴が提供される｡
だからこそ､ その前の文脈がある｡
LLMが､ GPT4が､ 30年前に私たちがそう言ったことを覚えているかのようではない｡
ただ､ コールがあるたびに､ すべてをパスするんだ｡
もうお分かりだろう｡
だから､ くどくどと書いてしまって申し訳ないんだけど､ 本当に大事なことだと思うんだ｡
ええと､ そうだ､ 下にprint文がいくつかあるのを覚えているだろう｡
最後に歴史がどうのこうのと言ったが､ これはグラディオが送ってくれたものだ｡
私たちが言ったこと､ 言ったこと､ 言ったこと､ 言ったこと｡
そして､ それをGPT 4ゼロの正しいフォーマットに変換したんだ｡
ええと､ GPTフォーミニ｡
私たちは､ それを役割システムの内容のリストに変換したんだ｡
君は役に立つアシスタントだ｡
そしてユーザーは､ こんにちは､ と言った｡
するとアシスタントは､ 「こんにちは､ 今日はどのようなご用件でしょうか？
などなど｡
だから､ そういうことにしたんだ｡
さて､ 先に進む前にちょっと余談をさせてもらうが､ これは重要な余談だ｡
だから､ これは私だけがしゃべっているのではない｡
これは､ 私が君たちに種を蒔きたいことなんだ｡
後で触れることになるが､ 重要なポイントだ｡
そうでなければ､ そうあるべきだ｡
ええと､ だから､ この構造､ このシステム・ユーザー・アシスタント・ユーザーについて､ あなたは考えているかもしれません｡
ああ､ これもそうだ｡
LLMでは､ このようなことは構造化されているのでしょうか？
このデータをLLMに提供するとき､ 私たちは何らかの形で､ 辞書のような､ 辞書のリストのような形で提供されているのでしょうか？
というのも､ Llmsはトークンを取るだけだと思っていたからだ｡
トークンのリストを受け取り､ 次のトークンを生成する｡
では､ この辞書などのリストは､ トークンの世界にどのように変換されるのでしょうか？
そして､ もしあなたがそのような考えを持っているなら､ それは素晴らしい考えだろう｡
ああ､ とてもいいね｡
答えは簡単で､ トークンがGPT4LLMに渡されるだけです｡
何が起こるかというと､ OpenAIはこれを一連のトークンに変え､ これがシステムプロンプトの始まりであることを説明する特別なトークン､
特別な方法を持っている｡
これがユーザーとアシスタンス対応の始まりである｡
そして､ そのマークアップ全体をトークン化し､ LLMに情報を伝える特別なプレースホルダートークンを含む｡
システム・プロンプト・モードに切り替えます｡
これがシステムプロンプトのテキストだ｡
そして今､ システム・プロンプト・モードから抜け出した｡
今はユーザーメッセージなどをやっている｡
つまり､ この構造はOpenAI APIに送るものだ｡
それをトークンに変換する｡
そして､ そのトークンがLLMに送られ､ 次のトークンを予測する｡
と言われるかもしれない｡
しかし､ LLMはどのようにして､ この特別なトークンがシステムメッセージを意味することを知り､ それをその高レベル指令と解釈するのだろうか？
また､ このトークンはユーザー､ このトークンはアシスタントを意味する､ などということをどうやって知るのだろうか｡
何がその能力を与えているのか､ それは何らかの形でアーキテクチャに組み込まれているのか？
それに対するとてもシンプルな答えがある｡
いや､ そう訓練されているからだよ｡
そのような構造で､ 何百万もの例で､ たくさんのデータで訓練されている｡
そして､ システム指示の中で特定の指示が与えられると､ 最も可能性の高い次のトークン､ 最も可能性の高いレスポンスは､
そのシステム・プロンプトに従ったものになることを､ トレーニングを通じて学習している｡
単純化しすぎましたね｡
シェフのようなテクニックのようなものとか､ そういうニュアンスがあるんだ｡
このようなことをすべて知っている人は､ それを聞いて､ ああ､ ちょっと単純化しすぎだが､ 一般的な考え方だ､
と言うだろう｡
基本的な考え方だ｡
この構造はAPI構造の一種である｡
これが､ 私たちがやりたいことをOpenAIに伝える方法です｡
そしてOpenAIはその構造をトークンに変える｡
つまり､ 最初のステップに進むために､ グラディオはこのようなフォーマットでデータを提供してくれる｡
それをこのフォーマットにマッピングしてOpenAIに送り､ OpenAIがそれをトークンに変換する｡
それは､ これまでの会話全体について､ すべてについて､ 会話全体を取得するたびにLLMに入り､
その次に来る可能性が最も高いトークンのシーケンスを生成することだ｡
そして､ それがアシスタンスレスポンスとして私たちに返される｡
だから､ かなり長いサイドバーだったことに気づいた｡
非常に重要で､ 基礎となる理解だ｡
そして､ 私たちが､ 特にオープンソースモデルに注目するときには､ またこの話に戻ることになるだろう｡
そして､ 私たちは実際にこのような生成されたトークンや特別なトークンを目にすることになる｡
それでは､ このチャットボットの構築を進める次のビデオまで､ このビデオを一時停止します｡