diff --git a/litellm/integrations/langfuse.py b/litellm/integrations/langfuse.py index caf5437b242..f1640dea516 100644 --- a/litellm/integrations/langfuse.py +++ b/litellm/integrations/langfuse.py @@ -262,7 +262,23 @@ class LangFuseLogger: try: tags = [] - metadata = copy.deepcopy(metadata) # Avoid modifying the original metadata + try: + metadata = copy.deepcopy( + metadata + ) # Avoid modifying the original metadata + except: + new_metadata = {} + for key, value in metadata.items(): + if ( + isinstance(value, list) + or isinstance(value, dict) + or isinstance(value, str) + or isinstance(value, int) + or isinstance(value, float) + ): + new_metadata[key] = copy.deepcopy(value) + metadata = new_metadata + supports_tags = Version(langfuse.version.__version__) >= Version("2.6.3") supports_prompt = Version(langfuse.version.__version__) >= Version("2.7.3") supports_costs = Version(langfuse.version.__version__) >= Version("2.7.3") diff --git a/litellm/proxy/proxy_config.yaml b/litellm/proxy/proxy_config.yaml index cd625564934..0378efced31 100644 --- a/litellm/proxy/proxy_config.yaml +++ b/litellm/proxy/proxy_config.yaml @@ -9,7 +9,6 @@ model_list: model: openai/* api_key: os.environ/OPENAI_API_KEY - general_settings: store_model_in_db: true master_key: sk-1234 @@ -17,4 +16,10 @@ general_settings: litellm_settings: success_callback: ["langfuse"] - _langfuse_default_tags: ["user_api_key_alias", "user_api_key_user_id", "user_api_key_user_email", "user_api_key_team_alias", "semantic-similarity", "proxy_base_url"] \ No newline at end of file + failure_callback: ["langfuse"] + default_team_settings: + - team_id: 7bf09cd5-217a-40d4-8634-fc31d9b88bf4 + success_callback: ["langfuse"] + failure_callback: ["langfuse"] + langfuse_public_key: "os.environ/LANGFUSE_DEV_PUBLIC_KEY" + langfuse_secret_key: "os.environ/LANGFUSE_DEV_SK_KEY" diff --git a/litellm/utils.py b/litellm/utils.py index 838d0fe553e..0babe2f0b10 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -1079,6 +1079,7 @@ class Logging: litellm_call_id, function_id, dynamic_success_callbacks=None, + dynamic_failure_callbacks=None, dynamic_async_success_callbacks=None, langfuse_public_key=None, langfuse_secret=None, @@ -1113,7 +1114,7 @@ class Logging: self.sync_streaming_chunks = [] # for generating complete stream response self.model_call_details = {} self.dynamic_input_callbacks = [] # [TODO] callbacks set for just that call - self.dynamic_failure_callbacks = [] # [TODO] callbacks set for just that call + self.dynamic_failure_callbacks = dynamic_failure_callbacks self.dynamic_success_callbacks = ( dynamic_success_callbacks # callbacks set for just that call ) @@ -2334,11 +2335,26 @@ class Logging: start_time=start_time, end_time=end_time, ) + callbacks = [] # init this to empty incase it's not created + + if self.dynamic_failure_callbacks is not None and isinstance( + self.dynamic_failure_callbacks, list + ): + callbacks = self.dynamic_failure_callbacks + ## keep the internal functions ## + for callback in litellm.failure_callback: + if ( + isinstance(callback, CustomLogger) + and "_PROXY_" in callback.__class__.__name__ + ): + callbacks.append(callback) + else: + callbacks = litellm.failure_callback result = None # result sent to all loggers, init this to None incase it's not created self.redact_message_input_output_from_logging(result=result) - for callback in litellm.failure_callback: + for callback in callbacks: try: if callback == "lite_debugger": print_verbose("reaches lite_debugger for logging!") @@ -2427,7 +2443,7 @@ class Logging: ) elif callback == "langfuse": global langFuseLogger - verbose_logger.debug("reaches langfuse for logging!") + verbose_logger.debug("reaches langfuse for logging failure") kwargs = {} for k, v in self.model_call_details.items(): if ( @@ -2436,8 +2452,16 @@ class Logging: kwargs[k] = v # this only logs streaming once, complete_streaming_response exists i.e when stream ends if langFuseLogger is None or ( - self.langfuse_public_key != langFuseLogger.public_key - and self.langfuse_secret != langFuseLogger.secret_key + ( + self.langfuse_public_key is not None + and self.langfuse_public_key + != langFuseLogger.public_key + ) + and ( + self.langfuse_public_key is not None + and self.langfuse_public_key + != langFuseLogger.public_key + ) ): langFuseLogger = LangFuseLogger( langfuse_public_key=self.langfuse_public_key, @@ -2713,6 +2737,7 @@ def function_setup( ### DYNAMIC CALLBACKS ### dynamic_success_callbacks = None dynamic_async_success_callbacks = None + dynamic_failure_callbacks = None if kwargs.get("success_callback", None) is not None and isinstance( kwargs["success_callback"], list ): @@ -2734,6 +2759,10 @@ def function_setup( for index in reversed(removed_async_items): kwargs["success_callback"].pop(index) dynamic_success_callbacks = kwargs.pop("success_callback") + if kwargs.get("failure_callback", None) is not None and isinstance( + kwargs["failure_callback"], list + ): + dynamic_failure_callbacks = kwargs.pop("failure_callback") if add_breadcrumb: try: @@ -2816,9 +2845,11 @@ def function_setup( call_type=call_type, start_time=start_time, dynamic_success_callbacks=dynamic_success_callbacks, + dynamic_failure_callbacks=dynamic_failure_callbacks, dynamic_async_success_callbacks=dynamic_async_success_callbacks, langfuse_public_key=kwargs.pop("langfuse_public_key", None), - langfuse_secret=kwargs.pop("langfuse_secret", None), + langfuse_secret=kwargs.pop("langfuse_secret", None) + or kwargs.pop("langfuse_secret_key", None), ) ## check if metadata is passed in litellm_params = {"api_base": ""} diff --git a/proxy_server_config.yaml b/proxy_server_config.yaml index 046ed7e95d5..b70d9b2022b 100644 --- a/proxy_server_config.yaml +++ b/proxy_server_config.yaml @@ -92,10 +92,12 @@ litellm_settings: default_team_settings: - team_id: team-1 success_callback: ["langfuse"] + failure_callback: ["langfuse"] langfuse_public_key: os.environ/LANGFUSE_PROJECT1_PUBLIC # Project 1 langfuse_secret: os.environ/LANGFUSE_PROJECT1_SECRET # Project 1 - team_id: team-2 success_callback: ["langfuse"] + failure_callback: ["langfuse"] langfuse_public_key: os.environ/LANGFUSE_PROJECT2_PUBLIC # Project 2 langfuse_secret: os.environ/LANGFUSE_PROJECT2_SECRET # Project 2