Skip to content

LLM Cost Calculator — JavaScript source

Estimate LLM costs per request or per month at billion-token scale — with realistic prompt-cache hit rates, four-lane pricing, and side-by-side model comparison from a dated pricing snapshot.

This is the JavaScript implementation — the same logic the interactive tool runs, in a shareable, citable form.

/**
 * LLM Cost Calculator - per-million-token cost math for LLM workloads.
 *
 * Language:   JavaScript (ES2020+, runs unmodified in Node 16+ and modern browsers)
 * Source:     CosmoDev polyglot showcase port of the LLM Cost Calculator tool,
 *             ported from src/lib/llmCost.ts (the canonical TypeScript
 *             implementation), with the tokensPerDollar helper inlined from
 *             src/lib/ai/models.ts so this file stays dependency-free.
 * Tool page:  https://dev.cosmolabs.org/tools/llm-cost-calculator
 * License:    display source - part of CosmoDev's polyglot tool pages.
 *
 * Design goals:
 *   - Pure + deterministic; never throws.
 *   - Functionally equivalent to the TS reference: same inputs -> same outputs
 *     (a null rate means "unpriced" and propagates to a null cost).
 *   - Self-contained: stdlib only (no npm dependencies, no model snapshot).
 *
 * Formula: ((inputTokens / 1e6) * inputPerM + (outputTokens / 1e6) * outputPerM)
 *          * requests * (batch ? 0.5 : 1). Model rates are NEVER hardcoded
 *          here - the caller supplies them (in the TS lib they flow from the
 *          model snapshot accessor; custom rates are the one exception).
 */

'use strict';

/** Multiplier applied to Batch API pricing (the standard 50% discount). */
export const BATCH_DISCOUNT = 0.5;

/**
 * Price pair for a model or a custom rate card. `null` = unpriced.
 *
 * @typedef {Object} CostRates
 * @property {number|null} inputPerM   USD per 1M input tokens.
 * @property {number|null} outputPerM  USD per 1M output tokens.
 */

/**
 * One workload to price.
 *
 * @typedef {Object} CostInput
 * @property {number}  inputTokens   Input tokens per request.
 * @property {number}  outputTokens  Output tokens per request.
 * @property {number}  [requests]    Request count; defaults to 1.
 * @property {boolean} [batch]       Apply the BATCH_DISCOUNT multiplier.
 */

/**
 * Pricing projection of a model. The full AiModel record (src/lib/ai/models.ts)
 * carries a dozen non-pricing fields; only these three matter to cost math.
 *
 * @typedef {Object} Model
 * @property {string}      id
 * @property {number|null} inputPerM
 * @property {number|null} outputPerM
 */

/**
 * Cost in USD for a workload, or null when either rate is unpriced:
 * ((inputTokens/1e6)*inputPerM + (outputTokens/1e6)*outputPerM) * requests
 * * BATCH_DISCOUNT when batch.
 *
 * @param {CostRates} rates
 * @param {CostInput} input
 * @returns {number|null}
 */
export function costFor(rates, input) {
  if (rates.inputPerM === null || rates.outputPerM === null) return null;
  const base =
    (input.inputTokens / 1_000_000) * rates.inputPerM +
    (input.outputTokens / 1_000_000) * rates.outputPerM;
  return base * (input.requests ?? 1) * (input.batch ? BATCH_DISCOUNT : 1);
}

/**
 * One row of a compareModels result.
 *
 * @typedef {Object} ModelCost
 * @property {string}      id
 * @property {number|null} inputPerM
 * @property {number|null} outputPerM
 * @property {number|null} cost             costFor with the model's rates.
 * @property {number|null} tokensPerDollar  1e6 / outputPerM (null-safe).
 */

/** Project a model onto its CostRates pair. @param {Model} m @returns {CostRates} */
export function ratesFor(m) {
  return { inputPerM: m.inputPerM, outputPerM: m.outputPerM };
}

/** Output tokens per USD: 1e6 / outputPerM. Null when unpriced. @param {Model} m @returns {number|null} */
export function tokensPerDollar(m) {
  return m.outputPerM === null ? null : 1_000_000 / m.outputPerM;
}

/** String compare standing in for TS localeCompare (ids are ASCII slugs). @param {string} a @param {string} b @returns {number} */
const idAsc = (a, b) => (a < b ? -1 : a > b ? 1 : 0);

/**
 * Cost every requested model for one workload. Unknown ids are dropped.
 * Sort: cost asc, nulls last, ties by id asc (byte-wise - ids are ASCII slugs).
 *
 * The TS original defaults `models` to the live snapshot (allModels()); this
 * port has no snapshot dependency, so the model list is always explicit.
 *
 * @param {string[]}   modelIds
 * @param {CostInput}  input
 * @param {Model[]}    models
 * @returns {ModelCost[]}
 */
export function compareModels(modelIds, input, models) {
  const rows = [];
  for (const id of modelIds) {
    const m = models.find((mo) => mo.id === id);
    if (m === undefined) continue;
    rows.push({
      id,
      inputPerM: m.inputPerM,
      outputPerM: m.outputPerM,
      cost: costFor(ratesFor(m), input),
      tokensPerDollar: tokensPerDollar(m),
    });
  }
  return rows.sort((a, b) => {
    if (a.cost === null || b.cost === null) {
      if (a.cost === null && b.cost === null) return idAsc(a.id, b.id);
      return a.cost === null ? 1 : -1;
    }
    if (a.cost === b.cost) return idAsc(a.id, b.id);
    return a.cost - b.cost;
  });
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →