Skip to content

Commit 4e695d1

Browse files
committed
fix: support async function tracing in trace_call and trace_function (#595)
1 parent abe0204 commit 4e695d1

1 file changed

Lines changed: 42 additions & 4 deletions

File tree

backend/app/rag/tracing.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,28 @@ def _build_traceable(name: str, run_type: str, metadata: Optional[dict[str, Any]
5757
return _langsmith_traceable(name=name, run_type=run_type)
5858

5959

60+
import inspect
61+
62+
async def async_trace_call(
63+
name: str,
64+
fn: Callable[..., Any],
65+
*args: Any,
66+
run_type: str = "chain",
67+
metadata: Optional[dict[str, Any]] = None,
68+
**kwargs: Any,
69+
) -> Any:
70+
"""Execute an asynchronous callable with LangSmith tracing when available."""
71+
if not LANGSMITH_ENABLED:
72+
return await fn(*args, **kwargs)
73+
74+
decorator = _build_traceable(name, run_type, metadata)
75+
if decorator is None:
76+
return await fn(*args, **kwargs)
77+
78+
traced_fn = decorator(fn)
79+
return await traced_fn(*args, **kwargs)
80+
81+
6082
def trace_call(
6183
name: str,
6284
fn: Callable[..., Any],
@@ -65,7 +87,10 @@ def trace_call(
6587
metadata: Optional[dict[str, Any]] = None,
6688
**kwargs: Any,
6789
) -> Any:
68-
"""Execute a callable with LangSmith tracing when available."""
90+
"""Execute a callable with LangSmith tracing when available. Supports both sync and async."""
91+
if inspect.iscoroutinefunction(fn):
92+
return async_trace_call(name, fn, *args, run_type=run_type, metadata=metadata, **kwargs)
93+
6994
if not LANGSMITH_ENABLED:
7095
return fn(*args, **kwargs)
7196

@@ -83,8 +108,22 @@ def trace_function(
83108
run_type: str = "chain",
84109
metadata_factory: Optional[Callable[..., dict[str, Any]]] = None,
85110
) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
86-
"""Decorator wrapper that becomes a no-op when LangSmith is disabled."""
111+
"""Decorator wrapper that becomes a no-op when LangSmith is disabled. Supports both sync and async."""
87112
def decorator(fn: Callable[..., Any]) -> Callable[..., Any]:
113+
if inspect.iscoroutinefunction(fn):
114+
@wraps(fn)
115+
async def async_wrapped(*args: Any, **kwargs: Any) -> Any:
116+
metadata = metadata_factory(*args, **kwargs) if metadata_factory else None
117+
return await trace_call(
118+
name,
119+
fn,
120+
*args,
121+
run_type=run_type,
122+
metadata=metadata,
123+
**kwargs,
124+
)
125+
return async_wrapped
126+
88127
@wraps(fn)
89128
def wrapped(*args: Any, **kwargs: Any) -> Any:
90129
metadata = metadata_factory(*args, **kwargs) if metadata_factory else None
@@ -96,7 +135,6 @@ def wrapped(*args: Any, **kwargs: Any) -> Any:
96135
metadata=metadata,
97136
**kwargs,
98137
)
99-
100138
return wrapped
101139

102-
return decorator
140+
return decorator

0 commit comments

Comments
 (0)