NTTコムウェア株式会社 エバンジェリスト(データサイエンティスト) 川前 徳章
“Prompt”を知り数年経っているが、未だに自分はpromptとうまく言えない、正確に言うと、言えるが、発声するまでに数秒かかる。発声までに、「脳内でPRONTO、違った、プロトン、もっと違った、pronto、何を言おうとしたのだろうか、そうだprompt!」と紆余曲折を経るので時間がかかる。最初の「PRONTO」は早茹でスパゲティの商品名、後者の「pronto」はイタリアで『Ciao, Buon giorno』に次いでよく聞く挨拶に使われるフレーズ。実は発声だけでなく書くのも怪しく、何度もpromptを間違えた。私の語彙体系は更新されず、共存も上手くいっていないようだ。
時間がかかるのはpromptの発声だけでない。この連載も遅々として進まず、関係者の皆様にご迷惑をかけていることを心よりお詫び申し上げます。OK GoのI Won’t Let You DownのMVは全編ワンカット撮影で有名だが、このMVに、もし、私が何らかの形で関わっていたら遅延が発生し、ワンカット撮影ができず関係者をガッカリさせたに違いない。
スパゲティの早ゆでの秘密は、麺に切り込みを入れることで、麺とお湯との接触面を拡大させたことにあるようだ。LLMではAttention mechanismでqueryが参照する範囲(contextとも言われることがある)の拡大がLLMの性能に影響を与える。Promptには生成AIのモデルのtuning及やアウトプットを制御する役割があり、今回はLLMにおけるそれぞれの役割を紹介する。
推しのLLMのアウトプットが期待から程遠かった場合、がっかりした経験はないだろうか?その解決策として、第二のLLMを探しに行くのだろうか?あるいは期待通りのアウトプットが得られるように推しのLLMを訓練するのだろうか?例えば、刀が刃毀れした場合には刀の買い替えと刀研ぎに出す選択がある。刀の状態にもよるが、大抵はコストの問題もあり、推しの刀を刀鍛冶職人など専門家に刀研ぎを依頼するのではないだろうか?余談になるが、以前、銀座のショップで見た刀の価格は、偶然なのか少し前のLLMの初期学習費用に近いものだった。以前より学習費用は安くなってきているとはいえ、コストの問題は生成AIでも重要な問題の一つである。
話を戻し、後者の選択、期待通りのアウトプットを得るため、LLMの鍛冶担当であるプロトンでなくLLMを制御するpromptの役割を見てみる。図1にpromptを含めたLLMの訓練方法を示す。喜ばしいことにLLMを構成するノードや重み等のパラメタを更新するチューニング(tuning)と呼ばれる多くの訓練手法がある。
図1で示す通り、最初に実装が終わり初期化状態のモデルがあり、それに対しPre-training(更にContinual training/Future pre-trainingなどを実施する場合もある)を実施することでLLMを得る。
前回紹介した通り、生成AIの柱であるLLMにも呼吸に相当する誤差逆伝播を用いた学習がある。学習済みのLLMのtuningにも更新戦略や更新対象のパラメタの違いだけでなく追加学習用のデータによりさまざまな方法が存在する。また検索(Search)との合わせ技であるRetrieval-Augmented Generation (RAG)がある。
Tuningによりパラメタを更新する戦略にはSupervised Fine Tuning(SFT)、Instruct Tuning、そしてReinforcement Learning from Human Feedback(RLHF)がある。SFTは、ラベル付きのデータを使用して、LLMを特定の下流タスク(Downstream task)に適応させる。Downstream taskは、LLMが訓練後に達成するタスクで、具体的には文章分類、抽出、要約や質問応答などのタスクがある。Instruct Tuningは、プロンプトと対応するLLMの出力のペアのデータセットを使用して、LLMをドメインやタスクに適応させる。Instruct Tuning によりLLMはInputの続きを予測するNext token predictionからInput の指示に従うテキスト生成のタスクを実行できるようになる。RLHFは強化学習(Reinforcement Learning, LR)と人間のフィードバックを用いたLLMのパラメタの更新手法である。この方法では、エージェントが訓練対象のLLM、報酬はそのLLMのアウトプットに対する人間の評価である。RLHFによりLLMのアウトプットが人間の評価に合わせられるようになるので、関連分野の論文ではAlignmentと言い、マルチモーダルのモデルなどにも頻繁に用いられている。これらのtuning以外にも、レイヤ毎に学習率を変え、更新対象のレイヤを上位レイヤから徐々に広げる等々の更新手法も存在する。
Tuningによりパラメタを更新する手法は、1)LLM全体、つまりLLMを構成するノードの重み等のパラメタを全部更新するfull-model fine-tuning (FFT)、あるいは2)LLMの特定の部分(例えば一番上の層(レイヤ))やLLMに追加したadapter(外部ネットワーク)のパラメタを更新するparameter-efficient fine-tuning (PEFT) に大別できる。更にPEFTをpromptの観点でみるとLLM全体を凍結し、promptの学習あるいはtuningがある。このtuningもPrefix Tuningはパラメタとトークン、Prompt TuningとP-tuningも入力トークンを追加して更新する方法に分けられる。
PEFTにおけるAdapterは後からLLMのレイヤなどに追加するネットワークであり、LLMの身代わりとなり?これらネットワークのパラメタを更新する手法である。PEFTはさまざまな手法が提案されているが、この分類はちょっと荒い。どれだけ荒いかというとLoRAとその拡張がAdapterと纏められているぐらいである。Adapterに関してはTransformer補完計画(仮題)で改めて触れる予定である。どうしても現時点でのPEFTの厳密な分類を知りたい方のために以下の文献を紹介する。
PEFT全般でなく、対象を絞ったpromptを使ったLLMの制御方法をもう少し詳しく見てみる。#promptはパラメタなの?PEFTの一種で良いの?という見方もある。Prompt DesignはLLMの出力を制御するため、最適なpromptを人間が頑張ってデザインする方法である。この方法はLLMの訓練よりもPrompt Engineerの訓練と言えそうだ。
Prefix TuningはLLMのアウトプットを制御するため、LLMの左側に更新可能なネットワークをPrefixとして結合する方法である。Prefix はLLMに追加したネットワークであり、レイヤ側のパラメタ更新を含むので、Adapter型の一種と言えなくもない。LLMがEncoder (bidirectional)あるいはDecoder (unidirectional)のアーキテクチャであってもPrefixはAttentionの参照範囲にあるので、他のトークンとの重みの加算を通しLLMのアウトプット(出力トークン)に影響を与える。TuningはLLMを凍結しつつ、このネットワークが入力の「先行あるいは指示」に相当するテキストと共に出力トークンの分布を更新する。
その結果トークンの集合であるLLMのアウトプットを制御できる。推論時は制御の目的に合わせ更新済みのネットワークをLLMにPrefixとして結合して利用する。例えば、出力制御の目的が「入力する表形式のデータからテキスト変換」タスクであれば、訓練時は入力する「表形式のデータ」から「テキスト」を変換するようにPrefixのネットワークを更新する。その結果、更新されたネットワークは同じLLMが、「入力する表形式のデータからテキスト変換」のタスクを実行するように制御される。出力制御の目的となるタスクが変わり、そのタスクに合うPrefixのネットワークが無ければ訓練で新たに更新することになるが、タスクに合うネットワークがあればそれを再利用あるいは継続更新して利用することもできる。
Prompt TuningもLLMの出力を制御するための方法であり、LLM(のパラメタ)を固定する点は同じだが、LLMに制御用のネットワークでなく、入力側で入力トークンに並行にembeddingを連結する点が異なる。先ほどのcontextの拡大に相当する。TuningはLLMを凍結しつつ、このembeddingが入力の「先行あるいは指示」のテキストであるpromptと共に出力トークンの分布形状の出力を制御できるように更新する。推論時はタスクに合わせ更新したembeddingをテキストに結合してLLMへの入力として利用する。例えば、出力制御の目的が「入力テキストの要約」タスクであれば、訓練時はLLMのアウトプットが入力テキストの要約になるようにembeddingを更新する。その結果、更新されたembeddingは同じLLMのアウトプットが「入力テキストの要約」となるように制御する。出力制御の目的が変わってもその目的に合うembeddingがあれば、再利用可能であるし、無ければ更新する点もPrefix Tuningと同じである。
P-tuningも入力トークンにembeddingを連結するが、このembeddingは(図では省略したが)PromptEncoderの出力であり、Prefix Tuning やPrompt Tuningと異なりLLMへの入力に対する連結方向が垂直であり、全てのトークンに共通のembeddingが連結される点が異なる。
PEFTはtuningとして有効な方法であるだけでなく、Prompt Tuning でも触れたようにPEFTにより学習済みのネットワークを同じLLMに対して再利用/共有することができる。
Instruct Tuningのようにデータを用意して「こういう入力にはこのように出力してください」あるいはpromptを通して「promptにこのようなcontextを追加するのでそれ込みで解釈してください」とLLMを制御する手法は他の手法よりも効果的に見え、ともすれば他の方法を「邪魔になるからさっさと・・・」と思われる方もいるかもしれない。これらの方法はAdapterとは排他的でなく、むしろ併用することで効果を発揮する。例えばRHFT+Adapter+Prompt tuningなどもあり得る。多くのtuningはLLMだけに限らずVison language model (VLM)やMulti Modal language model (MMLM)や画像生成のモデルなどにも適用できる。例えば、Instruct TuningやRLHFによりVLMのVision Question Answering (VQA)の性能を向上させ、learnable tokenはpromptに限らず、モダリティの緩和でも使われている。
生成AIのモデルにとりpromptは検索にとってのquery同様にコミュニケーション手段の一つである。従って、promptの良し悪しが生成AIのアウトプットの質を左右する。図1には示していないが、モデルの損出関数や強化学習の報酬の与え方でモデルのアウトプットを制御する手法が存在する。Promptは希望するアウトプットが得られるようにLLMを訓練するが、問題あるアウトプットが出てこないようにLLMを訓練することもある。例えば、Negative Promptや訓練用のデータに訓練を阻害する“ポイズン”を埋め込む方法がある。LLMあるいはそれに基づくサービスを提供する場合、セキュリティの問題としてPrompt Hacking (Injection, Leaking, Jailbreaking)などの対策も必要である。
LLMは巨大なネットワークと同時にそれよりちょっと小さなネットワークの集合体と見做せる。であれば、ネットワークのパラメタ等の重みを変えるよりは、意図した重みを持つネットワークを見つけた方がtuningとして効率的と考えることもできる。その発見手段がpromptであり、「巨大なネットワークであるLLMを制御するよりも、制御しやすい小さなネットワークの発見に相当する第二の地球探しに出る」と解釈できるかもしれない。FFT以外のtuningではLLMのパラメタを一部凍結(Frozen)するため、勾配がそこで止まって先に進まないじゃないか?と思いそうだが、その部分だけ勾配の計算はするが更新せず、先のノードに受け取った勾配を伝播する。具体的な実装、ここではPytorch実装のLLMのコードを見るとPEFTを導入してもloss.backward()があり、誤差逆伝播が実行されることがわかる。
生成AI関連の文献や論文を見比べると同じ概念が違う用語で表現されている場合がある。LLMのパラメタを固定することをFrozenと言い、論文中では雪の結晶や鍵のロックで記号化されていることが多い。逆にLLMを更新する場合はTunable(Learnable)と言い、対象的に炎や鍵のアンロックで記号化されている。凍結された世界は透き通った世界と見ることもできるため、雪の結晶や氷の記号を使うのは理にかなっているかもしれない。Prompt周辺も表現が豊富である。テキストをトークナイザでトークン化することは、トークナイザが数十万の語彙に対応していても、トークンの取りうる表現は固定であり、このようなトークンはdiscreteやhard、これらで構成されるpromptはdiscrete promptやhard promptとも呼ばれる。一方でトークンが分散表現のベクトル(embedding)に変換されると、ベクトル自体が更新により表現の多様性を実現できるのでlearnable vector, continuous vectorやsoft vector、これらを含むpromptはlearnable promptやsoft promptとも呼ばれる。
表現の多様性は厄介な側面もあるかもしれないが、解釈の柔軟性を許容する側面もある。例えばPEFTとしてPrompt TuningとPrompt Designの違いは、前者の方がprompt相当のトークンが固定(Hardやdiscrete)と異なり、Softやcontinuousであるだけでなく、初期値として与えたトークンの分散表現を誤差逆伝播により更新(learnable)出来ると解釈できる。もうちょっと解釈をすすめてみる。LLMから期待するアウトプットを引き出すpromptを用意できない場合、LLMのパラメタ更新以外にはpromptを最適化することになる。PromptがHardであるよりSoftの方が取りうる表現の種類が多く、かつ図で示したようにpromptのトークンの更新可能という魅力がある。またLLMのアーキテクチャがEncoderでもDecoderであってもpromptに対応する出力は他の出力と異なりクロスエントロピー等を損出関数の誤差を逆伝播として利用しない。「アウトプットのためにすることはtuningのためになっている」のである。ただし、API経由等でLLMのパラメタへのフルアクセスを許可しない場合は、Prompt Tuningなどのtuningを簡単に適用するのが難しい。
Prompt TuningによりLLMを「こんなこともあろうかと思って」訓練したが、後から「この知識も入れて稽古しておけば良かった」ということもあるかもしれない。そんな時にはRAGやin context learning (ICL)がある。PromptがLLMを含む生成AIとのコミュニケーション手段であるが、ここではPromptがLLMの訓練の指示でなく、LLMのアウトプットに対する指示になっていることに注意する。Tuningと違いpromptはinputそのものになっている。まずはイタリア語教室の会話を見てみよう。
イタリア語の先生「Ciao! イタリア語でおやすみなさいって言ってください。」
イタリア語の初級者「ローマ字は勉強したのですが、イタリア語は勉強したことがないのでわかりません。」
イタリア語の先生「大丈夫、これから勉強すればOKです。
“こんにちは”はBuon giorno、“こんばんは”はBuona sera、“夜”はnotteです。分かりますか?」
イタリア語の初級者「notteはseraと同じ女性名詞かな?だったらBuona notte!」
イタリア語の先生「Bravo!」
イタリア語の初級者「Grazie! Un momento. 携帯に電話がかかってきました。Pronto!」
この会話を定型化すれば、イタリア語の会話上達が早くなりそうだ。このpromptの定型化がpromptのテンプレートであり、生徒がLLMに相当する。会話で色をつけた箇所に例が全くない場合はzero-shot、例が一個であればone-shot、それ以上であればfew-shotと呼ぶ。Promptにfew-shotを埋め込むと、LLMのpromptのコンテキストから学習する(ICL、few shot learningと言われることもある)、それをアウトプットに反映する。多くのICLでは、LLMは凍結しているので、学習と言っても先ほどのtuningのようにLLMのパラメタを更新しているわけではない
早速、promptを使ってLLMにタスクを依頼しよう。これまでお世話になったGPT-2から同じTransformer decoderベースかつ最新のLLMであるMeta-Llama-3-8B-Instruct(Llama3-8b)にお世話になります。GPT-2に代わりLlama3-8bをLLMとして利用するが、Llama3-8b になってもTransformerのフレームワーク、Attention mechanism、そして誤差逆伝播を使うことに違いはないが、先に紹介したInstruct Tuningが活躍している点が異なる。リャマさん、宜しくお願いします。まずはJupyter Notebookを使って同じ質問をしてみます。
messages = [
{"role": "system", "content": "A chat with the user for language translation"},
{"role": "user", "content": "Pronto? Ciao! イタリア語でおやすみなさいって言ってください。"},
]
prompt pipeline.tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
print(f"prompt: {prompt}")
terminators = [
pipeline.tokenizer.eos_token_id,
pipeline.tokenizer.convert_tokens_to_ids("<|eot_id|>")
]
outputs = pipeline (
prompt,
max_new_tokens=256,
eos_token_id=terminators,
do_sample=True,
temperature=0. 6,
top_p=0. 9,
)
print(outputs[0]["generated_text"][len(prompt):])
出力は以下の通り(一部ディレクトリ等の情報を削除しています。)
正解なのは勿論、英語、日本語、イタリア語にも対応できそうですね!期待が膨らみます。
ここからが本番。高校時代に「アンモナイトは絶滅した」と授業で習ったが、その理由までは習った記憶がない。世界中の海にさまざまな形状で適応していったアンモナイトが絶滅した理由が知りたく、その疑問にLlama3-8b(以下、Llama3)は答えてくれるだろうか?テンプレートの一部を以下にように変更する。(これ以降、Llama3及びそのアウトプットは2024年6月21日現在のものである)
messages = [
{"role": "system", "content": "A chat between a user and LLM"},
{"role": "user", "content": "アンモナイトが絶滅した理由を簡潔に教えて"},
]
このpromptに対するLlama3のアウトプットは
😊
The ammonite, a type of cephalopod, went extinct at the end of the Cretaceous period, about 65 million years ago. The main reason for their extinction is believed to be the massive asteroid impact that occurred at that time, known as the Chicxulub asteroid impact. This impact cau sed a global cooling of the climate, massive earthquakes, tsunamis, and wildfires, which likely made it difficult for many species, including the ammonites, to survive.
Additionally, the ammonites were already facing some challenges, such as a decline in their food supply and competition from other cephalopods. The combination of these factors likely made them more vulnerable to extinction.
The ammonites had been thriving on Earth for over 300 million years, and their fossils are still found in many parts of the world. They were a fascinating group of animals, and their extinction is still studied by scientists today to gain a better understanding of the complex factors that contribute to mass extinctions. 💥
素晴らしい!鯨偶蹄目ラクダ科のリャマでも日本語の質問を理解し海の中のこともご存じとは。念のため、このアウトプットを検索したところ、任意のページのコピーではなく、部分的な内容も含め複数のページが見つかった。
もうちょっと詳しくpromptを設計するともっと詳細な答えに辿り着くかもしれない。まずはPrompt design。そのためにLLMの近種であるサーチエンジンで調べると次のようなことが分かる。
- アンモナイト亜綱は、オルドビス紀から生息するオウムガイ亜綱(英語版)の中から分化したものと考えられている。
- 生態ピラミッドの最高次捕食者として栄えた時期もあったオウムガイ亜綱とは違い、アンモナイト亜綱はその進化史の初めから食い食われる中位の捕食者としての出現であった。
- アンモナイト亜綱より先に存在していたオウムガイ亜綱は、これも長い地質時代の間に多くの種が現れては消えていった。それでも、遠い子孫がわずかに生き延び、我々はそれを「オウムガイ(オウムガイ属、現生のオウムガイ類)」と呼んでいる。
(出典はhttps://ja.wikipedia.org/wiki/アンモナイト、検索日時は2024年6月21日)
Wikipediaなら既にLLMの学習データに含まれていそうである。Prompt用に整理する。
そこでpromptを以下の通り作成し、得られたアウトプットをまとめて示す。Promptは上記messages内の {"role": "user"} の"content"に相当する。
A fascinating question about the Ammonites!
A very specific and interesting question! 😊
The Ammonite suborder, which thrived during the Paleozoic and Mesozoic Eras, did indeed survive the mass extinctions at the end of the Permian and Triassic Periods. However, they went extinct at the end of the Cretaceous Period, which is often referred to as the K-Pg extinction event.
There are several theories as to why ammonites failed to survive the K-Pg extinction event, while they had survived previous mass extinctions. Here are a few possible reasons:
簡潔にとお願いしたけど、字数が足りなかったみたいである。その場合pipeline() 中のmax_new_tokensの値を大きくすることで表示できるようになる。
A great topic! 😊
Let's have a chat about the differences between Ceratite and Ammonite.
🐳
Ceratite and Ammonite are both types of extinct cephalopods, but they belong to different orders and have distinct characteristics.
**Key differences
A fascinating topic! 😊
So, you're asking about the mass extinctions at the end of the Triassic period (around 201 million years ago) and the Cretaceous period (around 65 million years ago), and how they affected the ammonites and ceratites.
During this period, most of the ceratites (a type of cephalopod) went extinct, while the ammonites (also a type of cephalopod) survived. The reasons for this are still debated among scientists, but some theories include:
文字数の制限で肝心の部分が出力されていない例もあるが、回答だけでなく要約にもなっているようだ。決定的な原因の解明は今後の研究の展開を待つとして、現時点で検索や専門書で得られる知識と大差ないアウトプットが得られたと思う。
Llama3を使ってみて、promptの発声が今ひとつでも、LLMはpromptを理解しタスクを実行しているように感じた。そもそもpromptは多くの機能を持つ多義語と言えそうだ。Prontoやプロトンとも無関係とは言えないのではないか?だからといってpromptの発声に時間がかかっても許されたとしても、原稿の遅延は許されないだろう。次にはもっと早く提出できるようにしたいと思います。
「日本語に対応するLLMには大量の日本語の学習データが必要だ」と言われる。Llama3を利用してみると、「ドメインの知識が日本語の学習データになくても英語の学習データに存在し、それをLLMの学習や訓練に用い、結果、LLMが翻訳タスクを実行できれば日本語に対応したLLMになる」と感じる。言い換えるとLLMの知識にはドメイン知識と言語知識に分けられ、LLMが言語知識を獲得すれば、知識獲得した言語間(例えば日本語と英語)を跨いだドメイン知識を利用したタスク(日本語で英語のドメイン知識を利用したタスク)を実行できるのではないか。例えばドメイン知識を持つLLMをPEFTで言語翻訳タスクに特化して訓練する方法も考えられる。ここでpromptは刀鍛冶職人のようにLLMのtuningや、データの海に存在したアンモナイトのような価値あるアウトプットの生成指示のため活躍している。特に後者の役割は自然言語処理のアプローチを変えてしまった(ACL2023に参加しました:カール起きて!ナイアガラ上空にジャコビニ流星が!)。
プロトンミサイルがあったとして、それが突入した太陽のような状態、ここではHallucinationやCatastrophic forgettingをプロミネンスのように纏う状態の生成AIのモデルがあったとしても、それをpromptが制御できる可能性と希望を感じて貰えたと思う。「アンモナイトが深海にまで生息域を拡大していたら今でも生き残ったのかも」と思いつつ、次回は引き続きLLMを指示するpromptについて深く見る「Promptがうまく使えなくて」。
川前 徳章 [かわまえのりあき]
エバンジェリスト
(データサイエンティスト)
2009年NTTコムウェア入社。大規模データの分散処理基盤の調査・導入から始まり、レコメンドシステム、情報検索、機械学習、自然言語理解と生成、AI等データサイエンスの研究開発とその導入に従事。現在は生成AIやマルチモーダルに向けたAIの研究開発を行っている。
各種データサイエンスに関する講演など対外的な活動も多く、KDD2021-、ICLR2022-、NeurIPS2021-、ICML2022-、AAAI2024-、WSDM2024-等のトップカンファレンスのPCや査読委員など、国内外でAIやデータサイエンス系の論文審査委員も多く担当している。2023年9月より上智大学大学院 非常勤講師も務める。
エバンジェリスト(データサイエンティスト)
コラム一覧