プロンプトエンジニアリング

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

プロンプトエンジニアリングとは、ChatGPTのような言語モデルから最適な回答を引き出すためのプロンプトを設計する学問分野である。この記事では基本的なプロンプトエンジニアリングの使い方のコツを扱う。より詳細な内容については「Prompt Engineering Guide」を参照されたい。なお、この記事の内容については、ChatGPT(GPT-3.5)で動作確認を実施した。

パラメータの設定

パラメータを設定を変更すると、異なる回答が得られるようになる。

パラメータ説明
Temperatureモデルが応答を生成する際の決定性を表すパラメータ。この値が低いほどより決定論的になり、高くなるほどランダム性が増す。QAなどの正確性が求められるタスクではこの値を低く、詩の生成などの創造性が求められるタスクでは高く設定すると効果的である。
Top_pTemperatureと同様にモデルが応答を生成する際の決定性を表すパラメータ。

一般的には、上記のどちらか一方を変更すれば良い。なお、これらのパラメータは、ChatGPTのAPIでは変更できるが、ChatGPTのサイトでは変更できない。

簡単に始める

プロンプトの設計は最適な回答を得るために多くの試行錯誤が必要な反復的なプロセスである。プロンプトガイドラインに従い、シンプルなプロンプトから始めて、徐々に要素や文脈を追加していくのが良い。

Notion Image

プロンプトガイドライン

  • とにかくやってみる
  • 明確で具体的な指示を与える
  • なぜほしい結果が得られないのか分析する
  • アイデアとプロンプトを洗練させる
  • 繰り返す
  • 良いプロンプト

    指示を明確にする

    「書く」、「分類する」、「要約する」、「翻訳する」、「並べ替える」、「コードを生成する」など、達成したいことを明確に指示することで、効果的なプロンプトを設計できる。一般的に指示はプロンプトの最初に記述する。


    プロンプト:

    以下の文章をドイツ語に翻訳してください。
    
    入力:私はドイツ語を勉強しています。
    翻訳:

    出力:

    Ich lerne Deutsch.

    直接的、具体的に記述する

    あいまいな表現を避け、直接的、具体的に記述することで、効果的なプロンプトを設計できる。


    プロンプト(元):

    プロンプトエンジニアリングの説明を、短く、数文で、ざっくり説明してください。

    プロンプト(改良後):

    中学生にもわかるように、プロンプトエンジニアリングを2~3文で説明してください。

    区切り文字を利用する

    区切り文字を利用することで解釈しやすいプロンプトを設計できる。区切り文字には、```、"""、< >、<tag> </tag>、:などが利用できる。


    プロンプト:

    三重のバッククォートで区切られた文章を2~3文で要約してください。
    ```
    フィボナッチ数列は、最初の2つの数が1で始まり、それ以降の数は直前の2つの数の和で生成される数列です。具体的には、1, 1, 2, 3, 5, 8, 13, 21, ...と続きます。この数列は、古代のイタリア人数学者であるレオナルド・フィボナッチによって導入され、彼の著書『算術の書』で紹介されました。
    
    フィボナッチ数列は自然界や数学のさまざまな現象に見られることで知られており、その特性は興味深いです。例えば、植物の花弁の数や果実の種子の配置、螺旋を描く巻貝の殻の形状など、自然界の様々なパターンにフィボナッチ数列の比率が現れます。
    
    さらに、フィボナッチ数列は金融や計算機科学、芸術などの分野でも応用されています。金融では、株価の変動や市場の予測に使用されることがあります。計算機科学では、アルゴリズムやデータ構造の設計に応用されます。芸術では、フィボナッチ数列の比率を用いた黄金比や黄金長方形などが美的観点から採用されることがあります。
    
    フィボナッチ数列は、数学的な興味の対象だけでなく、実世界で広く応用される有用な数列です。
    ```

    出力:

    フィボナッチ数列は、最初の2つの数が1で始まり、その後の数は直前の2つの数の和で生成される数列です。自然界や数学の現象に現れ、金融や計算機科学、芸術などの分野でも応用されています。フィボナッチ数列は実世界で広く応用される有用な数列です。

    文脈を追加する

    文脈として、役職を与えたり、制限、前提、予備知識を追加することで、効果的なプロンプトを設計できる。


    プロンプト(役職を与える):

    あなたは優秀な物理学者です。
    小学生にもわかるように、万有引力について説明してください。

    出力:

    はい、分かりやすく説明しますね。
    
    万有引力とは、全ての物体には引力という力が働いており、その強さは物体の質量と距離によって決まる力です。例えば、地球の重力は私たちを引きつけ、私たちは地球に引かれています。同じように、月は地球の引力によって引き寄せられ、地球もまた月を引きつけます。
    
    この引力は、ニュートンの万有引力の法則で表されます。この法則によれば、二つの物体間の引力は、それらの質量の積に比例し、それらの間の距離の2乗に反比例することが分かっています。
    
    例えば、地球と月の間の引力は、地球と月の質量の積に比例し、地球と月の距離の2乗に反比例します。この法則によって、私たちは太陽系の惑星の動きや、銀河系の星々の動きなどを説明することができます。
    
    ということで、万有引力とは、全ての物体が持っている引力のことであり、それは物体の質量と距離によって決まる力です。

    プロンプト(文字数制限、人物の予備知識を追加する):

    AさんとBさんの会話を200文字程度で生成してください。
    
    ・Aさんは昨日のサッカーの試合で応援していたチームが勝ってテンションが高い。
    ・Bさんはサッカーにはあまり興味がない。

    出力:

    Aさん: 昨日のサッカーの試合、めっちゃ面白かった!うちのチームが勝ったんだ!
    Bさん: へー、それはよかったね。
    Aさん: ホントに最高だったよ!あの勝利は今シーズンで最高の瞬間だったと思う。
    Bさん: 私はサッカーにはあまり興味がないけど、うれしい気持ちはわかるよ。
    Aさん: ありがとう!今回の勝利は次の試合にもつながると思うんだ。もう次の試合が待ちきれない!
    Bさん: そうなるといいね。私はあまり詳しくないけど、がんばってほしいよ。

    出力のフォーマットを指定する

    フォーマットを具体的に指定すると、特定の出力フォーマットで回答を得ることができる。


    プロンプト:

    以下の文章からサウスウェスト航空が創業された年を抽出してください。
    望ましいフォーマット:
    年: <year>
    入力:サウスウェスト航空は、アメリカ合衆国の航空会社であり、世界最大のLCCの一つです。1971年にテキサス州で創業され、主にアメリカ国内を中心に路線網を持っています。サウスウェスト航空は、低価格と高品質のサービスを提供し、スタッフと乗客の笑顔を大切にしています。また、航空業界で先駆的な試みとして、創業時から「バッグチェック料金不要」という方針を取っています。現在は、アメリカ国内だけでなく、メキシコ、中央アメリカ、カリブ海にも就航しています。

    出力:

    年: 1971年

    また、以下のようにJSON形式やHTML形式、表形式を指定して出力することもできる。


    プロンプト:

    ノートPCとデスクトップPCの違いをJSON形式でまとめてください。

    出力:

    {
      "ノートPC": {
        "特徴": [
          "携帯性が高い",
          "バッテリー駆動できる",
          "内蔵キーボードとタッチパッド/ポインティングスティックが付属",
          "通常、小型のディスプレイを備える"
        ],
        "利点": [
          "移動中や外出先での使用が便利",
          "コンパクトで場所を取らない",
          "電源コードに依存せずに使用可能"
        ],
        "欠点": [
          "一般的にデスクトップPCよりも性能が低い",
          "アップグレードが制限される場合がある",
          "熱管理が難しいことがある"
        ]
      },
      "デスクトップPC": {
        "特徴": [
          "大型で重い",
          "通常、外部ディスプレイとの接続が必要",
          "マウスとキーボードは別途購入が必要",
          "性能が高い"
        ],
        "利点": [
          "高性能のハードウェアを搭載可能",
          "アップグレードが容易",
          "冷却が効率的"
        ],
        "欠点": [
          "携帯性が低い",
          "場所を取る",
          "電源コードに依存するため、移動中は使用できない"
        ]
      }
    }

    「しないこと」ではなく「すること」を記述する

    「しないこと」ではなく「すること」を記述することで、表現がより具体的になり、効果的なプロンプトを設計できる。


    プロンプト(元):

    以下は、顧客に映画を推薦するエージェントです。興味を尋ねないで、個人情報を尋ねないでください。
    顧客:私の興味に基づいて映画をお勧めください。
    エージェント:

    出力:

    はい、どのジャンルの映画をお探しですか?

    プロンプト(改良後):

    以下は、顧客に映画を推薦するエージェントです。エージェントは、上位のグローバルトレンド映画から映画をお勧めする責任があります。ユーザーの好みを尋ねることを避け、個人情報を尋ねることを避ける必要があります。エージェントがおすすめ映画を持っていない場合は、「申し訳ありませんが、今日お勧めする映画が見つかりませんでした。」と返答する必要があります。
    顧客:私の興味に基づいて映画をお勧めください。
    エージェント:

    出力:

    申し訳ありませんが、私たちはユーザーの好みを尋ねることができません。上位のグローバルトレンド映画からお勧めすることができます。ただし、今日おすすめできる映画が見つからない場合があります。

    Zero-ShotとFew-Shot

    Zero-Shot

    大量のデータでトレーニングされた大規模言語モデルは、追加の学習なし(ゼロショット)でも、ある程度精度の高い回答を得られる。前述のプロンプトはすべてZero-Shotプロンプティングである。以下に典型的なZero-Shotプロンプティングの例を示す。


    プロンプト:

    以下の文章をネガティブ、ポジティブに分類してください。
    昨日行ったレストランの料理は美味しかった。

    出力:

    ポジティブ

    Few-Shot

    ゼロショットでは十分な精度の回答が得られないときは、プロンプト内でデモ(フューショット)を提供することでより高精度の回答が得られる場合がある。以下に典型的なFew-Shotプロンプティングの例を示す。


    プロンプト:

    Q:素晴らしい。
    A:ポジティブ
    Q:このUIは酷い。
    A:ネガティブ
    Q:あの本は最高だった。
    A:ポジティブ
    Q:なんてひどい音楽だ。
    A:

    出力:

    ネガティブ

    QA方式ではなく//方式で記載しても同様の結果が得られる。


    プロンプト:

    素晴らしい。 // ポジティブ
    このUIは酷い。 // ネガティブ
    あの本は最高だった。 // ポジティブ
    なんてひどい音楽だ。 //

    出力:

    ネガティブ

    その他のTips

    ステップバイステップでの回答

    大規模言語モデルの学習には論文のような論理的な文章と話し言葉のような直感的な文章が両方使われている。推論系のタスクの場合、「ステップバイステップ」という条件を追加することで、論理的な文章を参考に思考の連鎖を促して、最適な回答を得られるようになる場合がある。


    プロンプト(元):

    私はAさんからみかんを12個もらって、Bさんに3つ、Cさんに2つ渡しました。その後、Dさんに3つもらい、2つ食べました。残りは何個ですか?

    プロンプト(改良後):

    私はAさんからみかんを12個もらって、Bさんに3つ、Cさんに2つ渡しました。その後、Dさんに3つもらい、2つ食べました。残りは何個ですか?ステップバイステップで考えてみましょう。

    ただし、「ステップバイステップ」の魔法はGPT-3時代に発見されたものであるため、バージョンが上がるに連れて「ステップバイステップ」という条件を追加しなくても十分に高精度の回答が得られるようになっていると思われる。著者がChatGPT(GPT-3.5)で動作確認した範囲では、「ステップバイステップ」という条件を追加しても優位な差はみられなかった。

    ステップごとに具体的な指示を記載する

    「ステップバイステップ」という条件に加えて、「ステップごとの具体的な指示」や「論理的な思考の連鎖を促すような出力形式の指定」を追加することで、最適な回答を得られるようになる場合がある。

    以下の例では、3番の生徒の解答が正しいが、元のプロンプトでは「1番の生徒の解答が正しい」と判断してしまっている。改良後のプロンプトではきちんと「3番の生徒の解答が正しい」と判断できている。


    プロンプト(元):

    以下の問題に対する生徒の解答が、それぞれ正しいかどうかを判断してください。
    
    問題:
    以下の条件で、太陽光発電施設を建設したいと考えています。
    - 土地代は10万円/平方メートルかかる
    - ソーラーパネルは25万円/平方メートルで購入できる
    - メンテナンスの契約をしたのですが、その費用は年間1000万円で、さらに1平方メートルあたり1万円かかる
    運用開始1年目の総費用はいくらかを平方メートル数の関数として計算してください。
    
    1番の生徒の解答:
    設置場所の広さを平方メートルでxとする。
    コスト:
    1. 土地代:10x
    2. ソーラーパネル代:25x
    3. メンテナンス費用:1000+ 10x
    合計金額:10x+25x+1000+10x=45x+1000(万円)
    
    2番の生徒の解答:
    設置場所の広さを平方メートルでxとする。
    コスト:
    1. 土地代:10x
    2. ソーラーパネル代:25x
    3. メンテナンス費用:1000+ x
    合計金額:10x+25x+1000x+x=1036x(万円)
    
    3番の生徒の解答:
    設置場所の広さを平方メートルでxとする。
    コスト:
    1. 土地代:10x
    2. ソーラーパネル代:25x
    3. メンテナンス費用:1000+ x
    

    出力:

    1番の生徒の解答は正しいです。
    
    2番の生徒の解答は間違っています。メンテナンス費用は1平方メートルあたり1万円かかるので、x平方メートルの場合はx万円です。合計金額は45x + 1000(万円)です。
    
    3番の生徒の解答も間違っています。メンテナンス費用は1平方メートルあたり1万円かかるので、x平方メートルの場合はx万円です。合計金額は45x + 1000(万円)です。

    プロンプト(改良後):

    あなたの仕事は、生徒の解答が正しいかどうかを判断することです。この問題を解くには、次のようにします:
    - まず、あなた自身の解答を作成する。
    - 次に、あなたの解答と生徒の解答を比較し、生徒の解答が正しいかどうかを評価する。
    生徒の解答が正しいかどうかは、自分で問題を解いた後で判断してください。
    
    次のような形式で出力してください:
    問題の解答:<問題の解答をステップバイステップでここに記載します>
    生徒の番号:<生徒の番号をここに記載します>
    生徒の解答:<生徒の最終的な解答を一行でここに記載します>
    実際の解答:<実際の解答をここに記載します>
    生徒の成績:<生徒の解答が正しい場合「正解」、間違っている場合「不正解」と記載します>
    生徒の番号:<生徒の番号をここに記載します>
    以降、生徒の数だけ繰り返し出力します。
    
    問題:
    以下の条件で、太陽光発電施設を建設したいと考えています。
    - 土地代は10万円/平方メートルかかる
    - ソーラーパネルは25万円/平方メートルで購入できる
    - メンテナンスの契約をしたのですが、その費用は年間1000万円で、さらに1平方メートルあたり1万円かかる
    運用開始1年目の総費用はいくらかを平方メートル数の関数として計算してください。
    
    1番の生徒の解答:
    設置場所の広さを平方メートルでxとする。
    コスト:
    1. 土地代:10x
    2. ソーラーパネル代:25x
    3. メンテナンス費用:1000+ 10x
    合計金額:10x+25x+1000+10x=45x+1000(万円)
    
    2番の生徒の解答:
    設置場所の広さを平方メートルでxとする。
    コスト:
    1. 土地代:10x
    2. ソーラーパネル代:25x
    3. メンテナンス費用:1000+ x
    合計金額:10x+25x+1000x+x=1036x(万円)
    
    3番の生徒の解答:
    設置場所の広さを平方メートルでxとする。
    コスト:
    1. 土地代:10x
    2. ソーラーパネル代:25x
    3. メンテナンス費用:1000+ x
    合計金額:10x+25x+1000x+x=36x+1000(万円)

    出力:

    問題の解答:
    設置場所の広さを平方メートルでxとする。
    コスト:
    
    土地代:10x
    ソーラーパネル代:25x
    メンテナンス費用:1000 + x
    合計金額:10x + 25x + 1000 + x = 36x + 1000(万円)
    
    生徒の番号:1
    生徒の解答:45x + 1000
    実際の解答:36x + 1000
    生徒の成績:不正解
    
    生徒の番号:2
    生徒の解答:1036x
    実際の解答:36x + 1000
    生徒の成績:不正解
    
    生徒の番号:3
    生徒の解答:36x + 1000
    実際の解答:36x + 1000
    生徒の成績:正解
    

    情報なしという回答

    大規模言語モデルでは、次の単語を予測して確率が高い単語を選び文章を生成しているだけなので、回答の中に間違った情報を含んでいる場合もある。情報がない場合は「情報がありません」と回答するように指定することで、最適な回答を得られるようになる場合がある。


    プロンプト(元):

    枠単回帰とはなんですか?

    出力:

    枠単回帰とは、統計学および機械学習の手法の一つであり、1つの説明変数を使用して目的変数を予測する回帰分析の手法です。枠単回帰では、説明変数と目的変数の間の線形な関係を仮定し、その関係を表す回帰直線を求めます。この回帰直線を使用して、与えられた説明変数の値に基づいて目的変数の値を予測することができます。枠単回帰は単純なモデルですが、説明変数と目的変数の関係を理解するための基本的な手法として広く使用されています。

    プロンプト(改良後):

    Q:原子とはなんですか?
    A:原子は身の回りのあらゆるものを構成する微小粒子で、原子核とその周りを回る電子から構成されています。
    Q:縞々島とはなんですか?
    A:情報がありません。
    Q:太陽系には何個の惑星がありますか?
    A:水星、金星、地球、火星、木星、土星、天王星、海王星の8個の惑星が存在します。
    Q:合祀練度とはなんですか?
    A:情報がありません。
    Q:枠単回帰とはなんですか?
    A:

    出力:

    情報がありません。

    回答が途中で切れる場合

    回答が途中で切れた場合、「続き」や「go on」などと入力すると回答の続きが生成される。ただし、長文になるほど関連性が弱く、つじつまが合わない文章が生成されるため、短く端的に出力できるプロンプトを作成し直す方が好ましい。


    プロンプト:

    続き
    go on

    変数と関数

    変数や関数を定義して、使い回すことができる。また、for文も使用できる。


    プロンプト(変数の利用):

    [テーマ]:意識
    
    [テーマ]について100文字程度で説明してください。

    出力:

    意識:知覚、認識、感情、思考などの心的状態や主体性の体験を指す心の現象。個体が自己や周囲の存在に気づき、意図的な行動を起こす能力を包括する。

    プロンプト(関数の利用):

    [説明]([テーマ]){
        [テーマ]について100文字程度で説明してください。
    }
    
    [説明]([テーマ]="メタ認知")を実行

    出力:

    メタ認知:自己の認識や思考プロセスを対象とした認知能力。自己監視、反省、計画立案などの高次の認知活動を含む。

    プロンプト(for文の利用):

    for i in ["テロ","お菓子","人間"]:
        print([説明]([テーマ]=i))

    出力:

    テロ: 暴力や脅威を通じて政治的・社会的な目的を達成しようとする行為。
    お菓子: 食べ物の一種であり、主に甘い味や楽しみを提供するために作られる。
    人間: ヒト属に属する生物で、高度な知能、言語能力、文化創造、情報伝達能力などを持つ。

    分岐させる

    分類問題などと組み合わせて、条件によって分岐させることもできる。


    プロンプト(ポジティブな文章):

    以下の文章の内容がネガティブかポジティブかを判定し、ポジティブな内容なら別の映画を勧める文章を、ネガティブな内容なら別の娯楽を勧める文章を生成してください。
    
    あの映画はとても面白かった。また見に行きたいよ。

    出力:

    この文章はポジティブな内容です。
    
    ポジティブな内容なので、別の映画を勧める文章を生成します。
    
    もし面白い映画を探しているのであれば、「インセプション」という映画がおすすめです。この映画は、夢の中での盗みを描いたサスペンス作品で、複雑なストーリーとスリリングな展開が特徴です。ぜひ楽しんで観てみてください!

    プロンプト(ネガティブな文章):

    以下の文章の内容がネガティブかポジティブかを判定し、ポジティブな内容なら別の映画を勧める文章を、ネガティブな内容なら別の娯楽を勧める文章を生成してください。
    
    あの映画はつまらなかった。時間の無駄だったよ。

    出力:

    この文章はネガティブな内容です。
    
    ネガティブな内容なので、別の娯楽を勧める文章を生成します。
    
    映画がつまらなかったようですね。それでは、読書をおすすめします。本を読むことは、想像力を刺激し、新たな世界や物語に没頭する素晴らしい娯楽です。ジャンルや興味のあるテーマに基づいて、本屋さんやオンラインでお気に入りの本を見つけてみてください。きっと新たな発見や楽しみが待っているはずです。

    参考資料


    著者画像

    ゆうき

    2018/04からITエンジニアとして活動、2021/11から独立。主な使用言語はPython, TypeScript, SAS, etc.