Amazon Bedrock のプロンプトエンジニアリング - プロンプト最適化

:::note info
2025年01月現在 プレビュー版
:::

# どんな機能？

ユーザーが LLM へ入力するプロンプトを最適化してくれる機能です。

https://aws.amazon.com/jp/about-aws/whats-new/2024/11/prompt-optimization-preview-amazon-bedrock/

https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/prompt-management-optimize.html

# 注意

:::note warn

- プロンプトの最適化は 1 日に 10 プロンプトのみ
- アカウント内で最大 100 プロンプトまで最適化可能

のいずれか
:::

# 対応リージョン

- 米国東部 (バージニア北部)
- 米国西部 (オレゴン)
- アジアパシフィック (ムンバイ)
- アジアパシフィック (シドニー)
- カナダ (中部)
- 欧州 (フランクフルト)
- 欧州 (アイルランド) (ゲート）
- 欧州 (ロンドン)
- 欧州 (パリ)
- 南米 (サンパウロ）

# 利用可能なモデル

- 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)


# 設定

ドキュメントには、Console と API のやり方が記載されています。

- Console
  - プレイグラウンドのプロンプトを最適化
  - プロンプト管理でプロンプトを最適化
- API

今回は API で試してみます。

- 難しく考えずドキュメントにサンプルがありますので、基本それを利用すれば良さそうです
- API は [AgentsforBedrockRuntime.Client.optimize_prompt](
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-agent-runtime/client/optimize_prompt.html) を使います


```python
import boto3

TARGET_MODEL_ID = "anthropic.claude-3-sonnet-20240229-v1:0"
PROMPT = "この文章を要約して: 日本語で"

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
```

PROMPT を日本語で投げると、文字列がエンコードされて出てきました。

```
python prompt.py 
Request ID: c5adbbff-f187-4cb8-9213-b176ab6eecef
========================== INPUT PROMPT ======================

この文章を要約して: 日本語で
========================= ANALYZE PROMPT =======================

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

{'optimizedPrompt': {'textPrompt': {'text': '"u30bf\\u30b9\\u30af: \\u4e0e\\u3048\\u3089\\u308c\\u305f\\u6587\\u7ae0\\u3092\\u8981\\u7d04\\u3059\\u308b\\n\\n\\u624b\\u9806:\\n1. <context>\\u30bf\\u30b0\\u5185\\u306e\\u6587\\u7ae0\\u3092\\u6ce8\\u610f\\u6df1\\u304f\\u8aad\\u3080\\n2. \\u6587\\u7ae0\\u306e\\u4e3b\\u8981\\u306a\\u30dd\\u30a4\\u30f3\\u30c8\\u3092\\u628a\\u63e1\\u3059\\u308b\\n3. \\u4e3b\\u8981\\u306a\\u30dd\\u30a4\\u30f3\\u30c8\\u3092\\u7c21\\u6f54\\u306b\\u307e\\u3068\\u3081\\u3001<summary>\\u30bf\\u30b0\\u5185\\u306b\\u8981\\u7d04\\u3092\\u8a18\\u5165\\u3059\\u308b\\n\\n\\u8981\\u7d04\\u306e\\u969b\\u306e\\u6ce8\\u610f\\u70b9:\\n- \\u5143\\u306e\\u6587\\u7ae0\\u306e\\u9577\\u3055\\u306b\\u95a2\\u4fc2\\u306a\\u304f\\u3001\\u8981\\u7d04\\u306f\\u77ed\\u304f\\u307e\\u3068\\u3081\\u308b\\u3053\\u3068\\n- \\u91cd\\u8981\\u306a\\u60c5\\u5831\\u304c\\u6b20\\u843d\\u3057\\u306a\\u3044\\u3088\\u3046\\u6ce8\\u610f\\u3059\\u308b\\n- \\u81ea\\u5206\\u306e\\u8a00\\u8449\\u3067\\u8981\\u7d04\\u3057\\u3001\\u5143\\u306e\\u6587\\u7ae0\\u304b\\u3089\\u306e\\u76f4\\u63a5\\u306e\\u5f15\\u7528\\u306f\\u907f\\u3051\\u308b\\n\\n\\u8981\\u7d04\\u5bfe\\u8c61\\u306e\\u6587\\u7ae0:\\n<context>\\n{{context}}\\n</context>\\n\\n\\u8981\\u7d04\\u3092\\u4ee5\\u4e0b\\u306e<summary>\\u30bf\\u30b0\\u5185\\u306b\\u8a18\\u5165\\u3057\\u3066\\u304f\\u3060\\u3055\\u3044:\\n<summary>\\n[\\u8981\\u7d04\\u3092\\u3053\\u3053\\u306b\\u8a18\\u5165]\\n</summary>"'}}}
```

デコードしてみます。

```
タスク: 与えられた文書を要約する

手順:
1. タグ内の文書を注意深く読む
2. 文書の主要なポイントを把握する
3. 主要なポイントを簡潔にまとめ、<summary>タグ内に要約を記入する

要約の場合の注意点:
- 元の文書の長さに関係なく、要約は短くまとめること
- 重要な情報が漏れ落ちないよう注意する
- 自分の言葉で要約し、元の文書からの直接の引用は避ける

要約対象の文書:
<context>
{{context}}
</context>

要約を以下の<summary>タグ内に記入してください:
<summary>
[要約をここに記入]
</summary>
```

PROMPT を "Summarize this sentence: In Japanese" に変えて英語で投げてみるといい感じに回答してくれてますね。

```
python prompt.py
Request ID: f4686151-3732-4d2b-91f8-c46fe45e9036
========================== INPUT PROMPT ======================

Summarize this sentence: In Japanese
========================= ANALYZE PROMPT =======================

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

{'optimizedPrompt': {'textPrompt': {'text': '"Task: Summarize the given text in a concise and clear manner.\\n\\nInstructions:\\n1. Read the provided text carefully and understand its content.\\n2. Identify the main points and key information in the text.\\n3. Rewrite the text in your own words, capturing only the essential details in a brief summary.\\n4. Ensure your summary is much shorter than the original text while preserving the core meaning.\\n5. Present your summary within the <summary> tags, without any additional text.\\n\\nText to summarize:\\nIn Japanese\\n\\n<summary>\\n[Your concise summary of the given text goes here]\\n</summary>"'}}}
```

# 番外編

[Claude](https://claude.ai/new) にプロンプト最適化をしてと質問を投げつけてみました。

![スクリーンショット 2025-02-02 19.56.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280929/edd050fb-0053-9dfe-63b2-40d01b8ccf07.png)

うーん、なるほど、Bedrock のプロンプト最適化を使った方が、Bedrock にあったプロンプト最適化を行なってくれるようですね

# ユースケース

質問を投げつける前に prompt を最適化する用途で利用されるのではないかと思いますが、
今現在は冒頭にも説明した通り利用回数には制限がありますし、RAG などで `PromptTemplate` を実装する際にプロンプトエンジニアリングで最適化したいといったときに利用できそうな気がします