Skip to content

Enhance Langfuse Integration: Add /responses Support, Fix /threads Context, and Decouple Dependencies #248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

avirajsingh7
Copy link
Collaborator

@avirajsingh7 avirajsingh7 commented Jun 25, 2025

Summary

Closes #210: Removes hard dependency on Langfuse for /threads and /response, allowing use with only OpenAI credentials.

Fixes #249: Eliminates race conditions caused by shared langfuse_context across async requests and background jobs.

Closes #244: Brings tracing to /responses, ensuring consistent Langfuse session grouping.

Key Changes:

  • Introduced LangfuseTracer, a modular tracing utility that conditionally activates based on credentials.
  • Context is now thread-safe: each request and scheduled job maintains its own tracer instance.
  • Ensured compatibility: Langfuse tracing is bypassed if credentials are not configured.
  • Set session_id = thread_id to logically group traces per conversation thread.

Grouping of traces in Response API

To group traces by conversation:

  • For the first response in a conversation, we generate a new session_id and associate it with the trace and we will add tag to this trace which is response_id . For subsequent responses in the same conversation:
  • We query tags in Langfuse traces using the previous response_id to fetch the trace metadata.
  • From this metadata, we extract the associated session_id.
  • The new trace for the current response is then assigned the same session_id, effectively grouping all related traces under the same conversation session.

Checklist

  • Ran fastapi run --reload app/main.py or docker compose up in the repository root and test.
  • If you've fixed a bug or added code that is tested and has test cases.

Notes

Please add here if any other information is required for the reviewer.

@avirajsingh7 avirajsingh7 self-assigned this Jun 27, 2025
@avirajsingh7 avirajsingh7 added the enhancement New feature or request label Jun 27, 2025
@avirajsingh7 avirajsingh7 changed the title Add Langfuse Tracing Support to Response API Enhance Langfuse Integration: Add /responses Support, Fix /threads Context, and Decouple Dependencies Jun 27, 2025
@avirajsingh7 avirajsingh7 moved this to In Progress in Dev Priorities Jun 27, 2025
Copy link

codecov bot commented Jun 27, 2025

Codecov Report

Attention: Patch coverage is 65.26316% with 33 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
backend/app/api/routes/responses.py 56.25% 14 Missing ⚠️
backend/app/core/langfuse/langfuse.py 75.60% 10 Missing ⚠️
backend/app/api/routes/threads.py 52.63% 9 Missing ⚠️

📢 Thoughts on this report? Let us know!

session_id: Optional[str] = None,
response_id: Optional[str] = None,
):
self.session_id = session_id or str(uuid.uuid4())
Copy link
Collaborator

@nishika26 nishika26 Jun 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't thread id used as session id, is it something that we can create as well?

if response_id:
traces = self.langfuse.fetch_traces(tags=response_id).data
if traces:
self.session_id = traces[0].session_id
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify, is this because since all the traces will belong under one session so it wont matter if we retrieve session id from 1st trace or lets say from 11th trace?


def update_trace(self, tags: list[str], output: Dict[str, Any]):
if self.trace:
self.trace.update(tags=tags, output=output)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are tags here

)

def flush(self):
self.langfuse.flush()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As stated here that langfuse.flush() is blocking so this holds a tiny possibility of causing a problem - check here

provider="langfuse",
project_id=request.project_id,
)
tracer = LangfuseTracer(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the case where it does not get langfuse credential, what happens. Same question for threads endpoint as well

@nishika26
Copy link
Collaborator

Have you tested a case where you use threads and/or response endpoint for a user with no langfuse creds given, directly after you run these endpoint(s) for a user with langfuse creds given

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request ready-for-review
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

Shared langfuse_context causes race condition when handling concurrent requests Langfuse: Trace Response API Langfuse Required for /threads
2 participants