OpenAI公式GPT-4向けベストプラクティスをわかりやすく日本語化

本ガイドでは、GPTからより良い結果を得るための戦略と手法を共有します。ここで説明する方法は、より大きな効果を得るために組み合わせて使用することもあります。ベストな方法を見つけるために実験を積極的に行うことを推奨します。

ここで示される一部の例は、現在我々の最も能力のあるモデル、gpt-4でのみ動作します。もしまだgpt-4へのアクセスがない場合、ウェイトリストに参加を考えてみてください。一般的に、GPTモデルが任務に失敗し、より能力のあるモデルが利用可能な場合、そのモデルで再度試す価値があります。

※ベストプラクティスはChatGPT向けではなく、GPT-4のchat completion api向けに書かれております。本記事ではできるだけChatGPTでも再現できるように記述しておりますが、一部以下のコードにあるシステムやアシスタントという記載があります。

```python
import openai

openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Who won the world series in 2020?"},
        {"role": "assistant", "content": "The Los Angeles Dodgers won the World Series in 2020."},
        {"role": "user", "content": "Where was it played?"}
    ]
)
```

## より良い結果を得るための6つの戦略

ベストプラクティスの６つの戦略は以下になります。

- 戦略１：明確な指示を書く
- 戦略２：参考文献を提供する
- 戦略３：複雑なタスクをより簡単なサブタスクに分割する
- 戦略４：GPTに「考える」時間を与える
- 戦略５：外部ツールを使用する
- 戦略６：変更を体系的にテストする

ここからそれぞれ詳細について説明していきます。


## 戦略１：明確な指示を書く
GPTはあなたの心を読むことはできません。出力が長すぎる場合は、簡潔な回答を求めてみてください。出力がシンプルすぎる場合は、専門家レベルの文章を求めてみてください。フォーマットが気に入らない場合は、希望するフォーマットを示してみてください。GPTがあなたが何を望んでいるかを推測しなければならないほど、あなたが望む結果を得る可能性が高くなります。

#### 戦術：

- **より関連性のある答えを得るために、クエリに詳細を含める**
高い関連性のある応答を得るためには、リクエストが重要な詳細やコンテキストを提供することを確認してください。そうしないと、あなたが何を意味するのかをモデルに推測させることになります。

例）
Excelで数値を足すにはどうすればいいですか？
↓
Excelで行全体のドル額を自動的に足すにはどうすればいいですか？全体の行をシートで自動的に足し、全ての合計を「合計」という列の右に表示したいです。

- **モデルにパーソナを採用させる**
システムメッセージは、モデルが回答で使用するペルソナを指定するために使用することができます。

例）
**システム**　何かを書くための助けを求めると、モデルは少なくとも一つの冗談や遊び心のあるコメントを含むドキュメントを返答します。
**ユーザー**　スチールボルトのベンダーに対し、納期通り、かつ短期間で納品してくれたことに感謝の言葉を書いてください。これにより、私たちは重要なオーダーを達成することができました。

- **入力の異なる部分を明確に示すためにデリミタを使用する**
3重の引用符、XMLタグ、セクションタイトルなどのデリミタは、テキストの異なるセクションを明確に区分するのに役立ちます。タスクが複雑になればなるほど、タスクの詳細を曖昧さを取り除くことが重要になります。

例）
3重引用符で区切られたテキストを一句で要約してください。

"""ここにテキストを挿入"""

例）

あなたは論文の抄録とそれに対する提案タイトルを提供されます。論文のタイトルは、論文のトピックを読者に良く理解させるべきですが、目を引くものでもあるべきです。もしタイトルがこれらの基準を満たしていない場合、5つの代替案を提案します。

Abstract: ここに抄録を挿入
Title: ここにタイトルを挿入


- **タスクを完了するために必要な手順を明記する**
いくつかのタスクは、手順のシーケンスとして最適に指定されます。手順を明確に書き出すことで、モデルがそれらに従うのがより簡単になります。

例）
以下の手順に従ってユーザーの入力に対応します。

ステップ1 - ユーザーは三重引用符でテキストを提供します。このテキストを"要約: "という接頭語で一文で要約します。

ステップ2 - ステップ1の要約をスペイン語に翻訳します。翻訳文には"翻訳: "という接頭語をつけます。

"""ここにテキストを挿入"""

- **例を提供する**
全ての例に適用可能な一般的な指示を提供することは、タスクの全ての変異を例示するよりも通常は効率的ですが、場合によっては例を提供する方が簡単かもしれません。たとえば、あなたがモデルにユーザーの問い合わせに対する特定のスタイルの応答をコピーするように意図しているが、それを明示的に記述するのが難しい場合などです。これは「少数ショット」プロンプトとして知られています。

例）
**システム**
一貫したスタイルで答えてください。

**ユーザー**
忍耐について教えてください。

**アシスタント**
最も深い谷を作り出す川は控えめな泉から流れ、最も壮大な交響曲は一つの音符から始まり、最も複雑なタペストリーは一本の糸から始まります。

**ユーザー**
海洋について教えてください。

- **出力の望ましい長さを指定する**
モデルに対して、与えられた目標の長さの出力を生成するように要求することができます。目標の出力長さは、単語、文、段落、箇条書きなどの数で指定することができます。ただし、モデルに特定の単語数を生成するように指示すると、精度が高くないことに注意してください。モデルは、特定の段落数または箇条書きの数を持つ出力をより信頼性高く生成することができます。

例）
3重引用符で区切られたテキストを約50語で要約してください。

"""ここにテキストを挿入"""

### 戦略２：参考文献を提供する

GPTは、特に専門的なトピックや引用、URLについて問われたときに、自信を持って偽の答えを作り出すことができます。ノートがテストでの成績向上に役立つように、GPTに参考文を提供することで、より少ない作り話で回答するのに役立ちます。

#### 戦術：

- **モデルに参考文を使って答えるよう指示する**
私たちがモデルに現在のクエリに関連する信頼できる情報を提供することができるならば、モデルに提供した情報を使用して回答を作成するよう指示することができます。
GPTは限定的なコンテクストウィンドウを持っているため、この戦術を適用するためには、現在の質問に関連する情報を動的に検索する方法が必要です。埋め込みは効率的な知識検索を実装するために使用できます。この方法の実装については、記事後半にある「埋め込みベースの検索を用いて効率的な知識検索を実装する」戦術を参照してください。


例）
三重引用符で区切られた提供された記事を用いて質問に答えてください。もし答えが記事内に見つからない場合は、「答えを見つけることができませんでした」と書いてください。

"""三重引用符で区切られた各記事を挿入"""

質問: <ここに質問を挿入>

- **モデルに参考文からの引用で答えるよう指示する**
入力が関連する知識で補完されている場合、モデルに対してその回答に引用を追加するように要求するのは簡単です。この引用は、提供されたドキュメントからのパッセージを参照することにより行います。出力内の引用は、提供されたドキュメント内での文字列マッチングによりプログラムで確認できることに注意してください。

例）
あなたには三重引用符で区切られたドキュメントと質問が提供されます。あなたのタスクは、提供されたドキュメントだけを用いて質問に答え、質問に答えるために用いたドキュメントのパッセージを引用することです。もしドキュメントがこの質問に答えるために必要な情報を含んでいない場合は、単に「情報が不十分です」と書いてください。質問への答えが提供される場合、それは引用注記付きでなければなりません。関連するパッセージを引用するための以下の形式を使用してください({"引用":…})

"""<ここにドキュメントを挿入>"""

質問: <ここに質問を挿入>

### 戦略３：複雑なタスクをより簡単なサブタスクに分割する

ソフトウェアエンジニアリングで複雑なシステムを一連のモジュラーコンポーネントに分解するのが良い慣行であるように、GPTに投稿されるタスクについても同じことが言えます。複雑なタスクは簡単なタスクよりもエラーレートが高い傾向があります。さらに、複雑なタスクはより早いタスクの出力を使って後のタスクの入力を構築する、より単純なタスクのワークフローとして再定義できることがよくあります。

#### 戦術：

- **ユーザークエリに最も関連性のある指示を特定するために意図分類を使用する**
異なるケースを処理するために多くの独立した指示セットが必要なタスクでは、最初にクエリのタイプを分類し、その分類を使用してどの指示が必要かを決定すると便利です。これは固定カテゴリを定義し、そのカテゴリでタスクを処理するための関連する指示をハードコードすることで達成できます。このプロセスは再帰的に適用でき、タスクを一連の段階に分解します。このアプローチの利点は、各クエリが次のタスクのステージを実行するために必要な指示のみを含むため、全体のタスクを一度に実行するための単一のクエリを使用するよりもエラーレートが低くなることです。また、大きなプロンプトは実行コストが高くなるため（料金情報を参照）、コストも低くなります。
例えば、カスタマーサービスのアプリケーションにおいて、クエリは次のように有用に分類することができます。

例）
>**システム**
カスタマーサービスのクエリが提供されます。各クエリを主要カテゴリと副カテゴリに分類します。出力はjson形式で、キーは: primaryとsecondaryであるべきです。
>
>主要なカテゴリ: Billing（請求）、Technical Support（技術サポート）、Account Management（アカウント管理）、または General Inquiry（一般的な問い合わせ）。
>
>請求の副カテゴリ:
>
>アンサブスクライブまたはアップグレード
支払い方法の追加
請求の説明
>
>技術サポートの副カテゴリ:
>
>トラブルシューティング
>デバイスの互換性
>
>アカウント管理の副カテゴリ:
>
>パスワードのリセット
個人情報の更新
>
>一般的な問い合わせの副カテゴリ:
>
>商品情報
>価格

**ユーザー**
またインターネットを使えるようにしたい。


さらに顧客クエリの分類に基づいて、GPTモデルに次のステップを処理するためのより具体的な指示を提供することができます。例えば、顧客が"トラブルシューティング"の助けが必要な場合。

>**システム**
技術サポートの文脈でトラブルシューティングが必要なカスタマーサービスの問い合わせが提供されます。以下の手順でユーザーを助けてください:
>
>ルーターへ/からのすべてのケーブルが接続されていることを確認するように頼んでください。ケーブルが時間と共に緩くなることはよくあります。
すべてのケーブルが接続されていても問題が解決しない場合、彼らがどのルーターモデルを使用しているかを尋ねてください
次に、デバイスを再起動する方法をアドバイスしてください:
モデル番号がMTD-327Jの場合、赤いボタンを押して5秒間押し続け、接続をテストする前に5分間待つようにアドバイスします。
モデル番号がMTD-327Sの場合、それを抜き差ししてから5分間待つようにアドバイスします。
デバイスを再起動して5分待った後でも、顧客の問題が解決しない場合は、ITサポートに接続するようにしてください。そのためには、{"IT support requested"}を出力します。
ユーザーがこのトピックと関連のない質問を始めた場合は、現在のトラブルシューティングについてのチャットを終了するかどうかを確認し、そのリクエストを以下のスキームに従って分類します:
<上記の主要/副カテゴリ分類スキームをここに挿入>

ユーザー
またインターネットを使えるようにしたい。

- **長い対話を必要とするダイアログアプリケーションの場合、以前の対話を要約またはフィルタリングする**
GPTは固定のコンテキスト長を持つため、ユーザーとアシスタントの間の対話で、全体の会話がコンテキストウィンドウに含まれる場合、無限に続けることはできません。
この問題に対する様々な回避策があり、その一つは、会話の前のターンを要約することです。入力のサイズがあらかじめ定められた閾値の長さに達すると、これは一部の会話を要約するクエリをトリガーし、先の会話の要約がシステムメッセージの一部として含まれることができます。あるいは、全体の会話を通じて以前の会話を非同期に要約することも可能です。
別の解決策は、現在のクエリに最も関連する会話の前の部分を動的に選択することです。この戦術については、「埋め込みベースの検索を使用して効率的な知識取得を実装する」を参照してください。

- **長いドキュメントを部分的に要約し、完全な要約を再帰的に構築する**
GPTは固定のコンテキスト長を持つため、生成される要約の長さを引いたコンテキスト長よりも長いテキストを一回のクエリで要約することはできません。
非常に長いドキュメント、例えば本を要約するためには、ドキュメントの各セクションを要約するための一連のクエリを使用することができます。セクションの要約を連結して要約し、要約の要約を作成します。このプロセスは、全体のドキュメントが要約されるまで再帰的に進行します。後のセクションを理解するためには初期のセクションに関する情報を使用する必要がある場合、本の任意のポイントで先行するテキストのランニングサマリーを含めることが有用なトリックとなるでしょう。この手順の効果性は、GPT-3のバリエーションを使用したOpenAIの以前の研究で調査されています。

### 戦略４：GPTに「考える」時間を与える

17を28で掛けると言われても、すぐには答えられないかもしれませんが、時間をかけて計算することはできます。同様に、GPTもすぐに答えようとすると推論エラーが多くなる傾向があります。答える前に推論の連鎖を求めることで、GPTがより確実に正解にたどり着くことができます。

#### 戦術：

- **モデルに、結論に急ぐ前に自分自身の解決策を考えるよう指示する**
時には、結論に達する前にモデルに明示的に原則から推論するよう指示すると、より良い結果が得られます。例えば、生徒の数学問題の解答を評価したいと思うモデルがあるとしましょう。最も明白なアプローチは、単純にモデルに生徒の解答が正しいかどうかを尋ねることです。それだと、まちがえてしまうことがあります！モデルがこれを正しく認識するためには、まずモデル自身に解答を生成させるように指示することが効果的です。 **自分自身で問題を解かないと、生徒の解答が正しいかどうかを決定しないでください。** を追加することで、解決策に沿って考えます。

例）
**システム**
まず自分で問題の解答を導き出してください。次に、自分の解答と生徒の解答を比較し、生徒の解答が正しいか評価してください。自分自身で問題を解かないと、生徒の解答が正しいかどうかを決定しないでください。

**ユーザー**
問題文：私はソーラーパネル設置プロジェクトを進行しており、費用計算の手助けが必要です。

- 土地は平方フィート当たり100ドル
- ソーラーパネルは平方フィート当たり250ドルで購入できます
- メンテナンス費は年間一律10万ドルで、さらに平方フィート当たり10ドルかかります
運営の初年度の総費用を設置面積の関数として何になるか。

生徒の解答：xを設置面積（平方フィート）とします。

1. 土地の費用：100x
1. ソーラーパネルの費用：250x
1. メンテナンス費：100,000 + 100x
総費用：100x + 250x + 100,000 + 100x = 450x + 100,000

**アシスタント**
xを設置面積（平方フィート）とします。
1. 土地の費用：100x
1. ソーラーパネルの費用：250x
1. メンテナンス費：100,000 + 10x
総費用：100x + 250x + 100,000 + 10x = 360x + 100,000

生徒の解答は誤っています。彼らはメンテナンス費の計算でエラーを犯し、100xではなく10xを使用すべきでした。運営の初年度の正しい総費用は360x + 100,000です。

- **モデルの推論過程を隠すために内的モノローグまたは一連のクエリを使用する**
前述の戦術では、モデルが特定の問いに答える前に、詳細に問題について推理することが重要であることが示されています。しかし、一部のアプリケーションでは、モデルが最終的な答えに至るまでの推理過程をユーザーと共有するのは不適切な場合もあります。例えば、チュータリングのアプリケーションでは、生徒が自分で答えを出すことを奨励したいかもしれませんが、**モデルが生徒の解答について推理する過程で、答えを生徒に知らせてしまう可能性があります**。

そのような問題を軽減するための戦術として、"内的モノローグ"があります。内的モノローグのアイデアは、モデルにユーザーから隠すべき出力の一部を、解析しやすい構造化された形式で書くように指示することです。そして、出力をユーザーに提示する前に、出力を解析し、出力の一部だけを可視化します。

例）
**システム**
以下のステップに従って、ユーザーの問いに答えてください。

ステップ1 - まず、自分自身で問題の解答を出してください。生徒の解答に頼ることなく、このステップでの作業は全て三重引用符（"""）で囲んでください。

ステップ2 - 自分の解答と生徒の解答を比較し、生徒の解答が正しいかどうかを評価してください。このステップでの作業は全て三重引用符（"""）で囲んでください。

ステップ3 - もし生徒が間違えていたら、答えを明かすことなく生徒に与えられるヒントを考えてみてください。このステップでの作業は全て三重引用符（"""）で囲んでください。

ステップ4 - もし生徒が間違えていたら、前のステップで考えたヒントを生徒に提供してください（三重引用符の外で）。"ステップ4 - ..."と書く代わりに、"ヒント:"と書いてください。

**ユーザー**
問題の提示: <問題の内容をここに挿入>

生徒の解答: <生徒の解答をここに挿入>

- **モデルが前のパスで何かを見落としていないかを尋ねる**
ある特定の質問に関連する情報源からの抜粋をリストアップするためにモデルを使用しているとします。モデルは、各抜粋をリストアップした後、新たに抜粋を作り始めるべきか、それとも停止するべきかを決定する必要があります。情報源が大きい場合、モデルが早まって停止し、すべての関連する抜粋をリストアップしきれないことがよくあります。そのような場合、前のパスで見逃した抜粋を見つけるためのフォローアップクエリでモデルをプロンプトすることで、より良いパフォーマンスがしばしば得られます。

例）
**システム**
三重引用符で区切られた文書が提供されます。次の質問に関連する抜粋を選択するのがあなたの役目です："人工知能の歴史において、何が重要なパラダイムシフトとなったのか。"

抜粋がそれらを解釈するために必要なすべての関連する文脈を含んでいることを確認してください。つまり、重要な文脈が欠けている小さな断片を抽出しないでください。出力は次のようなJSON形式で提供してください：

[{"excerpt": "..."},
...
{"excerpt": "..."}]

**ユーザー**
"""<ここに文書を挿入>"""

**アシスタント**
[{"excerpt": "ここにモデルが抜粋を書く"},
...
{"excerpt": "ここにモデルが別の抜粋を書く"}]

**ユーザー**
さらに関連する抜粋はありますか？抜粋が重複しないよう注意してください。また、抜粋がそれらを解釈するために必要なすべての関連する文脈を含んでいることを確認してください。つまり、重要な文脈が欠けている小さな断片を抽出しないでください。

### 戦略５：外部ツールを使用する

他のツールの出力をGPTにフィードすることで、GPTの弱点を補う。例えば、テキスト検索システムはGPTに関連文書について教えてくれます。コード実行エンジンはGPTが数学的な計算を行ったり、コードを実行したりするのを助けます。タスクがツールによってより確実に、または効率的に行われることができる場合、そのタスクを外部ツールに任せることで、GPTとツールの両方の利点を最大限に活用することができます。

#### 戦術：

- **効率的な知識検索を実装するために埋め込みベースの検索を使用する**
モデルは、入力の一部として提供される外部情報源を活用できます。これにより、モデルがより情報に基づいた、最新の回答を生成するのに役立ちます。たとえば、ユーザーが特定の映画についての質問をした場合、高品質な映画情報（例えば、俳優、監督など）をモデルの入力に追加すると便利かもしれません。埋め込みは効率的な知識取得を実装するために使用でき、実行時に動的にモデル入力に関連情報を追加できます。
テキスト埋め込みは、テキスト文字列間の関連性を測定できるベクトルです。類似した、または関連した文字列は、関連しない文字列よりも密接になるでしょう。この事実と、高速ベクトル検索アルゴリズムの存在は、埋め込みが効率的な知識取得を実装するために使用できることを意味します。具体的には、テキストコーパスをチャンクに分割し、各チャンクを埋め込み、保存できます。その後、特定のクエリが埋め込まれ、ベクトル検索が実行され、クエリに最も関連する（つまり、埋め込み空間で最も近い）コーパスのテキストチャンクを見つけることができます。
具体的な実装例は[OpenAI Cookbook](https://github.com/openai/openai-cookbook/blob/main/examples/vector_databases/Using_vector_databases_for_embeddings_search.ipynb)にあります。モデルが誤った事実を作り出す可能性を最小限に抑えるための知識取得の使用方法については、戦術「モデルにクエリへの回答に取得した知識を使用するよう指示する」を参照してください。

- **より正確な計算を行うために、または外部APIを呼び出すためにコード実行を使用する**
GPTは、単独で算数や長い計算を正確に実行することはできません。これが必要な場合、モデルは自分で計算をするのではなく、コードを書き、実行するように指示することができます。具体的には、モデルは、実行するためのコードを三つのバッククォートなどの指定された形式で記述するように指示することができます。出力が生成された後、コードを抽出して実行することができます。最後に必要であれば、コード実行エンジン（例：Pythonインタプリタ）からの出力を次のクエリのモデルへの入力として提供することができます。

例）
**システム**
Pythonコードを記述して実行するには、それを三つのバッククォートで囲むことができます。例：```code goes here``` これを使って計算を実行します。

**ユーザー**
次の多項式の実数値の根をすべて見つけてください：3*x **5 - 5*x **4 - 3*x ***3 - 7* x - 10


### 戦略６：変更を体系的にテストする
性能改善は、それを測定できる場合には容易です。一部の場合では、プロンプトの変更が数例でより良い性能を達成する一方で、より代表的な例群全体での性能を悪化させることがあります。そのため、性能に対する変更がネットでプラスであることを確認するためには、包括的なテストスイート（"評価"とも呼ばれます）を定義することが必要かもしれません。

#### 戦術：

- **ゴールドスタンダードの答えを参照してモデルの出力を評価する**
時には、新しい指示や新しいデザインなどの変更がシステムを良くするのか、それとも悪くするのかを判断するのは難しいことがあります。いくつかの例を見てみると、どちらが良いかのヒントになるかもしれませんが、サンプルサイズが小さいと、本当の改善なのか、それともただの偶然なのかを区別するのは難しいです。たとえば、変更が一部の入力で性能を向上させる一方で、他の入力では性能を低下させるかもしれません。
評価手順（または「評価」）は、システム設計を最適化するのに役立ちます。良い評価は次のような特徴があります：
- 実際の使用状況を代表する（少なくとも多様である）
- 統計的な確からしさを得るために多くのテストケースが含まれている（下の表を参照してください）
- 自動化や繰り返しやすい

検出するための差異|95%の信頼度で必要なサンプルサイズ
-|-
30%|約10
10%|約100
3%|約1,000
1%|約10,000

出力の評価は、コンピュータ、人間、またはその混合によって行うことができます。コンピュータは、客観的な基準（例えば、単一の正解を持つ質問）だけでなく、あいまいな基準に基づく評価も自動化することができます。これはモデルの出力が他のモデルのクエリによって評価される場合です。OpenAI Evalsは、自動化された評価を作成するためのツールを提供するオープンソースのソフトウェアフレームワークです。

モデルによる評価は、同等の高品質と考えられる可能性のある出力の範囲が存在する場合に有用です（例えば、長い回答を持つ質問）。モデルによる評価で現実的に評価できるものと、人間が評価する必要があるものの境界は、モデルがより能力を持つようになるにつれて、あいまいであり、常に移動しています。モデルによる評価があなたの使用ケースに対してどれほど効果的に機能するかを確認するために、実験を行うことをお勧めします。