Repository: BerriAI/litellm
Pull request: Langfuse integration support for `parent_observation_id` parameter
## Title

Langfuse integration support for `parent_observation_id` parameter

## Relevant issues

Fixes #3558 
Related to #1832 

## Type

🆕 New Feature
📖 Documentation

## Changes

`LangFuseLogger` now receives the `parent_observation_id` metadata value and passes it along to the Langfuse generation object.

## Testing

-

## Notes

-

## Pre-Submission Checklist (optional but appreciated):

- [x] I have included relevant documentation updates (stored in /docs/my-website)

## OS Tests (optional but appreciated):

- [ ] Tested on Windows
- [x] Tested on MacOS
- [ ] Tested on Linux


Problem statement:
[Feature]: Langfuse integration support for `parent_observation_id ` parameter
### The Feature

Currently, we cannot pass the `parent_observation_id ` metadata parameter to LiteLLM to attach Langfuse generation objects to a given parent observation. We can therefore not create nested Langfuse generation objects.



### Motivation, pitch

I want to have deeply nested Langfuse observation graphs and LiteLLM generations currently do not support this.

### Twitter / LinkedIn details

-

Hints from issue discussion:

Commit message: Update langfuse integration docs wiht the new `parent_observation_id` parameter

Patch to review:
diff --git a/docs/my-website/docs/observability/langfuse_integration.md b/docs/my-website/docs/observability/langfuse_integration.md
index ebf20b633595..9aa9d899c813 100644
--- a/docs/my-website/docs/observability/langfuse_integration.md
+++ b/docs/my-website/docs/observability/langfuse_integration.md
@@ -122,6 +122,7 @@ response = completion(
   metadata={
       "generation_name": "ishaan-test-generation",  # set langfuse Generation Name
       "generation_id": "gen-id22",                  # set langfuse Generation ID 
+      "parent_observation_id": "obs-id9"            # set langfuse Parent Observation ID
       "version":  "test-generation-version"         # set langfuse Generation Version
       "trace_user_id": "user-id2",                  # set langfuse Trace User ID
       "session_id": "session-1",                    # set langfuse Session ID
@@ -169,9 +170,10 @@ The following parameters can be updated on a continuation of a trace by passing
 
 #### Generation Specific Parameters
 
-* `generation_id`   - Identifier for the generation, auto-generated by default
-* `generation_name` - Identifier for the generation, auto-generated by default
-* `prompt`          - Langfuse prompt object used for the generation, defaults to None
+* `generation_id`         - Identifier for the generation, auto-generated by default
+* `generation_name`       - Identifier for the generation, auto-generated by default
+* `parent_observation_id` - Identifier for the parent observation, defaults to `None`
+* `prompt`                - Langfuse prompt object used for the generation, defaults to `None`
 
 Any other key value pairs passed into the metadata not listed in the above spec for a `litellm` completion will be added as a metadata key value pair for the generation.
 
diff --git a/litellm/integrations/langfuse.py b/litellm/integrations/langfuse.py
index caf5437b2426..49c0f6c69b0a 100644
--- a/litellm/integrations/langfuse.py
+++ b/litellm/integrations/langfuse.py
@@ -437,6 +437,7 @@ def _log_langfuse_v2(
             generation_params = {
                 "name": generation_name,
                 "id": clean_metadata.pop("generation_id", generation_id),
+                "parent_observation_id": metadata.get("parent_observation_id"),
                 "start_time": start_time,
                 "end_time": end_time,
                 "model": kwargs["model"],


Code review comments:
diff_hunk: @@ -437,6 +437,7 @@ def _log_langfuse_v2(
             generation_params = {
                 "name": generation_name,
                 "id": clean_metadata.pop("generation_id", generation_id),
+                "parent_observation_id": metadata.get("parent_observation_id"),
path: litellm/integrations/langfuse.py
text: @user1:
this would raise an error if the value is None i believe, as the dictionary would now contain a 'None' object

can you instead have this below in an if metadata.get('parent_observation_id') is not None statement

@author:
I have this PR branch in production in our application it does not raise an error. 
But I will add it anyway to make sure, that future Langfuse updates do not potentially break this!