mirror of
https://github.com/BerriAI/litellm.git
synced 2025-04-25 18:54:30 +00:00
* LiteLLM Minor Fixes & Improvements (09/16/2024) (#5723) * coverage (#5713) Signed-off-by: dbczumar <corey.zumar@databricks.com> * Move (#5714) Signed-off-by: dbczumar <corey.zumar@databricks.com> * fix(litellm_logging.py): fix logging client re-init (#5710) Fixes https://github.com/BerriAI/litellm/issues/5695 * fix(presidio.py): Fix logging_hook response and add support for additional presidio variables in guardrails config Fixes https://github.com/BerriAI/litellm/issues/5682 * feat(o1_handler.py): fake streaming for openai o1 models Fixes https://github.com/BerriAI/litellm/issues/5694 * docs: deprecated traceloop integration in favor of native otel (#5249) * fix: fix linting errors * fix: fix linting errors * fix(main.py): fix o1 import --------- Signed-off-by: dbczumar <corey.zumar@databricks.com> Co-authored-by: Corey Zumar <39497902+dbczumar@users.noreply.github.com> Co-authored-by: Nir Gazit <nirga@users.noreply.github.com> * feat(spend_management_endpoints.py): expose `/global/spend/refresh` endpoint for updating material view (#5730) * feat(spend_management_endpoints.py): expose `/global/spend/refresh` endpoint for updating material view Supports having `MonthlyGlobalSpend` view be a material view, and exposes an endpoint to refresh it * fix(custom_logger.py): reset calltype * fix: fix linting errors * fix: fix linting error * fix: fix import * test(test_databricks.py): fix databricks tests --------- Signed-off-by: dbczumar <corey.zumar@databricks.com> Co-authored-by: Corey Zumar <39497902+dbczumar@users.noreply.github.com> Co-authored-by: Nir Gazit <nirga@users.noreply.github.com>
This commit is contained in:
parent
1e59395280
commit
234185ec13
34 changed files with 1387 additions and 502 deletions
|
@ -92,6 +92,7 @@ def safe_deep_copy(data):
|
|||
if litellm.safe_memory_mode is True:
|
||||
return data
|
||||
|
||||
litellm_parent_otel_span: Optional[Any] = None
|
||||
# Step 1: Remove the litellm_parent_otel_span
|
||||
litellm_parent_otel_span = None
|
||||
if isinstance(data, dict):
|
||||
|
@ -101,7 +102,7 @@ def safe_deep_copy(data):
|
|||
new_data = copy.deepcopy(data)
|
||||
|
||||
# Step 2: re-add the litellm_parent_otel_span after doing a deep copy
|
||||
if isinstance(data, dict):
|
||||
if isinstance(data, dict) and litellm_parent_otel_span is not None:
|
||||
if "metadata" in data:
|
||||
data["metadata"]["litellm_parent_otel_span"] = litellm_parent_otel_span
|
||||
return new_data
|
||||
|
@ -468,7 +469,7 @@ class ProxyLogging:
|
|||
|
||||
# V1 implementation - backwards compatibility
|
||||
if callback.event_hook is None:
|
||||
if callback.moderation_check == "pre_call":
|
||||
if callback.moderation_check == "pre_call": # type: ignore
|
||||
return
|
||||
else:
|
||||
# Main - V2 Guardrails implementation
|
||||
|
@ -881,7 +882,12 @@ class PrismaClient:
|
|||
org_list_transactons: dict = {}
|
||||
spend_log_transactions: List = []
|
||||
|
||||
def __init__(self, database_url: str, proxy_logging_obj: ProxyLogging):
|
||||
def __init__(
|
||||
self,
|
||||
database_url: str,
|
||||
proxy_logging_obj: ProxyLogging,
|
||||
http_client: Optional[Any] = None,
|
||||
):
|
||||
verbose_proxy_logger.debug(
|
||||
"LiteLLM: DATABASE_URL Set in config, trying to 'pip install prisma'"
|
||||
)
|
||||
|
@ -912,7 +918,10 @@ class PrismaClient:
|
|||
# Now you can import the Prisma Client
|
||||
from prisma import Prisma # type: ignore
|
||||
verbose_proxy_logger.debug("Connecting Prisma Client to DB..")
|
||||
self.db = Prisma() # Client to connect to Prisma db
|
||||
if http_client is not None:
|
||||
self.db = Prisma(http=http_client)
|
||||
else:
|
||||
self.db = Prisma() # Client to connect to Prisma db
|
||||
verbose_proxy_logger.debug("Success - Connected Prisma Client to DB")
|
||||
|
||||
def hash_token(self, token: str):
|
||||
|
@ -987,7 +996,7 @@ class PrismaClient:
|
|||
return
|
||||
else:
|
||||
## check if required view exists ##
|
||||
if required_view not in ret[0]["view_names"]:
|
||||
if ret[0]["view_names"] and required_view not in ret[0]["view_names"]:
|
||||
await self.health_check() # make sure we can connect to db
|
||||
await self.db.execute_raw(
|
||||
"""
|
||||
|
@ -1009,7 +1018,9 @@ class PrismaClient:
|
|||
else:
|
||||
# don't block execution if these views are missing
|
||||
# Convert lists to sets for efficient difference calculation
|
||||
ret_view_names_set = set(ret[0]["view_names"])
|
||||
ret_view_names_set = (
|
||||
set(ret[0]["view_names"]) if ret[0]["view_names"] else set()
|
||||
)
|
||||
expected_views_set = set(expected_views)
|
||||
# Find missing views
|
||||
missing_views = expected_views_set - ret_view_names_set
|
||||
|
@ -1291,13 +1302,13 @@ class PrismaClient:
|
|||
verbose_proxy_logger.debug(
|
||||
f"PrismaClient: get_data - args_passed_in: {args_passed_in}"
|
||||
)
|
||||
hashed_token: Optional[str] = None
|
||||
try:
|
||||
response: Any = None
|
||||
if (token is not None and table_name is None) or (
|
||||
table_name is not None and table_name == "key"
|
||||
):
|
||||
# check if plain text or hash
|
||||
hashed_token = None
|
||||
if token is not None:
|
||||
if isinstance(token, str):
|
||||
hashed_token = token
|
||||
|
@ -1306,7 +1317,7 @@ class PrismaClient:
|
|||
verbose_proxy_logger.debug(
|
||||
f"PrismaClient: find_unique for token: {hashed_token}"
|
||||
)
|
||||
if query_type == "find_unique":
|
||||
if query_type == "find_unique" and hashed_token is not None:
|
||||
if token is None:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
|
@ -1706,7 +1717,7 @@ class PrismaClient:
|
|||
updated_data = v
|
||||
updated_data = json.dumps(updated_data)
|
||||
updated_table_row = self.db.litellm_config.upsert(
|
||||
where={"param_name": k},
|
||||
where={"param_name": k}, # type: ignore
|
||||
data={
|
||||
"create": {"param_name": k, "param_value": updated_data}, # type: ignore
|
||||
"update": {"param_value": updated_data},
|
||||
|
@ -2302,7 +2313,12 @@ def get_instance_fn(value: str, config_file_path: Optional[str] = None) -> Any:
|
|||
return instance
|
||||
except ImportError as e:
|
||||
# Re-raise the exception with a user-friendly message
|
||||
raise ImportError(f"Could not import {instance_name} from {module_name}") from e
|
||||
if instance_name and module_name:
|
||||
raise ImportError(
|
||||
f"Could not import {instance_name} from {module_name}"
|
||||
) from e
|
||||
else:
|
||||
raise e
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
|
@ -2377,12 +2393,12 @@ async def send_email(receiver_email, subject, html):
|
|||
|
||||
try:
|
||||
# Establish a secure connection with the SMTP server
|
||||
with smtplib.SMTP(smtp_host, smtp_port) as server:
|
||||
with smtplib.SMTP(smtp_host, smtp_port) as server: # type: ignore
|
||||
if os.getenv("SMTP_TLS", "True") != "False":
|
||||
server.starttls()
|
||||
|
||||
# Login to your email account
|
||||
server.login(smtp_username, smtp_password)
|
||||
server.login(smtp_username, smtp_password) # type: ignore
|
||||
|
||||
# Send the email
|
||||
server.send_message(email_message)
|
||||
|
@ -2945,7 +2961,7 @@ async def update_spend(
|
|||
if i >= n_retry_times: # If we've reached the maximum number of retries
|
||||
raise # Re-raise the last exception
|
||||
# Optionally, sleep for a bit before retrying
|
||||
await asyncio.sleep(2**i) # Exponential backoff
|
||||
await asyncio.sleep(2**i) # type: ignore
|
||||
except Exception as e:
|
||||
import traceback
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue