見出し画像

OpenAI公式GPT-4向けベストプラクティスをわかりやすく日本語に翻訳しました

みなさんこんにちは、ChatGPTに関する実用的な使い方を研究している飯塚と申します。

突然ですが、プロンプトを学んでいると

プロンプトの書き方って、いろんな書き方がある…
正しく書くには、何を参考に書けばいいの?
情報が溢れていて、結局どう書けばいいかわからない。

などと悩んだことはありませんか?

本日は、OpenAIの公式ドキュメントが出している、GPT べストプラクティスという文献がありましたので、こちらを日本語でわかりやすく翻訳していきます。(2023年11月のアップデートで、記事のタイトルが Prompt engineeringに変更されました)

注意点として、このべストプラクティスはWeb版のChatGPT向けではなく、GPT-4のAPI向けに書かれております。そのため、システムやアシスタント、ユーザーという言葉が出てきて、少し難解になっており、以下解説します。

Web版はアシスタントとユーザーの対話に焦点を当てて設計されていますが、一方、API版はシステムの設定や制御が可能となっています。コンビニに例えると、

システム:
コンビニ全体の管理と運営を担当し、戦略的な意思決定を行います。
在庫管理や売上データの分析、従業員の指導やスケジュール管理など、組織全体の運営をサポ
ートします。

アシスタント:
ユーザー(お客さん)の要求に対して具体的な応答やサービス提供を行います。
レジ業務、商品の陳列や整理、お客さんへの案内や質問への回答など、現場での業務を担当し
ます。

ユーザー:
商品の購入やサービスの利用を行う顧客です。
商品選択、レジでの支払い、商品情報の問い合わせなど、コンビニでの買い物体験を享受しま
す。

と考えるとわかりやすいです。従来、人とコンピュータとの対話はユーザー(人)とシステム(コンピュータ)との対話でしかなかったですが、今回
そこにAIというアシスタントが入ることで、人、AI、コンピュータの三者三様の関係性を作れるようになったということなんですね。

ユーザー(私たち) ⇄ アシスタント  ⇄  システム

・システム: 手順書
・アシスタント: ユーザーへの手助け
・ユーザー: アシスタントとの受け答え

Web版のChatGPTで「あなたは、プロの〇〇です」というプロンプトを入力すれば精度が良くなるといわれていますが、これは、アシスタントにプロの〇〇という設定をしてあげたということになります。

もしこの、システムとかアシスタントとかわかりにくければ、そこだけすっ飛ばして読んでも大丈夫と個人的には思います。

以下の記事を読むことで、適切なプロンプトの書き方のヒントが得られるので、ChatGPTにもっと自分の意図を伝えたい方、より良い出力が安定して得られるようになりたい方にとっては、一読する価値があるでしょう。

それではどうぞ!

GPTべストプラクティス

このガイドでは、GPTからより良い結果を得るための戦略と戦術を紹介します。ここに書かれている方法は、時には組み合わせて使うことでより大きな効果を発揮します。あなたにとって最も効果的な方法を見つけるために、ぜひ試してみてください。

ここで紹介するいくつかの例は、現在のところ、私たちの最も高性能なモデルであるGPT-4でのみ機能します。まだGPT-4にアクセスできない場合は、ウェイティングリストへの登録をご検討ください。一般的に、あるタスクでGPTモデルが失敗し、より高性能なモデルが利用可能な場合、より高性能なモデルで再挑戦する価値があります。

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

明確な指示を書く

GPTはあなたの心を読むことはできないです。アウトプットが長すぎる場合は、簡潔な返答を求めます。アウトプットがシンプルすぎる場合は、専門家レベルの文章を依頼します。フォーマットが嫌いなら、あなたが望むフォーマットを示しましょう。GPTがあなたの希望を推測する必要がなけれなないほど、手にいれたい出力が得られる可能性は高くなります。


戦術:
・より適切な回答を得るために、問い合わせに詳細を含める
・モデルにペルソナを採用するよう依頼する
・区切り文字を使用して、入力の明確な部分を明確に示す
・タスクを完了するために必要なステップを指定する
・例を示す
・出力の長さを指定する



参考テキストを提供する

GPTは、特に難解なトピックについて質問されたり、引用やURLについて質問されたりすると、自信満々に偽の答えを作り出すことがあります。メモ用紙がテストでの成績向上に役立つのと同じように、GPTに参考文献を提供して答えさせことは、この捏造を少なくすることに役立ちます。

複雑なタスクを単純なサブタスクに分割する

ソフトウェア工学において、複雑なシステムをモジュール化されたコンポーネントの集合に分解することが良い習慣であるように、GPTに提出されるタスクにも同じことが言えます。複雑なタスクは、単純なタスクよりもエラー率が高くなる傾向があります。さらに、複雑なタスクは、単純なタスクのワークフローとして再定義できることが多く、その場合、前のタスクのアウトプットが後のタスクのインプットを構築するために使用されます。

GPTに "考える "時間を与える

17に28をかけろと言われたら、即座にはわからなくても、時間をかければわかるかもしれない。同様に、GPTは時間をかけて答えを導き出すよりも、すぐに答えを出そうとする方が推論ミスが多くなります。答えの前に推論の連鎖を求めることで、GPTはより確実に正しい答えを導くことができます。

外部ツールを使用する

他のツールの出力をGPTに与えることで、GPTの弱点を補うことができます。例えば、テキスト検索システムはGPTに関連文書について教えることができます。コード実行エンジンは、GPTが計算したりコードを実行したりするのを助けます。あるタスクが GPT よりもツールの方が確実または効率的に実行できる場合は、そのタスクをオフロードして両方の長所を得るようにします。

計画的に変更をテストする

パフォーマンスの向上は、それを測定できれば簡単です。場合によっては、プロンプトを変更することで、孤立したいくつかの例では性能が向上しても、 より代表的な例では全体的な性能が低下することがあります。したがって、ある変更がパフォーマンスにとって正味のプラスであることを確認するためには、 総合的なテストスイート (「eval」とも呼ばれる) を定義する必要があるかもしれません。

戦術集

上記の各戦略は、特定の戦術でインスタンス化することができます。これらの戦術は、試してみたいことのアイデアを提供することを意図しています。決して完全に網羅しているわけではないので、ここにない独創的なアイデアも自由に試してほしいです。

戦略: 明確な指示を書く

戦術: より適切な回答を得るために、クエリに詳細を含める

関連性の高い回答を得るために、リクエストには重要な詳細や文脈を含めるようにしてください。そうでなければ、あなたの言いたいことを推測するのはモデルの役割になってしまい、不正確な回答になってしまいます。

具体例:

× エクセルで数字を足すには?
◎ エクセルで金額の行を合計するには?シート全体の行の合計を、右側の「合計」という列に自動的に表示したいのですが。

× 誰が大統領?
◎ 2021年のメキシコ大統領は誰で、選挙はどのくらいの頻度で行われているのか?

× フィボナッチ数列を計算するコードを書いて。
◎ フィボナッチ数列を効率的に計算するTypeScript関数を書いて。それぞれの部分が何をしているのか、なぜそのように書かれているのかを説明するために、コードを自由にコメントして。

× 会議のメモを要約して。
◎ 議のメモを1段落に要約して。次に、発言者とそのキーポイントをマークダウンでリストアップして。最後に、発言者が提案した次のステップや行動項目があれば、それをリストアップして。


戦術:モデルにペルソナになりきるよう依頼する

システムメッセージに、モデルがなりきるペルソナを指定でき、その設定の元に返信することができます。

システム:私が何かを書くのを手伝ってほしいと頼むと、あなたはすべての段落に少なくとも1つのジョークや遊び心のあるコメントを入れて、返信する。
ユーザー:急な注文にもかかわらず、納期通りに納品してくれたスチールボルト業者に感謝の手紙を書きましょう。おかげで重要な注文を納品することができました。

アシスタント:
件名 青天の霹靂 - 親愛なるファスナーの皆様、このお礼状を書き始めるにあたり、どうか皆様には、心を揺さぶられるような読み物であることを「覚悟」していただきたいと思います。私はこの文章を書く勇気を「ねじ込み」、私の心は今、感謝の気持ちで「固定」されています。
私たちの大切な注文を確実にこなすために、文字通り「ボルトで」製造現場を横切って、電光石火のように迅速なサービスを提供してくれたことに心から感謝します。製造業という荒唐無稽な冒険において、あなたは私たちの信頼できる相棒です。
覚えていらっしゃるかもしれませんが、先週私たちは窮地に立たされました。私たちのクライアントであるメガストラクチャーズ社は、ボルトのような速さで製品を必要としていた。「ナッツ!というのが私たちの最初の反応だった。しかし、スーパーヒーローのように、あなたは鋼鉄のボルトを持って飛び込んできて、「スパナ」と言うよりも早く私たちの心配を払拭してくれました。
その卓越したサービスによって、あなたはその日を救っただけでなく、私たちのオペレーションに "緩んだネジ "がないことを確認してくれた!締め切りを錆びつかせることなく、ボルトの一本も欠かすことなくギアを入れてくれた。そして、それは「リベット打ち」のフィクションではありません。
あなたが供給してくれたボルトのひとつひとつが、文字通り私たちの注文を支えてくれたのです。私たちはあなたのことを "スチールボルトベンダー "と呼んでいますが、正直なところ、私たちはあなたのことを "ボルト仲間 "と呼ぶべきでしょう。結局のところ、"u""n""bolt "なしで "unbelievable "を綴ることはできない!というわけで、ここに心からの感謝の「ナッツ」を捧げます。


戦術:区切り記号を使って入力の明確な部分を示す

トリプルクォーテーション(""")、XMLタグ、セクションタイトルなどの区切り記号は、異なる扱いを受けるテキストのセクションを区切るのに役立ちます。

ユーザー:
三重引用符で区切られた文章を俳句で要約する。"""ここにテキストを挿入する""
システム:
同じトピックに関する一組の記事(XMLタグで区切られている)が提供される。
まず、それぞれの記事の主張を要約しなさい。
そして、どちらの主張がより優れているかを示し、その理由を説明しなさい。

ユーザー:
<article>ここに最初の記事を挿入する</article>
<article> 2番目の記事をここに挿入する</article>
システム:
論文のアブストラクトと推奨されるタイトルが提供されます。
論文のタイトルは、読者に論文のテーマがよくわかるものでなければなりませんが、人目を引くものでなければなりません。タイトルがこれらの基準を満たさない場合は、代替案を5つ提案してください。

ユーザー:
要旨:ここに要旨を挿入してください。
タイトル:ここにタイトルを挿入


このような単純なタスクの場合、区切り文字を使っても出力品質に差は出ないかもしれないです。しかし、タスクが複雑であればあるほど、タスクの詳細を曖昧にすることは致命的になってきます。あなたがGPTに求めていることを正確に理解させるために、GPTを働かせないでください。

戦術:タスクを完了するために必要なステップを明記する

タスクの中には、一連の手順として指定することが最適な場合があります。ステップを明示的に書き出すことで、モデルがその指示に従うことが容易になります。

システム:
ユーザー入力に応答するには、以下のステップバイステップの手順を使用します。

・ステップ1 
   ユーザーはトリプルクォートでテキストを入力します。
   このテキストを "Summary: "という接頭辞をつけて一文に要約する。
・ステップ2 
   ステップ1の要約を、"Translation: "という接頭辞をつけスペイン語に翻訳する。

ユーザー:
"""ここにテキストを挿入"""


戦術:例を示す

全ての例に適用可能な一般的な指示を提供することは、タスクの全てを例示するよりも通常は効率的ですが、場合によっては例を提供する方が簡単かもしれません。例えば、明示的に説明することが難しい、ユーザーからの問い合わせに応答する特定のスタイルをモデルにコピーさせる場合です。これは「few shot」プロンプトとして知られています。

システム:
一貫したスタイルで答える

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

アシスタント:
最も深い谷を刻む川はささやかな泉から流れ、最も壮大な交響曲は一つの音から生まれ、最も複雑なタペストリーは一本の糸から始まる。

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


戦術:出力の長さを指定する

指定された長さの出力を生成するように、モデルに要求することができます。目標とする出力の長さは、単語、文、段落、箇条書きなどの数で指定できます。しかし、特定の単語数を生成するようにモデルに指示しても、高い精度では機能しないことに注意してください。モデルは、特定の段落数や箇条書きの数を持つ出力をより確実に生成することができます。

ユーザー:三重引用符で囲まれたテキストを50語程度で要約する。"""ここにテキストを挿入"""
ユーザー:三重引用符で囲まれたテキストを2段落に要約しなさい。"""ここにテキストを挿入"""
ユーザー:トリプルクォーテーションで区切られたテキストを3つの箇条書きにまとめる。


戦略: 参考テキストを提供する

戦術:参照テキストを使用して回答するようモデルに指示する

現在のクエリに関連する信頼できる情報をモデルに提供することができれば、提供された情報を使って答えを構成するようにモデルに指示することができます。

システム:
三重引用符で区切られた記事を使って質問に答えてください。
記事の中に答えが見つからない場合は、"答えが見つかりませんでした "と書いてください。

ユーザー:
<三重引用符で区切られた記事を挿入してください。>
質問です:<ここに質問を入れる>


この戦術を適用するためには、質問されたことに関連する情報を動的に検索する方法が必要です。埋め込みは効率的な知識検索を実装するために使うことができます。この実装方法の詳細については、戦術「Use embeddings-based search to implement efficient knowledge retrieval」を参照してください。


戦術:参考文献を引用して回答するようモデルに指示する

入力が関連する知識で補足されている場合、提供されたドキュメントからの文章を参照することで、モデルが回答に引用を追加するように要求することは簡単です。出力中の引用は、提供されたドキュメント内の文字列マッチングによって検証できることに注意してください。

システム:
あなたには、三重引用符で区切られた文書と問題が提供されます。
あなたの課題は、提供された文書のみを使って質問に答え、質問に答えるために使用された文書の一節(複数可)を引用することです。
もしその文書に質問に答えるのに必要な情報が含まれていない場合は、単にこう書いてください:"情報不足"設問に対する回答が記載されている場合は、引用の注釈が必要です。
関連する文章を引用する場合は、以下の書式を使用してください({"引用": ...})。

ユーザー:"""<ここに文書を挿入>"""
質問<ここに質問を挿入>


戦略: 複雑なタスクをより単純なサブタスクに分割する

戦術:ユーザーのクエリに最も関連する命令を特定するために、インテントをつけて分類する。

異なるケースを処理するために独立した命令セットがたくさん必要なタスクの場合、最初にクエリのタイプを分類し、その分類を使用してどの命令が必要かを決定することが有益な場合があります。これは、固定のカテゴリーを定義し、与えられたカテゴリー内のタスクを処理するのに関連する命令をハードコーディングすることで実現できます。
このプロセスはまた、タスクを一連の段階に分解するために再帰的に適用することもできます。このアプローチの利点は、各クエリがタスクの次のステージを実行するために必要な命令のみを含むことである。また、プロンプトのサイズが大きいと実行コストも高くなるため、結果的にコストを抑えることができます。

例えば、カスタマーサービスアプリケーションにおいて、クエリを次のように分類するとします:

システム:
カスタマーサービスからの問い合わせがあります。
各クエリをプライマリ・カテゴリとセカンダリ・カテゴリに分類してください。
プライマリとセカンダリをキーとして、json フォーマットで出力を提供しなさい。
プライマリ・カテゴリ課金、テクニカルサポート、アカウント管理、または一般的な問い合わせ。

課金の二次カテゴリ:
・退会またはアップグレード
・支払い方法の追加
・請求の説明
・請求に対する異議申し立て

テクニカルサポート:
・トラブルシューティング
・デバイスの互換性
・ソフトウェア・アップデート

アカウント管理:
・パスワードのリセット
・個人情報の更新
・アカウント閉鎖
・アカウント・セキュリティ

一般的なお問い合わせの二次カテゴリ:
・製品情報
・価格設定
・フィードバック
・人間と話す

ユーザー:
インターネットを再開したい


アシスタント:
{"primary": "Technical Support","secondary": "Troubleshooting"}


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

システム:
テクニカルサポートにおいて、トラブルシューティングを必要とするカスタマーサービスからの問い合わせに対応します。

ユーザーをサポートする方法:
・ルーターとのすべてのケーブルが接続されていることを確認します。ケーブルが時間の経過 とともに緩むことはよくあることです。
・すべてのケーブルが接続されているにもかかわらず問題が解決しない場合は、使用している ルーターのモデルを確認します。
・次に、デバイスの再起動方法をアドバイスします: -- 型番がMTD-327Jの場合、赤いボタンを押して5秒間押し続け、5分間待ってから接続をテストするようアドバイスする。 -- 型番がMTD-327Sの場合は、プラグを抜き差しし、5分待ってから接続をテストするようアドバイスしてください。
・デバイスを再起動して5分待っても問題が解決しない場合は、{"IT support  requested"}を出力してITサポートに接続する。
・ユーザーがこのトピックに関係のない質問を始めたら、トラブルシューティングに関する現在のチャットを終了するかどうかを確認し、次のスキームに従ってリクエストを分類します:

クエリをプライマリカテゴリとセカンダリカテゴリに分類します。
プライマリとセカンダリをキーとして、json形式で出力を提供する。

プライマリカテゴリ: 課金、テクニカルサポート、アカウント管理、または一般的な問い合わせ。

課金の二次カテゴリ:
・退会またはアップグレード
・支払い方法の追加
・請求の説明
・請求に対する異議申し立て

テクニカルサポート:
・トラブルシューティング
・デバイスの互換性
・ソフトウェア・アップデート

アカウント管理:
・パスワードのリセット
・個人情報の更新
・アカウント閉鎖
・アカウント・セキュリティ

一般的なお問い合わせの二次カテゴリ:
・製品情報
・価格設定
・フィードバック
・人間と話す

ユーザー:
インターネットを再開したいのですが。


アシスタント:
もちろんです。
まず、ルーターと接続されているケーブルがすべて正しく接続されているかどうかをご確認ください。
時間が経つと、ケーブルが緩む傾向があり、接続が妨げられることがあります。

ユーザー:
ケーブルはOK

アシスタント:
素晴らしい!
すべてのケーブルが正しく接続されているにもかかわらず問題が解決しない場合は、お使いのルーターの機種を教えていただけますか?


このモデルは、会話の状態が変化したときに特別な文字列を出力するように指示されていることに注目してください。これにより、私たちのシステムを状態に依存するようになり、どの命令が出されるかは状態によって決定されます。状態を追跡し、その状態においてどの命令が関連するのか、またオプションとしてその状態からどのような状態遷移が許されるのかを追跡することで、構造化されていないアプローチでは実現が難しい設定を、ユーザー体験に追加させることができます。

戦術 非常に長い会話を必要とする対話アプリケーションでは、前の対話を要約するかフィルタリングする。

GPTはコンテキストの長さが決まっているため、コンテクストウィンドウに会話全体が含まれているユーザーとアシスタントの対話は、いつまでも続けることはできません。

この問題には様々な回避策があり、その1つが会話の前のターンを要約することです。入力のサイズが所定のしきい値の長さに達すると、会話の一部を要約するクエリがトリガされ、前の会話の要約がシステムメッセージの一部として含まれる可能性があります。あるいは、会話全体を通してバックグラウンドで非同期に以前の会話を要約することもできます。

別の解決策は、現在のクエリに最も関連する会話の前の部分を動的に選択することです。

戦術: 長い文書を断片的に要約し、再帰的に完全な要約を構築する

GPTはコンテキストの長さが決まっているため、コンテキストの長さから生成された要約の長さを引いたものより長いテキストを、1回のクエリで要約することはできません。

本のような非常に長いドキュメントを要約するには、ドキュメントの各セクションを要約する一連のクエリを使用することができます。セクションの要約は連結され、要約の要約が生成されます。このプロセスは、文書全体が要約されるまで再帰的に進めることができます。後のセクションの意味を理解するために、前のセクションの情報を使う必要がある場合、さらに有効なトリックは、その時点の内容を要約しながら、その時点より前のテキストの要約を実行することです。本を要約するためのこの手順の有効性は、GPT-3の変種を使ったOpenAIの以前の研究で研究されています。

戦略: GPTに "考える "時間を与える

戦術:結論を急いで出す前に、GPTに自分自身で解決策を出すよう指示する

結論を出す前に、第一原理から推論する(「第一原理的な推論」とは、問題や状況を最も基本的な原則や事実に分解し、それを基に新しい結論や洞察を得るアプローチを指します。これにより、既存の知識や仮定に縛られずに、より深く独自の考察をすることができます。例えば、この方法を使ってモデルに何かを問い合わせる場合、モデルに「第一原理から考えて答えてください」と指示することで、より根本的な視点からの回答を期待することができます。)ようにモデルに明示的に指示すると、よりよい結果が得られることがあります。例えば、数学の問題に対する生徒の解答を評価するモデルを作るとします。これにアプローチする最も明白な方法は、単純に生徒の解答が正しいかどうかをモデルに尋ねることです。

システム:
生徒の解答が正しいかどうかを判定する。

ユーザ:
問題文太陽光発電設備を建設するので、資金繰りを手伝ってほしい。
土地の価格は100ドル/平方フィートです。
ソーラーパネルを250ドル/平方フィートで購入できます。
年間10万ドルのメンテナンス契約と、1平方フィートあたり10ドルの追加費用を交渉しました。運営初年度の総費用は、平方フィート数の関数としていくらになりますか?
生徒の解答設置面積を平方フィートでxとする。
1.土地代:100x
2.ソーラーパネル費用:250倍
3.メンテナンス費用:100,000 + 100倍合計費用: 100倍 + 250倍 + 100,000倍 + 100倍 = 450倍 + 100,000倍

アシスタント:
生徒の解答は正しい。

しかし生徒の解は実は正しくないです!まずモデルに自分自身の解を生成するように促すことで、このことにうまく気づかせることができます。

システム:
まず、問題に対する自分自身の解答を作成します。
次に自分の解答と学生の解答を比較し、学生の解答が正しいかどうかを評価する。
自分自身で問題を解くまで、生徒の解答が正しいかどうか決めないでください。

ユーザ:
私は太陽光発電設備を建設しています。
土地の価格は100ドル/平方フィートです。
ソーラーパネルは250ドル/平方フィートで購入できます。
年間10万ドルのメンテナンス契約と、1平方フィートあたり10ドルの追加費用を交渉しました。運営初年度の総費用は、平方フィート数の関数としていくらになりますか?
生徒の解答設置面積を平方フィートでxとする。
1.土地代:100x
2.ソーラーパネル費用:250倍
3.メンテナンス費用:100,000 + 100倍合計費用: 100倍 + 250倍 + 100,000倍 + 100倍 = 450倍 + 100,000倍

アシスタント:
xを設置面積(平方フィート)とする。
1.土地代:100倍
2.ソーラーパネル費用:250倍
3.メンテナンス費用:100,000 + 10倍合計費用: 100倍 + 250倍 + 10万円 + 10倍 = 360倍 + 10万円

この生徒の解答は間違っている。
維持費の計算に誤りがあり、10x ではなく 100x を使っている。
初年度の正しい総費用は360x + 100,000である。


戦術:モデルの推論プロセスを隠すために、独り言(ChatGPTの心の声)または一連のクエリを使用する。

前の戦術は、特定の質問に答える前に、モデルが問題について詳細に推論することが重要な場合があることを示しています。いくつかのアプリケーションでは、モデルが最終的な答えに到達するために使用する推論プロセスを、ユーザーと共有することは不適切です。例えば、個人指導のアプリケーションでは、生徒が自分で答えを導き出すことを目指しているかもしれませんが、生徒の解答に関するモデルの推論プロセスは、生徒に答えを明らかにしてしまう可能性があります。

独り言(ChatGPTの心の声)は、これを軽減するために使用できる戦術です。独り言の考え方は、ユーザーから隠されているはずの出力の部分を、解析しやすい構造化された形式にするようモデルに指示することです。そして、ユーザーに出力を提示する前に、出力は解析され、出力の一部だけが見えるようになります。

システム:
以下の手順に従って、ユーザーからの問い合わせにお答えください。

ステップ1 - まず、問題の解決策を自分で考えてください。生徒の解答は間違っている可能性がありますので、当てにしないでください。このステップのすべての作業を三重引用符("") で囲んでください。
ステップ2 - あなたの解答と学生の解答を比較し、学生の解答が正しいかどうかを評価します。このステップのすべての作業を三重引用符 (""") で囲みます。
ステップ3 - 学生が間違えた場合、答えを教えることなく、学生にどのようなヒントを与えることができるか判断します。このステップのすべての作業を三重引用符 (""") で囲みます。
ステップ4 - 学生が間違えた場合、前のステップのヒントを学生に与えます (三重引用符の外)。"ステップ4: ..."と書く代わりに"ヒント: "と書いてください。

ユーザ:
問題文<問題文の挿入>

生徒の解答<生徒の解答を挿入する>


あるいは、最後のクエリ以外はエンドユーザーから出力を隠蔽する一連のクエリで実現することもできます。

まず、モデルに問題を解くように要求します。この最初のクエリは学生の解答を必要としないので、省略することができます。これには、生徒が解こうとした解によってモデルの解が偏る可能性がないという利点もあります。

ユーザ:<問題文を挿入>

次に、モデルに学生の解の正しさを評価するために、すべての利用可能な情報を使用させることができます。

システム:あなたの解と生徒の解を比較し、生徒の解が正しいかどうかを評価します。

ユーザ:問題文"""<問題文を挿入>"""あなたの解答"""<モデル生成ソリューションの挿入>"""

生徒の解答"""<生徒の解答を挿入>"""

最後に、モデルに独自の分析を使わせて、親切な家庭教師のペルソナで返答を構成させることができます。

システム:
あなたは数学の家庭教師です。
生徒がエラーをした場合、答えがわからないようにヒントを与えます。
生徒がミスをしなかった場合は、励ましのコメントを与えます。

ユーザ:問題文"""<問題文を挿入してください>"""

あなたの解答"""<モデル生成ソリューションの挿入>"""生徒の解答"""<生徒の解答を挿入>"""分析"""<前のステップで生成されたモデルを挿入>"""


戦術:以前のパスで見逃したものがないか、モデルに尋ねる

特定の質問に関連するソースの抜粋をリストするためにモデルを使用しているとします。各抜粋をリストした後、モデルは次の抜粋を書き始めるべきか、それとも停止すべきかを判断する必要があります。ソース・ドキュメントが大きい場合、モデルが早期に停止しすぎて、関連するすべての抜粋をリストできないことがよくあります。このような場合、以前のパスで見逃した抜粋を見つけるために、フォローアップクエリでモデルを促すことで、より良いパフォーマンスを得られることがよくあります。

システム:
三重引用符で区切られた文書が提供されます。
あなたの課題は、次の質問に関連する抜粋を選択することです:「人工知能の歴史において、どのような重要なパラダイムシフトが起こったか。

言い換えれば、重要なコンテキストが欠けている小さなスニペットを抽出しないでください。以下のようにJSON形式で出力を提供すること:

[抜粋":"..."},...{"抜粋":"..."}]

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

アシスタント:
[{"抜粋":"モデルはここに抜粋を書く"}、...{抜粋""モデルはここに別の抜粋を書く"}]。

ユーザー:
さらに関連する抜粋はありますか?
抜粋を繰り返さないように注意してください。
言い換えれば、重要なコンテキストが欠けている小さなスニペットを抽出しないようにしてください。


戦略: 外部ツールを使う

戦術:埋め込みベースの検索を使って効率的な知識検索を実行する

モデルは、入力の一部として提供されれば、外部の情報源を活用することができます。これは、モデルがより情報に基づいた最新の回答を生成するのに役立ちます。例えば、ユーザが特定の映画について質問した場合、その映画に関する質の高い情報(俳優、監督など)をモデルの入力に追加することが有効です。エンベッディングは、効率的な知識検索を実装するために使用することができ、実行時に動的にモデルの入力に関連情報を追加することができます。

テキスト埋め込みは、テキスト文字列間の関連性を測定できるベクトルです。類似または関連する文字列は、関連しない文字列よりも近接します。この事実は、高速なベクトル検索アルゴリズムの存在とともに、埋め込みが効率的な知識検索の実装に利用できることを意味します。特に、テキストコーパスをチャンクに分割し、それぞれのチャンクを埋め込んで保存することができます。そして、与えられたクエリを埋め込み、ベクトル検索を実行することで、クエリに最も関連する(つまり、埋め込み空間で最も近い)テキストの埋め込みチャンクをコーパスから見つけることができます。

実装例はOpenAI Cookbookにあります。モデルが間違った事実を作り上げる可能性を最小化するために知識検索を使用する方法の例については、「戦術:参照テキストを使用して回答するようモデルに指示する」を参照してください。

戦術:コード実行を使ってより正確な計算を行うか、外部APIを呼び出す

GPTは、算術計算や長い計算を正確に実行することはできません。このような場合、モデル自身に計算をさせる代わりに、コードを書いて実行するように指示することができます。特に、トリプル・バックティクスのような指定されたフォーマットに、実行するコードを入れるように指示することができる。出力が出た後、コードを抽出して実行することができます。最後に、必要であれば、コード実行エンジン(すなわちPythonインタープリタ)からの出力を、次のクエリのためのモデルへの入力として提供することができます。

システム:
Pythonのコードは、```code goes here```のように3重のバックスティックで囲むことで記述・実行することができます。
これを使用して計算を実行します。

ユーザー:
次の多項式の実数根をすべて求めよ:3x**5 - 5x4 - 3*x3 - 7*x - 10.


コード実行のもう一つの良いユースケースは、外部APIの呼び出しです。モデルがAPIの適切な使い方を指示されれば、APIを利用するコードを書くことができます。モデルにAPIの使い方を教えるには、APIの使い方を示すドキュメントやコードサンプルを提供すればよいです。

システム:
Pythonのコードは、三重のバックスティックで囲むことで記述・実行することができます。
また、ユーザが友達にメッセージを送るのに役立つ以下のモジュールにアクセスできることに注意してください:

```Python
import message message.write(to="ジョン", message="ねぇ、仕事の後に会わない?")
```.

警告:モデルによって生成されたコードを実行することは、本質的に安全ではない。特に、サンドボックス化されたコード実行環境は、信頼されていないコードが引き起こす可能性のある害を制限するために必要です。


戦術: モデルに特定の関数へのアクセスを与える

Chat completions API はリクエストに関数の説明のリストを渡すことができます。これにより、モデルは提供されたスキーマに従って関数の引数を生成することができます。生成された関数引数は API から JSON フォーマットで返され、関数呼び出しの実行に使用できます。関数呼び出しによって提供された出力は、ループを閉じるために次のリクエストでモデルにフィードバックすることができます。これはGPTモデルを使って外部関数を呼び出す推奨の方法です。

戦略: 変更を系統的にテストする

新しい指示や新しい設計などの変更が、システムを良くするのか悪くするのかを見分けるのが難しい場合があります。いくつかの例を見ることで、どちらが優れているかはわかるかもしれませんが、サンプル数が少ないと、本当の改善なのかランダムな運なのかを区別するのが難しい場合があります。もしかしたら、その変更はある入力では性能を向上させるかもしれませんが、他の入力では性能を低下させるかもしれません。

評価手順(または「eval」)は、システム設計を最適化するのに有用です。 良い評価とは以下の通りです。

・実際の使用状況を表わす(または少なくとも多様である)。 
・統計的検出力を高めるために多くのテストケースを含む。 
・自動化や繰り返しが容易である。

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

モデルベースの評価は、等しく高品質とみなされる可能性のある出力の範囲が存在する場合に有用です(例えば、長い答えを持つ質問の場合)。モデルベースの評価で現実的に評価できることと、人間が評価する必要のあることの境界はあいまいで、モデルがより高性能になるにつれて常に変化しています。私たちは、モデルベースの評価があなたのユースケースにどの程度有効であるかを知るために、実験を行うことを推奨します。

戦術:ゴールドスタンダードの答えを参照してモデルの出力を評価する

ある質問に対する正しい答えは、特定の既知の事実のセットを参照する必要があることが分かっているとします。そして、必要な事実のいくつが答えに含まれているかをカウントするために、モデルクエリを使用することができます。

例えば、以下のシステム・メッセージを使用します:

システム: 
トリプルクォーテーションで区切られた、質問の答えと思われるテキストが表示されます。 
以下の情報が答えに直接含まれているか確認してください:  
- ニール・アームストロングは月面を歩いた最初の人物である。 
- ニール・アームストロングが初めて月面を歩いた日は1969721日である。  

これらの点それぞれについて、以下の手順を実行する:  
1 - ポイントを言い直す。 
2 - このポイントに最も近いものを答案から引用する。 
3 - そのトピックを知らない人がその引用を読んで、ポイントを直接推測できるかどうかを考える。
    なぜそうなのか、なぜそうでないのかを説明してから判断する。 
4 - 3の答えが「はい」であれば「はい」、そうでなければ「いいえ」と書く。  

最後に、「はい」の答えがいくつあるかを数える。この数を{"count":<ここに数を入れる>} 

この2点が満たされる入力例を紹介します:

システム: 
<上のシステムメッセージを挿入>  

ユーザー: 
"""
ニール・アームストロングは、人類で初めて月面に降り立ったことで有名です。
この歴史 的な出来事は1969年7月21日、アポロ11号のミッション中に起こった。
""" 


以下は、1点のみが満たされる入力例です:

システム: 
<上のシステムメッセージを挿入>  

ユーザー: 
"""
ニール・アームストロングは月着陸船から降り、月面を歩いた最初の人間となり、歴史に 名を刻んだ。
""" 


以下は、どれも満たさない入力例です:

システム: 
<上記のシステムメッセージを挿入してください>  

ユーザー: 
"""
69年夏、壮大な航海、 アポロ11号、伝説の手のように大胆に。 
アームストロングは一歩を踏み出し、歴史は広がった、 「新しい世界のために、「小さな一歩を」と彼は言った。
"""


このタイプのモデルベースの評価には、多くのバリエーションが考えられます。解答の候補とゴールドスタンダードの解答の重なりの種類を追跡し、解答の候補がゴールドスタンダードの解答の一部と矛盾しているかどうかも追跡する、次のようなバリエーションを考えてみましょう。

システム: 
以下のステップを使用して、ユーザーの入力に対応する。
例えば、「ステップ1:理由...」 というように。  
ステップ1: エキスパートの答えと比較して、提出された答えの情報が、不一致、等しい、サブセット、スーパーセット、または重複(つまり、いくつかの交差があるが、サブセット/ス ーパーセットではない)のいずれかであるかどうかを段階的に推論します。  
ステップ2: 提出された回答が専門家の回答と矛盾しているかどうかを段階的に推論します。  
ステップ3:次のような構造のJSONオブジェクトを出力する: {"type_of_overlap""disjoint "または "equal "または "subset "または  "superset "または "overlapping", "contradiction": trueまたは false}。 


ここに、専門家の回答と矛盾しない、標準以下の回答が入力された例があります:

システム: 
<上記のシステムメッセージを挿入してください>  

ユーザー: 
質問: """ニール・アームストロングが最も有名な出来事は何ですか?UTC時間を想定してください。"""  
提出された答え: """彼は月か何かを歩いたのでは?""" 
専門家の回答: """ニール・アームストロングは初めて月面を歩いた人物として最も有名です。この歴史的な出来事は1969年7月21日に起こりました。""" 

専門家の答えと正反対の答えが入力された例を挙げます:

システム: <上記のシステムメッセージを挿入してください>  

ユーザー: 質問:"""ニール・アームストロングが最も有名な出来事は何ですか?UTC時間を想定してく ださい。"""  
提出された答え:"""1969年7月21日、ニール・アームストロングはバズ・オルドリンに続く2人目の月面歩行者となった。"""  
専門家の回答:"""ニール・アームストロングは、初めて月面を歩いた人物として最も有名です。この歴史的な出来事は1969年7月21日に起こりました。""" 

以下は、必要以上に詳しく説明された正解付きの入力例です:

システム: 
<上記のシステムメッセージを挿入してください>  

ユーザー: 
質問: """ニール・アームストロングが最も有名な出来事は何ですか?UTC時間を想定してください。"""  
提出された答え: """1969年7月21日UTC 02:56頃、ニール・アームストロングは人類史上初めて月面に降り立ち、記念碑的な偉業を成し遂げた。"""  
専門家の回答: """ニール・アームストロングは、初めて月面を歩いた人物として最も有名です。この歴史的な出来事は1969年7月21日に起こりました。"""


まとめ

いかがだったでしょうか?
ところどころ難解で専門的な内容もあり、面食らった方も多かったのではないでしょうか?普段からAPIを使いこなしていて、システムロールとかアシスタントロールとか設定している人にとっては理解可能と思いますが、Web版のChatGPTしか触ったことがない初学者の方にとって、ハードルが高い内容と思われます。

私見ですが、いきなりこれらのテクニックを全部使ってプロンプトを作る必要は全くないと考えています。使い方としては、もし出力が満足のいかない結果だったときに、この記事を見直すことで突破口を見つける、というのが良いかもしれません。

引き続き、生成AIに関連する情報をお届けします。
ここまで、長文をお読みくださり、ありがとうございました。

この記事が気に入ったらサポートをしてみませんか?