-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
400 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
"""This module provides convenient tracing wrappers for popular libraries.""" | ||
|
||
from langsmith.wrappers._generic import wrap_sdk | ||
from langsmith.wrappers._openai import wrap_openai | ||
|
||
__all__ = ["wrap_openai"] | ||
__all__ = ["wrap_openai", "wrap_sdk"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import inspect | ||
import logging | ||
from typing import Any, Generic, TypeVar, cast | ||
|
||
from langsmith.run_helpers import traceable | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def _get_module_path(module_class: type) -> str: | ||
"""Get the full module path of a given class. | ||
:param module_class: The class to get the module path for. | ||
:type module_class: type | ||
:return: The module path | ||
:rtype: str | ||
""" | ||
return ( | ||
getattr(module_class, "__module__", "") | ||
or "" + "." + getattr(module_class, "__name__", "") | ||
or "" | ||
).strip(".") | ||
|
||
|
||
T = TypeVar("T") | ||
|
||
|
||
class Proxy(Generic[T]): | ||
__slots__ = ["_ls_obj", "__weakref__"] | ||
|
||
def __init__(self, obj: T): | ||
object.__setattr__(self, "_ls_obj", obj) | ||
|
||
def __getattr__(self, name: str) -> Any: | ||
attr = getattr(object.__getattribute__(self, "_ls_obj"), name) | ||
return self.__class__(attr) | ||
|
||
def __setattr__(self, name, value): | ||
setattr(self._ls_obj, name, value) | ||
|
||
def __delattr__(self, name): | ||
delattr(self._ls_obj, name) | ||
|
||
def __call__(self, *args, **kwargs): | ||
function_object = object.__getattribute__(self, "_ls_obj") | ||
if inspect.isclass(function_object): | ||
# Call to a constructor. Just reflect | ||
return self.__class__( | ||
function_object(*args, **kwargs), | ||
) | ||
run_name = _get_module_path(function_object) | ||
return traceable(name=run_name, run_type="llm")(function_object)( | ||
*args, **kwargs | ||
) | ||
|
||
def __repr__(self) -> str: | ||
return repr(object.__getattribute__(self, "_ls_obj")) | ||
|
||
def __getattribute__(self, __name: str) -> Any: | ||
if __name.startswith("__") and __name.endswith("__"): | ||
return object.__getattribute__(self, __name) | ||
return super().__getattribute__(__name) | ||
|
||
|
||
def wrap_sdk(client: T) -> T: | ||
"""Wrap a client to make it traceable. | ||
:param client: The client to wrap. | ||
:type client: T | ||
:return: The wrapped client. | ||
:rtype: T | ||
""" | ||
return cast(T, Proxy(client)) |
Oops, something went wrong.