Skip to content

Commit e5c1d09

Browse files
feat(langsmith.py): add langsmith sampling rate
Closes LIT-879
1 parent 7a1f723 commit e5c1d09

File tree

3 files changed

+38
-30
lines changed

3 files changed

+38
-30
lines changed

litellm/proxy/litellm_pre_call_utils.py

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
)
2222

2323
# Cache special headers as a frozenset for O(1) lookup performance
24-
_SPECIAL_HEADERS_CACHE = frozenset(v.value.lower() for v in SpecialHeaders._member_map_.values())
24+
_SPECIAL_HEADERS_CACHE = frozenset(
25+
v.value.lower() for v in SpecialHeaders._member_map_.values()
26+
)
2527
from litellm.proxy.auth.route_checks import RouteChecks
2628
from litellm.router import Router
2729
from litellm.types.llms.anthropic import ANTHROPIC_API_HEADERS
@@ -64,6 +66,7 @@ def parse_cache_control(cache_control):
6466
"files",
6567
)
6668

69+
6770
def _get_metadata_variable_name(request: Request) -> str:
6871
"""
6972
Helper to return what the "metadata" field should be called in the request data
@@ -157,6 +160,7 @@ def get_key_dynamic_logging_settings(user_api_key_dict: UserAPIKeyAuth):
157160

158161
@staticmethod
159162
def get_team_dynamic_logging_settings(user_api_key_dict: UserAPIKeyAuth):
163+
160164
if (
161165
user_api_key_dict.team_metadata is not None
162166
and "logging" in user_api_key_dict.team_metadata
@@ -169,12 +173,12 @@ def _get_dynamic_logging_metadata(
169173
user_api_key_dict: UserAPIKeyAuth, proxy_config: ProxyConfig
170174
) -> Optional[TeamCallbackMetadata]:
171175
callback_settings_obj: Optional[TeamCallbackMetadata] = None
172-
key_dynamic_logging_settings: Optional[
173-
dict
174-
] = KeyAndTeamLoggingSettings.get_key_dynamic_logging_settings(user_api_key_dict)
175-
team_dynamic_logging_settings: Optional[
176-
dict
177-
] = KeyAndTeamLoggingSettings.get_team_dynamic_logging_settings(user_api_key_dict)
176+
key_dynamic_logging_settings: Optional[dict] = (
177+
KeyAndTeamLoggingSettings.get_key_dynamic_logging_settings(user_api_key_dict)
178+
)
179+
team_dynamic_logging_settings: Optional[dict] = (
180+
KeyAndTeamLoggingSettings.get_team_dynamic_logging_settings(user_api_key_dict)
181+
)
178182
#########################################################################################
179183
# Key-based callbacks
180184
#########################################################################################
@@ -234,12 +238,16 @@ def clean_headers(
234238
Removes litellm api key from headers
235239
"""
236240
clean_headers = {}
237-
litellm_key_lower = litellm_key_header_name.lower() if litellm_key_header_name is not None else None
238-
241+
litellm_key_lower = (
242+
litellm_key_header_name.lower() if litellm_key_header_name is not None else None
243+
)
244+
239245
for header, value in headers.items():
240246
header_lower = header.lower()
241247
# Check if header should be excluded: either in special headers cache or matches custom litellm key
242-
if (header_lower not in _SPECIAL_HEADERS_CACHE and (litellm_key_lower is None or header_lower != litellm_key_lower)):
248+
if header_lower not in _SPECIAL_HEADERS_CACHE and (
249+
litellm_key_lower is None or header_lower != litellm_key_lower
250+
):
243251
clean_headers[header] = value
244252
return clean_headers
245253

@@ -614,11 +622,11 @@ def add_key_level_controls(
614622

615623
## KEY-LEVEL SPEND LOGS / TAGS
616624
if "tags" in key_metadata and key_metadata["tags"] is not None:
617-
data[_metadata_variable_name][
618-
"tags"
619-
] = LiteLLMProxyRequestSetup._merge_tags(
620-
request_tags=data[_metadata_variable_name].get("tags"),
621-
tags_to_add=key_metadata["tags"],
625+
data[_metadata_variable_name]["tags"] = (
626+
LiteLLMProxyRequestSetup._merge_tags(
627+
request_tags=data[_metadata_variable_name].get("tags"),
628+
tags_to_add=key_metadata["tags"],
629+
)
622630
)
623631
if "spend_logs_metadata" in key_metadata and isinstance(
624632
key_metadata["spend_logs_metadata"], dict
@@ -847,9 +855,9 @@ async def add_litellm_data_to_request( # noqa: PLR0915
847855
data[_metadata_variable_name]["litellm_api_version"] = version
848856

849857
if general_settings is not None:
850-
data[_metadata_variable_name][
851-
"global_max_parallel_requests"
852-
] = general_settings.get("global_max_parallel_requests", None)
858+
data[_metadata_variable_name]["global_max_parallel_requests"] = (
859+
general_settings.get("global_max_parallel_requests", None)
860+
)
853861

854862
### KEY-LEVEL Controls
855863
key_metadata = user_api_key_dict.metadata

litellm/proxy/management_endpoints/team_callback_endpoints.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,14 @@ async def add_team_callbacks(
7979
8080
"""
8181
try:
82+
from litellm.proxy._types import CommonProxyErrors
8283
from litellm.proxy.proxy_server import prisma_client
8384

8485
if prisma_client is None:
85-
raise HTTPException(status_code=500, detail={"error": "No db connected"})
86+
raise HTTPException(
87+
status_code=500,
88+
detail={"error": CommonProxyErrors.db_not_connected_error.value},
89+
)
8690

8791
# Check if team_id exists already
8892
_existing_team = await prisma_client.get_data(
@@ -101,13 +105,14 @@ async def add_team_callbacks(
101105
team_callback_settings = team_metadata.get("callback_settings", {})
102106
# expect callback settings to be
103107
team_callback_settings_obj = TeamCallbackMetadata(**team_callback_settings)
108+
104109
if data.callback_type == "success":
105110
if team_callback_settings_obj.success_callback is None:
106111
team_callback_settings_obj.success_callback = []
107112

108113
if data.callback_name in team_callback_settings_obj.success_callback:
109114
raise ProxyException(
110-
message=f"callback_name = {data.callback_name} already exists in failure_callback, for team_id = {team_id}. \n Existing failure_callback = {team_callback_settings_obj.success_callback}",
115+
message=f"callback_name = {data.callback_name} already exists in success_callback, for team_id = {team_id}. \n Existing failure_callback = {team_callback_settings_obj.success_callback}",
111116
code=status.HTTP_400_BAD_REQUEST,
112117
type=ProxyErrorTypes.bad_request_error,
113118
param="callback_name",
@@ -168,22 +173,16 @@ async def add_team_callbacks(
168173
"data": new_team_row,
169174
}
170175

176+
except HTTPException as e:
177+
raise e
178+
except ProxyException as e:
179+
raise e
171180
except Exception as e:
172181
verbose_proxy_logger.error(
173182
"litellm.proxy.proxy_server.add_team_callbacks(): Exception occured - {}".format(
174183
str(e)
175184
)
176185
)
177-
verbose_proxy_logger.debug(traceback.format_exc())
178-
if isinstance(e, HTTPException):
179-
raise ProxyException(
180-
message=getattr(e, "detail", f"Internal Server Error({str(e)})"),
181-
type=ProxyErrorTypes.internal_server_error.value,
182-
param=getattr(e, "param", "None"),
183-
code=getattr(e, "status_code", status.HTTP_500_INTERNAL_SERVER_ERROR),
184-
)
185-
elif isinstance(e, ProxyException):
186-
raise e
187186
raise ProxyException(
188187
message="Internal Server Error, " + str(e),
189188
type=ProxyErrorTypes.internal_server_error.value,

litellm/types/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,6 +2140,7 @@ class StandardCallbackDynamicParams(TypedDict, total=False):
21402140
langsmith_api_key: Optional[str]
21412141
langsmith_project: Optional[str]
21422142
langsmith_base_url: Optional[str]
2143+
langsmith_sampling_rate: Optional[float]
21432144

21442145
# Humanloop dynamic params
21452146
humanloop_api_key: Optional[str]

0 commit comments

Comments
 (0)