Skip to content

Commit

Permalink
[Python] Use _name (#1008)
Browse files Browse the repository at this point in the history
Fixes #1004
  • Loading branch information
hinthornw committed Sep 16, 2024
1 parent de3fec5 commit 5ed1a6f
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 4 deletions.
2 changes: 1 addition & 1 deletion python/langsmith/evaluation/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ def __call__(

def __repr__(self) -> str:
"""Represent the DynamicRunEvaluator object."""
return f"<DynamicComparisonRunEvaluator {getattr(self.func, '__name__')}>"
return f"<DynamicComparisonRunEvaluator {self._name}>"

@staticmethod
def _get_tags(runs: Sequence[Run]) -> List[str]:
Expand Down
2 changes: 1 addition & 1 deletion python/langsmith/run_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,7 @@ def _setup_run(
)
id_ = id_ or str(uuid.uuid4())
signature = inspect.signature(func)
name_ = name or func.__name__
name_ = name or utils._get_function_name(func)
docstring = func.__doc__
extra_inner = _collect_extra(extra_outer, langsmith_extra)
outer_metadata = _METADATA.get()
Expand Down
2 changes: 1 addition & 1 deletion python/langsmith/run_trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class RunTree(ls_schemas.RunBase):
)
session_id: Optional[UUID] = Field(default=None, alias="project_id")
extra: Dict = Field(default_factory=dict)
_client: Optional[Client] = Field(default=None)
_client: Optional[Client] = None
dotted_order: str = Field(
default="", description="The order of the run in the tree."
)
Expand Down
18 changes: 18 additions & 0 deletions python/langsmith/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -771,3 +771,21 @@ def get_host_url(web_url: Optional[str], api_url: str):
else:
link = "https://smith.langchain.com"
return link


def _get_function_name(fn: Callable, depth: int = 0) -> str:
if depth > 2 or not callable(fn):
return str(fn)

if hasattr(fn, "__name__"):
return fn.__name__

if isinstance(fn, functools.partial):
return _get_function_name(fn.func, depth + 1)

if hasattr(fn, "__call__"):
if hasattr(fn, "__class__") and hasattr(fn.__class__, "__name__"):
return fn.__class__.__name__
return _get_function_name(fn.__call__, depth + 1)

return str(fn)
2 changes: 1 addition & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "langsmith"
version = "0.1.120"
version = "0.1.121"
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
authors = ["LangChain <support@langchain.dev>"]
license = "MIT"
Expand Down
21 changes: 21 additions & 0 deletions python/tests/unit_tests/evaluation/test_evaluator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import logging
import uuid
from typing import Any, Optional
from unittest import mock
from unittest.mock import MagicMock
Expand All @@ -8,6 +9,8 @@

from langsmith import schemas
from langsmith.evaluation.evaluator import (
ComparisonEvaluationResult,
DynamicComparisonRunEvaluator,
DynamicRunEvaluator,
EvaluationResult,
EvaluationResults,
Expand Down Expand Up @@ -48,6 +51,24 @@ def sample_evaluator(run: Run, example: Optional[Example]) -> EvaluationResult:
assert result.score == 1.0


async def test_dynamie_comparison_run_evaluator():
def foo(runs: list, example):
return ComparisonEvaluationResult(key="bar", scores={uuid.uuid4(): 3.1})

async def afoo(runs: list, example):
return ComparisonEvaluationResult(key="bar", scores={uuid.uuid4(): 3.1})

evaluators = [
DynamicComparisonRunEvaluator(foo),
DynamicComparisonRunEvaluator(afoo),
DynamicComparisonRunEvaluator(foo, afoo),
]
for e in evaluators:
res = await e.acompare_runs([], None)
assert res.key == "bar"
repr(e)


def test_run_evaluator_decorator_dict(run_1: Run, example_1: Example):
@run_evaluator
def sample_evaluator(run: Run, example: Optional[Example]) -> dict:
Expand Down
6 changes: 6 additions & 0 deletions python/tests/unit_tests/test_run_trees.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from langsmith import run_trees
from langsmith.client import Client
from langsmith.run_trees import RunTree


def test_run_tree_accepts_tpe() -> None:
Expand All @@ -19,6 +20,11 @@ def test_run_tree_accepts_tpe() -> None:
)


def test_lazy_rt() -> None:
run_tree = RunTree(name="foo")
assert isinstance(run_tree.client, Client)


@pytest.mark.parametrize(
"inputs, expected",
[
Expand Down
41 changes: 41 additions & 0 deletions python/tests/unit_tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# mypy: disable-error-code="annotation-unchecked"
import copy
import dataclasses
import functools
import itertools
import threading
import unittest
Expand Down Expand Up @@ -357,3 +358,43 @@ def test_get_api_url() -> None:
ls_utils.get_env_var.cache_clear()
with pytest.raises(ls_utils.LangSmithUserError):
ls_utils.get_api_url(" ")


def test_get_func_name():
class Foo:
def __call__(self, foo: int):
return "bar"

assert ls_utils._get_function_name(Foo()) == "Foo"
assert ls_utils._get_function_name(functools.partial(Foo(), foo=3)) == "Foo"

class AFoo:
async def __call__(self, foo: int):
return "bar"

assert ls_utils._get_function_name(AFoo()) == "AFoo"
assert ls_utils._get_function_name(functools.partial(AFoo(), foo=3)) == "AFoo"

def foo(bar: int) -> None:
return bar

assert ls_utils._get_function_name(foo) == "foo"
assert ls_utils._get_function_name(functools.partial(foo, bar=3)) == "foo"

async def afoo(bar: int) -> None:
return bar

assert ls_utils._get_function_name(afoo) == "afoo"
assert ls_utils._get_function_name(functools.partial(afoo, bar=3)) == "afoo"

lambda_func = lambda x: x + 1 # noqa
assert ls_utils._get_function_name(lambda_func) == "<lambda>"

class BarClass:
pass

assert ls_utils._get_function_name(BarClass) == "BarClass"

assert ls_utils._get_function_name(print) == "print"

assert ls_utils._get_function_name("not_a_function") == "not_a_function"

0 comments on commit 5ed1a6f

Please sign in to comment.