Repository: BerriAI/litellm
Pull request: Fix: Problem with langfuse_tags when using litellm proxy with langfus…

## Title
Fix: Problem with langfuse_tags when using litellm proxy with langfuse integration 

## Relevant issues

Fixes #7801

## Type

<!-- Select the type of Pull Request -->
<!-- Keep only the necessary ones -->

🐛 Bug Fix

## Changes

<!-- List of changes -->
- Updated the tags processing logic to parse langfuse_tags using json.loads() to ensure it is properly handled as a list.

## [REQUIRED] Testing - Attach a screenshot of any new tests passing locally
If UI changes, send a screenshot/GIF of working UI fixes

<!-- Test procedure -->



Problem statement:
[Bug]: Problem with langfuse_tags when using litellm proxy with langfuse integration
### What happened?

When integrating litellm proxy with langfuse, specifying langfuse_tags in the HTTP header is expected to populate the Tags field in langfuse. However, in practice, attempting this results in the proxy crashing with the following error message:

```
07:52:12 - LiteLLM:ERROR: langfuse.py:731 - Langfuse Layer Error - Traceback (most recent call last):
  File "/home/ubuntu/work/xxx/venv/lib/python3.12/site-packages/litellm/integrations/langfuse/langfuse.py", line 499, in _log_langfuse_v2
    tags.append(f"{key}:{value}")
    ^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'append'
```

This error occurs at line 500 in litellm/integrations/langfuse/langfuse.py and seems to be caused by the tags being treated as a string instead of being parsed into a list.

Proposed Solution:
I made the following change, which resolved the issue. By ensuring tags is properly parsed as a JSON list, the error no longer occurs.
Before:
```python
tags = metadata.pop("tags", []) if supports_tags else []
```
After
```python
import json
tags = json.loads(metadata.pop("tags", "[]")) if supports_tags else []
```

Next Steps:
I plan to submit a pull request with this fix to address the issue. Please let me know if there are additional steps or considerations for this fix.

### Relevant log output

```shell
The error behavior differs when litellm_config.yaml contains the following setting:

litellm_settings:
  langfuse_default_tags: ["cache_hit", "cache_key", "proxy_base_url", "user_api_key_alias", "user_api_key_user_id", "user_api_key_user_email", "user_api_key_team_alias", "semantic-similarity", "proxy_base_url"]


Without setting langfuse_default_tags:
When this setting is not specified, the following error occurs:
```text
07:48:27 - LiteLLM:DEBUG: langfuse.py:594 - trace: 0
1 validation error for TraceBody
tags
  value is not a valid list (type=type_error.list)
Traceback (most recent call last):
  File "/home/ubuntu/work/xxx/venv/lib/python3.12/site-packages/langfuse/client.py", line 1432, in trace
    new_body = TraceBody(**new_dict)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/home/ubuntu/work/xxx/venv/lib/python3.12/site-packages/pydantic/v1/main.py", line 341, in __init__
    raise validation_error
pydantic.v1.error_wrappers.ValidationError: 1 validation error for TraceBody
tags
  value is not a valid list (type=type_error.list)
```

With langfuse_default_tags set:
When the langfuse_default_tags setting is specified, the following error occurs instead:
```
07:52:12 - LiteLLM:ERROR: langfuse.py:731 - Langfuse Layer Error - Traceback (most recent call last):
  File "/home/ubuntu/work/xxx/venv/lib/python3.12/site-packages/litellm/integrations/langfuse/langfuse.py", line 499, in _log_langfuse_v2
    tags.append(f"{key}:{value}")
    ^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'append'
```
```


### Are you a ML Ops Team?

No

### What LiteLLM version are you on ?

v1.58.1

### Twitter / LinkedIn details

_No response_

Hints from issue discussion:

Commit message: Fix: Problem with langfuse_tags when using litellm proxy with langfuse integration (#7801)

Patch to review:
diff --git a/litellm/integrations/langfuse/langfuse.py b/litellm/integrations/langfuse/langfuse.py
index 2a459af9b91e..3b4f38dd9f34 100644
--- a/litellm/integrations/langfuse/langfuse.py
+++ b/litellm/integrations/langfuse/langfuse.py
@@ -1,6 +1,7 @@
 #### What this does ####
 #    On success, logs events to Langfuse
 import copy
+import json
 import os
 import traceback
 from collections.abc import MutableMapping, MutableSequence, MutableSet
@@ -457,7 +458,7 @@ def _log_langfuse_v2(  # noqa: PLR0915
             supports_costs = langfuse_version >= Version("2.7.3")
             supports_completion_start_time = langfuse_version >= Version("2.7.3")
 
-            tags = metadata.pop("tags", []) if supports_tags else []
+            tags = json.loads(metadata.pop("tags", "[]")) if supports_tags else []
 
             standard_logging_object: Optional[StandardLoggingPayload] = cast(
                 Optional[StandardLoggingPayload],


Code review comments:
diff_hunk: @@ -457,7 +458,7 @@ def _log_langfuse_v2(  # noqa: PLR0915
             supports_costs = langfuse_version >= Version("2.7.3")
             supports_completion_start_time = langfuse_version >= Version("2.7.3")
 
-            tags = metadata.pop("tags", []) if supports_tags else []
+            tags = json.loads(metadata.pop("tags", "[]")) if supports_tags else []
path: litellm/integrations/langfuse/langfuse.py
text: @user1:
please make this a helper function - call it _get_langfuse_tags 

@author:
I have split the method as per your suggestion. What do you think?