Google kaggle が提唱するプロンプトエンジニアリング技術：AI言語モデルとのコミュニケーション術を極める

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214013/45febc90-e000-4417-84a4-abd371feab5a.png)

[Google kaggle: Prompt Engineering より](URL "https://www.kaggle.com/whitepaper-prompt-engineering")

## 目次
1. [プロンプトエンジニアリングとは？](#プロンプトエンジニアリングとは？)
2. [LLMの出力設定](#LLMの出力設定)
   - [出力の長さ](#出力の長さ)
   - [サンプリングコントロール](#サンプリングコントロール)
   - [設定の相互作用](#設定の相互作用)
3. [プロンプト技術](#プロンプト技術)
   - [ゼロショットプロンプト](#ゼロショットプロンプト)
   - [ワンショット＆フューショットプロンプト](#ワンショット＆フューショットプロンプト)
   - [システム・コンテキスト・ロールプロンプト](#システム・コンテキスト・ロールプロンプト)
   - [ステップバックプロンプト](#ステップバックプロンプト)
   - [思考連鎖（Chain of Thought）](#思考連鎖)
   - [自己一貫性（Self-consistency）](#自己一貫性)
   - [思考の木（Tree of Thoughts）](#思考の木)
   - [ReAct（理由付けと行動）](#ReAct)
   - [自動プロンプトエンジニアリング](#自動プロンプトエンジニアリング)
4. [コードプロンプト](#コードプロンプト)
   - [コード作成のプロンプト](#コード作成のプロンプト)
   - [コード説明のプロンプト](#コード説明のプロンプト)
   - [コード翻訳のプロンプト](#コード翻訳のプロンプト)
   - [コードデバッグのプロンプト](#コードデバッグのプロンプト)
5. [ベストプラクティス](#ベストプラクティス)
   - [具体例を提供する](#具体例を提供する)
   - [シンプルな設計](#シンプルな設計)
   - [出力について具体的に指示する](#出力について具体的に指示する)
   - [制約よりも指示を優先する](#制約よりも指示を優先する)
   - [その他のベストプラクティス](#その他のベストプラクティス)
6. [プロンプトエンジニアリングの知識チェック](#プロンプトエンジニアリングの知識チェック)
7. [まとめ](#まとめ)

## プロンプトエンジニアリングとは？

プロンプトエンジニアリングとは、大規模言語モデル（LLM）に対して効果的な入力（プロンプト）を設計し、望ましい出力を生成させるための技術です。プロンプトとは、モデルに提供する入力テキストで、タスクの説明や指示、例示などを含みます。

重要なのは、プロンプトエンジニアリングはデータサイエンティストやMLエンジニアでなくても誰でも行えるということです。しかし、最も効果的なプロンプトを作成するには、以下のような多くの要素を考慮する必要があります：

- 使用するモデル（Gemini、GPT、Claude、Gemmaなど）
- モデルのトレーニングデータ
- モデルの設定（温度、top-k、top-pなど）
- 単語選択、スタイル、トーン
- 構造とコンテキスト

プロンプトエンジニアリングは反復的なプロセスであり、不適切なプロンプトは曖昧または不正確な応答につながる可能性があります。

## LLMの出力設定

LLMを使用する際、出力を制御するためのいくつかの重要な設定があります：

### 出力の長さ

生成するトークン（単語や部分的な単語）の数を制御します。より多くのトークンを生成すると、より多くの計算が必要になり、応答が遅くなる可能性があり、コストも高くなります。

:::note info
**トークンとは？**
トークンはLLMが処理する基本単位で、単語や部分的な単語に相当します。英語では一般的に1トークンは約0.75単語ですが、日本語ではより少ない単語数に相当します。モデルの処理単位であり、コストや速度に直接影響します。
:::

### サンプリングコントロール

LLMは次のトークンの確率を予測し、それからサンプリングして実際の出力を決定します。主な設定は：

**1. 温度（Temperature）** 🌡️
- トークン選択のランダム性を制御します
- 低い温度（0に近い）：より決定論的で予測可能な応答（事実的な回答に最適）
- 高い温度（1に近い）：より多様で創造的/予測不可能な結果
- 温度0：常に最も確率の高いトークンが選択される（greedy decoding）

**2. Top-K** 🔝
- モデルの予測分布から最も可能性の高いK個のトークンだけを選択します
- 高いTop-K：より創造的で多様なモデル出力
- 低いTop-K：より制限的で事実に基づいたモデル出力
- Top-K=1はgreedy decodingと同等

**3. Top-P（核サンプリング）** ⚛️
- 累積確率が特定の値（P）を超えない上位トークンを選択します
- 値の範囲は0（greedy decoding）から1（LLMの語彙内のすべてのトークン）

### 設定の相互作用

これらの設定は互いに影響し合います：

- 温度を0に設定すると、Top-KとTop-Pは無関係になり、最も確率の高いトークンが次に予測されるトークンになります
- Top-Kを1に設定すると、温度とTop-Pは無関係になります
- 一般的な出発点として：
  - 比較的一貫性のある結果には：温度0.2、Top-P 0.95、Top-K 30
  - より創造的な結果には：温度0.9、Top-P 0.99、Top-K 40
  - より事実に基づいた結果には：温度0.1、Top-P 0.9、Top-K 20
  - 常に1つの正解がある場合（数学的問題など）：温度0

```plantuml
@startuml
title LLM出力設定の概要

rectangle "入力プロンプト" as input #LightBlue
rectangle "LLMの内部処理" as processing #LightGreen
rectangle "出力生成" as output #LightPink

input --> processing

package "LLM出力設定" {
  card "出力長" as length #LightYellow
  card "温度 (Temperature)" as temp #LightYellow
  card "Top-K" as topk #LightYellow
  card "Top-P" as topp #LightYellow
}

length --> output
temp --> output
topk --> output
topp --> output

processing --> output

note bottom of length
  生成するトークン数の制限
  より多くのトークン = より高いコスト
end note

note bottom of temp
  低い（0）= 決定論的
  高い（1）= 創造的
end note

note bottom of topk
  最も可能性の高いK個のトークンに制限
end note

note bottom of topp
  確率閾値Pを超えないトークンのみ使用
end note

@enduml
```

:::note info
**「繰り返しループバグ」に注意**
大量のフィラー単語で終わる応答を見たことがありますか？これは、モデルが同じ（フィラー）単語、フレーズ、または文構造を繰り返し生成するサイクルに陥る「繰り返しループバグ」として知られています。このバグは、温度やtop-k/top-p設定が不適切だと悪化することがあります。このような場合、温度とtop-k/top-p値を慎重に調整して、決定論とランダム性のバランスを最適化する必要があります。
:::

## プロンプト技術

効果的なプロンプトを作成するためのさまざまな技術を見ていきましょう：

### ゼロショットプロンプト

最もシンプルなタイプのプロンプトで、タスクの説明と開始テキストのみを提供します。「ゼロショット」という名前は「例なし」を意味します。

- [x] **基本パターン**: タスク説明 + 入力テキスト → 出力

**例：**
```
映画レビューをPOSITIVE、NEUTRAL、NEGATIVEに分類してください。
レビュー：「Her」はAIが進化し続けると人類がどこに向かうかを示す不穏な研究です。このような傑作がもっとあればいいのに。
感情：
```

**応答：**
```
POSITIVE
```

### ワンショット＆フューショットプロンプト

モデルに例を提供することで、モデルが理解しやすくなります。

- [x] **ワンショットプロンプト**：単一の例を提供します（一発の例）
- [x] **フューショットプロンプト**：複数の例を提供します（数発の例）

例を選ぶ際は、タスクに関連し、多様で、高品質かつ適切に書かれたものを使用することが重要です。一般的には、フューショットプロンプトには少なくとも3〜5の例を使用すべきです。

**例（フューショットプロンプト）：**
```
顧客のピザ注文を有効なJSONに解析してください：

例：
私はチーズ、トマトソース、ペパロニが入った小さなピザが欲しいです。
JSON応答：
```
{
  "size": "small",
  "type": "normal",
  "ingredients": [["cheese", "tomato sauce", "peperoni"]]
}
```

例：
トマトソース、バジル、モッツァレラが入った大きなピザをお願いできますか
{
  "size": "large",
  "type": "normal",
  "ingredients": [["tomato sauce", "bazel", "mozzarella"]]
}

次に、大きなピザを注文したいと思います。最初の半分にはチーズとモッツァレラ、もう半分にはトマトソース、ハム、パイナップルをトッピングしてください。
JSON応答：
```

### システム・コンテキスト・ロールプロンプト

これらの技術はLLMの応答を導くために使用されますが、それぞれ異なる側面に焦点を当てています：

**1. システムプロンプト** 🖥️
- 言語モデルの全体的なコンテキストと目的を設定します
- モデルが何をすべきかの「大きな絵」を定義します（翻訳、分類など）

**例：**
```
映画レビューをポジティブ、ニュートラル、ネガティブに分類してください。ラベルのみを大文字で返してください。
レビュー：「Her」はAIが進化し続けると人類がどこに向かうかを示す不穏な研究です。あまりにも不穏で見ることができませんでした。
感情：
```

**2. コンテキストプロンプト** 📚
- 現在の会話やタスクに関連する具体的な詳細や背景情報を提供します
- モデルが何が求められているかのニュアンスを理解するのに役立ちます

**例：**
```
コンテキスト：あなたは80年代のレトロアーケードビデオゲームについてのブログを書いています。
書くべき記事のトピックを3つ提案し、それぞれの記事に含めるべき内容を数行で説明してください。
```

**3. ロールプロンプト** 🎭
- 言語モデルに特定のキャラクターやアイデンティティを割り当てます
- 割り当てられた役割に一貫した応答を生成するのに役立ちます

**例：**
```
旅行ガイドとして行動してください。私は自分の場所についてあなたに書き、あなたは私の近くで訪れるべき3つの場所を提案します。場合によっては、訪れたい場所のタイプも伝えます。
私の提案：「私はアムステルダムにいて、美術館だけを訪れたいと思います。」
旅行の提案：
```

### ステップバックプロンプト

ステップバックプロンプトは、最初に手元の特定のタスクに関連する一般的な質問を考慮するようLLMに促し、その後、その一般的な質問への回答を特定のタスクのための後続のプロンプトに組み込む技術です。この「一歩引く」ことで、LLMは特定の問題に取り組む前に関連する背景知識と推論プロセスを活性化させることができます。

- [x] **手順**: 一般的な質問 → 回答 → 元のタスクに回答を組み込む → 最終回答

**例：**
1. まず、一般的な質問をします：
```
一人称シューティングゲームのアクションゲームに基づいて、一人称シューティングゲームのレベルの挑戦的で魅力的なストーリーラインに貢献する5つの架空の重要な設定は何ですか？
```

2. 次に、その回答を元のタスクに組み込みます：
```
コンテキスト：一人称シューターゲームの5つの魅力的なテーマ：
1. **放棄された軍事基地**：変異した兵士と暴走ロボットがはびこる広大な終末論的な軍事施設...
2. **サイバーパンクシティ**：ネオンに照らされた未来的な都市環境...
3. **エイリアン宇宙船**：地球に不時着した広大なエイリアン船...
4. **ゾンビに侵された町**：積極的なゾンビの大群に支配された荒廃した町...
5. **水中研究施設**：水で満たされた深海研究所...

これらのテーマの1つを選んで、挑戦的で魅力的な一人称シューティングゲームの新しいレベルのストーリーラインを1段落で書いてください。
```

### 思考連鎖（Chain of Thought）

思考連鎖（CoT）プロンプトは、LLMに中間的な推論ステップを生成させることで、特に複雑な推論が必要なタスクでモデルが正確な回答を導き出す能力を向上させる技術です。最終的な答えを出す前に段階的に考えさせることで、より正確な結果が得られます。

- [x] **主な利点**: 
  - 低労力で非常に効果的
  - 既製のLLMで機能する（微調整不要）
  - 推論ステップを見ることができる解釈可能性

**例：**
```
私が3歳のとき、私のパートナーは私の3倍の年齢でした。今、私は20歳です。パートナーは何歳ですか？一歩ずつ考えましょう。
```

**応答：**
```
1. 私が3歳のとき、私の年齢は3歳です。
2. そのとき、私のパートナーの年齢は私の年齢の3倍、つまり3 * 3 = 9歳でした。
3. 今、私は20歳です。つまり私の年齢は20 - 3 = 17歳増加しました。
4. パートナーの年齢も17歳増加したはずなので、現在のパートナーの年齢は9 + 17 = 26歳です。
したがって、パートナーは26歳です。
```

:::note info
**CoTのベストプラクティス**
- 推論の後に回答を置く（生成された推論がモデルが最終回答を予測するときに受け取るトークンを変えるため）
- 推論と最終回答を区別できるようにする
- 推論を使用して最終回答を出す場合は、温度を0に設定する（通常、1つの正解がある）
:::

### 自己一貫性（Self-consistency）

自己一貫性は、サンプリングと多数決を組み合わせて多様な推論パスを生成し、最も一貫性のある回答を選択することで、LLMの応答の精度と一貫性を向上させる技術です。

- [x] **手順**:
1. 同じプロンプトをLLMに複数回提供し、高い温度設定を使用して異なる推論パスを生成します
2. 各生成された応答から答えを抽出します
3. 最も一般的な答えを選択します

これはAIが不確かな場合に特に有効ですが、複数の応答を生成するため、コストが高くなります。

**例（メール分類）：**
```
EMAIL:
```
こんにちは、
あなたのウェブサイトにWordpressを使用しているのを見ました。素晴らしいオープンソースのコンテンツ管理システムですね。私も過去に使用したことがあります。多くの優れたユーザープラグインが付属しており、セットアップも非常に簡単です。
連絡フォームにバグがあることに気づきました。名前フィールドを選択するときに発生します。名前フィールドにテキストを入力している私のスクリーンショットを添付しました。私がinv0k3dしたJavaScriptアラートボックスに注目してください。
しかし、他の点では素晴らしいウェブサイトです。読むのを楽しんでいます。バグをウェブサイトに残しても構いません。より興味深いものを読むことができますので。
よろしくお願いします、
ハッカーのハリー
```
上記のメールをIMPORTANTまたはNOT IMPORTANTに分類してください。一歩一歩考えて、理由を説明してください。
```

### 思考の木（Tree of Thoughts）

思考の木（ToT）は、CoTプロンプトの概念を一般化し、LLMが単一の線形思考の連鎖に従うのではなく、複数の異なる推論パスを同時に探索できるようにします。

この手法では、「思考」のツリーを維持し、各思考は問題解決に向けた中間ステップとして機能する一貫した言語シーケンスを表します。モデルはツリー内の異なるノードから分岐することで、異なる推論パスを探索できます。

```plantuml
@startuml
title 思考連鎖 vs 思考の木

rectangle "プロンプト質問" as Q

rectangle "CoT（思考連鎖）" as CoT {
  card "ステップ1" as S1
  card "ステップ2" as S2
  card "ステップ3" as S3
  card "最終回答" as A
  
  S1 --> S2
  S2 --> S3
  S3 --> A
}

rectangle "ToT（思考の木）" as ToT {
  card "ステップ1" as T1
  
  card "ステップ2A" as T2A
  card "ステップ2B" as T2B
  card "ステップ2C" as T2C
  
  card "ステップ3A" as T3A
  card "ステップ3B" as T3B
  card "ステップ3C" as T3C
  
  card "回答A" as TA
  card "回答B" as TB
  card "回答C" as TC
  
  T1 --> T2A
  T1 --> T2B
  T1 --> T2C
  
  T2A --> T3A
  T2B --> T3B
  T2C --> T3C
  
  T3A --> TA
  T3B --> TB
  T3C --> TC
}

Q --> CoT
Q --> ToT

note bottom of CoT
  単一の線形推論パス
end note

note bottom of ToT
  複数の並行推論パス
end note

@enduml
```

### ReAct（理由付けと行動）

ReAct（Reason and Act）プロンプトは、自然言語推論と外部ツール（検索、コードインタプリタなど）を組み合わせ、LLMが複雑なタスクを解決できるようにするパラダイムです。これにより、LLMは情報を取得するために外部APIとやり取りするなど、特定のアクションを実行できるようになります。

- [x] **基本動作**: 思考（推論）→ 行動 → 観察 → 思考（推論）→ ...

ReActプロンプトは、推論とアクションを思考-行動ループに組み合わせることで機能します：
1. LLMはまず問題について推論し、行動計画を生成します
2. 次にプランのアクションを実行し、結果を観察します
3. LLMは観察を使用して推論を更新し、新しい行動計画を生成します
4. このプロセスは、LLMが問題の解決策に到達するまで継続します

**例（Pythonコード）：**
```python
from langchain.agents import load_tools
from langchain.agents import initialize_agent
from langchain.agents import AgentType
from langchain.llms import VertexAI

prompt = "メタリカのバンドメンバーには何人の子供がいますか？"
llm = VertexAI(temperature=0.1)
tools = load_tools(["serpapi"], llm=llm)
agent = initialize_agent(tools, llm,
                        agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose=True)
agent.run(prompt)
```

実行結果では、AIが以下のようなステップで考えます：
1. メタリカには4人のメンバーがいることを特定
2. 各メンバー（James Hetfield、Lars Ulrich、Kirk Hammett、Robert Trujillo）について子供の数を検索
3. 合計を計算（3 + 3 + 2 + 2 = 10）
4. 最終回答として「10」を返す

### 自動プロンプトエンジニアリング

自動プロンプトエンジニアリング（APE）は、プロンプト作成プロセスを自動化する方法です。このアプローチでは、モデルに多くのプロンプトを生成させ、それらを評価し、優れたものを選択・改良する反復プロセスを自動化します。

- [x] **手順**:
1. プロンプト候補を生成するプロンプトを書く
2. スコアリングメトリクスに基づいて候補を評価する
3. 最も評価スコアの高い候補を選択する
4. 必要に応じて選択したプロンプトを微調整し、再評価する

**例：**
1. まず、バリエーションを生成するプロンプトを書きます：
```
バンドグッズTシャツのウェブショップがあり、チャットボットをトレーニングするためにさまざまな注文方法が必要です：「メタリカのTシャツをSサイズで1枚」。同じ意味を保ちながら10のバリエーションを生成してください。
```

2. 生成された指示候補を評価します（BLEUやROUGEなどのメトリックに基づいてスコアリング）
3. 最も評価スコアの高い指示候補を選択します
4. 必要に応じて選択したプロンプトを微調整し、再評価します

## コードプロンプト

### コード作成のプロンプト

LLMは様々なプログラミング言語でコードを書くのに役立ちます。これにより、コード作成プロセスを大幅に高速化できます。

- [x] **適切な用途**: 新規コード生成、スクリプト開発、プロトタイピング

**例：**
```
フォルダ名を尋ねるBashのコードスニペットを書いてください。
次に、フォルダの内容を取得し、ファイル名の前に「draft」という名前を付けて、
フォルダ内のすべてのファイルの名前を変更します。
```

**応答：**
```bash
#!/bin/bash
# フォルダ名を尋ねる
echo "フォルダ名を入力してください："
read folder_name
# フォルダが存在するか確認
if [ ! -d "$folder_name" ]; then
  echo "フォルダが存在しません。"
  exit 1
fi
# フォルダ内のファイルリストを取得
files=( "$folder_name"/* )
# 各ファイルの名前の前に「draft」を付ける
for file in "${files[@]}"; do
  new_file_name="draft_$(basename "$file")"
  mv "$file" "$file_name"
done
echo "ファイルの名前が正常に変更されました。"
```

### コード説明のプロンプト

LLMはコードを説明するのにも役立ちます。これは他人のコードを理解する必要がある場合に特に便利です。

- [x] **適切な用途**: コードの理解、ドキュメント作成、チームコラボレーション

**例：**
```
以下のBashコードを説明してください：

```
#!/bin/bash
echo "フォルダ名を入力してください："
read folder_name
if [ ! -d "$folder_name" ]; then
  echo "フォルダが存在しません。"
  exit 1
fi
files=( "$folder_name"/* )
for file in "${files[@]}"; do
  new_file_name="draft_$(basename "$file")"
  mv "$file" "$new_file_name"
done
echo "ファイルの名前が正常に変更されました。"
```
```

### コード翻訳のプロンプト

ある言語から別の言語へのコードの翻訳も、LLMの重要な用途の一つです。

- [x] **適切な用途**: 言語移行、クロスプラットフォーム開発、レガシーコード更新

**例：**
```
以下のBashコードをPythonスニペットに翻訳してください。

```bash
#!/bin/bash
echo "フォルダ名を入力してください："
read folder_name
if [ ! -d "$folder_name" ]; then
  echo "フォルダが存在しません。"
  exit 1
fi
files=( "$folder_name"/* )
for file in "${files[@]}"; do
  new_file_name="draft_$(basename "$file")"
  mv "$file" "$new_file_name"
done
echo "ファイルの名前が正常に変更されました。"
```
```

**応答：**
```python
import os
import shutil
# ユーザーからフォルダ名を取得
folder_name = input("フォルダ名を入力してください：")
# フォルダが存在するか確認
if not os.path.isdir(folder_name):
    print("フォルダが存在しません。")
    exit(1)
# フォルダ内のすべてのファイルのリストを取得
files = os.listdir(folder_name)
# ファイルを繰り返し処理
for file in files:
    # 接頭辞「draft_」で新しいファイル名を作成
    new_file_name = f"draft_{file}"
    # ファイルを新しい名前に移動
    shutil.move(os.path.join(folder_name, file),
                os.path.join(folder_name, new_file_name))
# 成功メッセージを表示
print("ファイルの名前が正常に変更されました。")
```

### コードデバッグのプロンプト

LLMはコードのデバッグや見直しにも役立ちます。エラーメッセージを提供するだけで、問題と解決策を特定できます。

- [x] **適切な用途**: エラー診断、バグ修正、コード最適化

**例：**
```
以下のPythonコードではエラーが発生します：
Traceback (most recent call last):
File "/Users/user/Documents/test_folder/rename_files.py", line 7, in <module>
  text = toUpperCase(prefix)
NameError: name 'toUpperCase' is not defined

コードのデバッグと改善方法を説明してください。
```python
import os
import shutil
folder_name = input("フォルダ名を入力してください：")
prefix = input("ファイル名の前に付ける文字列を入力してください：")
text = toUpperCase(prefix)
if not os.path.isdir(folder_name):
  print("フォルダが存在しません。")
  exit(1)
files = os.listdir(folder_name)
for file in files:
  new_filename = f"{text}_{file}"
  shutil.move(os.path.join(folder_name, file),
              os.path.joi(folder_name, new_file_name))
print("ファイルの名前が正常に変更されました。")
```
```

:::note warn
**コードプロンプトの注意点**
LLMが生成したコードは、実行前に必ず確認してください。LLMは優れたコードを生成できますが、完璧ではありません。特に複雑なプロジェクトやセキュリティが重要な場合は、コードレビューが不可欠です。
:::

## ベストプラクティス

プロンプトエンジニアリングを行う際に役立つベストプラクティスをいくつか紹介します：

### 具体例を提供する

プロンプト内に例を提供することは非常に効果的です。例は強力な教育ツールとして機能し、モデルが期待に合わせた出力を生成するのに役立ちます。

- [x] **ポイント**: 例はモデルが模倣できるパターンを提供し、出力の精度を向上させます

### シンプルな設計

プロンプトは簡潔で明確で理解しやすいものにすべきです。経験則として、自分自身が混乱するようなプロンプトは、モデルにとっても混乱する可能性が高いです。

- [x] **ポイント**: 複雑な言語を避け、不必要な情報を提供しないようにする

**例：**
改善前：
```
私は今ニューヨークを訪れていて、素晴らしい場所についてもっと知りたいです。3歳の子供2人と一緒にいます。休暇中にどこに行くべきでしょうか？
```

改善後：
```
観光客向けの旅行ガイドとして行動してください。3歳の子供と一緒にニューヨークマンハッタンで訪れるべき素晴らしい場所を説明してください。
```

**アクションを記述する動詞を使用する例**:
Act（行動する）、Analyze（分析する）、Categorize（分類する）、Classify（分類する）、Contrast（対比する）、Compare（比較する）、Create（作成する）、Describe（説明する）、Define（定義する）、Evaluate（評価する）、Extract（抽出する）、Find（見つける）、Generate（生成する）、Identify（特定する）、List（リストする）、Measure（測定する）、Organize（整理する）、Parse（解析する）、Pick（選ぶ）、Predict（予測する）、Provide（提供する）、Rank（ランク付けする）、Recommend（推奨する）、Return（返す）、Retrieve（取得する）、Rewrite（書き直す）、Select（選択する）、Show（表示する）、Sort（並べ替える）、Summarize（要約する）、Translate（翻訳する）、Write（書く）

### 出力について具体的に指示する

望ましい出力について具体的に指示することが重要です。簡潔な指示ではLLMを十分に導けないか、あるいは一般的すぎる可能性があります。

- [x] **ポイント**: プロンプト内で出力の詳細（長さ、スタイル、フォーマットなど）を指定する

**推奨：**
```
ビデオゲームコンソールのトップ5についての3段落のブログ記事を生成してください。ブログ記事は情報提供的で魅力的であり、会話調で書かれているべきです。
```

**非推奨：**
```
ビデオゲームコンソールについてのブログ記事を生成してください。
```

### 制約よりも指示を優先する

指示と制約はどちらもLLMの出力を導くために使用されますが、それぞれ異なる目的があります：

- **指示**：応答の望ましいフォーマット、スタイル、内容に関する明示的な指示を提供します
- **制約**：応答に関する制限や境界のセットです

- [x] **ポイント**: 模範となる具体的な例を示すことで、制約よりも指示を優先する

研究によると、プロンプトでは制約に大きく頼るよりも肯定的な指示に焦点を当てることが効果的である可能性があります。

**推奨：**
```
上位5つのビデオゲームコンソールについての1段落のブログ記事を生成してください。コンソール、製造会社、発売年、総販売数についてのみ説明してください。
```

**非推奨：**
```
上位5つのビデオゲームコンソールについての1段落のブログ記事を生成してください。ビデオゲーム名をリストしないでください。
```

### その他のベストプラクティス

- [x] **トークン長の制限を制御する**：設定で最大トークン制限を設定するか、プロンプトで特定の長さを明示的に要求する
- [x] **プロンプトで変数を使用する**：異なる入力に対してプロンプトを再利用し、より動的にする
- [x] **入力フォーマットとライティングスタイルを実験する**：異なるモデル、設定、フォーマット、単語選択が異なる結果をもたらす可能性がある
- [x] **分類タスクでのクラスをミックスする**：フューショットプロンプトを使用する場合、可能な応答クラスを混合する
- [x] **モデルの更新に適応する**：モデルアーキテクチャの変更、追加されたデータ、機能に注意する
- [x] **出力フォーマットを実験する**：創造的でないタスク（抽出、選択、解析など）にはJSON形式などの構造化された出力を検討する
- [x] **プロンプト試行を記録する**：詳細に記録して、何がうまくいき、何がうまくいかなかったかを学ぶ

:::note info
**JSON出力の利点**
- 常に同じスタイルで返される
- 受け取りたいデータに焦点を当てる
- 幻覚（ハルシネーション）の可能性が低い
- 関係性を認識できる
- データ型が取得できる
- 並べ替えが可能
:::

## プロンプトエンジニアリングの知識チェック

以下の質問に答えてみて、プロンプトエンジニアリングの知識を確認しましょう：

1. 温度パラメータを0に設定すると、どのような効果がありますか？
   - [ ] より創造的な回答が生成される
   - [ ] 回答が完全にランダムになる
   - [ ] 常に最も確率の高いトークンが選択される
   - [ ] 回答が生成されなくなる

2. フューショットプロンプトの主な利点は何ですか？
   - [ ] 計算コストが低減される
   - [ ] モデルに具体例を提供することで理解を助ける
   - [ ] 出力が常に一定になる
   - [ ] トークン数を減らせる

3. 思考連鎖（Chain of Thought）プロンプトに最適な温度設定は？
   - [ ] 1.0（最大創造性）
   - [ ] 0.5（バランスの取れた創造性）
   - [ ] 0（決定論的な回答）
   - [ ] 設定は無関係

4. ReActプロンプトの主な特徴は？
   - [ ] 複数の異なる回答を生成すること
   - [ ] 推論と外部ツールの使用を組み合わせること
   - [ ] 常に最も確率の高い回答を選ぶこと
   - [ ] 最小限のトークンを使用すること

5. プロンプトエンジニアリングのベストプラクティスとして正しいのは？
   - [ ] 常に可能な限り長いプロンプトを使用する
   - [ ] 制約よりも肯定的な指示を優先する
   - [ ] 常に高温度設定を使用する
   - [ ] 例は提供しないほうが良い

（答え: 3, 2, 3, 2, 2）

## まとめ

プロンプトエンジニアリングは、さまざまな技術を使用してLLMからより良い応答を引き出す反復的なプロセスです：

- **ゼロショットプロンプト**：例なし
- **ワンショット・フューショットプロンプト**：1つまたは複数の例を提供
- **システム・コンテキスト・ロールプロンプト**：全体的なコンテキスト、背景情報、または特定の役割を提供
- **ステップバックプロンプト**：一般的な質問を最初に検討
- **思考連鎖（CoT）**：中間的な推論ステップを生成
- **自己一貫性**：多様な推論パスを生成し多数決を採る
- **思考の木（ToT）**：複数の推論パスを同時に探索
- **ReAct**：推論と外部ツールを組み合わせる
- **自動プロンプトエンジニアリング**：プロンプト生成プロセスを自動化

効果的なプロンプトエンジニアリングには、出力設定の理解、具体例の提供、シンプルな設計、出力に関する明確な指示、そして継続的な実験と記録が必要です。

プロンプトエンジニアリングはまだ進化している分野であり、新しいテクニックや戦略が常に開発されています。LLMの可能性を最大限に引き出すためには、この分野に関する最新の進展に注目し、自分自身のプロンプトを継続的に改善していくことが重要です。