GPTのベストプラクティスから学ぶ、プロンプトエンジニアリングざっくり

# はじめに
ChatGPT（以下、GPT）の普及に伴い、「プロンプトエンジニアリング」という言葉を耳にすることも増えてきたかと思います。プロンプトエンジニアリングとは、大規模言語モデル（Large Language Model）を使いこなすために必要なスキルです。GPTを命令（プロンプト）の書き方によって、出力されるコンテンツの質に大きな違いが生まれるために適切なものを入力するスキルが必要になります。
　今回はプロンプトエンジニアリングを学ぶ初歩として、OpenAIの公式ページに公開されている「GPT」のベストプラクティスを題材に学んでいこうと思います。

# ※使用前の注意事項
使用するGPTのサービスによっては、GPTのサービスで入力された情報はAI自身が学習し回答に使っています。つまり、世界中でGPTのサービスを使っている人に自身の入力した情報が回答として出力される可能性があります。

::: note alert
個人情報などの重要な情報は入力しないようにして下さい。
:::

以下の注意事項を理解した上で使用してください。
1. あなたが入力した情報をが学習に使っている場合がある。
（※社内利用される方は情報システム室等に入力された情報はどう使われているのか確認することをお勧めします。）
2. 誤った回答がされる場合がある
最近のGPTは非常に優秀で回答範囲が広い一方で、誤った回答をする場合があります。
AIに回答されたからと回答を鵜呑みにすることが内容に注意して下さい。

最低でも上記2点には十分に気をつけた上で利用するようにしてください。

# 1. 明確な指示を書く
働くうえで曖昧な指示を出されるのは嫌ですよね？AIが優れていると言っても人の心は読み取れません。
AIは「人が実現するあらゆる知覚や知性を人工的に再現（模倣）したものである」ということを忘れてはいけません。

そのため、自身が希望する回答を得るために明確な指示を出してあげてください。

OpenAIはアドバイスはくれています。
1. 詳細な説明をする
2. ペルソナを設定する
3. 区切り文字を使用する
4. 必要な手順を指定する
5. 例を挙げる
6. 出力の長さを指定する

## 1-1. 詳細な説明をする
関連性の高い回答を得るためには、何を意味するタスクであるのかをGPT側に推測させる必要があります。

|悪い例|より良い例|
|:---|:---|
|Excelで計算するにはどうすればいいか？|Excel で金額の行を合計するにはどうすればいいですか? これを行のシート全体に対して自動的に実行し、すべての合計が右側の「合計」という列に表示されるようにしたいです。|
|大統領は誰？|アメリカの初代大統領は誰ですか？選挙は何年に行われましたか？|
|フィボナッチ数列を計算してください|TypeScript 関数を作成して、フィボナッチ数列を効率的に計算します。コードに積極的にコメントを付けて、各部分が何を行うのか、なぜそのように記述されているのかを説明してください。|
|要約してください。|会議のメモを 1 つの段落に要約してください。次に、講演者とその要点のマークダウンリストを作成してください。最後に、講演者が提案した次のステップやアクション項目がある場合は、それをリストにしてください。|

表のように、ただGPTに指示を出すだけでなく、「何をしてほしいのか」「どういう出力を望んでいるのか」「5W1H」を意識してタスクを投げかけてください。これによって、自身が望む回答をGPTが返してくれる確率が高まります。

## 1-2. ペルソナを設定する
GPTにペルソナ（架空の人物モデル）を指定する。

```
私が何かを書くのに助けを求めると、あなたは各段落に少なくとも 1 つのジョークやふざけたコメントを含む文書を
返してくれるでしょう。

期日どおりに短期間で納品してくれたスチールボルトのベンダーに感謝の手紙を書いてください。
```

## 1-3. 区切り文字を使用する
三重引用符やXMLタグ、セクションタイトルなどの区切り文字で、テキストを区切ることができます。
```docker:例1
同じトピックに関する 2 つの記事 (XML タグで区切られた) が提供されます。まず各記事の主張を要約します。
次に、どちらがより良い議論を行うかを示し、その理由を説明します。
ユーザー
<article> ここに最初の記事を挿入 </article> 
<article> ここに 2 番目の記事を挿入 </article>
```

```docker:例2
論文の要約とそのタイトルの提案が提供されます。論文のタイトルは、読者に論文のテーマをよく理解させるもの
であると同時に、目を引くものでなければなりません。タイトルがこれらの基準を満たしていない場合は、
5つの代替案を提案してください。

要約: ここに要約を挿入 タイトル: ここにタイトルを挿入
```
簡単なタスクの場合は区切り文字を使用しても回答の品質に影響が出ない場合もあります。
しかし、タスクが複雑になるほど、詳細を明確にすることが重要になります。

## 1-4. 必要な手順を指定する
タスクによっては、ステップを指定してあげると効果的です。ステップを指示することでGPTがそのステップに従った回答をしやすくなります。

```docker:例1
ユーザー入力に応答するには、次の段階的な手順を使用してください。
ステップ 1 - ユーザーは三重引用符で囲んだテキストを提供します。
           「概要: 」という接頭辞を付けて、このテキストを 1 つの文で要約します。
ステップ 2 - ステップ 1 の概要を「翻訳: 」という接頭辞を付けてスペイン語に翻訳します。

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

## 1-5. 例を挙げる
GPTに指示や質問をするだけでなく、具体例を交えながら指示や質問を行うことでGPTがより具体的に理解します。結果として、適切な回答を生成しやすくなります。


## 1-6. 出力の長さを指定する
単語、文、段落、箇条書きなどの数を指定することができます。
ただし、特定の数の単語を生成するようにGPTに指示して、高い精度の回答が得られるとは限らないので注意してください。
段落や箇条書きの方が得意です。

```
三重引用符で区切られたテキストを約 50 語に要約してください。"""ここにテキストを挿入"""
```
```
三重引用符で区切られたテキストを 2 つの段落にまとめてください。"""ここにテキストを挿入"""
```


# 2. 参考テキストを提供する
[注意事項](https://qiita.com/Oimonokenp/items/c60f35ab9fe214f9a7c9#%E4%BD%BF%E7%94%A8%E5%89%8D%E3%81%AE%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A0%85)でも書きましたが、誤った回答をします。非常に知ったかぶりが上手く、それらしい回答を自信を持ってでっち上げます。

これを回避する方法として、参考テキストを用いることが挙げられます。

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

<記事を三重引用符で区切って挿入>
質問: <ここに質問を挿入>
```

```html:例2
提供された文書のみを使用して質問に答え、質問に答えるために使用された文書の一節を引用することです。
この質問に答えるために必要な情報が文書に含まれていない場合は、「情報が不十分です」と記入してください。

質問に対する回答が提供される場合は、引用で注釈を付ける必要があります。関連する文章を引用するには、
次の形式を使用します （{"citation": …}）。

"""
文章
"""

質問：(質問文)
```

# 3. 複雑なタスクは分割して、単純なタスクにする
複雑なタスクを処理する場合、エラー率が上がり回答の精度が低くなります。

サービスによってはGPTのコンテキストの長さはこていされているため、全体の会話がコンテキストウィンドウに含まれる場合無限に続けることができません。そこで、複雑なタスクを与える場合は一度にすべてをさせるのではなく、簡単な問題に分割して、一つずつ解いていくアプローチが有効になります。

例えば「ChatGPTの記事を書く」というタスクがあるとします。
プロンプトは次の流れのようになります。

最初に記事の概要を提案してもらう。
```
ChatGPTについての記事を書くための概要を提案して下さい。
```
次に提案してもらった概要を章や節に分割し、章や節ごとの説明を小さなタスクとして与える。
```
まずは序論について説明してください。
```
```
最後にまとめを書いてください。
```
今回の例だと、記事の概要を提案してもらい、それぞれの章や節ごとにタスクを与えることで1つの記事が完成する流れになります。

例のようにやりたいこと（タスク）の全体像を把握する（もしくは、GPTに提案してもらう）、その全体像を分割して投げてあげることによって、一つ一つのタスクの負荷が小さくなることで、精度の高い結果が得ることができます。

# 4. 「考える」時間を与える
人は17×39を掛けろと言われて、すぐにわからない場合もあると思います。しかし、時間が経てば解けるようになります。これはGPTも同じです。すぐに答えを出そうするときに推論のミスを起こすことが多くあります。
そのため、一連の推論を求めることで、GPTの回答がより正しくなるように導くことができます。
（※基本的にGPTは数値計算や論理推論などのタスクは間違えやすい傾向にあります。）

アプローチは2つあります。
1. 結論の前に独自の解決方法を見つけるようにモデルに指示する。
2. 前の回答で何か見逃していたかどうかを尋ねる。

ここでは1. のアプローチの例を「数学の問題に対する生徒の回答を評価するモデル」としてあげます。

```html:悪い例
生徒の解答が正しいかどうかを判断します。

問題の説明: 太陽光発電施設を建設しているのですが、財務状況を把握するのに助けが必要です。
- 土地の費用は平方フィートあたり 100 ドルです。 
- ソーラー パネルは平方フィートあたり 250 ドルで購入できます。 
- 年間一律 10 万ドル、追加で平方フィートあたり 10 ドルかかるメンテナンス契約を交渉しました。
操業初年度を平方フィート数の関数として表したもの。
生徒の解決策: x を平方フィート単位の設置サイズとします。
1. 土地代: 100x 
2. 太陽光パネル代: 250x 
3. 維持費: 100,000 + 100x 
4. 合計費用: 100x + 250x + 100,000 + 100x = 450x + 100,000
```

```html:良い例
まず、問題に対する独自の解決策を考え出します。次に、自分の解答と生徒の解答を比較し、生徒の解答が正しいか
どうかを評価します。自分で問題を解くまでは、生徒の解答が正しいかどうかを判断しないでください。

問題の説明: 太陽光発電施設を建設しているのですが、財務状況を把握するのに助けが必要です。
- 土地の費用は平方フィートあたり 100 ドルです。 
- ソーラー パネルは平方フィートあたり 250 ドルで購入できます。 
- 年間一律 10 万ドル、追加で平方フィートあたり 10 ドルかかるメンテナンス契約を交渉しました。
操業初年度を平方フィート数の関数として表したもの。
生徒の解決策: x を平方フィート単位の設置サイズとします。
1. 土地代: 100x 
2. 太陽光パネル代: 250x
3. 維持費: 100,000 + 100x
4. 合計費用: 100x + 250x + 100,000 + 100x = 450x + 100,000
```
このように正しいか間違っているかをすぐに出すのではなく、GPT自身に問題を解かせて正しい回答にたどり着き、そのうえで生徒の回答の正誤を問うようにタスクを与えてあげることで、より正しい回答に近づくことができます。

# 最後に
GPTのバージョンによって、「SYSTEM」と「USER」の入力欄があるものがあります。

SYSTEMには
```
私が何かを書くのに助けを求めると、あなたは各段落に少なくとも 1 つのジョークやふざけたコメントを含む文書を
返してくれるでしょう。
```
のようにモデルにペルソナを設定する。
```
同じトピックに関する 2 つの記事 (XML タグで区切られた) が提供されます。まず各記事の主張を要約します。次に、どちらがより良い議論を行うかを示し、その理由を説明します
```
や
```
論文の要約とそのタイトルの提案が提供されます。論文のタイトルは、読者に論文のテーマをよく理解させるものである
と同時に、目を引くものでなければなりません。タイトルがこれらの基準を満たしていない場合は、5 つの代替案を
提案してください。
```
```
まず、問題に対する独自の解決策を考え出します。次に、自分の解答と生徒の解答を比較し、生徒の解答が正しいか
どうかを評価します。自分で問題を解くまでは、生徒の解答が正しいかどうかを判断しないでください。
```
などのように、モデルにしてほしい振る舞いを指示してあげるといいでしょう。

生成AIは扱い方や付き合い方が重要になってきます。
困ったときには助けを求め、間違った回答したときは温かい目で見てあげましょう。