forked from phoenix/litellm-mirror
(fix) Langfuse key based logging (#6372)
* langfuse use helper for get_langfuse_logging_config * fix get_langfuse_logger_for_request * fix import * fix get_langfuse_logger_for_request * test_get_langfuse_logger_for_request_with_dynamic_params * unit testing for test_get_langfuse_logger_for_request_with_no_dynamic_params * parameterized langfuse testing * fix langfuse test * fix langfuse logging * fix test_aaalangfuse_logging_metadata * fix langfuse log metadata test * fix langfuse logger * use create_langfuse_logger_from_credentials * fix test_get_langfuse_logger_for_request_with_no_dynamic_params * fix correct langfuse/ folder structure * use static methods for langfuse logger * add commment on langfuse handler * fix linting error * add unit testing for langfuse logging * fix linting * fix failure handler langfuse
This commit is contained in:
parent
b70147f63b
commit
72a91ea9dd
7 changed files with 426 additions and 210 deletions
|
@ -428,7 +428,7 @@ async def test_aaalangfuse_logging_metadata(langfuse_client):
|
|||
|
||||
await asyncio.sleep(2)
|
||||
langfuse_client.flush()
|
||||
# await asyncio.sleep(10)
|
||||
await asyncio.sleep(4)
|
||||
|
||||
# Tests the metadata filtering and the override of the output to be the last generation
|
||||
for trace_id, generation_ids in trace_identifiers.items():
|
||||
|
@ -625,7 +625,7 @@ def test_aaalangfuse_existing_trace_id():
|
|||
import datetime
|
||||
|
||||
import litellm
|
||||
from litellm.integrations.langfuse import LangFuseLogger
|
||||
from litellm.integrations.langfuse.langfuse import LangFuseLogger
|
||||
|
||||
langfuse_Logger = LangFuseLogger(
|
||||
langfuse_public_key=os.getenv("LANGFUSE_PROJECT2_PUBLIC"),
|
||||
|
@ -1125,7 +1125,7 @@ generation_params = {
|
|||
)
|
||||
def test_langfuse_prompt_type(prompt):
|
||||
|
||||
from litellm.integrations.langfuse import _add_prompt_to_generation_params
|
||||
from litellm.integrations.langfuse.langfuse import _add_prompt_to_generation_params
|
||||
|
||||
clean_metadata = {
|
||||
"prompt": {
|
||||
|
@ -1232,7 +1232,7 @@ def test_langfuse_prompt_type(prompt):
|
|||
|
||||
|
||||
def test_langfuse_logging_metadata():
|
||||
from litellm.integrations.langfuse import log_requester_metadata
|
||||
from litellm.integrations.langfuse.langfuse import log_requester_metadata
|
||||
|
||||
metadata = {"key": "value", "requester_metadata": {"key": "value"}}
|
||||
|
||||
|
|
219
tests/logging_callback_tests/test_langfuse_unit_tests.py
Normal file
219
tests/logging_callback_tests/test_langfuse_unit_tests.py
Normal file
|
@ -0,0 +1,219 @@
|
|||
import json
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic.main import Model
|
||||
|
||||
sys.path.insert(
|
||||
0, os.path.abspath("../..")
|
||||
) # Adds the parent directory to the system-path
|
||||
|
||||
import pytest
|
||||
import litellm
|
||||
import asyncio
|
||||
import logging
|
||||
from litellm._logging import verbose_logger
|
||||
from litellm.integrations.langfuse.langfuse import (
|
||||
LangFuseLogger,
|
||||
)
|
||||
from litellm.integrations.langfuse.langfuse_handler import LangFuseHandler
|
||||
from litellm.types.utils import StandardCallbackDynamicParams
|
||||
from litellm.litellm_core_utils.litellm_logging import DynamicLoggingCache
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dynamic_logging_cache():
|
||||
return DynamicLoggingCache()
|
||||
|
||||
|
||||
global_langfuse_logger = LangFuseLogger(
|
||||
langfuse_public_key="global_public_key",
|
||||
langfuse_secret="global_secret",
|
||||
langfuse_host="https://global.langfuse.com",
|
||||
)
|
||||
|
||||
|
||||
# IMPORTANT: Test that passing both langfuse_secret_key and langfuse_secret works
|
||||
standard_params_1 = StandardCallbackDynamicParams(
|
||||
langfuse_public_key="test_public_key",
|
||||
langfuse_secret="test_secret",
|
||||
langfuse_host="https://test.langfuse.com",
|
||||
)
|
||||
|
||||
standard_params_2 = StandardCallbackDynamicParams(
|
||||
langfuse_public_key="test_public_key",
|
||||
langfuse_secret_key="test_secret",
|
||||
langfuse_host="https://test.langfuse.com",
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("globalLangfuseLogger", [None, global_langfuse_logger])
|
||||
@pytest.mark.parametrize("standard_params", [standard_params_1, standard_params_2])
|
||||
def test_get_langfuse_logger_for_request_with_dynamic_params(
|
||||
dynamic_logging_cache, globalLangfuseLogger, standard_params
|
||||
):
|
||||
"""
|
||||
If StandardCallbackDynamicParams contain langfuse credentials the returned Langfuse logger should use the dynamic params
|
||||
|
||||
the new Langfuse logger should be cached
|
||||
|
||||
Even if globalLangfuseLogger is provided, it should use dynamic params if they are passed
|
||||
"""
|
||||
|
||||
result = LangFuseHandler.get_langfuse_logger_for_request(
|
||||
standard_callback_dynamic_params=standard_params,
|
||||
in_memory_dynamic_logger_cache=dynamic_logging_cache,
|
||||
globalLangfuseLogger=globalLangfuseLogger,
|
||||
)
|
||||
|
||||
assert isinstance(result, LangFuseLogger)
|
||||
assert result.public_key == "test_public_key"
|
||||
assert result.secret_key == "test_secret"
|
||||
assert result.langfuse_host == "https://test.langfuse.com"
|
||||
|
||||
print("langfuse logger=", result)
|
||||
print("vars in langfuse logger=", vars(result))
|
||||
|
||||
# Check if the logger is cached
|
||||
cached_logger = dynamic_logging_cache.get_cache(
|
||||
credentials={
|
||||
"langfuse_public_key": "test_public_key",
|
||||
"langfuse_secret": "test_secret",
|
||||
"langfuse_host": "https://test.langfuse.com",
|
||||
},
|
||||
service_name="langfuse",
|
||||
)
|
||||
assert cached_logger is result
|
||||
|
||||
|
||||
@pytest.mark.parametrize("globalLangfuseLogger", [None, global_langfuse_logger])
|
||||
def test_get_langfuse_logger_for_request_with_no_dynamic_params(
|
||||
dynamic_logging_cache, globalLangfuseLogger
|
||||
):
|
||||
"""
|
||||
If StandardCallbackDynamicParams are not provided, the globalLangfuseLogger should be returned
|
||||
"""
|
||||
result = LangFuseHandler.get_langfuse_logger_for_request(
|
||||
standard_callback_dynamic_params=StandardCallbackDynamicParams(),
|
||||
in_memory_dynamic_logger_cache=dynamic_logging_cache,
|
||||
globalLangfuseLogger=globalLangfuseLogger,
|
||||
)
|
||||
|
||||
assert result is not None
|
||||
assert isinstance(result, LangFuseLogger)
|
||||
|
||||
print("langfuse logger=", result)
|
||||
|
||||
if globalLangfuseLogger is not None:
|
||||
assert result.public_key == "global_public_key"
|
||||
assert result.secret_key == "global_secret"
|
||||
assert result.langfuse_host == "https://global.langfuse.com"
|
||||
|
||||
|
||||
def test_dynamic_langfuse_credentials_are_passed():
|
||||
# Test when credentials are passed
|
||||
params_with_credentials = StandardCallbackDynamicParams(
|
||||
langfuse_public_key="test_key",
|
||||
langfuse_secret="test_secret",
|
||||
langfuse_host="https://test.langfuse.com",
|
||||
)
|
||||
assert (
|
||||
LangFuseHandler._dynamic_langfuse_credentials_are_passed(
|
||||
params_with_credentials
|
||||
)
|
||||
is True
|
||||
)
|
||||
|
||||
# Test when no credentials are passed
|
||||
params_without_credentials = StandardCallbackDynamicParams()
|
||||
assert (
|
||||
LangFuseHandler._dynamic_langfuse_credentials_are_passed(
|
||||
params_without_credentials
|
||||
)
|
||||
is False
|
||||
)
|
||||
|
||||
# Test when only some credentials are passed
|
||||
params_partial_credentials = StandardCallbackDynamicParams(
|
||||
langfuse_public_key="test_key"
|
||||
)
|
||||
assert (
|
||||
LangFuseHandler._dynamic_langfuse_credentials_are_passed(
|
||||
params_partial_credentials
|
||||
)
|
||||
is True
|
||||
)
|
||||
|
||||
|
||||
def test_get_dynamic_langfuse_logging_config():
|
||||
# Test with dynamic params
|
||||
dynamic_params = StandardCallbackDynamicParams(
|
||||
langfuse_public_key="dynamic_key",
|
||||
langfuse_secret="dynamic_secret",
|
||||
langfuse_host="https://dynamic.langfuse.com",
|
||||
)
|
||||
config = LangFuseHandler.get_dynamic_langfuse_logging_config(dynamic_params)
|
||||
assert config["langfuse_public_key"] == "dynamic_key"
|
||||
assert config["langfuse_secret"] == "dynamic_secret"
|
||||
assert config["langfuse_host"] == "https://dynamic.langfuse.com"
|
||||
|
||||
# Test with no dynamic params
|
||||
empty_params = StandardCallbackDynamicParams()
|
||||
config = LangFuseHandler.get_dynamic_langfuse_logging_config(empty_params)
|
||||
assert config["langfuse_public_key"] is None
|
||||
assert config["langfuse_secret"] is None
|
||||
assert config["langfuse_host"] is None
|
||||
|
||||
|
||||
def test_return_global_langfuse_logger():
|
||||
mock_cache = Mock()
|
||||
global_logger = LangFuseLogger(
|
||||
langfuse_public_key="global_key", langfuse_secret="global_secret"
|
||||
)
|
||||
|
||||
# Test with existing global logger
|
||||
result = LangFuseHandler._return_global_langfuse_logger(global_logger, mock_cache)
|
||||
assert result == global_logger
|
||||
|
||||
# Test without global logger, but with cached logger, should return cached logger
|
||||
mock_cache.get_cache.return_value = global_logger
|
||||
result = LangFuseHandler._return_global_langfuse_logger(None, mock_cache)
|
||||
assert result == global_logger
|
||||
|
||||
# Test without global logger and without cached logger, should create new logger
|
||||
mock_cache.get_cache.return_value = None
|
||||
with patch.object(
|
||||
LangFuseHandler,
|
||||
"_create_langfuse_logger_from_credentials",
|
||||
return_value=global_logger,
|
||||
):
|
||||
result = LangFuseHandler._return_global_langfuse_logger(None, mock_cache)
|
||||
assert result == global_logger
|
||||
|
||||
|
||||
def test_get_langfuse_logger_for_request_with_cached_logger():
|
||||
"""
|
||||
Test that get_langfuse_logger_for_request returns the cached logger if it exists when dynamic params are passed
|
||||
"""
|
||||
mock_cache = Mock()
|
||||
cached_logger = LangFuseLogger(
|
||||
langfuse_public_key="cached_key", langfuse_secret="cached_secret"
|
||||
)
|
||||
mock_cache.get_cache.return_value = cached_logger
|
||||
|
||||
dynamic_params = StandardCallbackDynamicParams(
|
||||
langfuse_public_key="test_key",
|
||||
langfuse_secret="test_secret",
|
||||
langfuse_host="https://test.langfuse.com",
|
||||
)
|
||||
|
||||
result = LangFuseHandler.get_langfuse_logger_for_request(
|
||||
standard_callback_dynamic_params=dynamic_params,
|
||||
in_memory_dynamic_logger_cache=mock_cache,
|
||||
globalLangfuseLogger=None,
|
||||
)
|
||||
|
||||
assert result == cached_logger
|
||||
mock_cache.get_cache.assert_called_once()
|
Loading…
Add table
Add a link
Reference in a new issue