Subchapter 25.33
references/phases/estimate/estimate-ai.mdMarkdown25 KBView on GitHub
Loaded when ai-workload-profile.json exists. Contributes estimation-ai.json (the assembler is its creator; see estimate.md). Execute ALL steps in order.
Fragment unit. This fragment to ; the artifact itself is declared on the assembler’s and written there — the same design-ai / aws-design-ai split, one layer over. prices the estate’s compute/database/storage/network; this file prices AI token spend and nothing else.
estimation-ai.json_producesestimate-infra.mdExecute ALL parts in order. Do not skip or optimize.
The parent estimate.md selects the pricing mode before loading this file.
Price lookup order:
shared/pricing-cache.md (primary) — Look up Bedrock model pricing and source
provider pricing by table. Set pricing_source: "cached".shared/pricing-fallback.md,
set pricing_source: "unavailable", emit null for the affected per-token fields, and warn
the user. Never fabricate a token price. An _unverified_ cache cell is blocking — do not
use it as if it were a confirmed price. There is no live pricing lookup to top the cache up.For typical migrations (Claude, Llama, Nova, Mistral, DeepSeek, Gemma, OpenAI gpt-oss, and the
proprietary GPT-5.x source rows), ALL prices are in pricing-cache.md.
Staleness: if pricing-cache.md is more than 30 days past its Last updated date, treat
AI prices as potentially stale, set pricing_source: "cached_stale", and note it — per that
file’s staleness warning.
Bedrock pricing is per-1M-tokens. Every generative Bedrock figure in pricing-cache.md is
stated per 1M input tokens and per 1M output tokens. Divide token counts by 1,000,000 before
multiplying by the rate. Embedding models are input-only — the § Embeddings — Bedrock table
gives a single per-1M-input rate and no output column; price an embedding workload as
input_tokens × rate (no output term), and compare against the § Embeddings — OpenAI / Azure OpenAI
source rate for the “$X today” baseline. A source text-embedding-3-* → Titan v2 move is a
re-embedding task (dimension change), not a free swap — carry the note into the estimate. There is no per-hour or baked-in-Multi-AZ dimension here — that RDS-style rule belongs
to estimate-infra.md and does NOT apply to token pricing.
Model lifecycle: When building the model comparison table, check
references/vendored/ai/ai-model-lifecycle.md and apply the 90-day exclusion rule:
model_comparison, recommended_model,
and backup_model.model_comparison with (Legacy — EOL YYYY-MM-DD)
annotation. Do not select as recommended_model unless no Active alternative exists.Read from $MIGRATION_DIR/:
ai-workload-profile.json — current_costs.monthly_ai_spend,
current_costs.services_detected, models[], metadata.profile_source,
summary.inferred_from_iac, integration.pattern.openai-usage-profile.json (if present) — summary.monthly_cost_usd,
usage_by_model[] (real per-model input/output token counts from the OpenAI / Azure OpenAI
usage API). Check metadata.capture_warnings first: a failed usage endpoint means that
category’s volume is UNKNOWN, not zero — say so in the output and do not price the affected
capability from this profile.preferences.json — ai_constraints.ai_token_volume.value,
ai_constraints.ai_capabilities_required.value.aws-design-ai.json — metadata.ai_source, ai_architecture.honest_assessment,
ai_architecture.tiered_strategy, ai_architecture.bedrock_models[] (with
source_provider_price, bedrock_price, honest_assessment, model_change),
ai_architecture.capability_mapping, and design_blocks[].Traditional-AI workloads (excluded from token cost): design_blocks[] entries with
target_aws_service set (capability document_extraction, image_analysis, or
speech_transcription → Textract, Rekognition, Transcribe) are per-page / per-image / per-minute
priced, not token priced, and this phase’s cost model does not cover them yet. Skip these blocks
in Parts 1–3; list them in the output under services_not_estimated[]
({workload_id, target_aws_service, reason: "not_token_priced"}) so the user knows they are
excluded rather than assumed free.
Determine current AI spending from the best available source. Four-level precedence, first match wins:
current_costs.monthly_ai_spend (preferred whenever present) — from
ai-workload-profile.json. This figure is already provider-aware: Discover merges billing
(an Azure Cost Management export) and OpenAI / Azure OpenAI usage-API spend there, summing
across providers with source: "mixed" and a per-provider breakdown[]. Do NOT bypass it by
reading openai-usage-profile.json → summary.monthly_cost_usd directly — that drops the
non-OpenAI half of a mixed workload. When breakdown[] exists, carry the per-provider split
into the comparison output. Partial-window check: if source is openai_usage_api or
mixed AND openai-usage-profile.json → metadata.partial_window is true, the OpenAI
portion is not a monthly baseline — apply level 2’s exception to that portion (reference figure
only, labeled with active_days; for mixed, keep the Azure portion from breakdown[] and
cover the OpenAI portion via levels 3–4).summary.monthly_cost_usd from
openai-usage-profile.json ONLY when no current_costs exists (standalone usage capture with
no AI workload profile). Exception: if metadata.partial_window is true, the window is
too short to be a monthly baseline — do NOT rank it above levels 3–4; fall back and present the
partial actuals as a reference figure only, labeled with active_days.ai_constraints.ai_token_volume.value from
preferences.json with OpenAI / Azure OpenAI source list prices from pricing-cache.md
(under “Source Provider Pricing → OpenAI / Azure OpenAI”). Azure OpenAI serves the same GPT
models and reads those same OpenAI rows — there is no separate Azure-OpenAI table. Apply the
60/40 input/output ratio if the actual ratio is unknown.Regardless of which dollar source wins, openai-usage-profile.json → usage_by_model[] remains
the Part 2 token-volume source (subject to the same partial_window exception there).
IaC-only profile: If metadata.profile_source is iac_cognitive or
summary.inferred_from_iac is true and billing/token data is missing, state explicitly that
current Azure AI spend is unverified and widen uncertainty bands (use the same multi-tier
comparison approach as in level 3).
Calculate the monthly Bedrock cost for every viable model at the user’s token volume.
Token volume mapping (from ai_token_volume in preferences.json):
ai_token_volume | Input tokens/month | Output tokens/month | Ratio |
|---|---|---|---|
"low" | 6M | 4M | 60/40 |
"medium" | 60M | 40M | 60/40 |
"high" | 600M | 400M | 60/40 |
"very_high" | 6B | 4B | 60/40 |
If the design or discover phase has more specific token estimates, use those instead. In
particular, when openai-usage-profile.json exists with metadata.partial_window false, use
its usage_by_model[] actual monthly input/output token totals (and actual ratio) instead of the
tier table — a real observed month beats a tier midpoint. Exception: if
metadata.partial_window is true, a few days of tokens is NOT a monthly volume — projecting it
as one understates the Bedrock estimate. Use the tier table (from ai_token_volume) and present
the partial actuals as a reference figure only, labeled with active_days.
Cost formula: Monthly = (input_tokens / 1M × input_rate) + (output_tokens / 1M × output_rate)
Long-context surcharge: If ai_critical_feature = "ultra_long_context" in preferences.json,
Claude models charge 2x the standard input rate for tokens beyond 200K context. Apply the
surcharge to the portion of input tokens that exceeds 200K per request. If per-request token
counts are unknown, assume 50% of input tokens fall in the long-context tier as a conservative
estimate.
Comparison table columns: Model, Bedrock Monthly, vs Source Provider ($ and %), vs Current
Azure, Quality, Capabilities Match (checked against ai_capabilities_required).
Include source provider pricing from aws-design-ai.json → bedrock_models[].source_provider_price.
If Bedrock is more expensive for the recommended model, flag prominently.
If embeddings are needed, add a separate line (additive to the primary model cost).
Using the model selected in the design phase, show:
Do not present human labor, contractors, professional services, or engineering effort as one-time migration costs or budget line items (no dollar figures, no “budget for people work” lists, no “one-time migration cost” categories for implementation).
Populate migration_cost_considerations.categories as an empty array []. Use
migration_cost_considerations.note to state that human and professional-services one-time
migration costs are intentionally excluded from this advisor.
Technical integration complexity (for internal JSON and risk context only — not framed as
money): from ai-workload-profile.json, record non-monetary factors in
migration_cost_considerations.complexity_factors[] as short strings, for example:
integration.pattern = "framework" → lower integration touch surfaceintegration.pattern = "direct_sdk" → moderate SDK and API pattern changesintegration.pattern = "rest_api" → higher endpoint, auth, and parsing changessummary.total_models_detected > 3 → multi-model coordinationquota_risk = "high" (from aws-design-ai.json) → Bedrock quota increase required before
migration; allow 1–5 business days (see vendored/ai/bedrock-quotas.md)Do not repeat these as “costs” in the user-facing summary.
Present the monthly and annual cost difference between current Azure AI spend and projected Bedrock cost:
model_change: false): projected cost is about 10% higher,
not the same — Bedrock in-region is priced at OpenAI’s data-residency tier, which is 1.10x
OpenAI / Azure OpenAI standard. Quote the increase plainly and make the case on non-cost
grounds. If any workload exceeds 272K context, price it at the long-context tier and show that
separately; it can dominate the comparison.Reference aws-design-ai.json → honest_assessment. If "recommend_stay", present prominently
along with honest_assessment_reason.
Non-cost benefits to present: usage counting toward existing AWS commitments, IAM/VPC/PrivateLink/KMS/CloudTrail governance, in-region processing for data residency, prompt caching (Claude, and GPT-5.6 at 90% off cached input with cached tokens exempt from the input-TPM quota), model flexibility (100+ models), AWS ecosystem (Guardrails, Knowledge Bases, AgentCore), and — for a same-model move — the elimination of behavior-delta and prompt-regression risk.
Pricing source caveat for OpenAI models: the AWS Price List API does not carry the
proprietary GPT-5.x models. A missing or empty price-list result is not evidence the model is
unavailable or free. Use shared/pricing-cache.md, and treat rows
marked unverified there as blocking for any quoted figure — resolve them from the Bedrock
pricing page first. See shared/openai-on-bedrock.md.
Note: Human / professional-services one-time migration costs are intentionally out of scope for this advisor and excluded from ROI calculations.
Present applicable optimizations with estimated savings:
| Optimization | Savings | Applies When |
|---|---|---|
| Model downsizing / tiering | 60-87% | High volume, premium model selected |
| Prompt caching (Claude) | ~30% | Repeated system prompts |
| Batch API | 50% | Non-real-time workloads (ai_latency = "flexible") |
| Provisioned throughput | Varies | Token volume > 100M/month, predictable traffic |
| Input token reduction | 10-30% | Prompt optimization, shorter context |
| Multi-model tiered routing | 60-87% | High/very-high volume, tiered_strategy in design |
For each applicable optimization, calculate before/after monthly cost and show an
optimized_projection (best-case monthly with all optimizations).
Post-migration optimization (do not surface during migration): Model distillation — training a smaller, faster student model from a larger teacher model — can reduce inference costs up to ~75% for high-volume, stable workloads. Requires production traffic, labeled examples, and a teacher/student eval loop. Mention in the estimate summary as: “Once you have 2–4 weeks of Bedrock production traffic, consider model distillation to further reduce costs. See docs.aws.amazon.com/bedrock/latest/userguide/model-distillation.html.” Do not recommend distillation before the startup has migrated and validated their workload.
Produce a clear migrate/stay/optimize verdict for the AI workload migration. This is the AI-only
equivalent of estimate-infra.md Part 8.
Decision logic:
| Condition | Verdict | recommendation.path |
|---|---|---|
Same model on Bedrock (model_change: false) — ~10% higher, short-context; non-cost benefits carry it | Migrate with caveat | migrate_optimized |
| Bedrock cheaper AND capabilities match | Migrate | migrate_optimized |
Bedrock more expensive BUT non-cost benefits justify (vendor diversification, Guardrails, multi-model) AND user priority ≠ cost | Migrate with caveat | migrate_optimized |
Bedrock more expensive AND user priority = cost AND no compelling non-cost reason | Stay | stay |
Design honest_assessment = recommend_stay | Stay | stay |
| Mixed (some workloads cheaper, some not) | Migrate selectively | migrate_phased |
Output fields (add to estimation-ai.json top-level):
"recommendation": {
"path": "migrate_optimized | migrate_phased | stay",
"path_label": "Migrate to Bedrock | Migrate selectively | Stay on current provider",
"migrate_if": "Brief condition under which migration makes sense (1 sentence)",
"stay_if": "Brief condition under which staying makes sense (1 sentence)",
"confidence": "high | medium | low",
"rationale": "2-3 sentence justification citing cost delta and non-cost factors"
}Rules:
recommendation — never omit. If data is insufficient, set confidence: "low" and
state why in rationale.honest_assessment from aws-design-ai.json says recommend_stay, recommendation.path
MUST be stay regardless of cost numbers.bedrock_models[].model_change is false, Bedrock in-region costs ~10% more than OpenAI /
Azure OpenAI standard for the same model. Report that figure rather than “no savings
identified”, and argue the case on commitments, governance, residency, prompt caching, and
eliminated behavior-delta risk. A ~10% increase alone should not route to stay unless
ai_priority = cost and no non-cost driver applies; a long-context workload at the 1M tier is a
different matter and may legitimately favour staying.migrate_phased and list which workloads to migrate vs. keep in rationale.The assembler writes estimation-ai.json to $MIGRATION_DIR/; this fragment contributes its
fields.
Schema — top-level fields:
| Field | Type | Description |
|---|---|---|
phase | string | "estimate" |
timestamp | string | ISO 8601 |
pricing_source | string | "cached", "live", "cached_fallback", "cached_stale", or "unavailable" |
accuracy_confidence | string | "±5-10%" or "±15-25%" |
current_costs | object | source, azure_monthly_ai_spend, services[] |
token_volume | object | source, monthly_input_tokens, monthly_output_tokens, ratio |
model_comparison | array | All viable models: model, monthly_cost, vs_current, quality, capabilities_match, missing_capabilities[] |
recommended_model | object | model, monthly_cost, breakdown (input/output/embeddings), rationale |
backup_model | object | model, monthly_cost, rationale |
embeddings | object | model, monthly_cost, monthly_tokens, note (if applicable) |
cost_comparison | object | current_azure_monthly, projected_bedrock_monthly, monthly_difference, annual_difference, percent_change |
migration_cost_considerations | object | categories[] (always []), complexity_factors[] (technical integration only), note (must state human/pro costs excluded) |
roi_analysis | object | monthly_cost_delta, annual_cost_delta, justification, non_cost_benefits[] |
optimization_opportunities | array | opportunity, potential_savings_monthly, implementation_effort, description |
optimized_projection | object | monthly_with_optimizations, vs_current, note |
recommendation | object | path, path_label, migrate_if, stay_if, confidence, rationale (see Part 7) |
services_not_estimated | array | Traditional-AI workloads excluded from token cost: {workload_id, target_aws_service, reason: "not_token_priced"} |
current_costs.azure_monthly_ai_spend (NOT gcp_monthly_ai_spend) and
cost_comparison.current_azure_monthly (NOT current_gcp_monthly) are the Azure field names.
All cost values are numbers, not strings. Output must be valid JSON.
recommendation field is present with non-empty path, path_label, migrate_if,
stay_if, and rationalerecommendation.path is one of: migrate_optimized, migrate_phased, stayhonest_assessment = recommend_stay, then recommendation.path = staymodel_comparison includes ALL viable Bedrock models, not just recommendedmodel_comparison are annotated with EOL dates (per
vendored/ai/ai-model-lifecycle.md)recommended_model is an Active model (not Legacy) unless no Active alternative existscapabilities_match checked against ai_capabilities_requiredrecommended_model.rationale references the user’s priority, preference, and volumeroi_analysis is honest — if migration increases cost, says sooptimization_opportunities only includes strategies relevant to the user’s workloadestimate-infra.md)migration_cost_considerations.categories is [] — no human one-time migration costsservices_not_estimated[] lists every traditional-AI workload (Textract/Rekognition/
Transcribe) with reason: "not_token_priced"Before returning control to estimate.md, require:
estimation-ai.json exists and passes the Validation Checklist above.If this gate fails: STOP and output: “estimate-ai did not produce a valid estimation-ai.json;
do not complete Phase 4.”
Note:
_asserthas no teeth here — a passing_assertonly confirms the file parses, not that it is correct. The Completion Handoff Gate above is judged by the oracle, not by_assert; treat the checklist, not schema-parseability, as the bar.
After the assembler writes estimation-ai.json, present under 25 lines:
Cost labeling rule: All dollar figures presented to the user MUST be labeled as “estimated monthly costs” or prefixed with “Est.” — never present raw dollar amounts as if they are exact.
The Generate phase uses estimation-ai.json:
recommended_model — Which Bedrock model to provision and testmigration_cost_considerations — complexity_factors[] only for integration risk
context; never present human one-time migration costs to the user (categories stays
[])optimization_opportunities — Which optimizations to implement and whencost_comparison — Cost monitoring targets and alerts in productionmodel_comparison — Fallback options if the recommended model doesn’t meet the quality barThis phase covers financial analysis ONLY for AI workloads.
FORBIDDEN — Do NOT include compute, database, storage, networking cost calculations, infrastructure provisioning, code migration examples, or detailed migration timelines.
Written alongside the other estimate AI consumers. Reads the aws-design-ai.json contract
(shared/schema-design-aws-ai.md, build step 2) and contributes estimation-ai.json, which the
Generate phase’s AI route (generation-ai.json) consumes in the next step.