はじめまして!データサイエンティストの山内(@jof_5)です。
本記事では、日々、プロンプト開発されている皆様に向けて、プロンプトを効率的に開発する手法の一つである「自動プロンプト最適化」について記載いたします。
1. プロンプトエンジニアリングの必要性と課題
プロンプトエンジニアリングの詳細な定義については別の記事に譲りますが、本記事では「LLMに対して最適な入力(プロンプト)を与え、目的に合った出力を得るための技術」をプロンプトエンジニアリングと定義します。
LLM の汎用性を活かし、様々なドメインや問題に対して最適な解決策を得るために、プロンプトエンジニアリングは必要不可欠です。一方で、プロンプトエンジニアリングの必要性は広く認識されていますが、その実践は非常に難しいです。なぜプロンプトエンジニアリングが難しいのでしょうか。筆者はその理由を以下の二点にまとめます:
LLM の不透明性
自然言語における探索空間の広さ
2. 自動プロンプト最適化について
2-0. 最適なプロンプトとは何か?☕
最適なプロンプトに関しては明確な定義がないので回答が難しいですが、プロンプトデザインにおける一般的なベストプラクティスとしては以下の項目が挙げられるかもしれません。
- 特定性を上げる。特定性とは、問題となっている名詞が具体的に指している対象を話し手が頭に思い浮かべているかどうかを表す概念 (Lonin+’14; 石田+’02)。
- 次の単語を予測する言語モデルにおいては文全体の累積サプライザルを小さくするような語順 (Kuribayashi+’20)。
- マークアップ・マークダウンの使用や 深津式プロンプト の使用による、レイアウト役割・談話構造の付与。
- リーディングワードの使用、出力形式の制限、疑似コードによる思考過程の制限など一意な出力を導出するための制約。
一方、本記事での最適化はタスクの実行性能として正解率を最大化させることを対象といたします。
2-1. 自動プロンプトの概要
効率的にプロンプトを開発する一つの打ち手として、過去の探索結果を利用し、新たなプロンプトを生成させる「自動プロンプト最適化」という手法があります。
prompt optimizationで調べると、複数件ヒットします。
- https://github.com/jxzhangjhu/Awesome-LLM-Prompt-Optimization
- Automatic Prompt Engineer (Zhou+’23, ICLR)
今回は、筆者にて自動プロンプト最適化を実装しました。探索履歴のプロンプトとスコアから、LLMに新たなプロンプトを生成させる論文 (Yang+’24, ICLR)を参考にしました。
2-2. 自動プロンプト最適化のアーキテクチャ
自動プロンプト最適化するにあたって、三つのコンポーネントを実装しました。
①Task Executor: LLMによるタスクの実行
Task Executorは、対象タスクを実行するLLMを表すコンポーネントを指します。入力されたプロンプトに基づいて、出力を生成します。
今回は、日本語の常識推論タスクである JCommonsenseQA を、GPT-3.5 Turbo と Haiku にとかせてみました。上記のように、出力結果は質問に対する回答になります。
②Output Evaluator: 出力の評価
Output Evaluatorは、Task Executor が生成した出力を評価し、品質を定量的にスコアするコンポーネントのことです。
Output Evaluatorを実装する上で、考慮すべきことは、①評価指標、②評価手段の2点です。①評価指標とは、精度を数値化したものです。今回は、LLM が生成した回答と正解ラベルから、プログラムで過去の正解率(Accuracy)を算出します。②評価手段には LLM による評価、プログラムによる評価、人による評価の3種類あって、今回はプログラムによって評価しました。
③ Prompt Improver: 最適なプロンプトの生成
Prompt Improver は、Task Executor にインプットされたプロンプトと、Output Evaluator で評価したスコアに基づいて、より良いプロンプトを生成するコンポーネントのことです。
今回は、過去プロンプトと評価を GPT-4o に与え、過去の評価より高い正解率を記録するプロンプトを生成させました。
ご紹介した3つのコンポーネントを用い、初期プロンプトである「この問題を解いて」より、高い正解率を記録できる最適化プロンプトを生成します。
3. 実験結果と考察
3-1. 自動プロンプト最適化の有効性の検証
下記は、初期プロンプトと最適化プロンプトをLLMに入れた精度比較結果です。
上記から分かるように、初期プロンプトを使用した場合と比べ、最適化されたプロンプトを用いることでLLMの正解率が向上したことから、自動プロンプト最適化の有効性が示唆されます。
また、最適化プロンプトをいれたHaikuは、初期プロンプトを使用したOpusとほぼ同等の精度を達成しました。この結果は、プロンプトを工夫することで、性能が劣るLLMであっても、最高性能のLLMと同等のパフォーマンスを発揮できることを意味しています。このことは、コストが常に制約となるLLMを活用したプロダクト開発において、非常に朗報と言えるでしょう。
3-2. 最適化プロンプトの生成過程
前提として最適化プロンプトをどのように生成したか、最適化プロンプトの生成過程についてご説明いたします。
まず、最適化プロンプトを生成するにあたって、データセットを8:2で訓練データとテストデータに分割しました。そして、訓練データだけをつかって、タスク実行、評価、改善プロンプト生成を繰り返します。繰り返しが10回に達した場合、実行を終了します。そして、繰り返しが終了した時点で、最も高い正解率を記録したプロンプトを最適化プロンプトとしました。
下記は、最適化プロンプトに至るまでのstep数と正解率の推移です。
Haiku は2回目、GPT-3.5-Turbo は4回目で、最適化プロンプトを生成しました。極端に正解率が低下しているstep は、生成されたプロンプト内で出力形式を記載されたため、Output Evaluator で定義したパーサーで、LLMの回答を取得できなかったからです。(今回は、回答をパースできなかった場合は不正解としています。)
3-3. 最適化されたプロンプトの特徴
初期プロンプトと実際に生成された最適化プロンプトは下記になります。
初期プロンプト
この問題をといて
GPT-3.5 Turbo 用最適化プロンプト
以下の選択肢問題に対して、正しい答えを選んでください。問題文と選択肢をよく読み、最も適切な答えを選んでください。選択肢の中から正解を選ぶ際には、以下の戦略やテクニックを活用してください。 1. **文脈を理解する**: 問題文の意味を正確に理解し、選択肢がどのように関連しているかを考えます。 2. **キーワードを特定する**: 問題文の中の重要なキーワードを見つけ、それに基づいて選択肢を評価します。 3. **消去法を使う**: 明らかに間違っている選択肢を排除し、残った選択肢から最も適切なものを選びます。 4. **一般的な知識を活用する**: 問題文に関連する一般的な知識や常識を活用して答えを導き出します。 5. **選択肢の比較**: 選択肢同士を比較し、最も適切なものを選びます。 6. **文法と構造**: 文法的に正しい選択肢を選びます。 7. **直感を信じる**: 直感的に正しいと思う選択肢を選びます。 以下の形式で回答してください。 ```json { "question": "{問題文}", "choices": [ "{選択肢0}", "{選択肢1}", "{選択肢2}", "{選択肢3}", "{選択肢4}" ], "answer": "{正しい答えの番号}" } ``` 例: ```json { "question": "主に子ども向けのもので、イラストのついた物語が書かれているものはどれ?", "choices": [ "世界", "写真集", "絵本", "論文", "図鑑" ], "answer": "2" } ```
Haiku 用最適化プロンプト
### 選択肢問題の正解率を最高にするためのメタプロンプト 以下の手順に従って、選択肢問題に対する最適な回答を生成してください。 1. **問題文を理解する**: 問題文をよく読み、何を問われているかを正確に理解します。 2. **選択肢を評価する**: 各選択肢を慎重に評価し、問題文に最も適した答えを選びます。 3. **文脈を考慮する**: 問題文の文脈や一般的な知識を考慮して、最も適切な選択肢を選びます。 4. **消去法を使用する**: 明らかに不適切な選択肢を排除し、残った選択肢から最も適切なものを選びます。 5. **最終確認**: 選んだ答えが問題文に対して最も適切であることを再確認します。 以下の形式で回答を生成してください。 ```yaml 問題文: "<問題文>" 選択肢: - "<選択肢0>" - "<選択肢1>" - "<選択肢2>" - "<選択肢3>" - "<選択肢4>" 正しい答え: <正しい選択肢の番号> ``` #### 例 ```yaml 問題文: "主に子ども向けのもので、イラストのついた物語が書かれているものはどれ?" 選択肢: - "世界" - "写真集" - "絵本" - "論文" - "図鑑" 正しい答え: 2 ```
初期プロンプトと最適化プロンプトを比較すると、問題を解く際のテクニックが提示されている、markdown 記法を用いたプロンプトの構造化、問題例を用いたshotの提示など、一般的に良いとされているプロンプトエンジニアリングのテクニックが最適化プロンプトに用いられています。
OpenAI - Best practices for prompt engineering with the OpenAI API
Anthropic - Migrating prompts from OpenAI/ChatGPT to legacy Claude models
一方で、Haiku用の最適化プロンプトとGPT-3.5 Turbo用の最適化プロンプトを比較すると、「プロンプトに記載されているテクニックの数」や「記法の種類」が異なることが確認できます。これは、LLMごとに最適なプロンプトが異なる可能性を示唆しています。人がプロンプトエンジニアリングする際にも、LLMごとにプロンプトエンジニアリングすべきかもしれません。
3-4. プロンプト生成用LLM(Prompt Improver)のプロンプトの重要性
下記は、Prompt Improver に使用したプロンプトの一部です。
# 指示 - あなたは、選択肢問題を答えるGPT-3.5のプロンプトを生成するエキスパートです。 - 選択肢問題の正解率を最高にするメタプロンプトを生成してください。 - 過去プロンプトのスコアより高いスコアを記録するメタプロンプトを生成して下さい。 - メタプロンプトには、選択肢問題の正解率を最高にするメタプロンプトを生成するために以下の観点を参考にしてください。 - 戦略やテクニックをメタプロンプトに追記する - markdown, XML, toml, YAML, INIなどの異なる記法を用いてプロンプトを再構築する - 指示プロンプトの順番を変更する - 回答は以下のjson形式で生成してください。{'improved_instruction':'新しいメタプロンプト'} "
上記を作成する過程で、筆者が感じたのは、当たり前かもしれないですが、Prompt Improver のプロンプト設計が重要ということです。(改善して、ぐらいの雑プロンプトでは、新しいプロンプトがうまく生成されませんでした。)
今回は、①テクニック、②記法、③指示プロンプトのように、改善プロンプトを生成する際の変更箇所を明示したことで、バラエティーに富む改善プロンプトが生成されました。
一方で、テクニックなどを追記するだけでなく、生成したプロンプトの不要部分を削除する指示を与えても良かったかもしれません。なぜなら、最適化中に複雑なプロンプトが低いスコアを記録したときに、Prompt Improver が、シンプルなプロンプトでなく複雑なプロンプトを生成することで、スコアの改善を試みたからです。
4. おわりに
本記事では、効率的にプロンプト開発する手段である「自動プロンプト最適化」に関して、自動プロンプト最適化の概要から実験結果と考察について記載しました。皆様のプロンプト開発の参考になれば幸いです。
また本記事では特定のタスク実行におけるプロンプト品質の改善という点に焦点を当てましたが、他にも LLM エージェントにおける(タスク集合としての)ワークフロー全体に対する改善も展望として期待されます。
例えば AutoAgents (Chen+’24, IJCAI) のように、タスクの内容に基づいて複数の専門エージェントを動的に生成するような場面では、エージェントの役割やペルソナを指示するための profile の定義が必須であり、自動プロンプト最適化を導入することでエージェントシステムにおけるワークフローの改善につながるかもしれません。
弊社の紹介
Algomatic では LLM を活用したプロダクト開発等を行っています。 LLM を活用したプロダクト開発に興味がある方は、下記リンクからカジュアル面談の応募ができるのでぜひお話ししましょう!