
AWS Transformのモデル移行機能を実際に試してみた
こんにちは、せーのです。
2026年6月16日、AWS Transform に model-to-model migration assessment(生成 AI ワークロードの Bedrock 移行アセスメント)が追加されました。OpenAI や Google Gemini などサードパーティの SDK で組んだアプリのコードを ATX CLI エージェントがスキャンし、Amazon Bedrock への移行計画を自動生成してくれる、という機能です。
「AI エージェントが AI アプリの移行計画を作る」というメタな面白さもあり、気になっていたので早速試してみました。今回は TypeScript + @google/genai で組んだ Gemini Flash チャットボットを移行元に、ATX CLI でアセスメントを実行し、5 フェーズの実出力をそのまま追体験できる形で共有します。
結論から言うと、約 100 行の超小規模アプリでも、Discover から Recommend まで一通り回り、モデルマッピング・コスト試算・SDK before/after コード・移行ランブックまで自動生成できました。agent-minute 課金は 約 6 分・概算 $0.21 でした(後述)。Bedrock モデルアクセスの有効化は、アセスメント(計画生成)だけなら不要でした。
AWS Transform と本機能の位置づけ(おさらい)
AWS Transform には、用途ごとに次のような系統があります。
| 系統 | 主な用途 | 料金 |
|---|---|---|
| AWS Transform for Windows | .NET Framework → .NET Core/Linux | 無料 |
| AWS Transform for VMware | VMware vSphere → AWS | 無料 |
| AWS Transform for Mainframe | COBOL 等の解析・変換 | 無料 |
| Migration Assessment(別機能) | オンプレ TCO 分析・What-if シナリオ | 無料 |
| AWS Transform custom | コード/API/フレームワーク変換 | $0.035 / agent minute |
今回試した model-to-model migration assessment は、AWS Transform custom のマネージド変換カタログに 2026-06-16 追加されたものです。Java バージョンアップや AWS SDK 移行などと同列の ready-to-use 変換定義の一つ、という位置づけです。
混同しやすい点: 「Migration Assessment」という名前の、オンプレ TCO 分析機能とは別物です。DevelopersIO にも AWS Transform 移行評価 What-if の記事 がありますが、あちらはインフラ移行の話で、今回の生成 AI → Bedrock アセスメントとは目的が違います。
何ができるか
- 移行元: OpenAI、Google Gemini、Anthropic 直接 SDK、LiteLLM / Ollama 等
- 統合パターン: 直接 SDK、LangChain / LlamaIndex、CrewAI / LangGraph、マルチプロバイダー・ルーティング
- 出力: モデルマッピング表、コスト比較、SDK 移行ガイド(before/after コード)、優先順位付き移行ランブック
- 料金: Transform custom の標準料金($0.035 / agent minute)のみ。本変換自体の追加料金なし
制約(公式ドキュメントより)
| 項目 | 制約 |
|---|---|
| 対応言語 | Python、TypeScript/JavaScript(Java は coming soon) |
| リポジトリ規模 | 500 ファイル未満推奨 |
| 移行不可 | OpenAI Realtime API、Assistants API の永続スレッド、DALL·E 画像生成 等 |
| EOL モデル | EOL 90 日以内のモデルは推奨から除外 |
5 フェーズのワークフロー
model-to-model assessment は次の 5 フェーズで進みます。
Discover → Clarify → Map → Estimate → Recommend
| フェーズ | やること | 主な出力 |
|---|---|---|
| Discover | コードベースをスキャンし AI SDK・モデルを検出 | ai-workload-profile.json |
| Clarify | 優先事項を対話形式で質問 | preferences.json |
| Map | Bedrock 等価モデルを特定 | モデルマッピング表 |
| Estimate | 月額コスト・削減額を試算(精度 ±15〜25%) | コスト比較表 |
| Recommend | 移行計画・SDK コード・ランブックを生成 | adapter、setup スクリプト等 |
以降、実機で回したログをフェーズごとに見ていきます。
セットアップ
ATX CLI のインストール
curl -fsSL https://transform-cli.awsstatic.com/install.sh | bash
atx --version
# v3.2.0
最初に入っていた v1.0.0 では本変換が動かなかったので、atx update で v3.2.0 へ更新しました。古い CLI のままだと atx custom def list に変換定義が出てこないことがあるので、先にバージョン確認をおすすめします。
認証
AWS Transform CLI は、IDE 連携の login_session 型プロファイルをそのまま読めないことがあります(前回の Node.js Transform 記事 でも同様でした)。aws configure export-credentials で環境変数に橋渡しします。
eval "$(aws configure export-credentials --profile kiro-aws --format env)"
unset AWS_PROFILE
export AWS_REGION=ap-northeast-1
aws sts get-caller-identity
IAM 権限は AWSTransformCustomFullAccess が推奨です。CLI のみ使う場合は IAM Identity Center 不要(IAM-only で OK)です。
変換定義名の確認
What's New では mke-genai-model-migration という表記もありますが、実機の atx custom def list では次の名前でした。
$ atx custom def list
AWS/GenAI-to-Bedrock-Migration-Assessment
exec するときは AWS/GenAI-to-Bedrock-Migration-Assessment を指定してください。
移行元サンプルアプリ
今回の移行元は、@google/genai を直接使った TypeScript の Gemini Flash チャットボットです。AWS Transform が検出しやすいパターンを意図的に入れています。
GoogleGenAIクラスの直接インポート・使用ai.models.generateContent()の直接 SDK コールgemini-2.5-flash/gemini-2.5-flash-liteのティアード・ルーティング- マルチターン会話履歴(
history: Content[])
src/chatbot.ts(コア部分):
import { GoogleGenAI, type Content } from "@google/genai";
function selectModel(userMessage: string): string {
const isSimpleQuery = userMessage.length < 100 && !userMessage.includes("?");
return isSimpleQuery ? "gemini-2.5-flash-lite" : "gemini-2.5-flash";
}
export class GeminiChatbot {
private ai: GoogleGenAI;
private history: Content[] = [];
constructor() {
this.ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY ?? "" });
}
async chat(userMessage: string): Promise<string> {
const modelName = selectModel(userMessage);
this.history.push({ role: "user", parts: [{ text: userMessage }] });
const response = await this.ai.models.generateContent({
model: modelName,
contents: this.history,
config: { maxOutputTokens: 1024, temperature: 0.7 },
});
const assistantMessage = response.text ?? "";
this.history.push({ role: "model", parts: [{ text: assistantMessage }] });
return assistantMessage;
}
}
前提条件:
- リポジトリは Git 管理必須(
git init && git add -A && git commit) node_modulesは.gitignoreに入れ、コミットしない- ファイル数は 500 未満推奨(今回は 8 ファイル)
アセスメント実行
cd ~/work/aws-transform-m2m
atx custom def exec \
--code-repository-path ./gemini-flash-chatbot \
--transformation-name AWS/GenAI-to-Bedrock-Migration-Assessment \
--trust-all-tools
--trust-all-tools は、Clarify フェーズ以降のエージェント操作を自動承認するオプションです。付けない場合は TTY 上で質問に手動回答が必要になります。Clarify を対話で進めたい場合は外してください。
実行開始時のログ例:
$ atx custom def exec \
--code-repository-path ./gemini-flash-chatbot \
--transformation-name AWS/GenAI-to-Bedrock-Migration-Assessment \
--trust-all-tools
📝 Conversation log: .../logs/2026-06-17T05-16-42-conversation.log
Phase 1: Discover
Discover フェーズでは、コードと依存関係から AI ワークロードのプロファイルを生成します。今回の出力 ai-workload-profile.json の要点は次のとおりです。
{
"summary": {
"overall_confidence": 0.98,
"confidence_level": "very_high",
"total_models_detected": 2,
"languages_found": ["typescript"],
"ai_source": "gemini"
},
"models": [
{
"model_id": "gemini-2.5-flash",
"detected_via": ["code"],
"evidence": [
{
"source": "code",
"file": "src/chatbot.ts",
"line": 19,
"pattern": "return isSimpleQuery ? \"gemini-2.5-flash-lite\" : \"gemini-2.5-flash\""
}
],
"usage_context": "Primary chatbot model for complex queries and multi-turn conversation"
},
{
"model_id": "gemini-2.5-flash-lite",
"usage_context": "Cost-optimized model for simple/short queries via tiered routing"
}
],
"integration": {
"primary_sdk": "@google/genai",
"sdk_version": "^1.3.0",
"pattern": "direct_sdk",
"capabilities_summary": {
"text_generation": true,
"streaming": false,
"function_calling": false
}
}
}
confidence 0.98 で 2 モデルを検出し、selectModel() のティアード・ルーティングまで正確に把握していました。import { GoogleGenAI } や package.json の @google/genai ^1.3.0 も detection_signals として記録されています。
Phase 2: Clarify
Clarify フェーズでは、ATX が 10 問を 2 バッチに分けて質問してきます。--trust-all-tools を付けていても、TTY 上では次のような対話が表示されました。
バッチ 1(Q1-5: AI 戦略):
ATX: 5 quick questions (reply like "A, E, A, B, A"):
1. Framework: A) Direct API *(detected)* | B) Router | C) LangChain | ...
2. Priority: A) Quality | B) Speed | C) Cost | E) Balanced | F) Don't know
3. Monthly spend: A) <$500 | B) $500–$2K | C) $2K–$10K | D) >$10K
4. Cross-cloud: A) Latency critical | B) Acceptable | C) Egress concern | D) Test first
5. Model: A) Gemini Flash *(detected)* | B) Gemini Pro | J) Other
> A, C, A, B, A ← Direct API / Cost 優先 / <$500 / Latency acceptable / Gemini Flash
バッチ 2(Q6-10: 技術要件):
ATX: Last section — 5 questions about your technical requirements:
Q6. Input types: A) Text only | B) Vision required | C) Audio/Video
Q7. Monthly volume: A) < 1M tokens | B) 1–10M | C) 10–100M | D) > 100M
Q8. Response speed: A) Critical (<500ms) | B) Important (<2s) | C) Flexible
Q9. Complexity: A) Simple | B) Moderate | C) Complex
Q10. Features: A) Function calling | ... | J) None
> A, A, B, B, J
回答は preferences.json に反映されます。
{
"ai_constraints": {
"ai_framework": { "value": ["direct"], "chosen_by": "extracted" },
"ai_priority": { "value": "cost", "chosen_by": "user" },
"ai_monthly_spend": { "value": "<$500", "chosen_by": "user" },
"cross_cloud": { "value": "latency-acceptable", "chosen_by": "user" },
"ai_model_baseline":{ "value": "claude-haiku-4-5", "chosen_by": "user" },
"ai_vision": { "value": "text-only", "chosen_by": "user" },
"ai_token_volume": { "value": "low", "chosen_by": "user" },
"ai_latency": { "value": "important", "chosen_by": "user" },
"ai_complexity": { "value": "moderate", "chosen_by": "user" }
}
}
Q2 で Cost を選んだのに ai_model_baseline が claude-haiku-4-5 になっている点は、最初モヤッとしました。ATX は Q5 の Gemini Flash を source モデルとして認識し、コスト優先の場合は Haiku 相当の Nova Micro/Lite を推奨する内部マッピングを使っている、と理解しました。
TTY について: Clarify は完全にインタラクティブ TTY 必須です。非対話環境から stdin をパイプすると cursorTo is not a function エラーになりました。自動化する場合は tmux + send-keys、または --trust-all-tools で可能な部分を自動承認する、という選択になります。
Phase 3: Map(Design)
Map フェーズでは、検出したモデルと優先事項に基づき Bedrock 等価モデルを提案します。ATX が出力したサマリーは次のとおりです。
ATX: Design Summary:
| Source Model | Bedrock Model | Price (in/out per 1M) | Savings | Assessment |
|-----------------------|--------------------|-----------------------|-------------|----------------|
| gemini-2.5-flash | Nova Lite (v1:0) | $0.06 / $0.24 | 88% cheaper | Strong migrate |
| gemini-2.5-flash-lite | Nova Micro (v1:0) | $0.035 / $0.14 | 53% cheaper | Strong migrate |
capability_gaps は 空配列 でした。テキスト生成のみのアプリなので、機能ギャップなし、という判断です。
ティアード・ルーティングについては、次の警告も出ています。
These models work as a cascade/routing pattern (flash-lite for simple queries, flash for complex).
Test the Bedrock replacement pair together — validate that Nova Micro's quality is acceptable
for simple queries before testing Nova Lite for complex queries.
simple → Nova Micro、complex → Nova Lite のペアは、セットで品質検証が必要、という注意ですね。
Phase 4: Estimate
Estimate フェーズでは、推定トークン量に基づく月額コストを試算します。公式・ATX ともに精度 ±15〜25% と明記されています。数字はその前提で読む必要があります。
ATX: Cost Estimation Summary (cached pricing, ±15-25% accuracy):
| Model Option | Monthly Cost | vs Current ($7.74/mo) |
|--------------------------------------|--------------|------------------------|
| Nova Lite + Nova Micro (recommended) | $1.10 | -86% |
| Nova Micro only | $0.77 | -90% |
| Llama 4 Scout | $3.66 | -53% |
| Llama 4 Maverick | $5.32 | -31% |
| Claude Haiku 4.5 | $26.00 | +236% |
Recommended: Nova Lite + Nova Micro = $1.10/mo (saves $6.64/mo, $79.68/yr)
Optimization: Nova Micro only (if quality acceptable) → $0.77/mo (-90%)
推奨は Nova Lite + Nova Micro の組み合わせで、現状推定 $7.74/月に対し $1.10/月(-86%) という試算でした。Nova Micro 一本化なら $0.77/月(-90%) まで下がる見込みですが、品質確認が前提です。
料金根拠は Amazon Bedrock 料金 のキャッシュ済み単価です。実際の請求は利用量・リージョン・プロンプト長で変わるので、±15〜25% の幅を見込んでおくのがよさそうです。
Phase 5: Recommend(Generate)
Recommend フェーズでは、移行計画・SDK コード・セットアップスクリプト・テストハーネスまで生成されます。
移行計画(2 週間)
generation-ai.json から抜粋した migration_plan です。
{
"migration_plan": {
"total_weeks": 2,
"approach": "direct_sdk_swap",
"phases": [
{
"name": "Setup & Development (Week 1)",
"activities": [
"Enable Bedrock model access (Nova Lite, Nova Micro) in us-east-1",
"Create IAM role with bedrock:InvokeModel permission",
"Install @aws-sdk/client-bedrock-runtime",
"Develop Bedrock provider adapter replacing @google/genai calls",
"Implement AI_PROVIDER feature flag for gradual rollout",
"Preserve tiered routing logic (simple → Nova Micro, complex → Nova Lite)"
]
},
{
"name": "Testing & Rollout (Week 2)",
"activities": [
"Deploy to staging with AI_PROVIDER=bedrock",
"A/B comparison: 100+ representative prompts",
"Gradual rollout: 10% → 50% → 100%",
"Monitor 48h at 100%"
]
}
]
}
}
Week 1 で SDK 差し替えと feature flag、Week 2 で A/B 比較と段階ロールアウト、という現実的な段取りになっていました。
SDK before/after コード
ATX が生成した before/after の対比です。
Before(@google/genai SDK):
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({ apiKey: GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: modelName, // "gemini-2.5-flash" or "gemini-2.5-flash-lite"
contents: history, // Content[] 形式
config: {
systemInstruction,
maxOutputTokens: 1024,
temperature: 0.7
}
});
const text = response.text;
After(Bedrock Converse API):
import { BedrockRuntimeClient, ConverseCommand } from '@aws-sdk/client-bedrock-runtime';
const client = new BedrockRuntimeClient({ region: 'us-east-1' });
const response = await client.send(new ConverseCommand({
modelId: modelName, // "amazon.nova-lite-v1:0" or "amazon.nova-micro-v1:0"
messages: messages, // {role, content: [{text}]}[] 形式
system: [{ text: systemInstruction }],
inferenceConfig: {
maxTokens: 1024,
temperature: 0.7
}
}));
const text = response.output.message.content[0].text;
違いを整理すると、Gemini SDK は API キー認証で generateContent() を呼び、Bedrock Converse API は IAM 認証で ConverseCommand を送る、というイメージです。
| 項目 | Gemini SDK | Bedrock Converse API |
|---|---|---|
| クライアント | new GoogleGenAI({apiKey}) |
new BedrockRuntimeClient({region}) |
| メソッド | ai.models.generateContent() |
client.send(new ConverseCommand()) |
| モデル指定 | model: "gemini-2.5-flash" |
modelId: "amazon.nova-lite-v1:0" |
| ロール | role: "model" |
role: "assistant" |
| コンテンツ形式 | parts: [{text}] |
content: [{text}] |
| システムプロンプト | config.systemInstruction |
system: [{text}](トップレベル) |
| レスポンス取得 | response.text |
response.output.message.content[0].text |
生成された成果物
.migration/0617-0517/ai-migration/
├── provider_adapter.js # gemini/bedrock/shadow 3モードの Provider Adapter
├── setup_bedrock.sh # Bedrock セットアップ(dry-run 対応)
└── test_comparison.py # Gemini vs Bedrock A/B テストハーネス
ロールバック計画も feature flag ベースで出力されていました。
{
"mechanism": "feature_flag",
"flag_name": "AI_PROVIDER",
"default_value": "gemini",
"rollback_time": "instant (env var change)",
"triggers": [
"Response quality below 80% of Gemini baseline",
"P95 latency > 2x Gemini baseline for 5 minutes",
"Error rate > 1% for 5 consecutive minutes"
]
}
ATX は結果をローカルのステージングブランチにもコミットします。
Branch: atx-result-staging-20260617_051633_d4197220
Commit: Step 1: Complete Gemini-to-Bedrock migration assessment.
Phases: Discover (detected gemini-2.5-flash + flash-lite),
Clarify (AI-only, cost priority),
Design (Nova Lite + Nova Micro, 86% savings),
Estimate ($7.74/mo → $1.10/mo),
Generate (setup script, provider adapter, test harness, migration guide)
実測コスト
| 項目 | 実測値 |
|---|---|
| 実行日時 | 2026-06-17 14:17〜15:12 JST |
| ATX CLI | v3.2.0 |
| 壁時計 | 約 55 分 |
| 推定 active 処理時間 | 約 6 分 |
| 概算 agent-minute | 約 6 min |
| 概算課金 | 約 $0.21($0.035 × 6) |
| Bedrock モデルアクセス | アセスメントのみなら不要(今回未使用) |
agent-minute はサーバー側エージェントの稼働時間のみ課金対象で、ローカルのビルド待ちやユーザー待機は含まれません。正確な精算は AWS Billing / Cost Explorer で確認するのが確実です。
ハマったところ・運用 Tips
今回つまずいた点を、再現時のチェックリストとしてまとめます。
- ATX v1.0.0 では動かない →
atx updateで v3.2.0 へ - Git 管理必須 →
git init && git add -A && git commit後に exec - node_modules をコミットしない →
.gitignore+git rm -r --cached node_modules/ - SSO プロファイルは
AWS_PROFILEだけでは足りない →export-credentialsで環境変数に橋渡し - Clarify は TTY 必須 → 非対話環境では
cursorTo is not a function。tmux か--trust-all-tools - ATX の実行リージョンは us-east-1 デフォルト →
AWS_REGION=ap-northeast-1を設定しても Transform 本体は us-east-1 で動く - 変換名は list で確認 → What's New の
mke-genai-model-migration表記と実名が異なる
まとめ
AWS Transform の model-to-model migration assessment を、Gemini Flash チャットボット(約 100 行)で試してみて感じたのは次の 3 点です。
要点
- 5 フェーズで移行計画が一通り出る: モデル検出 → 優先事項ヒアリング → Bedrock マッピング → コスト試算 → SDK コード・ランブック生成まで、CLI ログと JSON で追える
- コスト試算はたたき台として有用: ±15〜25% 精度なので盲信は禁物だが、Nova Lite/Micro など候補比較の起点になる
- SDK 移行の before/after がそのまま使える: Converse API への書き換え例、feature flag 付きロールバック計画まで含まれる
向いているケース
- OpenAI / Gemini 直接 SDK の小〜中規模アプリで、Bedrock 移行前に概算と計画が欲しい
- ティアード・ルーティングや LangChain 等のフレームワーク利用を、Bedrock 等価に置き換えたい
- AWS コミットメントへの支出集約や IAM/VPC 統合を検討している
向いていないケース
- Realtime API や画像生成など、移行不可機能に依存している
- 500 ファイル超の大規模モノレポ(サービス単位でディレクトリを切って実行が必要)
- コスト試算の数字だけで移行 GO を決めたい(必ず A/B テストと本番相当の検証が必要)
次のステップ
今回は アセスメント(計画生成)まで で、Phase 5 の before/after に従って Nova Lite で実際に Bedrock invoke する検証は未実施です。移行を進める場合は、生成された setup_bedrock.sh と test_comparison.py を使い、100+ プロンプトでの品質比較 → 段階ロールアウト、という流れがランブックに書かれていました。
もっとスマートな移行ノウハウや、大規模モノレポでの運用方法をお持ちの方がいれば、ぜひ DevelopersIO のコメントや X などで教えてください。










