Use run tree post/patch

This commit is contained in:
William Fu-Hinthorn 2025-06-04 14:47:38 -07:00
parent b149cce5f8
commit 86aad4a527
2 changed files with 7 additions and 34 deletions

View File

@ -3,7 +3,6 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
import warnings
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import TYPE_CHECKING, Any, Optional, Union from typing import TYPE_CHECKING, Any, Optional, Union
@ -12,7 +11,6 @@ from uuid import UUID
from langsmith import Client from langsmith import Client
from langsmith import run_trees as rt from langsmith import run_trees as rt
from langsmith import utils as ls_utils from langsmith import utils as ls_utils
from pydantic import PydanticDeprecationWarning
from tenacity import ( from tenacity import (
Retrying, Retrying,
retry_if_exception_type, retry_if_exception_type,
@ -67,21 +65,6 @@ def _get_executor() -> ThreadPoolExecutor:
return _EXECUTOR 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): class LangChainTracer(BaseTracer):
"""Implementation of the SharedTracer that POSTS to the LangChain endpoint.""" """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: def _persist_run_single(self, run: Run) -> None:
"""Persist a run.""" """Persist a run."""
try: try:
run_dict = _run_to_dict(run) run.extra["runtime"] = get_runtime_environment()
run_dict["tags"] = self._get_tags(run) run.tags = self._get_tags(run)
extra = run_dict.get("extra", {}) if run.ls_client is not self.client:
extra["runtime"] = get_runtime_environment() run.ls_client = self.client
run_dict["extra"] = extra run.post()
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)
except Exception as e: except Exception as e:
# Errors are swallowed by the thread executor so we need to log them here # Errors are swallowed by the thread executor so we need to log them here
log_error_once("post", e) log_error_once("post", e)
@ -238,10 +214,7 @@ class LangChainTracer(BaseTracer):
def _update_run_single(self, run: Run) -> None: def _update_run_single(self, run: Run) -> None:
"""Update a run.""" """Update a run."""
try: try:
exclude_inputs = run.extra.get("inputs_is_truthy", False) run.patch(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)
except Exception as e: except Exception as e:
# Errors are swallowed by the thread executor so we need to log them here # Errors are swallowed by the thread executor so we need to log them here
log_error_once("patch", e) log_error_once("patch", e)

View File

@ -7,7 +7,7 @@ authors = []
license = {text = "MIT"} license = {text = "MIT"}
requires-python = ">=3.9" requires-python = ">=3.9"
dependencies = [ dependencies = [
"langsmith<0.4,>=0.1.126", "langsmith<0.4,>=0.3.45",
"tenacity!=8.4.0,<10.0.0,>=8.1.0", "tenacity!=8.4.0,<10.0.0,>=8.1.0",
"jsonpatch<2.0,>=1.33", "jsonpatch<2.0,>=1.33",
"PyYAML>=5.3", "PyYAML>=5.3",