Amazon Bedrockのプロンプト最適化は、2026年8月時点で性格の違う2つの機能に分かれています。プレイグラウンドの魔法の杖アイコンを押すと数秒で書き換わる「シンプル最適化」と、2026年5月14日に追加された、評価データセットで採点しながら最大5モデル分のプロンプトを並行して書き換える「Advanced Prompt Optimization」です。両者は対応リージョンも料金体系もAPIも別物で、東京リージョンで使えるかどうかまで割れます。この記事では公式ドキュメントとAPIモデルを突き合わせ、どちらをいつ選ぶか、いくらかかるか、入力ファイルをどう書くかを整理します。
まとめ
- プロンプト最適化は「シンプル最適化」と「Advanced Prompt Optimization(AdvPO)」の2方式。前者は1プロンプト・1モデルの即時書き換え、後者は評価データで採点しながら最大5モデルを比較する非同期ジョブです。
- 東京リージョン(ap-northeast-1)で使えるのはAdvPOだけです。シンプル最適化はモデル別の対応リージョン表に東京が1件も含まれません。
- シンプル最適化は無料ではありません。入力プロンプトと最適化後プロンプトの合計トークンに対して1,000トークンあたり0.03ドルが課金されます。
- AdvPOには機能自体の追加料金がなく、最適化中に消費した推論トークンとLambda実行費だけがかかります。ただしトークン量の見積り式には係数16が掛かるため、評価サンプル数の16倍で概算します。
- AdvPOのAPIはboto3(botocore)1.43.8以降にしか入っていません。公式ドキュメントのコード例には、実際のAPIモデルに存在しないパラメータ名とメソッド名が混ざっています。
プロンプト最適化の2方式と選び分け
Amazon Bedrockのプロンプト最適化は、2024年11月にプレビュー公開され、2025年4月23日に一般提供へ移行しました。当時の機能は現在「シンプル最適化」と呼ばれています。そこへ2026年5月14日、評価駆動でプロンプトを書き換えるAdvanced Prompt Optimizationが加わり、公式ドキュメントも「Optimize and migrate prompts in Amazon Bedrock」という上位ページの下に2方式をぶら下げる構成へ組み替えられました。
シンプル最適化とAdvanced Prompt Optimizationの比較
公式ドキュメントの比較表を要点だけ抜き出すと次のとおりです。
| 観点 | シンプル最適化 | Advanced Prompt Optimization |
|---|---|---|
| 用途 | 短いプロンプト1本の書き換え | 評価で書き換えを誘導、モデル移行と性能調整 |
| 入力サイズ | およそ1,000トークン以下が適正 | モデルのコンテキスト長に収まれば長さ不問 |
| 入力単位 | プロンプト文1本 | プロンプトテンプレート最大10本+評価サンプル |
| モデル数 | 1 | 最大5モデルを同時比較 |
| 評価 | なし(ヒューリスティックな書き換え) | ステアリング基準/LLM-as-a-judge/Lambda関数 |
| 実行方式 | 同期(数秒) | 非同期ジョブ(15分〜数時間) |
| マルチモーダル | 非対応 | 画像とPDFに対応 |
| 出力 | 書き換え後のプロンプト | 最適化後テンプレート+評価スコア・コスト概算・レイテンシ |
どちらを選ぶかの判断基準
判断は「採点基準を自分で定義できるか」で切れます。AdvPOは評価結果を燃料にして書き換えループを回すため、何を高得点とみなすかを言語化できるほど効きます。正解応答(referenceResponse)はスキーマ上は必須ではなく、正解データを用意できないタスクでもステアリング基準という正規ルートが残ります。数時間のジョブ時間と推論費を払う価値が出るのは、少なくとも「良い応答とは何か」を短い自然言語で書き下せるときです。
逆に、シンプル最適化を選ぶべきでない場面もはっきりしています。モデル移行の判断材料が欲しいときです。シンプル最適化は指定した1モデル向けに書き換えるだけで、書き換え前後を横並びで採点しません。「Claude 3.5 Sonnetで動いているプロンプトをNova Proに移して大丈夫か」を確かめたいなら、書き換えたプロンプトを自前で評価し直す手間が結局かかります。この用途はAdvPOが正面から扱う領域です。
シンプル最適化の対応範囲と実行手順
対応モデルと単一リージョンでの利用可否
シンプル最適化の対応表は、モデルごとに「そのリージョン単体で使えるか」(Single-region model support)が定義されています。以下は公式表の全22行です。
| プロバイダ | モデル | モデルID | 単一リージョン対応 |
|---|---|---|---|
| Amazon | Nova Lite | amazon.nova-lite-v1:0 | us-east-1・eu-west-2・ap-southeast-2 |
| Amazon | Nova Micro | amazon.nova-micro-v1:0 | us-east-1・eu-west-2・ap-southeast-2 |
| Amazon | Nova Pro | amazon.nova-pro-v1:0 | us-east-1・eu-west-2・ap-southeast-2 |
| Amazon | Nova Premier | amazon.nova-premier-v1:0 | なし |
| Anthropic | Claude 3 Haiku | anthropic.claude-3-haiku-20240307-v1:0 | 10リージョン(注1) |
| Anthropic | Claude 3 Sonnet | anthropic.claude-3-sonnet-20240229-v1:0 | 10リージョン(注1) |
| Anthropic | Claude 3 Opus | anthropic.claude-3-opus-20240229-v1:0 | なし |
| Anthropic | Claude 3.5 Haiku | anthropic.claude-3-5-haiku-20241022-v1:0 | us-west-2 |
| Anthropic | Claude 3.5 Sonnet | anthropic.claude-3-5-sonnet-20240620-v1:0 | us-east-1・us-west-2・eu-central-1 |
| Anthropic | Claude 3.5 Sonnet v2 | anthropic.claude-3-5-sonnet-20241022-v2:0 | us-west-2・ap-southeast-2 |
| Anthropic | Claude 3.7 Sonnet | anthropic.claude-3-7-sonnet-20250219-v1:0 | eu-west-2 |
| Anthropic | Claude Opus 4 | anthropic.claude-opus-4-20250514-v1:0 | なし |
| Anthropic | Claude Sonnet 4 | anthropic.claude-sonnet-4-20250514-v1:0 | なし |
| DeepSeek | DeepSeek-R1 | deepseek.r1-v1:0 | なし |
| Meta | Llama 3 70B Instruct | meta.llama3-70b-instruct-v1:0 | us-east-1・us-west-2・ap-south-1・ca-central-1・eu-west-2 |
| Meta | Llama 3.1 70B Instruct | meta.llama3-1-70b-instruct-v1:0 | us-west-2 |
| Meta | Llama 3.2 11B Instruct | meta.llama3-2-11b-instruct-v1:0 | なし |
| Meta | Llama 3.3 70B Instruct | meta.llama3-3-70b-instruct-v1:0 | なし |
| Meta | Llama 4 Maverick 17B Instruct | meta.llama4-maverick-17b-instruct-v1:0 | なし |
| Meta | Llama 4 Scout 17B Instruct | meta.llama4-scout-17b-instruct-v1:0 | なし |
| Mistral AI | Mistral Large (24.02) | mistral.mistral-large-2402-v1:0 | 9リージョン(注2) |
| Mistral AI | Mistral Large (24.07) | mistral.mistral-large-2407-v1:0 | us-west-2 |
注1は us-east-1・us-west-2・ap-south-1・ap-southeast-2・ca-central-1・eu-central-1・eu-west-1・eu-west-2・eu-west-3・sa-east-1 の10リージョン、注2はそこから eu-central-1 を除いた9リージョンです。「なし」の行について、公式は空欄の意味を説明していません。ただし該当するのはNova Premier・Claude Opus 4・Claude Sonnet 4・DeepSeek-R1・Llama 4系など、いずれもクロスリージョン推論プロファイル前提で提供されているモデルです。
この表で日本の開発者が最初に足を取られるのが、東京リージョン(ap-northeast-1)が1行も出てこない点です。プロンプトを保管するPrompt management自体は22リージョン(商用20+AWS GovCloud 2)で動き、ap-northeast-1も含まれます。東京でプロンプトを作ったのに最適化ボタンだけ使えない、という組み合わせが起きるわけです。シンプル最適化を試すなら、us-east-1かus-west-2にプロンプトを置くのが手っ取り早い回避策です。
コンソールとOptimizePrompt APIでの実行
コンソールでの操作は2か所にあります。プレイグラウンドでモデルを選んでプロンプトを書き、魔法の杖アイコンを押すと最適化ダイアログが開いて元プロンプトと並べて比較できます。もう1つはPrompt managementで、こちらは最適化結果がバリアントとして横に並びます。比較ビューにプロンプトが3本ある状態でさらに最適化しようとすると、どれを上書きするか聞かれます。
APIから叩く場合は、bedrock-agent-runtimeのOptimizePromptを使います。レスポンスはイベントストリームで返り、分析完了のanalyzePromptEventと書き換え完了のoptimizedPromptEventが順に流れてきます。
import boto3
client = boto3.client("bedrock-agent-runtime", region_name="us-west-2")
response = client.optimize_prompt(
input={"textPrompt": {"text": "Summarize the following meeting minutes in 200 characters."}},
targetModelId="anthropic.claude-3-5-sonnet-20240620-v1:0",
)
for event in response["optimizedPrompt"]:
if "analyzePromptEvent" in event:
print("[analyze]", event["analyzePromptEvent"]["message"])
elif "optimizedPromptEvent" in event:
text = event["optimizedPromptEvent"]["optimizedPrompt"]["textPrompt"]["text"]
print("[optimized]", text)
else:
# throttlingException / validationException などもイベントとして流れてくる
print("[error]", event)
最後のelse節は省略しないでください。OptimizePromptのレスポンスストリームは、throttlingException・validationException・accessDeniedException・internalServerException・dependencyFailedException・badGatewayExceptionを、呼び出し時の例外ではなくストリーム内のイベントとして返す構造になっています。イベントを2種類しか見ないコードだと、失敗が無言で握り潰されます。
Advanced Prompt Optimizationのジョブ設計
AdvPOは、評価サンプルをプロンプトテンプレートのプレースホルダに差し込み、ターゲットモデルへ推論を投げ、指定した方法で採点し、その結果を見てプロンプトを書き換える、というループを内部で回します。対応リージョンはus-east-1、us-east-2、us-west-2、ca-central-1、sa-east-1、eu-west-1、eu-west-2、eu-central-1、eu-central-2、ap-south-1、ap-northeast-1、ap-northeast-2、ap-southeast-1、ap-southeast-2の14です。東京が入っているのはシンプル最適化との大きな違いです。ターゲットにできるのはテキストを出力するBedrockモデル全般で、シンプル最適化のような限定リストはありません。
データの所在を気にする場合は、サービスが評価と書き換えにクロスリージョン推論を使う点も見ておく必要があります。欧州リージョンではeuのクロスリージョン推論が使われ、ap-south-1・sa-east-1・ap-northeast-2・ap-southeast-1ではグローバルのクロスリージョン推論が使われる場合があるとドキュメントに明記されています。東京はこの列挙に含まれていません。
入力JSONLの必須フィールドと書式
入力は1行1テンプレートのJSONLで、ジョブごとに1ファイルです。必須はversion(固定値bedrock-2026-05-14)、templateId、promptTemplate、evaluationSamplesの4つ。プレースホルダは二重の中かっこで書きます。
{"version": "bedrock-2026-05-14", "templateId": "minutes-summary-v1", "promptTemplate": "You are a meeting assistant.\n\nMinutes:\n{{minutes}}\n\nSummarize the decisions and the owner of each action item.", "customEvaluationMetricLabel": "decisioncoverage", "evaluationMetricLambdaArn": "arn:aws:lambda:us-west-2:123456789012:function:advpo-decision-coverage", "evaluationSamples": [{"inputVariables": [{"minutes": "Sato: ship the billing fix by Friday. Tanaka: owns the migration script."}], "referenceResponse": "Decision: ship the billing fix by Friday (owner: Sato). Action: migration script (owner: Tanaka)."}]}
クォータは、1ジョブあたりテンプレート10本・モデル5つ、1テンプレートあたり評価サンプル100件・テキスト変数20個・ステアリング基準5個、1サンプルあたりマルチモーダルファイル100件、入力ファイル50MB、同時ジョブ20(アカウント・リージョンあたり)です。マルチモーダルはJPG・JPEG・PNG・GIF・WebPとPDFに対応しますが、アニメーションGIFとWebPはモデルが先頭フレームしか読まないため、複数フレームを見せたい場合は自分で分割して別ファイルとして渡します。
評価方法3種の使い分け
評価方法はテンプレートごとに1つだけ選びます。省略した場合はシステム既定の評価が使われ、これもClaude Sonnet 4.6によるLLM-as-a-judgeです。既定の採点軸はAnswer Accuracy(正確性)、Answer Completeness(網羅性)、Expression Quality(簡潔さと指示追従)の3つで、タスクに応じて重みが動的に決まります。既定の採点プロンプトはExpression Qualityについて「特別な指示がない限り簡潔なほど良い」を最重要と明示しており、冗長な応答を返すプロンプトは自動的に減点される設計です。
- ステアリング基準:steeringCriteriaに短い自然言語を最大5個並べるだけの方式です。PROFESSIONALやCONCISEのような単語でも、数文の記述でも構いません。正解データの用意が難しいタスク向けです。
- LLM-as-a-judge:customLLMJConfigに採点用プロンプトと採点モデルを渡します。採点プロンプトの中では、二重中かっこのプレースホルダとしてprompt・response・referenceResponseが使えます。採点モデルに指定できるのはanthropic.claude-opus-4-6-v1、anthropic.claude-sonnet-4-5-20250929-v1:0、anthropic.claude-sonnet-4-6の3つです。
- Lambda評価器:evaluationMetricLambdaArnに関数ARNを渡し、採点ロジックを自分で書きます。二値の合否判定や、JSONスキーマ適合のような機械的に判定できる指標に向きます。
LLM-as-a-judgeとLambdaを使う場合は、customEvaluationMetricLabelの指定が必須です。忘れるとValidationExceptionでジョブが立ち上がりません。また、採点結果は元の採点尺度に関わらず正規化され、値が大きいほど良い扱いになります。1から5の離散スコアを定義しても、カスタムの採点プロンプトがサービス側の既定プロンプトと結合される都合上、出力が定義した刻みと一致しないことがあります。二値の判定や厳密一致が欲しいならLambda評価器を選ぶほうが確実です。
Lambda評価器の実装契約
Lambda評価器には細かい制約があります。コードは全部入りの単一.pyファイルで、ハンドラはlambda_function.lambda_handler。compute_score(preds, golds)を実装し、集約スコアのscoreと件数分のリストであるscoresを返します。タイムアウトは最大の900秒に寄せ、bedrock.amazonaws.comからの呼び出しを許可するリソースベースポリシーを付けます。
実装上の要点は3つです。1つ目は例外を投げないこと。2つ目は連続値を返すことで、0か1の二値は最適化器にとって勾配のない信号になり、収束が遅くなります。値域を0.0から1.0に収める必要はなく、大きいほど良いという向きだけが要件です。3つ目は、失敗時に数値だけでなく診断情報を返すこと。返した辞書の中身はサービス側に読まれ、なぜ低得点なのかの手がかりとして使われます。加えて、compute_scoreのdocstringとソースコード自体も指標の説明として読み込まれるため、何を高得点とみなすかを明示的に書いておくと書き換えの方向づけが効きます。
import logging
import re
from typing import Any, Dict, List
logger = logging.getLogger()
logger.setLevel(logging.INFO)
STOPWORDS = {"the", "a", "an", "of", "to", "by", "and", "is", "are", "will", "for"}
def _content_words(text: str) -> set:
return {w for w in re.findall(r"[a-z0-9]+", text.lower()) if w not in STOPWORDS}
def compute_score(preds: List[str], golds: List[str]) -> Dict[str, Any]:
"""正解文の内容語を応答がどれだけ再現できたかを 0.0-1.0 で採点する。
1.0 は正解文の内容語をすべて含む応答、0.0 は 1 つも含まない応答を指す。
決定事項と担当者名の取りこぼしを減らす方向にプロンプトを誘導するための指標。
"""
scores = []
for pred, gold in zip(preds, golds):
gold_words = _content_words(str(gold))
if not gold_words:
scores.append(0.0)
continue
scores.append(len(gold_words & _content_words(str(pred))) / len(gold_words))
return {"score": sum(scores) / len(scores) if scores else 0.0, "scores": scores}
def lambda_handler(event, context):
try:
preds = event.get("preds", [])
golds = event.get("golds", [])
if not preds:
return {"score": 0.0, "scores": []}
return compute_score(preds, golds)
except Exception as e:
logger.error("scoring failed: %s", e, exc_info=True)
return {"score": 0.0, "scores": [0.0] * len(event.get("preds", [])), "error": str(e)}
# 動作確認に使った 3 本の応答(gold は上の JSONL の referenceResponse と同じ文)
# 0.73: "Sato will ship the billing fix by Friday. Tanaka owns the migration script."
# 0.45: "Sato will ship the billing fix by Friday."
# 0.00: "No decisions were recorded."
公式ドキュメントは「明らかに悪い出力を採点して、指標がちゃんと減点するか確かめること」を推奨しています。上のコードを手元のPython 3.9で実行し、コメントに残した3本の応答で0.73・0.45・0.00と段階が付くことを確認しました。ここで差の出ない指標のままジョブを流すと、最適化器は差の出ない方向へ数時間かけて走ります。
ジョブ作成と結果ファイルの読み取り
ジョブはbedrockクライアントから作成します。評価方法は入力JSONL側で決まるため、ジョブ作成リクエストに評価の設定は入りません。S3バケットはジョブと同じリージョンに置く必要があります。
import boto3
client = boto3.client("bedrock", region_name="us-west-2")
response = client.create_advanced_prompt_optimization_job(
jobName="minutes-summarizer-migration",
modelConfigurations=[
{"modelId": "us.anthropic.claude-sonnet-4-5-20250929-v1:0"},
],
inputConfig={"s3Uri": "s3://my-advpo-bucket/input/templates.jsonl"},
outputConfig={"s3Uri": "s3://my-advpo-bucket/output/"},
)
job_arn = response["jobArn"]
status = client.get_advanced_prompt_optimization_job(jobIdentifier=job_arn)
print(status["jobStatus"], status.get("failureMessage"))
modelConfigurationsは1件から5件までで、modelIdのほかにinferenceConfigとadditionalModelRequestFieldsを渡せます。モデルIDはリージョンによってクロスリージョン推論プロファイルの接頭辞が変わるため、各モデルの詳細ページで自分のリージョン向けのプロファイルIDを確認してください。
jobStatusが取りうる値はInProgress、Completed、Failed、PartiallyCompleted、Stopping、Stopped、Deletingの7つです。注意したいのはPartiallyCompletedで、5モデルのうち一部だけモデルアクセスが有効になっていない場合などにここへ落ちます。Completed以外を一括で失敗扱いにする実装だと、使える結果を捨てることになります。
結果は出力S3パスの下に、ジョブARNの末尾セグメントをジョブIDとしたディレクトリが切られ、advanced_prompt_optimization_results.jsonlとして書き出されます。1行がテンプレート1本に対応し、その中にターゲットモデルごとの書き換え後テンプレート・サンプル別スコア・初回トークンまでの時間・コスト概算が入ります。なお、この結果ファイルを別の場所へ移すとコンソールの結果画面が描画できなくなります。ジョブ完了後にライフサイクルルールで自動移動する構成にしていると、後からコンソールで見返せません。
書き換え範囲を絞る選択的最適化
既定では、最適化器はテンプレート全体のどこでも書き換えます。役割定義や禁止事項のように動かしたくない部分がある場合は、advpo名前空間のタグで範囲を指定します。挙動はタグの組み合わせで4通りに分かれます。
| タグの状態 | 書き換え対象 |
|---|---|
| タグなし | テンプレート全体 |
| optimizeが1つ以上ある | optimize内だけ。タグ外は自動で保全される |
| excludeだけがある | exclude内を除く全体 |
| 両方ある | optimize内だけ。excludeは冗長として扱われる |
つまり、守りたい箇所をexcludeで囲む必要は基本的にありません。改善したい箇所をoptimizeで囲めば残りは自動的に保全されます。次は公式ドキュメントに載っている例です。
You are a helpful customer service agent for Acme Corp. Always be polite and professional.
<advpo:optimize>When responding to a complaint, acknowledge the customer's frustration, summarize the issue, and propose exactly one concrete resolution. Use bullet points for clarity.</advpo:optimize>
Never disclose internal pricing or employee information.
あまり知られていない使い方として、空のoptimizeブロックを置くと、最適化器がその位置に新しいプロンプト文を生成して挿入します。出力形式の指示だけをサービスに書かせたいときに使えます。逆に落とし穴もあり、タグの入れ子・閉じ忘れ・optmizeのような綴り間違いはいずれもValidationExceptionになります。最終出力ではタグ自体が取り除かれるので、書き換え後のプロンプトをそのまま本番に載せられます。
変数との関係も整理されています。excludeで囲んだ範囲でも実行時の変数置換は行われ、optimizeで囲んだ範囲でもプレースホルダはプレースホルダのまま保たれます。タグの解析は変数置換の前にテンプレートに対してのみ行われるため、ユーザー入力の値にタグ文字列が混ざっても最適化指示として解釈されることはありません。
プロンプト最適化の料金とコスト見積り
シンプル最適化の従量課金
シンプル最適化は無料機能ではありません。入力プロンプトのトークン数と、出力された最適化後プロンプトのトークン数の合計に対して、1,000トークンあたり0.03ドルが課金されます。AWSの料金ページに載っている試算例では、429トークンのプロンプトを最適化して511トークンになり、そこからClaude 3.7とNova Pro向けに582トークンと579トークンのバリアントを作った場合、合計3,123トークンで0.09ドルという計算になっています。入力と出力の両方が数えられる点が見落としやすいところです。
Advanced Prompt Optimizationのトークン量見積り
AdvPOには機能自体の追加料金がありません。推論はすべて利用者のAWSアカウント内で実行され、オンデマンドの標準ティア料金で課金されます。Lambda評価器を使う場合のLambda実行費も同様に自己負担です。評価方法を指定しなくても、既定のLLM-as-a-judgeが動く以上は採点側のトークンも発生します。
問題は、ループが何回回るかが公表されていないことです。公式ドキュメントは「内部の最適化パラメータに従って繰り返す」とだけ書いています。ただし料金ページには見積り式が公開されているので、そこから概算できます。評価データセットの件数をN、プロンプトテンプレートの入力トークン数をP、ターゲットモデルの出力トークン数の見込みをO、正解応答のトークン数をGとすると、次のようになります。
| 項目 | 見積り式 |
|---|---|
| ターゲットモデルの総トークン数 | 16 x N x (P + O) |
| 最適化器LLM(Claude Sonnet 4.6)の入力トークン数 | 101 x (3700 + 0.35 x P) |
| 採点側の総トークン数(LLM-as-a-judgeとステアリング基準) | 16 x N x (P + O + G + 採点プロンプト) |
| Lambda呼び出し回数 | 16 x N |
3行目はLLM-as-a-judgeを選んだ場合だけの話に見えますが、料金ページの原文はステアリング基準を選んだ場合も同じ式だと書いています。ステアリング基準は自然言語を1行渡すだけなので安く済むと考えがちですが、採点のためのモデル呼び出しは同じだけ発生します。
係数の16が効いてくるので、評価サンプルを上限の100件まで積むと、ターゲットモデルへの推論は1テンプレートあたり1,600回相当のトークンになります。所要時間の目安が、少数サンプルで15分から20分、大量のサンプルを積むと数時間になるのはこのためです。最初から上限まで積まず、10件程度で式に当てはめて実費を見てから広げるのが安全です。
日本語プロンプトの扱いと英語推奨の意味
公式ドキュメントはシンプル最適化について「最良の結果を得るには英語でプロンプトを最適化することを推奨します」と明記しています。この一文は、日本語プロンプトを投げると必ず失敗するという意味ではなく、書き換え品質の保証が英語基準だという注記です。
実務上の落としどころは、最適化と本番実行を分けて考えることです。最適化にかけるのは、指示部分(役割定義・出力形式・制約)だけを英語で書いたテンプレートにして、日本語で入るのはユーザー入力の変数値に留める。この形なら、書き換え対象は英語のまま扱われ、本番の応答は日本語で受け取れます。AdvPOのテンプレートはプレースホルダで変数を切り出す構造なので、この分離と相性が良い設計です。
加えて、AdvPOの採点にLLM-as-a-judgeを使う場合は、採点プロンプト側の言語も揃えておくほうが安定します。応答は日本語、採点基準は英語、正解データは日本語といった混在は、採点のばらつきをそのまま最適化の方向に持ち込むためです。
公式ドキュメントどおりに書くと落ちる箇所と回避策
AdvPOは追加されて日が浅く、ドキュメントのコード例と実際のAPIモデルにずれが残っています。botocore 1.43.68に同梱されているbedrockのサービスモデルを直接読んで確認した差分は次の3点です。いずれも2026年8月時点でドキュメント側は修正されていません。
| ドキュメントの記述 | 実際のAPI・別ページの記述 | 起きること |
|---|---|---|
| encryptionConfig パラメータ | encryptionKeyArn(KMSキーのARN文字列) | ParamValidationError で送信前に落ちる |
| batch_delete_advanced_prompt_optimization_jobs | batch_delete_advanced_prompt_optimization_job(単数形) | AttributeError |
| 上位ページは正解応答を required と記述 | スキーマ表では referenceResponse は Required = No | 不要な正解データ作成の手戻り |
1点目と2点目は、ParamValidatorでの検証とサービスモデルのオペレーション名から確認できます。IAMポリシーのアクション名も同じで、公式のprereqsページは該当セルにタブや空白が混入して壊れた表記になっているため、オペレーション名から補うとbedrock:BatchDeleteAdvancedPromptOptimizationJobです。3点目は、上位ページの「It also requires ground truth answers」と、入力スキーマ表の「referenceResponse … Required = No(Recommended for best optimization results)」が食い違っているケースです。実際には推奨であって必須ではありません。
加えて、AdvPO関連のAPIが入ったのはbotocore 1.43.8(2026年5月14日リリース)からです。1つ前の1.43.7にはオペレーションが1つも入っていません。それ以前のSDKではcreate_advanced_prompt_optimization_jobというメソッド自体が存在しないため、コードの誤りを疑う前にpip listでバージョンを確認してください。
もう1つの事故源が、入力JSONLの無言の失敗です。ドキュメントが「silent failure」と明記しているのは、1つのinputVariablesオブジェクトに複数キーを入れた場合。エラーにならず、意図しない結果が返ります。プレースホルダを一重の中かっこで書いた場合、評価方法を2つ指定した場合、customEvaluationMetricLabelを忘れた場合はValidationExceptionになります。これらはアップロード前にローカルで潰せます。
import json
import re
import sys
EVAL_KEYS = ("steeringCriteria", "customLLMJConfig", "evaluationMetricLambdaArn")
def check(obj):
errors = []
for key in ("version", "templateId", "promptTemplate", "evaluationSamples"):
if key not in obj:
errors.append("必須フィールド " + key + " が無い")
if obj.get("version") != "bedrock-2026-05-14":
errors.append("version が固定値と違う: " + repr(obj.get("version")))
if re.search(r"(?<!\{)\{[A-Za-z_]\w*\}(?!\})", obj.get("promptTemplate", "")):
errors.append("プレースホルダが一重の中かっこになっている")
placeholders = set(re.findall(r"\{\{(\w+)\}\}", obj.get("promptTemplate", "")))
keys = set()
for sample in obj.get("evaluationSamples", []):
for pair in sample.get("inputVariables", []):
if len(pair) != 1:
errors.append("inputVariables の 1 オブジェクトに複数キー: " + str(sorted(pair)))
keys |= set(pair)
if placeholders != keys:
errors.append("プレースホルダと inputVariables が不一致")
used = [k for k in EVAL_KEYS if k in obj]
if len(used) > 1:
errors.append("評価方法を併用している: " + str(used))
if used and used != ["steeringCriteria"] and "customEvaluationMetricLabel" not in obj:
errors.append("customEvaluationMetricLabel が無い")
return errors
ng = 0
for line_no, line in enumerate(open(sys.argv[1], encoding="utf-8"), 1):
if not line.strip():
continue
try:
obj = json.loads(line)
except json.JSONDecodeError as e:
print(line_no, "行目: JSONとして壊れている", e)
ng += 1
continue
for message in check(obj):
print(line_no, "行目:", message)
ng += 1
print("NG 0件。アップロードして問題ありません。" if ng == 0 else "NG " + str(ng) + "件。修正してください。")
sys.exit(1 if ng else 0)
手元で実際に動かした結果を書いておきます。一重の中かっこ・inputVariablesの複数キー・評価方法の併用・ラベル欠落という4か所の誤りを仕込んだ1行のJSONLを食わせると、指摘は5件出て終了コード1で止まりました。一重の中かっこは、それ自体の指摘に加えてプレースホルダとinputVariablesの不一致も引き起こすためです。50MBの入力を作り込んでからジョブを流し、数十分後にValidationExceptionを見るより安上がりな確認方法です。
ジョブが動き出してから失敗する原因として、公式のトラブルシューティング表の先頭に挙がっているのは、モデルアクセスが有効になっていないケースです。「No inference API is accessible for model」というメッセージが出たら、BedrockコンソールでのモデルアクセスとIAMのbedrock:InvokeModelWithResponseStream権限の両方を確認します。AdvPOは現在ConverseStream経由で推論するため、非ストリーミングのbedrock:InvokeModelだけでは足りません。
よくある質問
Amazon Bedrockのプロンプト最適化は無料ですか?
無料ではありません。シンプル最適化は、入力プロンプトと最適化後プロンプトの合計トークンに対して1,000トークンあたり0.03ドルが課金されます。Advanced Prompt Optimizationは機能自体の追加料金がない代わりに、最適化中に消費した推論トークンとLambda実行費がオンデマンド料金でかかります。
東京リージョンでプロンプト最適化は使えますか?
Advanced Prompt Optimizationはap-northeast-1(東京)に対応しています。一方でシンプル最適化は、モデル別の対応リージョン表に東京が含まれていません。東京でシンプル最適化を試したい場合は、us-east-1かus-west-2など対応リージョンで実行してください。
プロンプト管理(Prompt management)とプロンプト最適化はどう違いますか?
Prompt managementはプロンプトの作成・バージョン管理・デプロイを担う機能で、シンプル最適化はその画面から呼び出せる書き換え機能です。Prompt management自体は商用20とAWS GovCloud 2を合わせた22リージョンで利用でき、ap-northeast-1も含まれるため、プロンプトの保管場所と最適化を実行できる場所が一致しないことがあります。
最適化ボタンを押したとき、内部では何が行われていますか?
シンプル最適化はプロンプトの構成要素を分析し、分析に成功するとプロンプトを書き換えます。APIから叩くと、分析完了を示すanalyzePromptEventと書き換え結果のoptimizedPromptEventの2種類のイベントが順に返ってきます。Advanced Prompt Optimizationはこれに評価が加わり、推論・採点・書き換えのループを内部の最適化パラメータに従って繰り返します。
プロンプトキャッシュと組み合わせられますか?
プロンプト最適化とプロンプトキャッシュは別々の機能で、目的も違います。最適化は応答品質を上げるためにプロンプトの中身を書き換えるもの、キャッシュは同じ接頭辞を繰り返し送る際の入力トークン料金とレイテンシを下げるものです。最適化で確定したプロンプトを本番に載せる段階で、共通部分をキャッシュ対象にする使い分けになります。対応モデルや実装方法はAmazon Bedrockのプロンプトキャッシュとは|仕組み・対応モデル・料金・実装方法【2026年最新】にまとめています。
関連記事
- Amazon Bedrockの使い方|料金・モデル・APIの始め方を4ステップで解説【2026年版】
- Amazon Bedrock Converse APIの使い方|boto3実装・ConverseStream・Tool Use・IAM権限【2026年最新】
- Amazon Bedrockのプロンプトキャッシュとは|仕組み・対応モデル・料金・実装方法【2026年最新】
- Amazon Bedrock Flowsとは|ノード14種・料金・上限とboto3実装【2026年最新】
- StreamlitでチャットボットのUIを作る手順|st.chat_input・session_stateで会話履歴を保持する実装