皆さん、Amazon Bedrock使ってますか?
Amazon Bedrockを日本語でも活用したい場合、現状は実質唯一の選択肢とも言えるAnthropic社のClaudeですが、Claudeには更に高精度に思った通りの回答をさせるのに使えるテクニックが多数あります。
今年後半はClaudeのPromptと向かい合う日々が続いていたので、Amazon Bedrock Advent Calanderの3日目では、その総まとめを兼ねてClaudeのPrompt Enginneringのコツをお伝えしていきたいと思います。
※ 別途Anthropic ClaudeのAdvent Calenderが存在していることに気づかずこちらに書いてしまいすみませんでした。
今後はClaude 2.1のfunction callingのサンプルなども拡張されるようですので、随時こちらの記事を更新予定です
ChatGPTでも使われるテクニックとはまた違うの?
Prompt Engineering Guide のようなサイトでも言及されているように、 LLMで汎用的に利用可能な手法として、Few-shot promptingやChain of Thought、ReAct等が挙げられますが、Claudeではそれらに加えてClaudeに特化した話も存在します。
以下のPromptを見ていただいて、
-
Human:
って何? - 謎のXMLタグは何?
- 最後に
Assistant: {
とあるのは何?
と思われた方は、ぜひこの記事でClaude Prompt Engineringの醍醐味を持って帰っていただければ嬉しいです。
Human:
以下に企業Xでのカスタマーサポートでの会話を文字起こしした会話記録を記載します。
<transcription>
ここに文字起こしした会話記録が入る
</transcription>
<transcription></transcription>に囲まれた会話記録をよく読んで、以下のようなJSONフォーマットで要約してください。
{
"summary": "ここに会話記録の要約結果を記載してください"
}
Assistant: {
Claude における Prompt Engineering Tips
公式ドキュメントはこちら
Anthropic公式のドキュメントにはここに記載する各種の方法の他に、ユースケースごとのプロンプト例なども数多く記載されているのでClaudeを利用する際は必見です。
さて、ここからは早速具体的なTipsをご紹介していきます!
Human: / Assistant: フォーマット
Claudeを利用する上で必ず理解すべき概念、それはこのHuman: / Assistant: フォーマットです。
Claudeは AIアシスタント(Assistant) と 人(Human) が対話している形式のデータで学習されています。従って、Claudeを利用する際には、必ず \n\nHuman:
と \n\nAssistant:
を含めてAIアシスタントと人の対話の形式にする必要があります。
Amazon Bedrock の InvokeModel API 呼び出し時にこれらが含まれていない場合は ValidationException が返ります。
Humanの側にタスクの詳細を記載し、最後に Assistant:
で終わるプロンプトを書くことで、Claudeはその続きの文章としてAIアシスタントの回答を生成してくれるという使い方がよく使われます。
Human: AWSとは何ですか?
Assistant:
Human:とAssistant:の前には、必ず改行を2つ挟む必要があることに注意してください。
マネジメントコンソール等で利用する場合は、裏で自動でこれらのフォーマットが挿入されるので、特に意識する必要はありません。
XMLタグを文章の区切りに利用する
Claudeは、XMLタグの構造に特に注目するように学習されています。ルールや具体例、RAGで利用するドキュメントやユーザーからの質問文など、Promptの中で重要な文章群を明確に区切るためにXMLタグが利用できます。
特に長いPromptを扱う場合は、指示内容や具体例、検索結果などの境界が曖昧になることで結果精度が落ちる場合もありますので、最大20万トークン扱えるClaudeで重宝される機能ですね。
Human: 以下にコールセンターでの文字起こしした結果を記載します。
<transcription>
ここに長い文字起こし結果が入る
</transcription>
<transcription></transcription> XMLタグで囲まれた文字起こし結果を読んだ上で、それを簡潔に要約してください。
Assistant:
この例では、長い文字起こし結果をタスクの説明と明確に分離するために、XMLタグを利用しています。
<document>
, <answer>
, <transcription>
など利用できるXMLタグ自体に制限はありません。と書きつつも、例えばClaude 2.1では長い文章を複数入力する際に以下のようなXMLフォーマットの利用を推奨するなど、XMLタグの種類の差が全くない訳では無いと考えられるので、ドキュメントの使い方を真似るのが良さそうです。
Claudeが生成する文章の始まりを指定する
Claudeのプロンプトでは、生成される文章の書き始めをこちら側で強制的に指定することができます。
プロンプト最後尾の\n\nAssistant:
の直後に、何かを追加で書くイメージです。
これは、Claudeの出力を望む形に安定させたい際に非常に使えるテクニックで、「はい、分かりました〜」というような冗長で不必要な回答を除きたい場合や、JSONでの出力であったり、A/B/Cの複数選択肢への回答など、決められたフォーマットで回答して欲しいという場合に有用です。
例えば以下のプロンプトでは、冗長な表現を避けるために、あるXMLタグの中に必要な情報を書くよう指定した上で、末尾の \n\nAssistant:
に続けて、XMLタグの始まりを記載しています。これにより、レシピの内容のみを出力することができるわけですね。
Human:
牛丼の作り方を説明してください。<recipe></recipe>の中に、レシピのみを記載してください。
Assistant:<recipe>
このプロンプトを利用すると、生成された文章の最後に </recipe>
が付いてくるのが気になる方もいらっしゃるかと思います。
その場合は、ClaudeのAPIを呼び出す際に指定できるパラメーターである stop_sequences
に、 デフォルトの\n\nHuman:
だけでなく</recipe>
も加えてやると、が生成されたタイミングでその直前の文字までを出力結果として返してくれるので便利です。stop_sequences
パラメータについては、下記でも説明しています。
また、JSONで出力する場合は、Promptの末尾を \n\nAssistant:{
に、[YES], [NO]のどちらかのみを出力させる場合は、\n\nAssistant:[
を指定するなど、応用の効かせやすいテクニックではあります。
公式のPrompt例の中でも頻繁に使われているので、注意して確認してみてください。
ちなみに英語のドキュメントではこのテクニックを Put words in Claude's mouth と記載しています。おしゃれな表現ですね。
指示や質問は最後に記載する
ClaudeはPromptの末尾付近に特に注意を払います。ですので、特に長いPromptの場合は、指示や質問は末尾に配置しましょう。
例えば回答する際に参照して欲しい長文の資料をPromptに含める場合は、必ず指示や質問の前に書くということです。
加えて、「後で質問するから丁寧に資料を読んでください」と伝えることも効果があるようです。
Human:
あなたは優秀なアシスタントです。
以下に資料を添付します。後ほど資料に関する質問をするので、丁寧に資料を読んでください。
<document>
長い資料はこの部分、つまり具体的な指示やルールの前に記載する
</document>
<document></document>タグの中に記載された資料の内容について、以下の質問に答えてください。
資料に一行でタイトルを付けるとすれば何が適切ですか?
Assistant:
具体例を加える
LLMでは具体例を示すとより求める回答を得られる可能性が高まるというのはよく聞く話ですが、Claudeでも同様です。特に複雑なタスクでは効果を発揮します。
Claudeの場合は、XMLタグと組み合わせて具体例を挿入するのが一般的です。
Human: タスクの詳細は割愛
以下の<example></example>に回答の例を示します。このフォーマットに従って回答してください。
<example>
ここに具体例を入れる
</example>
Assistant:
System Prompt を利用する
Claude 2.1でのみ利用可能な機能です。2023/12/3時点では、Claude 2.1はオレゴンリージョンのAmazon Bedrockで利用可能です。
Claudeの精度を向上させるための新たな手法として、System PromptがClaude 2.1で導入されました。
従来はHuman側にすべての情報を記載していましたが、エージェントの役割や、タスクの内容やコンテキスト、引用して欲しいドキュメント、守って欲しいルール、出力のフォーマットなどをSystem Promptに記載することもできるようになります。ドキュメントには、重要な情報や指示はSystem Promptに書くことで一般的には精度が向上するとはります。特にチャットボットのようにHumanとAssistantの会話が続く場合は、仕様や役割の定義と実際の会話内容を明確に分離するために有用そうですね。
書き方は簡単で、ただSystem PromptをPromptの序盤に書くだけです。その後に従来と同じく \n\nHuman:
と \n\nAssistant:
を続けます。
あなたは、AWSに非常に詳しいITエンジニアです。与えられた質問に、1行で端的に回答してください。
Human: EFSとは何ですか?
Assistant: EFSは、AWSのマネージド型のファイルストレージサービスです。
Human: EBSとはことなるのですか?
Assistant:
こちらのキャリアコーチのロールプレイ用のプロンプト例でも、System Promptを利用した例が記載されています。
API呼び出し時のパラメータを意識する
Claudeを呼び出す場合は以下のような複数のパラメータを指定可能です。
とは言えこれらのパラメータを都度細かくチューニングすることを推奨するわけではなく、基本的には以下のパラメータだけタスクに合わせて設定しておけばOKというのものを紹介します。公式のサンプルでも、これら以外はデフォルトのまま利用しているケースが大半な印象です。
これ以上パラメータをチューニングするぐらいであれば、Promptを分野違いの人に見せても明確に理解できるぐらい、分かりやすく具体的に書き直すのに時間を当てたほうが効果的です。
max_tokens_to_sample (default: 256)
これはモデルが出力するトークンの総数です。複数選択肢に回答する場合は数トークンで十分ですし、文章を生成する場合は数百、数千が適切な場合もあります。
こちらのAmazon Bedrockのドキュメントでは、最適なパフォーマンスを提供するために、4000トークン以下で指定することを推奨していることにご留意ください。
temperature (default: 1)
Claudeの回答にどれほどランダムさを与えるかという値です。複数選択肢への回答や分析的なタスクでは0に近い値を、クリエイティブに文章生成させるようなタスクの場合は1に近い値をセットしてください。
例えば文章から情報を抽出したり、社内文章を引用しつつ質問に回答させるような場合は、"temperature": 0
を指定することが多いです。
stop_sequences (default: ["\n\nHuman:"])
Claudeは、ここに指定した文字列を見つけると生成を停止します。デフォルトでは\n\nHuman:
が指定されていますが、例えば "stop_sequences": ["\n\nHuman", "</answer>"]
のようにXMLタグの片方を加えることで、Claudeに欲しい出力のみ生成させるようなテクニックでも利用されます。
詳細は上記の「Claudeが生成する文章の始まりを指定する」でも説明しています。
その他のTips
その他にも、公式のドキュメントで言及されているTipsや、一般的に利用されるTipsを簡単に記載します。
- 明確で分かりやすいPromptを書く
- 英語でPromptを書く
- ハルシネーションを避けるために、知らない場合は「知りません」と言うように指示する
- タグの中に思考の中間過程を書かせる (chain-of-thought prompting)
- step-by-stepで考えるよう指示する
- 複雑なタスクを複数のサブタスクに分ける
- PromptをChainさせる
- Claudeに指示を理解しているか聞く
複雑なPromptの実例
ここまででは、具体的なPrompt Engineeringのテクニックについて紹介してきましたが、ここではそれらを組み合わせることで具体的にどのようなPromptを書けるのかについて紹介します。
以下はドキュメントから関連箇所を引用しつつQ&Aする公式のプロンプト例(の日本語版)です。
Human: ドキュメントを添付し、そのドキュメントに関する質問をします。まず、質問への回答に利用できるドキュメントの一部を正確に引用して書き出してください。そして、引用した内容の事実を使って質問に回答してください。
以下がそのドキュメントです:
<document>
{{TEXT}}
</document>
まず、質問へ回答する上で最も関連する箇所をドキュメントから引用し、番号順に記載します。引用文は比較的短いものにしてください。
関連する引用がない場合は、代わりに「関連する引用はありません」と書いてください。
次に、"回答:"から始まる形で質問に答えます。 引用した内容を一語一語そのまま回答に含めたり、参照したりしてはいけません。回答の際に「引用[1]によると」と言わないでください。その代わりに、関連する文章の最後に括弧付きの番号を付けることで、回答の各セクションに関連する引用のみを参照するようにします。
したがって、回答全体の書式は、<example></example>タグの中に示されているようにしなければなりません。 書式と間隔を正確に守ってください。
<example>
関連する引用:
[1] "X社は2021年に1200万ドルの収益を計上した"
[2] "収益のほぼ90%はウィジェットの販売によるもので、残りの10%はガジェットの販売によるものである。"
回答:
X社は1,200万ドルの収入を得た[1]。 そのほぼ90%はウィジェットの販売によるものである[2]。
</example>
以下が最初の質問です: {{QUESTION}}
ドキュメントからは答えられない質問であれば、そのように書いてください。
前置きなしで即座に質問に答えてください。
Assistant:
最後に
Prompt Engineeringは科学的に実施しようというのをAnthropic社でも提唱しており、初めにinputとoutputのテストケースを包括的に作成した上で、精度を評価しつつPromptを改善していくことを勧めています。
ここまでの内容がAmazon BedrockでClaudeを利用される上でお役に立てば幸いです。それでは、よりAmazon Bedrockライフを!