mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-03 02:22:24 +00:00
refactor(cost): replace date lists with override_dates on off_peak_pricing windows
A window rule can now list override_dates: YYYY-MM-DD dates read on the block's weekday_timezone calendar. On a listed date only the matching rules decide (weekdays ignored, flat hours_utc and other rules skipped); on any other date a rule carrying override_dates never applies. The DeepSeek rows model the 2026 PRC public holidays (off-peak all day) and make-up workdays (weekday off-peak hours) this way.
This commit is contained in:
parent
b527ff0e40
commit
20507eb3e9
9 changed files with 361 additions and 355 deletions
|
|
@ -60,6 +60,15 @@ OFF_PEAK_WINDOW: Final[JsonSchema] = {
|
|||
},
|
||||
"minItems": 1,
|
||||
},
|
||||
"override_dates": {
|
||||
"type": "array",
|
||||
"items": ISO_DATE,
|
||||
"minItems": 1,
|
||||
"description": (
|
||||
"YYYY-MM-DD dates, read on weekday_timezone, on which this rule alone decides: "
|
||||
"weekdays and every other window are ignored. On any other date the rule does not apply."
|
||||
),
|
||||
},
|
||||
},
|
||||
"required": ["hours_utc"],
|
||||
"additionalProperties": False,
|
||||
|
|
@ -76,21 +85,6 @@ OBJECT_KEYS: dict[str, JsonSchema] = {
|
|||
"type": "string",
|
||||
"description": "IANA zone the weekdays of each window are read on; defaults to UTC.",
|
||||
},
|
||||
"off_peak_dates": {
|
||||
"type": "array",
|
||||
"items": ISO_DATE,
|
||||
"minItems": 1,
|
||||
"description": "Calendar dates, read on weekday_timezone, that are off-peak all day (public holidays).",
|
||||
},
|
||||
"weekday_dates": {
|
||||
"type": "array",
|
||||
"items": ISO_DATE,
|
||||
"minItems": 1,
|
||||
"description": (
|
||||
"Calendar dates, read on weekday_timezone, that follow the Monday-to-Friday rules "
|
||||
"even when they fall on a weekend (make-up workdays)."
|
||||
),
|
||||
},
|
||||
"input_cost_per_token": NONNEG_NUMBER,
|
||||
"output_cost_per_token": NONNEG_NUMBER,
|
||||
"output_cost_per_reasoning_token": NONNEG_NUMBER,
|
||||
|
|
|
|||
|
|
@ -116,6 +116,9 @@ pub struct OffPeakWindow {
|
|||
pub hours_utc: UtcHours,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub weekdays: Option<Vec<Weekday>>,
|
||||
/// YYYY-MM-DD dates on which this rule alone decides, ignoring weekdays and other windows.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub override_dates: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
/// Rates that replace the same-named base fields inside the stated UTC windows.
|
||||
|
|
@ -129,12 +132,6 @@ pub struct OffPeakPricing {
|
|||
pub windows: Option<Vec<OffPeakWindow>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub weekday_timezone: Option<String>,
|
||||
/// YYYY-MM-DD dates, read on weekday_timezone, that are off-peak all day.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub off_peak_dates: Option<Vec<String>>,
|
||||
/// YYYY-MM-DD dates, read on weekday_timezone, that follow the Monday-to-Friday rules.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub weekday_dates: Option<Vec<String>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub input_cost_per_token: Option<f64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
|
|
|
|||
|
|
@ -466,32 +466,22 @@ def _weekday_calendar(weekday_timezone: object) -> tzinfo:
|
|||
return timezone.utc
|
||||
|
||||
|
||||
_MONDAY_TO_FRIDAY: Final = frozenset({1, 2, 3, 4, 5})
|
||||
|
||||
|
||||
def _calendar_date(reference_utc: datetime, weekday_timezone: object) -> str:
|
||||
return reference_utc.astimezone(_weekday_calendar(weekday_timezone)).date().isoformat()
|
||||
|
||||
|
||||
def _matches_weekdays(
|
||||
reference_utc: datetime, weekdays: object, weekday_timezone: object, weekday_dates: frozenset[str]
|
||||
) -> bool:
|
||||
def _matches_weekdays(reference_utc: datetime, weekdays: object, weekday_timezone: object) -> bool:
|
||||
"""Return True when reference_utc falls on one of the rule's weekdays, read on the calendar
|
||||
named by weekday_timezone (default UTC). An absent weekdays means every day. The calendar
|
||||
matters even when UTC and vendor-local weekdays agree at every currently priced hour: a
|
||||
window past 16:00 UTC is where an Asia/Shanghai weekday diverges from the UTC one. A
|
||||
calendar date listed in weekday_dates is a make-up workday, so it follows the
|
||||
Monday-to-Friday rules whatever its real isoweekday is.
|
||||
window past 16:00 UTC is where an Asia/Shanghai weekday diverges from the UTC one.
|
||||
"""
|
||||
if weekdays is None:
|
||||
return True
|
||||
if isinstance(weekdays, str) or not isinstance(weekdays, Sequence):
|
||||
return False
|
||||
allowed: Final = frozenset(day for day in map(_normalize_weekday, weekdays) if day is not None)
|
||||
local: Final = reference_utc.astimezone(_weekday_calendar(weekday_timezone))
|
||||
if local.date().isoformat() in weekday_dates:
|
||||
return not allowed.isdisjoint(_MONDAY_TO_FRIDAY)
|
||||
return local.isoweekday() in allowed
|
||||
return reference_utc.astimezone(_weekday_calendar(weekday_timezone)).isoweekday() in allowed
|
||||
|
||||
|
||||
def _as_window_strings(value: object) -> tuple[str, ...]:
|
||||
|
|
@ -502,40 +492,48 @@ def _as_window_strings(value: object) -> tuple[str, ...]:
|
|||
return ()
|
||||
|
||||
|
||||
def _as_date_strings(value: object) -> frozenset[str]:
|
||||
def _as_date_strings(value: object) -> tuple[str, ...]:
|
||||
if isinstance(value, str) or not isinstance(value, Sequence):
|
||||
return frozenset()
|
||||
return frozenset(entry for entry in value if isinstance(entry, str))
|
||||
return ()
|
||||
return tuple(entry for entry in value if isinstance(entry, str))
|
||||
|
||||
|
||||
def _is_off_peak(off_peak: Mapping[str, object], current_time: datetime | None = None) -> bool:
|
||||
"""Return True when current_time (UTC, defaulting to now) is off-peak under the block's
|
||||
rules: the flat hours_utc windows, which apply every day, or any entry in windows, whose
|
||||
hours apply only on its weekdays. off_peak_dates lists calendar dates that are off-peak
|
||||
all day, and weekday_dates lists dates that follow the Monday-to-Friday rules even on a
|
||||
weekend; both are read on the weekday_timezone calendar.
|
||||
hours apply only on its weekdays. A rule carrying override_dates applies only on those
|
||||
dates, read on the weekday_timezone calendar: on a listed date the matching rules alone
|
||||
decide (their weekdays are ignored, and the flat hours_utc and every other rule are
|
||||
skipped), and on any other date the rule never applies.
|
||||
"""
|
||||
reference: Final = current_time if current_time is not None else current_billing_time()
|
||||
reference_utc: Final = (
|
||||
reference.astimezone(timezone.utc) if reference.tzinfo is not None else reference.replace(tzinfo=timezone.utc)
|
||||
)
|
||||
weekday_timezone: Final = off_peak.get("weekday_timezone")
|
||||
if _calendar_date(reference_utc, weekday_timezone) in _as_date_strings(off_peak.get("off_peak_dates")):
|
||||
return True
|
||||
today: Final = _calendar_date(reference_utc, weekday_timezone)
|
||||
windows: Final = off_peak.get("windows")
|
||||
rules: Final = (
|
||||
()
|
||||
if isinstance(windows, str) or not isinstance(windows, Sequence)
|
||||
else tuple(rule for rule in windows if isinstance(rule, Mapping))
|
||||
)
|
||||
override_rules: Final = tuple(rule for rule in rules if today in _as_date_strings(rule.get("override_dates")))
|
||||
if override_rules:
|
||||
for rule in override_rules:
|
||||
if _is_within_off_peak_window(_as_window_strings(rule.get("hours_utc")), reference_utc):
|
||||
return True
|
||||
return False
|
||||
flat_windows: Final = _as_window_strings(off_peak.get("hours_utc"))
|
||||
if flat_windows and _is_within_off_peak_window(flat_windows, reference_utc):
|
||||
return True
|
||||
windows: Final = off_peak.get("windows")
|
||||
if isinstance(windows, str) or not isinstance(windows, Sequence):
|
||||
return False
|
||||
weekday_dates: Final = _as_date_strings(off_peak.get("weekday_dates"))
|
||||
for rule in windows:
|
||||
if not isinstance(rule, Mapping):
|
||||
for rule in rules:
|
||||
if _as_date_strings(rule.get("override_dates")):
|
||||
continue
|
||||
rule_windows = _as_window_strings(rule.get("hours_utc"))
|
||||
if not rule_windows:
|
||||
continue
|
||||
if not _matches_weekdays(reference_utc, rule.get("weekdays"), weekday_timezone, weekday_dates):
|
||||
if not _matches_weekdays(reference_utc, rule.get("weekdays"), weekday_timezone):
|
||||
continue
|
||||
if _is_within_off_peak_window(rule_windows, reference_utc):
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -58222,51 +58222,7 @@
|
|||
"off_peak_pricing": {
|
||||
"cache_read_input_token_cost": 3e-09,
|
||||
"input_cost_per_token": 1.5e-07,
|
||||
"off_peak_dates": [
|
||||
"2026-01-01",
|
||||
"2026-01-02",
|
||||
"2026-01-03",
|
||||
"2026-02-15",
|
||||
"2026-02-16",
|
||||
"2026-02-17",
|
||||
"2026-02-18",
|
||||
"2026-02-19",
|
||||
"2026-02-20",
|
||||
"2026-02-21",
|
||||
"2026-02-22",
|
||||
"2026-02-23",
|
||||
"2026-04-04",
|
||||
"2026-04-05",
|
||||
"2026-04-06",
|
||||
"2026-05-01",
|
||||
"2026-05-02",
|
||||
"2026-05-03",
|
||||
"2026-05-04",
|
||||
"2026-05-05",
|
||||
"2026-06-19",
|
||||
"2026-06-20",
|
||||
"2026-06-21",
|
||||
"2026-09-25",
|
||||
"2026-09-26",
|
||||
"2026-09-27",
|
||||
"2026-10-01",
|
||||
"2026-10-02",
|
||||
"2026-10-03",
|
||||
"2026-10-04",
|
||||
"2026-10-05",
|
||||
"2026-10-06",
|
||||
"2026-10-07"
|
||||
],
|
||||
"output_cost_per_token": 6e-07,
|
||||
"weekday_dates": [
|
||||
"2026-01-04",
|
||||
"2026-02-14",
|
||||
"2026-02-28",
|
||||
"2026-05-09",
|
||||
"2026-09-20",
|
||||
"2026-10-10"
|
||||
],
|
||||
"weekday_timezone": "Asia/Shanghai",
|
||||
"windows": [
|
||||
{
|
||||
"hours_utc": [
|
||||
|
|
@ -58288,6 +58244,59 @@
|
|||
6,
|
||||
7
|
||||
]
|
||||
},
|
||||
{
|
||||
"hours_utc": "00:00-00:00",
|
||||
"override_dates": [
|
||||
"2026-01-01",
|
||||
"2026-01-02",
|
||||
"2026-01-03",
|
||||
"2026-02-15",
|
||||
"2026-02-16",
|
||||
"2026-02-17",
|
||||
"2026-02-18",
|
||||
"2026-02-19",
|
||||
"2026-02-20",
|
||||
"2026-02-21",
|
||||
"2026-02-22",
|
||||
"2026-02-23",
|
||||
"2026-04-04",
|
||||
"2026-04-05",
|
||||
"2026-04-06",
|
||||
"2026-05-01",
|
||||
"2026-05-02",
|
||||
"2026-05-03",
|
||||
"2026-05-04",
|
||||
"2026-05-05",
|
||||
"2026-06-19",
|
||||
"2026-06-20",
|
||||
"2026-06-21",
|
||||
"2026-09-25",
|
||||
"2026-09-26",
|
||||
"2026-09-27",
|
||||
"2026-10-01",
|
||||
"2026-10-02",
|
||||
"2026-10-03",
|
||||
"2026-10-04",
|
||||
"2026-10-05",
|
||||
"2026-10-06",
|
||||
"2026-10-07"
|
||||
]
|
||||
},
|
||||
{
|
||||
"hours_utc": [
|
||||
"00:00-01:00",
|
||||
"04:00-06:00",
|
||||
"10:00-00:00"
|
||||
],
|
||||
"override_dates": [
|
||||
"2026-01-04",
|
||||
"2026-02-14",
|
||||
"2026-02-28",
|
||||
"2026-05-09",
|
||||
"2026-09-20",
|
||||
"2026-10-10"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -58428,51 +58437,7 @@
|
|||
"off_peak_pricing": {
|
||||
"cache_read_input_token_cost": 2.2e-08,
|
||||
"input_cost_per_token": 6.6e-07,
|
||||
"off_peak_dates": [
|
||||
"2026-01-01",
|
||||
"2026-01-02",
|
||||
"2026-01-03",
|
||||
"2026-02-15",
|
||||
"2026-02-16",
|
||||
"2026-02-17",
|
||||
"2026-02-18",
|
||||
"2026-02-19",
|
||||
"2026-02-20",
|
||||
"2026-02-21",
|
||||
"2026-02-22",
|
||||
"2026-02-23",
|
||||
"2026-04-04",
|
||||
"2026-04-05",
|
||||
"2026-04-06",
|
||||
"2026-05-01",
|
||||
"2026-05-02",
|
||||
"2026-05-03",
|
||||
"2026-05-04",
|
||||
"2026-05-05",
|
||||
"2026-06-19",
|
||||
"2026-06-20",
|
||||
"2026-06-21",
|
||||
"2026-09-25",
|
||||
"2026-09-26",
|
||||
"2026-09-27",
|
||||
"2026-10-01",
|
||||
"2026-10-02",
|
||||
"2026-10-03",
|
||||
"2026-10-04",
|
||||
"2026-10-05",
|
||||
"2026-10-06",
|
||||
"2026-10-07"
|
||||
],
|
||||
"output_cost_per_token": 1.98e-06,
|
||||
"weekday_dates": [
|
||||
"2026-01-04",
|
||||
"2026-02-14",
|
||||
"2026-02-28",
|
||||
"2026-05-09",
|
||||
"2026-09-20",
|
||||
"2026-10-10"
|
||||
],
|
||||
"weekday_timezone": "Asia/Shanghai",
|
||||
"windows": [
|
||||
{
|
||||
"hours_utc": [
|
||||
|
|
@ -58494,6 +58459,59 @@
|
|||
6,
|
||||
7
|
||||
]
|
||||
},
|
||||
{
|
||||
"hours_utc": "00:00-00:00",
|
||||
"override_dates": [
|
||||
"2026-01-01",
|
||||
"2026-01-02",
|
||||
"2026-01-03",
|
||||
"2026-02-15",
|
||||
"2026-02-16",
|
||||
"2026-02-17",
|
||||
"2026-02-18",
|
||||
"2026-02-19",
|
||||
"2026-02-20",
|
||||
"2026-02-21",
|
||||
"2026-02-22",
|
||||
"2026-02-23",
|
||||
"2026-04-04",
|
||||
"2026-04-05",
|
||||
"2026-04-06",
|
||||
"2026-05-01",
|
||||
"2026-05-02",
|
||||
"2026-05-03",
|
||||
"2026-05-04",
|
||||
"2026-05-05",
|
||||
"2026-06-19",
|
||||
"2026-06-20",
|
||||
"2026-06-21",
|
||||
"2026-09-25",
|
||||
"2026-09-26",
|
||||
"2026-09-27",
|
||||
"2026-10-01",
|
||||
"2026-10-02",
|
||||
"2026-10-03",
|
||||
"2026-10-04",
|
||||
"2026-10-05",
|
||||
"2026-10-06",
|
||||
"2026-10-07"
|
||||
]
|
||||
},
|
||||
{
|
||||
"hours_utc": [
|
||||
"00:00-01:00",
|
||||
"04:00-06:00",
|
||||
"10:00-00:00"
|
||||
],
|
||||
"override_dates": [
|
||||
"2026-01-04",
|
||||
"2026-02-14",
|
||||
"2026-02-28",
|
||||
"2026-05-09",
|
||||
"2026-09-20",
|
||||
"2026-10-10"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -233,11 +233,14 @@ class OffPeakWindow(TypedDict, total=False):
|
|||
midnight and an equal-ended window covers the whole day. weekdays is a list of days the
|
||||
rule applies on, as ISO-8601 numbers (1 = Monday .. 7 = Sunday) or English day names;
|
||||
omitted means every day. The weekday is read on the calendar named by the block's
|
||||
weekday_timezone.
|
||||
weekday_timezone. override_dates lists YYYY-MM-DD dates on that calendar on which this
|
||||
rule alone decides, ignoring weekdays and every other window; on any other date the
|
||||
rule does not apply.
|
||||
"""
|
||||
|
||||
hours_utc: ReadOnly[str | Sequence[str]]
|
||||
weekdays: ReadOnly[Sequence[int | str]]
|
||||
override_dates: ReadOnly[Sequence[str]]
|
||||
|
||||
|
||||
class OffPeakPricing(TypedDict, total=False):
|
||||
|
|
@ -247,17 +250,12 @@ class OffPeakPricing(TypedDict, total=False):
|
|||
applying on every day of the week; a window may wrap past midnight. windows adds
|
||||
day-of-week-qualified rules (e.g. weekend-only whole-day off-peak), matched as a union
|
||||
with hours_utc. weekday_timezone names the IANA calendar weekdays are read on, defaulting
|
||||
to UTC. off_peak_dates lists YYYY-MM-DD dates, read on that calendar, that are off-peak
|
||||
all day (public holidays), and weekday_dates lists dates that follow the Monday-to-Friday
|
||||
rules even on a weekend (make-up workdays). Any rate left unset falls back to the
|
||||
standard rate.
|
||||
to UTC. Any rate left unset falls back to the standard rate.
|
||||
"""
|
||||
|
||||
hours_utc: ReadOnly[str | Sequence[str]]
|
||||
windows: ReadOnly[Sequence[OffPeakWindow]]
|
||||
weekday_timezone: ReadOnly[str]
|
||||
off_peak_dates: ReadOnly[Sequence[str]]
|
||||
weekday_dates: ReadOnly[Sequence[str]]
|
||||
input_cost_per_token: ReadOnly[float]
|
||||
output_cost_per_token: ReadOnly[float]
|
||||
output_cost_per_reasoning_token: ReadOnly[float]
|
||||
|
|
|
|||
|
|
@ -58222,51 +58222,7 @@
|
|||
"off_peak_pricing": {
|
||||
"cache_read_input_token_cost": 3e-09,
|
||||
"input_cost_per_token": 1.5e-07,
|
||||
"off_peak_dates": [
|
||||
"2026-01-01",
|
||||
"2026-01-02",
|
||||
"2026-01-03",
|
||||
"2026-02-15",
|
||||
"2026-02-16",
|
||||
"2026-02-17",
|
||||
"2026-02-18",
|
||||
"2026-02-19",
|
||||
"2026-02-20",
|
||||
"2026-02-21",
|
||||
"2026-02-22",
|
||||
"2026-02-23",
|
||||
"2026-04-04",
|
||||
"2026-04-05",
|
||||
"2026-04-06",
|
||||
"2026-05-01",
|
||||
"2026-05-02",
|
||||
"2026-05-03",
|
||||
"2026-05-04",
|
||||
"2026-05-05",
|
||||
"2026-06-19",
|
||||
"2026-06-20",
|
||||
"2026-06-21",
|
||||
"2026-09-25",
|
||||
"2026-09-26",
|
||||
"2026-09-27",
|
||||
"2026-10-01",
|
||||
"2026-10-02",
|
||||
"2026-10-03",
|
||||
"2026-10-04",
|
||||
"2026-10-05",
|
||||
"2026-10-06",
|
||||
"2026-10-07"
|
||||
],
|
||||
"output_cost_per_token": 6e-07,
|
||||
"weekday_dates": [
|
||||
"2026-01-04",
|
||||
"2026-02-14",
|
||||
"2026-02-28",
|
||||
"2026-05-09",
|
||||
"2026-09-20",
|
||||
"2026-10-10"
|
||||
],
|
||||
"weekday_timezone": "Asia/Shanghai",
|
||||
"windows": [
|
||||
{
|
||||
"hours_utc": [
|
||||
|
|
@ -58288,6 +58244,59 @@
|
|||
6,
|
||||
7
|
||||
]
|
||||
},
|
||||
{
|
||||
"hours_utc": "00:00-00:00",
|
||||
"override_dates": [
|
||||
"2026-01-01",
|
||||
"2026-01-02",
|
||||
"2026-01-03",
|
||||
"2026-02-15",
|
||||
"2026-02-16",
|
||||
"2026-02-17",
|
||||
"2026-02-18",
|
||||
"2026-02-19",
|
||||
"2026-02-20",
|
||||
"2026-02-21",
|
||||
"2026-02-22",
|
||||
"2026-02-23",
|
||||
"2026-04-04",
|
||||
"2026-04-05",
|
||||
"2026-04-06",
|
||||
"2026-05-01",
|
||||
"2026-05-02",
|
||||
"2026-05-03",
|
||||
"2026-05-04",
|
||||
"2026-05-05",
|
||||
"2026-06-19",
|
||||
"2026-06-20",
|
||||
"2026-06-21",
|
||||
"2026-09-25",
|
||||
"2026-09-26",
|
||||
"2026-09-27",
|
||||
"2026-10-01",
|
||||
"2026-10-02",
|
||||
"2026-10-03",
|
||||
"2026-10-04",
|
||||
"2026-10-05",
|
||||
"2026-10-06",
|
||||
"2026-10-07"
|
||||
]
|
||||
},
|
||||
{
|
||||
"hours_utc": [
|
||||
"00:00-01:00",
|
||||
"04:00-06:00",
|
||||
"10:00-00:00"
|
||||
],
|
||||
"override_dates": [
|
||||
"2026-01-04",
|
||||
"2026-02-14",
|
||||
"2026-02-28",
|
||||
"2026-05-09",
|
||||
"2026-09-20",
|
||||
"2026-10-10"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -58428,51 +58437,7 @@
|
|||
"off_peak_pricing": {
|
||||
"cache_read_input_token_cost": 2.2e-08,
|
||||
"input_cost_per_token": 6.6e-07,
|
||||
"off_peak_dates": [
|
||||
"2026-01-01",
|
||||
"2026-01-02",
|
||||
"2026-01-03",
|
||||
"2026-02-15",
|
||||
"2026-02-16",
|
||||
"2026-02-17",
|
||||
"2026-02-18",
|
||||
"2026-02-19",
|
||||
"2026-02-20",
|
||||
"2026-02-21",
|
||||
"2026-02-22",
|
||||
"2026-02-23",
|
||||
"2026-04-04",
|
||||
"2026-04-05",
|
||||
"2026-04-06",
|
||||
"2026-05-01",
|
||||
"2026-05-02",
|
||||
"2026-05-03",
|
||||
"2026-05-04",
|
||||
"2026-05-05",
|
||||
"2026-06-19",
|
||||
"2026-06-20",
|
||||
"2026-06-21",
|
||||
"2026-09-25",
|
||||
"2026-09-26",
|
||||
"2026-09-27",
|
||||
"2026-10-01",
|
||||
"2026-10-02",
|
||||
"2026-10-03",
|
||||
"2026-10-04",
|
||||
"2026-10-05",
|
||||
"2026-10-06",
|
||||
"2026-10-07"
|
||||
],
|
||||
"output_cost_per_token": 1.98e-06,
|
||||
"weekday_dates": [
|
||||
"2026-01-04",
|
||||
"2026-02-14",
|
||||
"2026-02-28",
|
||||
"2026-05-09",
|
||||
"2026-09-20",
|
||||
"2026-10-10"
|
||||
],
|
||||
"weekday_timezone": "Asia/Shanghai",
|
||||
"windows": [
|
||||
{
|
||||
"hours_utc": [
|
||||
|
|
@ -58494,6 +58459,59 @@
|
|||
6,
|
||||
7
|
||||
]
|
||||
},
|
||||
{
|
||||
"hours_utc": "00:00-00:00",
|
||||
"override_dates": [
|
||||
"2026-01-01",
|
||||
"2026-01-02",
|
||||
"2026-01-03",
|
||||
"2026-02-15",
|
||||
"2026-02-16",
|
||||
"2026-02-17",
|
||||
"2026-02-18",
|
||||
"2026-02-19",
|
||||
"2026-02-20",
|
||||
"2026-02-21",
|
||||
"2026-02-22",
|
||||
"2026-02-23",
|
||||
"2026-04-04",
|
||||
"2026-04-05",
|
||||
"2026-04-06",
|
||||
"2026-05-01",
|
||||
"2026-05-02",
|
||||
"2026-05-03",
|
||||
"2026-05-04",
|
||||
"2026-05-05",
|
||||
"2026-06-19",
|
||||
"2026-06-20",
|
||||
"2026-06-21",
|
||||
"2026-09-25",
|
||||
"2026-09-26",
|
||||
"2026-09-27",
|
||||
"2026-10-01",
|
||||
"2026-10-02",
|
||||
"2026-10-03",
|
||||
"2026-10-04",
|
||||
"2026-10-05",
|
||||
"2026-10-06",
|
||||
"2026-10-07"
|
||||
]
|
||||
},
|
||||
{
|
||||
"hours_utc": [
|
||||
"00:00-01:00",
|
||||
"04:00-06:00",
|
||||
"10:00-00:00"
|
||||
],
|
||||
"override_dates": [
|
||||
"2026-01-04",
|
||||
"2026-02-14",
|
||||
"2026-02-28",
|
||||
"2026-05-09",
|
||||
"2026-09-20",
|
||||
"2026-10-10"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -559,6 +559,16 @@
|
|||
]
|
||||
},
|
||||
"minItems": 1
|
||||
},
|
||||
"override_dates": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
|
||||
},
|
||||
"minItems": 1,
|
||||
"description": "YYYY-MM-DD dates, read on weekday_timezone, on which this rule alone decides: weekdays and every other window are ignored. On any other date the rule does not apply."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
@ -572,26 +582,6 @@
|
|||
"type": "string",
|
||||
"description": "IANA zone the weekdays of each window are read on; defaults to UTC."
|
||||
},
|
||||
"off_peak_dates": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
|
||||
},
|
||||
"minItems": 1,
|
||||
"description": "Calendar dates, read on weekday_timezone, that are off-peak all day (public holidays)."
|
||||
},
|
||||
"weekday_dates": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "date",
|
||||
"pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$"
|
||||
},
|
||||
"minItems": 1,
|
||||
"description": "Calendar dates, read on weekday_timezone, that follow the Monday-to-Friday rules even when they fall on a weekend (make-up workdays)."
|
||||
},
|
||||
"input_cost_per_token": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
|
|
|
|||
|
|
@ -601,156 +601,145 @@ def test_is_off_peak_weekday_qualified_windows_deepseek_schedule():
|
|||
|
||||
|
||||
def test_is_off_peak_holiday_weekday_is_off_peak_all_day():
|
||||
"""A date in off_peak_dates is off-peak around the clock, including inside the peak
|
||||
windows a plain weekday would bill at standard rates."""
|
||||
"""A rule whose override_dates names a public holiday applies its off-peak window all
|
||||
day, including inside the peak hours a plain weekday would bill at standard rates."""
|
||||
from datetime import datetime, timezone
|
||||
|
||||
deepseek = {
|
||||
"weekday_timezone": "Asia/Shanghai",
|
||||
"off_peak_dates": ["2026-01-01", "2026-10-01"],
|
||||
"weekday_dates": ["2026-01-04", "2026-02-14"],
|
||||
"windows": [
|
||||
{"hours_utc": ["00:00-01:00", "04:00-06:00", "10:00-00:00"], "weekdays": [1, 2, 3, 4, 5]},
|
||||
{"hours_utc": "00:00-00:00", "weekdays": [6, 7]},
|
||||
{"hours_utc": "00:00-00:00", "override_dates": ["2026-01-01", "2026-10-01"]},
|
||||
{
|
||||
"hours_utc": ["00:00-01:00", "04:00-06:00", "10:00-00:00"],
|
||||
"override_dates": ["2026-01-04", "2026-02-14"],
|
||||
},
|
||||
],
|
||||
}
|
||||
holiday = datetime(2026, 1, 1, 2, 0, tzinfo=timezone.utc)
|
||||
holiday_second_window = datetime(2026, 1, 1, 7, 30, tzinfo=timezone.utc)
|
||||
normal_thursday = datetime(2026, 1, 8, 2, 0, tzinfo=timezone.utc)
|
||||
normal_thursday_second_window = datetime(2026, 1, 8, 7, 30, tzinfo=timezone.utc)
|
||||
assert _is_off_peak(deepseek, holiday) is True, f"{holiday.isoformat()} is a public holiday"
|
||||
assert _is_off_peak(deepseek, holiday_second_window) is True, (
|
||||
f"{holiday_second_window.isoformat()} is a public holiday"
|
||||
)
|
||||
assert _is_off_peak(deepseek, normal_thursday) is False, (
|
||||
f"{normal_thursday.isoformat()} is a normal Thursday peak hour"
|
||||
)
|
||||
assert _is_off_peak(deepseek, normal_thursday_second_window) is False, (
|
||||
f"{normal_thursday_second_window.isoformat()} is a normal Thursday peak hour"
|
||||
)
|
||||
|
||||
|
||||
def test_is_off_peak_make_up_weekend_day_follows_weekday_rules():
|
||||
"""A Sunday listed in weekday_dates is a make-up workday: the weekday windows apply, so
|
||||
its peak hours bill standard and its weekday off-peak hours bill off-peak."""
|
||||
def test_is_off_peak_make_up_weekend_day_uses_override_hours():
|
||||
"""On a make-up workday only the rule listing the date decides: the weekend whole-day
|
||||
rule does not fire, and the make-up rule's weekday off-peak hours apply instead."""
|
||||
from datetime import datetime, timezone
|
||||
|
||||
deepseek = {
|
||||
"weekday_timezone": "Asia/Shanghai",
|
||||
"off_peak_dates": ["2026-01-01", "2026-10-01"],
|
||||
"weekday_dates": ["2026-01-04", "2026-02-14"],
|
||||
"windows": [
|
||||
{"hours_utc": ["00:00-01:00", "04:00-06:00", "10:00-00:00"], "weekdays": [1, 2, 3, 4, 5]},
|
||||
{"hours_utc": "00:00-00:00", "weekdays": [6, 7]},
|
||||
{"hours_utc": "00:00-00:00", "override_dates": ["2026-01-01", "2026-10-01"]},
|
||||
{
|
||||
"hours_utc": ["00:00-01:00", "04:00-06:00", "10:00-00:00"],
|
||||
"override_dates": ["2026-01-04", "2026-02-14"],
|
||||
},
|
||||
],
|
||||
}
|
||||
make_up_sunday_peak = datetime(2026, 1, 4, 2, 0, tzinfo=timezone.utc)
|
||||
make_up_sunday_peak_second = datetime(2026, 1, 4, 7, 30, tzinfo=timezone.utc)
|
||||
make_up_sunday_off_peak = datetime(2026, 1, 4, 5, 0, tzinfo=timezone.utc)
|
||||
make_up_sunday_off_peak_second = datetime(2026, 1, 4, 12, 0, tzinfo=timezone.utc)
|
||||
plain_sunday = datetime(2026, 1, 11, 2, 0, tzinfo=timezone.utc)
|
||||
assert _is_off_peak(deepseek, make_up_sunday_peak) is False, (
|
||||
f"{make_up_sunday_peak.isoformat()} is a make-up workday peak hour"
|
||||
)
|
||||
assert _is_off_peak(deepseek, make_up_sunday_peak_second) is False, (
|
||||
f"{make_up_sunday_peak_second.isoformat()} is a make-up workday peak hour"
|
||||
)
|
||||
assert _is_off_peak(deepseek, make_up_sunday_off_peak) is True, (
|
||||
f"{make_up_sunday_off_peak.isoformat()} is a make-up workday off-peak hour"
|
||||
)
|
||||
assert _is_off_peak(deepseek, make_up_sunday_off_peak_second) is True, (
|
||||
f"{make_up_sunday_off_peak_second.isoformat()} is a make-up workday off-peak hour"
|
||||
f"{make_up_sunday_off_peak.isoformat()} is inside the make-up rule's off-peak hours"
|
||||
)
|
||||
assert _is_off_peak(deepseek, plain_sunday) is True, (
|
||||
f"{plain_sunday.isoformat()} is a normal Sunday, off-peak all day"
|
||||
)
|
||||
|
||||
|
||||
def test_is_off_peak_date_exceptions_read_on_weekday_timezone_calendar():
|
||||
"""Both date lists are read on the weekday_timezone calendar, so the Shanghai date can
|
||||
def test_is_off_peak_override_skips_flat_hours_and_other_rules():
|
||||
"""On a date an override rule lists, the flat hours_utc and every other rule are
|
||||
skipped: only the matching rules' windows decide."""
|
||||
from datetime import datetime, timezone
|
||||
|
||||
block = {
|
||||
"hours_utc": "00:00-00:00",
|
||||
"windows": [
|
||||
{"hours_utc": "00:00-00:00", "weekdays": [1, 2, 3, 4, 5, 6, 7]},
|
||||
{"override_dates": ["2026-03-03"], "hours_utc": "12:00-13:00"},
|
||||
],
|
||||
}
|
||||
outside_window = datetime(2026, 3, 3, 2, 0, tzinfo=timezone.utc)
|
||||
inside_window = datetime(2026, 3, 3, 12, 30, tzinfo=timezone.utc)
|
||||
next_day = datetime(2026, 3, 4, 2, 0, tzinfo=timezone.utc)
|
||||
assert _is_off_peak(block, outside_window) is False, (
|
||||
"the override rule's window is closed and nothing else applies on its date"
|
||||
)
|
||||
assert _is_off_peak(block, inside_window) is True, "the override rule's window is open"
|
||||
assert _is_off_peak(block, next_day) is True, (
|
||||
"the next day falls back to the flat hours_utc and weekday rules"
|
||||
)
|
||||
|
||||
|
||||
def test_is_off_peak_override_rule_does_not_leak_onto_other_dates():
|
||||
"""A rule carrying override_dates never participates on a date it does not list."""
|
||||
from datetime import datetime, timezone
|
||||
|
||||
block = {"windows": [{"override_dates": ["2026-03-03"], "hours_utc": "00:00-00:00"}]}
|
||||
assert _is_off_peak(block, datetime(2026, 3, 3, 2, 0, tzinfo=timezone.utc)) is True
|
||||
assert _is_off_peak(block, datetime(2026, 3, 4, 2, 0, tzinfo=timezone.utc)) is False
|
||||
|
||||
|
||||
def test_is_off_peak_override_dates_read_on_weekday_timezone_calendar():
|
||||
"""Override dates are read on the weekday_timezone calendar, so the Shanghai date can
|
||||
diverge from the UTC date over 16:00-24:00 UTC."""
|
||||
from datetime import datetime, timezone
|
||||
|
||||
holiday_saturday_rule = {
|
||||
shanghai = {
|
||||
"weekday_timezone": "Asia/Shanghai",
|
||||
"windows": [{"hours_utc": "16:00-17:00", "weekdays": [6, 7]}],
|
||||
"off_peak_dates": ["2026-01-01"],
|
||||
"windows": [{"override_dates": ["2026-01-01"], "hours_utc": "00:00-00:00"}],
|
||||
}
|
||||
shanghai_new_year = datetime(2025, 12, 31, 16, 30, tzinfo=timezone.utc)
|
||||
utc_new_year = datetime(2026, 1, 1, 16, 30, tzinfo=timezone.utc)
|
||||
assert _is_off_peak(holiday_saturday_rule, shanghai_new_year) is True, (
|
||||
f"{shanghai_new_year.isoformat()} is already 2026-01-01 in Shanghai, a holiday"
|
||||
utc_block = {"windows": [{"override_dates": ["2026-01-01"], "hours_utc": "00:00-00:00"}]}
|
||||
in_shanghai = datetime(2025, 12, 31, 16, 30, tzinfo=timezone.utc)
|
||||
before_shanghai = datetime(2025, 12, 31, 15, 30, tzinfo=timezone.utc)
|
||||
assert _is_off_peak(shanghai, in_shanghai) is True, (
|
||||
f"{in_shanghai.isoformat()} is already 2026-01-01 in Shanghai"
|
||||
)
|
||||
assert _is_off_peak(holiday_saturday_rule, utc_new_year) is False, (
|
||||
f"{utc_new_year.isoformat()} is 2026-01-02 in Shanghai, no longer the holiday"
|
||||
assert _is_off_peak(shanghai, before_shanghai) is False, (
|
||||
f"{before_shanghai.isoformat()} is still 2025-12-31 in Shanghai"
|
||||
)
|
||||
|
||||
utc_holiday_saturday_rule = {
|
||||
"windows": [{"hours_utc": "16:00-17:00", "weekdays": [6, 7]}],
|
||||
"off_peak_dates": ["2026-01-01"],
|
||||
}
|
||||
assert _is_off_peak(utc_holiday_saturday_rule, shanghai_new_year) is False, (
|
||||
f"{shanghai_new_year.isoformat()} is still 2025-12-31 on the UTC calendar"
|
||||
)
|
||||
assert _is_off_peak(utc_holiday_saturday_rule, utc_new_year) is True, (
|
||||
f"{utc_new_year.isoformat()} is 2026-01-01 on the UTC calendar"
|
||||
)
|
||||
|
||||
make_up_weekday_rule = {
|
||||
"weekday_timezone": "Asia/Shanghai",
|
||||
"windows": [{"hours_utc": "16:00-17:00", "weekdays": [1, 2, 3, 4, 5]}],
|
||||
"weekday_dates": ["2026-01-04"],
|
||||
}
|
||||
shanghai_make_up_sunday = datetime(2026, 1, 3, 16, 30, tzinfo=timezone.utc)
|
||||
shanghai_saturday = datetime(2026, 1, 2, 16, 30, tzinfo=timezone.utc)
|
||||
assert _is_off_peak(make_up_weekday_rule, shanghai_make_up_sunday) is True, (
|
||||
f"{shanghai_make_up_sunday.isoformat()} is Sunday 2026-01-04 in Shanghai, a make-up workday"
|
||||
)
|
||||
assert _is_off_peak(make_up_weekday_rule, shanghai_saturday) is False, (
|
||||
f"{shanghai_saturday.isoformat()} is Saturday 2026-01-03 in Shanghai"
|
||||
assert _is_off_peak(utc_block, in_shanghai) is False, (
|
||||
f"{in_shanghai.isoformat()} is still 2025-12-31 on the UTC calendar"
|
||||
)
|
||||
|
||||
|
||||
def test_is_off_peak_make_up_day_does_not_match_weekend_only_rules():
|
||||
"""A make-up workday follows the Monday-to-Friday rules, so a weekend-only rule must not
|
||||
match it even though its real isoweekday is Sunday."""
|
||||
def test_is_off_peak_ignores_malformed_override_dates():
|
||||
"""A bare string, non-string entries, or an unparseable date are ignored, so malformed
|
||||
override_dates can never silently widen the off-peak hours."""
|
||||
from datetime import datetime, timezone
|
||||
|
||||
weekend_only = {
|
||||
"windows": [{"hours_utc": "00:00-00:00", "weekdays": [6, 7]}],
|
||||
"weekday_dates": ["2026-01-04"],
|
||||
}
|
||||
make_up_sunday = datetime(2026, 1, 4, 12, 0, tzinfo=timezone.utc)
|
||||
plain_saturday = datetime(2026, 1, 3, 12, 0, tzinfo=timezone.utc)
|
||||
assert _is_off_peak(weekend_only, make_up_sunday) is False, (
|
||||
f"{make_up_sunday.isoformat()} is a make-up workday, not a weekend day"
|
||||
)
|
||||
assert _is_off_peak(weekend_only, plain_saturday) is True, (
|
||||
f"{plain_saturday.isoformat()} is a normal Saturday"
|
||||
)
|
||||
peak_instant = datetime(2026, 1, 1, 12, 0, tzinfo=timezone.utc)
|
||||
weekday_windows = [{"hours_utc": "00:30-01:00", "weekdays": [1, 2, 3, 4, 5]}]
|
||||
for bad in ("2026-01-01", [20260101, None], ["2026-1-1"]):
|
||||
block = {"windows": [{**weekday_windows[0], "override_dates": bad}]}
|
||||
assert _is_off_peak(block, peak_instant) is False, (
|
||||
f"override_dates={bad!r} is malformed and must be ignored"
|
||||
)
|
||||
|
||||
|
||||
def test_is_off_peak_ignores_malformed_date_exceptions():
|
||||
"""A bare string or non-string entries are ignored, matching how a bare weekdays string
|
||||
is treated: malformed config can never silently widen the off-peak hours."""
|
||||
def test_is_off_peak_without_override_dates_is_unchanged():
|
||||
"""The plain DeepSeek windows with no override_dates bill a holiday peak hour at
|
||||
standard rates."""
|
||||
from datetime import datetime, timezone
|
||||
|
||||
holiday = datetime(2026, 1, 1, 12, 0, tzinfo=timezone.utc)
|
||||
weekend_whole_day = [{"hours_utc": "00:00-00:00", "weekdays": [6, 7]}]
|
||||
assert _is_off_peak({"off_peak_dates": "2026-01-01", "windows": weekend_whole_day}, holiday) is False, (
|
||||
"a bare off_peak_dates string is malformed and must be ignored"
|
||||
)
|
||||
block = {"off_peak_dates": ["01/01/2026", 20260101, None], "windows": weekend_whole_day}
|
||||
assert _is_off_peak(block, holiday) is False, "unparseable entries are simply never equal to a date"
|
||||
make_up_sunday = datetime(2026, 1, 4, 12, 0, tzinfo=timezone.utc)
|
||||
block = {"weekday_dates": "2026-01-04", "windows": weekend_whole_day}
|
||||
assert _is_off_peak(block, make_up_sunday) is True, (
|
||||
f"{make_up_sunday.isoformat()} is a plain Sunday once the bare weekday_dates string is ignored"
|
||||
)
|
||||
deepseek = {
|
||||
"windows": [
|
||||
{"hours_utc": ["00:00-01:00", "04:00-06:00", "10:00-00:00"], "weekdays": [1, 2, 3, 4, 5]},
|
||||
{"hours_utc": "00:00-00:00", "weekdays": [6, 7]},
|
||||
],
|
||||
}
|
||||
assert _is_off_peak(deepseek, datetime(2026, 1, 1, 2, 0, tzinfo=timezone.utc)) is False
|
||||
|
||||
|
||||
def test_get_token_base_cost_off_peak_date_bills_holiday_rates():
|
||||
"""End to end through _get_token_base_cost: a holiday listed in off_peak_dates bills the
|
||||
def test_get_token_base_cost_override_dates_bill_holiday_rates():
|
||||
"""End to end through _get_token_base_cost: a date listed on an override rule bills the
|
||||
off-peak input rate during what would be a weekday peak hour."""
|
||||
from datetime import datetime, timezone
|
||||
from typing import cast
|
||||
|
|
@ -763,10 +752,10 @@ def test_get_token_base_cost_off_peak_date_bills_holiday_rates():
|
|||
"input_cost_per_token": 1e-6,
|
||||
"output_cost_per_token": 2e-6,
|
||||
"off_peak_pricing": {
|
||||
"off_peak_dates": ["2026-01-01"],
|
||||
"windows": [
|
||||
{"hours_utc": ["00:00-01:00", "04:00-06:00", "10:00-00:00"], "weekdays": [1, 2, 3, 4, 5]},
|
||||
{"hours_utc": "00:00-00:00", "weekdays": [6, 7]},
|
||||
{"hours_utc": "00:00-00:00", "override_dates": ["2026-01-01"]},
|
||||
],
|
||||
"input_cost_per_token": 5e-7,
|
||||
"output_cost_per_token": 1e-6,
|
||||
|
|
|
|||
|
|
@ -135,10 +135,11 @@ OFF_PEAK_ENTRY: Final = MappingProxyType(
|
|||
"output_cost_per_token": 8e-6,
|
||||
"off_peak_pricing": {
|
||||
"hours_utc": "16:30-00:30",
|
||||
"windows": [{"hours_utc": ["00:30-02:00"], "weekdays": [6, "Sunday", "mon", "THURS"]}],
|
||||
"windows": [
|
||||
{"hours_utc": ["00:30-02:00"], "weekdays": [6, "Sunday", "mon", "THURS"]},
|
||||
{"hours_utc": "00:00-00:00", "override_dates": ["2026-01-01"]},
|
||||
],
|
||||
"weekday_timezone": "Asia/Shanghai",
|
||||
"off_peak_dates": ["2026-01-01"],
|
||||
"weekday_dates": ["2026-01-04"],
|
||||
"input_cost_per_token": 1e-6,
|
||||
"output_cost_per_token": 4e-6,
|
||||
"cache_read_input_token_cost": 1e-7,
|
||||
|
|
@ -169,9 +170,9 @@ def test_generator_classifies_off_peak_pricing_as_a_windowed_rate_block():
|
|||
{"hours_utc": "25:00-01:00", "input_cost_per_token": 1e-6},
|
||||
{"hours_utc": ["16:30-00:30", "4pm-midnight"], "input_cost_per_token": 1e-6},
|
||||
{"windows": [{"hours_utc": "00:30-02:00", "weekdays": ["Funday"]}], "input_cost_per_token": 1e-6},
|
||||
{"hours_utc": "16:30-00:30", "off_peak_dates": ["2026-1-1"], "input_cost_per_token": 1e-6},
|
||||
{"hours_utc": "16:30-00:30", "off_peak_dates": "2026-01-01", "input_cost_per_token": 1e-6},
|
||||
{"hours_utc": "16:30-00:30", "weekday_dates": [], "input_cost_per_token": 1e-6},
|
||||
{"windows": [{"hours_utc": "00:30-02:00", "override_dates": ["2026-1-1"]}], "input_cost_per_token": 1e-6},
|
||||
{"windows": [{"hours_utc": "00:30-02:00", "override_dates": "2026-01-01"}], "input_cost_per_token": 1e-6},
|
||||
{"windows": [{"hours_utc": "00:30-02:00", "override_dates": []}], "input_cost_per_token": 1e-6},
|
||||
],
|
||||
)
|
||||
def test_generated_off_peak_schema_rejects_malformed_blocks(block: dict):
|
||||
|
|
@ -388,7 +389,10 @@ def deepseek_off_peak_drift(entry: Mapping[str, object]) -> str | None:
|
|||
block: Final = entry.get("off_peak_pricing")
|
||||
if not isinstance(block, dict):
|
||||
return "no off_peak_pricing block"
|
||||
if tuple(block.get("windows", ())) != DEEPSEEK_OFF_PEAK_WINDOWS:
|
||||
windows: Final = tuple(block.get("windows", ()))
|
||||
if windows[: len(DEEPSEEK_OFF_PEAK_WINDOWS)] != DEEPSEEK_OFF_PEAK_WINDOWS:
|
||||
return f"windows={block.get('windows')}"
|
||||
if not all("override_dates" in rule for rule in windows[len(DEEPSEEK_OFF_PEAK_WINDOWS) :]):
|
||||
return f"windows={block.get('windows')}"
|
||||
halved: Final = {rate: block.get(rate) for rate in DEEPSEEK_HALVED_RATES}
|
||||
expected: Final = {rate: float(str(entry[rate])) / 2 for rate in DEEPSEEK_HALVED_RATES}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue