forked from phoenix/litellm-mirror
* fix(litellm_logging.py): ensure cache hits are scrubbed if 'turn_off_message_logging' is enabled * fix(sagemaker.py): fix streaming to raise error immediately Fixes https://github.com/BerriAI/litellm/issues/6054 * (fixes) gcs bucket key based logging (#6044) * fixes for gcs bucket logging * fix StandardCallbackDynamicParams * fix - gcs logging when payload is not serializable * add test_add_callback_via_key_litellm_pre_call_utils_gcs_bucket * working success callbacks * linting fixes * fix linting error * add type hints to functions * fixes for dynamic success and failure logging * fix for test_async_chat_openai_stream * fix handle case when key based logging vars are set as os.environ/ vars * fix prometheus track cooldown events on custom logger (#6060) * (docs) add 1k rps load test doc (#6059) * docs 1k rps load test * docs load testing * docs load testing litellm * docs load testing * clean up load test doc * docs prom metrics for load testing * docs using prometheus on load testing * doc load testing with prometheus * (fixes) docs + qa - gcs key based logging (#6061) * fixes for required values for gcs bucket * docs gcs bucket logging * bump: version 1.48.12 → 1.48.13 * ci/cd run again * bump: version 1.48.13 → 1.48.14 * update load test doc * (docs) router settings - on litellm config (#6037) * add yaml with all router settings * add docs for router settings * docs router settings litellm settings * (feat) OpenAI prompt caching models to model cost map (#6063) * add prompt caching for latest models * add cache_read_input_token_cost for prompt caching models * fix(litellm_logging.py): check if param is iterable Fixes https://github.com/BerriAI/litellm/issues/6025#issuecomment-2393929946 * fix(factory.py): support passing an 'assistant_continue_message' to prevent bedrock error Fixes https://github.com/BerriAI/litellm/issues/6053 * fix(databricks/chat): handle streaming responses * fix(factory.py): fix linting error * fix(utils.py): unify anthropic + deepseek prompt caching information to openai format Fixes https://github.com/BerriAI/litellm/issues/6069 * test: fix test * fix(types/utils.py): support all openai roles Fixes https://github.com/BerriAI/litellm/issues/6052 * test: fix test --------- Co-authored-by: Ishaan Jaff <ishaanjaffer0324@gmail.com>
129 lines
4 KiB
Python
129 lines
4 KiB
Python
# +-----------------------------------------------+
|
|
# | |
|
|
# | Give Feedback / Get Help |
|
|
# | https://github.com/BerriAI/litellm/issues/new |
|
|
# | |
|
|
# +-----------------------------------------------+
|
|
#
|
|
# Thank you users! We ❤️ you! - Krrish & Ishaan
|
|
|
|
import copy
|
|
from typing import TYPE_CHECKING, Any, Optional
|
|
|
|
import litellm
|
|
from litellm.integrations.custom_logger import CustomLogger
|
|
|
|
if TYPE_CHECKING:
|
|
from litellm.litellm_core_utils.litellm_logging import (
|
|
Logging as _LiteLLMLoggingObject,
|
|
)
|
|
|
|
LiteLLMLoggingObject = _LiteLLMLoggingObject
|
|
else:
|
|
LiteLLMLoggingObject = Any
|
|
|
|
|
|
def redact_message_input_output_from_custom_logger(
|
|
litellm_logging_obj: LiteLLMLoggingObject, result, custom_logger: CustomLogger
|
|
):
|
|
if (
|
|
hasattr(custom_logger, "message_logging")
|
|
and custom_logger.message_logging is not True
|
|
):
|
|
return perform_redaction(litellm_logging_obj.model_call_details, result)
|
|
return result
|
|
|
|
|
|
def perform_redaction(model_call_details: dict, result):
|
|
"""
|
|
Performs the actual redaction on the logging object and result.
|
|
"""
|
|
# Redact model_call_details
|
|
model_call_details["messages"] = [
|
|
{"role": "user", "content": "redacted-by-litellm"}
|
|
]
|
|
model_call_details["prompt"] = ""
|
|
model_call_details["input"] = ""
|
|
|
|
# Redact streaming response
|
|
if (
|
|
model_call_details.get("stream", False) is True
|
|
and "complete_streaming_response" in model_call_details
|
|
):
|
|
_streaming_response = model_call_details["complete_streaming_response"]
|
|
for choice in _streaming_response.choices:
|
|
if isinstance(choice, litellm.Choices):
|
|
choice.message.content = "redacted-by-litellm"
|
|
elif isinstance(choice, litellm.utils.StreamingChoices):
|
|
choice.delta.content = "redacted-by-litellm"
|
|
|
|
# Redact result
|
|
if result is not None and isinstance(result, litellm.ModelResponse):
|
|
_result = copy.deepcopy(result)
|
|
if hasattr(_result, "choices") and _result.choices is not None:
|
|
for choice in _result.choices:
|
|
if isinstance(choice, litellm.Choices):
|
|
choice.message.content = "redacted-by-litellm"
|
|
elif isinstance(choice, litellm.utils.StreamingChoices):
|
|
choice.delta.content = "redacted-by-litellm"
|
|
return _result
|
|
else:
|
|
return "redacted-by-litellm"
|
|
|
|
|
|
def redact_message_input_output_from_logging(
|
|
model_call_details: dict, result, input: Optional[Any] = None
|
|
):
|
|
"""
|
|
Removes messages, prompts, input, response from logging. This modifies the data in-place
|
|
only redacts when litellm.turn_off_message_logging == True
|
|
"""
|
|
_request_headers = (
|
|
model_call_details.get("litellm_params", {}).get("metadata", {}) or {}
|
|
)
|
|
|
|
request_headers = _request_headers.get("headers", {})
|
|
|
|
# check if user opted out of logging message/response to callbacks
|
|
if (
|
|
litellm.turn_off_message_logging is not True
|
|
and request_headers.get("litellm-enable-message-redaction", False) is not True
|
|
):
|
|
return result
|
|
|
|
if request_headers and request_headers.get(
|
|
"litellm-disable-message-redaction", False
|
|
):
|
|
return result
|
|
|
|
return perform_redaction(model_call_details, result)
|
|
|
|
|
|
def redact_user_api_key_info(metadata: dict) -> dict:
|
|
"""
|
|
removes any user_api_key_info before passing to logging object, if flag set
|
|
|
|
Usage:
|
|
|
|
SDK
|
|
```python
|
|
litellm.redact_user_api_key_info = True
|
|
```
|
|
|
|
PROXY:
|
|
```yaml
|
|
litellm_settings:
|
|
redact_user_api_key_info: true
|
|
```
|
|
"""
|
|
if litellm.redact_user_api_key_info is not True:
|
|
return metadata
|
|
|
|
new_metadata = {}
|
|
for k, v in metadata.items():
|
|
if isinstance(k, str) and k.startswith("user_api_key"):
|
|
pass
|
|
else:
|
|
new_metadata[k] = v
|
|
|
|
return new_metadata
|