feat: natural language date shortcuts for litellm_cost()
Adds _resolve_date() helper that converts natural language shortcuts into YYYY-MM-DD before calling the LiteLLM API. Supported shortcuts: - today, yesterday, tomorrow - N days ago (e.g. "two days ago") - monday-sunday (most recent occurrence) - last monday-last sunday - this week, last week - this month, last month Falls back to passthrough for already-formatted YYYY-MM-DD strings. Updated README with new parameter documentation.
This commit is contained in:
1 parent
67f79cfabe
commit
0fd8fcb742
2 files changed
+79
-5
No files matched your search
@@ -11,8 +11,8 @@ Check LiteLLM proxy health and authentication status. Returns which models are h
|
||||
Get LiteLLM cost breakdown for a date range. Returns per-model and per-day spend, token counts, cache hit rate, and request stats.
|
||||
|
||||
**Parameters:**
|
||||
- `start_date` (str, required): Start date in YYYY-MM-DD format
|
||||
- `end_date` (str, required): End date in YYYY-MM-DD format
|
||||
- `start_date` (str, required): Start date — YYYY-MM-DD or natural language shortcut (e.g. "2026-06-01", "today", "yesterday", "monday", "last monday", "two days ago", "this week", "last month")
|
||||
- `end_date` (str, required): End date — YYYY-MM-DD or natural language shortcut
|
||||
- `hide_zero_spend` (bool, default false): Hide models with sub-$0.001 spend. Useful when free-tier or subscription models (e.g. Ollama Cloud) dominate the breakdown with high token counts but negligible cost.
|
||||
|
||||
### `litellm_history`
|
||||
|
||||
+77
-3
@@ -10,6 +10,7 @@ licence: MIT
|
||||
"""
|
||||
|
||||
import requests
|
||||
from datetime import datetime, timedelta
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Optional
|
||||
|
||||
@@ -40,6 +41,76 @@ class Tools:
|
||||
"""Get base URL, strip trailing slash."""
|
||||
return self.valves.litellm_url.rstrip("/")
|
||||
|
||||
def _resolve_date(self, date_str: str) -> str:
|
||||
"""Resolve natural language date shortcuts to YYYY-MM-DD.
|
||||
|
||||
Supports: today, yesterday, tomorrow, N days ago,
|
||||
monday-sunday (this week), last monday-last sunday,
|
||||
this week, last week, this month, last month.
|
||||
Falls back to passthrough if already YYYY-MM-DD or unrecognized.
|
||||
"""
|
||||
date_str = date_str.strip().lower()
|
||||
today = datetime.utcnow().date()
|
||||
|
||||
# Direct shortcuts
|
||||
if date_str == "today":
|
||||
return today.isoformat()
|
||||
if date_str == "yesterday":
|
||||
return (today - timedelta(days=1)).isoformat()
|
||||
if date_str == "tomorrow":
|
||||
return (today + timedelta(days=1)).isoformat()
|
||||
|
||||
# "N days ago"
|
||||
if "days ago" in date_str:
|
||||
try:
|
||||
n = int(date_str.split()[0])
|
||||
return (today - timedelta(days=n)).isoformat()
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
# Day names — most recent occurrence (including today if it matches)
|
||||
days = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]
|
||||
if date_str in days:
|
||||
target_day = days.index(date_str)
|
||||
days_back = (today.weekday() - target_day) % 7
|
||||
return (today - timedelta(days=days_back)).isoformat()
|
||||
|
||||
# "last monday", "last tuesday", etc.
|
||||
if date_str.startswith("last "):
|
||||
day_part = date_str[5:].strip()
|
||||
if day_part in days:
|
||||
target_day = days.index(day_part)
|
||||
days_back = (today.weekday() - target_day) % 7 + 7
|
||||
return (today - timedelta(days=days_back)).isoformat()
|
||||
|
||||
# "this week" → Monday of this week
|
||||
if date_str == "this week":
|
||||
return (today - timedelta(days=today.weekday())).isoformat()
|
||||
|
||||
# "last week" → Monday of last week
|
||||
if date_str == "last week":
|
||||
return (today - timedelta(days=today.weekday() + 7)).isoformat()
|
||||
|
||||
# "this month" → 1st of this month
|
||||
if date_str == "this month":
|
||||
return today.replace(day=1).isoformat()
|
||||
|
||||
# "last month" → 1st of last month
|
||||
if date_str == "last month":
|
||||
if today.month == 1:
|
||||
return today.replace(year=today.year - 1, month=12, day=1).isoformat()
|
||||
return today.replace(month=today.month - 1, day=1).isoformat()
|
||||
|
||||
# Already YYYY-MM-DD — passthrough
|
||||
try:
|
||||
datetime.strptime(date_str, "%Y-%m-%d")
|
||||
return date_str
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Unknown — return as-is (API will reject with clear error)
|
||||
return date_str
|
||||
|
||||
def litellm_health(self) -> str:
|
||||
"""
|
||||
Check LiteLLM proxy health and authentication status.
|
||||
@@ -123,17 +194,20 @@ class Tools:
|
||||
) -> str:
|
||||
"""
|
||||
Get LiteLLM cost breakdown for a date range.
|
||||
:param start_date: Start date in YYYY-MM-DD format (e.g. "2026-06-01")
|
||||
:param end_date: End date in YYYY-MM-DD format (e.g. "2026-06-04")
|
||||
:param start_date: Start date — YYYY-MM-DD or natural language shortcut (e.g. "2026-06-01", "today", "yesterday", "monday", "last monday", "two days ago", "this week", "last month")
|
||||
:param end_date: End date — YYYY-MM-DD or natural language shortcut
|
||||
:param hide_zero_spend: Hide models with sub-$0.001 spend (default False). Useful when free-tier or subscription models (e.g. Ollama Cloud) dominate the breakdown with high token counts but negligible cost.
|
||||
Returns formatted cost report with per-model and per-day breakdowns, token counts, cache hit rate, and request stats.
|
||||
"""
|
||||
if not self.valves.litellm_master_key:
|
||||
return "❌ Master key required for cost data. Set the litellm_master_key valve."
|
||||
|
||||
resolved_start = self._resolve_date(start_date)
|
||||
resolved_end = self._resolve_date(end_date)
|
||||
|
||||
url = f"{self._base_url()}/user/daily/activity"
|
||||
headers = self._headers()
|
||||
params = {"start_date": start_date, "end_date": end_date}
|
||||
params = {"start_date": resolved_start, "end_date": resolved_end}
|
||||
|
||||
try:
|
||||
resp = requests.get(url, headers=headers, params=params, timeout=30)
|
||||
|
||||
Reference in new issue
Block a user