🤖

日本語で解説!Best practices for prompt engineering with OpenAI API

2023/04/01に公開

ChatGPTのプロンプトエンジニアリングのベストプラクティス

毎日使っているChatGPT。もっと自在に扱いたいと思いませんか?

OpenAIのJessica Shiehさんが提供するプロンプトエンジニアリングのベストプラクティス「Best practices for prompt engineering with OpenAI API」を、今回は日本語で分かりやすく解説します。

私自身もこれまでプロンプトに関して試行錯誤してきましたが、このベストプラクティスを学ぶことで、自分の知らない部分がまだまだあることに気付きました。これを機に、今後のChatGPT利用でさらに効果的なプロンプト作成ができるようになることを目指します。

https://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-openai-api

1. 最新のモデルを使う

1.Use the latest model
For best results, we generally recommend using the latest, most capable models. As of November 2022, the best options are the “text-davinci-003” model for text generation, and the “code-davinci-002” model for code generation.

特に解説することがないので割愛します。

2. プロンプトの最初に指示を書き、### や """ を使って指示とコンテキストを区切る

2.Put instructions at the beginning of the prompt and use ### or """ to separate the instruction and context

❌ 効果が低いプロンプト例

プロンプト
以下のテキストを要点を箇条書きにまとめてください。

{任意のテキストを入力する}

✅ より効果的なプロンプト例

ダブルクオーテーションを使ったもの

プロンプト
以下のテキストを要点を箇条書きにまとめてください。

テキスト: """
{任意のテキストを入力する}
"""

ハッシュを使ったもの

公式には###を使った例はないですが、###を使う場合は以下のようになると思います。
Markdownに慣れている人ならこちらのほうが書きやすいと思います。

プロンプト
以下のテキストを要点を箇条書きにまとめてください。

### テキスト
{任意のテキストを入力する}

ダブルクオーテーションとハッシュを組み合わせたもの

Markdownでおなじみの###の他に、"""も使うことも推奨されていたのは、個人的に嬉しい発見でした。
これにより、テキスト内にMarkdownを使用することができます。

なお公式には###"""を組み合わせたものはないです。

プロンプト
以下のテキストを要点を箇条書きにまとめてください。

テキスト: """
# {H1見出しを入力する}
{任意のテキストを入力する}
# {H1見出しを入力する}
{任意のテキストを入力する}
# {H1見出しを入力する}
## {H2見出しを入力する}
{任意のテキストを入力する}
## {H2見出しを入力する}
{任意のテキストを入力する}
"""

3. 望ましいコンテキスト、成果、長さ、形式、スタイルなどについて、具体的かつ説明的で、できるだけ詳細に説明すること

3.Be specific, descriptive and as detailed as possible about the desired context, outcome, length, format, style, etc

❌ 効果が低いプロンプト例

プロンプト
OpenAIについての詩を書いてください。

✅ より効果的なプロンプト例

プロンプト
OpenAIについての短くて感動的な詩を書いてください。
最近のDALL-E製品発表(DALL-Eはテキストから画像を生成する機械学習モデル)に焦点を当て、
{有名な詩人}のスタイルで書いてください。

{有名な詩人}のところに任意の詩人名を入力する。

4. 欲しい出力形式を明確にする

4.Articulate the desired output format through examples (example 1, example 2).

example 1 カンマで区切られたリストがほしい

example 2 トピックに対するポイントの箇条書きがほしい

❌ 効果が低いプロンプト例

プロンプト
以下のテキストから言及されているエンティティを抽出してください。
次の4つのエンティティタイプを抽出してください
:企業名、人名、特定のトピック、テーマ。

テキスト: """
{任意のテキストを入力する}
"""

✅ より効果的なプロンプト例

カンマで区切られたリストがほしい

プロンプト
以下のテキストから重要なエンティティを抽出してください。
まず、すべての企業名を抽出し、次にすべての人名を抽出し、
次にコンテンツに適した特定のトピックを抽出し、
最後に一般的な包括的なテーマを抽出してください。

希望する形式:
企業名: <カンマで区切られた企業名のリスト>
人名: -||-
特定のトピック: -||-
一般的なテーマ: -||-

テキスト: """
{任意のテキストを入力する}
"""

一応、日本語で <カンマで区切られた企業名のリスト> と書いています。英語で <comma_separated_list_of_company_names> と書かなくても成功するようです。

トピックに対するポイントの箇条書きがほしい

プロンプト
以下のテキストの主なポイントを要約してください。
使用するフォーマット:
Topic 1: <topic_name_1>
- <point_1>
..
Topic 2: <topic_name_2>
- <point_1>
..
Topic 10: ..

テキスト: """
{任意のテキストを入力する}
"""

ちなみに example 2 トピックに対するポイントの箇条書きがほしい
では以下のような出力が得られます。

example 2 トピックに対するポイントの箇条書きがほしい の出力
Topic 1: The war in Ukraine
- The war is taking a human toll with lives lost, families displaced, and communities destroyed
- The Biden administration is committed to holding Russia accountable
- The war has violated international law and is a challenge to the international order

Topic 2: The global economy
- The war is having negative impacts on the global economy, including higher commodity prices and inflation
- The IMF and World Bank will be focused on helping developing countries weather the impacts of the war

Topic 3: China
- China has a special relationship with Russia and it is hoped that China will help to end the war

Topic 4: Multilateralism
- There is a need to modernize the multilateral approach to trade and to implement the global tax deal
- The IMF needs to be better equipped to deal with global crises and there is a need to mobilize capital in support of developing countries

Topic 5: Climate change
- The global transition to a cleaner energy future needs to be expedited

Topic 6: Global health
- Work needs to be completed on strengthening the global health architecture

-||- ってなに? → ダミー文字列

「-||-」は特定の情報がない場合に、その位置に入れるべきデータを示すために使用されます。
BingChatにも聞いてみたのですが、「-||-」という表現は、英語圏で一般的に使われている表現らしく。この表現は、何かを伏せたり、何かを言いたくないときに使われることがあるようです。
間違っていたらすみません。

試しに、example 1 のテキストをかなり削ってから出力(テキスト量を削減することで、抽出されるエンティティが少なくなり、結果的に人物など何も抽出されないケースを意図的に作る)したところ以下のようになりました。

example 1 プロンプト テキストをかなり削った
Extract the important entities mentioned in the article below. First extract all company names, then extract all people names, then extract specific topics which fit the content and finally extract general overarching themes
Desired format:
Company names: <comma_separated_list_of_company_names>
People names: -||-
Specific topics: -||-
General themes: -||-

Text: """Powering Next Generation
Applications with OpenAI Codex
Codex is now powering 70 different applications across a variety of use cases through the OpenAI API.

May 24, 2022
4 minute read
OpenAI Codex, a natural language-to-code system based on GPT-3, helps turn simple English instructions into over a dozen popular coding languages. Codex was released last August through our API and is the principal building block of GitHub Copilot.

Our motivation behind Codex is to supplement developers’ work and increase productivity. Codex helps computers to better understand people’s intent, which enables everyone to do more with computers. This is an integral part of our mission to build general-purpose AI that benefits all of humanity.

"""
example 1 出力されたもの
Company names: OpenAI, GitHub
People names: -||-
Specific topics: OpenAI Codex, GPT-3, natural language-to-code
General themes: productivity, general-purpose AI

5. ゼロショットで始めて、次にフューショット、どちらもうまくいかなければ、ファインチューニングを行う

5.Start with zero-shot, then few-shot (example), neither of them worked, then fine-tune

zero-shot? few-shot?? fine-tune??? どうやら機械学習モデルの学習や適用方法に関する用語のようです。
これは具体例で理解したほうが早いと思います。ざっくり以下のような理解で具体例中心に解説します。

ケースとしては、「DeepLは、ウェブ開発者がウェブサイトやモバイルアプリケーションに翻訳機能を迅速かつ正確に統合できるAPIを提供しています。このDeepL APIは、最先端の機械翻訳技術を利用して、高品質なテキスト翻訳を実現し、多様なタスクを効率的に解決することができます。」という文章からキーワードを抽出します。

✅ ゼロショット (Zero-shot)

ゼロショットのアプローチでは、ChatGPTに具体的な例を与えずに、タスク(ここではキーワード抽出)を実行するよう指示します。この例では、テキスト({任意のテキストを入力する})からキーワードを抽出するよう依頼しています。ChatGPTは、事前学習済みの知識だけでタスクを実行しようとします。

プロンプト
以下のテキストからキーワードを抽出してください。

テキスト: {任意のテキストを入力する}
キーワード:

✅ フューショット (Few-shot)

フューショットのアプローチでは、ChatGPTにタスクの具体的な例を提供し、それらを参照してタスクを実行するよう指示します。この例では、2つのテキスト(テキスト1とテキスト2)と、それらに対応するキーワードが提供されています。

フューショットを行うと、ChatGPTが新しいテキスト(テキスト3: {任意のテキストを入力する})からキーワードを抽出するタスクをより正確に実行できるようになります。

プロンプト
以下の対応するテキストからキーワードを抽出してください。

テキスト1: Stripeは、ウェブ開発者がウェブサイトやモバイルアプリケーションに決済処理を統合できるようにするAPIを提供しています。
キーワード1: Stripe, 決済処理, API, ウェブ開発者, ウェブサイト, モバイルアプリケーション

テキスト2: OpenAIは、テキストの理解と生成が非常に得意な最先端の言語モデルを学習させました。弊社のAPIは、これらのモデルにアクセスし、テキスト処理を含むほぼすべてのタスクを解決するために使用できます。
キーワード2: OpenAI, 言語モデル, 言語処理, API, テキスト処理

テキスト3:  {任意のテキストを入力する}
キーワード3:


✅ ファインチューニング (Fine-tune)

ゼロショットでもフューショットでもダメならファインチューニングをすると良いそうです。
微調整を行うのがファインチューニングらしいですが、よくわからなかったので割愛します。

6. あいまいで不正確な説明を減らす

6.Reduce “fluffy” and imprecise descriptions

ふわっとしたあいまいな説明はできる限りやめましょう。

❌ 効果が低いプロンプト例

プロンプト
この製品の説明文は、かなり短く、数文程度で、それ以上は必要ありません。

✅ より効果的なプロンプト例

プロンプト
この製品の説明文は、3〜5文の段落で説明してください。

7. ChatGPTにやってほしくないこと伝えるだけでなく、代わりに何をすべきかを伝える

7.Instead of just saying what not to do, say what to do instead

ネガティブプロンプト(やってほしくない禁止事項)を乱発していました。もしもネガティブプロンプトに対して対処法が決まっているならそれも記載したほうが良さそうです。

❌ 効果が低いプロンプト例

プロンプト
以下は、サポートセンターとお客様の間の会話です。
ユーザー名やパスワードを尋ねないでください。繰り返さないでください。

お客様: アカウントにログインできません。
サポートセンター:

✅ より効果的なプロンプト例

プロンプト
以下は、サポートセンターとお客様の間の会話です。
サポートセンターは、問題を診断し、解決策を提案するよう試みますが、
個人情報に関連する質問を避けます。ユーザー名やパスワードなどの
個人情報を尋ねる代わりに、ユーザーをヘルプ記事 
www.samplewebsite.com/help/faq に誘導してください。

お客様: アカウントにログインできません。
エージェント:

8. コード生成に特化 - モデルを特定のパターンに誘導するために「リーディングワード(先行する単語)」を使用する

8.Code Generation Specific - Use “leading words” to nudge the model toward a particular pattern

これは具体例で理解したほうが早いです。

なお、ChatGPTをプログラミングで利用しよう!! という人向けの方法なので、関係ない方も多いと思います。

Pythonでの例

Pythonというプログラミング言語でコードを生成したい場合、Python固有の単語(例: "import")を「リーディングワード」として使用します。これがあることで、ChatGPTはPythonの文法や構造にしたがってコードを生成しやすくなります。

❌ 効果が低いプロンプト例

プロンプト
# 以下のような簡単なpython関数を書いてください。
# 1.マイル単位の数値を尋ねる
# 2.マイルをキロメートルに変換する

✅ より効果的なプロンプト例

プロンプト
# 以下のような簡単なpython関数を書いてください。
# 1.マイル単位の数値を尋ねる
# 2.マイルをキロメートルに変換する

import

VBAでの例

Pythonは専門ではないので、VBAで具体例解説します。

今回のケースは、Functionプロシージャとして引数milesマイルを受け取って、それをメートルに変換して返してくれる関数を作って欲しいケースです。その場合、リーディングワードとしてFunction ConvertMilesToKilometers(ByVal miles As Double) As Double を使用することで、ほしかったコードを得ることができます。

❌ 効果が低いプロンプト例

プロンプト
# 以下のような簡単なvba関数を書いてください。
# 1.マイル単位の数値を尋ねる
# 2.マイルをキロメートルに変換する

目的のコードを得ることができていません。↓

✅ より効果的なプロンプト例

プロンプト
# 以下のような簡単なvba関数を書いてください。
# 1.マイル単位の数値を尋ねる
# 2.マイルをキロメートルに変換する

Function ConvertMilesToKilometers(ByVal miles As Double) As Double

目的のコードを得ることができました!!
(プログラミングコードをうまく生成するためには、このリーディングワードの他にも、「使ってほしい参照設定を指定する」など、ChatGPTに指向性を持たせることが重要だと思っています。)

Discussion