Amazon Bedrock のプロンプトを最適化する機能を試してみた

## はじめに

Amazon Bedrock のプロンプト最適化機能（プレビュー版）について、Newsの記事を読んだ時に「後で試してみよう」とメモしていたことを思い出したので、実際に試してみて、ブログを書くことにしました。

なお、News記事はこちらです。
[Amazon Bedrock のプロンプト最適化機能 (プレビュー版) がリリース（投稿日 2024/11/21）](https://aws.amazon.com/jp/about-aws/whats-new/2024/11/prompt-optimization-preview-amazon-bedrock/)


## Amazon Bedrock プロンプト最適化機能とは

Amazon Bedrock プロンプト最適化機能は、基盤モデルから、ユースケースに適した、より質の高い応答が得られるように、プロンプトを書き換えてくれる機能です。
プロンプトを最適化する対象のモデルを選択し、修正されたプロンプトを生成することができます。

では、早速試してみましょう。

## 試してみる

### 前提

[Amazon Bedrock User Guide - Optimize a prompt](https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-management-optimize.html) を読みながら試しました。

私は、プロンプト最適化機能がサポートされているリージョンの1つである、オレゴンリージョンを使用しました。

ブログ執筆日(2024/12/21)現在は、Amazon Bedrockで利用できる次のモデルがサポートされているとのこと。

- Amazon Titan Text G1 - Premier
- Anthropic Claude 3 Haiku
- Anthropic Claude 3 Opus
- Anthropic Claude 3 Sonnet
- Anthropic Claude 3.5 Sonnet
- Meta Llama 3 70B Instruct
- Meta Llama 3.1 70B Instruct
- Mistral AI Mistral Large (24.02)

今回は、Anthropic Claude 3.5 Sonnet を選びました。

ユーザーガイドには、コンソールを使用する手順と、APIから使用する手順が書かれていますので、両方試してみます。

### AWSマネジメントコンソールを使って試す

AWSマネジメントコンソールからは、次のように操作します。

- Playgrounds を使用してモデルを選択後、プロンプトを入力し、ワンドアイコン（魔法使いのステッキのようなアイコン）を選択します

![モデルを選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619198/23b65251-6a9a-1c05-81f5-49031babdb23.png)

![プロンプト入力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619198/f2eea301-86a8-57d0-891f-d5bb87d47581.png)

- 最適化プロンプトダイアログボックスが開き、Amazon Bedrockがプロンプトの最適化を開始します

    左側は元のプロンプトで、「AWSのクラウドサービスについて教えてください。」と表示されています。
    右は最適化されたプロンプトです。「'AWSのクラウドサービスについて教えてください。' AWSのクラウドサービスに関する説明を簡潔かつ正確に答えてください。回答は分かりやすく、専門用語を避けるようにしてください。」という案が提示されました。

<br>
モデルと効果的なコミュニケーションをするためには、プロンプトは以下のようなポイントを抑えるのが良いとされています。
- 具体性: モデルにどのような情報を求めているのかを明確にする
- 制約条件: 期待するフォーマットや詳細度を指定する
- コンテキスト: 背景情報や目的を含めることで、回答が精度を増す

最適化前と後を比べると、明らかに改善されていると感じました。

![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619198/a9f7e00e-c4bb-1324-ea4c-1becc3c47b49.png)


- Amazon Bedrockがプロンプトの分析と最適化を完了すると、ダイアログボックスで元のプロンプトと最適化後のプロンプトを並べて比較することができます


- 元のプロンプトを維持する場合はキャンセル、最適化後のプロンプトに置き換えるには「Use optimized prompt（最適化されたプロンプトを使用）」を選択します

![最適化後を使用](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619198/7c0758a3-959a-da50-f647-f6e4d00456a8.png)


- プロンプトを送信して応答を生成するには「Run（実行）」を選択します

![実行](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619198/0d054dac-f665-6303-5646-e46fadab9728.png)


別のプロンプトでも試してみました。
物語の創作を依頼するプロンプトの最適化前・後の例です。

元のプロンプトは「面白い物語を作ってください。」と、あいまいな無茶振りをしてみました。

プロンプトの最適化後は以下のようになりました。最適化後のプロンプト案は英語で返ってきました。

```text
<task>
Create an interesting and engaging story based on the given prompt.
</task>

<instructions>
1. Read the prompt carefully: <prompt>'面白い物語を作ってください。'</prompt> (Translation: "Please create an interesting story.")

2. Use your creativity and imagination to craft an original narrative that captures the reader's attention and interest.

3. The story should have the following elements:
- An intriguing plot with a clear beginning, middle, and end
- Well-developed characters with distinct personalities and motivations
- Vivid descriptions that bring the story world to life
- Engaging dialogue (if applicable) that moves the story forward
- A central conflict or challenge that the characters must overcome
- A satisfying resolution or conclusion

4. Consider incorporating unique perspectives, unexpected twists, or thought-provoking themes to make the story stand out.

5. Pay attention to proper grammar, spelling, and overall coherence to ensure a smooth reading experience.

6. Aim for a story length of approximately 300-500 words, but feel free to adjust as needed to fully develop the narrative.

7. Provide your story immediately after these instructions, without any preamble or additional context.
</instructions>
```

翻訳すると、最適化後として次のようなプロンプトが提示されたことがわかります。
```text
<task>
与えられた指示に基づいて、興味深く魅力的なストーリーを作成してください。
</task>

<instructions>
1. 指示をよくお読みください： <prompt>「面白い物語を作ってください。」</prompt>（Translation: "Please create an interesting story.")

2. 読者の興味を惹きつける独創的な物語を、あなたの創造性と想像力を駆使して作成してください。

3. ストーリーには以下の要素を含めること。
- 明確な起承転結のある興味をそそるプロット
- 個性と動機が明確な、よく練られたキャラクター
- ストーリーの世界を生き生きと描写する鮮明な描写
- ストーリーを前進させる魅力的なセリフ（該当する場合
- キャラクターが乗り越えなければならない中心的な葛藤や課題
- 満足のいく解決または結末

4. ユニークな視点、予想外の展開、考えさせられるテーマなどを盛り込んで、ストーリーを際立たせることを検討してください。

5. 読みやすくするため、正しい文法、スペル、全体的な一貫性に注意してください。

6. ストーリーの長さは、300～500語程度を目安にしてください。ただし、ストーリーを十分に展開させるために、必要に応じて自由に調整してください。

7. これらの指示の後に、前置きや追加の説明を一切入れずに、すぐにストーリーを書き始めてください。
</instructions>
```

![最適化されたプロンプトの例2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619198/1a63c7f7-71af-4e31-a9f6-e8ee60a1d043.png)

![出力された物語1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3619198/0dd0e3e4-2b4a-4a5f-27ea-105175d88baf.png)

出力された物語例1（最適化後プロンプトの出力結果）
```
太郎は、毎日同じ電車に乗って通勤していた。ある朝、いつものように駅のホームに立っていると、不思議な光景が目に飛び込んできた。電車が到着したとき、車両の窓に映る自分の姿が、いつもと違って見えたのだ。

驚いた太郎は、よく見ようと窓に近づいた。すると、窓に映る自分の姿が突然動き出し、にっこりと笑ってウインクをしたのだ。太郎は思わず後ずさりした。

その日から、太郎の日常は一変した。窓に映る「もう一人の自分」は、太郎が望んでいた理想の姿だった。自信に満ち溢れ、魅力的で、人生を楽しんでいるように見えた。

最初は戸惑っていた太郎だが、次第に「もう一人の自分」と対話するようになった。窓越しの会話を通じて、太郎は自分の潜在能力や夢、そして恐れていることに気づかされていった。

ある日、「もう一人の自分」は太郎に言った。「君は本当は何がしたいんだ？」この質問に、太郎は長い間抑え込んでいた夢を思い出した。世界中を旅して、様々な文化や人々と出会うことだった。

その瞬間、窓に映る姿が消え、太郎は自分自身の反射だけを見ることになった。しかし、その姿は以前とは違っていた。自信に満ちた表情で、目には決意の光が宿っていた。

太郎は、その日をきっかけに人生を変える決断をした。会社を辞め、貯金を使って世界一周の旅に出たのだ。その旅で、太郎は自分の可能性を再発見し、新しい人生の道を見つけることができた。

年月が過ぎ、太郎は再びあの駅のホームに立っていた。電車の窓に映る自分の姿を見て、彼は微笑んだ。そこには、かつて「もう一人の自分」として見ていた姿そのものが映っていたのだった。
```

ちなみに、最適化前のプロンプトで出力された結果も参考として示します。
前置きや追加の説明を含んでおり、ストーリーも導入部で終わってしまいました。

```
はい、短い物語を作らせていただきます。

--
時の魔法使い

空が紫色に染まる夕暮れ時、古い時計塔の最上階で一人の少女が大きな古時計を見つめていました。彼女の名前はアカネ。14歳になったばかりの彼女は、この町で唯一の時の魔法使いの見習いでした。

「もう一度...もう一度だけ試してみよう」

アカネは深く息を吸い込み、両手を古時計に向けて広げました。指先から淡い青い光が放たれ、ゆっくりと時計の文字盤に触れていきます。

突然、時計の針が逆回転を始めました。部屋中の空気が渦を巻き、アカネの長い黒髪が舞い上がります。

「できた！」

しかし、その喜びもつかの間。時計の針は勢いを増し、制御不能なスピードで回り始めました。部屋の景色が歪み、まるで万華鏡の中にいるような感覚に襲われます。

「だ、だめ！止まって！」

必死に魔法を止めようとする彼女の前で、時計の文字盤が眩い光を放ちました。そして次の瞬間、アカネの姿は消えていました。

目を開けると、そこは見覚えのある時計塔。でも、何かが違います。窓の外を見ると、いつもの街並みはなく、代わりに広大な草原が広がっていました。

「まさか...時間を飛びすぎちゃった？」

ポケットから取り出した小さな手帳には、魔法使いの初代館長から代々受け継がれてきた言葉が記されていました。

『時を操る者は、時に導かれし場所にて己の使命を見出すべし』

アカネは深いため息をつきながら、手帳をしまい直しました。これは彼女の冒険の始まりに過ぎませんでした。街を元の時代に戻すため、そして一人前の時の魔法使いになるため、彼女は新たな旅路へと踏み出すのです。

時計塔の古い階段を降りながら、アカネは小さく微笑みました。確かに怖いけれど、どこか胸の奥がわくわくしているのを感じていました。時の魔法使いになるという夢は、こんな形で本当の冒険になるとは思ってもみなかったのですから。

これから始まる冒険が、どんな物語になっていくのか。それは誰にもわかりません。ただ、時の魔法使いの見習いである彼女なら、きっと道を見つけられるはずです。なぜなら、時間というものは、正しい時に正しい場所へと私たちを導いてくれるものだから。

そう信じて、アカネは未知の時代へと一歩を踏み出したのでした。
--

物語を作成しました。時の魔法使いの見習いである少女が、失敗した魔法で過去にタイムスリップしてしまう冒険ファンタジーです。新しい時代での彼女の冒険と成長を描いています。

どうでしょうか？他のタイプの物語をご希望でしたら、お申し付けください。
```


### APIから試す

APIから使用する場合もみてみましょう。

サンプルコードがユーザーガイドにあるため、参考にします。

```python
import boto3

# Set values here
TARGET_MODEL_ID = "anthropic.claude-3-5-sonnet-20241022-v2:0" # Model to optimize for. For model IDs, see https://docs.aws.amazon.com/bedrock/latest/userguide/model-ids.html
PROMPT = "英語を上達させるにはどうすればいいですか？" # Prompt to optimize

def get_input(prompt):
    return {
        "textPrompt": {
            "text": prompt
        }
    }
 
def handle_response_stream(response):
    try:
        event_stream = response['optimizedPrompt']
        for event in event_stream:
            if 'optimizedPromptEvent' in event:
                print("========================== OPTIMIZED PROMPT ======================\n")
                optimized_prompt = event['optimizedPromptEvent']
                print(optimized_prompt)
            else:
                print("========================= ANALYZE PROMPT =======================\n")
                analyze_prompt = event['analyzePromptEvent']
                print(analyze_prompt)
    except Exception as e:
        raise e
 
 
if __name__ == '__main__':
    client = boto3.client('bedrock-agent-runtime')
    try:
        response = client.optimize_prompt(
            input=get_input(PROMPT),
            targetModelId=TARGET_MODEL_ID
        )
        print("Request ID:", response.get("ResponseMetadata").get("RequestId"))
        print("========================== INPUT PROMPT ======================\n")
        print(PROMPT)
        handle_response_stream(response)
    except Exception as e:
        raise e
```

boto3を最新化した後でターミナルからpythonを実行すると、出力結果は以下のようになりました。

```sh
Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
========================== INPUT PROMPT ======================

英語を上達させるにはどうすればいいですか？
========================= ANALYZE PROMPT =======================

{'message': 'Analysis of your prompt is complete'}
========================== OPTIMIZED PROMPT ======================

{'optimizedPrompt': {'textPrompt': {'text': '"<task>\\nProvide suggestions to improve English language skills.\\n</task>\\n\\n<instructions>\\nGiven the question: \\"What should I do to improve my English skills?\\", provide a list of practical tips and recommendations to help the user enhance their English proficiency. Follow these guidelines:\\n\\n1. Suggest a variety of methods and activities that target different language skills (reading, writing, listening, speaking).\\n2. Explain each recommendation briefly and clearly.\\n3. Tailor your suggestions based on the assumption that the user is a native Japanese speaker learning English.\\n4. Provide 5-8 recommendations in a numbered or bulleted list format.\\n5. Focus on actionable steps the user can take rather than general advice.\\n\\n</instructions>\\n\\n<response_format>\\nHere are some suggestions to improve your English skills:\\n\\n[List of recommendations with brief explanations]\\n</response_format>\\n\\n<example>\\nHere are some suggestions to improve your English skills:\\n\\n1. Read books, newspapers, or online articles in English regularly. This will help expand your vocabulary and improve reading comprehension.\\n\\n2. Watch movies, TV shows, or videos in English with English subtitles. Listening to native speakers will train your ear and improve your listening comprehension.\\n\\n3. Practice writing in English by keeping a journal, writing emails or stories, or participating in online forums. This will help you improve your grammar and written expression.\\n\\n4. Find a language partner or join a conversation group to practice speaking English regularly. Conversing with others is crucial for improving your fluency and pronunciation.\\n\\n5. Use language learning apps or websites to study grammar rules, practice exercises, and learn new vocabulary in a structured way.\\n\\n6. Immerse yourself in an English-speaking environment by traveling to an English-speaking country or joining local English meetup groups.\\n\\n7. Listen to English podcasts, audiobooks, or music while commuting or doing chores to increase your exposure to the language.\\n</example>"'}}}
```

目視では読みづらいのですが、以下のように最適化されたプロンプトが返ってきました（読みやすいように手で整形して、英語を日本語に翻訳した結果です）。

```
<task>
英語能力の向上に役立つ提案をしてください。
</task>

<instructions>
「英語能力を向上させるにはどうすればよいか？」という質問を踏まえて、英語能力の向上に役立つ実践的なヒントや推奨事項のリストを作成してください。
以下のガイドラインに従ってください。

1. 異なる言語スキル（リーディング、ライティング、リスニング、スピーキング）を向上させるためのさまざまな方法やアクティビティを提案してください。
2. それぞれの提案を簡潔かつ明確に説明してください。
3. ユーザーは英語を学習中の日本語ネイティブスピーカーであるという想定に基づいて提案してください。
4. 提案を番号付きまたは箇条書きのリスト形式で5～8個記載してください。
5. 一般的なアドバイスよりも、ユーザーが実行可能なステップに焦点を当ててください。
</instructions>

<response_format>
英語力を向上させるためのいくつかの提案を以下に示します。
[提案のリストと簡単な説明]
</response_format>
<example>
英語力を向上させるためのいくつかの提案を以下に示します。
1. 英語の本、新聞、オンライン記事などを定期的に読みましょう。 語彙を増やし、読解力を向上させるのに役立ちます。
2. 英語の映画やテレビ番組、英語の字幕付きの動画を視聴しましょう。ネイティブスピーカーの英語を聞くことで耳が鍛えられ、リスニングの理解力が向上します。
3. 日記をつけたり、Eメールや物語を書いたり、オンラインフォーラムに参加したりして、英語で文章を書く練習をしましょう。これにより、文法や文章表現力が向上します。
4. 言語パートナーを見つけたり、会話グループに参加したりして、定期的に英語で会話する練習をしましょう。会話は流暢性や発音を向上させるために不可欠です。
5. 語学学習アプリやウェブサイトを利用して、文法規則や練習問題、新しい語彙を系統立てて学習しましょう。
6. 英語圏の国へ旅行したり、地元の英語のミートアップグループに参加したりして、英語環境に浸りましょう。
7. 通勤中や家事をしている間などに、英語のポッドキャストやオーディオブック、音楽を聴いて、英語に触れる機会を増やしましょう。
</example>
```

## 感想

AWSマネジメントコンソールとAPIで、簡単に試してみて、プロンプトを改善してくれそうな雰囲気を感じることができました。

これまで、モデルから良い品質の結果を得るためには、モデルのドキュメントを参照し、プロンプトをモデルに応じたフォーマットで記述することが必要でした。
その手間を、このプロンプト最適化機能が省いてくれます。
今回使ったモデルは1種類だったので、異なる複数の提供元（ベンダー）のモデルを切り替えて試してみると、もっと良さが分かるのではないかと思います。