mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
fix(ci): stabilize CI - formatting, type errors, test polling, security CVEs, router bug, batch resolution
Fix 1: Run Black formatter on 35 files Fix 2: Fix MyPy type errors: - setup_wizard.py: add type annotation for 'selected' set variable - user_api_key_auth.py: remove redundant type annotation on jwt_claims reassignment Fix 3: Fix spend accuracy test burst 2 polling to wait for expected total spend instead of just 'any increase' from burst 2 Fix 4: Bump Next.js 16.1.6 -> 16.1.7 to fix CVE-2026-27978, CVE-2026-27979, CVE-2026-27980, CVE-2026-29057 Fix 5: Fix router _pre_call_checks model variable being overwritten inside loop, causing wrong model lookups on subsequent deployments. Use local _deployment_model variable instead. Fix 6: Add missing resolve_output_file_ids_to_unified call in batch retrieve non-terminal-to-terminal path (matching the terminal path behavior) Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
This commit is contained in:
parent
d9a6036162
commit
fde9062846
41 changed files with 493 additions and 371 deletions
|
|
@ -1465,9 +1465,15 @@ if TYPE_CHECKING:
|
|||
from .llms.petals.completion.transformation import PetalsConfig as PetalsConfig
|
||||
from .llms.ollama.chat.transformation import OllamaChatConfig as OllamaChatConfig
|
||||
from .llms.ollama.completion.transformation import OllamaConfig as OllamaConfig
|
||||
from .llms.sagemaker.completion.transformation import SagemakerConfig as SagemakerConfig
|
||||
from .llms.sagemaker.chat.transformation import SagemakerChatConfig as SagemakerChatConfig
|
||||
from .llms.sagemaker.nova.transformation import SagemakerNovaConfig as SagemakerNovaConfig
|
||||
from .llms.sagemaker.completion.transformation import (
|
||||
SagemakerConfig as SagemakerConfig,
|
||||
)
|
||||
from .llms.sagemaker.chat.transformation import (
|
||||
SagemakerChatConfig as SagemakerChatConfig,
|
||||
)
|
||||
from .llms.sagemaker.nova.transformation import (
|
||||
SagemakerNovaConfig as SagemakerNovaConfig,
|
||||
)
|
||||
from .llms.cohere.chat.transformation import CohereChatConfig as CohereChatConfig
|
||||
from .llms.anthropic.experimental_pass_through.messages.transformation import (
|
||||
AnthropicMessagesConfig as AnthropicMessagesConfig,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ if set_verbose is True:
|
|||
"`litellm.set_verbose` is deprecated. Please set `os.environ['LITELLM_LOG'] = 'DEBUG'` for debug logs."
|
||||
)
|
||||
|
||||
_ENABLE_SECRET_REDACTION = os.getenv("LITELLM_DISABLE_REDACT_SECRETS", "").lower() != "true"
|
||||
_ENABLE_SECRET_REDACTION = (
|
||||
os.getenv("LITELLM_DISABLE_REDACT_SECRETS", "").lower() != "true"
|
||||
)
|
||||
|
||||
_REDACTED = "REDACTED"
|
||||
|
||||
|
|
@ -199,7 +201,9 @@ class JsonFormatter(Formatter):
|
|||
json_record[key] = value
|
||||
|
||||
if record.exc_info:
|
||||
json_record["stacktrace"] = record.exc_text or self.formatException(record.exc_info)
|
||||
json_record["stacktrace"] = record.exc_text or self.formatException(
|
||||
record.exc_info
|
||||
)
|
||||
|
||||
return safe_dumps(json_record)
|
||||
|
||||
|
|
|
|||
|
|
@ -1189,7 +1189,9 @@ def completion_cost( # noqa: PLR0915
|
|||
and _usage["prompt_tokens_details"] != {}
|
||||
and _usage["prompt_tokens_details"]
|
||||
):
|
||||
prompt_tokens_details = _usage.get("prompt_tokens_details") or {}
|
||||
prompt_tokens_details = (
|
||||
_usage.get("prompt_tokens_details") or {}
|
||||
)
|
||||
cache_read_input_tokens = prompt_tokens_details.get(
|
||||
"cached_tokens", 0
|
||||
)
|
||||
|
|
@ -1515,7 +1517,9 @@ def completion_cost( # noqa: PLR0915
|
|||
if custom_llm_provider == "azure_ai":
|
||||
model_for_additional_costs = request_model_for_cost
|
||||
if completion_response is not None:
|
||||
hidden_params = getattr(completion_response, "_hidden_params", None) or {}
|
||||
hidden_params = (
|
||||
getattr(completion_response, "_hidden_params", None) or {}
|
||||
)
|
||||
hidden_model = hidden_params.get("model") or hidden_params.get(
|
||||
"litellm_model_name"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -59,17 +59,14 @@ class FocusDestinationFactory:
|
|||
return {k: v for k, v in resolved.items() if v is not None}
|
||||
if provider == "vantage":
|
||||
resolved = {
|
||||
"api_key": overrides.get("api_key")
|
||||
or os.getenv("VANTAGE_API_KEY"),
|
||||
"api_key": overrides.get("api_key") or os.getenv("VANTAGE_API_KEY"),
|
||||
"integration_token": overrides.get("integration_token")
|
||||
or os.getenv("VANTAGE_INTEGRATION_TOKEN"),
|
||||
"base_url": overrides.get("base_url")
|
||||
or os.getenv("VANTAGE_BASE_URL", "https://api.vantage.sh"),
|
||||
}
|
||||
if not resolved.get("api_key"):
|
||||
raise ValueError(
|
||||
"VANTAGE_API_KEY must be provided for Vantage exports"
|
||||
)
|
||||
raise ValueError("VANTAGE_API_KEY must be provided for Vantage exports")
|
||||
if not resolved.get("integration_token"):
|
||||
raise ValueError(
|
||||
"VANTAGE_INTEGRATION_TOKEN must be provided for Vantage exports"
|
||||
|
|
|
|||
|
|
@ -340,9 +340,9 @@ class LangfusePromptManagement(LangFuseLogger, PromptManagementBase, CustomLogge
|
|||
)
|
||||
status_message = str(kwargs.get("exception", "Unknown error"))
|
||||
if standard_logging_object is not None:
|
||||
status_message = standard_logging_object.get(
|
||||
"error_str", None
|
||||
) or status_message
|
||||
status_message = (
|
||||
standard_logging_object.get("error_str", None) or status_message
|
||||
)
|
||||
langfuse_logger_to_use.log_event_on_langfuse(
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@ class VantageLogger(FocusLogger):
|
|||
|
||||
verbose_logger.debug(
|
||||
"VantageLogger initialized (integration_token=%s)",
|
||||
resolved_token[:4] + "***" if resolved_token and len(resolved_token) > 4 else "***",
|
||||
resolved_token[:4] + "***"
|
||||
if resolved_token and len(resolved_token) > 4
|
||||
else "***",
|
||||
)
|
||||
|
||||
async def initialize_focus_export_job(self) -> None:
|
||||
|
|
@ -128,9 +130,7 @@ class VantageLogger(FocusLogger):
|
|||
callback_type=VantageLogger
|
||||
)
|
||||
if not vantage_loggers:
|
||||
verbose_logger.debug(
|
||||
"No Vantage logger registered; skipping scheduler"
|
||||
)
|
||||
verbose_logger.debug("No Vantage logger registered; skipping scheduler")
|
||||
return
|
||||
|
||||
vantage_logger = cast(VantageLogger, vantage_loggers[0])
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ if custom_cache_dir:
|
|||
else:
|
||||
cache_dir = filename
|
||||
|
||||
os.environ["TIKTOKEN_CACHE_DIR"] = cache_dir # use local copy of tiktoken b/c of - https://github.com/BerriAI/litellm/issues/1071
|
||||
os.environ[
|
||||
"TIKTOKEN_CACHE_DIR"
|
||||
] = cache_dir # use local copy of tiktoken b/c of - https://github.com/BerriAI/litellm/issues/1071
|
||||
|
||||
import tiktoken
|
||||
import time
|
||||
|
|
@ -48,4 +50,3 @@ for attempt in range(_max_retries):
|
|||
# Exponential backoff with jitter to reduce collision probability
|
||||
delay = _retry_delay * (2**attempt) + random.uniform(0, 0.1)
|
||||
time.sleep(delay)
|
||||
|
||||
|
|
|
|||
|
|
@ -352,9 +352,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
)
|
||||
self.function_id = function_id
|
||||
self.streaming_chunks: List[Any] = [] # for generating complete stream response
|
||||
self.sync_streaming_chunks: List[Any] = (
|
||||
[]
|
||||
) # for generating complete stream response
|
||||
self.sync_streaming_chunks: List[
|
||||
Any
|
||||
] = [] # for generating complete stream response
|
||||
self.log_raw_request_response = log_raw_request_response
|
||||
|
||||
# Initialize dynamic callbacks
|
||||
|
|
@ -782,9 +782,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
prompt_spec=prompt_spec,
|
||||
dynamic_callback_params=dynamic_callback_params,
|
||||
):
|
||||
self.model_call_details["prompt_integration"] = (
|
||||
logger.__class__.__name__
|
||||
)
|
||||
self.model_call_details[
|
||||
"prompt_integration"
|
||||
] = logger.__class__.__name__
|
||||
return logger
|
||||
except Exception:
|
||||
# If check fails, continue to next logger
|
||||
|
|
@ -852,9 +852,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
if anthropic_cache_control_logger := AnthropicCacheControlHook.get_custom_logger_for_anthropic_cache_control_hook(
|
||||
non_default_params
|
||||
):
|
||||
self.model_call_details["prompt_integration"] = (
|
||||
anthropic_cache_control_logger.__class__.__name__
|
||||
)
|
||||
self.model_call_details[
|
||||
"prompt_integration"
|
||||
] = anthropic_cache_control_logger.__class__.__name__
|
||||
return anthropic_cache_control_logger
|
||||
|
||||
#########################################################
|
||||
|
|
@ -866,9 +866,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
internal_usage_cache=None,
|
||||
llm_router=None,
|
||||
)
|
||||
self.model_call_details["prompt_integration"] = (
|
||||
vector_store_custom_logger.__class__.__name__
|
||||
)
|
||||
self.model_call_details[
|
||||
"prompt_integration"
|
||||
] = vector_store_custom_logger.__class__.__name__
|
||||
# Add to global callbacks so post-call hooks are invoked
|
||||
if (
|
||||
vector_store_custom_logger
|
||||
|
|
@ -928,9 +928,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
model
|
||||
): # if model name was changes pre-call, overwrite the initial model call name with the new one
|
||||
self.model_call_details["model"] = model
|
||||
self.model_call_details["litellm_params"]["api_base"] = (
|
||||
self._get_masked_api_base(additional_args.get("api_base", ""))
|
||||
)
|
||||
self.model_call_details["litellm_params"][
|
||||
"api_base"
|
||||
] = self._get_masked_api_base(additional_args.get("api_base", ""))
|
||||
|
||||
def pre_call(self, input, api_key, model=None, additional_args={}): # noqa: PLR0915
|
||||
# Log the exact input to the LLM API
|
||||
|
|
@ -959,10 +959,10 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
try:
|
||||
# [Non-blocking Extra Debug Information in metadata]
|
||||
if turn_off_message_logging is True:
|
||||
_metadata["raw_request"] = (
|
||||
"redacted by litellm. \
|
||||
_metadata[
|
||||
"raw_request"
|
||||
] = "redacted by litellm. \
|
||||
'litellm.turn_off_message_logging=True'"
|
||||
)
|
||||
else:
|
||||
curl_command = self._get_request_curl_command(
|
||||
api_base=additional_args.get("api_base", ""),
|
||||
|
|
@ -973,34 +973,34 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
|
||||
_metadata["raw_request"] = str(curl_command)
|
||||
# split up, so it's easier to parse in the UI
|
||||
self.model_call_details["raw_request_typed_dict"] = (
|
||||
RawRequestTypedDict(
|
||||
raw_request_api_base=str(
|
||||
additional_args.get("api_base") or ""
|
||||
),
|
||||
raw_request_body=self._get_raw_request_body(
|
||||
additional_args.get("complete_input_dict", {})
|
||||
),
|
||||
# NOTE: setting ignore_sensitive_headers to True will cause
|
||||
# the Authorization header to be leaked when calls to the health
|
||||
# endpoint are made and fail.
|
||||
raw_request_headers=self._get_masked_headers(
|
||||
additional_args.get("headers", {}) or {},
|
||||
),
|
||||
error=None,
|
||||
)
|
||||
self.model_call_details[
|
||||
"raw_request_typed_dict"
|
||||
] = RawRequestTypedDict(
|
||||
raw_request_api_base=str(
|
||||
additional_args.get("api_base") or ""
|
||||
),
|
||||
raw_request_body=self._get_raw_request_body(
|
||||
additional_args.get("complete_input_dict", {})
|
||||
),
|
||||
# NOTE: setting ignore_sensitive_headers to True will cause
|
||||
# the Authorization header to be leaked when calls to the health
|
||||
# endpoint are made and fail.
|
||||
raw_request_headers=self._get_masked_headers(
|
||||
additional_args.get("headers", {}) or {},
|
||||
),
|
||||
error=None,
|
||||
)
|
||||
except Exception as e:
|
||||
self.model_call_details["raw_request_typed_dict"] = (
|
||||
RawRequestTypedDict(
|
||||
error=str(e),
|
||||
)
|
||||
self.model_call_details[
|
||||
"raw_request_typed_dict"
|
||||
] = RawRequestTypedDict(
|
||||
error=str(e),
|
||||
)
|
||||
_metadata["raw_request"] = (
|
||||
"Unable to Log \
|
||||
_metadata[
|
||||
"raw_request"
|
||||
] = "Unable to Log \
|
||||
raw request: {}".format(
|
||||
str(e)
|
||||
)
|
||||
str(e)
|
||||
)
|
||||
if getattr(self, "logger_fn", None) and callable(self.logger_fn):
|
||||
try:
|
||||
|
|
@ -1301,13 +1301,13 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
for callback in callbacks:
|
||||
try:
|
||||
if isinstance(callback, CustomLogger):
|
||||
response: Optional[MCPPostCallResponseObject] = (
|
||||
await callback.async_post_mcp_tool_call_hook(
|
||||
kwargs=kwargs,
|
||||
response_obj=post_mcp_tool_call_response_obj,
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
)
|
||||
response: Optional[
|
||||
MCPPostCallResponseObject
|
||||
] = await callback.async_post_mcp_tool_call_hook(
|
||||
kwargs=kwargs,
|
||||
response_obj=post_mcp_tool_call_response_obj,
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
)
|
||||
######################################################################
|
||||
# if any of the callbacks modify the response, use the modified response
|
||||
|
|
@ -1502,9 +1502,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
verbose_logger.debug(
|
||||
f"response_cost_failure_debug_information: {debug_info}"
|
||||
)
|
||||
self.model_call_details["response_cost_failure_debug_information"] = (
|
||||
debug_info
|
||||
)
|
||||
self.model_call_details[
|
||||
"response_cost_failure_debug_information"
|
||||
] = debug_info
|
||||
return None
|
||||
|
||||
try:
|
||||
|
|
@ -1530,9 +1530,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
verbose_logger.debug(
|
||||
f"response_cost_failure_debug_information: {debug_info}"
|
||||
)
|
||||
self.model_call_details["response_cost_failure_debug_information"] = (
|
||||
debug_info
|
||||
)
|
||||
self.model_call_details[
|
||||
"response_cost_failure_debug_information"
|
||||
] = debug_info
|
||||
|
||||
return None
|
||||
|
||||
|
|
@ -1688,9 +1688,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
result=logging_result
|
||||
)
|
||||
|
||||
self.model_call_details["standard_logging_object"] = (
|
||||
self._build_standard_logging_payload(logging_result, start_time, end_time)
|
||||
)
|
||||
self.model_call_details[
|
||||
"standard_logging_object"
|
||||
] = self._build_standard_logging_payload(logging_result, start_time, end_time)
|
||||
|
||||
if (
|
||||
standard_logging_payload := self.model_call_details.get(
|
||||
|
|
@ -1768,9 +1768,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
end_time = datetime.datetime.now()
|
||||
if self.completion_start_time is None:
|
||||
self.completion_start_time = end_time
|
||||
self.model_call_details["completion_start_time"] = (
|
||||
self.completion_start_time
|
||||
)
|
||||
self.model_call_details[
|
||||
"completion_start_time"
|
||||
] = self.completion_start_time
|
||||
|
||||
self.model_call_details["log_event_type"] = "successful_api_call"
|
||||
self.model_call_details["end_time"] = end_time
|
||||
|
|
@ -1807,10 +1807,10 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
end_time=end_time,
|
||||
)
|
||||
elif isinstance(result, dict) or isinstance(result, list):
|
||||
self.model_call_details["standard_logging_object"] = (
|
||||
self._build_standard_logging_payload(
|
||||
result, start_time, end_time
|
||||
)
|
||||
self.model_call_details[
|
||||
"standard_logging_object"
|
||||
] = self._build_standard_logging_payload(
|
||||
result, start_time, end_time
|
||||
)
|
||||
if (
|
||||
standard_logging_payload := self.model_call_details.get(
|
||||
|
|
@ -1819,9 +1819,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
) is not None:
|
||||
emit_standard_logging_payload(standard_logging_payload)
|
||||
elif standard_logging_object is not None:
|
||||
self.model_call_details["standard_logging_object"] = (
|
||||
standard_logging_object
|
||||
)
|
||||
self.model_call_details[
|
||||
"standard_logging_object"
|
||||
] = standard_logging_object
|
||||
else:
|
||||
self.model_call_details["response_cost"] = None
|
||||
|
||||
|
|
@ -1979,17 +1979,17 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
verbose_logger.debug(
|
||||
"Logging Details LiteLLM-Success Call streaming complete"
|
||||
)
|
||||
self.model_call_details["complete_streaming_response"] = (
|
||||
complete_streaming_response
|
||||
)
|
||||
self.model_call_details["response_cost"] = (
|
||||
self._response_cost_calculator(result=complete_streaming_response)
|
||||
)
|
||||
self.model_call_details[
|
||||
"complete_streaming_response"
|
||||
] = complete_streaming_response
|
||||
self.model_call_details[
|
||||
"response_cost"
|
||||
] = self._response_cost_calculator(result=complete_streaming_response)
|
||||
## STANDARDIZED LOGGING PAYLOAD
|
||||
self.model_call_details["standard_logging_object"] = (
|
||||
self._build_standard_logging_payload(
|
||||
complete_streaming_response, start_time, end_time
|
||||
)
|
||||
self.model_call_details[
|
||||
"standard_logging_object"
|
||||
] = self._build_standard_logging_payload(
|
||||
complete_streaming_response, start_time, end_time
|
||||
)
|
||||
if (
|
||||
standard_logging_payload := self.model_call_details.get(
|
||||
|
|
@ -2323,10 +2323,10 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
)
|
||||
else:
|
||||
if self.stream and complete_streaming_response:
|
||||
self.model_call_details["complete_response"] = (
|
||||
self.model_call_details.get(
|
||||
"complete_streaming_response", {}
|
||||
)
|
||||
self.model_call_details[
|
||||
"complete_response"
|
||||
] = self.model_call_details.get(
|
||||
"complete_streaming_response", {}
|
||||
)
|
||||
result = self.model_call_details["complete_response"]
|
||||
openMeterLogger.log_success_event(
|
||||
|
|
@ -2350,10 +2350,10 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
)
|
||||
else:
|
||||
if self.stream and complete_streaming_response:
|
||||
self.model_call_details["complete_response"] = (
|
||||
self.model_call_details.get(
|
||||
"complete_streaming_response", {}
|
||||
)
|
||||
self.model_call_details[
|
||||
"complete_response"
|
||||
] = self.model_call_details.get(
|
||||
"complete_streaming_response", {}
|
||||
)
|
||||
result = self.model_call_details["complete_response"]
|
||||
|
||||
|
|
@ -2492,9 +2492,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
if complete_streaming_response is not None:
|
||||
print_verbose("Async success callbacks: Got a complete streaming response")
|
||||
|
||||
self.model_call_details["async_complete_streaming_response"] = (
|
||||
complete_streaming_response
|
||||
)
|
||||
self.model_call_details[
|
||||
"async_complete_streaming_response"
|
||||
] = complete_streaming_response
|
||||
|
||||
try:
|
||||
if self.model_call_details.get("cache_hit", False) is True:
|
||||
|
|
@ -2505,10 +2505,10 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
model_call_details=self.model_call_details
|
||||
)
|
||||
# base_model defaults to None if not set on model_info
|
||||
self.model_call_details["response_cost"] = (
|
||||
self._response_cost_calculator(
|
||||
result=complete_streaming_response
|
||||
)
|
||||
self.model_call_details[
|
||||
"response_cost"
|
||||
] = self._response_cost_calculator(
|
||||
result=complete_streaming_response
|
||||
)
|
||||
|
||||
verbose_logger.debug(
|
||||
|
|
@ -2521,10 +2521,10 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
self.model_call_details["response_cost"] = None
|
||||
|
||||
## STANDARDIZED LOGGING PAYLOAD
|
||||
self.model_call_details["standard_logging_object"] = (
|
||||
self._build_standard_logging_payload(
|
||||
complete_streaming_response, start_time, end_time
|
||||
)
|
||||
self.model_call_details[
|
||||
"standard_logging_object"
|
||||
] = self._build_standard_logging_payload(
|
||||
complete_streaming_response, start_time, end_time
|
||||
)
|
||||
|
||||
# print standard logging payload
|
||||
|
|
@ -2551,9 +2551,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
# _success_handler_helper_fn
|
||||
if self.model_call_details.get("standard_logging_object") is None:
|
||||
## STANDARDIZED LOGGING PAYLOAD
|
||||
self.model_call_details["standard_logging_object"] = (
|
||||
self._build_standard_logging_payload(result, start_time, end_time)
|
||||
)
|
||||
self.model_call_details[
|
||||
"standard_logging_object"
|
||||
] = self._build_standard_logging_payload(result, start_time, end_time)
|
||||
|
||||
# print standard logging payload
|
||||
if (
|
||||
|
|
@ -2796,18 +2796,18 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
|
||||
## STANDARDIZED LOGGING PAYLOAD
|
||||
|
||||
self.model_call_details["standard_logging_object"] = (
|
||||
get_standard_logging_object_payload(
|
||||
kwargs=self.model_call_details,
|
||||
init_response_obj={},
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
logging_obj=self,
|
||||
status="failure",
|
||||
error_str=str(exception),
|
||||
original_exception=exception,
|
||||
standard_built_in_tools_params=self.standard_built_in_tools_params,
|
||||
)
|
||||
self.model_call_details[
|
||||
"standard_logging_object"
|
||||
] = get_standard_logging_object_payload(
|
||||
kwargs=self.model_call_details,
|
||||
init_response_obj={},
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
logging_obj=self,
|
||||
status="failure",
|
||||
error_str=str(exception),
|
||||
original_exception=exception,
|
||||
standard_built_in_tools_params=self.standard_built_in_tools_params,
|
||||
)
|
||||
return start_time, end_time
|
||||
|
||||
|
|
@ -3771,9 +3771,9 @@ def _init_custom_logger_compatible_class( # noqa: PLR0915
|
|||
service_name=arize_config.project_name,
|
||||
)
|
||||
|
||||
os.environ["OTEL_EXPORTER_OTLP_TRACES_HEADERS"] = (
|
||||
f"space_id={arize_config.space_key or arize_config.space_id},api_key={arize_config.api_key}"
|
||||
)
|
||||
os.environ[
|
||||
"OTEL_EXPORTER_OTLP_TRACES_HEADERS"
|
||||
] = f"space_id={arize_config.space_key or arize_config.space_id},api_key={arize_config.api_key}"
|
||||
for callback in _in_memory_loggers:
|
||||
if (
|
||||
isinstance(callback, ArizeLogger)
|
||||
|
|
@ -3799,13 +3799,13 @@ def _init_custom_logger_compatible_class( # noqa: PLR0915
|
|||
existing_attrs = os.environ.get("OTEL_RESOURCE_ATTRIBUTES", "")
|
||||
# Add openinference.project.name attribute
|
||||
if existing_attrs:
|
||||
os.environ["OTEL_RESOURCE_ATTRIBUTES"] = (
|
||||
f"{existing_attrs},openinference.project.name={arize_phoenix_config.project_name}"
|
||||
)
|
||||
os.environ[
|
||||
"OTEL_RESOURCE_ATTRIBUTES"
|
||||
] = f"{existing_attrs},openinference.project.name={arize_phoenix_config.project_name}"
|
||||
else:
|
||||
os.environ["OTEL_RESOURCE_ATTRIBUTES"] = (
|
||||
f"openinference.project.name={arize_phoenix_config.project_name}"
|
||||
)
|
||||
os.environ[
|
||||
"OTEL_RESOURCE_ATTRIBUTES"
|
||||
] = f"openinference.project.name={arize_phoenix_config.project_name}"
|
||||
|
||||
# Set Phoenix project name from environment variable
|
||||
phoenix_project_name = os.environ.get("PHOENIX_PROJECT_NAME", None)
|
||||
|
|
@ -3813,19 +3813,19 @@ def _init_custom_logger_compatible_class( # noqa: PLR0915
|
|||
existing_attrs = os.environ.get("OTEL_RESOURCE_ATTRIBUTES", "")
|
||||
# Add openinference.project.name attribute
|
||||
if existing_attrs:
|
||||
os.environ["OTEL_RESOURCE_ATTRIBUTES"] = (
|
||||
f"{existing_attrs},openinference.project.name={phoenix_project_name}"
|
||||
)
|
||||
os.environ[
|
||||
"OTEL_RESOURCE_ATTRIBUTES"
|
||||
] = f"{existing_attrs},openinference.project.name={phoenix_project_name}"
|
||||
else:
|
||||
os.environ["OTEL_RESOURCE_ATTRIBUTES"] = (
|
||||
f"openinference.project.name={phoenix_project_name}"
|
||||
)
|
||||
os.environ[
|
||||
"OTEL_RESOURCE_ATTRIBUTES"
|
||||
] = f"openinference.project.name={phoenix_project_name}"
|
||||
|
||||
# auth can be disabled on local deployments of arize phoenix
|
||||
if arize_phoenix_config.otlp_auth_headers is not None:
|
||||
os.environ["OTEL_EXPORTER_OTLP_TRACES_HEADERS"] = (
|
||||
arize_phoenix_config.otlp_auth_headers
|
||||
)
|
||||
os.environ[
|
||||
"OTEL_EXPORTER_OTLP_TRACES_HEADERS"
|
||||
] = arize_phoenix_config.otlp_auth_headers
|
||||
|
||||
for callback in _in_memory_loggers:
|
||||
if (
|
||||
|
|
@ -3904,7 +3904,9 @@ def _init_custom_logger_compatible_class( # noqa: PLR0915
|
|||
from litellm.integrations.focus.focus_logger import FocusLogger
|
||||
|
||||
for callback in _in_memory_loggers:
|
||||
if type(callback) is FocusLogger: # exact match; exclude subclasses like VantageLogger
|
||||
if (
|
||||
type(callback) is FocusLogger
|
||||
): # exact match; exclude subclasses like VantageLogger
|
||||
return callback # type: ignore
|
||||
focus_logger = FocusLogger()
|
||||
_in_memory_loggers.append(focus_logger)
|
||||
|
|
@ -4010,9 +4012,9 @@ def _init_custom_logger_compatible_class( # noqa: PLR0915
|
|||
exporter="otlp_http",
|
||||
endpoint="https://langtrace.ai/api/trace",
|
||||
)
|
||||
os.environ["OTEL_EXPORTER_OTLP_TRACES_HEADERS"] = (
|
||||
f"api_key={os.getenv('LANGTRACE_API_KEY')}"
|
||||
)
|
||||
os.environ[
|
||||
"OTEL_EXPORTER_OTLP_TRACES_HEADERS"
|
||||
] = f"api_key={os.getenv('LANGTRACE_API_KEY')}"
|
||||
for callback in _in_memory_loggers:
|
||||
if (
|
||||
isinstance(callback, OpenTelemetry)
|
||||
|
|
@ -4286,7 +4288,9 @@ def get_custom_logger_compatible_class( # noqa: PLR0915
|
|||
from litellm.integrations.focus.focus_logger import FocusLogger
|
||||
|
||||
for callback in _in_memory_loggers:
|
||||
if type(callback) is FocusLogger: # exact match; exclude subclasses like VantageLogger
|
||||
if (
|
||||
type(callback) is FocusLogger
|
||||
): # exact match; exclude subclasses like VantageLogger
|
||||
return callback
|
||||
elif logging_integration == "vantage":
|
||||
from litellm.integrations.vantage.vantage_logger import VantageLogger
|
||||
|
|
@ -4934,10 +4938,10 @@ class StandardLoggingPayloadSetup:
|
|||
for key in StandardLoggingHiddenParams.__annotations__.keys():
|
||||
if key in hidden_params:
|
||||
if key == "additional_headers":
|
||||
clean_hidden_params["additional_headers"] = (
|
||||
StandardLoggingPayloadSetup.get_additional_headers(
|
||||
hidden_params[key]
|
||||
)
|
||||
clean_hidden_params[
|
||||
"additional_headers"
|
||||
] = StandardLoggingPayloadSetup.get_additional_headers(
|
||||
hidden_params[key]
|
||||
)
|
||||
else:
|
||||
clean_hidden_params[key] = hidden_params[key] # type: ignore
|
||||
|
|
@ -5576,9 +5580,9 @@ def scrub_sensitive_keys_in_metadata(litellm_params: Optional[dict]):
|
|||
):
|
||||
for k, v in metadata["user_api_key_metadata"].items():
|
||||
if k == "logging": # prevent logging user logging keys
|
||||
cleaned_user_api_key_metadata[k] = (
|
||||
"scrubbed_by_litellm_for_sensitive_keys"
|
||||
)
|
||||
cleaned_user_api_key_metadata[
|
||||
k
|
||||
] = "scrubbed_by_litellm_for_sensitive_keys"
|
||||
else:
|
||||
cleaned_user_api_key_metadata[k] = v
|
||||
|
||||
|
|
|
|||
|
|
@ -780,7 +780,7 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
# Keep Anthropic-native tools in their original format
|
||||
new_tools.append(tool) # type: ignore[arg-type]
|
||||
continue
|
||||
|
||||
|
||||
original_name = tool["name"]
|
||||
truncated_name = truncate_tool_name(original_name)
|
||||
|
||||
|
|
|
|||
|
|
@ -336,9 +336,7 @@ class BaseVideoConfig(ABC):
|
|||
Returns:
|
||||
Tuple[str, Dict]: (url, data) for the POST request
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"video edit is not supported for this provider"
|
||||
)
|
||||
raise NotImplementedError("video edit is not supported for this provider")
|
||||
|
||||
def transform_video_edit_response(
|
||||
self,
|
||||
|
|
@ -346,9 +344,7 @@ class BaseVideoConfig(ABC):
|
|||
logging_obj: LiteLLMLoggingObj,
|
||||
custom_llm_provider: Optional[str] = None,
|
||||
) -> VideoObject:
|
||||
raise NotImplementedError(
|
||||
"video edit is not supported for this provider"
|
||||
)
|
||||
raise NotImplementedError("video edit is not supported for this provider")
|
||||
|
||||
def transform_video_extension_request(
|
||||
self,
|
||||
|
|
@ -366,9 +362,7 @@ class BaseVideoConfig(ABC):
|
|||
Returns:
|
||||
Tuple[str, Dict]: (url, data) for the POST request
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"video extension is not supported for this provider"
|
||||
)
|
||||
raise NotImplementedError("video extension is not supported for this provider")
|
||||
|
||||
def transform_video_extension_response(
|
||||
self,
|
||||
|
|
@ -376,9 +370,7 @@ class BaseVideoConfig(ABC):
|
|||
logging_obj: LiteLLMLoggingObj,
|
||||
custom_llm_provider: Optional[str] = None,
|
||||
) -> VideoObject:
|
||||
raise NotImplementedError(
|
||||
"video extension is not supported for this provider"
|
||||
)
|
||||
raise NotImplementedError("video extension is not supported for this provider")
|
||||
|
||||
def get_error_class(
|
||||
self, error_message: str, status_code: int, headers: Union[dict, httpx.Headers]
|
||||
|
|
|
|||
|
|
@ -6162,7 +6162,10 @@ class BaseLLMHTTPHandler:
|
|||
litellm_params=dict(litellm_params),
|
||||
)
|
||||
|
||||
url, files_list = video_provider_config.transform_video_create_character_request(
|
||||
(
|
||||
url,
|
||||
files_list,
|
||||
) = video_provider_config.transform_video_create_character_request(
|
||||
name=name,
|
||||
video=video,
|
||||
api_base=api_base,
|
||||
|
|
@ -6230,7 +6233,10 @@ class BaseLLMHTTPHandler:
|
|||
litellm_params=dict(litellm_params),
|
||||
)
|
||||
|
||||
url, files_list = video_provider_config.transform_video_create_character_request(
|
||||
(
|
||||
url,
|
||||
files_list,
|
||||
) = video_provider_config.transform_video_create_character_request(
|
||||
name=name,
|
||||
video=video,
|
||||
api_base=api_base,
|
||||
|
|
@ -6324,11 +6330,7 @@ class BaseLLMHTTPHandler:
|
|||
)
|
||||
|
||||
try:
|
||||
response = sync_httpx_client.get(
|
||||
url=url,
|
||||
headers=headers,
|
||||
params=params
|
||||
)
|
||||
response = sync_httpx_client.get(url=url, headers=headers, params=params)
|
||||
response.raise_for_status()
|
||||
return video_provider_config.transform_video_get_character_response(
|
||||
raw_response=response,
|
||||
|
|
@ -6386,9 +6388,7 @@ class BaseLLMHTTPHandler:
|
|||
|
||||
try:
|
||||
response = await async_httpx_client.get(
|
||||
url=url,
|
||||
headers=headers,
|
||||
params=params
|
||||
url=url, headers=headers, params=params
|
||||
)
|
||||
response.raise_for_status()
|
||||
return video_provider_config.transform_video_get_character_response(
|
||||
|
|
|
|||
|
|
@ -525,28 +525,47 @@ class GeminiVideoConfig(BaseVideoConfig):
|
|||
"""Video delete is not supported."""
|
||||
raise NotImplementedError("Video delete is not supported by Google Veo.")
|
||||
|
||||
def transform_video_create_character_request(self, name, video, api_base, litellm_params, headers):
|
||||
def transform_video_create_character_request(
|
||||
self, name, video, api_base, litellm_params, headers
|
||||
):
|
||||
raise NotImplementedError("video create character is not supported for Gemini")
|
||||
|
||||
def transform_video_create_character_response(self, raw_response, logging_obj):
|
||||
raise NotImplementedError("video create character is not supported for Gemini")
|
||||
|
||||
def transform_video_get_character_request(self, character_id, api_base, litellm_params, headers):
|
||||
def transform_video_get_character_request(
|
||||
self, character_id, api_base, litellm_params, headers
|
||||
):
|
||||
raise NotImplementedError("video get character is not supported for Gemini")
|
||||
|
||||
def transform_video_get_character_response(self, raw_response, logging_obj):
|
||||
raise NotImplementedError("video get character is not supported for Gemini")
|
||||
|
||||
def transform_video_edit_request(self, prompt, video_id, api_base, litellm_params, headers, extra_body=None):
|
||||
def transform_video_edit_request(
|
||||
self, prompt, video_id, api_base, litellm_params, headers, extra_body=None
|
||||
):
|
||||
raise NotImplementedError("video edit is not supported for Gemini")
|
||||
|
||||
def transform_video_edit_response(self, raw_response, logging_obj, custom_llm_provider=None):
|
||||
def transform_video_edit_response(
|
||||
self, raw_response, logging_obj, custom_llm_provider=None
|
||||
):
|
||||
raise NotImplementedError("video edit is not supported for Gemini")
|
||||
|
||||
def transform_video_extension_request(self, prompt, video_id, seconds, api_base, litellm_params, headers, extra_body=None):
|
||||
def transform_video_extension_request(
|
||||
self,
|
||||
prompt,
|
||||
video_id,
|
||||
seconds,
|
||||
api_base,
|
||||
litellm_params,
|
||||
headers,
|
||||
extra_body=None,
|
||||
):
|
||||
raise NotImplementedError("video extension is not supported for Gemini")
|
||||
|
||||
def transform_video_extension_response(self, raw_response, logging_obj, custom_llm_provider=None):
|
||||
def transform_video_extension_response(
|
||||
self, raw_response, logging_obj, custom_llm_provider=None
|
||||
):
|
||||
raise NotImplementedError("video extension is not supported for Gemini")
|
||||
|
||||
def get_error_class(
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
@overload
|
||||
def _transform_messages(
|
||||
self, messages: List[AllMessageValues], model: str, is_async: Literal[True]
|
||||
) -> Coroutine[Any, Any, List[AllMessageValues]]: ...
|
||||
) -> Coroutine[Any, Any, List[AllMessageValues]]:
|
||||
...
|
||||
|
||||
@overload
|
||||
def _transform_messages(
|
||||
|
|
@ -27,7 +28,8 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
messages: List[AllMessageValues],
|
||||
model: str,
|
||||
is_async: Literal[False] = False,
|
||||
) -> List[AllMessageValues]: ...
|
||||
) -> List[AllMessageValues]:
|
||||
...
|
||||
|
||||
def _transform_messages(
|
||||
self, messages: List[AllMessageValues], model: str, is_async: bool = False
|
||||
|
|
@ -53,9 +55,13 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
messages = handle_messages_with_content_list_to_str_conversion(messages)
|
||||
|
||||
if is_async:
|
||||
return super()._transform_messages(messages=messages, model=model, is_async=True)
|
||||
return super()._transform_messages(
|
||||
messages=messages, model=model, is_async=True
|
||||
)
|
||||
else:
|
||||
return super()._transform_messages(messages=messages, model=model, is_async=False)
|
||||
return super()._transform_messages(
|
||||
messages=messages, model=model, is_async=False
|
||||
)
|
||||
|
||||
def _get_openai_compatible_provider_info(
|
||||
self, api_base: Optional[str], api_key: Optional[str]
|
||||
|
|
@ -141,7 +147,9 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
optional_params["temperature"] = 0.3
|
||||
return optional_params
|
||||
|
||||
def fill_reasoning_content(self, messages: List[AllMessageValues]) -> List[AllMessageValues]:
|
||||
def fill_reasoning_content(
|
||||
self, messages: List[AllMessageValues]
|
||||
) -> List[AllMessageValues]:
|
||||
"""
|
||||
Moonshot reasoning models require `reasoning_content` on every assistant
|
||||
message that contains tool_calls (multi-turn tool-calling flows).
|
||||
|
|
|
|||
|
|
@ -592,28 +592,51 @@ class RunwayMLVideoConfig(BaseVideoConfig):
|
|||
|
||||
return video_obj
|
||||
|
||||
def transform_video_create_character_request(self, name, video, api_base, litellm_params, headers):
|
||||
raise NotImplementedError("video create character is not supported for RunwayML")
|
||||
def transform_video_create_character_request(
|
||||
self, name, video, api_base, litellm_params, headers
|
||||
):
|
||||
raise NotImplementedError(
|
||||
"video create character is not supported for RunwayML"
|
||||
)
|
||||
|
||||
def transform_video_create_character_response(self, raw_response, logging_obj):
|
||||
raise NotImplementedError("video create character is not supported for RunwayML")
|
||||
raise NotImplementedError(
|
||||
"video create character is not supported for RunwayML"
|
||||
)
|
||||
|
||||
def transform_video_get_character_request(self, character_id, api_base, litellm_params, headers):
|
||||
def transform_video_get_character_request(
|
||||
self, character_id, api_base, litellm_params, headers
|
||||
):
|
||||
raise NotImplementedError("video get character is not supported for RunwayML")
|
||||
|
||||
def transform_video_get_character_response(self, raw_response, logging_obj):
|
||||
raise NotImplementedError("video get character is not supported for RunwayML")
|
||||
|
||||
def transform_video_edit_request(self, prompt, video_id, api_base, litellm_params, headers, extra_body=None):
|
||||
def transform_video_edit_request(
|
||||
self, prompt, video_id, api_base, litellm_params, headers, extra_body=None
|
||||
):
|
||||
raise NotImplementedError("video edit is not supported for RunwayML")
|
||||
|
||||
def transform_video_edit_response(self, raw_response, logging_obj, custom_llm_provider=None):
|
||||
def transform_video_edit_response(
|
||||
self, raw_response, logging_obj, custom_llm_provider=None
|
||||
):
|
||||
raise NotImplementedError("video edit is not supported for RunwayML")
|
||||
|
||||
def transform_video_extension_request(self, prompt, video_id, seconds, api_base, litellm_params, headers, extra_body=None):
|
||||
def transform_video_extension_request(
|
||||
self,
|
||||
prompt,
|
||||
video_id,
|
||||
seconds,
|
||||
api_base,
|
||||
litellm_params,
|
||||
headers,
|
||||
extra_body=None,
|
||||
):
|
||||
raise NotImplementedError("video extension is not supported for RunwayML")
|
||||
|
||||
def transform_video_extension_response(self, raw_response, logging_obj, custom_llm_provider=None):
|
||||
def transform_video_extension_response(
|
||||
self, raw_response, logging_obj, custom_llm_provider=None
|
||||
):
|
||||
raise NotImplementedError("video extension is not supported for RunwayML")
|
||||
|
||||
def get_error_class(
|
||||
|
|
|
|||
|
|
@ -184,9 +184,7 @@ class SagemakerChatConfig(OpenAIGPTConfig, BaseAWSLLM):
|
|||
llm_provider = LlmProviders(custom_llm_provider)
|
||||
except ValueError:
|
||||
llm_provider = LlmProviders.SAGEMAKER_CHAT
|
||||
client = get_async_httpx_client(
|
||||
llm_provider=llm_provider, params={}
|
||||
)
|
||||
client = get_async_httpx_client(llm_provider=llm_provider, params={})
|
||||
|
||||
try:
|
||||
response = await client.post(
|
||||
|
|
|
|||
|
|
@ -142,8 +142,8 @@ class VertexAIBatchTransformation:
|
|||
Gets the output file id from the Vertex AI Batch response
|
||||
"""
|
||||
|
||||
output_file_id: str = (
|
||||
response.get("outputInfo", OutputInfo()).get("gcsOutputDirectory", "")
|
||||
output_file_id: str = response.get("outputInfo", OutputInfo()).get(
|
||||
"gcsOutputDirectory", ""
|
||||
)
|
||||
if output_file_id:
|
||||
output_file_id = output_file_id.rstrip("/") + "/predictions.jsonl"
|
||||
|
|
|
|||
|
|
@ -624,28 +624,51 @@ class VertexAIVideoConfig(BaseVideoConfig, VertexBase):
|
|||
"""Video delete is not supported."""
|
||||
raise NotImplementedError("Video delete is not supported by Vertex AI Veo.")
|
||||
|
||||
def transform_video_create_character_request(self, name, video, api_base, litellm_params, headers):
|
||||
raise NotImplementedError("video create character is not supported for Vertex AI")
|
||||
def transform_video_create_character_request(
|
||||
self, name, video, api_base, litellm_params, headers
|
||||
):
|
||||
raise NotImplementedError(
|
||||
"video create character is not supported for Vertex AI"
|
||||
)
|
||||
|
||||
def transform_video_create_character_response(self, raw_response, logging_obj):
|
||||
raise NotImplementedError("video create character is not supported for Vertex AI")
|
||||
raise NotImplementedError(
|
||||
"video create character is not supported for Vertex AI"
|
||||
)
|
||||
|
||||
def transform_video_get_character_request(self, character_id, api_base, litellm_params, headers):
|
||||
def transform_video_get_character_request(
|
||||
self, character_id, api_base, litellm_params, headers
|
||||
):
|
||||
raise NotImplementedError("video get character is not supported for Vertex AI")
|
||||
|
||||
def transform_video_get_character_response(self, raw_response, logging_obj):
|
||||
raise NotImplementedError("video get character is not supported for Vertex AI")
|
||||
|
||||
def transform_video_edit_request(self, prompt, video_id, api_base, litellm_params, headers, extra_body=None):
|
||||
def transform_video_edit_request(
|
||||
self, prompt, video_id, api_base, litellm_params, headers, extra_body=None
|
||||
):
|
||||
raise NotImplementedError("video edit is not supported for Vertex AI")
|
||||
|
||||
def transform_video_edit_response(self, raw_response, logging_obj, custom_llm_provider=None):
|
||||
def transform_video_edit_response(
|
||||
self, raw_response, logging_obj, custom_llm_provider=None
|
||||
):
|
||||
raise NotImplementedError("video edit is not supported for Vertex AI")
|
||||
|
||||
def transform_video_extension_request(self, prompt, video_id, seconds, api_base, litellm_params, headers, extra_body=None):
|
||||
def transform_video_extension_request(
|
||||
self,
|
||||
prompt,
|
||||
video_id,
|
||||
seconds,
|
||||
api_base,
|
||||
litellm_params,
|
||||
headers,
|
||||
extra_body=None,
|
||||
):
|
||||
raise NotImplementedError("video extension is not supported for Vertex AI")
|
||||
|
||||
def transform_video_extension_response(self, raw_response, logging_obj, custom_llm_provider=None):
|
||||
def transform_video_extension_response(
|
||||
self, raw_response, logging_obj, custom_llm_provider=None
|
||||
):
|
||||
raise NotImplementedError("video extension is not supported for Vertex AI")
|
||||
|
||||
def get_error_class(
|
||||
|
|
|
|||
|
|
@ -7533,9 +7533,7 @@ def stream_chunk_builder( # noqa: PLR0915
|
|||
# the final chunk.
|
||||
all_annotations: list = []
|
||||
for ac in annotation_chunks:
|
||||
all_annotations.extend(
|
||||
ac["choices"][0]["delta"]["annotations"]
|
||||
)
|
||||
all_annotations.extend(ac["choices"][0]["delta"]["annotations"])
|
||||
response["choices"][0]["message"]["annotations"] = all_annotations
|
||||
|
||||
audio_chunks = [
|
||||
|
|
|
|||
|
|
@ -1946,7 +1946,7 @@ class MCPServerManager:
|
|||
incoming_bearer_token: Optional[str] = None
|
||||
auth_hdr = normalized_raw.get("authorization", "")
|
||||
if auth_hdr.lower().startswith("bearer "):
|
||||
incoming_bearer_token = auth_hdr[len("bearer "):]
|
||||
incoming_bearer_token = auth_hdr[len("bearer ") :]
|
||||
|
||||
pre_hook_kwargs = {
|
||||
"name": name,
|
||||
|
|
|
|||
|
|
@ -903,12 +903,12 @@ if MCP_AVAILABLE:
|
|||
try:
|
||||
client_id, client_secret, scopes = _extract_credentials(request)
|
||||
|
||||
_oauth2_flow: Optional[Literal["client_credentials", "authorization_code"]] = (
|
||||
request.oauth2_flow or (
|
||||
"client_credentials"
|
||||
if client_id and client_secret and request.token_url
|
||||
else None
|
||||
)
|
||||
_oauth2_flow: Optional[
|
||||
Literal["client_credentials", "authorization_code"]
|
||||
] = request.oauth2_flow or (
|
||||
"client_credentials"
|
||||
if client_id and client_secret and request.token_url
|
||||
else None
|
||||
)
|
||||
# client_credentials requires token_url to fetch a token; without it the
|
||||
# incoming auth header would be dropped with nothing to replace it.
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@ def get_customer_user_header_from_mapping(user_id_mapping) -> Optional[list]:
|
|||
|
||||
if customer_headers_mappings:
|
||||
return customer_headers_mappings
|
||||
|
||||
|
||||
return None
|
||||
|
||||
|
||||
|
|
@ -754,15 +754,11 @@ def get_end_user_id_from_request_body(
|
|||
user_id_str = str(header_value)
|
||||
if user_id_str.strip():
|
||||
return user_id_str
|
||||
|
||||
|
||||
elif isinstance(custom_header_name_to_check, str):
|
||||
for header_name, header_value in request_headers.items():
|
||||
if header_name.lower() == custom_header_name_to_check.lower():
|
||||
user_id_str = (
|
||||
str(header_value)
|
||||
if header_value is not None
|
||||
else ""
|
||||
)
|
||||
user_id_str = str(header_value) if header_value is not None else ""
|
||||
if user_id_str.strip():
|
||||
return user_id_str
|
||||
|
||||
|
|
|
|||
|
|
@ -730,7 +730,7 @@ async def _user_api_key_auth_builder( # noqa: PLR0915
|
|||
team_membership: Optional[LiteLLM_TeamMembership] = result.get(
|
||||
"team_membership", None
|
||||
)
|
||||
jwt_claims: Optional[dict] = result.get("jwt_claims", None)
|
||||
jwt_claims = result.get("jwt_claims", None)
|
||||
|
||||
global_proxy_spend = await get_global_proxy_spend(
|
||||
litellm_proxy_admin_name=litellm_proxy_admin_name,
|
||||
|
|
|
|||
|
|
@ -537,9 +537,10 @@ async def retrieve_batch( # noqa: PLR0915
|
|||
)
|
||||
|
||||
# Fix: bug_feb14_batch_retrieve_returns_raw_input_file_id
|
||||
# Resolve raw provider input_file_id to unified ID.
|
||||
# Resolve raw provider file IDs (input, output, error) to unified IDs.
|
||||
if unified_batch_id:
|
||||
await resolve_input_file_id_to_unified(response, prisma_client)
|
||||
await resolve_output_file_ids_to_unified(response, prisma_client)
|
||||
|
||||
### ALERTING ###
|
||||
asyncio.create_task(
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ def _load_private_key_from_env(env_var: str) -> RSAPrivateKey:
|
|||
f"MCPJWTSigner: environment variable '{env_var}' is set but empty."
|
||||
)
|
||||
if key_material.startswith("file://"):
|
||||
path = key_material[len("file://"):]
|
||||
path = key_material[len("file://") :]
|
||||
with open(path, "rb") as f:
|
||||
key_bytes = f.read()
|
||||
else:
|
||||
|
|
@ -273,9 +273,7 @@ class MCPJWTSigner(CustomGuardrail):
|
|||
or "litellm"
|
||||
)
|
||||
self.audience: str = (
|
||||
audience
|
||||
or os.environ.get("MCP_JWT_AUDIENCE")
|
||||
or self.DEFAULT_AUDIENCE
|
||||
audience or os.environ.get("MCP_JWT_AUDIENCE") or self.DEFAULT_AUDIENCE
|
||||
)
|
||||
resolved_ttl = int(
|
||||
ttl_seconds
|
||||
|
|
@ -395,8 +393,12 @@ class MCPJWTSigner(CustomGuardrail):
|
|||
malformed response doesn't permanently disable JWT verification.
|
||||
"""
|
||||
now = time.time()
|
||||
cache_expired = (now - self._oidc_discovery_fetched_at) >= self._OIDC_DISCOVERY_TTL
|
||||
if (self._oidc_discovery_doc is None or cache_expired) and self.access_token_discovery_uri:
|
||||
cache_expired = (
|
||||
now - self._oidc_discovery_fetched_at
|
||||
) >= self._OIDC_DISCOVERY_TTL
|
||||
if (
|
||||
self._oidc_discovery_doc is None or cache_expired
|
||||
) and self.access_token_discovery_uri:
|
||||
doc = await _fetch_oidc_discovery(self.access_token_discovery_uri)
|
||||
if "jwks_uri" in doc:
|
||||
self._oidc_discovery_doc = doc
|
||||
|
|
@ -560,7 +562,7 @@ class MCPJWTSigner(CustomGuardrail):
|
|||
value: Optional[str] = None
|
||||
|
||||
if source.startswith("token:"):
|
||||
claim_name = source[len("token:"):]
|
||||
claim_name = source[len("token:") :]
|
||||
raw = (jwt_claims or {}).get(claim_name)
|
||||
value = str(raw) if raw else None
|
||||
|
||||
|
|
|
|||
|
|
@ -2142,8 +2142,7 @@ async def _resolve_org_filter_for_user_search(
|
|||
member_org_ids: List[str] = []
|
||||
if caller_user is not None:
|
||||
member_org_ids = [
|
||||
m.organization_id
|
||||
for m in (caller_user.organization_memberships or [])
|
||||
m.organization_id for m in (caller_user.organization_memberships or [])
|
||||
]
|
||||
|
||||
if member_org_ids:
|
||||
|
|
|
|||
|
|
@ -1863,16 +1863,10 @@ async def _validate_update_key_data(
|
|||
user_api_key_cache: Any,
|
||||
) -> None:
|
||||
"""Validate permissions and constraints for key update."""
|
||||
_is_proxy_admin = (
|
||||
user_api_key_dict.user_role == LitellmUserRoles.PROXY_ADMIN.value
|
||||
)
|
||||
_is_proxy_admin = user_api_key_dict.user_role == LitellmUserRoles.PROXY_ADMIN.value
|
||||
|
||||
# Prevent non-admin from removing user_id (setting to empty string) (LIT-1884)
|
||||
if (
|
||||
data.user_id is not None
|
||||
and data.user_id == ""
|
||||
and not _is_proxy_admin
|
||||
):
|
||||
if data.user_id is not None and data.user_id == "" and not _is_proxy_admin:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail="Non-admin users cannot remove the user_id from a key.",
|
||||
|
|
|
|||
|
|
@ -857,7 +857,13 @@ async def new_team( # noqa: PLR0915
|
|||
|
||||
# Apply defaults from litellm.default_team_params for any fields
|
||||
# not explicitly provided in the request.
|
||||
for field in ("max_budget", "budget_duration", "tpm_limit", "rpm_limit", "team_member_permissions"):
|
||||
for field in (
|
||||
"max_budget",
|
||||
"budget_duration",
|
||||
"tpm_limit",
|
||||
"rpm_limit",
|
||||
"team_member_permissions",
|
||||
):
|
||||
if getattr(data, field, None) is None:
|
||||
default_value = _get_default_team_param(field)
|
||||
if default_value is not None:
|
||||
|
|
|
|||
|
|
@ -857,7 +857,10 @@ async def update_batch_in_database(
|
|||
# If the batch_processed column doesn't exist (old schema),
|
||||
# retry without it so the status update still succeeds.
|
||||
err_str = str(col_err).lower()
|
||||
if "batch_processed" in err_str and update_data.get("batch_processed") is not None:
|
||||
if (
|
||||
"batch_processed" in err_str
|
||||
and update_data.get("batch_processed") is not None
|
||||
):
|
||||
verbose_proxy_logger.warning(
|
||||
f"batch_processed column not found, retrying update without it: {col_err}"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -115,7 +115,9 @@ async def background_streaming_task( # noqa: PLR0915
|
|||
UPDATE_INTERVAL = 0.150 # 150ms batching interval
|
||||
|
||||
# Track the terminal event from the stream (may not be "completed")
|
||||
terminal_status: Optional[ResponsesAPIStatus] = None # Will be set by response.completed/failed/incomplete/cancelled
|
||||
terminal_status: Optional[
|
||||
ResponsesAPIStatus
|
||||
] = None # Will be set by response.completed/failed/incomplete/cancelled
|
||||
terminal_error = None
|
||||
_event_to_status = {
|
||||
"response.completed": "completed",
|
||||
|
|
|
|||
|
|
@ -40,9 +40,7 @@ def _get_registered_vantage_logger():
|
|||
return None
|
||||
|
||||
|
||||
async def _set_vantage_settings(
|
||||
api_key: str, integration_token: str, base_url: str
|
||||
):
|
||||
async def _set_vantage_settings(api_key: str, integration_token: str, base_url: str):
|
||||
"""Store Vantage settings in the database with encrypted API key."""
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
|
||||
|
|
@ -341,9 +339,7 @@ async def init_vantage_settings(
|
|||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.error(
|
||||
f"Error initializing Vantage settings: {str(e)}"
|
||||
)
|
||||
verbose_proxy_logger.error(f"Error initializing Vantage settings: {str(e)}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail={"error": f"Failed to initialize Vantage settings: {str(e)}"},
|
||||
|
|
@ -395,7 +391,8 @@ async def vantage_dry_run_export(
|
|||
"""Cast Decimal columns to Float64 so .to_dicts() produces
|
||||
JSON-serializable float values instead of decimal.Decimal."""
|
||||
decimal_cols = [
|
||||
col for col, dtype in zip(frame.columns, frame.dtypes)
|
||||
col
|
||||
for col, dtype in zip(frame.columns, frame.dtypes)
|
||||
if isinstance(dtype, pl.Decimal)
|
||||
]
|
||||
if decimal_cols:
|
||||
|
|
@ -404,8 +401,16 @@ async def vantage_dry_run_export(
|
|||
)
|
||||
return frame.to_dicts()
|
||||
|
||||
usage_sample = _to_json_safe_dicts(data.head(min(50, len(data)))) if not data.is_empty() else []
|
||||
normalized_sample = _to_json_safe_dicts(normalized.head(min(50, len(normalized)))) if not normalized.is_empty() else []
|
||||
usage_sample = (
|
||||
_to_json_safe_dicts(data.head(min(50, len(data))))
|
||||
if not data.is_empty()
|
||||
else []
|
||||
)
|
||||
normalized_sample = (
|
||||
_to_json_safe_dicts(normalized.head(min(50, len(normalized))))
|
||||
if not normalized.is_empty()
|
||||
else []
|
||||
)
|
||||
|
||||
# Use the same pre-transform column names as
|
||||
# FocusExportEngine.dry_run_export_usage_data for consistency.
|
||||
|
|
@ -437,14 +442,10 @@ async def vantage_dry_run_export(
|
|||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.error(
|
||||
f"Error performing Vantage dry run export: {str(e)}"
|
||||
)
|
||||
verbose_proxy_logger.error(f"Error performing Vantage dry run export: {str(e)}")
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail={
|
||||
"error": f"Failed to perform Vantage dry run export: {str(e)}"
|
||||
},
|
||||
detail={"error": f"Failed to perform Vantage dry run export: {str(e)}"},
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -845,7 +845,10 @@ class ProxyLogging:
|
|||
# key collisions so that the most-specific guardrail (e.g. JWT signer)
|
||||
# takes precedence over earlier ones.
|
||||
existing = modified_kwargs.get("extra_headers") or {}
|
||||
modified_kwargs["extra_headers"] = {**existing, **response_data["extra_headers"]}
|
||||
modified_kwargs["extra_headers"] = {
|
||||
**existing,
|
||||
**response_data["extra_headers"],
|
||||
}
|
||||
|
||||
return modified_kwargs
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ from litellm.types.videos.utils import encode_character_id_with_provider
|
|||
|
||||
def extract_model_from_target_model_names(target_model_names: Any) -> Optional[str]:
|
||||
if isinstance(target_model_names, str):
|
||||
target_model_names = [m.strip() for m in target_model_names.split(",") if m.strip()]
|
||||
target_model_names = [
|
||||
m.strip() for m in target_model_names.split(",") if m.strip()
|
||||
]
|
||||
elif not isinstance(target_model_names, list):
|
||||
return None
|
||||
return target_model_names[0] if target_model_names else None
|
||||
|
|
|
|||
|
|
@ -692,11 +692,11 @@ def responses(
|
|||
return run_async_function(aresponses_api_with_mcp, **mcp_call_kwargs)
|
||||
|
||||
# get provider config
|
||||
responses_api_provider_config: Optional[BaseResponsesAPIConfig] = (
|
||||
ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=model,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
responses_api_provider_config: Optional[
|
||||
BaseResponsesAPIConfig
|
||||
] = ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=model,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
|
||||
local_vars.update(kwargs)
|
||||
|
|
@ -908,11 +908,11 @@ def delete_responses(
|
|||
raise ValueError("custom_llm_provider is required but passed as None")
|
||||
|
||||
# get provider config
|
||||
responses_api_provider_config: Optional[BaseResponsesAPIConfig] = (
|
||||
ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=None,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
responses_api_provider_config: Optional[
|
||||
BaseResponsesAPIConfig
|
||||
] = ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=None,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
|
||||
if responses_api_provider_config is None:
|
||||
|
|
@ -1089,11 +1089,11 @@ def get_responses(
|
|||
raise ValueError("custom_llm_provider is required but passed as None")
|
||||
|
||||
# get provider config
|
||||
responses_api_provider_config: Optional[BaseResponsesAPIConfig] = (
|
||||
ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=None,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
responses_api_provider_config: Optional[
|
||||
BaseResponsesAPIConfig
|
||||
] = ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=None,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
|
||||
if responses_api_provider_config is None:
|
||||
|
|
@ -1247,11 +1247,11 @@ def list_input_items(
|
|||
if custom_llm_provider is None:
|
||||
raise ValueError("custom_llm_provider is required but passed as None")
|
||||
|
||||
responses_api_provider_config: Optional[BaseResponsesAPIConfig] = (
|
||||
ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=None,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
responses_api_provider_config: Optional[
|
||||
BaseResponsesAPIConfig
|
||||
] = ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=None,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
|
||||
if responses_api_provider_config is None:
|
||||
|
|
@ -1406,11 +1406,11 @@ def cancel_responses(
|
|||
raise ValueError("custom_llm_provider is required but passed as None")
|
||||
|
||||
# get provider config
|
||||
responses_api_provider_config: Optional[BaseResponsesAPIConfig] = (
|
||||
ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=None,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
responses_api_provider_config: Optional[
|
||||
BaseResponsesAPIConfig
|
||||
] = ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=None,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
|
||||
if responses_api_provider_config is None:
|
||||
|
|
@ -1594,11 +1594,11 @@ def compact_responses(
|
|||
raise ValueError("custom_llm_provider is required but passed as None")
|
||||
|
||||
# get provider config
|
||||
responses_api_provider_config: Optional[BaseResponsesAPIConfig] = (
|
||||
ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=model,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
responses_api_provider_config: Optional[
|
||||
BaseResponsesAPIConfig
|
||||
] = ProviderConfigManager.get_provider_responses_api_config(
|
||||
model=model,
|
||||
provider=custom_llm_provider,
|
||||
)
|
||||
|
||||
if responses_api_provider_config is None:
|
||||
|
|
|
|||
|
|
@ -8611,6 +8611,7 @@ class Router:
|
|||
_model_info = deployment.get("model_info", {})
|
||||
|
||||
# see if we have the info for this model
|
||||
_deployment_model = None # per-deployment model name (avoids overwriting the outer `model` group name)
|
||||
try:
|
||||
base_model = _model_info.get("base_model", None)
|
||||
if base_model is None:
|
||||
|
|
@ -8618,7 +8619,7 @@ class Router:
|
|||
model_info = self.get_router_model_info(
|
||||
deployment=deployment, received_model_name=model
|
||||
)
|
||||
model = base_model or _litellm_params.get("model", None)
|
||||
_deployment_model = base_model or _litellm_params.get("model", None)
|
||||
|
||||
if (
|
||||
isinstance(model_info, dict)
|
||||
|
|
@ -8632,7 +8633,9 @@ class Router:
|
|||
_context_window_error = True
|
||||
_potential_error_str += (
|
||||
"Model={}, Max Input Tokens={}, Got={}".format(
|
||||
model, model_info["max_input_tokens"], input_tokens
|
||||
_deployment_model,
|
||||
model_info["max_input_tokens"],
|
||||
input_tokens,
|
||||
)
|
||||
)
|
||||
continue
|
||||
|
|
@ -8688,13 +8691,21 @@ class Router:
|
|||
|
||||
## INVALID PARAMS ## -> catch 'gpt-3.5-turbo-16k' not supporting 'response_format' param
|
||||
if request_kwargs is not None and litellm.drop_params is False:
|
||||
# get supported params
|
||||
model, custom_llm_provider, _, _ = litellm.get_llm_provider(
|
||||
model=model, litellm_params=LiteLLM_Params(**_litellm_params)
|
||||
# get supported params — use per-deployment model to avoid overwriting the outer model group name
|
||||
_dep_model_for_params = _deployment_model or model
|
||||
(
|
||||
_dep_model_for_params,
|
||||
custom_llm_provider,
|
||||
_,
|
||||
_,
|
||||
) = litellm.get_llm_provider(
|
||||
model=_dep_model_for_params,
|
||||
litellm_params=LiteLLM_Params(**_litellm_params),
|
||||
)
|
||||
|
||||
supported_openai_params = litellm.get_supported_openai_params(
|
||||
model=model, custom_llm_provider=custom_llm_provider
|
||||
model=_dep_model_for_params,
|
||||
custom_llm_provider=custom_llm_provider,
|
||||
)
|
||||
|
||||
if supported_openai_params is None:
|
||||
|
|
|
|||
|
|
@ -319,7 +319,8 @@ class SetupWizard:
|
|||
|
||||
@staticmethod
|
||||
def _select_interactive() -> List[Dict]:
|
||||
cursor, selected = 0, set()
|
||||
cursor = 0
|
||||
selected: set[int] = set()
|
||||
|
||||
if _supports_color():
|
||||
sys.stdout.write(_CURSOR_HIDE)
|
||||
|
|
@ -432,9 +433,9 @@ class SetupWizard:
|
|||
f" {blue('❯')} Azure deployment name {grey('(e.g. my-gpt4o)')}: "
|
||||
)
|
||||
if deployment:
|
||||
env_vars[f"_LITELLM_AZURE_DEPLOYMENT_{p['id'].upper()}"] = (
|
||||
deployment
|
||||
)
|
||||
env_vars[
|
||||
f"_LITELLM_AZURE_DEPLOYMENT_{p['id'].upper()}"
|
||||
] = deployment
|
||||
|
||||
# Store the key returned by validation — may be a re-entered replacement
|
||||
env_vars[p["env_key"]] = SetupWizard._validate_and_report(p, key)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ class VantageExportRequest(BaseModel):
|
|||
"""Request model for Vantage export operations (actual export, no default limit)"""
|
||||
|
||||
limit: Optional[int] = Field(
|
||||
None, description="Optional limit on number of records to export (default: no limit)"
|
||||
None,
|
||||
description="Optional limit on number of records to export (default: no limit)",
|
||||
)
|
||||
start_time_utc: Optional[datetime] = Field(
|
||||
None, description="Start time for data export in UTC"
|
||||
|
|
|
|||
|
|
@ -195,7 +195,9 @@ def decode_character_id_with_provider(encoded_character_id: str) -> DecodedChara
|
|||
character_id=decoded_character_id,
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(f"Error decoding character_id '{encoded_character_id}': {e}")
|
||||
verbose_logger.debug(
|
||||
f"Error decoding character_id '{encoded_character_id}': {e}"
|
||||
)
|
||||
return DecodedCharacterId(
|
||||
custom_llm_provider=None,
|
||||
model_id=None,
|
||||
|
|
|
|||
|
|
@ -1186,13 +1186,17 @@ def video_create_character(
|
|||
|
||||
litellm_params = GenericLiteLLMParams(**kwargs)
|
||||
|
||||
provider_config: Optional[BaseVideoConfig] = ProviderConfigManager.get_provider_video_config(
|
||||
provider_config: Optional[
|
||||
BaseVideoConfig
|
||||
] = ProviderConfigManager.get_provider_video_config(
|
||||
model=None,
|
||||
provider=litellm.LlmProviders(custom_llm_provider),
|
||||
)
|
||||
|
||||
if provider_config is None:
|
||||
raise ValueError(f"video create character is not supported for {custom_llm_provider}")
|
||||
raise ValueError(
|
||||
f"video create character is not supported for {custom_llm_provider}"
|
||||
)
|
||||
|
||||
local_vars.update(kwargs)
|
||||
request_params: Dict = {"name": name}
|
||||
|
|
@ -1311,13 +1315,17 @@ def video_get_character(
|
|||
|
||||
litellm_params = GenericLiteLLMParams(**kwargs)
|
||||
|
||||
provider_config: Optional[BaseVideoConfig] = ProviderConfigManager.get_provider_video_config(
|
||||
provider_config: Optional[
|
||||
BaseVideoConfig
|
||||
] = ProviderConfigManager.get_provider_video_config(
|
||||
model=None,
|
||||
provider=litellm.LlmProviders(custom_llm_provider),
|
||||
)
|
||||
|
||||
if provider_config is None:
|
||||
raise ValueError(f"video get character is not supported for {custom_llm_provider}")
|
||||
raise ValueError(
|
||||
f"video get character is not supported for {custom_llm_provider}"
|
||||
)
|
||||
|
||||
local_vars.update(kwargs)
|
||||
request_params: Dict = {"character_id": character_id}
|
||||
|
|
@ -1439,7 +1447,9 @@ def video_edit(
|
|||
|
||||
litellm_params = GenericLiteLLMParams(**kwargs)
|
||||
|
||||
provider_config: Optional[BaseVideoConfig] = ProviderConfigManager.get_provider_video_config(
|
||||
provider_config: Optional[
|
||||
BaseVideoConfig
|
||||
] = ProviderConfigManager.get_provider_video_config(
|
||||
model=None,
|
||||
provider=litellm.LlmProviders(custom_llm_provider),
|
||||
)
|
||||
|
|
@ -1572,16 +1582,24 @@ def video_extension(
|
|||
|
||||
litellm_params = GenericLiteLLMParams(**kwargs)
|
||||
|
||||
provider_config: Optional[BaseVideoConfig] = ProviderConfigManager.get_provider_video_config(
|
||||
provider_config: Optional[
|
||||
BaseVideoConfig
|
||||
] = ProviderConfigManager.get_provider_video_config(
|
||||
model=None,
|
||||
provider=litellm.LlmProviders(custom_llm_provider),
|
||||
)
|
||||
|
||||
if provider_config is None:
|
||||
raise ValueError(f"video extension is not supported for {custom_llm_provider}")
|
||||
raise ValueError(
|
||||
f"video extension is not supported for {custom_llm_provider}"
|
||||
)
|
||||
|
||||
local_vars.update(kwargs)
|
||||
request_params: Dict = {"video_id": video_id, "prompt": prompt, "seconds": seconds}
|
||||
request_params: Dict = {
|
||||
"video_id": video_id,
|
||||
"prompt": prompt,
|
||||
"seconds": seconds,
|
||||
}
|
||||
|
||||
litellm_logging_obj.update_environment_variables(
|
||||
model="",
|
||||
|
|
|
|||
|
|
@ -308,16 +308,19 @@ async def test_long_term_spend_accuracy_with_bursts():
|
|||
response = await chat_completion(session, key)
|
||||
print(f"Burst 2 - Request {i + 1}/{BURST_2_REQUESTS} completed")
|
||||
|
||||
# Poll until key spend reflects burst 2
|
||||
burst_1_spend = intermediate_key_info["info"]["spend"]
|
||||
# Poll until key spend reaches expected total (burst 1 + burst 2)
|
||||
start = time.time()
|
||||
while time.time() - start < 120:
|
||||
key_info_check = await get_spend_info(session, "key", key)
|
||||
current_spend = key_info_check["info"]["spend"]
|
||||
if current_spend > burst_1_spend:
|
||||
print(f"Key spend increased to {current_spend} after {time.time() - start:.1f}s")
|
||||
if abs(current_spend - expected_spend) < TOLERANCE:
|
||||
print(
|
||||
f"Total spend reached expected {expected_spend} after {time.time() - start:.1f}s"
|
||||
)
|
||||
break
|
||||
print(f"Key spend still {current_spend}, waiting for burst 2 flush...")
|
||||
print(
|
||||
f"Key spend {current_spend}, expected {expected_spend}, waiting..."
|
||||
)
|
||||
await asyncio.sleep(10)
|
||||
|
||||
# Allow extra time for all entity spend aggregations
|
||||
|
|
|
|||
82
ui/litellm-dashboard/package-lock.json
generated
82
ui/litellm-dashboard/package-lock.json
generated
|
|
@ -23,7 +23,7 @@
|
|||
"jwt-decode": "^4.0.0",
|
||||
"lucide-react": "^0.513.0",
|
||||
"moment": "^2.30.1",
|
||||
"next": "^16.1.6",
|
||||
"next": "^16.1.7",
|
||||
"openai": "^4.93.0",
|
||||
"papaparse": "^5.5.2",
|
||||
"react": "^18.3.1",
|
||||
|
|
@ -1828,9 +1828,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.6.tgz",
|
||||
"integrity": "sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-16.1.7.tgz",
|
||||
"integrity": "sha512-rJJbIdJB/RQr2F1nylZr/PJzamvNNhfr3brdKP6s/GW850jbtR70QlSfFselvIBbcPUOlQwBakexjFzqLzF6pg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@next/eslint-plugin-next": {
|
||||
|
|
@ -1844,9 +1844,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-arm64": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.6.tgz",
|
||||
"integrity": "sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.1.7.tgz",
|
||||
"integrity": "sha512-b2wWIE8sABdyafc4IM8r5Y/dS6kD80JRtOGrUiKTsACFQfWWgUQ2NwoUX1yjFMXVsAwcQeNpnucF2ZrujsBBPg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -1860,9 +1860,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-x64": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.6.tgz",
|
||||
"integrity": "sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.1.7.tgz",
|
||||
"integrity": "sha512-zcnVaaZulS1WL0Ss38R5Q6D2gz7MtBu8GZLPfK+73D/hp4GFMrC2sudLky1QibfV7h6RJBJs/gOFvYP0X7UVlQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -1876,9 +1876,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-gnu": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.6.tgz",
|
||||
"integrity": "sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.1.7.tgz",
|
||||
"integrity": "sha512-2ant89Lux/Q3VyC8vNVg7uBaFVP9SwoK2jJOOR0L8TQnX8CAYnh4uctAScy2Hwj2dgjVHqHLORQZJ2wH6VxhSQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -1892,9 +1892,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-musl": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.6.tgz",
|
||||
"integrity": "sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.1.7.tgz",
|
||||
"integrity": "sha512-uufcze7LYv0FQg9GnNeZ3/whYfo+1Q3HnQpm16o6Uyi0OVzLlk2ZWoY7j07KADZFY8qwDbsmFnMQP3p3+Ftprw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -1908,9 +1908,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-x64-gnu": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.6.tgz",
|
||||
"integrity": "sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.1.7.tgz",
|
||||
"integrity": "sha512-KWVf2gxYvHtvuT+c4MBOGxuse5TD7DsMFYSxVxRBnOzok/xryNeQSjXgxSv9QpIVlaGzEn/pIuI6Koosx8CGWA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -1924,9 +1924,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-x64-musl": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.6.tgz",
|
||||
"integrity": "sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.1.7.tgz",
|
||||
"integrity": "sha512-HguhaGwsGr1YAGs68uRKc4aGWxLET+NevJskOcCAwXbwj0fYX0RgZW2gsOCzr9S11CSQPIkxmoSbuVaBp4Z3dA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -1940,9 +1940,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-arm64-msvc": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.6.tgz",
|
||||
"integrity": "sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.1.7.tgz",
|
||||
"integrity": "sha512-S0n3KrDJokKTeFyM/vGGGR8+pCmXYrjNTk2ZozOL1C/JFdfUIL9O1ATaJOl5r2POe56iRChbsszrjMAdWSv7kQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -1956,9 +1956,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-x64-msvc": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.6.tgz",
|
||||
"integrity": "sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.1.7.tgz",
|
||||
"integrity": "sha512-mwgtg8CNZGYm06LeEd+bNnOUfwOyNem/rOiP14Lsz+AnUY92Zq/LXwtebtUiaeVkhbroRCQ0c8GlR4UT1U+0yg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -9343,14 +9343,14 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/next": {
|
||||
"version": "16.1.6",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-16.1.6.tgz",
|
||||
"integrity": "sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==",
|
||||
"version": "16.1.7",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-16.1.7.tgz",
|
||||
"integrity": "sha512-WM0L7WrSvKwoLegLYr6V+mz+RIofqQgVAfHhMp9a88ms0cFX8iX9ew+snpWlSBwpkURJOUdvCEt3uLl3NNzvWg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@next/env": "16.1.6",
|
||||
"@next/env": "16.1.7",
|
||||
"@swc/helpers": "0.5.15",
|
||||
"baseline-browser-mapping": "^2.8.3",
|
||||
"baseline-browser-mapping": "^2.9.19",
|
||||
"caniuse-lite": "^1.0.30001579",
|
||||
"postcss": "8.4.31",
|
||||
"styled-jsx": "5.1.6"
|
||||
|
|
@ -9362,14 +9362,14 @@
|
|||
"node": ">=20.9.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@next/swc-darwin-arm64": "16.1.6",
|
||||
"@next/swc-darwin-x64": "16.1.6",
|
||||
"@next/swc-linux-arm64-gnu": "16.1.6",
|
||||
"@next/swc-linux-arm64-musl": "16.1.6",
|
||||
"@next/swc-linux-x64-gnu": "16.1.6",
|
||||
"@next/swc-linux-x64-musl": "16.1.6",
|
||||
"@next/swc-win32-arm64-msvc": "16.1.6",
|
||||
"@next/swc-win32-x64-msvc": "16.1.6",
|
||||
"@next/swc-darwin-arm64": "16.1.7",
|
||||
"@next/swc-darwin-x64": "16.1.7",
|
||||
"@next/swc-linux-arm64-gnu": "16.1.7",
|
||||
"@next/swc-linux-arm64-musl": "16.1.7",
|
||||
"@next/swc-linux-x64-gnu": "16.1.7",
|
||||
"@next/swc-linux-x64-musl": "16.1.7",
|
||||
"@next/swc-win32-arm64-msvc": "16.1.7",
|
||||
"@next/swc-win32-x64-msvc": "16.1.7",
|
||||
"sharp": "^0.34.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
"jwt-decode": "^4.0.0",
|
||||
"lucide-react": "^0.513.0",
|
||||
"moment": "^2.30.1",
|
||||
"next": "^16.1.6",
|
||||
"next": "^16.1.7",
|
||||
"openai": "^4.93.0",
|
||||
"papaparse": "^5.5.2",
|
||||
"react": "^18.3.1",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue