【KARAKURI LM 10本ノック】#6 KARAKURI LM で自動プロンプト最適化を実行してみた
LLMに精度よく生成を行わせるためには、タスクに適したプロンプトが欠かせません。
この記事では、KARAKURI LMで自動プロンプト最適化を動かしてみた結果を紹介したいと思います!
自動プロンプト最適化について
本記事では、自動プロンプト最適化をあるタスクにおけるスコアを最大化するためのプロンプトの導出を、手動でのプロンプトエンジニアリング(ほぼ)無しに行う技術とします。
「ほぼ」と書いてあるのは、後述の「プロンプトを最適化する処理を行うためのプロンプト」(メタプロンプト)が必要になるためです。
プロンプトエンジニアリングの難しさや問題点、ベストプラクティスについては様々なブログ、論文で論じられているためここでは詳細を省略しますが、個人的にLLMとプロンプトを使って処理を記述する際の問題点として特に感じるのは以下のものです。
-
LLMのアップデートによる既存プロンプトの陳腐化
- OpenAIのGPTシリーズ一択であった昨年までの状況と異なり、今年はClaude、Gemini、Llamaといったモデルの選択肢は大きく広がりました。
- 例えば、コストパフォーマンスなどの理由で、利用中のモデルを差し替えたい場合があります。この場合、まずはプロンプトは変更せずにモデルのみを差し替えたいケースが多いです(LangChainやLiteLLMといった、モデルの差分を吸収できるライブラリのおかげで、簡単に変更できることが多いです)
- しかし、モデルごとに得意とするフォーマット、指示の与え方が異なるため、そのままのプロンプトでは性能が劣化する場合があります
上記のような問題点を解決するための解決策の1つとして、自動プロンプト最適化は可能性があります。
試した手法
以下のOPRO (Yang et al., 2023)を簡略化したものを試しました。
OPROにした理由としては、以下が挙げられます。
- 論文上で、算数問題のデータセットであるGSM8Kにおいて有望な結果が得られていること
- 実装が、プロンプトの生成と評価を繰り返す比較的素直な手法であること
実装、検証の概要
今回は、以下のモデルとデータセットについて評価を行いました
- karakuri-ai/karakuri-lm-8x7b-chat-v0.1
- GSM8Kの多言語翻訳バージョンであるMGSMデータセットの日本語サブセット
-
train setが少ないから、test setのデータの半分(125問)を利用しています
-
データセットの1レコードには、以下のような問題文と答えなどが収められています(翻訳が正しくない部分も含んでいることがわかります)
-
question
問題:サーバールームには9台のコンピューターがありました。月曜日から木曜日まで毎日5台のコンピューターをインストールしました。今サーバールームには難題のコンピューターがありますか?
-
answer_number
29
-
評価指標は正解率です
-
今回の設定でOPROを行うには、LLMを利用する以下2点の実装が必要になります。
- LLM as optimizer(以降
optimizer
)- 最適化の過程で得られたプロンプトの履歴と「プロンプトを最適化する処理を行うためのプロンプト」(以降メタプロンプト)から、新しいプロンプトを出力するLLM
- 補足: OPROの論文ではLLMがoptimizerとして機能するという側面がより広く探索されており、自動プロンプト最適化以外にも線形回帰、巡回セールスマン問題への適用が行われています。実際に問題をある程度解けることが検証されており、興味深いです。
- objective function evaluator(以降
evaluator
)- optimizerから供給されたプロンプトをもとに実際にMGSMデータセットの問題を解くLLM
- 補足: 最適化を行いたいタスク設定が自動プロンプト最適化ではない場合、必ずしもLLMである必要はありません。巡回セールスマン問題の最適化では、巡回セールスマン問題の解の評価を決定的なアルゴリズムで行うことができます
今回は、上記2つの両方にkarakuri-lm-8x7b-chat-v0.1
を用いました。
実用上は、optimizerには最大限賢いLLM、evaluatorには運用したいLLMを設定することになると考えられます。
また、OPROの論文からは主に以下の点を変更しました。
- 題材となるデータセット
- 論文では、オリジナルのMGSMデータセットの翻訳前のものであるGSM8K等を利用しています
- メタプロンプト
- 元のプロンプトは英語であり、また簡素な指示であったため、プロンプトに関する一般的なプラクティスを書き足しています
- 1ステップあたりのプロンプト生成数
- 論文では、1ステップにつき8つのプロンプトを生成していますが、今回は1つだけ生成しています
- 自動プロンプト最適化のステップ数
- 論文では200ステップ実行していますが、今回は10ステップのみ実行しました
実際に利用したメタプロンプトの詳細などは末尾に記載しています。
結果
OPROのイテレーションを10回行い、以下のような正解率の推移を得ました(縦軸: 正解率)
初期プロンプトから14%程度正解率が上がっており、自動プロンプト最適化が機能していることが確認できました。
また、正解率が最大となったiteration=4のシステムプロンプトは以下の通りでした
あなたは算数の問題を解く大規模言語モデルです。問題は以下の通りです。(問題文を挿入)。あなたはこの問題を解くために、必要な情報を収集し、適切な計算を行い、答えを導き出すことができます。まず、問題文を読み上げ、その後、必要な情報がすべて与えられていることを確認します。そして、問題解決に必要な計算手順を説明します。最後に、解答を提示する指示を行います。これらの指示を組み合わせ、問題の種類や難易度に応じて調整することで、大規模言語モデルが問題を正確に解く助けになります。指示は具体的かつ明確にすることが重要です。
出力されたプロンプトがどのように使われるのかの理解不足が感じられ、私の目で見ると少し修正したくなるものにはなりました。ただし、step by stepで思考する方向性は存在するため、大筋では悪くないように見えます。
考察
今回自動プロンプト最適化を実装してみて感じた、メリットやデメリットは以下の通りです
- メリット
- 汎用的なプロンプトから、ある程度タスクの内容に沿った(かつ評価がついた)特化プロンプトを自動的に作成することができる
- デメリット、課題
- evaluatorの評価部分の実装コストや信頼性がタスクごとに異なること
- 今回は、ほぼ決定的にスコアをつけることができるMGSMデータセットを題材としたため、evaluator LLMの出力を評価する際に大きな問題は生じませんでした
- ただし、これが文章要約や翻訳といった、解を1つに定めるのが難しいタスクを利用する場合には、以下のような対策が必要になります
- LLMによる評価: 出力した文章にスコアをつけるLLMを利用する( LLM-as-a-Judge といったものを利用する
- 人手による評価(手間がかかりあまり現実的ではないですが)
- これらには、以下のような課題が発生する可能性が高く、別途対処する必要があるかもしれません
- 金銭的、時間的な追加コスト
- 評価の信頼性を担保するための検証が別途必要になる可能性がある
- 得られたプロンプトが、人の目から見てベストに見えるわけではないこと
- 結局修正したくなってしまう可能性があります
- evaluatorの評価部分の実装コストや信頼性がタスクごとに異なること
上記のようなメリデメを踏まえた上で、今回は以下のようなことをやり残しています。
- few-shot sampleといった、より良い結果が得られる可能性が高い手法と自動プロンプト最適化の組み合わせ
- optimizerのみをGPT-4o(またはOpenAI o1), Gemini-1.5-Proといった最大限賢いLLMに差し替えた場合に、どのようなプロンプトが得られるか
- 今回得られたプロンプトを初期値として、別のevaluator LLM(Gemini-1.5-Flashなど)用のプロンプトを得るためにOPROを実行すると、スコアがどのように変化するか
終わりに
今回は、KARAKURI LMを自動プロンプト最適化に使ってみるとどうなるか、というのを試してみました。結果として、今回試した手法にはまだまだ課題も多く残ったものの、自動プロンプト最適化が実際に機能することを確認できました。
実運用上、自動プロンプト最適化はモデルの差し替え時などにメリットが大きいと考えられます。そのため、今後も利用するモデルの進化、手法自体の進化の両面でウォッチしていきたい分野であると思いました。
最後に、今回の記事では、紹介した論文に加え、以下のテックブログを大いに参考にさせていただきました。感謝いたします。
- 自動プロンプト最適化をやってみた - Algomatic Tech Blog
- 日本語LLMベンチマークと自動プロンプトエンジニアリング - Preferred Networks Research & Development
実装詳細
-
optimizerが利用するメタプロンプト
- 他のタスクでも使いまわせるよう、可能な限り汎用的な指示を記載します(今回は問題の種類、評価指標のみ可変記述のみ可変なものとしました)
あなたは、「算数問題を解く大規模言語モデル」に与えるメタ指示テキスト(prompt)を改善する専門家です。 [入力] * 以下のデータがいくつか与えられます(正解率が低い順に並べます) * 大規模言語モデルが問題を解く際に利用したメタ指示テキスト * 大規模言語モデルの出力に対するスコア(正解率) [手順] * 1つの1つのメタ指示テキストに対して、以下の考察をしてください * スコアが高くなる原因となる指示 * スコアが低くなる原因となる指示 * スコアを最大化するには、スコアが最大のメタ指示テキストをどのように変更すればいいか * それらの考察を踏まえて、最後の行にスコア(正解率)を最大化する指示を作成してください [補足] * 品質の高いメタ指示テキストの一般的な原則は以下の通りです。必ずしもスコアの最大化につながるとは限りませんが、参考にしてください * 段階的に推論する * 重要な情報と関係のない情報を区別する * 実際の問題の解き方を例示する * 同じ意味でも、多様な指示フォーマットを試す * 複雑すぎる指示は、スコアを下げる可能性がある * 新しいメタ指示テキストは、入力されたメタ指示テキストの履歴のいずれかと一致しないことを厳守してください [出力フォーマット] * 改善後のメタ指示テキストをプレーンテキストで記載してください。 * そのままメタ指示テキストとして利用するため、考察やコメントといった余計な要素は不要です。
- 今回はこちらのメタプロンプトをシステムプロンプト、過去に出力したプロンプトと対応するMGSMのスコアを以下のユーザープロンプト部分に入力しています
score: 0.296, rank: 2 [system_prompt] がんばれ!!! ------------------------------- score: 0.35, rank: 1 [system_prompt] 以下の問題を解いてください ------------------------------- 以上です。改善後のメタ指示テキストを出力してください
-
evaluatorに入力するプロンプト
-
OPROの論文では、optimizerが出力した新しいプロンプトの挿入位置もいくつかの種類(問題文の前、問題文の後ろ、など)を検討していました。今回は簡略化してevaluator LLMのシステムプロンプト部分に挿入のみを行なっています
-
システムプロンプト: optimizerが出力したプロンプト
-
以下のような、MGSMデータセットのquestionを解くためのプロンプトが出力されることを想定しています
以下の問題を解いてください
-
今回は、以下のプロンプトを初期プロンプトとして処理を開始しています
がんばれ!!!
-
-
ユーザープロンプト: MGSMの問題文を入力して、問題を解かせています
問題:サーバールームには9台のコンピューターがありました。月曜日から木曜日まで毎日5台のコンピューターをインストールしました。今サーバールームには難題のコンピューターがありますか?
-
Discussion