2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Amazon Novaをboto3のconverseまたはconverse_stream APIで実行する

Last updated at Posted at 2025-01-12

はじめに

Amazon Bedrockでは、生成AIの基盤モデルをConverse (Stream) APIで呼び出して実行しますが、Amazon Nova系のモデルを呼び出した時の考慮点について、本記事で備忘録としてまとめます。

Amazon Novaの推論タイプはON_DEMANDではない

Amazon Bedrockがサポートするモデルの中で、特にinferenceTypesSupportedON_DEMANDのモデルを利用するケースが非常に多いと思いますが、以下のコードで、フィルタしつつ全てリストすることが可能です。

boto3
# Bedrockがサポートするモデル一覧を取得
def fetch_on_demand_models():
    try:
        response = bedrock_client.list_foundation_models()

        # 'modelSummaries'からON_DEMANDモデルのみ抽出
        models = [
            {
                "modelId": model['modelId'],
                "modelName": model['modelName'],
                "providerName": model['providerName'],
                "inferenceType": ", ".join(model.get('inferenceTypesSupported', [])),
                "shortModelId": model['modelId'].split(":")[0],
                "inputModalities": model.get("inputModalities", []),  # 入力モダリティ
                "outputModalities": model.get("outputModalities", []),  # 出力モダリティ
            }
            for model in response.get('modelSummaries', [])
            if "ON_DEMAND" in model.get('inferenceTypesSupported', [])
        ]
        return models

    except Exception as e:
        print(f"モデル一覧の取得中にエラーが発生しました: {e}")
        return []

簡単に書くとlist_foundation_models()のAPIを呼び出すことでモデル一覧が取得できるため、その中からinferenceTypesSupportedON_DEMANDのモデルをフィルタしているだけです。

ところが、Amazon Nova系のモデルはinferenceTypesSupportedON_DEMANDではなくINFERENCE_PROFILEであり、このコードではリストされないことが分かりました。
そこで、ON_DEMANDのモデルに加えてINFERENCE_PROFILEのモデルもリストするよう、コードの変更が必要となりました。

INFERENCE_PROFILEの推論タイプに対応する

変更後のコードは以下になります。

boto3
# Bedrockがサポートするモデル一覧を取得
def fetch_on_demand_models():
    try:
        response = bedrock_client.list_foundation_models()
        
        # 'modelSummaries'からON_DEMANDモデルのみ抽出
        models = []
        for model in response.get('modelSummaries', []):
            inference_types = model.get('inferenceTypesSupported', [])
            
            # INFERENCE_PROFILEタイプの場合は推論プロファイルを取得
            if "INFERENCE_PROFILE" in inference_types:
                try:
                    # 推論プロファイルの一覧を取得
                    profiles_response = bedrock_client.list_inference_profiles()
                    for profile in profiles_response.get('inferenceProfileSummaries', []):
                        # モデルのARNが一致する推論プロファイルを探す
                        for profile_model in profile.get('models', []):
                            if profile_model.get('modelArn') == model.get('modelArn'):
                                models.append({
                                    "modelId": profile['inferenceProfileId'],  # 推論プロファイルIDを使用
                                    "modelName": f"{model['modelName']} (Profile: {profile['inferenceProfileName']})",
                                    "providerName": model['providerName'],
                                    "inferenceType": ", ".join(inference_types),
                                    "shortModelId": model['modelId'].split(":")[0],
                                    "inputModalities": model.get("inputModalities", []),
                                    "outputModalities": model.get("outputModalities", []),
                                })
                                break

                except Exception as e:
                    print(f"推論プロファイルの取得中にエラーが発生しました: {e}")
            
            # ON_DEMANDタイプの場合は通常のmodelIdを使用
            elif "ON_DEMAND" in inference_types:
                models.append({
                    "modelId": model['modelId'],
                    "modelName": model['modelName'],
                    "providerName": model['providerName'],
                    "inferenceType": ", ".join(inference_types),
                    "shortModelId": model['modelId'].split(":")[0],
                    "inputModalities": model.get("inputModalities", []),
                    "outputModalities": model.get("outputModalities", []),
                })
        return models
 
    except Exception as e:
        print(f"モデル一覧の取得中にエラーが発生しました: {e}")
        return []

先ほどのコードとの違いは、list_foundation_models()のAPIを呼び出した結果を走査しつつ、inferenceTypesSupportedINFERENCE_PROFILEのモデルの場合にlist_inference_profiles()のAPIを呼び出して、推論プロファイルID (inferenceProfileId) を従来のモデルIDの属性に代入している点です。

このような処理が必要となる理由は、converse()またはconverse_stream()のAPIでinferenceTypesSupportedINFERENCE_PROFILEのモデル (= Amazon Nova系) を呼び出そうとすると、以下のエラーが出力されて失敗するためです。

エラーが発生しました: An error occurred (ValidationException) when calling the ConverseStream operation: Invocation of model ID amazon.nova-pro-v1:0 with on-demand throughput isn’t supported. Retry your request with the ID or ARN of an inference profile that contains this model.

上のコードにおけるmodelIdinferenceProfileIdの値を代入することによる違和感は拭えませんが、この変更によってモデル一覧のスキーマを統一したままにでき、inferenceTypesSupported属性の違いを全く意識することなく、 以下画像の例のようにアプリケーションのユーザにモデルを選ばせることが可能となります。

image.png

converse_stream()のAPIでモデルを呼び出すときに指定する属性もmodelIdであり、converse_stream()を呼び出すコードを変えるのではなく、modelIdを渡すかinferenceProfileIdを渡すかの違いとなります。

以下はboto3の公式ドキュメントから、リクエスト仕様を引用したものですが、このmodelIdに与える値が、Amazon Nova系の場合はinferenceProfileIdになるということです。(大変ややこしい)

boto3
response = client.converse_stream(
    modelId='string',
    messages=[
        {
            'role': 'user'|'assistant',
            'content': [
                {
                    'text': 'string',
                    'image': {
                        'format': 'png'|'jpeg'|'gif'|'webp',
                        'source': {
                            'bytes': b'bytes'
                        }
                    },
                    (以下略)

この仕様に沿ったコードの変更後にAmazon Nova系のモデルを呼び出せていることが、ログからも確認できました。

image.png

参考文献

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?