はじめに
Amazon Bedrockでは、生成AIの基盤モデルをConverse (Stream) APIで呼び出して実行しますが、Amazon Nova系のモデルを呼び出した時の考慮点について、本記事で備忘録としてまとめます。
Amazon Novaの推論タイプはON_DEMANDではない
Amazon Bedrockがサポートするモデルの中で、特にinferenceTypesSupported
がON_DEMAND
のモデルを利用するケースが非常に多いと思いますが、以下のコードで、フィルタしつつ全てリストすることが可能です。
# 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を呼び出すことでモデル一覧が取得できるため、その中からinferenceTypesSupported
がON_DEMAND
のモデルをフィルタしているだけです。
ところが、Amazon Nova系のモデルはinferenceTypesSupported
がON_DEMAND
ではなくINFERENCE_PROFILE
であり、このコードではリストされないことが分かりました。
そこで、ON_DEMAND
のモデルに加えてINFERENCE_PROFILE
のモデルもリストするよう、コードの変更が必要となりました。
INFERENCE_PROFILEの推論タイプに対応する
変更後のコードは以下になります。
# 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を呼び出した結果を走査しつつ、inferenceTypesSupported
がINFERENCE_PROFILE
のモデルの場合にlist_inference_profiles()
のAPIを呼び出して、推論プロファイルID (inferenceProfileId
) を従来のモデルIDの属性に代入している点です。
このような処理が必要となる理由は、converse()
またはconverse_stream()
のAPIでinferenceTypesSupported
がINFERENCE_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.
上のコードにおけるmodelId
にinferenceProfileId
の値を代入することによる違和感は拭えませんが、この変更によってモデル一覧のスキーマを統一したままにでき、inferenceTypesSupported
属性の違いを全く意識することなく、 以下画像の例のようにアプリケーションのユーザにモデルを選ばせることが可能となります。
converse_stream()
のAPIでモデルを呼び出すときに指定する属性もmodelId
であり、converse_stream()
を呼び出すコードを変えるのではなく、modelId
を渡すかinferenceProfileId
を渡すかの違いとなります。
以下はboto3の公式ドキュメントから、リクエスト仕様を引用したものですが、このmodelId
に与える値が、Amazon Nova系の場合はinferenceProfileId
になるということです。(大変ややこしい)
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系のモデルを呼び出せていることが、ログからも確認できました。