Tony20100/langchain_full huggingface dataset:
return await run_in_executor(
                None,
                self._run,
                run_manager=run_manager.get_sync() if run_manager else None,
                *args,
                **kwargs,
            )
    # TODO: this is for backwards compatibility, remove in future
    def __init__(
        self, name: str, func: Optional[Callable], description: str, **kwargs: Any
    ) -> None:
        """Initialize tool."""
        super(Tool, self).__init__(  # type: ignore[call-arg]
            name=name, func=func, description=description, **kwargs
        )
[docs]    @classmethod
    def from_function(
        cls,
        func: Optional[Callable],
        name: str,  # We keep these required to support backwards compatibility
        description: str,
        return_direct: bool = False,
        args_schema: Optional[Type[BaseModel]] = None,
        coroutine: Optional[
            Callable[..., Awaitable[Any]]
        ] = None,  # This is last for compatibility, but should be after func
        **kwargs: Any,
    ) -> Tool:
        """Initialize tool from a function."""
        if func is None and coroutine is None:
            raise ValueError("Function and/or coroutine must be provided")
        return cls(
            name=name,
            func=func,
            coroutine=coroutine,
            description=description,
            return_direct=return_direct,
            args_schema=args_schema,
            **kwargs,
        )
[docs]class StructuredTool(BaseTool):
    """Tool that can operate on any number of inputs."""
    description: str = ""
    args_schema: Type[BaseModel] = Field(..., description="The tool schema.")
args_schema: Type[BaseModel] = Field(..., description="The tool schema.")
    """The input arguments' schema."""
    func: Optional[Callable[..., Any]]
    """The function to run when the tool is called."""
    coroutine: Optional[Callable[..., Awaitable[Any]]] = None
    """The asynchronous version of the function."""
    # --- Runnable ---
[docs]    async def ainvoke(
        self,
        input: Union[str, Dict],
        config: Optional[RunnableConfig] = None,
        **kwargs: Any,
    ) -> Any:
        if not self.coroutine:
            # If the tool does not implement async, fall back to default implementation
            return await run_in_executor(config, self.invoke, input, config, **kwargs)
        return await super().ainvoke(input, config, **kwargs)
    # --- Tool ---
    @property
    def args(self) -> dict:
        """The tool's input arguments."""
        return self.args_schema.schema()["properties"]
    def _run(
        self,
        *args: Any,
        run_manager: Optional[CallbackManagerForToolRun] = None,
        **kwargs: Any,
    ) -> Any:
        """Use the tool."""
        if self.func:
            new_argument_supported = signature(self.func).parameters.get("callbacks")
            return (
                self.func(
                    *args,
                    callbacks=run_manager.get_child() if run_manager else None,
                    **kwargs,
                )
                if new_argument_supported
                else self.func(*args, **kwargs)
            )
        raise NotImplementedError("Tool does not support sync")
    async def _arun(
        self,
        *args: Any,
async def _arun(
        self,
        *args: Any,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
        **kwargs: Any,
    ) -> str:
        """Use the tool asynchronously."""
        if self.coroutine:
            new_argument_supported = signature(self.coroutine).parameters.get(
                "callbacks"
            )
            return (
                await self.coroutine(
                    *args,
                    callbacks=run_manager.get_child() if run_manager else None,
                    **kwargs,
                )
                if new_argument_supported
                else await self.coroutine(*args, **kwargs)
            )
        return await run_in_executor(
            None,
            self._run,
            run_manager=run_manager.get_sync() if run_manager else None,
            *args,
            **kwargs,
        )
[docs]    @classmethod
    def from_function(
        cls,
        func: Optional[Callable] = None,
        coroutine: Optional[Callable[..., Awaitable[Any]]] = None,
        name: Optional[str] = None,
        description: Optional[str] = None,
        return_direct: bool = False,
        args_schema: Optional[Type[BaseModel]] = None,
        infer_schema: bool = True,
        **kwargs: Any,
    ) -> StructuredTool:
        """Create tool from a given function.
        A classmethod that helps to create a tool from a function.
        Args:
            func: The function from which to create a tool
            coroutine: The async function from which to create a tool
            name: The name of the tool. Defaults to the function name
            description: The description of the tool. Defaults to the function docstring
description: The description of the tool. Defaults to the function docstring
            return_direct: Whether to return the result directly or as a callback
            args_schema: The schema of the tool's input arguments
            infer_schema: Whether to infer the schema from the function's signature
            **kwargs: Additional arguments to pass to the tool
        Returns:
            The tool
        Examples:
            .. code-block:: python
                def add(a: int, b: int) -> int:
                    \"\"\"Add two numbers\"\"\"
                    return a + b
                tool = StructuredTool.from_function(add)
                tool.run(1, 2) # 3
        """
        if func is not None:
            source_function = func
        elif coroutine is not None:
            source_function = coroutine
        else:
            raise ValueError("Function and/or coroutine must be provided")
        name = name or source_function.__name__
        description_ = description or source_function.__doc__
        if description_ is None:
            raise ValueError(
                "Function must have a docstring if description not provided."
            )
        if description is None:
            # Only apply if using the function's docstring
            description_ = textwrap.dedent(description_).strip()
        # Description example:
        # search_api(query: str) - Searches the API for the query.
        description_ = f"{description_.strip()}"
        _args_schema = args_schema
        if _args_schema is None and infer_schema:
            # schema name is appended within function
            _args_schema = create_schema_from_function(name, source_function)
        return cls(
            name=name,
            func=func,
            coroutine=coroutine,
            args_schema=_args_schema,  # type: ignore[arg-type]
args_schema=_args_schema,  # type: ignore[arg-type]
            description=description_,
            return_direct=return_direct,
            **kwargs,
        )
[docs]def tool(
    *args: Union[str, Callable, Runnable],
    return_direct: bool = False,
    args_schema: Optional[Type[BaseModel]] = None,
    infer_schema: bool = True,
) -> Callable:
    """Make tools out of functions, can be used with or without arguments.
    Args:
        *args: The arguments to the tool.
        return_direct: Whether to return directly from the tool rather
            than continuing the agent loop.
        args_schema: optional argument schema for user to specify
        infer_schema: Whether to infer the schema of the arguments from
            the function's signature. This also makes the resultant tool
            accept a dictionary input to its `run()` function.
    Requires:
        - Function must be of type (str) -> str
        - Function must have a docstring
    Examples:
        .. code-block:: python
            @tool
            def search_api(query: str) -> str:
                # Searches the API for the query.
                return
            @tool("search", return_direct=True)
            def search_api(query: str) -> str:
                # Searches the API for the query.
                return
    """
    def _make_with_name(tool_name: str) -> Callable:
        def _make_tool(dec_func: Union[Callable, Runnable]) -> BaseTool:
            if isinstance(dec_func, Runnable):
                runnable = dec_func
                if runnable.input_schema.schema().get("type") != "object":
                    raise ValueError("Runnable must have an object schema.")
                async def ainvoke_wrapper(
raise ValueError("Runnable must have an object schema.")
                async def ainvoke_wrapper(
                    callbacks: Optional[Callbacks] = None, **kwargs: Any
                ) -> Any:
                    return await runnable.ainvoke(kwargs, {"callbacks": callbacks})
                def invoke_wrapper(
                    callbacks: Optional[Callbacks] = None, **kwargs: Any
                ) -> Any:
                    return runnable.invoke(kwargs, {"callbacks": callbacks})
                coroutine = ainvoke_wrapper
                func = invoke_wrapper
                schema: Optional[Type[BaseModel]] = runnable.input_schema
                description = repr(runnable)
            elif inspect.iscoroutinefunction(dec_func):
                coroutine = dec_func
                func = None
                schema = args_schema
                description = None
            else:
                coroutine = None
                func = dec_func
                schema = args_schema
                description = None
            if infer_schema or args_schema is not None:
                return StructuredTool.from_function(
                    func,
                    coroutine,
                    name=tool_name,
                    description=description,
                    return_direct=return_direct,
                    args_schema=schema,
                    infer_schema=infer_schema,
                )
            # If someone doesn't want a schema applied, we must treat it as
            # a simple string->string function
            if func.__doc__ is None:
                raise ValueError(
                    "Function must have a docstring if "
                    "description not provided and infer_schema is False."
                )
            return Tool(
                name=tool_name,
                func=func,
                description=f"{tool_name} tool",
                return_direct=return_direct,
                coroutine=coroutine,
            )
        return _make_tool
coroutine=coroutine,
            )
        return _make_tool
    if len(args) == 2 and isinstance(args[0], str) and isinstance(args[1], Runnable):
        return _make_with_name(args[0])(args[1])
    elif len(args) == 1 and isinstance(args[0], str):
        # if the argument is a string, then we use the string as the tool name
        # Example usage: @tool("search", return_direct=True)
        return _make_with_name(args[0])
    elif len(args) == 1 and callable(args[0]):
        # if the argument is a function, then we use the function name as the tool name
        # Example usage: @tool
        return _make_with_name(args[0].__name__)(args[0])
    elif len(args) == 0:
        # if there are no arguments, then we use the function name as the tool name
        # Example usage: @tool(return_direct=True)
        def _partial(func: Callable[[str], str]) -> BaseTool:
            return _make_with_name(func.__name__)(func)
        return _partial
    else:
        raise ValueError("Too many arguments for tool decorator")
[docs]class RetrieverInput(BaseModel):
    """Input to the retriever."""
    query: str = Field(description="query to look up in retriever")
def _get_relevant_documents(
    query: str,
    retriever: BaseRetriever,
    document_prompt: BasePromptTemplate,
    document_separator: str,
    callbacks: Callbacks = None,
) -> str:
    docs = retriever.invoke(query, config={"callbacks": callbacks})
    return document_separator.join(
        format_document(doc, document_prompt) for doc in docs
return document_separator.join(
        format_document(doc, document_prompt) for doc in docs
    )
async def _aget_relevant_documents(
    query: str,
    retriever: BaseRetriever,
    document_prompt: BasePromptTemplate,
    document_separator: str,
    callbacks: Callbacks = None,
) -> str:
    docs = await retriever.ainvoke(query, config={"callbacks": callbacks})
    return document_separator.join(
        [await aformat_document(doc, document_prompt) for doc in docs]
    )
[docs]def create_retriever_tool(
    retriever: BaseRetriever,
    name: str,
    description: str,
    *,
    document_prompt: Optional[BasePromptTemplate] = None,
    document_separator: str = "\n\n",
) -> Tool:
    """Create a tool to do retrieval of documents.
    Args:
        retriever: The retriever to use for the retrieval
        name: The name for the tool. This will be passed to the language model,
            so should be unique and somewhat descriptive.
        description: The description for the tool. This will be passed to the language
            model, so should be descriptive.
    Returns:
        Tool class to pass to an agent
    """
    document_prompt = document_prompt or PromptTemplate.from_template("{page_content}")
    func = partial(
        _get_relevant_documents,
        retriever=retriever,
        document_prompt=document_prompt,
        document_separator=document_separator,
    )
    afunc = partial(
        _aget_relevant_documents,
        retriever=retriever,
        document_prompt=document_prompt,
        document_separator=document_separator,
    )
    return Tool(
        name=name,
        description=description,
)
    return Tool(
        name=name,
        description=description,
        func=func,
        coroutine=afunc,
        args_schema=RetrieverInput,
    )
ToolsRenderer = Callable[[List[BaseTool]], str]
[docs]def render_text_description(tools: List[BaseTool]) -> str:
    """Render the tool name and description in plain text.
    Output will be in the format of:
    .. code-block:: markdown
        search: This tool is used for search
        calculator: This tool is used for math
    """
    descriptions = []
    for tool in tools:
        if hasattr(tool, "func") and tool.func:
            sig = signature(tool.func)
            description = f"{tool.name}{sig} - {tool.description}"
        else:
            description = f"{tool.name} - {tool.description}"
        descriptions.append(description)
    return "\n".join(descriptions)
[docs]def render_text_description_and_args(tools: List[BaseTool]) -> str:
    """Render the tool name, description, and args in plain text.
    Output will be in the format of:
    .. code-block:: markdown
        search: This tool is used for search, args: {"query": {"type": "string"}}
        calculator: This tool is used for math, \
args: {"expression": {"type": "string"}}
    """
    tool_strings = []
    for tool in tools:
        args_schema = str(tool.args)
        if hasattr(tool, "func") and tool.func:
            sig = signature(tool.func)
            description = f"{tool.name}{sig} - {tool.description}"
        else:
            description = f"{tool.name} - {tool.description}"
else:
            description = f"{tool.name} - {tool.description}"
        tool_strings.append(f"{description}, args: {args_schema}")
    return "\n".join(tool_strings)
[docs]class BaseToolkit(BaseModel, ABC):
    """Base Toolkit representing a collection of related tools."""
[docs]    @abstractmethod
    def get_tools(self) -> List[BaseTool]:
        """Get the tools in the toolkit."""
Source code for langchain_core.globals
# flake8: noqa
"""Global values and configuration that apply to all of LangChain."""
import warnings
from typing import TYPE_CHECKING, Optional
if TYPE_CHECKING:
    from langchain_core.caches import BaseCache
# DO NOT USE THESE VALUES DIRECTLY!
# Use them only via `get_<X>()` and `set_<X>()` below,
# or else your code may behave unexpectedly with other uses of these global settings:
# https://github.com/langchain-ai/langchain/pull/11311#issuecomment-1743780004
_verbose: bool = False
_debug: bool = False
_llm_cache: Optional["BaseCache"] = None
[docs]def set_verbose(value: bool) -> None:
    """Set a new value for the `verbose` global setting."""
    try:
        import langchain  # type: ignore[import]
        # We're about to run some deprecated code, don't report warnings from it.
        # The user called the correct (non-deprecated) code path and shouldn't get warnings.
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore",
                message=(
                    "Importing verbose from langchain root module is no longer supported"
                ),
            )
            # N.B.: This is a workaround for an unfortunate quirk of Python's
            #       module-level `__getattr__()` implementation:
            # https://github.com/langchain-ai/langchain/pull/11311#issuecomment-1743780004
            #
            # Remove it once `langchain.verbose` is no longer supported, and once all users
            # have migrated to using `set_verbose()` here.
            langchain.verbose = value
    except ImportError:
        pass
    global _verbose
langchain.verbose = value
    except ImportError:
        pass
    global _verbose
    _verbose = value
[docs]def get_verbose() -> bool:
    """Get the value of the `verbose` global setting."""
    try:
        import langchain  # type: ignore[import]
        # We're about to run some deprecated code, don't report warnings from it.
        # The user called the correct (non-deprecated) code path and shouldn't get warnings.
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore",
                message=(
                    ".*Importing verbose from langchain root module is no longer supported"
                ),
            )
            # N.B.: This is a workaround for an unfortunate quirk of Python's
            #       module-level `__getattr__()` implementation:
            # https://github.com/langchain-ai/langchain/pull/11311#issuecomment-1743780004
            #
            # Remove it once `langchain.verbose` is no longer supported, and once all users
            # have migrated to using `set_verbose()` here.
            #
            # In the meantime, the `verbose` setting is considered True if either the old
            # or the new value are True. This accommodates users who haven't migrated
            # to using `set_verbose()` yet. Those users are getting deprecation warnings
            # directing them to use `set_verbose()` when they import `langhchain.verbose`.
            old_verbose = langchain.verbose
    except ImportError:
        old_verbose = False
    global _verbose
    return _verbose or old_verbose
[docs]def set_debug(value: bool) -> None:
    """Set a new value for the `debug` global setting."""
    try:
"""Set a new value for the `debug` global setting."""
    try:
        import langchain  # type: ignore[import]
        # We're about to run some deprecated code, don't report warnings from it.
        # The user called the correct (non-deprecated) code path and shouldn't get warnings.
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore",
                message="Importing debug from langchain root module is no longer supported",
            )
            # N.B.: This is a workaround for an unfortunate quirk of Python's
            #       module-level `__getattr__()` implementation:
            # https://github.com/langchain-ai/langchain/pull/11311#issuecomment-1743780004
            #
            # Remove it once `langchain.debug` is no longer supported, and once all users
            # have migrated to using `set_debug()` here.
            langchain.debug = value
    except ImportError:
        pass
    global _debug
    _debug = value
[docs]def get_debug() -> bool:
    """Get the value of the `debug` global setting."""
    try:
        import langchain  # type: ignore[import]
        # We're about to run some deprecated code, don't report warnings from it.
        # The user called the correct (non-deprecated) code path and shouldn't get warnings.
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore",
                message="Importing debug from langchain root module is no longer supported",
            )
            # N.B.: This is a workaround for an unfortunate quirk of Python's
            #       module-level `__getattr__()` implementation:
#       module-level `__getattr__()` implementation:
            # https://github.com/langchain-ai/langchain/pull/11311#issuecomment-1743780004
            #
            # Remove it once `langchain.debug` is no longer supported, and once all users
            # have migrated to using `set_debug()` here.
            #
            # In the meantime, the `debug` setting is considered True if either the old
            # or the new value are True. This accommodates users who haven't migrated
            # to using `set_debug()` yet. Those users are getting deprecation warnings
            # directing them to use `set_debug()` when they import `langhchain.debug`.
            old_debug = langchain.debug
    except ImportError:
        old_debug = False
    global _debug
    return _debug or old_debug
[docs]def set_llm_cache(value: Optional["BaseCache"]) -> None:
    """Set a new LLM cache, overwriting the previous value, if any."""
    try:
        import langchain  # type: ignore[import]
        # We're about to run some deprecated code, don't report warnings from it.
        # The user called the correct (non-deprecated) code path and shouldn't get warnings.
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore",
                message=(
                    "Importing llm_cache from langchain root module is no longer supported"
                ),
            )
            # N.B.: This is a workaround for an unfortunate quirk of Python's
            #       module-level `__getattr__()` implementation:
            # https://github.com/langchain-ai/langchain/pull/11311#issuecomment-1743780004
            #
#
            # Remove it once `langchain.llm_cache` is no longer supported, and
            # once all users have migrated to using `set_llm_cache()` here.
            langchain.llm_cache = value
    except ImportError:
        pass
    global _llm_cache
    _llm_cache = value
[docs]def get_llm_cache() -> "BaseCache":
    """Get the value of the `llm_cache` global setting."""
    try:
        import langchain  # type: ignore[import]
        # We're about to run some deprecated code, don't report warnings from it.
        # The user called the correct (non-deprecated) code path and shouldn't get warnings.
        with warnings.catch_warnings():
            warnings.filterwarnings(
                "ignore",
                message=(
                    "Importing llm_cache from langchain root module is no longer supported"
                ),
            )
            # N.B.: This is a workaround for an unfortunate quirk of Python's
            #       module-level `__getattr__()` implementation:
            # https://github.com/langchain-ai/langchain/pull/11311#issuecomment-1743780004
            #
            # Remove it once `langchain.llm_cache` is no longer supported, and
            # once all users have migrated to using `set_llm_cache()` here.
            #
            # In the meantime, the `llm_cache` setting returns whichever of
            # its two backing sources is truthy (not `None` and non-empty),
            # or the old value if both are falsy. This accommodates users
            # who haven't migrated to using `set_llm_cache()` yet.
            # Those users are getting deprecation warnings directing them