From 385859dd2d4f8ae8968e7b6cda6a0d9930c5dc4a Mon Sep 17 00:00:00 2001 From: Konstantinos Koukopoulos Date: Mon, 30 Jun 2025 19:38:10 +0300 Subject: [PATCH 1/2] Fix async generator case in decorator The decorator code in `langfuse/_client/observe.py` seems to have been built to support the case of observing an async generator however it misses the mark by using `asyncio.iscoroutinefunction` to decide whether to wrap it in the async or the sync implementation. That method doesn't detect async generators. The solution is to use the inspect module and check for both cases. --- langfuse/_client/observe.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/langfuse/_client/observe.py b/langfuse/_client/observe.py index e37e91e99..7288e4e81 100644 --- a/langfuse/_client/observe.py +++ b/langfuse/_client/observe.py @@ -1,4 +1,3 @@ -import asyncio import inspect import logging import os @@ -169,7 +168,7 @@ def decorator(func: F) -> F: capture_output=should_capture_output, transform_to_string=transform_to_string, ) - if asyncio.iscoroutinefunction(func) + if inspect.iscoroutinefunction(func) or inspect.isasyncgenfunction(func) else self._sync_observe( func, name=name, From 2e03b0324c2b4cdf7eb8593fbd1946abfe4bf69b Mon Sep 17 00:00:00 2001 From: Konstantinos Koukopoulos Date: Tue, 1 Jul 2025 12:44:39 +0300 Subject: [PATCH 2/2] fixup --- langfuse/_client/observe.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/langfuse/_client/observe.py b/langfuse/_client/observe.py index 7288e4e81..ce4d862d5 100644 --- a/langfuse/_client/observe.py +++ b/langfuse/_client/observe.py @@ -168,7 +168,7 @@ def decorator(func: F) -> F: capture_output=should_capture_output, transform_to_string=transform_to_string, ) - if inspect.iscoroutinefunction(func) or inspect.isasyncgenfunction(func) + if inspect.iscoroutinefunction(func) else self._sync_observe( func, name=name, @@ -354,6 +354,14 @@ def sync_wrapper(*args, **kwargs): result, transform_to_string, ) + elif inspect.isasyncgen(result): + is_return_type_generator = True + + return self._wrap_async_generator_result( + langfuse_span_or_generation, + result, + transform_to_string, + ) langfuse_span_or_generation.update(output=result)