summaryrefslogtreecommitdiff
path: root/internal/provider/google/pricing.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/provider/google/pricing.go')
-rw-r--r--internal/provider/google/pricing.go60
1 files changed, 60 insertions, 0 deletions
diff --git a/internal/provider/google/pricing.go b/internal/provider/google/pricing.go
new file mode 100644
index 0000000..55ea66f
--- /dev/null
+++ b/internal/provider/google/pricing.go
@@ -0,0 +1,60 @@
+package google
+
+import "strings"
+
+// modelPrice is USD cost per million tokens for one model (or model family
+// prefix).
+type modelPrice struct {
+ InputPerMTok float64
+ OutputPerMTok float64
+}
+
+// pricingTable maps a model-name *prefix* to its per-million-token pricing.
+// Keyed by prefix (rather than exact model string) so dated/versioned model
+// IDs (e.g. "gemini-2.5-flash-preview-09-2025") still resolve without
+// needing an entry per snapshot. Edit this table as Google's pricing or
+// model lineup changes — it intentionally has no other logic attached.
+//
+// Prices below are cached from training/research as of mid-2026 and are not
+// fetched live; verify against https://ai.google.dev/gemini-api/docs/pricing
+// before relying on them for real billing decisions. Two caveats specific to
+// Gemini pricing that this flat per-model table does NOT model:
+// - Some tiers (notably 1.5 Pro and some 2.5 Pro contexts) charge a higher
+// rate once the prompt exceeds 128K/200K tokens; the price below is the
+// lower/base-context rate.
+// - Some Flash-tier models charge a different (higher) output rate for
+// "thinking"/reasoning tokens vs. plain output tokens; the price below
+// is the standard output rate, not the thinking-token rate.
+var pricingTable = map[string]modelPrice{
+ // Pro tier (most capable, most expensive).
+ "gemini-2.5-pro": {InputPerMTok: 1.25, OutputPerMTok: 10.00},
+ "gemini-1.5-pro": {InputPerMTok: 1.25, OutputPerMTok: 5.00},
+
+ // Flash tier (balanced cost/capability; default for most tasks).
+ "gemini-2.5-flash-lite": {InputPerMTok: 0.10, OutputPerMTok: 0.40},
+ "gemini-2.5-flash": {InputPerMTok: 0.30, OutputPerMTok: 2.50},
+ "gemini-2.0-flash-lite": {InputPerMTok: 0.075, OutputPerMTok: 0.30},
+ "gemini-2.0-flash": {InputPerMTok: 0.10, OutputPerMTok: 0.40},
+ "gemini-1.5-flash-8b": {InputPerMTok: 0.0375, OutputPerMTok: 0.15},
+ "gemini-1.5-flash": {InputPerMTok: 0.075, OutputPerMTok: 0.30},
+}
+
+// defaultPricing is used for unrecognized models rather than erroring —
+// Flash-tier pricing is a reasonable default since it's the most commonly
+// used tier for the harness's escalation ladder.
+var defaultPricing = modelPrice{InputPerMTok: 0.30, OutputPerMTok: 2.50}
+
+// pricingFor returns the per-million-token input/output pricing for model,
+// matching the longest pricingTable prefix that model starts with. Falls
+// back to defaultPricing for unrecognized models.
+func pricingFor(model string) (inputPerMTok, outputPerMTok float64) {
+ price := defaultPricing
+ bestLen := -1
+ for prefix, p := range pricingTable {
+ if len(prefix) > bestLen && strings.HasPrefix(model, prefix) {
+ bestLen = len(prefix)
+ price = p
+ }
+ }
+ return price.InputPerMTok, price.OutputPerMTok
+}