mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
chore: migrate Python formatter from black to ruff format (#31317)
This commit is contained in:
parent
6db55e0aa5
commit
17bfd415ae
215 changed files with 1877 additions and 1241 deletions
4
.github/workflows/test-linting.yml
vendored
4
.github/workflows/test-linting.yml
vendored
|
|
@ -50,10 +50,10 @@ jobs:
|
|||
run: |
|
||||
uv sync --frozen
|
||||
|
||||
- name: Check Black formatting
|
||||
- name: Check ruff format
|
||||
run: |
|
||||
cd litellm
|
||||
uv run --no-sync black --check --exclude '/enterprise/' .
|
||||
uv run --no-sync ruff format --check --line-length 88 --exclude '/enterprise/' .
|
||||
cd ..
|
||||
|
||||
- name: Debug - Check file state
|
||||
|
|
|
|||
16
Makefile
16
Makefile
|
|
@ -20,13 +20,13 @@ help:
|
|||
@echo " make install-test-deps - Install the full local test environment"
|
||||
@echo " make install-helm-unittest - Install helm unittest plugin"
|
||||
@echo " make install-hooks - Install git hooks (Conventional Commits + Branches)"
|
||||
@echo " make format - Apply Black code formatting"
|
||||
@echo " make format-check - Check Black code formatting (matches CI)"
|
||||
@echo " make lint - Run all linting (Ruff, basedpyright, Black check, circular imports, import safety)"
|
||||
@echo " make format - Apply ruff format code formatting"
|
||||
@echo " make format-check - Check ruff format code formatting (matches CI)"
|
||||
@echo " make lint - Run all linting (Ruff, basedpyright, format check, circular imports, import safety)"
|
||||
@echo " make lint-ruff - Run Ruff linting only"
|
||||
@echo " make lint-basedpyright - Run basedpyright strict, gated by per-rule error counts"
|
||||
@echo " make lint-basedpyright-budget-update - Re-capture the basedpyright per-rule budget (ratchet)"
|
||||
@echo " make lint-black - Check Black formatting (matches CI)"
|
||||
@echo " make lint-format - Check ruff format formatting (matches CI)"
|
||||
@echo " make lint-ruff-budget - Gate the codebase total of each strict ruff rule against its ceiling"
|
||||
@echo " make lint-gate - Strict ruff gate in CI-parity mode (fetches staging, simulates the merge)"
|
||||
@echo " make lint-ruff-budget-update - Re-capture per-rule baselines in ruff-strict-budget.json (ratchet)"
|
||||
|
|
@ -82,11 +82,13 @@ install-hooks:
|
|||
./scripts/install_git_hooks.sh
|
||||
|
||||
# Formatting
|
||||
# 88-column wrap matches the Black width the whole repo is formatted to; ruff.toml's
|
||||
# global line-length is 120 (for E501/isort), so 88 is forced here.
|
||||
format: install-dev
|
||||
cd litellm && $(UV_RUN) black . && cd ..
|
||||
cd litellm && $(UV_RUN) ruff format --line-length 88 --exclude '/enterprise/' . && cd ..
|
||||
|
||||
format-check: install-dev
|
||||
cd litellm && $(UV_RUN) black --check . && cd ..
|
||||
cd litellm && $(UV_RUN) ruff format --check --line-length 88 --exclude '/enterprise/' . && cd ..
|
||||
|
||||
# Linting targets
|
||||
lint-ruff: install-dev
|
||||
|
|
@ -131,7 +133,7 @@ lint-basedpyright: install-dev
|
|||
lint-basedpyright-budget-update: install-dev
|
||||
($(UV_RUN) basedpyright --outputjson || true) | $(UV_RUN) python scripts/type_check_gate.py --update
|
||||
|
||||
lint-black: format-check
|
||||
lint-format: format-check
|
||||
|
||||
lint-ruff-budget: install-dev
|
||||
$(UV_RUN) python scripts/ruff_strict_gate.py
|
||||
|
|
|
|||
|
|
@ -390,12 +390,8 @@ require_managed_files: bool = (
|
|||
enable_caching_on_provider_specific_optional_params: bool = (
|
||||
False # feature-flag for caching on optional params - e.g. 'top_k'
|
||||
)
|
||||
caching: bool = (
|
||||
False # Not used anymore, will be removed in next MAJOR release - https://github.com/BerriAI/litellm/discussions/648
|
||||
)
|
||||
caching_with_models: bool = (
|
||||
False # # Not used anymore, will be removed in next MAJOR release - https://github.com/BerriAI/litellm/discussions/648
|
||||
)
|
||||
caching: bool = False # Not used anymore, will be removed in next MAJOR release - https://github.com/BerriAI/litellm/discussions/648
|
||||
caching_with_models: bool = False # # Not used anymore, will be removed in next MAJOR release - https://github.com/BerriAI/litellm/discussions/648
|
||||
cache: Optional["Cache"] = (
|
||||
None # cache object <- use this - https://docs.litellm.ai/docs/caching
|
||||
)
|
||||
|
|
@ -416,9 +412,7 @@ forward_traceparent_to_llm_provider: bool = False
|
|||
|
||||
_current_cost = 0.0 # private variable, used if max budget is set
|
||||
error_logs: Dict = {}
|
||||
add_function_to_prompt: bool = (
|
||||
False # if function calling not supported by api, append function call details to system prompt
|
||||
)
|
||||
add_function_to_prompt: bool = False # if function calling not supported by api, append function call details to system prompt
|
||||
client_session: Optional[httpx.Client] = None
|
||||
aclient_session: Optional[httpx.AsyncClient] = None
|
||||
model_fallbacks: Optional[List] = None # Deprecated for 'litellm.fallbacks'
|
||||
|
|
@ -485,9 +479,7 @@ prometheus_end_user_metrics_cleanup_interval_seconds: Optional[float] = 60.0
|
|||
disable_add_prefix_to_prompt: bool = (
|
||||
False # used by anthropic, to disable adding prefix to prompt
|
||||
)
|
||||
disable_copilot_system_to_assistant: bool = (
|
||||
False # If false (default), converts all 'system' role messages to 'assistant' for GitHub Copilot compatibility. Set to true to disable this behavior.
|
||||
)
|
||||
disable_copilot_system_to_assistant: bool = False # If false (default), converts all 'system' role messages to 'assistant' for GitHub Copilot compatibility. Set to true to disable this behavior.
|
||||
public_mcp_servers: Optional[List[str]] = None
|
||||
public_mcp_hub_strict_whitelist: bool = True
|
||||
public_model_groups: Optional[List[str]] = None
|
||||
|
|
@ -507,17 +499,13 @@ if TYPE_CHECKING:
|
|||
|
||||
|
||||
######## Networking Settings ########
|
||||
use_aiohttp_transport: bool = (
|
||||
True # Older variable, aiohttp is now the default. use disable_aiohttp_transport instead.
|
||||
)
|
||||
use_aiohttp_transport: bool = True # Older variable, aiohttp is now the default. use disable_aiohttp_transport instead.
|
||||
aiohttp_trust_env: bool = False # set to true to use HTTP_ Proxy settings
|
||||
disable_aiohttp_transport: bool = False # Set this to true to use httpx instead
|
||||
disable_aiohttp_trust_env: bool = (
|
||||
False # When False, aiohttp will respect HTTP(S)_PROXY env vars
|
||||
)
|
||||
force_ipv4: bool = (
|
||||
False # when True, litellm will force ipv4 for all LLM requests. Some users have seen httpx ConnectionError when using ipv6.
|
||||
)
|
||||
force_ipv4: bool = False # when True, litellm will force ipv4 for all LLM requests. Some users have seen httpx ConnectionError when using ipv6.
|
||||
network_mock: bool = False # When True, use mock transport — no real network calls
|
||||
|
||||
####### STOP SEQUENCE LIMIT #######
|
||||
|
|
@ -551,12 +539,12 @@ output_parse_pii: bool = False
|
|||
from litellm.litellm_core_utils.get_model_cost_map import get_model_cost_map
|
||||
|
||||
model_cost = get_model_cost_map(url=model_cost_map_url)
|
||||
cost_discount_config: Dict[str, float] = (
|
||||
{}
|
||||
) # Provider-specific cost discounts {"vertex_ai": 0.05} = 5% discount
|
||||
cost_margin_config: Dict[str, Union[float, Dict[str, float]]] = (
|
||||
{}
|
||||
) # Provider-specific or global cost margins. Examples:
|
||||
cost_discount_config: Dict[
|
||||
str, float
|
||||
] = {} # Provider-specific cost discounts {"vertex_ai": 0.05} = 5% discount
|
||||
cost_margin_config: Dict[
|
||||
str, Union[float, Dict[str, float]]
|
||||
] = {} # Provider-specific or global cost margins. Examples:
|
||||
# Percentage: {"openai": 0.10} = 10% margin
|
||||
# Fixed: {"openai": {"fixed_amount": 0.001}} = $0.001 per request
|
||||
# Global: {"global": 0.05} = 5% global margin on all providers
|
||||
|
|
@ -1457,9 +1445,9 @@ from . import rag
|
|||
from .types.llms.custom_llm import CustomLLMItem
|
||||
|
||||
custom_provider_map: List[CustomLLMItem] = []
|
||||
_custom_providers: List[str] = (
|
||||
[]
|
||||
) # internal helper util, used to track names of custom providers
|
||||
_custom_providers: List[
|
||||
str
|
||||
] = [] # internal helper util, used to track names of custom providers
|
||||
disable_hf_tokenizer_download: Optional[bool] = (
|
||||
None # disable huggingface tokenizer download. Defaults to openai clk100
|
||||
)
|
||||
|
|
|
|||
|
|
@ -327,7 +327,9 @@ def _get_redis_client_logic(**env_overrides):
|
|||
**env_overrides,
|
||||
}
|
||||
|
||||
_startup_nodes: Optional[Union[str, list]] = redis_kwargs.get("startup_nodes", None) or get_secret( # type: ignore
|
||||
_startup_nodes: Optional[Union[str, list]] = redis_kwargs.get(
|
||||
"startup_nodes", None
|
||||
) or get_secret( # type: ignore
|
||||
"REDIS_CLUSTER_NODES"
|
||||
)
|
||||
|
||||
|
|
@ -338,7 +340,9 @@ def _get_redis_client_logic(**env_overrides):
|
|||
elif _startup_nodes is None:
|
||||
redis_kwargs.pop("startup_nodes", None)
|
||||
|
||||
_sentinel_nodes: Optional[Union[str, list]] = redis_kwargs.get("sentinel_nodes", None) or get_secret( # type: ignore
|
||||
_sentinel_nodes: Optional[Union[str, list]] = redis_kwargs.get(
|
||||
"sentinel_nodes", None
|
||||
) or get_secret( # type: ignore
|
||||
"REDIS_SENTINEL_NODES"
|
||||
)
|
||||
|
||||
|
|
@ -609,7 +613,8 @@ def get_redis_async_client(
|
|||
|
||||
# Create async RedisCluster with IAM token as password if available
|
||||
cluster_client = async_redis.RedisCluster(
|
||||
startup_nodes=new_startup_nodes, **cluster_kwargs # type: ignore
|
||||
startup_nodes=new_startup_nodes,
|
||||
**cluster_kwargs, # type: ignore
|
||||
)
|
||||
|
||||
return cluster_client
|
||||
|
|
|
|||
|
|
@ -184,7 +184,9 @@ def get_assistants(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -198,7 +200,9 @@ def get_assistants(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -394,7 +398,9 @@ def create_assistants(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
if response is None:
|
||||
|
|
@ -761,7 +767,9 @@ def create_thread(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response # type: ignore
|
||||
|
|
@ -916,7 +924,9 @@ def get_thread(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response # type: ignore
|
||||
|
|
@ -1103,7 +1113,9 @@ def add_message(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -1263,7 +1275,9 @@ def get_messages(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -1478,7 +1492,9 @@ def run_thread(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response # type: ignore
|
||||
|
|
|
|||
|
|
@ -71,9 +71,7 @@ def get_optional_params_add_message(
|
|||
if custom_llm_provider == "openai":
|
||||
optional_params = non_default_params
|
||||
elif custom_llm_provider == "azure":
|
||||
supported_params = (
|
||||
litellm.AzureOpenAIAssistantsAPIConfig().get_supported_openai_create_message_params()
|
||||
)
|
||||
supported_params = litellm.AzureOpenAIAssistantsAPIConfig().get_supported_openai_create_message_params()
|
||||
_check_valid_arg(supported_params=supported_params)
|
||||
optional_params = litellm.AzureOpenAIAssistantsAPIConfig().map_openai_params_create_message_params(
|
||||
non_default_params=non_default_params, optional_params=optional_params
|
||||
|
|
|
|||
|
|
@ -359,7 +359,9 @@ def create_batch(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_batch", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_batch", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
@ -553,7 +555,9 @@ def _handle_retrieve_batch_providers_without_provider_config(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="retrieve_batch", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="retrieve_batch", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
@ -819,7 +823,11 @@ def list_batches(
|
|||
max_retries=optional_params.max_retries,
|
||||
)
|
||||
elif custom_llm_provider == "azure":
|
||||
api_base = optional_params.api_base or litellm.api_base or get_secret_str("AZURE_API_BASE") # type: ignore
|
||||
api_base = (
|
||||
optional_params.api_base
|
||||
or litellm.api_base
|
||||
or get_secret_str("AZURE_API_BASE")
|
||||
) # type: ignore
|
||||
api_version = (
|
||||
optional_params.api_version
|
||||
or litellm.api_version
|
||||
|
|
@ -887,7 +895,9 @@ def list_batches(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
@ -1097,7 +1107,9 @@ def cancel_batch(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="cancel_batch", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="cancel_batch", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
|
|||
|
|
@ -67,9 +67,7 @@ class BudgetManager:
|
|||
)
|
||||
response = response.json()
|
||||
if response["status"] == "error":
|
||||
self.user_dict = (
|
||||
{}
|
||||
) # assume this means the user dict hasn't been stored yet
|
||||
self.user_dict = {} # assume this means the user dict hasn't been stored yet
|
||||
else:
|
||||
self.user_dict = response["data"]
|
||||
|
||||
|
|
|
|||
|
|
@ -79,9 +79,7 @@ class CachingHandlerResponse(BaseModel):
|
|||
|
||||
cached_result: Optional[Any] = None
|
||||
final_embedding_cached_response: Optional[EmbeddingResponse] = None
|
||||
embedding_all_elements_cache_hit: bool = (
|
||||
False # this is set to True when all elements in the list have a cache hit in the embedding cache, if true return the final_embedding_cached_response no need to make an API call
|
||||
)
|
||||
embedding_all_elements_cache_hit: bool = False # this is set to True when all elements in the list have a cache hit in the embedding cache, if true return the final_embedding_cached_response no need to make an API call
|
||||
|
||||
|
||||
in_memory_cache_obj = InMemoryCache()
|
||||
|
|
@ -165,10 +163,11 @@ class LLMCachingHandler:
|
|||
"""
|
||||
# Check if caching should be performed BEFORE doing expensive operations
|
||||
if (
|
||||
(kwargs.get("caching", None) is None and litellm.cache is not None)
|
||||
or kwargs.get("caching", False) is True
|
||||
) and (
|
||||
kwargs.get("cache", {}).get("no-cache", False) is not True
|
||||
(
|
||||
(kwargs.get("caching", None) is None and litellm.cache is not None)
|
||||
or kwargs.get("caching", False) is True
|
||||
)
|
||||
and (kwargs.get("cache", {}).get("no-cache", False) is not True)
|
||||
): # allow users to control returning cached responses from the completion function
|
||||
args = args or ()
|
||||
final_embedding_cached_response: Optional[EmbeddingResponse] = None
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ class RedisClusterCache(RedisCache):
|
|||
|
||||
# Create a fresh Redis Cluster client with current settings
|
||||
redis_client = redis_async.RedisCluster(
|
||||
startup_nodes=new_startup_nodes, **cluster_kwargs # type: ignore
|
||||
startup_nodes=new_startup_nodes,
|
||||
**cluster_kwargs, # type: ignore
|
||||
)
|
||||
|
||||
# Test the connection
|
||||
|
|
|
|||
|
|
@ -151,7 +151,9 @@ class ResponsesToCompletionBridgeHandler:
|
|||
custom_llm_provider=custom_llm_provider,
|
||||
)
|
||||
|
||||
def completion(self, *args, **kwargs) -> Union[
|
||||
def completion(
|
||||
self, *args, **kwargs
|
||||
) -> Union[
|
||||
Coroutine[Any, Any, Union["ModelResponse", "CustomStreamWrapper"]],
|
||||
"ModelResponse",
|
||||
"CustomStreamWrapper",
|
||||
|
|
|
|||
|
|
@ -205,9 +205,9 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
if provider_specific_fields:
|
||||
tool_call_dict["provider_specific_fields"] = provider_specific_fields
|
||||
# Also add to function's provider_specific_fields for consistency
|
||||
tool_call_dict["function"][
|
||||
"provider_specific_fields"
|
||||
] = provider_specific_fields
|
||||
tool_call_dict["function"]["provider_specific_fields"] = (
|
||||
provider_specific_fields
|
||||
)
|
||||
|
||||
msg = Message(
|
||||
content=None,
|
||||
|
|
@ -301,7 +301,9 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
{
|
||||
"type": "message",
|
||||
"role": role,
|
||||
"content": self._convert_content_to_responses_format(content, cast(str, role)), # type: ignore[arg-type]
|
||||
"content": self._convert_content_to_responses_format(
|
||||
content, cast(str, role)
|
||||
), # type: ignore[arg-type]
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -1021,7 +1023,11 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
|
||||
# If string is passed, map with optional summary based on flag/env var
|
||||
if reasoning_effort == "none":
|
||||
return Reasoning(effort="none", summary="detailed") if auto_summary_enabled else Reasoning(effort="none") # type: ignore
|
||||
return (
|
||||
Reasoning(effort="none", summary="detailed")
|
||||
if auto_summary_enabled
|
||||
else Reasoning(effort="none")
|
||||
) # type: ignore
|
||||
elif reasoning_effort == "high":
|
||||
return (
|
||||
Reasoning(effort="high", summary="detailed")
|
||||
|
|
@ -1029,7 +1035,11 @@ class LiteLLMResponsesTransformationHandler(CompletionTransformationBridge):
|
|||
else Reasoning(effort="high")
|
||||
)
|
||||
elif reasoning_effort == "xhigh":
|
||||
return Reasoning(effort="xhigh", summary="detailed") if auto_summary_enabled else Reasoning(effort="xhigh") # type: ignore[typeddict-item]
|
||||
return (
|
||||
Reasoning(effort="xhigh", summary="detailed")
|
||||
if auto_summary_enabled
|
||||
else Reasoning(effort="xhigh")
|
||||
) # type: ignore[typeddict-item]
|
||||
elif reasoning_effort == "medium":
|
||||
return (
|
||||
Reasoning(effort="medium", summary="detailed")
|
||||
|
|
|
|||
|
|
@ -296,7 +296,8 @@ DEFAULT_SSL_CIPHERS = os.getenv(
|
|||
"ECDHE-ECDSA-AES256-GCM-SHA384:"
|
||||
"ECDHE-ECDSA-AES128-GCM-SHA256:"
|
||||
# Priority 3: Additional modern ciphers (good balance)
|
||||
"ECDHE-RSA-CHACHA20-POLY1305:" "ECDHE-ECDSA-CHACHA20-POLY1305:"
|
||||
"ECDHE-RSA-CHACHA20-POLY1305:"
|
||||
"ECDHE-ECDSA-CHACHA20-POLY1305:"
|
||||
# Priority 4: Widely compatible fallbacks (slower but universally supported)
|
||||
"ECDHE-RSA-AES256-SHA384:" # Common fallback
|
||||
"ECDHE-RSA-AES128-SHA256:" # Very widely supported
|
||||
|
|
@ -885,31 +886,29 @@ openai_compatible_providers: List = [
|
|||
"pinstripes", # Pinstripes - JSON-configured provider
|
||||
"darkbloom",
|
||||
]
|
||||
openai_text_completion_compatible_providers: List = (
|
||||
[ # providers that support `/v1/completions`
|
||||
"together_ai",
|
||||
"fireworks_ai",
|
||||
"hosted_vllm",
|
||||
"meta_llama",
|
||||
"llamafile",
|
||||
"featherless_ai",
|
||||
"nebius",
|
||||
"dashscope",
|
||||
"modelscope",
|
||||
"moonshot",
|
||||
"publicai",
|
||||
"synthetic",
|
||||
"tensormesh",
|
||||
"apertis",
|
||||
"nano-gpt",
|
||||
"poe",
|
||||
"chutes",
|
||||
"v0",
|
||||
"lambda_ai",
|
||||
"hyperbolic",
|
||||
"wandb",
|
||||
]
|
||||
)
|
||||
openai_text_completion_compatible_providers: List = [ # providers that support `/v1/completions`
|
||||
"together_ai",
|
||||
"fireworks_ai",
|
||||
"hosted_vllm",
|
||||
"meta_llama",
|
||||
"llamafile",
|
||||
"featherless_ai",
|
||||
"nebius",
|
||||
"dashscope",
|
||||
"modelscope",
|
||||
"moonshot",
|
||||
"publicai",
|
||||
"synthetic",
|
||||
"tensormesh",
|
||||
"apertis",
|
||||
"nano-gpt",
|
||||
"poe",
|
||||
"chutes",
|
||||
"v0",
|
||||
"lambda_ai",
|
||||
"hyperbolic",
|
||||
"wandb",
|
||||
]
|
||||
_openai_like_providers: List = [
|
||||
"predibase",
|
||||
"databricks",
|
||||
|
|
|
|||
|
|
@ -1020,7 +1020,7 @@ def _apply_cost_discount(
|
|||
|
||||
if verbose_logger.isEnabledFor(logging.DEBUG):
|
||||
verbose_logger.debug(
|
||||
f"Applied {discount_percent*100}% discount to {custom_llm_provider}: "
|
||||
f"Applied {discount_percent * 100}% discount to {custom_llm_provider}: "
|
||||
f"${original_cost:.6f} -> ${final_cost:.6f} (saved ${discount_amount:.6f})"
|
||||
)
|
||||
|
||||
|
|
@ -1088,7 +1088,7 @@ def _apply_cost_margin(
|
|||
verbose_logger.debug(
|
||||
f"Applied margin to {custom_llm_provider or 'global'}: "
|
||||
f"${original_cost:.6f} -> ${final_cost:.6f} "
|
||||
f"(margin: {margin_percent*100 if margin_percent > 0 else 0}% + ${margin_fixed_amount:.6f} = ${margin_total_amount:.6f})"
|
||||
f"(margin: {margin_percent * 100 if margin_percent > 0 else 0}% + ${margin_fixed_amount:.6f} = ${margin_total_amount:.6f})"
|
||||
)
|
||||
|
||||
return final_cost, margin_percent, margin_fixed_amount, margin_total_amount
|
||||
|
|
@ -1621,7 +1621,9 @@ def completion_cost(
|
|||
model in litellm.replicate_models or "replicate" in model
|
||||
) and model not in litellm.model_cost:
|
||||
# for unmapped replicate model, default to replicate's time tracking logic
|
||||
return get_replicate_completion_pricing(completion_response, total_time) # type: ignore
|
||||
return get_replicate_completion_pricing(
|
||||
completion_response, total_time
|
||||
) # type: ignore
|
||||
|
||||
if model is None:
|
||||
raise ValueError(
|
||||
|
|
|
|||
|
|
@ -264,7 +264,9 @@ def create_file(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_file", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_file", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
@ -435,7 +437,10 @@ def file_retrieve(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread",
|
||||
url="https://github.com/BerriAI/litellm",
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
|
||||
|
|
@ -618,7 +623,10 @@ def file_delete(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread",
|
||||
url="https://github.com/BerriAI/litellm",
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return cast(FileDeleted, response)
|
||||
|
|
@ -786,7 +794,9 @@ def file_list(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="file_list", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="file_list", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
@ -1037,7 +1047,9 @@ def file_content(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
@ -1118,7 +1130,9 @@ def file_content_streaming(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -245,7 +245,11 @@ def create_fine_tuning_job(
|
|||
)
|
||||
# Azure OpenAI
|
||||
elif custom_llm_provider == "azure":
|
||||
api_base = optional_params.api_base or litellm.api_base or get_secret_str("AZURE_API_BASE") # type: ignore
|
||||
api_base = (
|
||||
optional_params.api_base
|
||||
or litellm.api_base
|
||||
or get_secret_str("AZURE_API_BASE")
|
||||
) # type: ignore
|
||||
|
||||
api_version = (
|
||||
optional_params.api_version
|
||||
|
|
@ -340,7 +344,9 @@ def create_fine_tuning_job(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
@ -458,7 +464,11 @@ def cancel_fine_tuning_job(
|
|||
)
|
||||
# Azure OpenAI
|
||||
elif custom_llm_provider == "azure":
|
||||
api_base = optional_params.api_base or litellm.api_base or get_secret("AZURE_API_BASE") # type: ignore
|
||||
api_base = (
|
||||
optional_params.api_base
|
||||
or litellm.api_base
|
||||
or get_secret("AZURE_API_BASE")
|
||||
) # type: ignore
|
||||
|
||||
api_version = (
|
||||
optional_params.api_version
|
||||
|
|
@ -500,7 +510,9 @@ def cancel_fine_tuning_job(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
@ -621,7 +633,11 @@ def list_fine_tuning_jobs(
|
|||
)
|
||||
# Azure OpenAI
|
||||
elif custom_llm_provider == "azure":
|
||||
api_base = optional_params.api_base or litellm.api_base or get_secret_str("AZURE_API_BASE") # type: ignore
|
||||
api_base = (
|
||||
optional_params.api_base
|
||||
or litellm.api_base
|
||||
or get_secret_str("AZURE_API_BASE")
|
||||
) # type: ignore
|
||||
|
||||
api_version = (
|
||||
optional_params.api_version
|
||||
|
|
@ -664,7 +680,9 @@ def list_fine_tuning_jobs(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="create_thread", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="create_thread", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
@ -776,7 +794,11 @@ def retrieve_fine_tuning_job(
|
|||
)
|
||||
# Azure OpenAI
|
||||
elif custom_llm_provider == "azure":
|
||||
api_base = optional_params.api_base or litellm.api_base or get_secret_str("AZURE_API_BASE") # type: ignore
|
||||
api_base = (
|
||||
optional_params.api_base
|
||||
or litellm.api_base
|
||||
or get_secret_str("AZURE_API_BASE")
|
||||
) # type: ignore
|
||||
|
||||
api_version = (
|
||||
optional_params.api_version
|
||||
|
|
@ -818,7 +840,10 @@ def retrieve_fine_tuning_job(
|
|||
response=httpx.Response(
|
||||
status_code=400,
|
||||
content="Unsupported provider",
|
||||
request=httpx.Request(method="retrieve_fine_tuning_job", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="retrieve_fine_tuning_job",
|
||||
url="https://github.com/BerriAI/litellm",
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
return response
|
||||
|
|
|
|||
|
|
@ -726,9 +726,9 @@ class GoogleGenAIAdapter:
|
|||
wrapper.accumulated_tool_calls[tool_call_index]["name"] = function_name
|
||||
|
||||
if args_chunk:
|
||||
wrapper.accumulated_tool_calls[tool_call_index][
|
||||
"arguments"
|
||||
] += args_chunk
|
||||
wrapper.accumulated_tool_calls[tool_call_index]["arguments"] += (
|
||||
args_chunk
|
||||
)
|
||||
|
||||
# Attempt to parse and emit a complete tool call
|
||||
accumulated_data = wrapper.accumulated_tool_calls[tool_call_index]
|
||||
|
|
|
|||
|
|
@ -880,20 +880,20 @@ def image_edit(
|
|||
|
||||
local_vars.update(kwargs)
|
||||
# Get ImageEditOptionalRequestParams with only valid parameters
|
||||
image_edit_optional_params: (
|
||||
ImageEditOptionalRequestParams
|
||||
) = _get_ImageEditRequestUtils().get_requested_image_edit_optional_param(
|
||||
local_vars
|
||||
image_edit_optional_params: ImageEditOptionalRequestParams = (
|
||||
_get_ImageEditRequestUtils().get_requested_image_edit_optional_param(
|
||||
local_vars
|
||||
)
|
||||
)
|
||||
# Get optional parameters for the responses API
|
||||
image_edit_request_params: (
|
||||
Dict
|
||||
) = _get_ImageEditRequestUtils().get_optional_params_image_edit(
|
||||
model=model,
|
||||
image_edit_provider_config=image_edit_provider_config,
|
||||
image_edit_optional_params=image_edit_optional_params,
|
||||
drop_params=kwargs.get("drop_params"),
|
||||
additional_drop_params=kwargs.get("additional_drop_params"),
|
||||
image_edit_request_params: Dict = (
|
||||
_get_ImageEditRequestUtils().get_optional_params_image_edit(
|
||||
model=model,
|
||||
image_edit_provider_config=image_edit_provider_config,
|
||||
image_edit_optional_params=image_edit_optional_params,
|
||||
drop_params=kwargs.get("drop_params"),
|
||||
additional_drop_params=kwargs.get("additional_drop_params"),
|
||||
)
|
||||
)
|
||||
|
||||
# Pre Call logging
|
||||
|
|
|
|||
|
|
@ -104,10 +104,10 @@ class AlertingHangingRequestCheck:
|
|||
)
|
||||
|
||||
for request_id in hanging_requests:
|
||||
hanging_request_data: Optional[HangingRequestData] = (
|
||||
await self.hanging_request_cache.async_get_cache(
|
||||
key=request_id,
|
||||
)
|
||||
hanging_request_data: Optional[
|
||||
HangingRequestData
|
||||
] = await self.hanging_request_cache.async_get_cache(
|
||||
key=request_id,
|
||||
)
|
||||
|
||||
if hanging_request_data is None:
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ class SlackAlerting(CustomBatchLogger):
|
|||
return
|
||||
|
||||
for api_base, latency in _deployment_latency_map.items():
|
||||
_message_to_send += f"\n{api_base}: {round(latency,2)}s"
|
||||
_message_to_send += f"\n{api_base}: {round(latency, 2)}s"
|
||||
_message_to_send = "```" + _message_to_send + "```"
|
||||
return _message_to_send
|
||||
|
||||
|
|
@ -272,7 +272,7 @@ class SlackAlerting(CustomBatchLogger):
|
|||
if litellm.turn_off_message_logging or litellm.redact_messages_in_exceptions:
|
||||
messages = "Message not logged. litellm.redact_messages_in_exceptions=True"
|
||||
request_info = f"\nRequest Model: `{model}`\nAPI Base: `{api_base}`\nMessages: `{messages}`"
|
||||
slow_message = f"`Responses are slow - {round(time_difference_float,2)}s response time > Alerting threshold: {self.alerting_threshold}s`"
|
||||
slow_message = f"`Responses are slow - {round(time_difference_float, 2)}s response time > Alerting threshold: {self.alerting_threshold}s`"
|
||||
alerting_metadata: dict = {}
|
||||
if time_difference_float > self.alerting_threshold:
|
||||
# add deployment latencies to alert
|
||||
|
|
@ -460,7 +460,7 @@ class SlackAlerting(CustomBatchLogger):
|
|||
if api_base is None:
|
||||
api_base = ""
|
||||
value = replaced_failed_values[top_5_failed[i]]
|
||||
message += f"\t{i+1}. Deployment: `{deployment_name}`, Failed Requests: `{value}`, API Base: `{api_base}`\n"
|
||||
message += f"\t{i + 1}. Deployment: `{deployment_name}`, Failed Requests: `{value}`, API Base: `{api_base}`\n"
|
||||
|
||||
message += "\n\n*😅 Top Slowest Deployments:*\n\n"
|
||||
if not top_5_slowest:
|
||||
|
|
@ -479,7 +479,7 @@ class SlackAlerting(CustomBatchLogger):
|
|||
),
|
||||
)
|
||||
value = round(replaced_slowest_values[top_5_slowest[i]], 3)
|
||||
message += f"\t{i+1}. Deployment: `{deployment_name}`, Latency per output token: `{value}s/token`, API Base: `{api_base}`\n\n"
|
||||
message += f"\t{i + 1}. Deployment: `{deployment_name}`, Latency per output token: `{value}s/token`, API Base: `{api_base}`\n\n"
|
||||
|
||||
# cache cleanup -> reset values to 0
|
||||
latency_cache_keys = [(key, 0) for key in latency_keys]
|
||||
|
|
@ -595,9 +595,7 @@ class SlackAlerting(CustomBatchLogger):
|
|||
"projected_limit_exceeded",
|
||||
"soft_budget_crossed",
|
||||
]
|
||||
] = (
|
||||
"projected_limit_exceeded" if type == "projected_limit_exceeded" else None
|
||||
)
|
||||
] = "projected_limit_exceeded" if type == "projected_limit_exceeded" else None
|
||||
|
||||
webhook_event: Optional[WebhookEvent] = None
|
||||
|
||||
|
|
@ -854,9 +852,9 @@ class SlackAlerting(CustomBatchLogger):
|
|||
### UNIQUE CACHE KEY ###
|
||||
cache_key = provider + region_name
|
||||
|
||||
outage_value: Optional[ProviderRegionOutageModel] = (
|
||||
await self.internal_usage_cache.async_get_cache(key=cache_key)
|
||||
)
|
||||
outage_value: Optional[
|
||||
ProviderRegionOutageModel
|
||||
] = await self.internal_usage_cache.async_get_cache(key=cache_key)
|
||||
|
||||
# Convert deployment_ids back to set if it was stored as a list
|
||||
if outage_value is not None:
|
||||
|
|
@ -981,7 +979,9 @@ class SlackAlerting(CustomBatchLogger):
|
|||
max_alerts_size = 10
|
||||
"""
|
||||
try:
|
||||
outage_value: Optional[OutageModel] = await self.internal_usage_cache.async_get_cache(key=deployment_id) # type: ignore
|
||||
outage_value: Optional[
|
||||
OutageModel
|
||||
] = await self.internal_usage_cache.async_get_cache(key=deployment_id) # type: ignore
|
||||
if (
|
||||
getattr(exception, "status_code", None) is None
|
||||
or (
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ class BraintrustLogger(CustomLogger):
|
|||
"Authorization": "Bearer " + self.api_key,
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
self._project_id_cache: Dict[str, str] = (
|
||||
{}
|
||||
) # Cache mapping project names to IDs
|
||||
self._project_id_cache: Dict[
|
||||
str, str
|
||||
] = {} # Cache mapping project names to IDs
|
||||
self.global_braintrust_http_handler = get_async_httpx_client(
|
||||
llm_provider=httpxSpecialProvider.LoggingCallback
|
||||
)
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ def create_mock_braintrust_client():
|
|||
create_mock_braintrust_factory_client()
|
||||
|
||||
verbose_logger.debug(
|
||||
f"[BRAINTRUST MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS*1000:.0f}ms"
|
||||
f"[BRAINTRUST MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS * 1000:.0f}ms"
|
||||
)
|
||||
verbose_logger.debug(
|
||||
"[BRAINTRUST MOCK] Braintrust mock client initialization complete"
|
||||
|
|
|
|||
|
|
@ -981,7 +981,9 @@ class CustomLogger: # https://docs.litellm.ai/docs/observability/custom_callbac
|
|||
verbose_logger.debug(
|
||||
f"Incrementing callback failure metric for {callback_name}"
|
||||
)
|
||||
callback_obj.increment_callback_logging_failure(callback_name=callback_name) # type: ignore
|
||||
callback_obj.increment_callback_logging_failure(
|
||||
callback_name=callback_name
|
||||
) # type: ignore
|
||||
return
|
||||
|
||||
verbose_logger.debug(
|
||||
|
|
|
|||
|
|
@ -256,7 +256,9 @@ class DatadogMetricsLogger(CustomBatchLogger):
|
|||
headers["Content-Encoding"] = "gzip"
|
||||
|
||||
response = await self.async_client.post(
|
||||
self.upload_url, content=compressed_data, headers=headers # type: ignore
|
||||
self.upload_url,
|
||||
content=compressed_data,
|
||||
headers=headers, # type: ignore
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ class FocusVantageDestination(FocusDestination):
|
|||
async def _upload_csv(
|
||||
self, client: AsyncHTTPHandler, csv_bytes: bytes, filename: str
|
||||
) -> None:
|
||||
url = f"{self.base_url}/v2/integrations/" f"{self.integration_token}/costs.csv"
|
||||
url = f"{self.base_url}/v2/integrations/{self.integration_token}/costs.csv"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.api_key}",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -154,7 +154,10 @@ def create_mock_gcs_client():
|
|||
|
||||
This function is idempotent - it only initializes mocks once, even if called multiple times.
|
||||
"""
|
||||
global _original_async_handler_get, _original_async_handler_delete, _mocks_initialized
|
||||
global \
|
||||
_original_async_handler_get, \
|
||||
_original_async_handler_delete, \
|
||||
_mocks_initialized
|
||||
|
||||
# Use factory for POST handler
|
||||
_create_mock_gcs_post()
|
||||
|
|
@ -179,7 +182,7 @@ def create_mock_gcs_client():
|
|||
verbose_logger.debug("[GCS MOCK] Patched AsyncHTTPHandler.delete")
|
||||
|
||||
verbose_logger.debug(
|
||||
f"[GCS MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS*1000:.0f}ms"
|
||||
f"[GCS MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS * 1000:.0f}ms"
|
||||
)
|
||||
verbose_logger.debug("[GCS MOCK] GCS mock client initialization complete")
|
||||
|
||||
|
|
|
|||
|
|
@ -372,7 +372,9 @@ class GitLabPromptManager(CustomPromptManagement):
|
|||
if parsed_messages:
|
||||
final_messages: List[AllMessageValues] = parsed_messages
|
||||
else:
|
||||
final_messages = [{"role": "user", "content": rendered_prompt}] + messages # type: ignore
|
||||
final_messages = [
|
||||
{"role": "user", "content": rendered_prompt}
|
||||
] + messages # type: ignore
|
||||
|
||||
if litellm_params is None:
|
||||
litellm_params = {}
|
||||
|
|
@ -412,24 +414,41 @@ class GitLabPromptManager(CustomPromptManagement):
|
|||
low = line.lower()
|
||||
if low.startswith("system:"):
|
||||
if current_role and current_content:
|
||||
messages.append({"role": current_role, "content": "\n".join(current_content).strip()}) # type: ignore
|
||||
messages.append(
|
||||
{
|
||||
"role": current_role,
|
||||
"content": "\n".join(current_content).strip(),
|
||||
}
|
||||
) # type: ignore
|
||||
current_role = "system"
|
||||
current_content = [line[7:].strip()]
|
||||
elif low.startswith("user:"):
|
||||
if current_role and current_content:
|
||||
messages.append({"role": current_role, "content": "\n".join(current_content).strip()}) # type: ignore
|
||||
messages.append(
|
||||
{
|
||||
"role": current_role,
|
||||
"content": "\n".join(current_content).strip(),
|
||||
}
|
||||
) # type: ignore
|
||||
current_role = "user"
|
||||
current_content = [line[5:].strip()]
|
||||
elif low.startswith("assistant:"):
|
||||
if current_role and current_content:
|
||||
messages.append({"role": current_role, "content": "\n".join(current_content).strip()}) # type: ignore
|
||||
messages.append(
|
||||
{
|
||||
"role": current_role,
|
||||
"content": "\n".join(current_content).strip(),
|
||||
}
|
||||
) # type: ignore
|
||||
current_role = "assistant"
|
||||
current_content = [line[10:].strip()]
|
||||
else:
|
||||
current_content.append(line)
|
||||
|
||||
if current_role and current_content:
|
||||
messages.append({"role": current_role, "content": "\n".join(current_content).strip()}) # type: ignore
|
||||
messages.append(
|
||||
{"role": current_role, "content": "\n".join(current_content).strip()}
|
||||
) # type: ignore
|
||||
if not messages and prompt_content.strip():
|
||||
messages = [{"role": "user", "content": prompt_content.strip()}] # type: ignore
|
||||
return messages
|
||||
|
|
|
|||
|
|
@ -131,9 +131,9 @@ class LagoLogger(CustomLogger):
|
|||
|
||||
def log_success_event(self, kwargs, response_obj, start_time, end_time):
|
||||
_url = os.getenv("LAGO_API_BASE")
|
||||
assert _url is not None and isinstance(
|
||||
_url, str
|
||||
), "LAGO_API_BASE missing or not set correctly. LAGO_API_BASE={}".format(_url)
|
||||
assert _url is not None and isinstance(_url, str), (
|
||||
"LAGO_API_BASE missing or not set correctly. LAGO_API_BASE={}".format(_url)
|
||||
)
|
||||
if _url.endswith("/"):
|
||||
_url += "api/v1/events"
|
||||
else:
|
||||
|
|
@ -165,10 +165,10 @@ class LagoLogger(CustomLogger):
|
|||
try:
|
||||
verbose_logger.debug("ENTERS LAGO CALLBACK")
|
||||
_url = os.getenv("LAGO_API_BASE")
|
||||
assert _url is not None and isinstance(
|
||||
_url, str
|
||||
), "LAGO_API_BASE missing or not set correctly. LAGO_API_BASE={}".format(
|
||||
_url
|
||||
assert _url is not None and isinstance(_url, str), (
|
||||
"LAGO_API_BASE missing or not set correctly. LAGO_API_BASE={}".format(
|
||||
_url
|
||||
)
|
||||
)
|
||||
if _url.endswith("/"):
|
||||
_url += "api/v1/events"
|
||||
|
|
|
|||
|
|
@ -86,9 +86,9 @@ class LangFuseHandler:
|
|||
if globalLangfuseLogger is not None:
|
||||
return globalLangfuseLogger
|
||||
|
||||
credentials_dict: Dict[str, Any] = (
|
||||
{}
|
||||
) # the global langfuse logger uses Environment Variables, there are no dynamic credentials
|
||||
credentials_dict: Dict[
|
||||
str, Any
|
||||
] = {} # the global langfuse logger uses Environment Variables, there are no dynamic credentials
|
||||
globalLangfuseLogger = in_memory_dynamic_logger_cache.get_cache(
|
||||
credentials=credentials_dict,
|
||||
service_name="langfuse",
|
||||
|
|
|
|||
|
|
@ -65,8 +65,7 @@ class LangsmithLogger(CustomBatchLogger):
|
|||
langsmith_tenant_id=langsmith_tenant_id,
|
||||
)
|
||||
self.sampling_rate: float = (
|
||||
langsmith_sampling_rate
|
||||
or float(os.getenv("LANGSMITH_SAMPLING_RATE")) # type: ignore
|
||||
langsmith_sampling_rate or float(os.getenv("LANGSMITH_SAMPLING_RATE")) # type: ignore
|
||||
if os.getenv("LANGSMITH_SAMPLING_RATE") is not None
|
||||
and os.getenv("LANGSMITH_SAMPLING_RATE").strip().isdigit() # type: ignore
|
||||
else 1.0
|
||||
|
|
|
|||
|
|
@ -232,7 +232,11 @@ def create_mock_client_factory(config: MockClientConfig):
|
|||
# Create mock client initialization function
|
||||
def create_mock_client():
|
||||
"""Initialize the mock client by patching HTTP handlers."""
|
||||
nonlocal _original_async_handler_post, _original_sync_client_post, _original_http_handler_post, _mocks_initialized
|
||||
nonlocal \
|
||||
_original_async_handler_post, \
|
||||
_original_sync_client_post, \
|
||||
_original_http_handler_post, \
|
||||
_mocks_initialized
|
||||
|
||||
if _mocks_initialized:
|
||||
return
|
||||
|
|
@ -261,7 +265,7 @@ def create_mock_client_factory(config: MockClientConfig):
|
|||
verbose_logger.debug(f"[{config.name} MOCK] Patched HTTPHandler.post")
|
||||
|
||||
verbose_logger.debug(
|
||||
f"[{config.name} MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS*1000:.0f}ms"
|
||||
f"[{config.name} MOCK] Mock latency set to {_MOCK_LATENCY_SECONDS * 1000:.0f}ms"
|
||||
)
|
||||
verbose_logger.debug(
|
||||
f"[{config.name} MOCK] {config.name} mock client initialization complete"
|
||||
|
|
|
|||
|
|
@ -174,7 +174,9 @@ class OpikLogger(CustomBatchLogger):
|
|||
) -> None:
|
||||
try:
|
||||
response = self.sync_httpx_client.post(
|
||||
url=url, headers=headers, json=batch # type: ignore
|
||||
url=url,
|
||||
headers=headers,
|
||||
json=batch, # type: ignore
|
||||
)
|
||||
response.raise_for_status()
|
||||
if response.status_code != 204:
|
||||
|
|
@ -264,7 +266,9 @@ class OpikLogger(CustomBatchLogger):
|
|||
) -> None:
|
||||
try:
|
||||
response = await self.async_httpx_client.post(
|
||||
url=url, headers=headers, json=batch # type: ignore
|
||||
url=url,
|
||||
headers=headers,
|
||||
json=batch, # type: ignore
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ def resolve_mappers(names: Iterable[str]) -> list[AttributeMapper]:
|
|||
factory = _MAPPER_BY_NAME.get(name)
|
||||
if factory is None:
|
||||
raise ValueError(
|
||||
f"unknown mapper name {name!r}; known: " f"{sorted(_MAPPER_BY_NAME)}"
|
||||
f"unknown mapper name {name!r}; known: {sorted(_MAPPER_BY_NAME)}"
|
||||
)
|
||||
out.append(factory())
|
||||
return out
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ from litellm.integrations.otel.model.spans import db_system
|
|||
|
||||
|
||||
class GenAIMapper:
|
||||
|
||||
_LLM_CALL_ATTRS: dict[str, Callable[[LLMCallSpanData], AttrValue | None]] = {
|
||||
GenAI.OPERATION_NAME: lambda d: d.operation.value,
|
||||
GenAI.PROVIDER_NAME: lambda d: d.provider or None,
|
||||
|
|
@ -81,9 +80,13 @@ class GenAIMapper:
|
|||
f"{LiteLLM.COST_PREFIX}original": lambda d: d.cost.original,
|
||||
f"{LiteLLM.COST_PREFIX}discount_amount": lambda d: d.cost.discount_amount,
|
||||
f"{LiteLLM.COST_PREFIX}discount_percent": lambda d: d.cost.discount_percent,
|
||||
f"{LiteLLM.COST_PREFIX}margin_fixed_amount": lambda d: d.cost.margin_fixed_amount,
|
||||
f"{LiteLLM.COST_PREFIX}margin_fixed_amount": lambda d: (
|
||||
d.cost.margin_fixed_amount
|
||||
),
|
||||
f"{LiteLLM.COST_PREFIX}margin_percent": lambda d: d.cost.margin_percent,
|
||||
f"{LiteLLM.COST_PREFIX}margin_total_amount": lambda d: d.cost.margin_total_amount,
|
||||
f"{LiteLLM.COST_PREFIX}margin_total_amount": lambda d: (
|
||||
d.cost.margin_total_amount
|
||||
),
|
||||
LiteLLM.REQUEST_STREAMING: lambda d: d.is_streaming,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ from litellm.integrations.otel.model.payloads import (
|
|||
|
||||
|
||||
class LangfuseMapper:
|
||||
|
||||
_LLM_CALL_ATTRS: dict[str, Callable[[LLMCallSpanData], AttrValue | None]] = {
|
||||
"langfuse.observation.type": lambda d: "generation",
|
||||
"langfuse.observation.model.name": lambda d: d.request_model or None,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ from litellm.integrations.otel.model.payloads import LLMCallSpanData
|
|||
|
||||
|
||||
class LangtraceMapper:
|
||||
|
||||
_LLM_CALL_ATTRS: dict[str, Callable[[LLMCallSpanData], AttrValue | None]] = {
|
||||
"gen_ai.operation.name": lambda d: "chat",
|
||||
"langtrace.service.name": lambda d: d.provider or None,
|
||||
|
|
|
|||
|
|
@ -29,13 +29,15 @@ _PROMOTABLE: Final[
|
|||
] = {
|
||||
LiteLLM.TEAM_ID: lambda identity, model, team_metadata_keys: identity.team_id,
|
||||
LiteLLM.TEAM_ALIAS: lambda identity, model, team_metadata_keys: identity.team_alias,
|
||||
LiteLLM.TEAM_METADATA: lambda identity, model, team_metadata_keys: _filtered_team_metadata_json(
|
||||
identity.team_metadata, team_metadata_keys
|
||||
LiteLLM.TEAM_METADATA: lambda identity, model, team_metadata_keys: (
|
||||
_filtered_team_metadata_json(identity.team_metadata, team_metadata_keys)
|
||||
),
|
||||
LiteLLM.KEY_HASH: lambda identity, model, team_metadata_keys: identity.key_hash,
|
||||
LiteLLM.END_USER: lambda identity, model, team_metadata_keys: identity.end_user,
|
||||
GenAI.REQUEST_MODEL: lambda identity, model, team_metadata_keys: model,
|
||||
LiteLLM.PROVIDER_MODEL: lambda identity, model, team_metadata_keys: identity.provider_model,
|
||||
LiteLLM.PROVIDER_MODEL: lambda identity, model, team_metadata_keys: (
|
||||
identity.provider_model
|
||||
),
|
||||
}
|
||||
|
||||
# Keys promoted by default (a subset of ``_PROMOTABLE``). ``END_USER`` is
|
||||
|
|
|
|||
|
|
@ -3237,7 +3237,9 @@ class PrometheusLogger(CustomLogger):
|
|||
)
|
||||
return
|
||||
|
||||
async def fetch_keys(page_size: int, page: int) -> Tuple[
|
||||
async def fetch_keys(
|
||||
page_size: int, page: int
|
||||
) -> Tuple[
|
||||
List[Union[str, UserAPIKeyAuth, LiteLLM_DeletedVerificationToken]],
|
||||
Optional[int],
|
||||
]:
|
||||
|
|
|
|||
|
|
@ -550,8 +550,7 @@ class RubrikLogger(CustomGuardrail, CustomBatchLogger):
|
|||
"response": response_data,
|
||||
}
|
||||
verbose_logger.debug(
|
||||
f"Sending request to tool blocking service: "
|
||||
f"{self.tool_blocking_endpoint}"
|
||||
f"Sending request to tool blocking service: {self.tool_blocking_endpoint}"
|
||||
)
|
||||
http_response = await self.tool_blocking_client.post(
|
||||
self.tool_blocking_endpoint,
|
||||
|
|
|
|||
|
|
@ -88,12 +88,12 @@ class VectorStorePreCallHook(CustomLogger):
|
|||
pass
|
||||
|
||||
# Use database fallback to ensure synchronization across instances
|
||||
vector_stores_to_run: List[LiteLLM_ManagedVectorStore] = (
|
||||
await litellm.vector_store_registry.pop_vector_stores_to_run_with_db_fallback(
|
||||
non_default_params=non_default_params,
|
||||
tools=tools,
|
||||
prisma_client=prisma_client,
|
||||
)
|
||||
vector_stores_to_run: List[
|
||||
LiteLLM_ManagedVectorStore
|
||||
] = await litellm.vector_store_registry.pop_vector_stores_to_run_with_db_fallback(
|
||||
non_default_params=non_default_params,
|
||||
tools=tools,
|
||||
prisma_client=prisma_client,
|
||||
)
|
||||
|
||||
if not vector_stores_to_run:
|
||||
|
|
|
|||
|
|
@ -361,9 +361,9 @@ def safe_deep_copy(data):
|
|||
"litellm_metadata" in data
|
||||
and "litellm_parent_otel_span" in data["litellm_metadata"]
|
||||
):
|
||||
data["litellm_metadata"][
|
||||
"litellm_parent_otel_span"
|
||||
] = litellm_parent_otel_span
|
||||
data["litellm_metadata"]["litellm_parent_otel_span"] = (
|
||||
litellm_parent_otel_span
|
||||
)
|
||||
return new_data
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -272,8 +272,8 @@ def _map_openai_exception(
|
|||
else:
|
||||
message = str(original_exception)
|
||||
|
||||
if message is not None and isinstance(
|
||||
message, str
|
||||
if (
|
||||
message is not None and isinstance(message, str)
|
||||
): # done to prevent user-confusion. Relevant issue - https://github.com/BerriAI/litellm/issues/1414
|
||||
message = message.replace("OPENAI", custom_llm_provider.upper())
|
||||
message = message.replace(
|
||||
|
|
@ -726,7 +726,6 @@ def _map_openai_like_exception(
|
|||
extra_information: str,
|
||||
) -> None:
|
||||
if "authorization denied for" in error_str:
|
||||
|
||||
# Predibase returns the raw API Key in the response - this block ensures it's not returned in the exception
|
||||
if (
|
||||
error_str is not None
|
||||
|
|
@ -1161,7 +1160,9 @@ def _map_vertex_exception(
|
|||
response=httpx.Response(
|
||||
status_code=500,
|
||||
content=str(original_exception),
|
||||
request=httpx.Request(method="completion", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="completion", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
litellm_debug_info=extra_information,
|
||||
)
|
||||
|
|
@ -1327,7 +1328,9 @@ def _map_vertex_exception(
|
|||
response=httpx.Response(
|
||||
status_code=500,
|
||||
content=str(original_exception),
|
||||
request=httpx.Request(method="completion", url="https://github.com/BerriAI/litellm"), # type: ignore
|
||||
request=httpx.Request(
|
||||
method="completion", url="https://github.com/BerriAI/litellm"
|
||||
), # type: ignore
|
||||
),
|
||||
)
|
||||
if original_exception.status_code == 502:
|
||||
|
|
@ -1965,13 +1968,9 @@ def _map_azure_exception(
|
|||
# content policy violation even when the top-level
|
||||
# code is generic (e.g. "invalid_request_error").
|
||||
if azure_error_code != "content_policy_violation":
|
||||
_inner = body_dict["error"].get(
|
||||
"inner_error"
|
||||
) or body_dict[ # type: ignore[index]
|
||||
_inner = body_dict["error"].get("inner_error") or body_dict[ # type: ignore[index]
|
||||
"error"
|
||||
].get(
|
||||
"innererror"
|
||||
) # type: ignore[index]
|
||||
].get("innererror") # type: ignore[index]
|
||||
if (
|
||||
isinstance(_inner, dict)
|
||||
and _inner.get("code") == "ResponsibleAIPolicyViolation"
|
||||
|
|
|
|||
|
|
@ -616,7 +616,11 @@ def _get_openai_compatible_provider_info(
|
|||
return model, "aiohttp_openai", api_key, api_base
|
||||
elif custom_llm_provider == "anyscale":
|
||||
# anyscale is openai compatible, we just need to set this to custom_openai and have the api_base be https://api.endpoints.anyscale.com/v1
|
||||
api_base = api_base or get_secret_str("ANYSCALE_API_BASE") or "https://api.endpoints.anyscale.com/v1" # type: ignore
|
||||
api_base = (
|
||||
api_base
|
||||
or get_secret_str("ANYSCALE_API_BASE")
|
||||
or "https://api.endpoints.anyscale.com/v1"
|
||||
) # type: ignore
|
||||
dynamic_api_key = api_key or get_secret_str("ANYSCALE_API_KEY")
|
||||
elif custom_llm_provider == "deepinfra":
|
||||
(
|
||||
|
|
@ -709,9 +713,7 @@ def _get_openai_compatible_provider_info(
|
|||
) # type: ignore
|
||||
dynamic_api_key = api_key or get_secret_str("NEBIUS_API_KEY")
|
||||
elif custom_llm_provider == "ollama":
|
||||
api_base = (
|
||||
api_base or get_secret("OLLAMA_API_BASE") or "http://localhost:11434"
|
||||
) # type: ignore
|
||||
api_base = api_base or get_secret("OLLAMA_API_BASE") or "http://localhost:11434" # type: ignore
|
||||
dynamic_api_key = api_key or get_secret_str("OLLAMA_API_KEY")
|
||||
elif (custom_llm_provider == "ai21_chat") or (
|
||||
custom_llm_provider == "ai21" and model in litellm.ai21_chat_models
|
||||
|
|
|
|||
|
|
@ -293,7 +293,17 @@ def _get_cached_prometheus_logger():
|
|||
|
||||
|
||||
class Logging(LiteLLMLoggingBaseClass):
|
||||
global supabaseClient, promptLayerLogger, weightsBiasesLogger, logfireLogger, capture_exception, add_breadcrumb, lunaryLogger, logfireLogger, prometheusLogger, slack_app
|
||||
global \
|
||||
supabaseClient, \
|
||||
promptLayerLogger, \
|
||||
weightsBiasesLogger, \
|
||||
logfireLogger, \
|
||||
capture_exception, \
|
||||
add_breadcrumb, \
|
||||
lunaryLogger, \
|
||||
logfireLogger, \
|
||||
prometheusLogger, \
|
||||
slack_app
|
||||
custom_pricing: bool = False
|
||||
stream_options = None
|
||||
litellm_request_debug: bool = False
|
||||
|
|
@ -359,9 +369,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
|
||||
|
|
@ -903,8 +913,11 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
self.model_call_details["prompt_integration"] = logger.__class__.__name__
|
||||
return logger
|
||||
|
||||
if anthropic_cache_control_logger := AnthropicCacheControlHook.get_custom_logger_for_anthropic_cache_control_hook(
|
||||
non_default_params
|
||||
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__
|
||||
|
|
@ -978,9 +991,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
self.model_call_details["api_key"] = api_key
|
||||
self.model_call_details["additional_args"] = additional_args
|
||||
self.model_call_details["log_event_type"] = "pre_api_call"
|
||||
if (
|
||||
model
|
||||
): # if model name was changes pre-call, overwrite the initial model call name with the new one
|
||||
if 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", ""))
|
||||
|
|
@ -1359,13 +1370,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
|
||||
|
|
@ -1865,7 +1876,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
self.model_call_details["litellm_params"].setdefault("metadata", {})
|
||||
if self.model_call_details["litellm_params"]["metadata"] is None:
|
||||
self.model_call_details["litellm_params"]["metadata"] = {}
|
||||
self.model_call_details["litellm_params"]["metadata"]["hidden_params"] = getattr(logging_result, "_hidden_params", {}) # type: ignore
|
||||
self.model_call_details["litellm_params"]["metadata"][
|
||||
"hidden_params"
|
||||
] = getattr(logging_result, "_hidden_params", {}) # type: ignore
|
||||
|
||||
if self.model_call_details.get("cache_hit") is True:
|
||||
self.model_call_details["response_cost"] = 0.0
|
||||
|
|
@ -1944,7 +1957,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
)
|
||||
|
||||
result = result.model_copy()
|
||||
transformed_usage = TranscriptionUsageObjectTransformation.transform_transcription_usage_object(result.usage) # type: ignore
|
||||
transformed_usage = TranscriptionUsageObjectTransformation.transform_transcription_usage_object(
|
||||
result.usage
|
||||
) # type: ignore
|
||||
setattr(result, "usage", transformed_usage)
|
||||
return result
|
||||
|
||||
|
|
@ -2948,7 +2963,9 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
|
||||
for callback_obj in all_callbacks:
|
||||
if hasattr(callback_obj, "increment_callback_logging_failure"):
|
||||
callback_obj.increment_callback_logging_failure(callback_name=callback_name) # type: ignore
|
||||
callback_obj.increment_callback_logging_failure(
|
||||
callback_name=callback_name
|
||||
) # type: ignore
|
||||
break # Only increment once
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -3292,9 +3309,7 @@ class Logging(LiteLLMLoggingBaseClass):
|
|||
except Exception as e:
|
||||
verbose_logger.exception(
|
||||
"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while failure \
|
||||
logging {}\nCallback={}".format(
|
||||
str(e), callback
|
||||
)
|
||||
logging {}\nCallback={}".format(str(e), callback)
|
||||
)
|
||||
# Track callback logging failures in Prometheus
|
||||
self._handle_callback_failure(callback=callback)
|
||||
|
|
@ -3762,7 +3777,29 @@ def set_callbacks(callback_list, function_id=None):
|
|||
"""
|
||||
Globally sets the callback client
|
||||
"""
|
||||
global sentry_sdk_instance, capture_exception, add_breadcrumb, slack_app, alerts_channel, traceloopLogger, athinaLogger, heliconeLogger, supabaseClient, lunaryLogger, promptLayerLogger, langFuseLogger, customLogger, weightsBiasesLogger, logfireLogger, dynamoLogger, s3Logger, dataDogLogger, prometheusLogger, greenscaleLogger, openMeterLogger, deepevalLogger
|
||||
global \
|
||||
sentry_sdk_instance, \
|
||||
capture_exception, \
|
||||
add_breadcrumb, \
|
||||
slack_app, \
|
||||
alerts_channel, \
|
||||
traceloopLogger, \
|
||||
athinaLogger, \
|
||||
heliconeLogger, \
|
||||
supabaseClient, \
|
||||
lunaryLogger, \
|
||||
promptLayerLogger, \
|
||||
langFuseLogger, \
|
||||
customLogger, \
|
||||
weightsBiasesLogger, \
|
||||
logfireLogger, \
|
||||
dynamoLogger, \
|
||||
s3Logger, \
|
||||
dataDogLogger, \
|
||||
prometheusLogger, \
|
||||
greenscaleLogger, \
|
||||
openMeterLogger, \
|
||||
deepevalLogger
|
||||
|
||||
try:
|
||||
for callback in callback_list:
|
||||
|
|
@ -4607,7 +4644,7 @@ def _maybe_auto_initialize_arize_phoenix(_in_memory_loggers: list) -> None:
|
|||
litellm.logging_callback_manager.add_litellm_callback(phoenix_logger)
|
||||
|
||||
verbose_logger.info(
|
||||
"Auto-initialized Arize Phoenix logger alongside otel " "(endpoint=%s)",
|
||||
"Auto-initialized Arize Phoenix logger alongside otel (endpoint=%s)",
|
||||
arize_phoenix_config.endpoint,
|
||||
)
|
||||
except Exception as e:
|
||||
|
|
@ -5781,7 +5818,8 @@ def get_standard_logging_object_payload(
|
|||
id = f"{id}_cache_hit{time.time()}" # do not duplicate the request id
|
||||
saved_cache_cost = (
|
||||
logging_obj._response_cost_calculator(
|
||||
result=init_response_obj, cache_hit=False # type: ignore
|
||||
result=init_response_obj,
|
||||
cache_hit=False, # type: ignore
|
||||
)
|
||||
or 0.0
|
||||
)
|
||||
|
|
|
|||
|
|
@ -131,8 +131,10 @@ def _generic_cost_per_character(
|
|||
assert (
|
||||
"input_cost_per_character" in model_info
|
||||
and model_info["input_cost_per_character"] is not None
|
||||
), "model info for model={} does not have 'input_cost_per_character'-pricing\nmodel_info={}".format(
|
||||
model, model_info
|
||||
), (
|
||||
"model info for model={} does not have 'input_cost_per_character'-pricing\nmodel_info={}".format(
|
||||
model, model_info
|
||||
)
|
||||
)
|
||||
custom_prompt_cost = model_info["input_cost_per_character"]
|
||||
|
||||
|
|
@ -152,8 +154,10 @@ def _generic_cost_per_character(
|
|||
assert (
|
||||
"output_cost_per_character" in model_info
|
||||
and model_info["output_cost_per_character"] is not None
|
||||
), "model info for model={} does not have 'output_cost_per_character'-pricing\nmodel_info={}".format(
|
||||
model, model_info
|
||||
), (
|
||||
"model info for model={} does not have 'output_cost_per_character'-pricing\nmodel_info={}".format(
|
||||
model, model_info
|
||||
)
|
||||
)
|
||||
custom_completion_cost = model_info["output_cost_per_character"]
|
||||
completion_cost = completion_characters * custom_completion_cost
|
||||
|
|
|
|||
|
|
@ -333,9 +333,15 @@ def convert_to_streaming_response(
|
|||
|
||||
if "usage" in response_object and response_object["usage"] is not None:
|
||||
setattr(model_response_object, "usage", Usage())
|
||||
model_response_object.usage.completion_tokens = response_object["usage"].get("completion_tokens", 0) # type: ignore
|
||||
model_response_object.usage.prompt_tokens = response_object["usage"].get("prompt_tokens", 0) # type: ignore
|
||||
model_response_object.usage.total_tokens = response_object["usage"].get("total_tokens", 0) # type: ignore
|
||||
model_response_object.usage.completion_tokens = response_object["usage"].get(
|
||||
"completion_tokens", 0
|
||||
) # type: ignore
|
||||
model_response_object.usage.prompt_tokens = response_object["usage"].get(
|
||||
"prompt_tokens", 0
|
||||
) # type: ignore
|
||||
model_response_object.usage.total_tokens = response_object["usage"].get(
|
||||
"total_tokens", 0
|
||||
) # type: ignore
|
||||
|
||||
if "id" in response_object:
|
||||
model_response_object.id = response_object["id"]
|
||||
|
|
@ -848,9 +854,15 @@ def convert_to_model_response_object(
|
|||
model_response_object.data = response_object["data"]
|
||||
|
||||
if "usage" in response_object and response_object["usage"] is not None:
|
||||
model_response_object.usage.completion_tokens = response_object["usage"].get("completion_tokens", 0) # type: ignore
|
||||
model_response_object.usage.prompt_tokens = response_object["usage"].get("prompt_tokens", 0) # type: ignore
|
||||
model_response_object.usage.total_tokens = response_object["usage"].get("total_tokens", 0) # type: ignore
|
||||
model_response_object.usage.completion_tokens = response_object[
|
||||
"usage"
|
||||
].get("completion_tokens", 0) # type: ignore
|
||||
model_response_object.usage.prompt_tokens = response_object[
|
||||
"usage"
|
||||
].get("prompt_tokens", 0) # type: ignore
|
||||
model_response_object.usage.total_tokens = response_object["usage"].get(
|
||||
"total_tokens", 0
|
||||
) # type: ignore
|
||||
|
||||
if start_time is not None and end_time is not None:
|
||||
model_response_object._response_ms = ( # type: ignore
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ class LoggingCallbackManager:
|
|||
Ensures no duplicates are added.
|
||||
"""
|
||||
self._safe_add_callback_to_list(
|
||||
callback=callback, parent_list=litellm.callbacks # type: ignore
|
||||
callback=callback,
|
||||
parent_list=litellm.callbacks, # type: ignore
|
||||
)
|
||||
|
||||
def add_litellm_success_callback(
|
||||
|
|
|
|||
|
|
@ -1586,7 +1586,9 @@ def convert_to_gemini_tool_call_result(
|
|||
file_data = (
|
||||
file_content.get("file_data", "")
|
||||
if isinstance(file_content, dict)
|
||||
else file_content if isinstance(file_content, str) else ""
|
||||
else file_content
|
||||
if isinstance(file_content, str)
|
||||
else ""
|
||||
)
|
||||
|
||||
if file_data:
|
||||
|
|
@ -2556,9 +2558,7 @@ def anthropic_messages_pt(
|
|||
ChatCompletionToolMessage,
|
||||
ChatCompletionUserMessage,
|
||||
ChatCompletionFunctionMessage,
|
||||
] = messages[
|
||||
msg_i
|
||||
] # type: ignore
|
||||
] = messages[msg_i] # type: ignore
|
||||
if user_message_types_block["role"] == "user":
|
||||
if isinstance(user_message_types_block["content"], list):
|
||||
for m in user_message_types_block["content"]:
|
||||
|
|
@ -4926,8 +4926,10 @@ class BedrockConverseMessagesProcessor:
|
|||
image_url = element["image_url"]["url"]
|
||||
else:
|
||||
image_url = element["image_url"]
|
||||
assistants_part = await BedrockImageProcessor.process_image_async( # type: ignore
|
||||
image_url=image_url
|
||||
assistants_part = (
|
||||
await BedrockImageProcessor.process_image_async( # type: ignore
|
||||
image_url=image_url
|
||||
)
|
||||
)
|
||||
assistants_parts.append(assistants_part)
|
||||
# Add cache point block for assistant content elements
|
||||
|
|
|
|||
|
|
@ -169,7 +169,9 @@ class RealTimeStreaming:
|
|||
try:
|
||||
event_type = message_obj.get("type", "")
|
||||
if event_type in self._SESSION_EVENT_TYPES:
|
||||
typed_obj: OpenAIRealtimeEvents = OpenAIRealtimeStreamSessionEvents(**message_obj) # type: ignore
|
||||
typed_obj: OpenAIRealtimeEvents = OpenAIRealtimeStreamSessionEvents(
|
||||
**message_obj
|
||||
) # type: ignore
|
||||
else:
|
||||
# Catch-all base object so unknown/new event names never raise.
|
||||
typed_obj = OpenAIRealtimeStreamResponseBaseObject(**message_obj) # type: ignore
|
||||
|
|
|
|||
|
|
@ -33,7 +33,11 @@ class Rules:
|
|||
if callable(rule):
|
||||
decision = rule(input)
|
||||
if decision is False:
|
||||
raise litellm.APIResponseValidationError(message="LLM Response failed post-call-rule check", llm_provider="", model=model) # type: ignore
|
||||
raise litellm.APIResponseValidationError(
|
||||
message="LLM Response failed post-call-rule check",
|
||||
llm_provider="",
|
||||
model=model,
|
||||
) # type: ignore
|
||||
return True
|
||||
|
||||
def post_call_rules(self, input: Optional[str], model: str) -> bool:
|
||||
|
|
@ -44,12 +48,18 @@ class Rules:
|
|||
decision = rule(input)
|
||||
if isinstance(decision, bool):
|
||||
if decision is False:
|
||||
raise litellm.APIResponseValidationError(message="LLM Response failed post-call-rule check", llm_provider="", model=model) # type: ignore
|
||||
raise litellm.APIResponseValidationError(
|
||||
message="LLM Response failed post-call-rule check",
|
||||
llm_provider="",
|
||||
model=model,
|
||||
) # type: ignore
|
||||
elif isinstance(decision, dict):
|
||||
decision_val = decision.get("decision", True)
|
||||
decision_message = decision.get(
|
||||
"message", "LLM Response failed post-call-rule check"
|
||||
)
|
||||
if decision_val is False:
|
||||
raise litellm.APIResponseValidationError(message=decision_message, llm_provider="", model=model) # type: ignore
|
||||
raise litellm.APIResponseValidationError(
|
||||
message=decision_message, llm_provider="", model=model
|
||||
) # type: ignore
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -54,9 +54,9 @@ class SensitiveDataMasker:
|
|||
|
||||
# Handle the case where visible_suffix is 0 to avoid showing the entire string
|
||||
if self.visible_suffix == 0:
|
||||
return f"{value_str[:self.visible_prefix]}{self.mask_char * masked_length}"
|
||||
return f"{value_str[: self.visible_prefix]}{self.mask_char * masked_length}"
|
||||
else:
|
||||
return f"{value_str[:self.visible_prefix]}{self.mask_char * masked_length}{value_str[-self.visible_suffix:]}"
|
||||
return f"{value_str[: self.visible_prefix]}{self.mask_char * masked_length}{value_str[-self.visible_suffix :]}"
|
||||
|
||||
def is_sensitive_key(
|
||||
self, key: str, excluded_keys: Optional[Set[str]] = None
|
||||
|
|
|
|||
|
|
@ -213,9 +213,9 @@ class ChunkProcessor:
|
|||
self, tool_call_chunks: List[Dict[str, Any]]
|
||||
) -> List[ChatCompletionMessageToolCall]:
|
||||
tool_calls_list: List[ChatCompletionMessageToolCall] = []
|
||||
tool_call_map: Dict[int, Dict[str, Any]] = (
|
||||
{}
|
||||
) # Map to store tool calls by index
|
||||
tool_call_map: Dict[
|
||||
int, Dict[str, Any]
|
||||
] = {} # Map to store tool calls by index
|
||||
|
||||
for chunk in tool_call_chunks:
|
||||
choices = chunk["choices"]
|
||||
|
|
@ -720,15 +720,16 @@ class ChunkProcessor:
|
|||
returned_usage.prompt_tokens = prompt_tokens or token_counter(
|
||||
model=model, messages=messages
|
||||
)
|
||||
except (
|
||||
Exception
|
||||
): # don't allow this failing to block a complete streaming response from being returned
|
||||
except Exception: # don't allow this failing to block a complete streaming response from being returned
|
||||
print_verbose("token_counter failed, assuming prompt tokens is 0")
|
||||
returned_usage.prompt_tokens = 0
|
||||
returned_usage.completion_tokens = completion_tokens or token_counter(
|
||||
model=model,
|
||||
text=completion_output,
|
||||
count_response_tokens=True, # count_response_tokens is a Flag to tell token counter this is a response, No need to add extra tokens we do for input messages
|
||||
returned_usage.completion_tokens = (
|
||||
completion_tokens
|
||||
or token_counter(
|
||||
model=model,
|
||||
text=completion_output,
|
||||
count_response_tokens=True, # count_response_tokens is a Flag to tell token counter this is a response, No need to add extra tokens we do for input messages
|
||||
)
|
||||
)
|
||||
returned_usage.total_tokens = (
|
||||
returned_usage.prompt_tokens + returned_usage.completion_tokens
|
||||
|
|
|
|||
|
|
@ -189,9 +189,7 @@ class CustomStreamWrapper:
|
|||
True if self.check_send_stream_usage(self.stream_options) else False
|
||||
)
|
||||
self.tool_call = False
|
||||
self.chunks: List = (
|
||||
[]
|
||||
) # keep track of the returned chunks - used for calculating the input/output tokens for stream options
|
||||
self.chunks: List = [] # keep track of the returned chunks - used for calculating the input/output tokens for stream options
|
||||
self._repeated_messages_count = 1
|
||||
self.is_function_call = self.check_is_function_call(logging_obj=logging_obj)
|
||||
self.created: Optional[int] = None
|
||||
|
|
@ -1861,8 +1859,10 @@ class CustomStreamWrapper:
|
|||
Caches the streaming response
|
||||
"""
|
||||
if not cache_hit and self.logging_obj._llm_caching_handler is not None:
|
||||
await self.logging_obj._llm_caching_handler._add_streaming_response_to_cache(
|
||||
processed_chunk
|
||||
await (
|
||||
self.logging_obj._llm_caching_handler._add_streaming_response_to_cache(
|
||||
processed_chunk
|
||||
)
|
||||
)
|
||||
|
||||
def run_success_logging_and_cache_storage(self, processed_chunk, cache_hit: bool):
|
||||
|
|
@ -2217,7 +2217,9 @@ class CustomStreamWrapper:
|
|||
)
|
||||
)
|
||||
# Add MCP metadata to final chunk if present (after hooks)
|
||||
processed_chunk = self._add_mcp_metadata_to_final_chunk(processed_chunk) # type: ignore[reportArgumentType]
|
||||
processed_chunk = self._add_mcp_metadata_to_final_chunk(
|
||||
processed_chunk
|
||||
) # type: ignore[reportArgumentType]
|
||||
|
||||
return processed_chunk
|
||||
raise StopAsyncIteration
|
||||
|
|
@ -2229,7 +2231,9 @@ class CustomStreamWrapper:
|
|||
):
|
||||
chunk = self.completion_stream
|
||||
else:
|
||||
chunk = await asyncio.to_thread(_next_sync_or_exhausted, self.completion_stream) # type: ignore[arg-type]
|
||||
chunk = await asyncio.to_thread(
|
||||
_next_sync_or_exhausted, self.completion_stream
|
||||
) # type: ignore[arg-type]
|
||||
if chunk is _SYNC_ITER_EXHAUSTED:
|
||||
raise StopAsyncIteration
|
||||
if chunk is not None and chunk != b"":
|
||||
|
|
|
|||
|
|
@ -63,9 +63,9 @@ def get_cost_for_web_search_request(
|
|||
return None
|
||||
|
||||
|
||||
def discover_guardrail_translation_mappings() -> (
|
||||
Dict[CallTypes, Type["BaseTranslation"]]
|
||||
):
|
||||
def discover_guardrail_translation_mappings() -> Dict[
|
||||
CallTypes, Type["BaseTranslation"]
|
||||
]:
|
||||
"""
|
||||
Discover guardrail translation mappings by scanning the llms directory structure.
|
||||
|
||||
|
|
|
|||
|
|
@ -288,9 +288,9 @@ class AnthropicMessagesHandler(BaseTranslation):
|
|||
|
||||
elif isinstance(content, list) and content_idx_optional is not None:
|
||||
# Replace specific text item in list content
|
||||
messages[msg_idx]["content"][content_idx_optional][
|
||||
"text"
|
||||
] = guardrail_response
|
||||
messages[msg_idx]["content"][content_idx_optional]["text"] = (
|
||||
guardrail_response
|
||||
)
|
||||
|
||||
async def process_output_response(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -624,7 +624,9 @@ class ModelResponseIterator:
|
|||
speed=self.speed,
|
||||
)
|
||||
|
||||
def _content_block_delta_helper(self, chunk: dict) -> Tuple[
|
||||
def _content_block_delta_helper(
|
||||
self, chunk: dict
|
||||
) -> Tuple[
|
||||
str,
|
||||
Optional[ChatCompletionToolCallChunk],
|
||||
List[Union[ChatCompletionThinkingBlock, ChatCompletionRedactedThinkingBlock]],
|
||||
|
|
|
|||
|
|
@ -750,7 +750,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
additional_tool_params[k] = v
|
||||
|
||||
returned_tool = AnthropicHostedTools(
|
||||
type=tool["type"], name=function_name, **additional_tool_params # type: ignore
|
||||
type=tool["type"],
|
||||
name=function_name,
|
||||
**additional_tool_params, # type: ignore
|
||||
)
|
||||
elif tool["type"] == "url": # mcp server tool
|
||||
mcp_server = AnthropicMcpServerTool(**tool) # type: ignore
|
||||
|
|
@ -2144,7 +2146,9 @@ class AnthropicConfig(AnthropicModelInfo, BaseConfig):
|
|||
filtered_tools = [t for i, t in enumerate(tool_calls) if i not in json_indices]
|
||||
return None, filtered_tools, extra_content
|
||||
|
||||
def extract_response_content(self, completion_response: dict) -> Tuple[
|
||||
def extract_response_content(
|
||||
self, completion_response: dict
|
||||
) -> Tuple[
|
||||
str,
|
||||
Optional[List[Any]],
|
||||
Optional[
|
||||
|
|
|
|||
|
|
@ -502,7 +502,8 @@ class AnthropicModelInfo(BaseLLMModelInfo):
|
|||
"computer_20241022": "computer-use-2024-10-22",
|
||||
}
|
||||
return computer_tool_beta_mapping.get(
|
||||
computer_tool_version, "computer-use-2024-10-22" # Default fallback
|
||||
computer_tool_version,
|
||||
"computer-use-2024-10-22", # Default fallback
|
||||
)
|
||||
|
||||
def get_anthropic_beta_list(
|
||||
|
|
|
|||
|
|
@ -184,9 +184,7 @@ class AnthropicStreamWrapper(AdapterCompletionStreamWrapper):
|
|||
# class level) so concurrent streams don't share the same mutable dict
|
||||
# — `_should_start_new_content_block` mutates `tool_block["name"]` in
|
||||
# place, which would otherwise leak across streams.
|
||||
self.current_content_block_start: (
|
||||
"AnthropicStreamWrapper.ContentBlockContentBlockDict"
|
||||
) = self.TextBlock(
|
||||
self.current_content_block_start: "AnthropicStreamWrapper.ContentBlockContentBlockDict" = self.TextBlock(
|
||||
type="text",
|
||||
text="",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -595,9 +595,9 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
|
||||
## ASSISTANT MESSAGE ##
|
||||
assistant_message_str: Optional[str] = None
|
||||
assistant_content_list: List[Dict[str, Any]] = (
|
||||
[]
|
||||
) # For content blocks with cache_control
|
||||
assistant_content_list: List[
|
||||
Dict[str, Any]
|
||||
] = [] # For content blocks with cache_control
|
||||
has_cache_control_in_text = False
|
||||
tool_calls: List[ChatCompletionAssistantToolCall] = []
|
||||
thinking_blocks: List[
|
||||
|
|
@ -1025,7 +1025,9 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
if openai_system_content:
|
||||
new_messages.insert(
|
||||
0,
|
||||
ChatCompletionSystemMessage(role="system", content=openai_system_content), # type: ignore
|
||||
ChatCompletionSystemMessage(
|
||||
role="system", content=openai_system_content
|
||||
), # type: ignore
|
||||
)
|
||||
|
||||
def _translate_metadata_to_openai(
|
||||
|
|
@ -1456,7 +1458,9 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
"input_tokens": uncached_input_tokens,
|
||||
"output_tokens": usage.completion_tokens or 0,
|
||||
}
|
||||
anthropic_usage["iterations"] = list(polyfill_result.iterations_usage) + [message_iteration] # type: ignore[typeddict-unknown-key]
|
||||
anthropic_usage["iterations"] = list(polyfill_result.iterations_usage) + [
|
||||
message_iteration
|
||||
] # type: ignore[typeddict-unknown-key]
|
||||
|
||||
translated_obj = AnthropicMessagesResponse(
|
||||
id=response.id,
|
||||
|
|
@ -1672,7 +1676,9 @@ class LiteLLMAnthropicMessagesAdapter:
|
|||
else:
|
||||
usage_delta = UsageDelta(input_tokens=0, output_tokens=0)
|
||||
message_block = MessageBlockDelta(
|
||||
type="message_delta", delta=delta, usage=usage_delta # type: ignore
|
||||
type="message_delta",
|
||||
delta=delta,
|
||||
usage=usage_delta, # type: ignore
|
||||
)
|
||||
if applied_edits:
|
||||
message_block["context_management"] = ContextManagementResponse(
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class BaseAnthropicMessagesStreamingIterator:
|
|||
"""
|
||||
if isinstance(chunk, dict):
|
||||
event_type: str = str(chunk.get("type", "message"))
|
||||
payload = f"event: {event_type}\n" f"data: {json.dumps(chunk)}\n\n"
|
||||
payload = f"event: {event_type}\ndata: {json.dumps(chunk)}\n\n"
|
||||
return payload.encode()
|
||||
else:
|
||||
# For non-dict chunks, return as is
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ class AnthropicResponsesStreamWrapper:
|
|||
# Map item_id -> content_block_index so we can stop the right block later
|
||||
self._item_id_to_block_index: Dict[str, int] = {}
|
||||
# Track open function_call items by item_id so we can emit tool_use start
|
||||
self._pending_tool_ids: Dict[str, str] = (
|
||||
{}
|
||||
) # item_id -> call_id / name accumulator
|
||||
self._pending_tool_ids: Dict[
|
||||
str, str
|
||||
] = {} # item_id -> call_id / name accumulator
|
||||
self._sent_message_start = False
|
||||
self._sent_message_stop = False
|
||||
self._chunk_queue: deque = deque()
|
||||
|
|
|
|||
|
|
@ -203,8 +203,11 @@ class AzureAssistantsAPI(BaseAzureLLM):
|
|||
litellm_params=litellm_params,
|
||||
)
|
||||
|
||||
thread_message: OpenAIMessage = await openai_client.beta.threads.messages.create( # type: ignore
|
||||
thread_id, **message_data # type: ignore
|
||||
thread_message: OpenAIMessage = (
|
||||
await openai_client.beta.threads.messages.create( # type: ignore
|
||||
thread_id,
|
||||
**message_data, # type: ignore
|
||||
)
|
||||
)
|
||||
|
||||
response_obj: Optional[OpenAIMessage] = None
|
||||
|
|
@ -292,7 +295,8 @@ class AzureAssistantsAPI(BaseAzureLLM):
|
|||
)
|
||||
|
||||
thread_message: OpenAIMessage = openai_client.beta.threads.messages.create( # type: ignore
|
||||
thread_id, **message_data # type: ignore
|
||||
thread_id,
|
||||
**message_data, # type: ignore
|
||||
)
|
||||
|
||||
response_obj: Optional[OpenAIMessage] = None
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ class AzureAudioTranscription(AzureChatCompletion):
|
|||
)
|
||||
|
||||
response = azure_client.audio.transcriptions.create(
|
||||
**data, timeout=timeout # type: ignore
|
||||
**data,
|
||||
timeout=timeout, # type: ignore
|
||||
)
|
||||
|
||||
if isinstance(response, BaseModel):
|
||||
|
|
@ -95,7 +96,12 @@ class AzureAudioTranscription(AzureChatCompletion):
|
|||
original_response=stringified_response,
|
||||
)
|
||||
hidden_params = {"model": model, "custom_llm_provider": "azure"}
|
||||
final_response: TranscriptionResponse = convert_to_model_response_object(response_object=stringified_response, model_response_object=model_response, hidden_params=hidden_params, response_type="audio_transcription") # type: ignore
|
||||
final_response: TranscriptionResponse = convert_to_model_response_object(
|
||||
response_object=stringified_response,
|
||||
model_response_object=model_response,
|
||||
hidden_params=hidden_params,
|
||||
response_type="audio_transcription",
|
||||
) # type: ignore
|
||||
return final_response
|
||||
|
||||
async def async_audio_transcriptions(
|
||||
|
|
|
|||
|
|
@ -817,7 +817,9 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM):
|
|||
)
|
||||
|
||||
## COMPLETION CALL
|
||||
raw_response = azure_client.embeddings.with_raw_response.create(**data, timeout=timeout) # type: ignore
|
||||
raw_response = azure_client.embeddings.with_raw_response.create(
|
||||
**data, timeout=timeout
|
||||
) # type: ignore
|
||||
headers = dict(raw_response.headers)
|
||||
response = raw_response.parse()
|
||||
if isinstance(response, str):
|
||||
|
|
@ -833,7 +835,12 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM):
|
|||
original_response=response,
|
||||
)
|
||||
|
||||
return convert_to_model_response_object(response_object=response.model_dump(), model_response_object=model_response, response_type="embedding", _response_headers=process_azure_headers(headers)) # type: ignore
|
||||
return convert_to_model_response_object(
|
||||
response_object=response.model_dump(),
|
||||
model_response_object=model_response,
|
||||
response_type="embedding",
|
||||
_response_headers=process_azure_headers(headers),
|
||||
) # type: ignore
|
||||
except AzureOpenAIError as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
|
|
@ -1296,7 +1303,18 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM):
|
|||
is_async=False,
|
||||
)
|
||||
if aimg_generation is True:
|
||||
return self.aimage_generation(data=data, input=input, logging_obj=logging_obj, model_response=model_response, api_key=api_key, client=client, azure_client_params=azure_client_params, timeout=timeout, headers=headers, model=model) # type: ignore
|
||||
return self.aimage_generation(
|
||||
data=data,
|
||||
input=input,
|
||||
logging_obj=logging_obj,
|
||||
model_response=model_response,
|
||||
api_key=api_key,
|
||||
client=client,
|
||||
azure_client_params=azure_client_params,
|
||||
timeout=timeout,
|
||||
headers=headers,
|
||||
model=model,
|
||||
) # type: ignore
|
||||
|
||||
img_gen_api_base = self.create_azure_base_url(
|
||||
azure_client_params=azure_client_params,
|
||||
|
|
@ -1348,7 +1366,11 @@ class AzureChatCompletion(BaseAzureLLM, BaseLLM):
|
|||
original_response=response,
|
||||
)
|
||||
# return response
|
||||
return convert_to_model_response_object(response_object=response, model_response_object=model_response, response_type="image_generation") # type: ignore
|
||||
return convert_to_model_response_object(
|
||||
response_object=response,
|
||||
model_response_object=model_response,
|
||||
response_type="image_generation",
|
||||
) # type: ignore
|
||||
except AzureOpenAIError as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -75,7 +75,9 @@ class AzureBatchesAPI(BaseAzureLLM):
|
|||
return self.acreate_batch( # type: ignore
|
||||
create_batch_data=create_batch_data, azure_client=azure_client
|
||||
)
|
||||
response = cast(Union[AzureOpenAI, OpenAI], azure_client).batches.create(**create_batch_data) # type: ignore[arg-type]
|
||||
response = cast(Union[AzureOpenAI, OpenAI], azure_client).batches.create(
|
||||
**create_batch_data
|
||||
) # type: ignore[arg-type]
|
||||
return LiteLLMBatch(**response.model_dump())
|
||||
|
||||
async def aretrieve_batch(
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ class AzureOpenAIFilesAPI(BaseAzureLLM):
|
|||
openai_client: Union[AsyncAzureOpenAI, AsyncOpenAI],
|
||||
) -> OpenAIFileObject:
|
||||
verbose_logger.debug("create_file_data=%s", create_file_data)
|
||||
response = await openai_client.files.create(**self._prepare_create_file_data(create_file_data)) # type: ignore[arg-type]
|
||||
response = await openai_client.files.create(
|
||||
**self._prepare_create_file_data(create_file_data)
|
||||
) # type: ignore[arg-type]
|
||||
verbose_logger.debug("create_file_response=%s", response)
|
||||
return OpenAIFileObject(**response.model_dump())
|
||||
|
||||
|
|
@ -86,7 +88,9 @@ class AzureOpenAIFilesAPI(BaseAzureLLM):
|
|||
return self.acreate_file(
|
||||
create_file_data=create_file_data, openai_client=openai_client
|
||||
)
|
||||
response = cast(Union[AzureOpenAI, OpenAI], openai_client).files.create(**self._prepare_create_file_data(create_file_data)) # type: ignore[arg-type]
|
||||
response = cast(Union[AzureOpenAI, OpenAI], openai_client).files.create(
|
||||
**self._prepare_create_file_data(create_file_data)
|
||||
) # type: ignore[arg-type]
|
||||
return OpenAIFileObject(**response.model_dump())
|
||||
|
||||
async def afile_content(
|
||||
|
|
|
|||
|
|
@ -403,8 +403,7 @@ class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM):
|
|||
# skip strategy matching and fall back to raw JSON string
|
||||
if not isinstance(response_json, dict):
|
||||
verbose_logger.warning(
|
||||
"AgentCore: JSON response is not a dict. "
|
||||
"Returning raw JSON as content."
|
||||
"AgentCore: JSON response is not a dict. Returning raw JSON as content."
|
||||
)
|
||||
return AgentCoreParsedResponse(
|
||||
content=json.dumps(response_json),
|
||||
|
|
@ -940,9 +939,9 @@ class AmazonAgentCoreConfig(BaseConfig, BaseAWSLLM):
|
|||
)
|
||||
parsed = self._parse_json_response(response_json)
|
||||
|
||||
async def _json_as_async_stream() -> (
|
||||
AsyncGenerator[ModelResponseStream, None]
|
||||
):
|
||||
async def _json_as_async_stream() -> AsyncGenerator[
|
||||
ModelResponseStream, None
|
||||
]:
|
||||
# Content chunk
|
||||
content_chunk = ModelResponseStream(
|
||||
id=f"chatcmpl-{uuid.uuid4()}",
|
||||
|
|
|
|||
|
|
@ -51,19 +51,19 @@ def make_sync_call(
|
|||
)
|
||||
|
||||
if fake_stream:
|
||||
model_response: (
|
||||
ModelResponse
|
||||
) = litellm.AmazonConverseConfig()._transform_response(
|
||||
model=model,
|
||||
response=response,
|
||||
model_response=litellm.ModelResponse(),
|
||||
stream=True,
|
||||
logging_obj=logging_obj,
|
||||
optional_params={},
|
||||
api_key="",
|
||||
data=data,
|
||||
messages=messages,
|
||||
encoding=litellm.encoding,
|
||||
model_response: ModelResponse = (
|
||||
litellm.AmazonConverseConfig()._transform_response(
|
||||
model=model,
|
||||
response=response,
|
||||
model_response=litellm.ModelResponse(),
|
||||
stream=True,
|
||||
logging_obj=logging_obj,
|
||||
optional_params={},
|
||||
api_key="",
|
||||
data=data,
|
||||
messages=messages,
|
||||
encoding=litellm.encoding,
|
||||
)
|
||||
) # type: ignore
|
||||
completion_stream: Any = MockResponseIterator(
|
||||
model_response=model_response, json_mode=json_mode
|
||||
|
|
|
|||
|
|
@ -1963,7 +1963,9 @@ class AmazonConverseConfig(BaseConfig):
|
|||
|
||||
return message, returned_finish_reason
|
||||
|
||||
def _translate_message_content(self, content_blocks: List[ContentBlock]) -> Tuple[
|
||||
def _translate_message_content(
|
||||
self, content_blocks: List[ContentBlock]
|
||||
) -> Tuple[
|
||||
str,
|
||||
List[ChatCompletionToolCallChunk],
|
||||
Optional[List[BedrockConverseReasoningContentBlock]],
|
||||
|
|
|
|||
|
|
@ -225,19 +225,19 @@ async def make_call(
|
|||
raise BedrockError(status_code=response.status_code, message=response.text)
|
||||
|
||||
if fake_stream:
|
||||
model_response: (
|
||||
ModelResponse
|
||||
) = litellm.AmazonConverseConfig()._transform_response(
|
||||
model=model,
|
||||
response=response,
|
||||
model_response=litellm.ModelResponse(),
|
||||
stream=True,
|
||||
logging_obj=logging_obj,
|
||||
optional_params={},
|
||||
api_key="",
|
||||
data=data,
|
||||
messages=messages,
|
||||
encoding=litellm.encoding,
|
||||
model_response: ModelResponse = (
|
||||
litellm.AmazonConverseConfig()._transform_response(
|
||||
model=model,
|
||||
response=response,
|
||||
model_response=litellm.ModelResponse(),
|
||||
stream=True,
|
||||
logging_obj=logging_obj,
|
||||
optional_params={},
|
||||
api_key="",
|
||||
data=data,
|
||||
messages=messages,
|
||||
encoding=litellm.encoding,
|
||||
)
|
||||
) # type: ignore
|
||||
completion_stream: Any = MockResponseIterator(
|
||||
model_response=model_response, json_mode=json_mode
|
||||
|
|
@ -321,19 +321,19 @@ def make_sync_call(
|
|||
raise BedrockError(status_code=response.status_code, message=response.text)
|
||||
|
||||
if fake_stream:
|
||||
model_response: (
|
||||
ModelResponse
|
||||
) = litellm.AmazonConverseConfig()._transform_response(
|
||||
model=model,
|
||||
response=response,
|
||||
model_response=litellm.ModelResponse(),
|
||||
stream=True,
|
||||
logging_obj=logging_obj,
|
||||
optional_params={},
|
||||
api_key="",
|
||||
data=data,
|
||||
messages=messages,
|
||||
encoding=litellm.encoding,
|
||||
model_response: ModelResponse = (
|
||||
litellm.AmazonConverseConfig()._transform_response(
|
||||
model=model,
|
||||
response=response,
|
||||
model_response=litellm.ModelResponse(),
|
||||
stream=True,
|
||||
logging_obj=logging_obj,
|
||||
optional_params={},
|
||||
api_key="",
|
||||
data=data,
|
||||
messages=messages,
|
||||
encoding=litellm.encoding,
|
||||
)
|
||||
) # type: ignore
|
||||
completion_stream: Any = MockResponseIterator(
|
||||
model_response=model_response, json_mode=json_mode
|
||||
|
|
@ -1300,7 +1300,9 @@ class BedrockLLM(BaseAWSLLM):
|
|||
if isinstance(timeout, float) or isinstance(timeout, int):
|
||||
timeout = httpx.Timeout(timeout)
|
||||
_params["timeout"] = timeout
|
||||
client = get_async_httpx_client(params=_params, llm_provider=litellm.LlmProviders.BEDROCK) # type: ignore
|
||||
client = get_async_httpx_client(
|
||||
params=_params, llm_provider=litellm.LlmProviders.BEDROCK
|
||||
) # type: ignore
|
||||
else:
|
||||
client = client # type: ignore
|
||||
|
||||
|
|
|
|||
|
|
@ -142,7 +142,9 @@ class BedrockEmbedding(BaseAWSLLM):
|
|||
client = client
|
||||
|
||||
try:
|
||||
response = await client.post(url=api_base, headers=headers, data=json.dumps(data)) # type: ignore
|
||||
response = await client.post(
|
||||
url=api_base, headers=headers, data=json.dumps(data)
|
||||
) # type: ignore
|
||||
response.raise_for_status()
|
||||
except httpx.HTTPStatusError as err:
|
||||
error_code = err.response.status_code
|
||||
|
|
@ -451,10 +453,10 @@ class BedrockEmbedding(BaseAWSLLM):
|
|||
batch_data = []
|
||||
for i in input:
|
||||
if model == "amazon.titan-embed-image-v1":
|
||||
transformed_request: (
|
||||
AmazonEmbeddingRequest
|
||||
) = AmazonTitanMultimodalEmbeddingG1Config()._transform_request(
|
||||
input=i, inference_params=inference_params
|
||||
transformed_request: AmazonEmbeddingRequest = (
|
||||
AmazonTitanMultimodalEmbeddingG1Config()._transform_request(
|
||||
input=i, inference_params=inference_params
|
||||
)
|
||||
)
|
||||
elif model == "amazon.titan-embed-text-v1":
|
||||
transformed_request = AmazonTitanG1Config()._transform_request(
|
||||
|
|
|
|||
|
|
@ -112,7 +112,11 @@ class BedrockImageEdit(BaseAWSLLM):
|
|||
if client is None or not isinstance(client, HTTPHandler):
|
||||
client = _get_httpx_client()
|
||||
try:
|
||||
response = client.post(url=prepared_request.endpoint_url, headers=prepared_request.prepped.headers, data=prepared_request.body) # type: ignore
|
||||
response = client.post(
|
||||
url=prepared_request.endpoint_url,
|
||||
headers=prepared_request.prepped.headers,
|
||||
data=prepared_request.body,
|
||||
) # type: ignore
|
||||
response.raise_for_status()
|
||||
except httpx.HTTPStatusError as err:
|
||||
error_code = err.response.status_code
|
||||
|
|
@ -150,7 +154,11 @@ class BedrockImageEdit(BaseAWSLLM):
|
|||
)
|
||||
|
||||
try:
|
||||
response = await async_client.post(url=prepared_request.endpoint_url, headers=prepared_request.prepped.headers, data=prepared_request.body) # type: ignore
|
||||
response = await async_client.post(
|
||||
url=prepared_request.endpoint_url,
|
||||
headers=prepared_request.prepped.headers,
|
||||
data=prepared_request.body,
|
||||
) # type: ignore
|
||||
response.raise_for_status()
|
||||
except httpx.HTTPStatusError as err:
|
||||
error_code = err.response.status_code
|
||||
|
|
|
|||
|
|
@ -122,7 +122,9 @@ class BedrockStabilityImageEditConfig(BaseImageEditConfig):
|
|||
if k in param_mapping:
|
||||
# Map param if mapping exists and value is valid
|
||||
if k == "size" and v in OPENAI_SIZE_TO_STABILITY_ASPECT_RATIO:
|
||||
mapped_params[param_mapping[k]] = OPENAI_SIZE_TO_STABILITY_ASPECT_RATIO[v] # type: ignore
|
||||
mapped_params[param_mapping[k]] = (
|
||||
OPENAI_SIZE_TO_STABILITY_ASPECT_RATIO[v]
|
||||
) # type: ignore
|
||||
# Don't copy "size" itself to final dict
|
||||
elif k == "n":
|
||||
# Store for logic but do not add to outgoing params
|
||||
|
|
|
|||
|
|
@ -111,8 +111,10 @@ class AmazonNovaCanvasConfig:
|
|||
**color_guided_generation_params,
|
||||
}
|
||||
try:
|
||||
color_guided_generation_params_typed = AmazonNovaCanvasColorGuidedGenerationParams(
|
||||
**color_guided_generation_params # type: ignore
|
||||
color_guided_generation_params_typed = (
|
||||
AmazonNovaCanvasColorGuidedGenerationParams(
|
||||
**color_guided_generation_params # type: ignore
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
raise ValueError(
|
||||
|
|
@ -171,8 +173,9 @@ class AmazonNovaCanvasConfig:
|
|||
_size = non_default_params.get("size")
|
||||
if _size is not None:
|
||||
width, height = _size.split("x")
|
||||
optional_params["width"], optional_params["height"] = int(width), int(
|
||||
height
|
||||
optional_params["width"], optional_params["height"] = (
|
||||
int(width),
|
||||
int(height),
|
||||
)
|
||||
if non_default_params.get("n") is not None:
|
||||
optional_params["numberOfImages"] = non_default_params.get("n")
|
||||
|
|
|
|||
|
|
@ -115,7 +115,11 @@ class BedrockImageGeneration(BaseAWSLLM):
|
|||
if client is None or not isinstance(client, HTTPHandler):
|
||||
client = _get_httpx_client()
|
||||
try:
|
||||
response = client.post(url=prepared_request.endpoint_url, headers=prepared_request.prepped.headers, data=prepared_request.body) # type: ignore
|
||||
response = client.post(
|
||||
url=prepared_request.endpoint_url,
|
||||
headers=prepared_request.prepped.headers,
|
||||
data=prepared_request.body,
|
||||
) # type: ignore
|
||||
response.raise_for_status()
|
||||
except httpx.HTTPStatusError as err:
|
||||
error_code = err.response.status_code
|
||||
|
|
@ -154,7 +158,11 @@ class BedrockImageGeneration(BaseAWSLLM):
|
|||
)
|
||||
|
||||
try:
|
||||
response = await async_client.post(url=prepared_request.endpoint_url, headers=prepared_request.prepped.headers, data=prepared_request.body) # type: ignore
|
||||
response = await async_client.post(
|
||||
url=prepared_request.endpoint_url,
|
||||
headers=prepared_request.prepped.headers,
|
||||
data=prepared_request.body,
|
||||
) # type: ignore
|
||||
response.raise_for_status()
|
||||
except httpx.HTTPStatusError as err:
|
||||
error_code = err.response.status_code
|
||||
|
|
|
|||
|
|
@ -237,9 +237,7 @@ class BedrockRealtime(BaseAWSLLM):
|
|||
# Transform Bedrock format to OpenAI format
|
||||
from litellm.types.realtime import RealtimeResponseTransformInput
|
||||
|
||||
realtime_response_transform_input: (
|
||||
RealtimeResponseTransformInput
|
||||
) = {
|
||||
realtime_response_transform_input: RealtimeResponseTransformInput = {
|
||||
"current_output_item_id": session_state.get(
|
||||
"current_output_item_id"
|
||||
),
|
||||
|
|
|
|||
|
|
@ -96,7 +96,13 @@ class BedrockRerankHandler(BaseAWSLLM):
|
|||
)
|
||||
|
||||
if _is_async:
|
||||
return self.arerank(prepared_request, timeout=timeout, client=client if client is not None and isinstance(client, AsyncHTTPHandler) else None) # type: ignore
|
||||
return self.arerank(
|
||||
prepared_request,
|
||||
timeout=timeout,
|
||||
client=client
|
||||
if client is not None and isinstance(client, AsyncHTTPHandler)
|
||||
else None,
|
||||
) # type: ignore
|
||||
|
||||
if client is None or not isinstance(client, HTTPHandler):
|
||||
client = _get_httpx_client()
|
||||
|
|
|
|||
|
|
@ -253,9 +253,9 @@ class BedrockVectorStoreConfig(BaseVectorStoreConfig, BaseAWSLLM):
|
|||
verbose_logger.debug(
|
||||
"Overriding extra_body retrievalConfiguration.vectorSearchConfiguration.filter with filters from vector_store_search_optional_params"
|
||||
)
|
||||
retrieval_config.setdefault("vectorSearchConfiguration", {})[
|
||||
"filter"
|
||||
] = filters
|
||||
retrieval_config.setdefault("vectorSearchConfiguration", {})["filter"] = (
|
||||
filters
|
||||
)
|
||||
if retrieval_config:
|
||||
request_body["retrievalConfiguration"] = cast(
|
||||
BedrockKBRetrievalConfiguration, retrieval_config
|
||||
|
|
|
|||
|
|
@ -72,9 +72,9 @@ _AIOHTTP_SUPPORTS_SOCKET_FACTORY = (
|
|||
)
|
||||
|
||||
|
||||
def _build_aiohttp_keepalive_socket_factory() -> (
|
||||
Optional[Callable[[Tuple[Any, ...]], socket.socket]]
|
||||
):
|
||||
def _build_aiohttp_keepalive_socket_factory() -> Optional[
|
||||
Callable[[Tuple[Any, ...]], socket.socket]
|
||||
]:
|
||||
"""
|
||||
Build a socket_factory that enables SO_KEEPALIVE on aiohttp TCP sockets.
|
||||
|
||||
|
|
@ -719,7 +719,14 @@ class AsyncHTTPHandler:
|
|||
)
|
||||
|
||||
req = self.client.build_request(
|
||||
"PUT", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore
|
||||
"PUT",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
response = await self.client.send(req)
|
||||
response.raise_for_status()
|
||||
|
|
@ -780,7 +787,14 @@ class AsyncHTTPHandler:
|
|||
)
|
||||
|
||||
req = self.client.build_request(
|
||||
"PATCH", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore
|
||||
"PATCH",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
response = await self.client.send(req)
|
||||
response.raise_for_status()
|
||||
|
|
@ -841,7 +855,14 @@ class AsyncHTTPHandler:
|
|||
)
|
||||
|
||||
req = self.client.build_request(
|
||||
"DELETE", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore
|
||||
"DELETE",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
response = await self.client.send(req, stream=stream)
|
||||
response.raise_for_status()
|
||||
|
|
@ -888,7 +909,13 @@ class AsyncHTTPHandler:
|
|||
request_data, request_content = _prepare_request_data_and_content(data, content)
|
||||
|
||||
req = client.build_request(
|
||||
"POST", url, data=request_data, json=json, params=params, headers=headers, content=request_content # type: ignore
|
||||
"POST",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
response = await client.send(req, stream=stream)
|
||||
response.raise_for_status()
|
||||
|
|
@ -1200,7 +1227,14 @@ class HTTPHandler:
|
|||
)
|
||||
else:
|
||||
req = self.client.build_request(
|
||||
"POST", url, data=request_data, json=json, params=params, headers=headers, files=files, content=request_content # type: ignore
|
||||
"POST",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
files=files,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
response = self.client.send(req, stream=stream)
|
||||
response.raise_for_status()
|
||||
|
|
@ -1235,11 +1269,24 @@ class HTTPHandler:
|
|||
|
||||
if timeout is not None:
|
||||
req = self.client.build_request(
|
||||
"PATCH", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore
|
||||
"PATCH",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
else:
|
||||
req = self.client.build_request(
|
||||
"PATCH", url, data=request_data, json=json, params=params, headers=headers, content=request_content # type: ignore
|
||||
"PATCH",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
response = self.client.send(req, stream=stream)
|
||||
response.raise_for_status()
|
||||
|
|
@ -1274,11 +1321,24 @@ class HTTPHandler:
|
|||
|
||||
if timeout is not None:
|
||||
req = self.client.build_request(
|
||||
"PUT", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore
|
||||
"PUT",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
else:
|
||||
req = self.client.build_request(
|
||||
"PUT", url, data=request_data, json=json, params=params, headers=headers, content=request_content # type: ignore
|
||||
"PUT",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
response = self.client.send(req, stream=stream)
|
||||
return response
|
||||
|
|
@ -1312,11 +1372,24 @@ class HTTPHandler:
|
|||
|
||||
if timeout is not None:
|
||||
req = self.client.build_request(
|
||||
"DELETE", url, data=request_data, json=json, params=params, headers=headers, timeout=timeout, content=request_content # type: ignore
|
||||
"DELETE",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
timeout=timeout,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
else:
|
||||
req = self.client.build_request(
|
||||
"DELETE", url, data=request_data, json=json, params=params, headers=headers, content=request_content # type: ignore
|
||||
"DELETE",
|
||||
url,
|
||||
data=request_data,
|
||||
json=json,
|
||||
params=params,
|
||||
headers=headers,
|
||||
content=request_content, # type: ignore
|
||||
)
|
||||
response = self.client.send(req, stream=stream)
|
||||
response.raise_for_status()
|
||||
|
|
|
|||
|
|
@ -54,7 +54,10 @@ class HTTPHandler:
|
|||
):
|
||||
try:
|
||||
response = await self.client.post(
|
||||
url, data=data, params=params, headers=headers # type: ignore
|
||||
url,
|
||||
data=data,
|
||||
params=params,
|
||||
headers=headers, # type: ignore
|
||||
)
|
||||
return response
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -578,11 +578,11 @@ class FireworksAIConfig(OpenAIGPTConfig):
|
|||
|
||||
## FIREWORKS AI sends tool calls in the content field instead of tool_calls
|
||||
for choice in response.choices:
|
||||
cast(Choices, choice).message = (
|
||||
self._handle_message_content_with_tool_calls(
|
||||
message=cast(Choices, choice).message,
|
||||
tool_calls=optional_params.get("tools", None),
|
||||
)
|
||||
cast(
|
||||
Choices, choice
|
||||
).message = self._handle_message_content_with_tool_calls(
|
||||
message=cast(Choices, choice).message,
|
||||
tool_calls=optional_params.get("tools", None),
|
||||
)
|
||||
|
||||
response._hidden_params = {
|
||||
|
|
|
|||
|
|
@ -1755,9 +1755,9 @@ class GeminiRealtimeConfig(BaseRealtimeConfig):
|
|||
)
|
||||
tool_call_temperature = tool_call_generation_config.get("temperature")
|
||||
if tool_call_temperature is not None:
|
||||
tool_call_done_event["response"][
|
||||
"temperature"
|
||||
] = tool_call_temperature
|
||||
tool_call_done_event["response"]["temperature"] = (
|
||||
tool_call_temperature
|
||||
)
|
||||
tool_call_max_output_tokens = tool_call_generation_config.get(
|
||||
"maxOutputTokens"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ class Authenticator:
|
|||
)
|
||||
except httpx.HTTPStatusError as e:
|
||||
verbose_logger.error(
|
||||
f"HTTP error refreshing API key (attempt {attempt+1}/{max_retries}): {str(e)}"
|
||||
f"HTTP error refreshing API key (attempt {attempt + 1}/{max_retries}): {str(e)}"
|
||||
)
|
||||
except Exception as e:
|
||||
verbose_logger.error(f"Unexpected error refreshing API key: {str(e)}")
|
||||
|
|
@ -318,7 +318,7 @@ class Authenticator:
|
|||
and resp_json.get("error") == "authorization_pending"
|
||||
):
|
||||
verbose_logger.debug(
|
||||
f"Authorization pending (attempt {attempt+1}/{max_attempts})"
|
||||
f"Authorization pending (attempt {attempt + 1}/{max_attempts})"
|
||||
)
|
||||
else:
|
||||
verbose_logger.warning(f"Unexpected response: {resp_json}")
|
||||
|
|
|
|||
|
|
@ -58,8 +58,7 @@ def github_copilot_supports_responses_api(model: str) -> bool:
|
|||
)
|
||||
except Exception as e:
|
||||
verbose_logger.debug(
|
||||
"github_copilot_supports_responses_api: get_model_info failed "
|
||||
"for %s: %s",
|
||||
"github_copilot_supports_responses_api: get_model_info failed for %s: %s",
|
||||
model,
|
||||
e,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@ class InceptionChatConfig(OpenAILikeChatConfig):
|
|||
self, api_base: Optional[str], api_key: Optional[str]
|
||||
) -> Tuple[Optional[str], Optional[str]]:
|
||||
passed_api_base = api_base
|
||||
api_base = api_base or get_secret_str("INCEPTION_API_BASE") or "https://api.inceptionlabs.ai/v1" # type: ignore
|
||||
api_base = (
|
||||
api_base
|
||||
or get_secret_str("INCEPTION_API_BASE")
|
||||
or "https://api.inceptionlabs.ai/v1"
|
||||
) # type: ignore
|
||||
dynamic_api_key = api_key
|
||||
if passed_api_base is None or api_key:
|
||||
dynamic_api_key = (
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@ class LlamafileChatConfig(OpenAIGPTConfig):
|
|||
If both are None, a default Llamafile server URL is returned.
|
||||
See: https://github.com/Mozilla-Ocho/llamafile/blob/bd1bbe9aabb1ee12dbdcafa8936db443c571eb9d/README.md#L61
|
||||
"""
|
||||
return api_base or get_secret_str("LLAMAFILE_API_BASE") or "http://127.0.0.1:8080/v1" # type: ignore
|
||||
return (
|
||||
api_base
|
||||
or get_secret_str("LLAMAFILE_API_BASE")
|
||||
or "http://127.0.0.1:8080/v1"
|
||||
) # type: ignore
|
||||
|
||||
def _get_openai_compatible_provider_info(
|
||||
self, api_base: Optional[str], api_key: Optional[str]
|
||||
|
|
|
|||
|
|
@ -64,7 +64,11 @@ class MoonshotChatConfig(OpenAIGPTConfig):
|
|||
def _get_openai_compatible_provider_info(
|
||||
self, api_base: Optional[str], api_key: Optional[str]
|
||||
) -> Tuple[Optional[str], Optional[str]]:
|
||||
api_base = api_base or get_secret_str("MOONSHOT_API_BASE") or "https://api.moonshot.ai/v1" # type: ignore
|
||||
api_base = (
|
||||
api_base
|
||||
or get_secret_str("MOONSHOT_API_BASE")
|
||||
or "https://api.moonshot.ai/v1"
|
||||
) # type: ignore
|
||||
dynamic_api_key = api_key or get_secret_str("MOONSHOT_API_KEY")
|
||||
return api_base, dynamic_api_key
|
||||
|
||||
|
|
|
|||
|
|
@ -234,12 +234,18 @@ class NvidiaNimRerankConfig(BaseRerankConfig):
|
|||
}
|
||||
|
||||
# Add optional top_k parameter if provided (already mapped from top_n in map_cohere_rerank_params)
|
||||
if "top_k" in optional_rerank_params and optional_rerank_params.get("top_k") is not None: # type: ignore
|
||||
if (
|
||||
"top_k" in optional_rerank_params
|
||||
and optional_rerank_params.get("top_k") is not None
|
||||
): # type: ignore
|
||||
request_data["top_k"] = optional_rerank_params.get("top_k") # type: ignore
|
||||
|
||||
# Add Nvidia-specific truncate parameter if provided
|
||||
# This is passed through from non_default_params, not in base OptionalRerankParams
|
||||
if "truncate" in optional_rerank_params and optional_rerank_params.get("truncate") is not None: # type: ignore
|
||||
if (
|
||||
"truncate" in optional_rerank_params
|
||||
and optional_rerank_params.get("truncate") is not None
|
||||
): # type: ignore
|
||||
truncate_value = optional_rerank_params.get("truncate") # type: ignore
|
||||
if truncate_value in ["NONE", "END"]:
|
||||
request_data["truncate"] = truncate_value # type: ignore
|
||||
|
|
|
|||
|
|
@ -274,7 +274,9 @@ def handle_cohere_response(
|
|||
total_tokens=usage_info.totalTokens,
|
||||
)
|
||||
else:
|
||||
model_response.usage = Usage(prompt_tokens=0, completion_tokens=0, total_tokens=0) # type: ignore[attr-defined]
|
||||
model_response.usage = Usage(
|
||||
prompt_tokens=0, completion_tokens=0, total_tokens=0
|
||||
) # type: ignore[attr-defined]
|
||||
|
||||
return model_response
|
||||
|
||||
|
|
|
|||
|
|
@ -529,7 +529,8 @@ class OCIChatConfig(BaseConfig):
|
|||
)
|
||||
else:
|
||||
selected_params["tools"] = adapt_tool_definition_to_oci_standard( # type: ignore[assignment]
|
||||
selected_params["tools"], vendor # type: ignore[arg-type]
|
||||
selected_params["tools"],
|
||||
vendor, # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
# Normalise tool_choice to OCI's flat uppercase dict form
|
||||
|
|
|
|||
|
|
@ -339,7 +339,9 @@ def sign_with_manual_credentials(
|
|||
private_key = (
|
||||
load_private_key_from_str(oci_key_content)
|
||||
if oci_key_content
|
||||
else load_private_key_from_file(oci_key_file) if oci_key_file else None
|
||||
else load_private_key_from_file(oci_key_file)
|
||||
if oci_key_file
|
||||
else None
|
||||
)
|
||||
|
||||
if private_key is None:
|
||||
|
|
|
|||
|
|
@ -411,7 +411,9 @@ class OllamaChatConfig(BaseConfig):
|
|||
model_response.choices[0].finish_reason = "tool_calls"
|
||||
model_response.created = int(time.time())
|
||||
model_response.model = "ollama_chat/" + model
|
||||
prompt_tokens = response_json.get("prompt_eval_count", litellm.token_counter(messages=messages)) # type: ignore
|
||||
prompt_tokens = response_json.get(
|
||||
"prompt_eval_count", litellm.token_counter(messages=messages)
|
||||
) # type: ignore
|
||||
completion_tokens = response_json.get(
|
||||
"eval_count",
|
||||
litellm.token_counter(text=response_json["message"]["content"]),
|
||||
|
|
|
|||
|
|
@ -337,7 +337,8 @@ class OllamaConfig(BaseConfig):
|
|||
model_response.model = "ollama/" + model
|
||||
_prompt = request_data.get("prompt", "")
|
||||
prompt_tokens = response_json.get(
|
||||
"prompt_eval_count", len(encoding.encode(_prompt, disallowed_special=())) # type: ignore
|
||||
"prompt_eval_count",
|
||||
len(encoding.encode(_prompt, disallowed_special=())), # type: ignore
|
||||
)
|
||||
completion_tokens = response_json.get(
|
||||
"eval_count", len(response_json.get("message", dict()).get("content", ""))
|
||||
|
|
|
|||
|
|
@ -65,7 +65,9 @@ class OobaboogaConfig(OpenAIGPTConfig):
|
|||
)
|
||||
else:
|
||||
try:
|
||||
model_response.choices[0].message.content = completion_response["choices"][0]["message"]["content"] # type: ignore
|
||||
model_response.choices[0].message.content = completion_response[
|
||||
"choices"
|
||||
][0]["message"]["content"] # type: ignore
|
||||
except Exception as e:
|
||||
raise OobaboogaError(
|
||||
message=str(e),
|
||||
|
|
|
|||
|
|
@ -379,10 +379,10 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig):
|
|||
List[OpenAIMessageContentListBlock], message_content
|
||||
)
|
||||
for i, content_item in enumerate(message_content_types):
|
||||
message_content_types[i] = (
|
||||
await self._async_transform_content_item(
|
||||
cast(OpenAIMessageContentListBlock, content_item),
|
||||
)
|
||||
message_content_types[
|
||||
i
|
||||
] = await self._async_transform_content_item(
|
||||
cast(OpenAIMessageContentListBlock, content_item),
|
||||
)
|
||||
return messages
|
||||
|
||||
|
|
@ -419,7 +419,8 @@ class OpenAIGPTConfig(BaseLLMModelInfo, BaseConfig):
|
|||
|
||||
for i, message in enumerate(messages):
|
||||
messages[i] = cast(
|
||||
AllMessageValues, filter_value_from_dict(message, "cache_control") # type: ignore
|
||||
AllMessageValues,
|
||||
filter_value_from_dict(message, "cache_control"), # type: ignore
|
||||
)
|
||||
if tools is not None:
|
||||
for i, tool in enumerate(tools):
|
||||
|
|
|
|||
|
|
@ -259,9 +259,9 @@ class OpenAIChatCompletionsHandler(BaseTranslation):
|
|||
|
||||
elif isinstance(content, list) and content_idx_optional is not None:
|
||||
# Replace specific text item in list content
|
||||
messages[msg_idx]["content"][content_idx_optional][
|
||||
"text"
|
||||
] = guardrail_response
|
||||
messages[msg_idx]["content"][content_idx_optional]["text"] = (
|
||||
guardrail_response
|
||||
)
|
||||
|
||||
async def _apply_guardrail_responses_to_input_tool_calls(
|
||||
self,
|
||||
|
|
@ -746,7 +746,9 @@ class OpenAIChatCompletionsHandler(BaseTranslation):
|
|||
|
||||
elif isinstance(content, list) and content_idx_optional is not None:
|
||||
# Replace specific text item in list content
|
||||
choice.message.content[content_idx_optional]["text"] = guardrail_response # type: ignore
|
||||
choice.message.content[content_idx_optional]["text"] = (
|
||||
guardrail_response # type: ignore
|
||||
)
|
||||
|
||||
async def _apply_guardrail_responses_to_output_tool_calls(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -96,7 +96,19 @@ class OpenAITextCompletion(BaseLLM):
|
|||
organization=organization,
|
||||
)
|
||||
else:
|
||||
return self.acompletion(api_base=api_base, data=data, headers=headers, model_response=model_response, api_key=api_key, logging_obj=logging_obj, model=model, timeout=timeout, max_retries=max_retries, organization=organization, client=client) # type: ignore
|
||||
return self.acompletion(
|
||||
api_base=api_base,
|
||||
data=data,
|
||||
headers=headers,
|
||||
model_response=model_response,
|
||||
api_key=api_key,
|
||||
logging_obj=logging_obj,
|
||||
model=model,
|
||||
timeout=timeout,
|
||||
max_retries=max_retries,
|
||||
organization=organization,
|
||||
client=client,
|
||||
) # type: ignore
|
||||
elif optional_params.get("stream", False):
|
||||
return self.streaming(
|
||||
logging_obj=logging_obj,
|
||||
|
|
@ -124,7 +136,9 @@ class OpenAITextCompletion(BaseLLM):
|
|||
else:
|
||||
openai_client = client
|
||||
|
||||
raw_response = openai_client.completions.with_raw_response.create(**data) # type: ignore
|
||||
raw_response = openai_client.completions.with_raw_response.create(
|
||||
**data
|
||||
) # type: ignore
|
||||
response = raw_response.parse()
|
||||
response_json = response.model_dump()
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,9 @@ class OpenAIImageVariationsHandler:
|
|||
client=client, init_client_params=init_client_params
|
||||
)
|
||||
|
||||
raw_response = await client.images.with_raw_response.create_variation(**data) # type: ignore
|
||||
raw_response = await client.images.with_raw_response.create_variation(
|
||||
**data
|
||||
) # type: ignore
|
||||
response = raw_response.parse()
|
||||
response_json = response.model_dump()
|
||||
|
||||
|
|
|
|||
|
|
@ -1132,9 +1132,7 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM):
|
|||
data = drop_params_from_unprocessable_entity_error(e, data)
|
||||
else:
|
||||
raise e
|
||||
except (
|
||||
Exception
|
||||
) as e: # need to exception handle here. async exceptions don't get caught in sync functions.
|
||||
except Exception as e: # need to exception handle here. async exceptions don't get caught in sync functions.
|
||||
if isinstance(e, OpenAIError):
|
||||
raise e
|
||||
|
||||
|
|
@ -1433,7 +1431,11 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM):
|
|||
additional_args={"complete_input_dict": data},
|
||||
original_response=stringified_response,
|
||||
)
|
||||
return convert_to_model_response_object(response_object=stringified_response, model_response_object=model_response, response_type="image_generation") # type: ignore
|
||||
return convert_to_model_response_object(
|
||||
response_object=stringified_response,
|
||||
model_response_object=model_response,
|
||||
response_type="image_generation",
|
||||
) # type: ignore
|
||||
except Exception as e:
|
||||
## LOGGING
|
||||
logging_obj.post_call(
|
||||
|
|
@ -1466,7 +1468,19 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM):
|
|||
raise OpenAIError(status_code=422, message="max retries must be an int")
|
||||
|
||||
if aimg_generation is True:
|
||||
return self.aimage_generation(data=data, prompt=prompt, logging_obj=logging_obj, model_response=model_response, api_base=api_base, api_key=api_key, timeout=timeout, client=client, max_retries=max_retries, organization=organization, headers=headers) # type: ignore
|
||||
return self.aimage_generation(
|
||||
data=data,
|
||||
prompt=prompt,
|
||||
logging_obj=logging_obj,
|
||||
model_response=model_response,
|
||||
api_base=api_base,
|
||||
api_key=api_key,
|
||||
timeout=timeout,
|
||||
client=client,
|
||||
max_retries=max_retries,
|
||||
organization=organization,
|
||||
headers=headers,
|
||||
) # type: ignore
|
||||
|
||||
openai_client: OpenAI = self._get_openai_client( # type: ignore
|
||||
is_async=False,
|
||||
|
|
@ -1503,7 +1517,11 @@ class OpenAIChatCompletion(BaseLLM, BaseOpenAILLM):
|
|||
additional_args={"complete_input_dict": data},
|
||||
original_response=response,
|
||||
)
|
||||
return convert_to_model_response_object(response_object=response, model_response_object=model_response, response_type="image_generation") # type: ignore
|
||||
return convert_to_model_response_object(
|
||||
response_object=response,
|
||||
model_response_object=model_response,
|
||||
response_type="image_generation",
|
||||
) # type: ignore
|
||||
except OpenAIError as e:
|
||||
## LOGGING
|
||||
logging_obj.post_call(
|
||||
|
|
@ -2517,8 +2535,11 @@ class OpenAIAssistantsAPI(BaseLLM):
|
|||
client=client,
|
||||
)
|
||||
|
||||
thread_message: OpenAIMessage = await openai_client.beta.threads.messages.create( # type: ignore
|
||||
thread_id, **message_data # type: ignore
|
||||
thread_message: OpenAIMessage = (
|
||||
await openai_client.beta.threads.messages.create( # type: ignore
|
||||
thread_id,
|
||||
**message_data, # type: ignore
|
||||
)
|
||||
)
|
||||
|
||||
response_obj: Optional[OpenAIMessage] = None
|
||||
|
|
@ -2596,7 +2617,8 @@ class OpenAIAssistantsAPI(BaseLLM):
|
|||
)
|
||||
|
||||
thread_message: OpenAIMessage = openai_client.beta.threads.messages.create( # type: ignore
|
||||
thread_id, **message_data # type: ignore
|
||||
thread_id,
|
||||
**message_data, # type: ignore
|
||||
)
|
||||
|
||||
response_obj: Optional[OpenAIMessage] = None
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue