mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-30 01:52:18 +00:00
fix(schema): accept override_dates on off_peak_pricing windows
A window rule may carry override_dates, YYYY-MM-DD dates on which it alone decides, so the generated schema, the OffPeakWindow TypedDict, and the Rust model catalog now model it.
This commit is contained in:
parent
6dbd65b230
commit
ecfcf0b62c
6 changed files with 47 additions and 8 deletions
|
|
@ -20,6 +20,11 @@ NONNEG_INTEGER: JsonSchema = {"type": "integer", "minimum": 0}
|
|||
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)$"
|
||||
)
|
||||
|
|
@ -55,6 +60,16 @@ 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, and malformed entries disable it."
|
||||
),
|
||||
},
|
||||
},
|
||||
"required": ["hours_utc"],
|
||||
"additionalProperties": False,
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -249,9 +249,9 @@
|
|||
},
|
||||
"deprecation_date": {
|
||||
"type": "string",
|
||||
"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])$"
|
||||
"pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$",
|
||||
"description": "Date the provider deprecates the model, YYYY-MM-DD."
|
||||
},
|
||||
"gemini_audio_only_live": {
|
||||
"type": "boolean"
|
||||
|
|
@ -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, and malformed entries disable it."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
|
|||
|
|
@ -135,7 +135,10 @@ 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",
|
||||
"input_cost_per_token": 1e-6,
|
||||
"output_cost_per_token": 4e-6,
|
||||
|
|
@ -167,6 +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},
|
||||
{"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):
|
||||
|
|
@ -383,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}
|
||||
|
|
|
|||
|
|
@ -1057,6 +1057,7 @@ def test_aaamodel_prices_and_context_window_json_is_valid():
|
|||
"type": "array",
|
||||
"items": {"oneOf": [{"type": "integer"}, {"type": "string"}]},
|
||||
},
|
||||
"override_dates": {"type": "array", "items": {"type": "string"}},
|
||||
},
|
||||
"required": ["hours_utc"],
|
||||
"additionalProperties": False,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue