📚

OpenAI・Anthropic・Googleのプロンプトエンジニアリングガイドをまとめてみた

2024/08/25に公開

こんにちは、ナウキャストでLLMエンジニアをしているRyotaroです。

プロンプトエンジニアリングのガイドはいくつかあって、有名なのはDAIR.AIによって編纂された『プロンプトエンジニアリングガイド』ですよね。でもOpenAI、Anthropic、Googleも実は公式で出していて、結構よかったのでこれらを抜粋してまとめてみたいと思います。

総合的なまとめ

結論、共通部分や独自のものをまとめていくと以下のようなポイントにまとまりました。

共通

明確な指示を書く

プロンプトにおいて明確で具体的な指示を提供することが不可欠です。明確な指示を書くことで、モデルは期待される結果を正確に理解し、応答の関連性や質が向上します。指示は、タスクの詳細や目的、求める結果を具体的に記載する必要があります。曖昧な表現や一般的な指示は避け、具体的な行動を指示することが重要です。

例:

  • 「以下の文章を要約してください。要約は3文以内でお願いします。」
  • 「次の文を日本語に翻訳してください。翻訳の際は、文のニュアンスを保つようにしてください。」

タスクを定義する

実行するタスクを明確に定義することは、モデルに正確な出力を促すための基本的なステップです。タスクを具体的に定義することで、モデルはユーザーが何を求めているのかを容易に理解でき、期待される出力を生成しやすくなります。タスクの目的や文脈を提供することで、モデルの理解を深めることができます。

例:

  • 「以下のデータセットを分析し、異常値を特定してください。異常値の定義は、標準偏差を基にした3σ法を用いてください。」
  • 「このビジネスプランの要点をまとめて、主要な強みと弱みをリストアップしてください。」

few-shotを入れる

プロンプトに具体的な例を含めることで、モデルの出力を大幅に向上させることができます。具体的な例を挙げることで、モデルが期待される出力を正確に理解し、生成する内容の精度や一貫性を高めることが可能です。また、例は指示の誤解を減らし、モデルのパフォーマンスを向上させる役割を果たします。

例:

以下のような回答を求めます:
- 例1: 成功した企業の特徴は?
- 例2: 起業におけるリスク管理の重要性について教えてください。
次の問題に対する解答例を示します:
- 例1: “地球温暖化の影響は?”
- 例2: “新しい技術の利点は?”

モデルに考えさせる

モデルに考える時間を与えることで、質の高い出力を引き出すことが非常に重要です。モデルに独自の解決策を導き出すよう指示し、思考プロセスを明示的に示すことで、より精度の高い結果を得ることができます。考えさせるプロンプトを用いることで、特に複雑な問題に対してより深い理解を促すことが可能です。いわゆるCoTの考え方です。

例:

  • 「問題を段階的に考えて、解決策を提示してください。まずは問題の要点を整理することから始めてください。」
  • 「この数学の問題を解くために、まず何をすべきか考えてみてください。解法のステップを示してください。」

複雑なタスクは分ける

複雑なタスクに取り組む際、1つのプロンプトですべてを処理しようとすると、LLMが時々ボールを落とすことがあります。CoTでも頑張ればできますが、精度が格段に落ちてしまいます。そういうときはタスクを分割し、一つ一つこなすように指示をするのが有効です。

ベンダー独自

OpenAI

  • 参照テキストを提供する
    • 参照テキストを使用してモデルに回答するよう指示する
  • 外部ツールを使用する
    • 埋め込みベースの検索やコード実行を使用
  • 変更を体系的にテストする
    • ゴールドスタンダードの回答を参照してモデル出力を評価する

Anthropic

  • プロンプトの構造化にXMLタグを使用する
    • プロンプトにコンテキスト、指示、例など複数の要素が含まれる場合にXMLタグを活用
  • システムプロンプトを使用してClaudeに役割を与える
    • systemパラメータを使用して役割を設定

Google

  • 長文コンテキストプロンプトのヒント
    • 長文データを上部に配置し、XMLタグを使用して文書の内容とメタデータを構造化する
  • プロンプトを連結する
    • 複数の連続したステップを含む複雑なタスクのためにプロンプトを順番に連結する

OpenAI

https://platform.openai.com/docs/guides/prompt-engineering

1. 明確な指示を書く

  • より関連性の高い回答を得るために、クエリに詳細を含めて
  • モデルにペルソナを採用するよう依頼する
  • 区切り文字を使用して、入力の異なる部分を明確に示す
  • タスクを完了するために必要な手順を指定します
  • 例を挙げる
  • 出力の希望の長さを指定します

2. 参照テキストを提供する

  • 参照テキストを使用してモデルに回答するよう指示する
  • モデルに参考文献からの引用で回答するよう指示する

3. 複雑なタスクをより単純なサブタスクに分割する

  • 意図分類を使用して、ユーザークエリに最も関連性の高い指示を特定します
  • 非常に長い会話を必要とする対話アプリケーションの場合、以前の対話を要約またはフィルタリングします
  • 長い文書を部分的に要約し、再帰的に完全な要約を構築する

4. モデルに「考える」時間を与える

  • 結論を急ぐ前に、モデルに独自の解決策を導き出すよう指示する
  • モデルの推論プロセスを隠すために、内なる独白や一連のクエリを使用する
  • 前回のパスで何か見逃したかどうかをモデルに尋ねる

5. 外部ツールを使用する

  • 埋め込みベースの検索を使用して効率的な知識検索を実装する
  • コード実行を使用して、より正確な計算を実行したり、外部APIを呼び出したりします。
  • モデルに特定の機能へのアクセス権を与える

6. 変更を体系的にテストする

  • ゴールドスタンダードの回答を参照してモデル出力を評価する

Anthropic

https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview

1. 明確で文脈に沿った具体的な方法

Claudeに文脈情報を与える:

より多くの文脈情報を持っていればタスクをより上手く遂行できるように、Claudeにも文脈情報を与えればパフォーマンスが上がります。

文脈情報の例:

  • タスクの結果が何に使われるのか

  • 出力結果が誰を対象としているのか

  • タスクがどのワークフローの一部で、そのワークフローのどこに位置しているのか

  • タスクの最終目標、あるいは成功したタスク完了とはどのようなものか

  • Claudeに何をしてほしいのか

  • 具体的に:

例えば、コードのみを出力してほしい場合は、そう伝えましょう。

手順を順を追って提供する:

番号付きリストや箇条書きを使って、Claudeにタスクを望み通りの方法で実行してもらいましょう。

2. 例を使用して Claude の動作を制御する (マルチショットプロンプティング)

例は、Claude に必要なものを正確に生成させるための秘密兵器のショートカットです。プロンプトにいくつかの適切な例を提供することで、Claude の出力の正確性、一貫性、品質を劇的に向上させることができます。 この手法は、few-shot プロンプティングまたは multishot プロンプティングとして知られており、構造化された出力や特定のフォーマットへの準拠を必要とするタスクに特に効果的です。

プロンプトをパワーアップ: Claude に必要なものを正確に示すために、3~5 つの多様で関連性の高い例を含めましょう。例が多いほど、特に複雑なタスクでのパフォーマンスが向上します。

例を使用する理由

  • 正確性: 例は指示の誤解釈を減らします。

  • 一貫性: 例は統一された構造とスタイルを強制します。

  • パフォーマンス: 適切に選択された例は、Claude の複雑なタスクを処理する能力を高めます。

    効果的な例の作成
    最大限の効果を得るために、例が以下の条件を満たしていることを確認してください:

  • 関連性: 実際のユースケースを反映している。

  • 多様性: エッジケースや潜在的な課題をカバーし、Claude が意図しないパターンを誤って拾わないように十分に変化がある。

  • 明確性: 例が <example> タグで囲まれている (複数の場合は <examples> タグ内にネストされている)。

3. Claudeに考えさせる(思考連鎖プロンプティング)でパフォーマンスを向上

研究、分析、問題解決などの複雑なタスクに直面した際、Claudeに考える余地を与えることで、そのパフォーマンスを劇的に向上させることができます。思考連鎖(CoT)プロンプティングとして知られるこの手法は、Claudeに問題を段階的に分解することを促し、より正確で微妙な出力につながります。

CoTを実装する前に

なぜClaudeに考えさせるのか?

  • 正確性: 問題を段階的に解決することで、特に数学、論理、分析、または一般的に複雑なタスクにおけるエラーを減らすことができます。
  • 一貫性: 構造化された思考は、より一貫性のある、よく組織化された応答につながります。
  • デバッグ: Claudeの思考プロセスを見ることで、プロンプトが不明確な場所を特定するのに役立ちます。

    なぜClaudeに考えさせないのか?
  • 出力の長さが増えると、レイテンシーに影響を与える可能性があります。
  • すべてのタスクが深い思考を必要とするわけではありません。パフォーマンスとレイテンシーの適切な
    バランスを確保するために、CoTを賢明に使用してください。
  • 複雑な数学、多段階の分析、複雑な文書の作成、多くの要因を考慮した意思決定など、人間が考える必要のあるタスクにCoTを使用してください。

    思考のためのプロンプトの方法
    以下の思考連鎖の手法は、最も複雑でないものから最も複雑なものへと順番に並んでいます。複雑でない方法はコンテキストウィンドウのスペースを少なくて済みますが、一般的にはそれほど強力ではありません。

CoTのヒント:常にClaudeに思考を出力させてください。思考プロセスを出力しないと、思考は起こりません!
基本的なプロンプト:プロンプトに「段階的に考えてください」を含めます。
どのように考えるかについての指針がない(特にタスクがアプリ、ユースケース、または組織に非常に特化している場合は理想的ではない)

例:寄付者へのメール作成(基本的なCoT)

ガイド付きプロンプト:Claudeが思考プロセスで従うべき具体的な手順を概説します。
回答と思考を分離して取り出しやすくするための構造化がない。

例:寄付者へのメール作成(ガイド付きCoT)

構造化プロンプト:<thinking>や<answer>などのXMLタグを使用して、推論と最終的な回答を分離します。

例:寄付者へのメール作成(構造化ガイド付きCoT)

4. プロンプトの構造化にXMLタグを使用する

プロンプトにコンテキスト、指示、例など複数の要素が含まれる場合、XMLタグは非常に役立ちます。XMLタグを使用することで、Claudeはプロンプトをより正確に解析し、高品質の出力を生成できます。

XMLのヒント: <instructions>、<example>、<formatting>などのタグを使用して、プロンプトの異なる部分を明確に区切ります。これにより、Claudeが指示を例やコンテキストと混同することを防げます。

XMLタグを使用する理由

  • 明確さ: プロンプトの異なる部分を明確に区切り、プロンプトが適切に構造化されていることを確認できます。
  • 正確性: プロンプトの一部をClaudeが誤って解釈することによるエラーを減らせます。
  • 柔軟性: プロンプトの特定の部分を簡単に見つけ、追加、削除、または変更できます。すべてを書き直す必要はありません。
  • 解析しやすさ: ClaudeにXMLタグを使用して出力させることで、後処理によって応答の特定の部分を簡単に抽出できます。​

5. システムプロンプトを使用してClaudeに役割を与える

Claudeを使用する際、systemパラメータを使用して役割を与えることで、パフォーマンスを大幅に向上させることができます。このテクニックは、役割プロンプティングとして知られており、Claudeでシステムプロンプトを使用する最も強力な方法です。

適切な役割は、Claudeを一般的なアシスタントから仮想ドメインエキスパートに変えることができます!

システムプロンプトのヒント: systemパラメータを使用してClaudeの役割を設定します。タスク固有の指示など、他のすべてをuserターンに入れてください。

役割プロンプティングを使用する理由

  • 精度の向上: 法的分析や財務モデリングなどの複雑なシナリオでは、役割プロンプティングによりClaudeのパフォーマンスが大幅に向上します。
  • トーンのカスタマイズ: CFOの簡潔さやコピーライターの才能など、役割プロンプティングによりClaudeのコミュニケーションスタイルを調整できます。
  • フォーカスの改善: 役割のコンテキストを設定することで、Claudeはタスクの特定の要件の範囲内にとどまります。

    Claudeに役割を与える方法
    Messages APIのsystemパラメータを使用して、Claudeの役割を設定します:
import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-3-5-sonnet-20240620",
    max_tokens=2048,
    system="あなたはFortune 500企業のベテランデータサイエンティストです。", # <-- 役割プロンプト
    messages=[
        {"role": "user", "content": "このデータセットで異常を分析してください: <dataset>{{DATASET}}</dataset>"}
    ]
)

print(response.content)

6. Claudeの応答をプリフィルして、出力をより細かく制御する

Claudeを使用する際、Assistantメッセージをプリフィルすることで、応答を導くことができるユニークな機能があります。この強力なテクニックにより、Claudeのアクションを指示し、前置きをスキップし、JSONやXMLなどの特定のフォーマットを強制し、ロールプレイシナリオでキャラクターの一貫性を維持するのに役立ちます。

Claudeが期待通りに動作しない場合、数文のプリフィルで、Claudeのパフォーマンスを大幅に改善できることがあります。少しのプリフィルが大きな効果を発揮します!

Claudeの応答をプリフィルする方法
プリフィルするには、Assistantメッセージに希望する初期テキストを含めます(Claudeの応答は、Assistantメッセージが終了した時点から続きます):

import anthropic

client = anthropic.Anthropic()
response = client.messages.create(
    model="claude-3-5-sonnet-20240620",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "あなたの好きな色は何ですか?"},
        {"role": "assistant", "content": "AIアシスタントとして、私に好きな色はありません。しかし、あえて選ぶとすれば、緑でしょう。なぜなら、"}  # ここでプリフィル
    ]
)

7. 複雑なプロンプトをチェーンして、より強力なパフォーマンスを実現する

複雑なタスクに取り組む際、1つのプロンプトですべてを処理しようとすると、Claudeが時々ボールを落とすことがあります。思考の連鎖(CoT)プロンプティングは素晴らしいですが、タスクに深い思考を必要とする明確な複数のステップがある場合はどうでしょうか?

プロンプトチェーンの登場です:複雑なタスクを、管理しやすい小さなサブタスクに分割します。

プロンプトをチェーンする理由

  • 正確性:各サブタスクにClaudeの注意が集中し、エラーが減少します。
  • 明確性:シンプルなサブタスクは、明確な指示とアウトプットを意味します。
  • トレーサビリティ:プロンプトチェーンの問題を簡単に特定して修正できます。

    プロンプトをチェーンするタイミング
    研究の統合、ドキュメント分析、反復的なコンテンツ作成など、複数のステップを含むタスクにプロンプトチェーンを使用します。タスクに複数の変換、引用、または指示が含まれている場合、チェーンを使用すると、Claudeがステップを落としたり、誤って処理したりするのを防ぐことができます。

覚えておいてください: チェーンの各リンクにClaudeの注意が集中します!

デバッグのヒント:Claudeがステップを見逃したり、パフォーマンスが悪かったりする場合は、そのステップを独自のプロンプトで分離します。これにより、タスク全体をやり直すことなく、問題のあるステップを微調整できます。

プロンプトをチェーンする方法
サブタスクを特定する:タスクを明確で順次的なステップに分割します。
明確な引き渡しのためにXMLで構造化する:XMLタグを使用して、プロンプト間でアウトプットを渡します。
単一タスクの目標を持つ:各サブタスクには、明確な単一の目的が必要です。
反復する:Claudeのパフォーマンスに基づいてサブタスクを改良します。

チェーンワークフローの例:

  • 多段階分析:以下の法務と業務の例を参照してください。
  • コンテンツ作成パイプライン:リサーチ → アウトライン → ドラフト → 編集 → フォーマット。
  • データ処理:抽出 → 変換 → 分析 → 可視化。
  • 意思決定:情報収集 → オプションのリスト化 → 各オプションの分析 → 推奨。
  • 検証ループ:コンテンツ生成 → レビュー → 改良 → 再レビュー。
  • 最適化のヒント:独立したサブタスク(複数のドキュメントの分析など)がある場合は、別々のプロンプトを作成し、スピードアップのために並行して実行します。

    上級者向け:自己修正チェーン
    Claudeに自身の作業をレビューさせるためにプロンプトをチェーンすることができます!これにより、特に重要なタスクでエラーを発見し、アウトプットを改良できます。

8. 長文コンテキストプロンプトのヒント

Claudeの拡張コンテキストウィンドウ(Claude 3モデルで200Kトークン)により、複雑でデータ豊富なタスクの処理が可能になります。このガイドは、この力を効果的に活用するのに役立ちます。

長文コンテキストプロンプトの重要なヒント
長文データを上部に配置する: 長い文書や入力(~20K+トークン)をプロンプトの上部、クエリ、指示、例の上に配置します。これにより、すべてのモデルにわたってClaudeのパフォーマンスが大幅に向上する可能性があります。

テストでは、特に複雑な複数文書の入力の場合、末尾にクエリを置くことで応答品質が最大30%向上する可能性があります。
XMLタグを使用して文書の内容とメタデータを構造化する: 複数の文書を使用する場合、各文書を<document>タグで囲み、<document_content>と<source>(および他のメタデータ)のサブタグを使用して明確にします。

複数文書構造の例

引用を基に回答を根拠付ける: 長文書のタスクでは、Claudeにタスクを実行する前に文書の関連部分を引用するよう依頼します。これにより、Claudeは文書の残りの内容の「ノイズ」を切り抜けることができます。

Google

https://ai.google.dev/gemini-api/docs/prompting-strategies?hl=ja

明確で具体的な指示にする

実行するタスクを定義する

モデルに実行させたいタスクを詳しく記述します。タスクには段階的な手順のリストのような単純なものもあれば、ユーザー エクスペリエンスや考え方を示すような複雑なものもあります。#### 制約を指定する

制約を指定する

プロンプトの読み取りやレスポンスの生成に関する制約を指定します。行うべきことと、行うべきでないことをモデルに指示できます。前の例では、要約が元のテキストよりも短くなっていますが、さらに短い要約がほしい場合もあります。その場合、必要な要約の長さについてプロンプトで制約を指定できます。

レスポンスの形式を定義する

指示の中でレスポンスの形式を指定することもできます。たとえば、表、箇条書き、エレベーター ピッチ、キーワード、文、段落の形式でレスポンスを求めることができます。

few-shotの例を含める

プロンプトには、モデルに期待する動作の例を含めることができます。モデルは、パターンと関係を例から識別し、レスポンスを生成する際にそれらを適用します。いくつかの例を含むプロンプトは少数ショット プロンプトと呼ばれ、例のないプロンプトはゼロショット プロンプトと呼ばれます。少数ショット プロンプトは、モデルのレスポンスの形式、フレーズ、範囲、一般的なパターンを規制するためによく使用されています。具体的で多様な例を使用して、モデルが焦点を絞り込み、より正確な結果を生成できるようにします。

プロンプトには、常に少数ショットの例を含めることをおすすめします。少数ショットの例は、モデルに対して指示の適用方法を示すものであり、このようなショットのないプロンプトは効果的でない可能性があります。タスクを説明するのに十分な例が含まれていれば、プロンプトから指示を削除することも可能です。

例を使用してアンチパターンではなくパターンを示す

回避すべきアンチパターンを例示するよりも、従うべきパターンをモデルに例示するほうが効果的です。

⛔ネガティブ パターン:

Don't end haikus with a question:
Haiku are fun
A short and simple poem
Don't you enjoy them?

✅ポジティブ パターン:

Always end haikus with an assertion:
Haiku are fun
A short and simple poem
A joy to write

サンプル全体で一貫した形式を使用する

レスポンスが望ましくない形式で返されないように、少数ショットの例の構造と形式を同じにする必要があります。プロンプトに少数ショットの例を追加する主な目的の 1 つは、モデルにレスポンスの形式を示すことです。そのため、すべてのサンプルで形式を統一することが重要になります。特に、XML タグ、空白、改行、サンプルの分割子には注意してください。

まとめ

  • モデルが応答方法を効率的に学習できるように、プロンプトにはプロンプト / レスポンスの例を含めてください。
  • 回避するパターンの例ではなく、従うべきパターンの例をモデルに提示します。
  • 表示するプロンプトの数を調べてみてください。モデルによっては、例が少なすぎると、モデルの動作の変更は期待できません。サンプルが多すぎると、モデルが過学習する原因となります。
  • サンプル全体で一貫した形式を使用してください。

コンテキスト情報を追加する

モデルに必要な情報がすべて与えられていると仮定するのではなく、モデルが問題を解決するために必要な情報をプロンプトの手順と情報に含めることができます。このコンテキスト情報により、モデルは、要求された内容の制約と詳細を理解できます。

接頭辞を追加する

接頭辞は、プロンプト コンテンツに追加する単語またはフレーズであり、接頭辞を付加する場所に応じてさまざまな目的で使用できます。

  • 入力接頭辞: モデルへの入力の意味的に重要な部分である入力シグナルに接頭辞を追加します。たとえば、接頭辞「English:」と「French:」は 2 つの異なる言語を識別可能にします。
  • 出力接頭辞: 出力はモデルによって生成されますが、プロンプトで出力に接頭辞を追加できます。出力接頭辞は、レスポンスとして期待される内容に関する情報をモデルに与えます。たとえば、出力接頭辞「JSON:」は、出力を JSON 形式にする必要があることをモデルに伝えます。
  • 接頭辞の例: 少数ショット プロンプトでは、例に接頭辞を追加すると、モデルが出力の生成時に使用できるラベルが提供されます。これにより、出力内容の解析が容易になります。

モデルに部分的な入力を任せる

生成言語モデルは、高度な予測入力ツールのように機能します。部分的なコンテンツを提供すると、モデルは残りのコンテンツ、またはコンテンツの継続として認識したコンテンツをレスポンスとして提供できます。その場合、例やコンテキストを含めると、モデルはそれらの例やコンテキストを参考にできます。

プロンプトを単純なコンポーネントに分割する

指示を分割する

1 つのプロンプトに複数の指示を記述するのではなく、指示ごとに 1 つのプロンプトを作成します。ユーザーの入力に基づいて、処理するプロンプトを選択できます。

プロンプトを連結する

複数の連続したステップを含む複雑なタスクの場合は、各ステップをプロンプトにして、プロンプトを順番に連結します。このプロンプトのチェーンでは、シーケンス内の 1 つのプロンプトの出力が次のプロンプトの入力になります。シーケンスの最後のプロンプトの出力が最終出力になります。

レスポンスを集計する

集計とは、データのさまざまな部分に対して異なる並列タスクを実行し、結果を集計して最終出力を生成
することです。たとえば、データの最初の部分に対して 1 つのオペレーションを実行し、残りのデータに対して別のオペレーションを実行して、結果を集計するようにモデルに指示できます。

非推奨事項

  • 事実に基づく情報の生成についてモデルに頼ることは回避してください。
  • 数学や論理の問題では慎重に使用してください。

We are Hiring!

この件についてもっと詳しく知りたい、議論したい、はたまたナウキャストという会社に興味を持ったという方は、カジュアル面談フォームから連絡ください。その際に「プロンプトエンジニアリングガイドをまとめてみたを見た」と書いていただければ幸いです!

https://herp.careers/v1/finatexthd/vZWzSlI_B-qk

https://herp.careers/v1/finatexthd/KhEf95X_TKvD

Discussion