Litellm dev 07 09 2025 p1 (#12462)

* fix(db_spend_update_writer.py): fix db query

* fix(litellm_pre_call_utils.py): support passing anthropic-beta headers when 'forward_client_headers_to_llm_api' is True

allows user to pass along extra headers to vertex ai anthropic models

* docs(config_settings.md): update docs
This commit is contained in:
Krish Dholakia 2025-07-09 21:46:15 -07:00 • committed by GitHub
parent 5bf9c97094
commit 635367b020
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 29 additions and 7 deletions

View file

@ -211,7 +211,7 @@ general_settings:
| pass_through_endpoints | List[Dict[str, Any]] | Define the pass through endpoints. [Docs](./pass_through) |
| enable_oauth2_proxy_auth | boolean | (Enterprise Feature) If true, enables oauth2.0 authentication |
| forward_openai_org_id | boolean | If true, forwards the OpenAI Organization ID to the backend LLM call (if it's OpenAI). |
| forward_client_headers_to_llm_api | boolean | If true, forwards the client headers (any `x-` headers) to the backend LLM call |
| forward_client_headers_to_llm_api | boolean | If true, forwards the client headers (any `x-` headers and `anthropic-beta` headers) to the backend LLM call |
| maximum_spend_logs_retention_period | str | Used to set the max retention time for spend logs in the db, after which they will be auto-purged |
| maximum_spend_logs_retention_interval | str | Used to set the interval in which the spend log cleanup task should run in. |
### router_settings - Reference

View file

@ -875,7 +875,8 @@ class DBSpendUpdateWriter:
),
"mcp_namespaced_tool_name": transaction.get(
"mcp_namespaced_tool_name"
),
)
or "",
}
}

View file

@ -141,28 +141,41 @@ def convert_key_logging_metadata_to_callback(
return team_callback_settings_obj
class KeyAndTeamLoggingSettings:
"""
Helper class to get the dynamic logging settings for the key and team
"""
@staticmethod
def get_key_dynamic_logging_settings(user_api_key_dict: UserAPIKeyAuth):
if user_api_key_dict.metadata is not None and "logging" in user_api_key_dict.metadata:
if (
user_api_key_dict.metadata is not None
and "logging" in user_api_key_dict.metadata
):
return user_api_key_dict.metadata["logging"]
return None
@staticmethod
def get_team_dynamic_logging_settings(user_api_key_dict: UserAPIKeyAuth):
if user_api_key_dict.team_metadata is not None and "logging" in user_api_key_dict.team_metadata:
if (
user_api_key_dict.team_metadata is not None
and "logging" in user_api_key_dict.team_metadata
):
return user_api_key_dict.team_metadata["logging"]
return None
def _get_dynamic_logging_metadata(
user_api_key_dict: UserAPIKeyAuth, proxy_config: ProxyConfig
) -> Optional[TeamCallbackMetadata]:
callback_settings_obj: Optional[TeamCallbackMetadata] = None
key_dynamic_logging_settings: Optional[dict] = KeyAndTeamLoggingSettings.get_key_dynamic_logging_settings(user_api_key_dict)
team_dynamic_logging_settings: Optional[dict] = KeyAndTeamLoggingSettings.get_team_dynamic_logging_settings(user_api_key_dict)
key_dynamic_logging_settings: Optional[dict] = (
KeyAndTeamLoggingSettings.get_key_dynamic_logging_settings(user_api_key_dict)
)
team_dynamic_logging_settings: Optional[dict] = (
KeyAndTeamLoggingSettings.get_team_dynamic_logging_settings(user_api_key_dict)
)
#########################################################################################
# Key-based callbacks
#########################################################################################
@ -267,6 +280,8 @@ class LiteLLMProxyRequestSetup:
Get the headers that should be forwarded to the LLM Provider.
Looks for any `x-` headers and sends them to the LLM Provider.
[07/09/2025] - Support 'anthropic-beta' header as well.
"""
forwarded_headers = {}
for header, value in headers.items():
@ -274,6 +289,8 @@ class LiteLLMProxyRequestSetup:
"x-stainless"
): # causes openai sdk to fail
forwarded_headers[header] = value
elif header.lower().startswith("anthropic-beta"):
forwarded_headers[header] = value
return forwarded_headers

View file

@ -211,6 +211,7 @@ def test_add_headers_to_request(litellm_key_header_name):
"Authorization": "Bearer 1234",
"X-Custom-Header": "Custom-Value",
"X-Stainless-Header": "Stainless-Value",
"anthropic-beta": "beta-value",
}
request = Request(scope={"type": "http"})
request._url = URL(url="/chat/completions")
@ -219,7 +220,10 @@ def test_add_headers_to_request(litellm_key_header_name):
forwarded_headers = LiteLLMProxyRequestSetup._get_forwardable_headers(
request_headers
)
assert forwarded_headers == {"X-Custom-Header": "Custom-Value"}
assert forwarded_headers == {
"X-Custom-Header": "Custom-Value",
"anthropic-beta": "beta-value",
}
@pytest.mark.parametrize(