Skip to content

Commit c05327d

Browse files
barnuriautofix-ci[bot]ogabrielluizcoderabbitai[bot]
authored
fix: improve LangSmith traces with added details (#7897)
* langsmith-improve * langsmith-improve * [autofix.ci] apply automated fixes * Update langsmith.py * fix lint * [autofix.ci] apply automated fixes * Update langsmith.py * Refactor LangSmithTracer to improve type checking and error handling - Moved RunTree import to the appropriate section for clarity. - Updated end_trace method to check both readiness and existence of run_tree before proceeding. * readd if not self._ready check * solve invalid run types * Update src/backend/base/langflow/services/tracing/langsmith.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update src/backend/base/langflow/services/tracing/langsmith.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update src/backend/base/langflow/services/tracing/langsmith.py Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 1903f60 commit c05327d

1 file changed

Lines changed: 60 additions & 27 deletions

File tree

src/backend/base/langflow/services/tracing/langsmith.py

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from uuid import UUID
1919

2020
from langchain.callbacks.base import BaseCallbackHandler
21+
from langsmith.run_trees import RunTree
2122

2223
from langflow.graph.vertex.base import Vertex
2324
from langflow.services.tracing.schema import Log
@@ -29,28 +30,51 @@ def __init__(self, trace_name: str, trace_type: str, project_name: str, trace_id
2930
self._ready = self.setup_langsmith()
3031
if not self._ready:
3132
return
32-
from langsmith.run_trees import RunTree
33-
3433
self.trace_name = trace_name
3534
self.trace_type = trace_type
3635
self.project_name = project_name
3736
self.trace_id = trace_id
38-
self._run_tree = RunTree(
39-
project_name=self.project_name,
40-
name=self.trace_name,
41-
run_type=self.trace_type,
42-
id=self.trace_id,
43-
)
44-
self._run_tree.add_event({"name": "Start", "time": datetime.now(timezone.utc).isoformat()})
37+
from langsmith import get_current_run_tree
38+
from langsmith.run_helpers import trace
39+
40+
self._run_tree: RunTree | None = None
4541
self._children: dict[str, RunTree] = {}
46-
except Exception: # noqa: BLE001
47-
logger.debug("Error setting up LangSmith tracer")
42+
self._children_traces: dict[str, trace] = {}
43+
self._child_link: dict[str, str] = {}
44+
parent = get_current_run_tree()
45+
if parent is not None and (parent.id == trace_id or parent.name == trace_name):
46+
# duplicate init of LangSmithTracer with same trace_id\\trace_name, using current run tree
47+
self._run_tree = parent
48+
else:
49+
self._trace = trace(
50+
project_name=self.project_name,
51+
name=self.trace_name,
52+
run_type=self.get_run_type(self.trace_type),
53+
run_id=self.trace_id if parent is None else None,
54+
parent=parent,
55+
)
56+
self._run_tree = self._trace.__enter__()
57+
self._run_tree.add_event({"name": "Start", "time": datetime.now(timezone.utc).isoformat()})
58+
self._run_tree.post()
59+
except Exception as ex: # noqa: BLE001
60+
logger.warning(f"Error setting up LangSmith tracer: {ex}")
4861
self._ready = False
4962

5063
@property
5164
def ready(self):
5265
return self._ready
5366

67+
def get_run_type(self, run_type: str) -> str:
68+
from typing import get_args
69+
70+
from langsmith import client
71+
72+
valid_run_types = set(get_args(client.RUN_TYPE_T))
73+
if run_type not in valid_run_types:
74+
logger.warning("Run type %s is not valid. Using default run type 'chain'.", run_type)
75+
return "chain"
76+
return run_type
77+
5478
def setup_langsmith(self) -> bool:
5579
if os.getenv("LANGCHAIN_API_KEY") is None:
5680
return False
@@ -66,7 +90,7 @@ def setup_langsmith(self) -> bool:
6690

6791
def add_trace(
6892
self,
69-
trace_id: str, # noqa: ARG002
93+
trace_id: str,
7094
trace_name: str,
7195
trace_type: str,
7296
inputs: dict[str, Any],
@@ -78,15 +102,20 @@ def add_trace(
78102
processed_inputs = {}
79103
if inputs:
80104
processed_inputs = self._convert_to_langchain_types(inputs)
81-
child = self._run_tree.create_child(
105+
106+
from langsmith.run_helpers import trace
107+
108+
child_trace = trace(
82109
name=trace_name,
83-
run_type=trace_type, # type: ignore[arg-type]
110+
run_type=self.get_run_type(trace_type),
111+
parent=self._run_tree,
84112
inputs=processed_inputs,
113+
metadata=self._convert_to_langchain_types(metadata) if metadata else None,
85114
)
86-
if metadata:
87-
child.add_metadata(self._convert_to_langchain_types(metadata))
88-
self._children[trace_name] = child
89-
self._child_link: dict[str, str] = {}
115+
child = child_trace.__enter__()
116+
child.post()
117+
self._children[trace_id] = child
118+
self._children_traces[trace_id] = child_trace
90119

91120
def _convert_to_langchain_types(self, io_dict: dict[str, Any]):
92121
converted = {}
@@ -117,15 +146,18 @@ def _convert_to_langchain_type(self, value):
117146

118147
def end_trace(
119148
self,
120-
trace_id: str, # noqa: ARG002
121-
trace_name: str,
149+
trace_id: str,
150+
trace_name: str, # noqa: ARG002
122151
outputs: dict[str, Any] | None = None,
123152
error: Exception | None = None,
124153
logs: Sequence[Log | dict] = (),
125154
):
126-
if not self._ready or trace_name not in self._children:
155+
if not self._ready or not self._run_tree:
156+
return
157+
if trace_id not in self._children:
158+
logger.warning(f"Trace {trace_id} not found in children traces")
127159
return
128-
child = self._children[trace_name]
160+
child = self._children[trace_id]
129161
raw_outputs = {}
130162
processed_outputs = {}
131163
if outputs:
@@ -136,10 +168,8 @@ def end_trace(
136168
child.add_metadata(self._convert_to_langchain_types({"logs": {log.get("name"): log for log in logs_dicts}}))
137169
child.add_metadata(self._convert_to_langchain_types({"outputs": raw_outputs}))
138170
child.end(outputs=processed_outputs, error=self._error_to_string(error))
139-
if error:
140-
child.patch()
141-
else:
142-
child.post()
171+
self._children_traces[trace_id].__exit__(None, None, None)
172+
self._child_link[trace_id] = child.get_url()
143173

144174
@staticmethod
145175
def _error_to_string(error: Exception | None):
@@ -162,7 +192,10 @@ def end(
162192
if metadata:
163193
self._run_tree.add_metadata(serialize(metadata))
164194
self._run_tree.end(outputs=serialize(outputs), error=self._error_to_string(error))
165-
self._run_tree.post()
195+
self._run_tree.patch()
196+
self._run_link = self._run_tree.get_url()
197+
if getattr(self, "_trace", None):
198+
self._trace.__exit__()
166199

167200
@property
168201
def run_link(self):

0 commit comments

Comments
 (0)