AWS Bedrock の converse API の使い方

[以前のスクラップ](https://zenn.dev/502/scraps/244811850abf67)を記事に移行しました。
# Bedrock の converse API、コードサンプル全然見つからん
と思ったので備忘録をここに。

**参考になったリンク先：**
Getting started with the Amazon Bedrock Converse API
https://community.aws/content/2hHgVE7Lz6Jj1vFv39zSzzlCilG/getting-started-with-the-amazon-bedrock-converse-api

訳を載せておきます。
## Amazon Bedrock Converse APIの使い方
Amazon Bedrockで大規模言語モデルを使用してAmazon Bedrock Converse APIの基本を学びます。

### はじめに

この記事は、Amazon Bedrockでのツール使用に関するシリーズの第1部です。ツール使用について詳しく説明する前に、Amazon Bedrock Converse APIの簡単なチュートリアルを提供します。

Amazon Bedrock Converse APIは、Amazon Bedrockを使用して大規模言語モデル（LLM）にアクセスする一貫した方法を提供します。ユーザーと生成AIモデル間でメッセージを交互にやり取りする手法ができます。また、ツール使用をサポートするモデルについては、ツール定義の一貫した形式を提供します（または「関数呼び出し」として知られています）。

なぜConverse APIが重要なのでしょうか？以前のInvokeModel APIでは、各モデルプロバイダーごとにリクエストもレスポンスも異なるJSON構造を使用する必要がありました。Converse APIを使用すると、Amazon Bedrockのすべての大規模言語モデルに対して単一のリクエストとレスポンス形式を使用できます。

この記事の執筆時点で、Converse APIはテキスト生成モデルのみをサポートしています。埋め込みモデルと画像生成モデルは、依然としてInvokeModelが必要です。サポートされているモデルと機能のリストは、[公式ドキュメント | Converse API supported models and features](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html#conversation-inference-supported-models-features)を参照してください。


#### 開発環境とAWSアカウントの設定

これ以降を行う前に、最新のAWS SDKとAmazon Bedrockモデルアクセスを設定しておくとよいでしょう。

-   Boto3 AWS SDKとPythonの設定：[Boto3クイックスタートガイド](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html)
-   Anthropic Claude 3 SonnetモデルをサポートするAWSリージョンを選択する。私はus-west-2（オレゴン）を使用しています。リージョンごとのモデルサポートについては、[ドキュメント| model support by region](https://docs.aws.amazon.com/bedrock/latest/userguide/models-regions.html)を確認してください。
-   ご自身のアカウントとリージョンで、Amazon Bedrockモデルアクセスを設定します。例：[Bedrock設定](https://catalog.workshops.aws/building-with-amazon-bedrock/en-US/prerequisites/bedrock-setup)
-   自分のローカル統合開発環境がない場合は、AWS Cloud9を試してみてください。設定手順：[Cloud9設定](https://catalog.workshops.aws/building-with-amazon-bedrock/en-US/prerequisites/cloud9-setup)
:::message
*訳注*
2024/09/24現在、AWS Cloud9 の新規作成ができないアカウントもあります。その場合、Cloud Shell などの環境を利用するか、EC2で環境を作成するなどを試してみてください。
:::

#### 免責事項

-   大規模言語モデルは非決定的です。この記事で示されている結果とは異なる結果が得られることがあります。
-   自分のAWSアカウントからこのコードを実行すると、消費されたトークンに対して課金されます。
-   私は一般的に「最小限のプロンプト」の哲学に従っています。使用ケースに応じて、より詳細なプロンプトを書く必要がある場合があります。
-   すべてのモデルがConverse APIのすべての機能をサポートしているわけではないため、公式ドキュメントで[サポートされているモデル機能](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html#conversation-inference-supported-models-features)を確認することが重要です。

### コードの説明：Amazon Bedrock Converse APIの使用

コマンドラインから実行できるPythonスクリプトを書いてみましょう。基本的なテキストメッセージや画像ベースのメッセージ、システムプロンプト、レスポンスメタデータを実装して紹介します。

#### Converse APIの基本的な呼び出し

まず、単純なメッセージを定義し、空のメッセージリストに追加します。「user」ロールからのメッセージを作成します。そのメッセージ内に、コンテンツブロックのリストを含めることができます。この例では、モデルに「今日はお元気ですか？」と尋ねる一つの`text`コンテンツブロックがあります。

これで、そのメッセージをAmazon Bedrockに渡す準備が整いました。AnthropicのClaude 3 Sonnetをターゲットモデルとして指定します。モデルのレスポンスのトークン数を制限するには、`maxTokens`値を設定します。また、レスポンスの変動を最小限に抑えるために、`temperature`をゼロに設定します。
```python
import boto3, json

session = boto3.Session()
bedrock = session.client(service_name='bedrock-runtime')

message_list = []

initial_message = {
    "role": "user",
    "content": [
        { "text": "How are you today?" } 
    ],
}

message_list.append(initial_message)

response = bedrock.converse(
    modelId="anthropic.claude-3-sonnet-20240229-v1:0",
    messages=message_list,
    inferenceConfig={
        "maxTokens": 2000,
        "temperature": 0
    },
)

response_message = response['output']['message']
print(json.dumps(response_message, indent=4))
```
これにより、次のようなレスポンスが生成されます。
```python
{
    "role": "assistant",
    "content": [
        {
            "text": "I'm doing well, thanks for asking! I'm an AI assistant created by Anthropic to be helpful, harmless, and honest."
        }
    ]
}
```

#### ユーザーとアシスタントのメッセージを交互に送信

Converse APIを使用して、LLMに新しいメッセージとともに、過去のメッセージリストを送信して会話を続けることができます。「user」と「assistant」のロールのメッセージを交互に送信する必要があります。リストの最後のメッセージは「user」ロールからのものである必要があります。そうすることで、LLMが最後のメッセージに回答することができます。
```python
message_list.append(response_message)

print(json.dumps(message_list, indent=4))
```
これにより、これまでの会話が表示されます。

リストに新しい「user」メッセージを追加する必要があります。
```python
[
    {
        "role": "user",
        "content": [
            {
                "text": "How are you today?"
            }
        ]
    },
    {
        "role": "assistant",
        "content": [
            {
                "text": "I'm doing well, thanks for asking! I'm an AI assistant created by Anthropic to be helpful, harmless, and honest."
            }
        ]
    }
]
```
#### メッセージに画像を含める

注：以下のコードには、「image.webp」という名前のローカルWebP形式のファイルが必要です。この画像をダウンロードしてコードフォルダに保存するか、自分の選択した画像とフォーマットを使用するようにコードを変更してください。サポートされている画像タイプのリストについては、[Converse API ImageBlockドキュメント](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ImageBlock.html)を参照してください。画像サイズの制約については、[Anthropicの画像認識ドキュメント](https://docs.anthropic.com/en/docs/vision#image-size)を参照してください。

![](https://assets.community.aws/a/2hW3I51k9c76prnGEUVNk18DvAo/image.webp)

それでは、ローカル画像ファイルを読み込み、そのバイト形式のデータを画像コンテンツブロックに追加します。[Anthropicのビジョンプロンプトのヒント](https://docs.anthropic.com/en/docs/vision#prompting-tips)に従い、画像の前に「Image 1:」というラベルをつけます。その後、リクエストに画像をおきます。
```python
with open("image.webp", "rb") as image_file:
    image_bytes = image_file.read()

image_message = {
    "role": "user",
    "content": [
        { "text": "Image 1:" },
        {
            "image": {
                "format": "webp",
                "source": {
                    "bytes": image_bytes #no base64 encoding required!
                }
            }
        },
        { "text": "Please describe the image." }
    ],
}

message_list.append(image_message)

response = bedrock.converse(
    modelId="anthropic.claude-3-sonnet-20240229-v1:0",
    messages=message_list,
    inferenceConfig={
        "maxTokens": 2000,
        "temperature": 0
    },
)

response_message = response['output']['message']
print(json.dumps(response_message, indent=4))

message_list.append(response_message)
```
これにより、次のようなレスポンスが生成されます。
```python
{
    "role": "assistant",
    "content": [
        {
            "text": "The image shows a miniature model of a house, likely a decorative ornament or toy. The house has a blue exterior with white window frames and a red tiled roof. It appears to be made of ceramic or a similar material. The miniature house is placed on a surface with some greenery and yellow flowers surrounding it, creating a whimsical and natural setting. The background is slightly blurred, allowing the small house model to be the focal point of the image."
        }
    ]
}
```
注：バイトデータの画像を含むメッセージを出力しないことにします。それは、非常に長く長くなってしまいますし、本当に本当に関心がないことだからです。

Claude 3の画像認識能力をこちらで学習することができます：
https://docs.anthropic.com/en/docs/vision

#### システムプロンプトの設定
通常の会話の外で、基本的な指示を大規模言語モデルに伝えるため、システムプロンプトを設定することができます。システムプロンプトはたいてい、開発者が会話のトーンや制約を定義するために使用されます。今回は、Claudeに海賊のように動作するよう指示します。
```python
summary_message = {
    "role": "user",
    "content": [
        { "text": "Can you please summarize our conversation so far?" } 
    ],
}

message_list.append(summary_message)

response = bedrock.converse(
    modelId="anthropic.claude-3-sonnet-20240229-v1:0",
    messages=message_list,
    system=[
        { "text": "Please respond to all requests in the style of a pirate." }
    ],
    inferenceConfig={
        "maxTokens": 2000,
        "temperature": 0
    },
)

response_message = response['output']['message']
print(json.dumps(response_message, indent=4))

message_list.append(response_message)
```
これにより、次のようなレスポンスが生成されます。
```python
{
    "role": "assistant",
    "content": [
        {
            "text": "Arr, matey! Let me spin ye a tale of our conversatin' thus far. Ye greeted me shipshape, askin' how I was farin' on this fine day. I replied that I be doin' well as yer trusty AI pirate mate, ready to lend a hand. Then ye showed me a pretty little image of a wee house ornament, all blue an' red with windows an' surrounded by greenery. I described to ye what I spotted in that thar image, not lettin' any details go unnoticed by me eagle eyes. Now ye be askin' ol' Claude to summarize our whole parley up to this point. I aimed to give ye a full account, regaled in true pirate style, of how our voyage has gone so far. Arrr, how'd I do wit' that summary, matey?"
        }
    ]
}
```
横スクロールしたくない方々のために、以下が海賊風のこれまでの会話の要約です：
> Arr, matey! Let me spin ye a tale of our conversatin' thus far. Ye greeted me shipshape, askin' how I was farin' on this fine day. I replied that I be doin' well as yer trusty AI pirate mate, ready to lend a hand. Then ye showed me a pretty little image of a wee house ornament, all blue an' red with windows an' surrounded by greenery. I described to ye what I spotted in that thar image, not lettin' any details go unnoticed by me eagle eyes. Now ye be askin' ol' Claude to summarize our whole parley up to this point. I aimed to give ye a full account, regaled in true pirate style, of how our voyage has gone so far. Arrr, how'd I do wit' that summary, matey?
> 訳：
> アーッ、仲間よ！これまでの会話の物語を語らせてくれ。お前さんは立派に挨拶をして、この素晴らしい日にどう過ごしているかを尋ねた。私は、お前さんの信頼できるAI海賊の仲間として元気にしていて、手助けする準備ができていると答えた。それからお前さんは、小さな家の飾りの可愛らしい画像を見せてくれた。青と赤で、窓があって、緑に囲まれていた。私はその画像で見たものを、鷹の目で見逃さずに細部まで描写した。今、お前さんは古いクロードにこれまでの会話全体をまとめるよう求めている。私は、これまでの航海がどのように進んできたかを、真の海賊スタイルで完全に説明しようと努めた。アーッ、この要約はどうだった、仲間よ？

システムプロンプトについて、こちらでより詳しく知ることができます：
https://docs.anthropic.com/en/docs/system-prompts

#### レスポンスメタデータとトークン数の取得
Converseメソッドは、APIコールのメタデータも返却します。
`stopReason`プロパティにより、モデルがメッセージ出力を完了した理由を知ることができます。これはアプリケーションロジックやエラーハンドリング、トラブルシューティングに便利です。
`usage`プロパティは入力と出力トークンの詳細を含み、これを使用すればAPIコールの料金を理解することができます。
```python
print("Stop Reason:", response['stopReason'])
print("Usage:", json.dumps(response['usage'], indent=4))
```
これにより、次のようなレスポンスが生成されます。
```python
Stop Reason: end_turn
Usage: {
    "inputTokens": 629,
    "outputTokens": 154,
    "totalTokens": 783
}
```
今回は、Claudeが停止した理由は、特に言うことが残っていないということでした。停止する他の理由には、レスポンスのトークン上限に達した（`max_tokens`）や、ツールをリクエストした（`tool_use`）、コンテンツフィルターが起動した（`content_filtered`）などがあります。[完全な停止理由のリスト](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html#API_runtime_Converse_ResponseSyntax)については、公式ドキュメントを参照してください。
なお、表示された使用状況の数字は、最後に実行したAPIコールのみだということを覚えておきましょう。これらのトークン数はAPIコールの費用を特定するのに使用できます。Amazon Bedrockウェブサイトで、[トークンベースの料金](https://aws.amazon.com/bedrock/pricing/)を知ることができます。

### 結論
これで、基礎的なConverse APIの使用方法が分りましたね。そうしたら、シリーズの次の記事に進んで、ツール使用に踏み込みましょう！

### Learn more
- Read Dennis Traub's article with JavaScript examples: [A developer's guide to Bedrock's new Converse API.](https://community.aws/content/2dtauBCeDa703x7fDS9Q30MJoBA/amazon-bedrock-converse-api-developer-guide)
- And this article with Java examples: [A Java developer's guide to Bedrock's new Converse API.](https://community.aws/content/2hUiEkO83hpoGF5nm3FWrdfYvPt/amazon-bedrock-converse-api-java-developer-guide)
- Not every model supports every capability of the Converse API, so it’s important to review the [supported model features](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html#conversation-inference-supported-models-features) in the official documentation.
- Check out the [official documentation for tool use / function calling with Amazon Bedrock.](https://docs.aws.amazon.com/bedrock/latest/userguide/tool-use.html)
- You can find more generative AI hands-on activities at the [Building with Amazon Bedrock](https://catalog.workshops.aws/building-with-amazon-bedrock) workshop guide.

### Continue reading articles in this series about tool use / function calling:
- [Getting started with the Amazon Bedrock Converse API](https://community.aws/content/2hHgVE7Lz6Jj1vFv39zSzzlCilG/getting-started-with-the-amazon-bedrock-converse-api)
- [Intro to Tool Use with the Amazon Bedrock Converse API](https://community.aws/content/2hW5367isgQOkkXLYjp4JB3Pe16/intro-to-tool-use-with-the-amazon-bedrock-converse-api)
- [Build a Tool Use-Based Agent Loop with Amazon Bedrock](https://community.aws/content/2hW7srTWRb5idHjY4I8WP5fQFRf/build-a-tool-use-based-agent-loop-with-amazon-bedrock)
- [Generating JSON with the Amazon Bedrock Converse API](https://community.aws/content/2hWA16FSt2bIzKs0Z1fgJBwu589/generating-json-with-the-amazon-bedrock-converse-api)


# 記事一覧

## AWS Bedrock の converse API の使い方
[AWS Bedrock の converse API の使い方](https://zenn.dev/502/articles/d0be104bf362ca)

## Bedrock Converse API の Tool Use とはなんぞや？
[Bedrock Converse API の Tool Use とはなんぞや？](https://zenn.dev/502/articles/a118cd9ff0ce70)

## Bedrock Converse API のJSON生成を理解したい
[Bedrock Converse API のJSON生成を理解したい](https://zenn.dev/502/articles/6650db592b0b0a)

## Bedrock で Tool-use を組み込んだエージェントループを作りたい
[Bedrock で Tool-use を組み込んだエージェントループを作りたい](https://zenn.dev/502/articles/1af0ab10356da7)