Make Sonnet's expiring intro pricing date-aware
The table hardcoded $2/$10 with a comment noting it lapses 2026-08-31. From Sept 1 that would have under-reported every grade by a third — both the per-grade figure in the UI and the cost recorded against each result.
This commit is contained in:
parent
602bce8ce3
commit
762b394c8a
1 changed files with 28 additions and 5 deletions
33
vision.py
33
vision.py
|
|
@ -16,6 +16,7 @@ Works on any trading card: Pokemon, sports, Magic, whatever PSA grades.
|
|||
import base64
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
|
||||
import cardimage
|
||||
|
||||
|
|
@ -48,8 +49,11 @@ MODELS = {
|
|||
"effort": True,
|
||||
"adaptive_thinking": True,
|
||||
"fallbacks": False,
|
||||
# Introductory pricing runs through 2026-08-31, then 3.00 / 15.00.
|
||||
# Introductory pricing, which EXPIRES — see `priced_from` below.
|
||||
# Hardcoding the intro rate alone would have quietly under-reported
|
||||
# every grade by a third from 2026-09-01 onward.
|
||||
"in_per_mtok": 2.00, "out_per_mtok": 10.00,
|
||||
"priced_from": [("2026-09-01", 3.00, 15.00)],
|
||||
"approx_image_tokens": 4800,
|
||||
},
|
||||
"claude-opus-5": {
|
||||
|
|
@ -824,13 +828,31 @@ def grade_card(images, api_key=None, model=None, effort=None, zoom_details=True)
|
|||
}
|
||||
|
||||
|
||||
def current_rates(caps, on_date=None):
|
||||
"""(input, output) $/Mtok for a model, honouring any scheduled change.
|
||||
|
||||
A model on introductory pricing carries the dated rates that supersede
|
||||
it in `priced_from`; the latest one whose date has passed wins. Without
|
||||
this the table silently keeps quoting a rate that no longer exists once
|
||||
the promotion ends, and every cost shown in the app is wrong by
|
||||
whatever the increase was.
|
||||
"""
|
||||
rate_in, rate_out = caps["in_per_mtok"], caps["out_per_mtok"]
|
||||
today = on_date or time.strftime("%Y-%m-%d")
|
||||
for starts, new_in, new_out in sorted(caps.get("priced_from") or []):
|
||||
if today >= starts:
|
||||
rate_in, rate_out = new_in, new_out
|
||||
return rate_in, rate_out
|
||||
|
||||
|
||||
def estimate_cost(usage):
|
||||
"""Actual USD cost of one grading call, from the reported token counts."""
|
||||
if not usage:
|
||||
return None
|
||||
caps = MODELS.get(usage.get("model") or "", MODELS[DEFAULT_MODEL])
|
||||
return ((usage.get("input_tokens") or 0) * caps["in_per_mtok"] / 1_000_000
|
||||
+ (usage.get("output_tokens") or 0) * caps["out_per_mtok"] / 1_000_000)
|
||||
rate_in, rate_out = current_rates(caps)
|
||||
return ((usage.get("input_tokens") or 0) * rate_in / 1_000_000
|
||||
+ (usage.get("output_tokens") or 0) * rate_out / 1_000_000)
|
||||
|
||||
|
||||
def price_guide():
|
||||
|
|
@ -840,10 +862,11 @@ def price_guide():
|
|||
# 1 supplied photo + ~12 generated close-ups, JSON verdict out.
|
||||
est_in = caps["approx_image_tokens"] * 5 + 600
|
||||
est_out = 700
|
||||
rate_in, rate_out = current_rates(caps)
|
||||
guide[model_id] = {
|
||||
"label": caps["label"],
|
||||
"supports_effort": caps["effort"],
|
||||
"per_grade": round(est_in * caps["in_per_mtok"] / 1_000_000
|
||||
+ est_out * caps["out_per_mtok"] / 1_000_000, 4),
|
||||
"per_grade": round(est_in * rate_in / 1_000_000
|
||||
+ est_out * rate_out / 1_000_000, 4),
|
||||
}
|
||||
return guide
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue