diff --git a/langfuse/logger.py b/langfuse/logger.py index afe8c0aef..a18fb0e1c 100644 --- a/langfuse/logger.py +++ b/langfuse/logger.py @@ -22,7 +22,10 @@ httpx_logger.setLevel(logging.WARNING) # Add console handler if no handlers exist -console_handler = logging.StreamHandler() -formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") -console_handler.setFormatter(formatter) -httpx_logger.addHandler(console_handler) +if not httpx_logger.handlers: + console_handler = logging.StreamHandler() + formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + ) + console_handler.setFormatter(formatter) + httpx_logger.addHandler(console_handler) diff --git a/langfuse/openai.py b/langfuse/openai.py index 97bb0f89e..e2a337117 100644 --- a/langfuse/openai.py +++ b/langfuse/openai.py @@ -898,7 +898,7 @@ def _get_langfuse_data_from_default_response( completion = None if resource.type == "completion": - choices = response.get("choices", []) + choices = response.get("choices") or [] if len(choices) > 0: choice = choices[-1] @@ -908,7 +908,7 @@ def _get_langfuse_data_from_default_response( completion = _extract_response_api_completion(response.get("output", {})) elif resource.type == "chat": - choices = response.get("choices", []) + choices = response.get("choices") or [] if len(choices) > 0: # If multiple choices were generated, we'll show all of them in the UI as a list. if len(choices) > 1: diff --git a/tests/unit/test_logger.py b/tests/unit/test_logger.py index 6417fba28..09dcca72b 100644 --- a/tests/unit/test_logger.py +++ b/tests/unit/test_logger.py @@ -1,3 +1,5 @@ +import importlib +import logging import os from langfuse import Langfuse @@ -34,3 +36,18 @@ def test_debug_langfuse(): # Reset langfuse_logger.setLevel("WARNING") + + +def test_httpx_handler_not_duplicated_when_handler_exists(): + import langfuse.logger as lf_logger + + httpx_logger = logging.getLogger("httpx") + saved = httpx_logger.handlers[:] + httpx_logger.handlers = [] + pre_existing = logging.NullHandler() + httpx_logger.addHandler(pre_existing) + try: + importlib.reload(lf_logger) + assert httpx_logger.handlers == [pre_existing] + finally: + httpx_logger.handlers = saved diff --git a/tests/unit/test_openai.py b/tests/unit/test_openai.py index c06ce9df2..88783dd31 100644 --- a/tests/unit/test_openai.py +++ b/tests/unit/test_openai.py @@ -1051,3 +1051,15 @@ def test_with_raw_response_streaming_passes_through_untraced( span.name != "OpenAI-generation" for span in memory_exporter.get_finished_spans() ) + + +def test_default_response_handles_null_choices(): + for resource_type in ("chat", "completion"): + model, completion, usage = ( + lf_openai_module._get_langfuse_data_from_default_response( + SimpleNamespace(type=resource_type, object="ChatCompletion"), + {"model": "gpt-4", "choices": None, "usage": None}, + ) + ) + assert completion is None + assert model == "gpt-4"