はじめに
新しいモデルが出るたびに「今のプロンプトをそのまま流したら品質はどうなる?」と気になりつつ、手動で書き換えて並べて比較する作業がそれなりに重く、後回しになりがちです。Bedrock には以前から
OptimizePromptという同期APIのプロンプト最適化機能がありましたが、こちらは1モデル・1プロンプトを書き換えるだけのシンプルなものだった印象です。
2026年5月14日、これを拡張した Advanced Prompt Optimization and Migration Tool が Bedrock に追加されました。1ジョブで最大5モデル × 最大10テンプレートを横並びで最適化・評価できる非同期ジョブ型のツールで、モデル移行(migration)のためのベースライン取りにも使える内容になっていそうです。
忙しい人のための要約
- Bedrock に 非同期ジョブ型のプロンプト最適化機能が追加
- 1ジョブで最大5モデルを同時に比較可能
- 入力はテンプレート(最大10個)+ 評価サンプル(テンプレートあたり最大100件)の JSONL
- 画像・PDF などのマルチモーダル入力にも対応
- 評価方法は「自然言語の steering criteria」「LLM-as-a-judge(既定は Claude Sonnet 4.6)」「Lambda カスタム評価」から選択可能
- 追加料金は無く、内部で発生する モデル呼び出しトークン料金 + (使うなら)Lambda 料金だけが課金対象
Advanced Prompt Optimization とは
ざっくり言うと、「複数モデル × 複数プロンプトテンプレートを掛け合わせて最適化し、スコア・コスト・レイテンシーをまとめて出してくれる非同期ジョブ」です。
既存のシンプル版との違い
従来からある同期API(
bedrock-agent-runtimeの
OptimizePrompt)と並んで、新しい advanced 版が
bedrockサービス側のジョブAPIとして提供される形になっているようです。
| 観点 | 従来の Simple(OptimizePrompt) |
新しい Advanced |
|---|---|---|
| 実行方式 | 同期・数秒で完了 | 非同期ジョブ・15分〜数時間 |
| 対象モデル数 | 1 | 最大5モデルを同時比較 |
| プロンプト数 | 1(短めのもの) | 最大10テンプレート / ジョブ |
| 評価 | 書き換えのみ(評価なし) | steering criteria / LLM-judge / Lambda |
| マルチモーダル | 非対応 | png / jpg / PDF 対応 |
| 出力 | 書き換え後プロンプト | スコア + コスト推定 + TTFT レイテンシー |
「サクッと1本書き直したい」なら従来の同期APIで十分で、「モデル移行や本番投入前にちゃんと比較したい」なら advanced の方、という棲み分けかと思います。
全体のアーキテクチャ
ジョブを作ると Bedrock 側で対象モデルへの呼び出しと評価が走り、結果が S3 に書き出されます。
ジョブ実行のシーケンス
CLI から投げる場合の流れはおおむね以下のようになります。
やってみた
ドキュメント上は東京(
ap-northeast-1)も対応リージョンに含まれていますが、本記事執筆時点では東京のコンソール左ナビにまだ Advanced Prompt Optimization の項目が出てこなかったため、今回はバージニア北部(
us-east-1)で試します。
入力 JSONL を用意する
テンプレートは1行1オブジェクトのJSONLで書きます。読みやすさのため整形した形で示しますが、実際の
prompts.jsonlには 1テンプレートを1行に潰して 保存する点だけ注意です(複数テンプレートを比較したい場合は2行目以降に別オブジェクトを並べます)。
{
"version": "bedrock-2026-05-14",
"templateId": "summarize-ja",
"promptTemplate": "以下の議事録を3行で要約してください。\n\n{{minutes}}",
"evaluationSamples": [
{
"inputVariables": [
{
"minutes": "2026年5月15日 開発定例。出席:田中、佐藤、鈴木。CI/CDパイプラインの刷新を5月末までに完了する方針で合意。IaC部分は佐藤、モニタリング設定は鈴木が担当。次回は5月22日。"
}
],
"referenceResponse": "CI/CDパイプライン刷新を5月末までに完了することで合意した。IaCは佐藤、モニタリング設定は鈴木が担当する。次回ミーティングは5月22日。"
},
{
"inputVariables": [
{
"minutes": "2026年5月14日 リリース判定会議。出席:山田、田中。本番リリースは5月20日に決定。事前にステージング環境で負荷試験を実施し、山田が試験計画を5月16日までに作成する。"
}
],
"referenceResponse": "本番リリース日を5月20日に決定した。事前にステージング環境で負荷試験を実施する。山田が試験計画を5月16日までに作成する。"
}
],
"steeringCriteria": [
"日本語で出力",
"重要な決定事項とアクションアイテムを必ず含める",
"固有名詞は省略しない"
]
}
inputVariablesは オブジェクト1個ではなくオブジェクトの配列 で書く必要があります。
{"minutes": "..."} のように単体オブジェクトで書くと、Cannot deserialize value of type ArrayList<Map<String,String>> from Object valueで弾かれるので注意です。
referenceResponseは任意項目ですが、LLM-as-a-judge や Lambda評価で「期待出力との一致度」を見たい場合は入れておくと判定の質が安定するようです。
# 整形版 prompts.json → 1テンプレート1行の prompts.jsonl jq -c . prompts.json > prompts.jsonl wc -l prompts.jsonl # 1 行になっていることを確認 # 入出力バケット(Bedrock がアカウント用に作る既定のバケットを流用しています) INPUT_URI=s3://bedrock-123456789012-us-east-1-an/inputs/prompts.jsonl OUTPUT_URI=s3://bedrock-123456789012-us-east-1-an/outputs/ aws s3 cp prompts.jsonl "$INPUT_URI"
ジョブを作成する
ちょうど「Nova 1 Lite で動いている既存プロンプトを Nova 2 Lite に乗せ換えたい」という、まさにこのツールが想定するユースケースで投げてみます。比較対象は Nova 1 Lite (
us.amazon.nova-lite-v1:0) と Nova 2 Lite (
global.amazon.nova-2-lite-v1:0) の2モデルです。
aws bedrock create-advanced-prompt-optimization-job \
--region us-east-1 \
--job-name minutes-summarizer-2026-05-16 \
--input-config "s3Uri=$INPUT_URI" \
--output-config "s3Uri=$OUTPUT_URI" \
--model-configurations '[
{"modelId":"us.amazon.nova-lite-v1:0"},
{"modelId":"global.amazon.nova-2-lite-v1:0"}
]'
戻り値で
jobArn(例:
arn:aws:bedrock:us-east-1:123456789012:advanced-prompt-optimization-job/4a38ef56fdd9)が返ってくるので控えておきます。
ジョブの進捗を確認する
非同期なので、
get-advanced-prompt-optimization-jobでステータスを見ます。小さめのジョブで15〜20分、大きめだと数時間掛かることもあるようです。
JOB_ARN=arn:aws:bedrock:us-east-1:123456789012:advanced-prompt-optimization-job/4a38ef56fdd9 aws bedrock get-advanced-prompt-optimization-job \ --region us-east-1 \ --job-identifier "$JOB_ARN" \ --query 'jobStatus'
InProgress→
Completedになれば完了です。
結果を確認する
今回のジョブは約20分で
Completedになりました。出力先は固定で
{OUTPUT_URI}/{job-id}/advanced_prompt_optimization_results.jsonl というパスです。job-idは jobArn の末尾セグメント(今回なら
4a38ef56fdd9)です。
aws s3 ls "$OUTPUT_URI" --recursive
# outputs/4a38ef56fdd9/advanced_prompt_optimization_results.jsonl ← これが本体
aws s3 cp "${OUTPUT_URI}4a38ef56fdd9/advanced_prompt_optimization_results.jsonl" /tmp/apo_result.jsonl
中身は1テンプレート1行の JSONL で、トップレベルに
promptTemplateId/
promptTemplate/
steeringCriteria/
customEvaluationMetricLabel/
promptOptimizationResults(モデル別の配列)が並びます。
promptOptimizationResults[].dataset[]に各サンプルごとの生のモデル応答(
originalPromptModelResponse/
optimizedPromptModelResponse)と判官モデルの判定理由まで全部入っているので、後からスプレッドシートに流して人手レビューしたい用途にも使えそうです。
注意点として、ドキュメントには「コスト推定」も結果に含まれるような書き方がありますが、実際のJSONLにはトークン数(
inputTokens/
outputTokens)と TTFT(
ttftInSec)が入るだけで、$換算値そのものは出ません。料金見積もりは「平均トークン数 × Bedrock の現行単価」で自分で出す形になります。
平均メトリクスは
originalPromptMetrics/
optimizedPromptMetricsで取り出せます。今回のジョブの結果はこんな感じでした。
| モデル | 元プロンプト スコア | 最適化後 スコア | 入力トークン (元→最適化後) | 出力トークン (元→最適化後) | TTFT (元→最適化後) |
|---|---|---|---|---|---|
Nova 1 Lite (us.amazon.nova-lite-v1:0) |
0.892 | 1.000 | 84 → 380 | 69 → 52 | 0.407s → 0.373s |
Nova 2 Lite (global.amazon.nova-2-lite-v1:0) |
0.933 | 1.000 | 120 → 390 | 74 → 42 | 0.435s → 0.452s |
スコアは0〜1に正規化された数値で、両モデルとも最適化後は満点に到達しています。元のプロンプトでも Nova 2 Lite の方がベースが0.93と高めで、ベースモデル時点の品質差がそのまま見える形なので、移行判断のたたき台としては素直な出力です。
入力トークンが3〜4倍に増えているのは、最適化器が「禁則ルール」「変換例」「Few-shot 例」などをプロンプトに足し込んで品質を担保しているためです。たとえば Nova 1 Lite に対しては Few-shot 例まで埋め込まれていて、こんな形に書き換わっていました。
以下の議事録を、必ず独立した3行(3文)で要約してください。
【出力ルール】
- 各行は、それだけで意味が完結する独立した1文(主語または主題+述語が明確)にすること。
- 1つの行に複数の事実を「〜し、〜」「〜また〜」などの接続表現でまとめないこと。
- 会議の開催日・出席者など過去のメタ情報は省略すること。ただし、次回ミーティングの確定日程など今後のスケジュール情報はアクションアイテムとして扱い、省略しないこと。出力内容は決定事項・アクションアイテム(担当者・期限・次回予定を含む)の情報に絞ること。
- 各行は句点(。)で終わること。【出力例】
入力:「2026年3月10日 開発定例。出席:山田、田中。APIの認証方式をOAuthに変更することで合意。田中が仕様書を3月15日までに作成する。次回は3月17日。」
出力:
APIの認証方式をOAuthに変更することで合意した。
田中が仕様書を3月15日までに作成する。
次回ミーティングは3月17日に予定されている。
{{minutes}}
一方の Nova 2 Lite には Few-shot は付かず、ルールリスト + 言い回しの変換例で済んでいて、モデルごとに最適化方針が変わっているのが分かります。出力トークン数が小さくなっているのも、これらのルールが「冗長な前置きを削れ」という方向に寄与しているからのようです。
コンソールから見るのが一番楽で、Bedrock コンソールの左ナビに Advanced Prompt Optimization が追加されているので、そこからジョブを選ぶとモデル別のスコア表と最適化後プロンプトが並んで表示されていました。なお、出力S3オブジェクトを後から動かすとコンソールの結果ページが追従できなくなるとのことなので、結果が要らなくなるまでは出力先を触らない方が無難そうです。
料金
ツール自体には専用料金はなく、内部で行われるモデル呼び出しのオンデマンドトークン料金だけが課金対象とのことです。LLM-as-a-judge を使う場合の judge モデル呼び出しも、Lambda カスタム評価を使う場合の Lambda 実行料金も、それぞれ通常通り発生するイメージです。
サンプル数 × モデル数 × (ベースライン+候補プロンプト)の分だけ推論が発生するので、検証中は安価なモデルで小さいサンプル数から試して当たりをつけるのが現実的かと思います。
Judge モデルの既定
評価メソッドを自前で
customLLMJConfigで指定しない限り、判官役は既定で Claude Sonnet 4.6 が走るようです。今回のように steering criteria を渡した場合も、デフォルトの3観点(Answer Accuracy / Answer Completeness / Expression Quality)に「Output Language and Content Requirements」のような独自観点が動的に1つ追加され、重み付け込みで合計スコアが算出される挙動でした。
まとめ
- 単発の書き換えなら従来の
OptimizePrompt
、モデル移行の評価まで含めて回したいなら Advanced を、と棲み分けるのが良さそうです - 今回のような小さい検証(1テンプレ × 2サンプル × 2モデル)なら20分前後・$0.5以下に収まるので、社内プロンプトの棚卸し用に1本回してみるくらいなら気軽に試せそうな印象でした