見出し画像

ChatGPTによるプロンプトの生成-2:チューニングと対話

前回の記事では日本語テキストからからプロンプトを出力する際にJSONを経由することの意味などを解説しました。

今回はご自分でカスタムしたりチューニングをするとっかかりになる情報をお伝えしたいと思います。そしてまたしても割と長文です。長丁場ですがよろしくお付き合いください。

◆はじめに

ではまあ、今回の内容は既に私以上に研究されている方もいらっしゃる気もします……が、とりあえずやせていただきます!

まず最初に、前回の記事を公開後に皆さんからお知らせいただいた情報の検証を行った結果、BingやGPT3.5でもお願いの仕方をちゃんと考えればJSONを問題ないレベルで出力し、プロンプトの変換までできることがわかりました。私の知識が至らず申し訳ありませんでした。

ただ、BingにはMSによるフィルタリングや外部検索があったりで、処理が思うようにいかない場合がごくまれにあります。また、Bingは外部検索から話を膨らますことができるため、素の状態だとGPT4よりも生成する文章の創造力がやや劣る気がします。気のせいかもしれません。ごめんなさい、詳細な検証はしてません。

また、GPT3.5ではJSON変換をキレイに処理してくれなかったり文章的な表現力がやや物足りない場合があります。これを留意したうえで当記事をご利用ください。

また、既にご存じの方も多いとは思いますが、すでにBDさんを中心とした皆さまにより、使い勝手の良いツールとして完成されたものが公開されています。これはセミクローズな場所で新機能の実装や使い勝手の改善といった開発作業が進んでいますので、すぐにツールととして使いたいという方はBDさんのフォローを強くお勧めします。

◆チューニングのベースとなるGPTプロンプトの例

前回紹介したGPTへのお願い(プロンプト)ですが、分かりやすくするために記述を必要最低限まで絞ったもので、あれだけではうまくいかないことも多々ありました。

ここでまず先に、比較的安定して詳細な変換を行ってくれるお願い文を紹介します。

以下の処理では説明部分は日本語でお願いします。
1: 指定されたテキストを英語に翻訳してください。なお、「夏、海、走る」といった単語を羅列するような表記がある場合、その部分は文章にせず英単語へ翻訳してください。また、短いセンテンスの場合も長文への変換はしないでください。
2: 翻訳された英語テキストから単語同士の関連性を分析して、その結果をJSON形式で出力してください。具体的には、必要とされるカテゴリをJSONオブジェクトとして、関連する属性をキー、それに対応する値をバリューとして記述してください。例えば、{"category":{"attribute1":"value1", "attribute2":"value2"}}といった内容に改行とインデントを入れた形式です。
3: 生成されたJSONデータを基に、英語での自然言語のテキストを作成してください。その際には、JSONデータが保持する情報が適切に反映されるようにし、冗長な表現は抑え、見ている光景を伝えるような内容にしてください。

前回のものよりだいぶ長くなりましたね。前回同様このお願いに続いて単語の羅列や文章を入力してご使用ください。

これはGPT4とBingの両方で比較的バランスの取れたJSONを出力してくれるように調整したものです。GPT3.5でも出力はされますが、結果がちょっと不安定です。3.5はめっちゃ高速なんですけどねぇ……。

でもまあ、BingとGPT4はほぼ同レベルの出力をしてくれますので、無料のBingを推奨ってことでお願いします。

◇チューンナップの前に:小技

チューンナップの話題に入る前に、以下を覚えておくと後々便利です。

最後の一連の処理手順を"@tjp"として記憶してください。次からは@tjpを添えたテキストを同様に処理してください。

これをお願いしておけば次からはテキストに@tjpと添えれば同じ処理をしてくれます。また、チューンナップが終わったお願いをテキストファイルなどで保存しておく場合は文頭に以下を添えてください。

次に示す一連の処理を"@tjp"と呼びます。その後は@tjpを添えたテキストを次の一連の手順で処理してください。

修正を行いました。今度はこれで動くと思います。

これで新規に作業を始める時、このお願いを書き足した内容をコピペしてお願いしておけばその後の作業がちょっとだけ楽になります。

“@tjp”の部分はご自分で分かりやすいものに変えてご利用ください。“#変換”とかでもOKです。

◆JSON変換のチューンナップについて

JSON変換の前に日本語から英語への翻訳処理を行いますが、まずはここをチューンナップする必要があります。

単語の羅列や数単語の短文を渡した場合、GPT君は英訳の段階で、特にChatGPT-4がそこから無理やり文章を作ろうとする傾向があります。変な長文にされるとJSON変換の段階で単語同士の関連付けがおかしなことになるので、まずはこれを避けるためのお願いを一緒に与えます。

前出のお願いでは

「なお、「夏、海、走る」といった単語を羅列するような表記がある場合、その部分は文章にせず英単語へ翻訳してください。また、短いセンテンスの場合も長文化はしないでください。」

という命令を加えてこれに対応しています。

逆に長文を多用する場合であれば、この部分は必要ありませんし、精度も高くなるかも?

いずれにせよ、JSONへの変換で心がけておいた方がいいかな、というポイントは、JSONデータのバリュー部分が極端に長くならないようにすることです。この部分が長くなってしまうと最終的に出力された自然言語型プロンプトが非常に冗長な内容になります。

極端な例になりますが、
「彼女は雨に濡れて寒さで震えている猫を心配そうな表情を浮かべて抱いている。」
というプロンプトよりも、
「彼女は心配した表情で猫を抱いている。猫は濡れて寒さで震えている。」
、といった出力の方が冗長性を抑えらえるし、後々プロンプトを手直ししやすくなります。
でもこれだと猫が2回出るから増殖しやすいんですがね……。

なお、これは後述しますが、1つの長い文章であっても区切りが分かりやすい書かれ方だと後々楽になります。

◆JSONからプロンプトへの出力をチューンナップ

まず、前回の記事で追記として書いてありますが、長文での入力は出力結果が非常に情感のこもった小説的な文章になります。特にChatGPT-4は気持ちとか、行動の背景まで話を膨らませてくれたりします。そこまで行ってしまうとプロンプトは長くなるばかりで不要な情報が増え、重要な単語が埋もれてしまいます。

なので、

「冗長な表現は抑えて見ている光景を伝えるような内容にしてください。」

と追加のお願いをしてあります。

でも、単語の羅列を入力したときはGPT君が多少の脚色を加えてくれて逆に効果的な場合もあります。

このあたりのバランスはご自分の入力スタイルで調整してみてください。

調整に使えるキーワードは多種様々ですので数例だけ以下に紹介します。

「光景を述べるだけの」
「キャラクターの様子を重点的に記述した」
「美しい光景になるような要素を加え」
「写実的な」
「シンプルな」
「緻密な」

ただし、こういったお願いは最初の入力の段階で使用するようにしてください。これの目的はあくまでもお使いのモデルが上手く反応してくれるようにすることです。出力するイラストの調整を目的とするお願いに関しては後述します。

注意点としては「JSONデータが保持する情報が適切に反映されるように」というワードは消さないでください。これがないとGPT君はやりたい放題を始めるかもしれません。自由度を与えたいときは「JSONデータが保持する情報を踏まえて発想を広げるように」とか、そんな言い回しを試してみてください。

◇CLIP Skip 2のモデルに対する自然言語型プロンプトの考察

ここでは自分も完全に理解していないので、とっても端折った説明をします。なので誤認や間違いが多分に含まれている可能性があることをご容赦ください。

NovelAIはdanbooru系のタグと画像を紐づけて学習しています。その際にプロンプトとしてのdanbooruタグを実装するにあたり、すでにあるStable DiffusionのCLIPの影響力が邪魔になりました。それなら既存のプロンプトで一番強力な役目を果たしているCLIPの最深部分を使わずにその1歩手前のところまでを利用して、その1歩手前のところにdanbooruタグをぶち込んでおけばいいじゃないか。そうすればSDの影響は抑えらえれるじゃん、となったと解釈しています。

その後、Waifu Diffusionなどのオリジナルなチェックポイントやそれらを流用したモデルはCLIP Skip 2が主流となったようです。ただし、Skip2のチェックポイントにSkip1で追加学習させたものも存在します。

さて、ここでSDの公式プロンプト記述ガイドを見てみると、本来SDは自然言語での記述を用いています。ただし、1文章が極端に長くなると精度が落ちるようではあります。

もしかして、AIが生成した文章ならAIも理解しやすいんじゃね? なんて根拠のない妄想も捗ります。

それはさておき、SD本来の自然言語能力を活かすにはやはりCLIP Skipは1が良いのではと漠然と考えています。これは使用するチェックポイント次第なので、全部がそうだというわけではありませんが、長文型のプロンプトを試すときはCLIP Skipを変えて違いを見てみてください。何かわかったことがあったら教えてください!

と、投げっぱなしも何なので、下記のようなものを用意しました。

3: 生成されたJSONデータを基に、英語での自然言語のテキストを作成してください。その際には、JSONデータが保持する情報が適切に反映されるようにします。また、合致、あるいは近似するdanbooruタグがある場合、該当する単語を#を表記しない形で利用してください。(また、冗長な表現は抑え、見ている光景を伝えるような内容にしてください。)

これでを先ほどお伝えしたお願い方法の3番目の処理と入れ替えてください。カッコ内は様子を見て付けたり外してください。これでNAI系、WD系との相性が向上します。するといいな。してほしいな。

◆最終出力を後からいじって楽しもう

これはチューンナップというわけではありませんが、JSONから最終的に出力されるプロンプトの調整をやってみましょう。

でも、毎回1から生成し直すのも芸がないです。なので、前回もちょっと書きましたが、ここはGPT君がChatGPTと名乗る所以でもあるチャットを用いた対話方式での調整をやってみましょう。

夏、山、キャンプ、3人の女の子、12歳、河原、鳥、焚火、テント、笑顔、キャンプ料理、夕日


手足がダメダメなのは私のモデルのせいでGPT君は悪くない!
でもなんで裸足なんだろう?

同じ構成で朝食を作っている様子に変更して出力してください。

朝っぽい?

全体の雰囲気は残し、季節を秋に、人数を4人にして、夜にバーベキューをしている光景にして出力し直してください。

1人多いよ! あと、夜だから紅葉が出てない! それと、星空とか追加で書いた方がいいね

この出力をモノクロのスケッチのような絵を表現する言葉を加えて出力しなおしてください。

この出力をモノクロなスタイルから、パステルトーンでビビッドカラーなスタイルに変更して出力してください。

1人減ったし……。あとなんで地べたに座ってるのよ

この出力に全員が地面に敷いたキャンピングシートに座っている様子を追加してください。

ちょっとイメージと違ったけど、まあ許そう

と、こんなことができます。GPT君にツッコミ入れながら出力をいじっていくの楽しいですよ(笑)。

この出力に、追加した要素をすべて取り除き、土砂降りで絶望している様子にして出力してください。

キャンプは楽しいことばかりじゃないよ?

◆最終的なプロンプトのチューニング

他にもあるかもだけどポイントは2つ。今は他を思いつかない。

◇強調を使ってダメなら文章の途中でもぶった切れ!

まず以下の長文テキストをプロンプト化します。

雨が降りしきる都会の片隅で赤いコートを着た10歳ぐらいの少女が雨に濡れながら足早に道を歩いている。よく見るとその少女は猫を大事そうに抱えていて、その様子を気にかけている。猫は体を細かく震わせ寒がっている。少女は早く猫を温かい場所に連れて行こうという決意と心配が混ざった表情だ。

入力した文章。テキトーに書きました

In the corner of a city battered by pouring rain, a 10-year-old girl clothed in a red coat hastily navigates the streets. Despite the inclement weather, she clings tightly to a cat, showing obvious concern for its wellbeing as it shivers from the cold. Her face is a mix of resolve to bring the feline to a warm place and worry about its condition.

その出力結果。ちなみに入力テキストが同じでも結果が微妙に違うことがあります。揺らぎ?

この出力されたプロンプトでイラストを出力しようとしても、なかなか猫を抱っこしてくれません。かといって「clings tightly to a cat(猫にしっかりとしがみつく)」の部分を強調しても猫が大量に増えていくだけだったりします。また「clings tightly」だけを強調しても自分の体を抱きしめ始めたりします。たまにうまく行くんですけどね。

そういう時は「she clings tightly to a cat,」の前でBREAKしちゃいましょう。それでも打率が低ければ「BREAK she (clings tightly:1.1) to a cat」と、軽く強調してみましょう(猫を含めて強調すると増殖の恐れがあるので注意)。

これでかなり打率が上がるはずです。

どうしても外せない要素に関してはこのように強調を試し、それでダメなら文節と文節の間でBREAKし、軽い強調を併用していくと良いでしょう。文節を意識したほうがいいのですが、文の途中でBREAKしても行ける時は行けます。

A 15-year-old girl with blonde hair and blue eyes stands in a meadow wearing a white dress. The wind blows as she holds back her hair with one hand. In the distance, mountains can be seen with a river flowing in front of them. Above the mountains, the sunset can be seen. The girl smiles.

前回使った草原に立つお嬢さんのテキストを今回のお願い方法でプロンプト化したもの

このプロンプト、実は「髪をかき上げている」という表現を「she brushes her hair」と最初は出力しました。英語的には正しい表現ですが、これだとヘアブラシを手に持っちゃうことが多いので、brushesという表現を変えてとお願いして再出力してもらったものです。

本題に戻ります。この出力ではそこそこの確率で髪をかき上げてくれますが、もっと打率を上げたいときは「she holds back her hair」の前でBREAKしちゃいます。

まあ、そもそもの意味が、「風でなびく髪を押さえている」というような英文に変わっちゃってますが……絵面的には問題なし!

◇自然言語型だからって単語型を使っちゃいけないわけじゃない

これも前回軽く書きましたが、全部自然言語だけにしなきゃだめなんてことは一切ありません。出力結果を見て髪型や髪色、服装や背景物を変えたい追加したいなんて時はどんどん単語で書き足してください。

ただし、追加しいたものがイラストの中で大きな役割を荷うものであれば、入力テキストにそれを追加して最初から出力し直してください。

次に、追加先の自然言語型のプロンプトは文法にのっとった英文なので、どこに書いてもいいというわけではありません。必ず英文がおかしくならない位置にしなければだめです。

簡単なのはクオリティ系プロンプトの直後や全体の最後部にまとめて書くとか、人物への言及がある文章の前後に入れ込むとか、です。また、情報を追加したい文章があるBREAK段と同じところに入れることも重要です。

さらに注意する点は、文章中にSheとかHerとかHeとか、人物に関する記述は既にあります。そこに[1girl, blonde hair, white miniskirt,]とか入れちゃうと、さらに人物の追加が発生して増殖します。なのでここは[blonde hair, white miniskirt,]とだけ追加してください。

◆まとめ

今回は実践的な利用の仕方を紹介しました。今回の情報を基にご自分なりにカスタムして楽しんでいただければなと思います。

繰り返しになりますが、手軽に使ってみたいなという方はBDさんが公開されているものをお使いください。凄い機能もありますから!

さて、とりあえず今回はここまでにします。

次はもうちょっとダイナミックに出力を変えていく方法を紹介できればと考えていますが、相変わらず検証したりする時間もとれません。また、今紹介しているようなやり方とは別の方法も模索しており、そちらにも時間を取られそうです。

次回はまたしばらく先になりそうですが、それまで皆さんも色々と試して遊んでみてください。

それでは良きプロンプティングライフを!

この記事が気に入ったらサポートをしてみませんか?