Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions ci_cd/generate_model_prices_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
BOOLEAN: JsonSchema = {"type": "boolean"}
STRING: JsonSchema = {"type": "string"}
TIME_WINDOW: Final[JsonSchema] = {"type": "string", "pattern": r"^([01]\d|2[0-3]):[0-5]\d-([01]\d|2[0-3]):[0-5]\d$"}
ISO_DATE: Final[JsonSchema] = {
"type": "string",
"format": "date",
"pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
}
WEEKDAY_PATTERN: Final = (
r"(?i)^(mon|monday|tue|tues|tuesday|wed|wednesday|thu|thur|thurs|thursday|fri|friday|sat|saturday|sun|sunday)$"
)
Expand Down Expand Up @@ -55,6 +60,16 @@
},
"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, and malformed entries disable it."
),
},
},
"required": ["hours_utc"],
"additionalProperties": False,
Expand Down Expand Up @@ -258,10 +273,8 @@ def string_key_schemas(modes: tuple) -> dict[str, JsonSchema]:
"description": "URL of the provider pricing/model page this entry was taken from.",
},
"deprecation_date": {
"type": "string",
**ISO_DATE,
"description": "Date the provider deprecates the model, YYYY-MM-DD.",
"format": "date",
"pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
},
"web_search_billing_unit": {
"type": "string",
Expand Down
3 changes: 3 additions & 0 deletions litellm-rust/crates/model-catalog/src/model_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
38 changes: 31 additions & 7 deletions litellm/litellm_core_utils/llm_cost_calc/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,10 @@ def _weekday_calendar(weekday_timezone: object) -> tzinfo:
return timezone.utc


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) -> 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
Expand All @@ -488,24 +492,44 @@ def _as_window_strings(value: object) -> tuple[str, ...]:
return ()


def _as_date_strings(value: object) -> tuple[str, ...]:
if isinstance(value, str) or not isinstance(value, Sequence):
return ()
return tuple(entry for entry in value if isinstance(entry, str))
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Resolved


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.
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 (a malformed override_dates
disables the rule entirely).
"""
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")
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_timezone: Final = off_peak.get("weekday_timezone")
for rule in windows:
if not isinstance(rule, Mapping):
for rule in rules:
if "override_dates" in rule:
continue
rule_windows = _as_window_strings(rule.get("hours_utc"))
if not rule_windows:
Expand Down
112 changes: 110 additions & 2 deletions litellm/model_prices_and_context_window_backup.json
Original file line number Diff line number Diff line change
Expand Up @@ -58244,8 +58244,62 @@
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"
]
}
]
],
"weekday_timezone": "Asia/Shanghai"
},
"output_cost_per_token": 1.2e-06,
"source": "https://api-docs.deepseek.com/quick_start/pricing",
Expand Down Expand Up @@ -58406,8 +58460,62 @@
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"
]
}
]
],
"weekday_timezone": "Asia/Shanghai"
},
"output_cost_per_token": 3.96e-06,
"source": "https://api-docs.deepseek.com/quick_start/pricing",
Expand Down
5 changes: 4 additions & 1 deletion litellm/types/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, and malformed entries disable it entirely.
"""

hours_utc: ReadOnly[str | Sequence[str]]
weekdays: ReadOnly[Sequence[int | str]]
override_dates: ReadOnly[Sequence[str]]


class OffPeakPricing(TypedDict, total=False):
Expand Down
112 changes: 110 additions & 2 deletions model_prices_and_context_window.json
Original file line number Diff line number Diff line change
Expand Up @@ -58244,8 +58244,62 @@
6,
7
]
},
{
"hours_utc": "00:00-00:00",
"override_dates": [
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
Resolved
"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"
]
}
]
],
"weekday_timezone": "Asia/Shanghai"
},
"output_cost_per_token": 1.2e-06,
"source": "https://api-docs.deepseek.com/quick_start/pricing",
Expand Down Expand Up @@ -58406,8 +58460,62 @@
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"
]
}
]
],
"weekday_timezone": "Asia/Shanghai"
},
"output_cost_per_token": 3.96e-06,
"source": "https://api-docs.deepseek.com/quick_start/pricing",
Expand Down
Loading
Loading