From 86aad4a52702bdcb074d71c64e199482e62ad74c Mon Sep 17 00:00:00 2001 From: William Fu-Hinthorn <13333726+hinthornw@users.noreply.github.com> Date: Wed, 4 Jun 2025 14:47:38 -0700 Subject: [PATCH] Use run tree post/patch --- libs/core/langchain_core/tracers/langchain.py | 39 +++---------------- libs/core/pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 34 deletions(-) diff --git a/libs/core/langchain_core/tracers/langchain.py b/libs/core/langchain_core/tracers/langchain.py index ac6dc218e0e..acd25f6681f 100644 --- a/libs/core/langchain_core/tracers/langchain.py +++ b/libs/core/langchain_core/tracers/langchain.py @@ -3,7 +3,6 @@ from __future__ import annotations import logging -import warnings from concurrent.futures import ThreadPoolExecutor from datetime import datetime, timezone from typing import TYPE_CHECKING, Any, Optional, Union @@ -12,7 +11,6 @@ from uuid import UUID from langsmith import Client from langsmith import run_trees as rt from langsmith import utils as ls_utils -from pydantic import PydanticDeprecationWarning from tenacity import ( Retrying, retry_if_exception_type, @@ -67,21 +65,6 @@ def _get_executor() -> ThreadPoolExecutor: return _EXECUTOR -def _run_to_dict(run: Run, *, exclude_inputs: bool = False) -> dict: - # TODO: Update once langsmith moves to Pydantic V2 and we can swap run.dict for - # run.model_dump - with warnings.catch_warnings(): - warnings.simplefilter("ignore", category=PydanticDeprecationWarning) - - res = { - **run.dict(exclude={"child_runs", "inputs", "outputs"}), - "outputs": run.outputs, - } - if not exclude_inputs: - res["inputs"] = run.inputs - return res - - class LangChainTracer(BaseTracer): """Implementation of the SharedTracer that POSTS to the LangChain endpoint.""" @@ -218,18 +201,11 @@ class LangChainTracer(BaseTracer): def _persist_run_single(self, run: Run) -> None: """Persist a run.""" try: - run_dict = _run_to_dict(run) - run_dict["tags"] = self._get_tags(run) - extra = run_dict.get("extra", {}) - extra["runtime"] = get_runtime_environment() - run_dict["extra"] = extra - inputs_ = run_dict.get("inputs") - if inputs_ and (len(inputs_) > 1 or bool(next(iter(inputs_.values())))): - inputs_is_truthy = True - else: - inputs_is_truthy = False - run.extra["inputs_is_truthy"] = inputs_is_truthy - self.client.create_run(**run_dict, project_name=self.project_name) + run.extra["runtime"] = get_runtime_environment() + run.tags = self._get_tags(run) + if run.ls_client is not self.client: + run.ls_client = self.client + run.post() except Exception as e: # Errors are swallowed by the thread executor so we need to log them here log_error_once("post", e) @@ -238,10 +214,7 @@ class LangChainTracer(BaseTracer): def _update_run_single(self, run: Run) -> None: """Update a run.""" try: - exclude_inputs = run.extra.get("inputs_is_truthy", False) - run_dict = _run_to_dict(run, exclude_inputs=exclude_inputs) - run_dict["tags"] = self._get_tags(run) - self.client.update_run(run.id, **run_dict) + run.patch(exclude_inputs=run.extra.get("inputs_is_truthy", False)) except Exception as e: # Errors are swallowed by the thread executor so we need to log them here log_error_once("patch", e) diff --git a/libs/core/pyproject.toml b/libs/core/pyproject.toml index b31ee92cd83..92b543d8382 100644 --- a/libs/core/pyproject.toml +++ b/libs/core/pyproject.toml @@ -7,7 +7,7 @@ authors = [] license = {text = "MIT"} requires-python = ">=3.9" dependencies = [ - "langsmith<0.4,>=0.1.126", + "langsmith<0.4,>=0.3.45", "tenacity!=8.4.0,<10.0.0,>=8.1.0", "jsonpatch<2.0,>=1.33", "PyYAML>=5.3",