> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fireworks.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Training cost estimator

> Estimate Managed Training, compare Fireworks Serverless with Dedicated, or compare Fireworks Dedicated with Tinker

export const TrainingCostEstimator = () => {
  const estimateTrainingCost = ({surface, method, tokenMillions, paramCount, managedRates, serverlessRates, tinkerRates, effectiveRatePerM}) => {
    if (method === "rl") return {
      route: "contact-training"
    };
    let rate = null;
    if (surface === "managed") {
      const tier = managedRates.find(candidate => candidate.maxParams === null || paramCount <= candidate.maxParams) || managedRates[managedRates.length - 1];
      rate = method === "sft" ? tier.sft : tier.dpo;
    } else if (surface === "serverless") {
      rate = serverlessRates?.train ?? null;
    } else if (surface === "tinker") {
      rate = tinkerRates?.train ?? null;
    } else if (surface === "dedicated") {
      rate = effectiveRatePerM ?? null;
    }
    if (!rate) return {
      route: "contact-training"
    };
    const center = Math.max(0, Number(tokenMillions) || 0) * rate;
    return {
      route: "estimate",
      rate,
      low: center * 0.7,
      high: center * 1.3
    };
  };
  const dpoCostBreakdown = ({policyTokenMillions, referenceTokenMillions, rates}) => {
    if (!rates?.train || !rates?.prefill) return null;
    const policyCost = policyTokenMillions * rates.train;
    const referenceCost = referenceTokenMillions * rates.prefill;
    return {
      policyCost,
      referenceCost,
      baseline: policyCost + referenceCost
    };
  };
  const surfaceAvailability = ({model, surface, method, shape, maxExampleTokens}) => {
    if (!model) {
      return {
        available: false,
        note: "No model selected."
      };
    }
    if (surface === "managed" && !(method === "sft" ? model.managedSft : model.managedDpo)) {
      return {
        available: false,
        note: "Not available for this model and method."
      };
    }
    if (surface === "serverless" && !model.serverless) {
      return {
        available: false,
        note: "Not available on Serverless Training."
      };
    }
    if (surface === "dedicated" && !shape) {
      return {
        available: false,
        note: "No compatible Dedicated shape."
      };
    }
    if (surface !== "dedicated" && shape && shape.method !== "LoRA") {
      const surfaceLabel = surface === "managed" ? "Managed" : surface === "serverless" ? "Serverless Training" : "Tinker";
      return {
        available: false,
        note: `${surfaceLabel} is LoRA only in this comparison. Choose a Dedicated LoRA shape for a parameter-mode-matched comparison.`
      };
    }
    let context = null;
    if (surface === "managed") {
      context = method === "sft" ? model.managedSftContext : model.managedDpoContext;
    } else if (surface === "serverless") {
      context = model.serverless?.context ?? null;
    } else if (surface === "dedicated") {
      context = shape?.context ?? null;
    } else {
      return {
        available: true
      };
    }
    if (!context) {
      return {
        available: false,
        note: "No published context limit is available for this path."
      };
    }
    if (maxExampleTokens > context) {
      return {
        available: false,
        note: `The configured ${maxExampleTokens.toLocaleString()}-token sequence exceeds this path's ${context.toLocaleString()}-token context limit.`
      };
    }
    return {
      available: true,
      context
    };
  };
  const selectDefaultShape = (model, shapeId) => model?.dedicated.find(shape => shape.id === shapeId) || model?.dedicated.find(shape => shape.method === "LoRA") || model?.dedicated[0];
  const shouldShowTinkerComparison = (dedicatedResult, tinkerResult) => !dedicatedResult?.unavailable && !dedicatedResult?.suppressComparisons && dedicatedResult?.display !== "Contact us" && !tinkerResult?.unavailable;
  const ESTIMATOR_CATALOG = {
    "generatedAt": "2026-09-07 19:00 UTC",
    "benchmarkGeneratedAt": "2026-08-30T23:59:00Z",
    "gpuPriceEffective": "2026-09-01",
    "gpuPriceSource": "https://fireworks.ai/pricing",
    "gpuRates": {
      "H100": 8,
      "H200": 8,
      "B200": 13,
      "B300": 15,
      "GB300": 20
    },
    "managedRates": [{
      "maxParams": 16000000000,
      "sft": 0.5,
      "dpo": 1
    }, {
      "maxParams": 80000000000,
      "sft": 3,
      "dpo": 6
    }, {
      "maxParams": 300000000000,
      "sft": 6,
      "dpo": 12
    }, {
      "maxParams": null,
      "sft": 10,
      "dpo": 20
    }],
    "models": [{
      "id": "deepseek-v4-flash",
      "label": "DeepSeek-V4-Flash",
      "paramCount": 284000000000,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "deepseek-v4-flash-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B300",
        "effectiveRatePerM": 1.95380156,
        "policyEffectiveRatePerM": 1.95380156,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "deepseek-v4-flash-0731",
      "label": "DeepSeek-V4-Flash-0731",
      "paramCount": 304000000000,
      "managed": false,
      "managedSft": false,
      "managedDpo": false,
      "managedSftContext": null,
      "managedDpoContext": null,
      "serverless": {
        "prefill": 1.74,
        "cached": 0.35,
        "sample": 4.33,
        "train": 5.2,
        "context": 262144
      },
      "dedicated": [{
        "id": "deepseek-v4-flash-0731-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B300",
        "effectiveRatePerM": 2.55859175,
        "policyEffectiveRatePerM": 2.55859175,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "deepseek-v4-pro-0813",
      "label": "DeepSeek-V4-Pro-0813",
      "paramCount": 1600000000000,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "deepseek-v4-pro-0813-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "gemma-4-26b-a4b-it",
      "label": "Gemma 4 26B A4B IT",
      "paramCount": 26000000000,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "gemma-4-26b-a4b-256k-b200",
        "method": "Full-Param",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 1.43634478,
        "policyEffectiveRatePerM": 1.43634478,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "gemma-4-26b-a4b-256k-b200-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 1.31918379,
        "policyEffectiveRatePerM": 1.31918379,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "gemma-4-31b-it",
      "label": "Gemma 4 31B IT",
      "paramCount": 32216731964,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "gemma-4-31b-256k-b200",
        "method": "Full-Param",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 4.01300674,
        "policyEffectiveRatePerM": 4.01300674,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "price-sweep"
      }, {
        "id": "gemma-4-31b-256k-b200-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 4.00960469,
        "policyEffectiveRatePerM": 4.00960469,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "glm-5p1",
      "label": "GLM 5.1",
      "paramCount": 743911218432,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 204785,
      "managedDpoContext": 204785,
      "serverless": null,
      "dedicated": [{
        "id": "glm-5p1-200k-lora",
        "method": "LoRA",
        "context": 204785,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": 8.34545987,
        "policyEffectiveRatePerM": 8.34545987,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "glm-5p2-fp8",
      "label": "GLM 5.2 FP8",
      "paramCount": 743911218432,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 204736,
      "managedDpoContext": 204736,
      "serverless": null,
      "dedicated": [{
        "id": "glm-5p2-200k-lora",
        "method": "LoRA",
        "context": 204736,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "glm-5p3",
      "label": "GLM-5.3",
      "paramCount": 743377019904,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 204736,
      "managedDpoContext": 204736,
      "serverless": null,
      "dedicated": [{
        "id": "glm-5p3-204k-b300-lora",
        "method": "LoRA",
        "context": 204736,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "kimi-k2p5",
      "label": "Kimi K2.5",
      "paramCount": 1028542417904,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "kimi-k2p5-text-only-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": 9.60807499,
        "policyEffectiveRatePerM": 9.60807499,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "kimi-k2p6",
      "label": "Kimi K2.6",
      "paramCount": 1028542417904,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "kimi-k2p6-text-only-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": [{
        "id": "moonshotai/Kimi-K2.6",
        "context": 32768,
        "prefill": 2.205,
        "cached": 0.441,
        "sample": 5.49,
        "train": 4.84,
        "note": null
      }, {
        "id": "moonshotai/Kimi-K2.6:peft:131072",
        "context": 131072,
        "prefill": 5.15,
        "cached": 1.03,
        "sample": 12.81,
        "train": 15.4,
        "note": null
      }]
    }, {
      "id": "kimi-k2p7-code",
      "label": "Kimi K2.7 Code",
      "paramCount": 1028542417904,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "kimi-k2p7-coder-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "kimi-k3",
      "label": "Kimi K3",
      "paramCount": 2780913302112,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 524288,
      "managedDpoContext": 524288,
      "serverless": {
        "prefill": 10.87,
        "cached": 2.17,
        "sample": 27.11,
        "train": 32.55,
        "context": 196608
      },
      "dedicated": [{
        "id": "kimi-k3-512k-lora",
        "method": "LoRA",
        "context": 524288,
        "gpus": "32 \u00d7 B300",
        "effectiveRatePerM": 16.94657163,
        "policyEffectiveRatePerM": 16.94657163,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "llama-v3p1-8b-instruct",
      "label": "Llama 3.1 8B Instruct",
      "paramCount": 8835567616,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 131072,
      "managedDpoContext": 131072,
      "serverless": null,
      "dedicated": [{
        "id": "llama-v3p1-8b-instruct-128k-lora",
        "method": "LoRA",
        "context": 131072,
        "gpus": "1 \u00d7 H200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "llama-v3p2-3b-instruct",
      "label": "Llama 3.2 3B Instruct",
      "paramCount": 3606752256,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 131072,
      "managedDpoContext": 131072,
      "serverless": null,
      "dedicated": [{
        "id": "llama-v3p2-3b-instruct-128k-lora",
        "method": "LoRA",
        "context": 131072,
        "gpus": "1 \u00d7 H200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "llama-v3p3-70b-instruct",
      "label": "Llama 3.3 70B Instruct",
      "paramCount": 77264592896,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 131072,
      "managedDpoContext": 131072,
      "serverless": null,
      "dedicated": [{
        "id": "llama-v3p3-70b-instruct-128k-lora-b200",
        "method": "LoRA",
        "context": 131072,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }, {
        "id": "llama-v3p3-70b-instruct-64k-lora-b200",
        "method": "LoRA",
        "context": 65536,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "minimax-m3",
      "label": "Minimax M3",
      "paramCount": 428000000000,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 229376,
      "managedDpoContext": 229376,
      "serverless": null,
      "dedicated": [{
        "id": "minimax-m3-256k-lora",
        "method": "LoRA",
        "context": 229376,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "ministral-3-3b-instruct-2512",
      "label": "Ministral 3 3B Instruct 2512",
      "paramCount": 3000000000,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 16384,
      "managedDpoContext": 16384,
      "serverless": null,
      "dedicated": [{
        "id": "ministral-3-3b-instruct-2512-16k",
        "method": "Full-Param",
        "context": 16384,
        "gpus": "1 \u00d7 B200",
        "effectiveRatePerM": 1.53533679,
        "policyEffectiveRatePerM": 1.53533679,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "ministral-3-3b-instruct-2512-16k-lora",
        "method": "LoRA",
        "context": 16384,
        "gpus": "1 \u00d7 B200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "mistral-small-24b-instruct-2501",
      "label": "Mistral Small 24B Instruct 2501",
      "paramCount": 23572403200,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 32768,
      "managedDpoContext": 32768,
      "serverless": null,
      "dedicated": [{
        "id": "mistral-small-24b-instruct-2501-32k-lora",
        "method": "LoRA",
        "context": 32768,
        "gpus": "1 \u00d7 H200",
        "effectiveRatePerM": 1.03122807,
        "policyEffectiveRatePerM": 1.03122807,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "muse-glimmer-30b",
      "label": "Muse Glimmer 30B",
      "paramCount": 29776626688,
      "managed": false,
      "managedSft": false,
      "managedDpo": false,
      "managedSftContext": null,
      "managedDpoContext": null,
      "serverless": {
        "prefill": 1.96,
        "cached": 0.39,
        "sample": 4.88,
        "train": 5.86,
        "context": 131072
      },
      "dedicated": [{
        "id": "muse-glimmer-30b-131k-lora",
        "method": "LoRA",
        "context": 131072,
        "gpus": "1 \u00d7 B200",
        "effectiveRatePerM": 0.98234796,
        "policyEffectiveRatePerM": 0.98234796,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "nemotron-3-super-120b-a12b-bf16",
      "label": "NVIDIA Nemotron 3 Super 120B A12B BF16",
      "paramCount": 120000000000,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "nemotron-3-super-120b-a12b-bf16-262k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "8 \u00d7 H200",
        "effectiveRatePerM": 1.50807097,
        "policyEffectiveRatePerM": 1.50807097,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "nemotron-3-super-120b-a12b-bf16-128k-lora",
        "method": "LoRA",
        "context": 131072,
        "gpus": "8 \u00d7 B200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "nemotron-3-ultra-bf16",
      "label": "NVIDIA Nemotron 3 Ultra BF16",
      "paramCount": 549308108800,
      "managed": false,
      "managedSft": false,
      "managedDpo": false,
      "managedSftContext": null,
      "managedDpoContext": null,
      "serverless": null,
      "dedicated": [{
        "id": "nemotron-3-ultra-550b-a55b-bf16",
        "method": "Full-Param",
        "context": 131072,
        "gpus": "16 \u00d7 B300",
        "effectiveRatePerM": 7.61631836,
        "policyEffectiveRatePerM": 7.61631836,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "nemotron-3-ultra-550b-a55b-bf16-lora",
        "method": "LoRA",
        "context": 131072,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": 5.88906509,
        "policyEffectiveRatePerM": 5.88906509,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "nemotron-nano-3-30b-a3b",
      "label": "NVIDIA Nemotron Nano 3 30B A3B",
      "paramCount": 31577937344,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "nemotron-nano-3-30b-a3b-262k-b200-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "2 \u00d7 B200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }, {
        "id": "nemotron-nano-3-30b-a3b-262k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "2 \u00d7 H200",
        "effectiveRatePerM": 0.64183239,
        "policyEffectiveRatePerM": 0.64183239,
        "referenceForwardRatePerM": 0.21382009,
        "benchmarkSource": "price-sweep"
      }],
      "tinker": []
    }, {
      "id": "qwen2p5-32b-instruct",
      "label": "Qwen 2.5 32B Instruct",
      "paramCount": 32763876352,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 32768,
      "managedDpoContext": 32768,
      "serverless": null,
      "dedicated": [{
        "id": "qwen2p5-32b-instruct-32k-lora",
        "method": "LoRA",
        "context": 32768,
        "gpus": "4 \u00d7 H200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "qwen3-0p6b",
      "label": "Qwen 3 0.6B",
      "paramCount": 751632384,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 65536,
      "managedDpoContext": 65536,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3-0p6b-65k-lora",
        "method": "LoRA",
        "context": 65536,
        "gpus": "1 \u00d7 B200",
        "effectiveRatePerM": 0.2805053,
        "policyEffectiveRatePerM": 0.2805053,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "qwen3-14b",
      "label": "Qwen 3 14B",
      "paramCount": 14768307200,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 131072,
      "managedDpoContext": 131072,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3-14b-128k-lora",
        "method": "LoRA",
        "context": 131072,
        "gpus": "2 \u00d7 H200",
        "effectiveRatePerM": 2.9108007,
        "policyEffectiveRatePerM": 2.9108007,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "qwen3-235b-a22b-instruct-2507",
      "label": "Qwen 3 235B A22B Instruct 2507",
      "paramCount": 235093634560,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 128000,
      "managedDpoContext": 128000,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3-235b-a22b-instruct-2507-128k-lora",
        "method": "LoRA",
        "context": 128000,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "qwen3-32b",
      "label": "Qwen 3 32B",
      "paramCount": 32762123264,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 131072,
      "managedDpoContext": 131072,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3-32b-128k-lora",
        "method": "LoRA",
        "context": 131072,
        "gpus": "8 \u00d7 B200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": []
    }, {
      "id": "qwen3-4b-instruct-2507",
      "label": "Qwen 3 4B Instruct 2507",
      "paramCount": 4411424256,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3-4b-instruct-2507-256k-b200-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "1 \u00d7 B200",
        "effectiveRatePerM": 1.22460988,
        "policyEffectiveRatePerM": 1.22460988,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "qwen3-8b",
      "label": "Qwen 3 8B",
      "paramCount": 8190735360,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 256000,
      "managedDpoContext": 256000,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3-8b-256k-h200-lora",
        "method": "LoRA",
        "context": 256000,
        "gpus": "8 \u00d7 B200",
        "effectiveRatePerM": 7.68646358,
        "policyEffectiveRatePerM": 7.68646358,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": [{
        "id": "Qwen/Qwen3-8B",
        "context": 32768,
        "prefill": 0.195,
        "cached": 0.039,
        "sample": 0.6,
        "train": 0.44,
        "note": null
      }]
    }, {
      "id": "qwen3p5-27b",
      "label": "Qwen 3.5 27B",
      "paramCount": 27356728560,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3p5-27b-256k",
        "method": "Full-Param",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 2.47844746,
        "policyEffectiveRatePerM": 2.47844746,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p5-27b-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 2.37088777,
        "policyEffectiveRatePerM": 2.37088777,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p5-27b-64k-lora",
        "method": "LoRA",
        "context": 65536,
        "gpus": "1 \u00d7 B200",
        "effectiveRatePerM": 1.09944292,
        "policyEffectiveRatePerM": 1.09944292,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "qwen3p5-35b-a3b",
      "label": "Qwen 3.5 35B A3B",
      "paramCount": 35107181936,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3p5-35b-a3b-256k",
        "method": "Full-Param",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 1.93768246,
        "policyEffectiveRatePerM": 1.93768246,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p5-35b-a3b-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 1.47477665,
        "policyEffectiveRatePerM": 1.47477665,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "qwen3p5-397b-a17b",
      "label": "Qwen 3.5 397B A17B",
      "paramCount": 396802360816,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3p5-397b-a17b-256k",
        "method": "Full-Param",
        "context": 262144,
        "gpus": "16 \u00d7 B300",
        "effectiveRatePerM": 9.50879204,
        "policyEffectiveRatePerM": 9.50879204,
        "referenceForwardRatePerM": 1.82803542,
        "benchmarkSource": "price-sweep"
      }, {
        "id": "qwen3p5-397b-a17b-256k-lora-b300",
        "method": "LoRA",
        "context": 262144,
        "gpus": "8 \u00d7 B300",
        "effectiveRatePerM": 5.25467729,
        "policyEffectiveRatePerM": 5.25467729,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": [{
        "id": "Qwen/Qwen3.5-397B-A17B",
        "context": 65536,
        "prefill": 3.0,
        "cached": 0.6,
        "sample": 7.5,
        "train": 6.6,
        "note": null
      }, {
        "id": "Qwen/Qwen3.5-397B-A17B:peft:262144",
        "context": 262144,
        "prefill": 4.0,
        "cached": 0.8,
        "sample": 10.0,
        "train": 12.0,
        "note": null
      }]
    }, {
      "id": "qwen3p5-9b",
      "label": "Qwen 3.5 9B",
      "paramCount": 9409813744,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3p5-9b-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "2 \u00d7 B200",
        "effectiveRatePerM": 0.78857065,
        "policyEffectiveRatePerM": 0.78857065,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p5-9b-65k-lora",
        "method": "LoRA",
        "context": 65536,
        "gpus": "2 \u00d7 B200",
        "effectiveRatePerM": 0.8570159,
        "policyEffectiveRatePerM": 0.8570159,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": [{
        "id": "Qwen/Qwen3.5-9B",
        "context": 65536,
        "prefill": 0.66,
        "cached": 0.132,
        "sample": 1.995,
        "train": 1.463,
        "note": null
      }]
    }, {
      "id": "qwen3p6-27b",
      "label": "Qwen 3.6 27B",
      "paramCount": 27356728560,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3p6-27b-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 2.41661113,
        "policyEffectiveRatePerM": 2.41661113,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p6-27b-128k-lora",
        "method": "LoRA",
        "context": 131072,
        "gpus": "2 \u00d7 B200",
        "effectiveRatePerM": 1.95081596,
        "policyEffectiveRatePerM": 1.95081596,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": [{
        "id": "Qwen/Qwen3.6-27B",
        "context": 65536,
        "prefill": 1.86,
        "cached": 0.372,
        "sample": 5.595,
        "train": 4.103,
        "note": "Retiring September 2"
      }]
    }, {
      "id": "qwen3p6-35b-a3b",
      "label": "Qwen 3.6-35B-A3B",
      "paramCount": 35107181936,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3p6-35b-a3b-256k",
        "method": "Full-Param",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 1.76551636,
        "policyEffectiveRatePerM": 1.76551636,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p6-35b-a3b-256k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 1.48428938,
        "policyEffectiveRatePerM": 1.48428938,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p6-35b-a3b-262k-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B300",
        "effectiveRatePerM": 1.71857432,
        "policyEffectiveRatePerM": 1.71857432,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": [{
        "id": "Qwen/Qwen3.6-35B-A3B",
        "context": 65536,
        "prefill": 0.54,
        "cached": 0.108,
        "sample": 1.335,
        "train": 1.177,
        "note": null
      }]
    }, {
      "id": "qwen3p7-plus-vl-instruct",
      "label": "Qwen 3.7 Plus VL Instruct",
      "paramCount": 396802360816,
      "managed": false,
      "managedSft": false,
      "managedDpo": false,
      "managedSftContext": null,
      "managedDpoContext": null,
      "serverless": null,
      "dedicated": [{
        "id": "qwen3p7-plus-vl-instruct-256k-lora",
        "method": "LoRA",
        "context": null,
        "gpus": null,
        "effectiveRatePerM": 3.12347278,
        "policyEffectiveRatePerM": 3.12347278,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }],
      "tinker": []
    }, {
      "id": "qwen3p8-27b",
      "label": "Qwen 3.8 27B",
      "paramCount": 27356728560,
      "managed": true,
      "managedSft": true,
      "managedDpo": true,
      "managedSftContext": 262144,
      "managedDpoContext": 262144,
      "serverless": {
        "prefill": 1.86,
        "cached": 0.372,
        "sample": 5.595,
        "train": 4.103,
        "context": 131072
      },
      "dedicated": [{
        "id": "qwen3p8-27b-262k-b200",
        "method": "Full-Param",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 2.22598928,
        "policyEffectiveRatePerM": 2.22598928,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p8-27b-262k-b300",
        "method": "Full-Param",
        "context": 262144,
        "gpus": "4 \u00d7 B300",
        "effectiveRatePerM": 2.19587176,
        "policyEffectiveRatePerM": 2.19587176,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p8-27b-262k-b200-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": 1.87834128,
        "policyEffectiveRatePerM": 1.87834128,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p8-27b-262k-b300-lora",
        "method": "LoRA",
        "context": 262144,
        "gpus": "4 \u00d7 B300",
        "effectiveRatePerM": 2.03227249,
        "policyEffectiveRatePerM": 2.03227249,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "speed-gate"
      }, {
        "id": "qwen3p8-27b-32k-b200-lora",
        "method": "LoRA",
        "context": 32768,
        "gpus": "4 \u00d7 B200",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }, {
        "id": "qwen3p8-27b-32k-b300-lora",
        "method": "LoRA",
        "context": 32768,
        "gpus": "4 \u00d7 B300",
        "effectiveRatePerM": null,
        "policyEffectiveRatePerM": null,
        "referenceForwardRatePerM": null,
        "benchmarkSource": "unavailable"
      }],
      "tinker": [{
        "id": "Qwen/Qwen3.8-27B",
        "context": 65536,
        "prefill": 1.86,
        "cached": 0.372,
        "sample": 5.595,
        "train": 4.103,
        "note": null
      }, {
        "id": "Qwen/Qwen3.8-27B:peft:262144",
        "context": 262144,
        "prefill": 2.48,
        "cached": 0.496,
        "sample": 7.46,
        "train": 7.46,
        "note": null
      }]
    }]
  };
  const CONTACT_URL = "https://fireworks.ai/contact-training";
  const money = (value, bound) => {
    const dollars = Math.max(0, Number(value) || 0);
    let display = dollars;
    if (dollars >= 100) {
      display = bound === "low" ? Math.floor(dollars / 10) * 10 : Math.ceil(dollars / 10) * 10;
    }
    const digits = dollars > 0 && dollars < 10 ? 2 : 0;
    return new Intl.NumberFormat("en-US", {
      style: "currency",
      currency: "USD",
      minimumFractionDigits: digits,
      maximumFractionDigits: digits
    }).format(Math.max(dollars > 0 ? 0.01 : 0, display));
  };
  const rateMoney = value => new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
    minimumFractionDigits: 2,
    maximumFractionDigits: 3
  }).format(value);
  const costMoney = value => new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: "USD",
    minimumFractionDigits: 2,
    maximumFractionDigits: 2
  }).format(value);
  const millionTokens = value => `${Number(value || 0).toLocaleString(undefined, {
    maximumFractionDigits: 2
  })}M`;
  const numberValue = value => Math.max(0, Number(value) || 0);
  const [Field] = useState(() => ({label, children, full = false}) => <label className={full ? "block sm:col-span-2" : "block"}>
      <span className="mb-1.5 block text-xs font-medium text-gray-700 dark:text-gray-300">
        {label}
      </span>
      {children}
    </label>);
  const [Choice] = useState(() => ({kicker, title, description, selected, onClick, href, muted = false}) => {
    const className = `flex min-h-44 flex-col rounded-lg border p-5 text-left transition-colors ${muted ? "border-gray-200 bg-gray-100 text-gray-500 hover:border-gray-400 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-400" : selected ? "border-[#6720FF] bg-[#F3EDFF] text-gray-950 hover:border-[#6720FF] dark:border-purple-400 dark:bg-purple-950/40 dark:text-gray-100" : "border-gray-300 bg-gray-50 text-gray-950 hover:border-[#6720FF] dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:hover:border-purple-400"}`;
    const body = <>
            <span className={`block min-h-10 text-[11px] font-semibold uppercase tracking-widest ${muted ? "text-gray-500 dark:text-gray-400" : "text-[#6720FF] dark:text-purple-300"}`}>
              {kicker}
            </span>
            <span className={`block min-h-14 text-lg font-semibold ${muted ? "text-gray-600 dark:text-gray-400" : "text-gray-900 dark:text-gray-100"}`}>
              {title}
            </span>
            <span className={`mt-1 block text-sm leading-6 ${muted ? "text-gray-500 dark:text-gray-400" : "text-gray-600 dark:text-gray-300"}`}>
              {description}
            </span>
          </>;
    if (href) {
      return <a className={className} href={href} target="_blank" rel="noreferrer" onClick={onClick}>
              {body}
            </a>;
    }
    return <button type="button" className={className} onClick={onClick}>
            {body}
          </button>;
  });
  const [method, setMethod] = useState("sft");
  const [modelId, setModelId] = useState("kimi-k3");
  const [shapeId, setShapeId] = useState("");
  const [items, setItems] = useState(50000);
  const [epochs, setEpochs] = useState(1);
  const [promptTokens, setPromptTokens] = useState(400);
  const [responseTokens, setResponseTokens] = useState(100);
  const [chosenTokens, setChosenTokens] = useState(150);
  const [rejectedTokens, setRejectedTokens] = useState(150);
  const [promptCopied, setPromptCopied] = useState(false);
  const agentPrompt = "I want to estimate the cost of a Fireworks training job before spending.\n\n1. Follow the coding-agent installation guide: https://docs.fireworks.ai/fine-tuning/agent/use-with-coding-agents\n2. Install or load the Fireworks Training Skill from: https://github.com/fw-ai/cookbook/tree/main/skills/fireworks-training\n3. Calculate Managed and Fireworks Serverless from live published rates at: https://fireworks.ai/pricing\n4. For RL, do not invent a number. Send me to https://fireworks.ai/contact-training\n\nAsk me for any missing Managed or Serverless workload inputs. Do not launch a job or authorize spend.";
  const models = ESTIMATOR_CATALOG.models || [];
  const hasPricedDedicated = model => (model.dedicated || []).some(shape => shape.policyEffectiveRatePerM || shape.effectiveRatePerM);
  const eligibleModels = models.filter(model => (method === "sft" ? model.managedSft : model.managedDpo) || model.serverless || hasPricedDedicated(model));
  const selectedModel = eligibleModels.find(model => model.id === modelId) || eligibleModels.find(model => model.id === "kimi-k3") || eligibleModels[0];
  const selectedShape = selectDefaultShape(selectedModel, shapeId);
  const inputClass = "h-11 w-full rounded-lg border border-gray-300 bg-white px-3 text-sm text-gray-900 outline-none focus:border-[#6720FF] focus:ring-2 focus:ring-[#6720FF]/20 dark:border-gray-600 dark:bg-gray-900 dark:text-gray-100 dark:focus:border-purple-400 dark:focus:ring-purple-400/20";
  const publicTokenCount = method === "sft" ? numberValue(items) * numberValue(epochs) * (numberValue(promptTokens) + numberValue(responseTokens)) : numberValue(items) * numberValue(epochs) * (numberValue(promptTokens) * 2 + numberValue(chosenTokens) + numberValue(rejectedTokens));
  const tokenMillions = publicTokenCount / 1e6;
  const referenceTokenCount = method === "dpo" ? numberValue(items) * (numberValue(promptTokens) * 2 + numberValue(chosenTokens) + numberValue(rejectedTokens)) : 0;
  const referenceTokenMillions = referenceTokenCount / 1e6;
  const maxExampleTokens = method === "sft" ? numberValue(promptTokens) + numberValue(responseTokens) : numberValue(promptTokens) + Math.max(numberValue(chosenTokens), numberValue(rejectedTokens));
  const tinkerVariantFor = model => model?.tinker?.find(variant => variant.context >= maxExampleTokens);
  const shortSequenceForShape = shape => shape?.context && maxExampleTokens > 0 ? maxExampleTokens / shape.context < 0.1 : false;
  const resultFor = (model, surface, shape) => {
    const availability = surfaceAvailability({
      model,
      surface,
      method,
      shape,
      maxExampleTokens
    });
    if (!availability.available) {
      return {
        unavailable: true,
        note: availability.note
      };
    }
    const tinkerVariant = tinkerVariantFor(model);
    if (surface === "tinker" && !tinkerVariant) {
      return {
        unavailable: true,
        note: "No exact Tinker model tier supports this sequence length."
      };
    }
    if ((surface === "serverless" || surface === "tinker") && method === "dpo") {
      const rates = surface === "serverless" ? model.serverless : tinkerVariant;
      const breakdown = dpoCostBreakdown({
        policyTokenMillions: tokenMillions,
        referenceTokenMillions,
        rates
      });
      const {policyCost, referenceCost, baseline} = breakdown;
      return {
        display: surface === "serverless" ? `Baseline ${money(baseline, "low")}` : `${money(baseline, "low")}–${money(baseline * 1.3, "high")}`,
        detail: `${millionTokens(tokenMillions)} policy tokens · ${millionTokens(referenceTokenMillions)} one-time reference tokens`,
        lines: [`Policy train meter: ${costMoney(policyCost)}`, `Reference prefill, all uncached: ${costMoney(referenceCost)}`, surface === "serverless" ? "Batch padding is excluded. This is an unpadded baseline, not an upper bound." : null].filter(Boolean),
        note: `${surface === "tinker" ? `Tinker ${tinkerVariant.context / 1024}K tier${tinkerVariant.note ? ` (${tinkerVariant.note})` : ""}. ` : ""}Reference scoring is priced as all-uncached because prompt caching is not guaranteed for this loop. Batch padding, evaluation, and generation sampling are excluded.`,
        lowerBound: surface === "serverless"
      };
    }
    const policyEffectiveRatePerM = shape?.policyEffectiveRatePerM ?? shape?.effectiveRatePerM;
    if (surface === "dedicated" && method === "dpo" && !policyEffectiveRatePerM) {
      return {
        unavailable: true,
        note: "No Dedicated policy rate for this shape."
      };
    }
    if (surface === "dedicated" && method === "dpo" && !shape?.referenceForwardRatePerM) {
      const policyCost = tokenMillions * policyEffectiveRatePerM;
      return {
        display: `Policy floor ${money(policyCost, "low")}`,
        detail: `${millionTokens(tokenMillions)} policy tokens · frozen reference excluded`,
        lines: [`Policy GPU work: ${costMoney(policyCost)}`, "Frozen reference forward: excluded from this lower bound"].filter(Boolean),
        note: "Policy compute lower bound only. Frozen reference scoring is not included.",
        lowerBound: true,
        suppressComparisons: true
      };
    }
    const estimate = estimateTrainingCost({
      surface,
      method,
      tokenMillions,
      paramCount: model.paramCount,
      managedRates: ESTIMATOR_CATALOG.managedRates,
      serverlessRates: model.serverless,
      tinkerRates: tinkerVariant,
      effectiveRatePerM: policyEffectiveRatePerM
    });
    if (estimate.route === "contact-training") {
      return {
        display: "Contact us",
        detail: `${millionTokens(tokenMillions)} planned training tokens`,
        note: "No unambiguous customer-facing benchmark is available."
      };
    }
    if (surface === "managed") {
      return {
        display: `${money(estimate.low, "low")}–${money(estimate.high, "high")}`,
        detail: `${millionTokens(tokenMillions)} rendered tokens at ${rateMoney(estimate.rate)}/M`,
        lines: [method === "dpo" ? `Chosen + rejected policy tokens: ${millionTokens(tokenMillions)}` : null, method === "dpo" ? "Reference-method premium is included in the published DPO rate." : null].filter(Boolean),
        note: "Published token rate; range reflects rendered-token assumptions."
      };
    }
    if (surface === "serverless") {
      return {
        display: `${money(estimate.low, "low")}–${money(estimate.high, "high")}`,
        detail: `${millionTokens(tokenMillions)} train-meter tokens at ${rateMoney(estimate.rate)}/M`,
        note: method === "dpo" ? "Prefill, cache, sampling, and reference-forward work can add cost." : "Loop prefill, cache, or sampling work can add cost."
      };
    }
    if (surface === "tinker") {
      return {
        display: `${money(estimate.low, "low")}–${money(estimate.high, "high")}`,
        detail: `${millionTokens(tokenMillions)} train tokens at ${rateMoney(estimate.rate)}/M`,
        note: `Official Tinker ${tinkerVariant.context / 1024}K tier${tinkerVariant.note ? ` (${tinkerVariant.note})` : ""}. Prefill and sampling are additional when the workflow uses them.`
      };
    }
    if (method === "dpo") {
      const policyCost = tokenMillions * policyEffectiveRatePerM;
      const referenceCost = referenceTokenMillions * shape.referenceForwardRatePerM;
      const center = policyCost + referenceCost;
      return {
        display: `${money(center * 0.7, "low")}–${money(center * 1.3, "high")}`,
        detail: `${millionTokens(tokenMillions)} policy tokens · ${millionTokens(referenceTokenMillions)} one-time reference tokens`,
        lines: [`Policy GPU work: ${costMoney(policyCost)}`, `Reference forward: ${costMoney(referenceCost)}`, shortSequenceForShape(shape) ? `Your ${maxExampleTokens.toLocaleString()}-token examples are far shorter than this shape's ${shape.context.toLocaleString()}-token benchmark, so the cluster cannot be saturated and real cost can run several times higher.` : null].filter(Boolean),
        note: "Range around the maximum-context DPO benchmark. Well-packed mixed-length batches have measured below it; short or poorly packed workloads can cost several times more.",
        suppressComparisons: shortSequenceForShape(shape)
      };
    }
    const tokenFloor = tokenMillions * policyEffectiveRatePerM;
    const shortSequence = shortSequenceForShape(shape);
    return {
      display: `Compute floor ${money(tokenFloor, "low")}`,
      detail: `${millionTokens(tokenMillions)} planned tokens · ${shape.id}`,
      lines: [`Saturated token floor: ${costMoney(tokenFloor)} at ${rateMoney(policyEffectiveRatePerM)}/M`, shortSequence ? `Your ${maxExampleTokens.toLocaleString()}-token examples are far shorter than this shape's ${shape.context.toLocaleString()}-token benchmark, so the cluster cannot be saturated. A comparable workload cost several times this floor. Measure observed throughput over 20 to 50 steps before committing spend.` : null].filter(Boolean),
      note: `${shape.method === "LoRA" ? "LoRA" : "Full Parameter"} saturated GPU-hour floor. Allocated time for model initialization, checkpoints, and idle periods is excluded. Queue wait is not billed.`,
      lowerBound: true,
      suppressComparisons: shortSequence
    };
  };
  const surfaceDefinitions = [{
    id: "managed",
    label: "Managed",
    eyebrow: "Priced per token"
  }, {
    id: "serverless",
    label: "Serverless Training API",
    eyebrow: "Priced per token, shared GPUs"
  }, {
    id: "dedicated",
    label: "Dedicated Training API",
    eyebrow: "Priced per GPU-hour"
  }];
  const renderSurfaceCard = (model, shape, surface) => {
    const result = resultFor(model, surface.id, shape);
    const tinkerResult = surface.id === "dedicated" ? resultFor(model, "tinker", shape) : null;
    const tinkerVariant = tinkerVariantFor(model);
    const dedicatedRate = shape?.policyEffectiveRatePerM ?? shape?.effectiveRatePerM;
    const dedicatedIsLower = method === "sft" && dedicatedRate && tinkerVariant?.train && tokenMillions * dedicatedRate < tokenMillions * tinkerVariant.train;
    return <div key={`${model.id}-${surface.id}`} className="flex h-full flex-col rounded-lg border border-gray-300 bg-white p-5 dark:border-gray-700 dark:bg-gray-900">
        <p className="m-0 text-[10px] font-semibold uppercase tracking-widest text-gray-500 dark:text-gray-400">
          {surface.eyebrow}
        </p>
        <h4 className="mt-1 mb-4 text-sm font-semibold text-gray-900 dark:text-gray-100">
          {surface.label}
        </h4>
        {result?.unavailable ? <>
            <p className="m-0 text-xl font-semibold text-gray-400 dark:text-gray-500">
              Unavailable
            </p>
            <p className="mt-2 mb-0 text-xs leading-5 text-gray-500 dark:text-gray-400">
              {result.note}
            </p>
          </> : <>
            <p className="m-0 text-2xl font-semibold tracking-tight text-gray-950 dark:text-white">
              {result?.display}
            </p>
            <p className="mt-2 mb-0 text-xs leading-5 text-gray-700 dark:text-gray-300">
              {result?.note}
            </p>
            {(result?.detail || result?.lines?.length > 0) && <details className="order-last mt-auto border-t border-gray-200 pt-3 dark:border-gray-700">
                <summary className="cursor-pointer text-xs font-medium text-[#6720FF] dark:text-purple-300">
                  How this is calculated
                </summary>
                {result?.detail && <p className="mt-2 mb-0 text-xs leading-5 text-gray-600 dark:text-gray-400">
                    {result.detail}
                  </p>}
                {result?.lines?.map(line => <p key={line} className="mt-1 mb-0 text-xs leading-5 text-gray-700 dark:text-gray-300">
                    {line}
                  </p>)}
              </details>}
            {surface.id === "dedicated" && shouldShowTinkerComparison(result, tinkerResult) && <details className="mt-3 border-t border-gray-200 pt-3 dark:border-gray-700">
                  <summary className="cursor-pointer text-xs font-medium text-[#6720FF] dark:text-purple-300">
                    {dedicatedIsLower ? "Dedicated estimate is lower · See Tinker price" : "Compare Dedicated with Tinker"}
                  </summary>
                  <p className="mt-3 mb-0 text-xl font-semibold text-gray-950 dark:text-white">
                    Tinker {tinkerResult.display}
                  </p>
                  <p className="mt-1 mb-0 text-xs leading-5 text-gray-700 dark:text-gray-300">
                    {tinkerResult.note}
                  </p>
                  {tinkerResult.detail && <p className="mt-2 mb-0 text-xs leading-5 text-gray-600 dark:text-gray-400">
                      {tinkerResult.detail}
                    </p>}
                </details>}
          </>}
      </div>;
  };
  const renderModelResults = (model, shape) => <section>
      <div className="mb-4 flex flex-wrap items-baseline justify-between gap-2">
        <div>
          <p className="m-0 text-[11px] font-semibold uppercase tracking-widest text-[#6720FF] dark:text-purple-300">
            Cost estimate
          </p>
          <h3 className="mt-1 mb-0 text-xl font-semibold">{model.label}</h3>
        </div>
        <span className="text-sm text-gray-600 dark:text-gray-400">
          {method === "sft" ? "SFT" : "DPO"}
          {shape ? ` · Dedicated ${shape.method === "LoRA" ? "LoRA" : "Full Parameter"}` : ""}{" "}
          · {millionTokens(tokenMillions)}
        </span>
      </div>
      <div className="grid gap-3 md:grid-cols-3">
        {surfaceDefinitions.map(surface => renderSurfaceCard(model, shape, surface))}
      </div>
    </section>;
  return <div className="not-prose my-6 overflow-hidden rounded-xl border border-gray-300 bg-white text-gray-900 dark:border-gray-700 dark:bg-gray-950 dark:text-gray-100">
      <div className="border-b border-gray-300 px-6 py-5 dark:border-gray-700">
        <p className="m-0 text-[11px] font-semibold uppercase tracking-widest text-[#6720FF] dark:text-purple-300">
          Training cost estimator
        </p>
        <h2 className="mt-1 mb-0 text-2xl font-semibold">
          Configure once. Compare every supported path.
        </h2>
        <p className="mt-2 mb-0 max-w-3xl text-sm leading-6 text-gray-700 dark:text-gray-300">
          Keep the method, model, workload, and assumptions visible while
          estimating Managed and comparing Fireworks Serverless vs Dedicated or
          Fireworks Dedicated vs Tinker.
        </p>
      </div>

      <div className="p-6">
        <div>
          <p className="mb-2 text-xs font-medium text-gray-700 dark:text-gray-300">
            Training method
          </p>
          <div className="grid gap-2 sm:grid-cols-3">
            {[["sft", "Supervised fine-tuning (SFT)", "Labeled examples"], ["dpo", "Direct preference optimization (DPO)", "Preference pairs"], ["rl", "Reinforcement learning (RL)", "Rough rollout lower bound"]].map(([id, label, detail]) => <button key={id} type="button" onClick={() => setMethod(id)} className={`rounded-lg border px-4 py-3 text-left ${method === id ? "border-[#6720FF] bg-[#F3EDFF] dark:border-purple-400 dark:bg-purple-950/40" : "border-gray-300 bg-gray-50 dark:border-gray-700 dark:bg-gray-900"}`}>
                <span className="block text-sm font-semibold">{label}</span>
                <span className="mt-1 block text-xs text-gray-600 dark:text-gray-400">
                  {detail}
                </span>
              </button>)}
          </div>
        </div>

        {method === "rl" ? <div className="mt-6">
            <div className="w-full rounded-lg border border-gray-300 bg-white p-6 dark:border-gray-700 dark:bg-gray-900">
              <p className="m-0 text-[11px] font-semibold uppercase tracking-widest text-gray-500 dark:text-gray-400">
                Complete RL workload
              </p>
              <h3 className="mt-2 mb-0 text-xl font-semibold">
                Get a tailored trainer and rollout estimate
              </h3>
              <p className="mt-2 text-sm leading-6 text-gray-700 dark:text-gray-300">
                Share rollout shape, environment latency, concurrency, reward
                design, trainer topology, and evaluation volume with the
                Training team.
              </p>
              <a href={CONTACT_URL} target="_blank" rel="noreferrer" className="mt-3 inline-flex rounded-lg border border-gray-300 px-4 py-2 text-sm font-medium hover:border-[#6720FF] dark:border-gray-600 dark:text-gray-100 dark:hover:border-purple-400">
                Contact Training
              </a>
            </div>
          </div> : <>
            <div className="mt-6 grid gap-8 lg:grid-cols-[1.5fr_0.8fr]">
              <div>
                <div className="grid gap-4 sm:grid-cols-2">
                  <Field label="Model">
                    <select className={inputClass} value={selectedModel?.id || ""} onChange={event => {
    setModelId(event.target.value);
    setShapeId("");
  }}>
                      {eligibleModels.map(model => <option key={model.id} value={model.id}>
                          {model.label}
                        </option>)}
                    </select>
                  </Field>
                  {selectedModel?.dedicated.length > 0 && <Field label="Dedicated setup">
                      <select className={inputClass} value={selectedShape?.id || ""} onChange={event => setShapeId(event.target.value)}>
                        {selectedModel.dedicated.map(shape => <option key={shape.id} value={shape.id}>
                            {shape.id} · {shape.method}
                            {shape.context ? ` · ${Math.round(shape.context / 1024)}K` : ""}
                          </option>)}
                      </select>
                    </Field>}
                  <Field label={method === "sft" ? "Examples" : "Preference pairs"}>
                    <input className={inputClass} type="number" min="0" value={items} onChange={event => setItems(event.target.value)} />
                  </Field>
                  <Field label="Epochs">
                    <input className={inputClass} type="number" min="0" step="0.1" value={epochs} onChange={event => setEpochs(event.target.value)} />
                  </Field>
                  <Field label="Average prompt tokens">
                    <input className={inputClass} type="number" min="0" value={promptTokens} onChange={event => setPromptTokens(event.target.value)} />
                  </Field>
                  {method === "sft" ? <Field label="Average response tokens">
                      <input className={inputClass} type="number" min="0" value={responseTokens} onChange={event => setResponseTokens(event.target.value)} />
                    </Field> : <>
                      <Field label="Average chosen tokens">
                        <input className={inputClass} type="number" min="0" value={chosenTokens} onChange={event => setChosenTokens(event.target.value)} />
                      </Field>
                      <Field label="Average rejected tokens">
                        <input className={inputClass} type="number" min="0" value={rejectedTokens} onChange={event => setRejectedTokens(event.target.value)} />
                      </Field>
                    </>}
                </div>
              </div>

              <aside className="rounded-lg border border-[#E3D4FF] bg-[#F8F4FF] p-5 dark:border-purple-800 dark:bg-purple-950/30">
                <h3 className="m-0 text-sm font-semibold text-[#6720FF] dark:text-purple-300">
                  Estimate in your coding agent
                </h3>
                <p className="mt-2 text-sm leading-6 text-gray-700 dark:text-gray-300">
                  Copy a prompt for Claude Code, Cursor, Codex, or another agent.
                </p>
                <button type="button" onClick={async () => {
    await navigator.clipboard.writeText(agentPrompt);
    setPromptCopied(true);
    window.setTimeout(() => setPromptCopied(false), 2000);
  }} className="mt-3 inline-flex rounded-lg bg-[#6720FF] px-3 py-2 text-sm font-medium text-white dark:bg-purple-500">
                  {promptCopied ? "Copied" : "Copy"}
                </button>
              </aside>
            </div>

            <div className="mt-8">
              {selectedModel && <>{renderModelResults(selectedModel, selectedShape)}</>}
            </div>
          </>}
      </div>
    </div>;
};

<Info>
  <ul>
    <li>
      Managed and Serverless are [priced per
      token](https://fireworks.ai/pricing#training-pricing).
    </li>

    <li>
      Dedicated is [priced per allocated GPU
      hour](https://fireworks.ai/pricing#on-demand-pricing).
    </li>
  </ul>
</Info>

<TrainingCostEstimator />

<Warning>
  <ul>
    <li>Planning estimates are not quotes.</li>

    <li>
      Managed estimates can be low when rendered-token inputs omit multi-turn
      unrolling. Dedicated compute floors can be low when sequences pack poorly.
    </li>

    <li>
      Dedicated shows a saturated compute floor. Allocated GPU time spent
      initializing the model, writing checkpoints, or idle can make real jobs
      cost more. Queue wait and pre-allocation provisioning are not billed.
    </li>
  </ul>
</Warning>

## Prepare inputs with the Training Skill

The [Fireworks Training Skill](/fine-tuning/agent/use-with-coding-agents)
prepares inputs and calculates Managed and Serverless estimates from published
rates. It can inspect a local dataset or an existing job and identify
assumptions. It does not calculate Dedicated numbers. Use this page for
Dedicated planning.

The Skill does not launch a job or authorize spend while estimating. Training
still requires the Skill's complete final plan and your explicit confirmation.

## Reinforcement learning

RL cost varies with rollout shape, concurrency, reward or verifier design,
training method, and evaluation workload. [Contact the Training
team](https://fireworks.ai/contact-training) for a tailored estimate.

To compare the rollout inference cost of multi-turn agentic RL, use the separate
[rollout cost comparison](/fine-tuning/multi-turn-cost-comparison). That page
does not estimate SFT or DPO training cost.
