Source code for langchain_community.tools.memorize.tool
from abc import abstractmethod
from typing import Any, Optional, Protocol, Sequence, runtime_checkable
from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.pydantic_v1 import Field
from langchain_core.tools import BaseTool
from langchain_community.llms.gradient_ai import TrainResult
[docs]@runtime_checkable
class TrainableLLM(Protocol):
[docs]    @abstractmethod
    def train_unsupervised(
        self,
        inputs: Sequence[str],
        **kwargs: Any,
    ) -> TrainResult:
        ...
[docs]    @abstractmethod
    async def atrain_unsupervised(
        self,
        inputs: Sequence[str],
        **kwargs: Any,
    ) -> TrainResult:
        ...
[docs]class Memorize(BaseTool):
    name: str = "Memorize"
    description: str = (
        "Useful whenever you observed novel information "
        "from previous conversation history, "
        "i.e., another tool's action outputs or human comments. "
        "The action input should include observed information in detail, "
        "then the tool will fine-tune yourself to remember it."
    )
    llm: TrainableLLM = Field()
    def _run(
        self,
        information_to_learn: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        train_result = self.llm.train_unsupervised((information_to_learn,))
        return f"Train complete. Loss: {train_result['loss']}"
    async def _arun(
        self,
        information_to_learn: str,


async def _arun(
        self,
        information_to_learn: str,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        train_result = await self.llm.atrain_unsupervised((information_to_learn,))
        return f"Train complete. Loss: {train_result['loss']}"


Source code for langchain_community.tools.clickup.tool
"""
This tool allows agents to interact with the clickup library
and operate on a Clickup instance.
To use this tool, you must first set as environment variables:
    client_secret
    client_id
    code
Below is a sample script that uses the Clickup tool:
```python
from langchain_community.agent_toolkits.clickup.toolkit import ClickupToolkit
from langchain_community.utilities.clickup import ClickupAPIWrapper
clickup = ClickupAPIWrapper()
toolkit = ClickupToolkit.from_clickup_api_wrapper(clickup)
```
"""
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.pydantic_v1 import Field
from langchain_core.tools import BaseTool
from langchain_community.utilities.clickup import ClickupAPIWrapper
[docs]class ClickupAction(BaseTool):
    """Tool that queries the  Clickup API."""
    api_wrapper: ClickupAPIWrapper = Field(default_factory=ClickupAPIWrapper)
    mode: str
    name: str = ""
    description: str = ""
    def _run(
        self,
        instructions: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the  Clickup API to run an operation."""
        return self.api_wrapper.run(self.mode, instructions)


Source code for langchain_community.tools.human.tool
"""Tool for asking human input."""
from typing import Callable, Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.pydantic_v1 import Field
from langchain_core.tools import BaseTool
def _print_func(text: str) -> None:
    print("\n")
    print(text)
[docs]class HumanInputRun(BaseTool):
    """Tool that asks user for input."""
    name: str = "human"
    description: str = (
        "You can ask a human for guidance when you think you "
        "got stuck or you are not sure what to do next. "
        "The input should be a question for the human."
    )
    prompt_func: Callable[[str], None] = Field(default_factory=lambda: _print_func)
    input_func: Callable = Field(default_factory=lambda: input)
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the Human input tool."""
        self.prompt_func(query)
        return self.input_func()


Source code for langchain_community.tools.ddg_search.tool
"""Tool for the DuckDuckGo search API."""
import warnings
from typing import Any, Optional, Type
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.tools import BaseTool
from langchain_community.utilities.duckduckgo_search import DuckDuckGoSearchAPIWrapper
[docs]class DDGInput(BaseModel):
    query: str = Field(description="search query to look up")
[docs]class DuckDuckGoSearchRun(BaseTool):
    """Tool that queries the DuckDuckGo search API."""
    name: str = "duckduckgo_search"
    description: str = (
        "A wrapper around DuckDuckGo Search. "
        "Useful for when you need to answer questions about current events. "
        "Input should be a search query."
    )
    api_wrapper: DuckDuckGoSearchAPIWrapper = Field(
        default_factory=DuckDuckGoSearchAPIWrapper
    )
    args_schema: Type[BaseModel] = DDGInput
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.api_wrapper.run(query)
[docs]class DuckDuckGoSearchResults(BaseTool):
    """Tool that queries the DuckDuckGo search API and gets back json."""
    name: str = "DuckDuckGo Results JSON"
    description: str = (
        "A wrapper around Duck Duck Go Search. "
        "Useful for when you need to answer questions about current events. "


"Useful for when you need to answer questions about current events. "
        "Input should be a search query. Output is a JSON array of the query results"
    )
    max_results: int = Field(alias="num_results", default=4)
    api_wrapper: DuckDuckGoSearchAPIWrapper = Field(
        default_factory=DuckDuckGoSearchAPIWrapper
    )
    backend: str = "text"
    args_schema: Type[BaseModel] = DDGInput
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        res = self.api_wrapper.results(query, self.max_results, source=self.backend)
        res_strs = [", ".join([f"{k}: {v}" for k, v in d.items()]) for d in res]
        return ", ".join([f"[{rs}]" for rs in res_strs])
[docs]def DuckDuckGoSearchTool(*args: Any, **kwargs: Any) -> DuckDuckGoSearchRun:
    """
    Deprecated. Use DuckDuckGoSearchRun instead.
    Args:
        *args:
        **kwargs:
    Returns:
        DuckDuckGoSearchRun
    """
    warnings.warn(
        "DuckDuckGoSearchTool will be deprecated in the future. "
        "Please use DuckDuckGoSearchRun instead.",
        DeprecationWarning,
    )
    return DuckDuckGoSearchRun(*args, **kwargs)


Source code for langchain_community.tools.brave_search.tool
from __future__ import annotations
from typing import Any, Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.tools import BaseTool
from langchain_community.utilities.brave_search import BraveSearchWrapper
[docs]class BraveSearch(BaseTool):
    """Tool that queries the BraveSearch."""
    name: str = "brave_search"
    description: str = (
        "a search engine. "
        "useful for when you need to answer questions about current events."
        " input should be a search query."
    )
    search_wrapper: BraveSearchWrapper
[docs]    @classmethod
    def from_api_key(
        cls, api_key: str, search_kwargs: Optional[dict] = None, **kwargs: Any
    ) -> BraveSearch:
        """Create a tool from an api key.
        Args:
            api_key: The api key to use.
            search_kwargs: Any additional kwargs to pass to the search wrapper.
            **kwargs: Any additional kwargs to pass to the tool.
        Returns:
            A tool.
        """
        wrapper = BraveSearchWrapper(api_key=api_key, search_kwargs=search_kwargs or {})
        return cls(search_wrapper=wrapper, **kwargs)
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.search_wrapper.run(query)


Source code for langchain_community.tools.wikipedia.tool
"""Tool for the Wikipedia API."""
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.tools import BaseTool
from langchain_community.utilities.wikipedia import WikipediaAPIWrapper
[docs]class WikipediaQueryRun(BaseTool):
    """Tool that searches the Wikipedia API."""
    name: str = "Wikipedia"
    description: str = (
        "A wrapper around Wikipedia. "
        "Useful for when you need to answer general questions about "
        "people, places, companies, facts, historical events, or other subjects. "
        "Input should be a search query."
    )
    api_wrapper: WikipediaAPIWrapper
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the Wikipedia tool."""
        return self.api_wrapper.run(query)


Source code for langchain_community.tools.multion.close_session
import asyncio
from typing import TYPE_CHECKING, Optional, Type
from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.tools import BaseTool
if TYPE_CHECKING:
    # This is for linting and IDE typehints
    import multion
else:
    try:
        # We do this so pydantic can resolve the types when instantiating
        import multion
    except ImportError:
        pass
[docs]class CloseSessionSchema(BaseModel):
    """Input for UpdateSessionTool."""
    sessionId: str = Field(
        ...,
        description="""The sessionId, received from one of the createSessions
        or updateSessions run before""",
    )
[docs]class MultionCloseSession(BaseTool):
    """Tool that closes an existing Multion Browser Window with provided fields.
    Attributes:
        name: The name of the tool. Default: "close_multion_session"
        description: The description of the tool.
        args_schema: The schema for the tool's arguments. Default: UpdateSessionSchema
    """
    name: str = "close_multion_session"
    description: str = """Use this tool to close \
an existing corresponding Multion Browser Window with provided fields. \
Note: SessionId must be received from previous Browser window creation."""
    args_schema: Type[CloseSessionSchema] = CloseSessionSchema
    sessionId: str = ""
    def _run(
        self,
        sessionId: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> None:
        try:
            try:


) -> None:
        try:
            try:
                multion.close_session(sessionId)
            except Exception as e:
                print(f"{e}, retrying...")
        except Exception as e:
            raise Exception(f"An error occurred: {e}")
    async def _arun(
        self,
        sessionId: str,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> None:
        loop = asyncio.get_running_loop()
        await loop.run_in_executor(None, self._run, sessionId)


Source code for langchain_community.tools.multion.create_session
import asyncio
from typing import TYPE_CHECKING, Optional, Type
from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.tools import BaseTool
if TYPE_CHECKING:
    # This is for linting and IDE typehints
    import multion
else:
    try:
        # We do this so pydantic can resolve the types when instantiating
        import multion
    except ImportError:
        pass
[docs]class CreateSessionSchema(BaseModel):
    """Input for CreateSessionTool."""
    query: str = Field(
        ...,
        description="The query to run in multion agent.",
    )
    url: str = Field(
        "https://www.google.com/",
        description="""The Url to run the agent at. Note: accepts only secure \
            links having https://""",
    )
[docs]class MultionCreateSession(BaseTool):
    """Tool that creates a new Multion Browser Window with provided fields.
    Attributes:
        name: The name of the tool. Default: "create_multion_session"
        description: The description of the tool.
        args_schema: The schema for the tool's arguments.
    """
    name: str = "create_multion_session"
    description: str = """
        Create a new web browsing session based on a user's command or request. \
        The command should include the full info required for the session. \
        Also include an url (defaults to google.com if no better option) \
        to start the session. \
        Use this tool to create a new Browser Window with provided fields. \


Use this tool to create a new Browser Window with provided fields. \
        Always the first step to run any activities that can be done using browser.
        """
    args_schema: Type[CreateSessionSchema] = CreateSessionSchema
    def _run(
        self,
        query: str,
        url: Optional[str] = "https://www.google.com/",
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> dict:
        try:
            response = multion.new_session({"input": query, "url": url})
            return {
                "sessionId": response["session_id"],
                "Response": response["message"],
            }
        except Exception as e:
            raise Exception(f"An error occurred: {e}")
    async def _arun(
        self,
        query: str,
        url: Optional[str] = "https://www.google.com/",
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> dict:
        loop = asyncio.get_running_loop()
        result = await loop.run_in_executor(None, self._run, query, url)
        return result


Source code for langchain_community.tools.multion.update_session
import asyncio
from typing import TYPE_CHECKING, Optional, Type
from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.tools import BaseTool
if TYPE_CHECKING:
    # This is for linting and IDE typehints
    import multion
else:
    try:
        # We do this so pydantic can resolve the types when instantiating
        import multion
    except ImportError:
        pass
[docs]class UpdateSessionSchema(BaseModel):
    """Input for UpdateSessionTool."""
    sessionId: str = Field(
        ...,
        description="""The sessionID,
        received from one of the createSessions run before""",
    )
    query: str = Field(
        ...,
        description="The query to run in multion agent.",
    )
    url: str = Field(
        "https://www.google.com/",
        description="""The Url to run the agent at. \
        Note: accepts only secure links having https://""",
    )
[docs]class MultionUpdateSession(BaseTool):
    """Tool that updates an existing Multion Browser Window with provided fields.
    Attributes:
        name: The name of the tool. Default: "update_multion_session"
        description: The description of the tool.
        args_schema: The schema for the tool's arguments. Default: UpdateSessionSchema
    """
    name: str = "update_multion_session"
    description: str = """Use this tool to update \
an existing corresponding Multion Browser Window with provided fields. \
Note: sessionId must be received from previous Browser window creation."""


Note: sessionId must be received from previous Browser window creation."""
    args_schema: Type[UpdateSessionSchema] = UpdateSessionSchema
    sessionId: str = ""
    def _run(
        self,
        sessionId: str,
        query: str,
        url: Optional[str] = "https://www.google.com/",
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> dict:
        try:
            try:
                response = multion.update_session(
                    sessionId, {"input": query, "url": url}
                )
                content = {"sessionId": sessionId, "Response": response["message"]}
                self.sessionId = sessionId
                return content
            except Exception as e:
                print(f"{e}, retrying...")
                return {"error": f"{e}", "Response": "retrying..."}
        except Exception as e:
            raise Exception(f"An error occurred: {e}")
    async def _arun(
        self,
        sessionId: str,
        query: str,
        url: Optional[str] = "https://www.google.com/",
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> dict:
        loop = asyncio.get_running_loop()
        result = await loop.run_in_executor(None, self._run, sessionId, query, url)
        return result


Source code for langchain_community.tools.ainetwork.base
from __future__ import annotations
import asyncio
import threading
from enum import Enum
from typing import TYPE_CHECKING, Any, Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.pydantic_v1 import Field
from langchain_core.tools import BaseTool
from langchain_community.tools.ainetwork.utils import authenticate
if TYPE_CHECKING:
    from ain.ain import Ain
[docs]class OperationType(str, Enum):
    """Type of operation as enumerator."""
    SET = "SET"
    GET = "GET"
[docs]class AINBaseTool(BaseTool):
    """Base class for the AINetwork tools."""
    interface: Ain = Field(default_factory=authenticate)
    """The interface object for the AINetwork Blockchain."""
    def _run(
        self,
        *args: Any,
        run_manager: Optional[CallbackManagerForToolRun] = None,
        **kwargs: Any,
    ) -> str:
        try:
            loop = asyncio.get_event_loop()
        except RuntimeError:
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
        if loop.is_closed():
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
        if loop.is_running():
            result_container = []
            def thread_target() -> None:
                nonlocal result_container
                new_loop = asyncio.new_event_loop()
                asyncio.set_event_loop(new_loop)
                try:
                    result_container.append(
                        new_loop.run_until_complete(self._arun(*args, **kwargs))
                    )
                except Exception as e:
                    result_container.append(e)
                finally:
                    new_loop.close()
            thread = threading.Thread(target=thread_target)


new_loop.close()
            thread = threading.Thread(target=thread_target)
            thread.start()
            thread.join()
            result = result_container[0]
            if isinstance(result, Exception):
                raise result
            return result
        else:
            result = loop.run_until_complete(self._arun(*args, **kwargs))
            loop.close()
            return result


Source code for langchain_community.tools.ainetwork.rule
import builtins
import json
from typing import Optional, Type
from langchain_core.callbacks import AsyncCallbackManagerForToolRun
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_community.tools.ainetwork.base import AINBaseTool, OperationType
[docs]class RuleSchema(BaseModel):
    """Schema for owner operations."""
    type: OperationType = Field(...)
    path: str = Field(..., description="Path on the blockchain where the rule applies")
    eval: Optional[str] = Field(None, description="eval string to determine permission")
[docs]class AINRuleOps(AINBaseTool):
    """Tool for owner operations."""
    name: str = "AINruleOps"
    description: str = """
Covers the write `rule` for the AINetwork Blockchain database. The SET type specifies write permissions using the `eval` variable as a JavaScript eval string.
In order to AINvalueOps with SET at the path, the execution result of the `eval` string must be true.
## Path Rules
1. Allowed characters for directory: `[a-zA-Z_0-9]`
2. Use `$<key>` for template variables as directory.
## Eval String Special Variables
- auth.addr: Address of the writer for the path
- newData: New data for the path
- data: Current data for the path
- currentTime: Time in seconds
- lastBlockNumber: Latest processed block number
## Eval String Functions
- getValue(<path>)
- getRule(<path>)
- getOwner(<path>)
- getFunction(<path>)
- evalRule(<path>, <value to set>, auth, currentTime)
- evalOwner(<path>, 'write_owner', auth)
## SET Example
- type: SET


## SET Example
- type: SET
- path: /apps/langchain_project_1/$from/$to/$img
- eval: auth.addr===$from&&!getValue('/apps/image_db/'+$img)
## GET Example
- type: GET
- path: /apps/langchain_project_1
"""  # noqa: E501
    args_schema: Type[BaseModel] = RuleSchema
    async def _arun(
        self,
        type: OperationType,
        path: str,
        eval: Optional[str] = None,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        from ain.types import ValueOnlyTransactionInput
        try:
            if type is OperationType.SET:
                if eval is None:
                    raise ValueError("'eval' is required for SET operation.")
                res = await self.interface.db.ref(path).setRule(
                    transactionInput=ValueOnlyTransactionInput(
                        value={".rule": {"write": eval}}
                    )
                )
            elif type is OperationType.GET:
                res = await self.interface.db.ref(path).getRule()
            else:
                raise ValueError(f"Unsupported 'type': {type}.")
            return json.dumps(res, ensure_ascii=False)
        except Exception as e:
            return f"{builtins.type(e).__name__}: {str(e)}"


Source code for langchain_community.tools.ainetwork.utils
"""AINetwork Blockchain tool utils."""
from __future__ import annotations
import os
from typing import TYPE_CHECKING, Literal, Optional
if TYPE_CHECKING:
    from ain.ain import Ain
[docs]def authenticate(network: Optional[Literal["mainnet", "testnet"]] = "testnet") -> Ain:
    """Authenticate using the AIN Blockchain"""
    try:
        from ain.ain import Ain
    except ImportError as e:
        raise ImportError(
            "Cannot import ain-py related modules. Please install the package with "
            "`pip install ain-py`."
        ) from e
    if network == "mainnet":
        provider_url = "https://mainnet-api.ainetwork.ai/"
        chain_id = 1
        if "AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY" in os.environ:
            private_key = os.environ["AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY"]
        else:
            raise EnvironmentError(
                "Error: The AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY environmental variable "
                "has not been set."
            )
    elif network == "testnet":
        provider_url = "https://testnet-api.ainetwork.ai/"
        chain_id = 0
        if "AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY" in os.environ:
            private_key = os.environ["AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY"]
        else:
            raise EnvironmentError(
                "Error: The AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY environmental variable "
                "has not been set."
            )
    elif network is None:
        if (
            "AIN_BLOCKCHAIN_PROVIDER_URL" in os.environ
            and "AIN_BLOCKCHAIN_CHAIN_ID" in os.environ
            and "AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY" in os.environ
        ):


and "AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY" in os.environ
        ):
            provider_url = os.environ["AIN_BLOCKCHAIN_PROVIDER_URL"]
            chain_id = int(os.environ["AIN_BLOCKCHAIN_CHAIN_ID"])
            private_key = os.environ["AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY"]
        else:
            raise EnvironmentError(
                "Error: The AIN_BLOCKCHAIN_PROVIDER_URL and "
                "AIN_BLOCKCHAIN_ACCOUNT_PRIVATE_KEY and AIN_BLOCKCHAIN_CHAIN_ID "
                "environmental variable has not been set."
            )
    else:
        raise ValueError(f"Unsupported 'network': {network}")
    ain = Ain(provider_url, chain_id)
    ain.wallet.addAndSetDefaultAccount(private_key)
    return ain


Source code for langchain_community.tools.ainetwork.owner
import builtins
import json
from typing import List, Optional, Type, Union
from langchain_core.callbacks import AsyncCallbackManagerForToolRun
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_community.tools.ainetwork.base import AINBaseTool, OperationType
[docs]class RuleSchema(BaseModel):
    """Schema for owner operations."""
    type: OperationType = Field(...)
    path: str = Field(..., description="Blockchain reference path")
    address: Optional[Union[str, List[str]]] = Field(
        None, description="A single address or a list of addresses"
    )
    write_owner: Optional[bool] = Field(
        False, description="Authority to edit the `owner` property of the path"
    )
    write_rule: Optional[bool] = Field(
        False, description="Authority to edit `write rule` for the path"
    )
    write_function: Optional[bool] = Field(
        False, description="Authority to `set function` for the path"
    )
    branch_owner: Optional[bool] = Field(
        False, description="Authority to initialize `owner` of sub-paths"
    )
[docs]class AINOwnerOps(AINBaseTool):
    """Tool for owner operations."""
    name: str = "AINownerOps"
    description: str = """
Rules for `owner` in AINetwork Blockchain database.
An address set as `owner` can modify permissions according to its granted authorities
## Path Rule
- (/[a-zA-Z_0-9]+)+
- Permission checks ascend from the most specific (child) path to broader (parent) paths until an `owner` is located.
## Address Rules


## Address Rules
- 0x[0-9a-fA-F]{40}: 40-digit hexadecimal address
- *: All addresses permitted
- Defaults to the current session's address
## SET
- `SET` alters permissions for specific addresses, while other addresses remain unaffected.
- When removing an address of `owner`, set all authorities for that address to false.
- message `write_owner permission evaluated false` if fail
### Example
- type: SET
- path: /apps/langchain
- address: [<address 1>, <address 2>]
- write_owner: True
- write_rule: True
- write_function: True
- branch_owner: True
## GET
- Provides all addresses with `owner` permissions and their authorities in the path.
### Example
- type: GET
- path: /apps/langchain
"""  # noqa: E501
    args_schema: Type[BaseModel] = RuleSchema
    async def _arun(
        self,
        type: OperationType,
        path: str,
        address: Optional[Union[str, List[str]]] = None,
        write_owner: Optional[bool] = None,
        write_rule: Optional[bool] = None,
        write_function: Optional[bool] = None,
        branch_owner: Optional[bool] = None,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        from ain.types import ValueOnlyTransactionInput
        try:
            if type is OperationType.SET:
                if address is None:
                    address = self.interface.wallet.defaultAccount.address
                if isinstance(address, str):
                    address = [address]
                res = await self.interface.db.ref(path).setOwner(
                    transactionInput=ValueOnlyTransactionInput(
                        value={


transactionInput=ValueOnlyTransactionInput(
                        value={
                            ".owner": {
                                "owners": {
                                    address: {
                                        "write_owner": write_owner or False,
                                        "write_rule": write_rule or False,
                                        "write_function": write_function or False,
                                        "branch_owner": branch_owner or False,
                                    }
                                    for address in address
                                }
                            }
                        }
                    )
                )
            elif type is OperationType.GET:
                res = await self.interface.db.ref(path).getOwner()
            else:
                raise ValueError(f"Unsupported 'type': {type}.")
            return json.dumps(res, ensure_ascii=False)
        except Exception as e:
            return f"{builtins.type(e).__name__}: {str(e)}"


Source code for langchain_community.tools.ainetwork.value
import builtins
import json
from typing import Optional, Type, Union
from langchain_core.callbacks import AsyncCallbackManagerForToolRun
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_community.tools.ainetwork.base import AINBaseTool, OperationType
[docs]class ValueSchema(BaseModel):
    """Schema for value operations."""
    type: OperationType = Field(...)
    path: str = Field(..., description="Blockchain reference path")
    value: Optional[Union[int, str, float, dict]] = Field(
        None, description="Value to be set at the path"
    )
[docs]class AINValueOps(AINBaseTool):
    """Tool for value operations."""
    name: str = "AINvalueOps"
    description: str = """
Covers the read and write value for the AINetwork Blockchain database.
## SET
- Set a value at a given path
### Example
- type: SET
- path: /apps/langchain_test_1/object
- value: {1: 2, "34": 56}
## GET
- Retrieve a value at a given path
### Example
- type: GET
- path: /apps/langchain_test_1/DB
## Special paths
- `/accounts/<address>/balance`: Account balance
- `/accounts/<address>/nonce`: Account nonce
- `/apps`: Applications
- `/consensus`: Consensus
- `/checkin`: Check-in
- `/deposit/<service id>/<address>/<deposit id>`: Deposit
- `/deposit_accounts/<service id>/<address>/<account id>`: Deposit accounts
- `/escrow`: Escrow
- `/payments`: Payment
- `/sharding`: Sharding
- `/token/name`: Token name


- `/sharding`: Sharding
- `/token/name`: Token name
- `/token/symbol`: Token symbol
- `/token/total_supply`: Token total supply
- `/transfer/<address from>/<address to>/<key>/value`: Transfer
- `/withdraw/<service id>/<address>/<withdraw id>`: Withdraw
"""
    args_schema: Type[BaseModel] = ValueSchema
    async def _arun(
        self,
        type: OperationType,
        path: str,
        value: Optional[Union[int, str, float, dict]] = None,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        from ain.types import ValueOnlyTransactionInput
        try:
            if type is OperationType.SET:
                if value is None:
                    raise ValueError("'value' is required for SET operation.")
                res = await self.interface.db.ref(path).setValue(
                    transactionInput=ValueOnlyTransactionInput(value=value)
                )
            elif type is OperationType.GET:
                res = await self.interface.db.ref(path).getValue()
            else:
                raise ValueError(f"Unsupported 'type': {type}.")
            return json.dumps(res, ensure_ascii=False)
        except Exception as e:
            return f"{builtins.type(e).__name__}: {str(e)}"


Source code for langchain_community.tools.ainetwork.transfer
import json
from typing import Optional, Type
from langchain_core.callbacks import AsyncCallbackManagerForToolRun
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_community.tools.ainetwork.base import AINBaseTool
[docs]class TransferSchema(BaseModel):
    """Schema for transfer operations."""
    address: str = Field(..., description="Address to transfer AIN to")
    amount: int = Field(..., description="Amount of AIN to transfer")
[docs]class AINTransfer(AINBaseTool):
    """Tool for transfer operations."""
    name: str = "AINtransfer"
    description: str = "Transfers AIN to a specified address"
    args_schema: Type[TransferSchema] = TransferSchema
    async def _arun(
        self,
        address: str,
        amount: int,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        try:
            res = await self.interface.wallet.transfer(address, amount, nonce=-1)
            return json.dumps(res, ensure_ascii=False)
        except Exception as e:
            return f"{type(e).__name__}: {str(e)}"


Source code for langchain_community.tools.ainetwork.app
import builtins
import json
from enum import Enum
from typing import List, Optional, Type, Union
from langchain_core.callbacks import AsyncCallbackManagerForToolRun
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_community.tools.ainetwork.base import AINBaseTool
[docs]class AppOperationType(str, Enum):
    """Type of app operation as enumerator."""
    SET_ADMIN = "SET_ADMIN"
    GET_CONFIG = "GET_CONFIG"
[docs]class AppSchema(BaseModel):
    """Schema for app operations."""
    type: AppOperationType = Field(...)
    appName: str = Field(..., description="Name of the application on the blockchain")
    address: Optional[Union[str, List[str]]] = Field(
        None,
        description=(
            "A single address or a list of addresses. Default: current session's "
            "address"
        ),
    )
[docs]class AINAppOps(AINBaseTool):
    """Tool for app operations."""
    name: str = "AINappOps"
    description: str = """
Create an app in the AINetwork Blockchain database by creating the /apps/<appName> path.
An address set as `admin` can grant `owner` rights to other addresses (refer to `AINownerOps` for more details).
Also, `admin` is initialized to have all `owner` permissions and `rule` allowed for that path.
## appName Rule
- [a-z_0-9]+
## address Rules
- 0x[0-9a-fA-F]{40}
- Defaults to the current session's address
- Multiple addresses can be specified if needed
## SET_ADMIN Example 1
- type: SET_ADMIN
- appName: ain_project


## SET_ADMIN Example 1
- type: SET_ADMIN
- appName: ain_project
### Result:
1. Path /apps/ain_project created.
2. Current session's address registered as admin.
## SET_ADMIN Example 2
- type: SET_ADMIN
- appName: test_project
- address: [<address1>, <address2>]
### Result:
1. Path /apps/test_project created.
2. <address1> and <address2> registered as admin.
"""  # noqa: E501
    args_schema: Type[BaseModel] = AppSchema
    async def _arun(
        self,
        type: AppOperationType,
        appName: str,
        address: Optional[Union[str, List[str]]] = None,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        from ain.types import ValueOnlyTransactionInput
        from ain.utils import getTimestamp
        try:
            if type is AppOperationType.SET_ADMIN:
                if address is None:
                    address = self.interface.wallet.defaultAccount.address
                if isinstance(address, str):
                    address = [address]
                res = await self.interface.db.ref(
                    f"/manage_app/{appName}/create/{getTimestamp()}"
                ).setValue(
                    transactionInput=ValueOnlyTransactionInput(
                        value={"admin": {address: True for address in address}}
                    )
                )
            elif type is AppOperationType.GET_CONFIG:
                res = await self.interface.db.ref(
                    f"/manage_app/{appName}/config"
                ).getValue()
            else:
                raise ValueError(f"Unsupported 'type': {type}.")
            return json.dumps(res, ensure_ascii=False)
        except Exception as e:


return json.dumps(res, ensure_ascii=False)
        except Exception as e:
            return f"{builtins.type(e).__name__}: {str(e)}"


Source code for langchain_community.tools.edenai.edenai_base_tool
from __future__ import annotations
import logging
from abc import abstractmethod
from typing import Any, Dict, List, Optional
import requests
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.pydantic_v1 import root_validator
from langchain_core.tools import BaseTool
from langchain_core.utils import get_from_dict_or_env
logger = logging.getLogger(__name__)
[docs]class EdenaiTool(BaseTool):
    """
    the base tool for all the EdenAI Tools .
    you should have
    the environment variable ``EDENAI_API_KEY`` set with your API token.
    You can find your token here: https://app.edenai.run/admin/account/settings
    """
    feature: str
    subfeature: str
    edenai_api_key: Optional[str] = None
    is_async: bool = False
    providers: List[str]
    """provider to use for the API call."""
    @root_validator(allow_reuse=True)
    def validate_environment(cls, values: Dict) -> Dict:
        """Validate that api key exists in environment."""
        values["edenai_api_key"] = get_from_dict_or_env(
            values, "edenai_api_key", "EDENAI_API_KEY"
        )
        return values
[docs]    @staticmethod
    def get_user_agent() -> str:
        from langchain_community import __version__
        return f"langchain/{__version__}"
    def _call_eden_ai(self, query_params: Dict[str, Any]) -> str:
        """
        Make an API call to the EdenAI service with the specified query parameters.
        Args:
            query_params (dict): The parameters to include in the API call.
        Returns:


query_params (dict): The parameters to include in the API call.
        Returns:
            requests.Response: The response from the EdenAI API call.
        """
        # faire l'API call
        headers = {
            "Authorization": f"Bearer {self.edenai_api_key}",
            "User-Agent": self.get_user_agent(),
        }
        url = f"https://api.edenai.run/v2/{self.feature}/{self.subfeature}"
        payload = {
            "providers": str(self.providers),
            "response_as_dict": False,
            "attributes_as_list": True,
            "show_original_response": False,
        }
        payload.update(query_params)
        response = requests.post(url, json=payload, headers=headers)
        self._raise_on_error(response)
        try:
            return self._parse_response(response.json())
        except Exception as e:
            raise RuntimeError(f"An error occurred while running tool: {e}")
    def _raise_on_error(self, response: requests.Response) -> None:
        if response.status_code >= 500:
            raise Exception(f"EdenAI Server: Error {response.status_code}")
        elif response.status_code >= 400:
            raise ValueError(f"EdenAI received an invalid payload: {response.text}")
        elif response.status_code != 200:
            raise Exception(
                f"EdenAI returned an unexpected response with status "
                f"{response.status_code}: {response.text}"
            )
        # case where edenai call succeeded but provider returned an error
        # (eg: rate limit, server error, etc.)
        if self.is_async is False:
            # async call are different and only return a job_id,
            # not the provider response directly
            provider_response = response.json()[0]


# not the provider response directly
            provider_response = response.json()[0]
            if provider_response.get("status") == "fail":
                err_msg = provider_response["error"]["message"]
                raise ValueError(err_msg)
    @abstractmethod
    def _run(
        self, query: str, run_manager: Optional[CallbackManagerForToolRun] = None
    ) -> str:
        pass
    @abstractmethod
    def _parse_response(self, response: Any) -> str:
        """Take a dict response and condense it's data in a human readable string"""
        pass
    def _get_edenai(self, url: str) -> requests.Response:
        headers = {
            "accept": "application/json",
            "authorization": f"Bearer {self.edenai_api_key}",
            "User-Agent": self.get_user_agent(),
        }
        response = requests.get(url, headers=headers)
        self._raise_on_error(response)
        return response
    def _parse_json_multilevel(
        self, extracted_data: dict, formatted_list: list, level: int = 0
    ) -> None:
        for section, subsections in extracted_data.items():
            indentation = "  " * level
            if isinstance(subsections, str):
                subsections = subsections.replace("\n", ",")
                formatted_list.append(f"{indentation}{section} : {subsections}")
            elif isinstance(subsections, list):
                formatted_list.append(f"{indentation}{section} : ")
                self._list_handling(subsections, formatted_list, level + 1)
            elif isinstance(subsections, dict):
                formatted_list.append(f"{indentation}{section} : ")
                self._parse_json_multilevel(subsections, formatted_list, level + 1)


self._parse_json_multilevel(subsections, formatted_list, level + 1)
    def _list_handling(
        self, subsection_list: list, formatted_list: list, level: int
    ) -> None:
        for list_item in subsection_list:
            if isinstance(list_item, dict):
                self._parse_json_multilevel(list_item, formatted_list, level)
            elif isinstance(list_item, list):
                self._list_handling(list_item, formatted_list, level + 1)
            else:
                formatted_list.append(f"{'  ' * level}{list_item}")


Source code for langchain_community.tools.edenai.ocr_invoiceparser
from __future__ import annotations
import logging
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_community.tools.edenai.edenai_base_tool import EdenaiTool
logger = logging.getLogger(__name__)
[docs]class EdenAiParsingInvoiceTool(EdenaiTool):
    """Tool that queries the Eden AI Invoice parsing API.
    for api reference check edenai documentation:
    https://docs.edenai.co/reference/ocr_invoice_parser_create.
    To use, you should have
    the environment variable ``EDENAI_API_KEY`` set with your API token.
    You can find your token here: https://app.edenai.run/admin/account/settings
    """
    name = "edenai_invoice_parsing"
    description = (
        "A wrapper around edenai Services invoice parsing. "
        """Useful for when you have to extract information from
        an image it enables to take invoices
        in a variety of formats and returns the data in contains
        (items, prices, addresses, vendor name, etc.)
        in a structured format to automate the invoice processing """
        "Input should be the string url of the document to parse."
    )
    language: Optional[str] = None
    """
    language of the image passed to the model.
    """
    feature = "ocr"
    subfeature = "invoice_parser"
    def _parse_response(self, response: list) -> str:
        formatted_list: list = []
        if len(response) == 1:
            self._parse_json_multilevel(
                response[0]["extracted_data"][0], formatted_list
            )
        else:
            for entry in response:


)
        else:
            for entry in response:
                if entry.get("provider") == "eden-ai":
                    self._parse_json_multilevel(
                        entry["extracted_data"][0], formatted_list
                    )
        return "\n".join(formatted_list)
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        query_params = {
            "file_url": query,
            "language": self.language,
            "attributes_as_list": False,
        }
        return self._call_eden_ai(query_params)


Source code for langchain_community.tools.edenai.ocr_identityparser
from __future__ import annotations
import logging
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_community.tools.edenai.edenai_base_tool import EdenaiTool
logger = logging.getLogger(__name__)
[docs]class EdenAiParsingIDTool(EdenaiTool):
    """Tool that queries the Eden AI  Identity parsing API.
    for api reference check edenai documentation:
    https://docs.edenai.co/reference/ocr_identity_parser_create.
    To use, you should have
    the environment variable ``EDENAI_API_KEY`` set with your API token.
    You can find your token here: https://app.edenai.run/admin/account/settings
    """
    name = "edenai_identity_parsing"
    description = (
        "A wrapper around edenai Services Identity parsing. "
        "Useful for when you have to extract information from an ID Document "
        "Input should be the string url of the document to parse."
    )
    feature = "ocr"
    subfeature = "identity_parser"
    language: Optional[str] = None
    """
    language of the text passed to the model.
    """
    def _parse_response(self, response: list) -> str:
        formatted_list: list = []
        if len(response) == 1:
            self._parse_json_multilevel(
                response[0]["extracted_data"][0], formatted_list
            )
        else:
            for entry in response:
                if entry.get("provider") == "eden-ai":
                    self._parse_json_multilevel(
                        entry["extracted_data"][0], formatted_list
                    )
        return "\n".join(formatted_list)


)
        return "\n".join(formatted_list)
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        query_params = {
            "file_url": query,
            "language": self.language,
            "attributes_as_list": False,
        }
        return self._call_eden_ai(query_params)


Source code for langchain_community.tools.edenai.audio_speech_to_text
from __future__ import annotations
import json
import logging
import time
from typing import List, Optional
import requests
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.pydantic_v1 import validator
from langchain_community.tools.edenai.edenai_base_tool import EdenaiTool
logger = logging.getLogger(__name__)
[docs]class EdenAiSpeechToTextTool(EdenaiTool):
    """Tool that queries the Eden AI Speech To Text API.
    for api reference check edenai documentation:
    https://app.edenai.run/bricks/speech/asynchronous-speech-to-text.
    To use, you should have
    the environment variable ``EDENAI_API_KEY`` set with your API token.
    You can find your token here: https://app.edenai.run/admin/account/settings
    """
    edenai_api_key: Optional[str] = None
    name = "edenai_speech_to_text"
    description = (
        "A wrapper around edenai Services speech to text "
        "Useful for when you have to convert audio to text."
        "Input should be a url to an audio file."
    )
    is_async = True
    language: Optional[str] = "en"
    speakers: Optional[int]
    profanity_filter: bool = False
    custom_vocabulary: Optional[List[str]]
    feature: str = "audio"
    subfeature: str = "speech_to_text_async"
    base_url = "https://api.edenai.run/v2/audio/speech_to_text_async/"
    @validator("providers")
    def check_only_one_provider_selected(cls, v: List[str]) -> List[str]:
        """


"""
        This tool has no feature to combine providers results.
        Therefore we only allow one provider
        """
        if len(v) > 1:
            raise ValueError(
                "Please select only one provider. "
                "The feature to combine providers results is not available "
                "for this tool."
            )
        return v
    def _wait_processing(self, url: str) -> requests.Response:
        for _ in range(10):
            time.sleep(1)
            audio_analysis_result = self._get_edenai(url)
            temp = audio_analysis_result.json()
            if temp["status"] == "finished":
                if temp["results"][self.providers[0]]["error"] is not None:
                    raise Exception(
                        f"""EdenAI returned an unexpected response
                        {temp['results'][self.providers[0]]['error']}"""
                    )
                else:
                    return audio_analysis_result
        raise Exception("Edenai speech to text job id processing Timed out")
    def _parse_response(self, response: dict) -> str:
        return response["public_id"]
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        all_params = {
            "file_url": query,
            "language": self.language,
            "speakers": self.speakers,
            "profanity_filter": self.profanity_filter,
            "custom_vocabulary": self.custom_vocabulary,
        }
        # filter so we don't send val to api when val is `None
        query_params = {k: v for k, v in all_params.items() if v is not None}


job_id = self._call_eden_ai(query_params)
        url = self.base_url + job_id
        audio_analysis_result = self._wait_processing(url)
        result = audio_analysis_result.text
        formatted_text = json.loads(result)
        return formatted_text["results"][self.providers[0]]["text"]


Source code for langchain_community.tools.edenai.image_objectdetection
from __future__ import annotations
import logging
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_community.tools.edenai.edenai_base_tool import EdenaiTool
logger = logging.getLogger(__name__)
[docs]class EdenAiObjectDetectionTool(EdenaiTool):
    """Tool that queries the Eden AI Object detection API.
    for api reference check edenai documentation:
    https://docs.edenai.co/reference/image_object_detection_create.
    To use, you should have
    the environment variable ``EDENAI_API_KEY`` set with your API token.
    You can find your token here: https://app.edenai.run/admin/account/settings
    """
    name = "edenai_object_detection"
    description = (
        "A wrapper around edenai Services Object Detection . "
        """Useful for when you have to do an  to identify and locate
        (with bounding boxes) objects in an image """
        "Input should be the string url of the image to identify."
    )
    show_positions: bool = False
    feature = "image"
    subfeature = "object_detection"
    def _parse_json(self, json_data: dict) -> str:
        result = []
        label_info = []
        for found_obj in json_data["items"]:
            label_str = f"{found_obj['label']} - Confidence {found_obj['confidence']}"
            x_min = found_obj.get("x_min")
            x_max = found_obj.get("x_max")
            y_min = found_obj.get("y_min")
            y_max = found_obj.get("y_max")
            if self.show_positions and all(


if self.show_positions and all(
                [x_min, x_max, y_min, y_max]
            ):  # some providers don't return positions
                label_str += f""",at the position x_min: {x_min}, x_max: {x_max},
                y_min: {y_min}, y_max: {y_max}"""
            label_info.append(label_str)
        result.append("\n".join(label_info))
        return "\n\n".join(result)
    def _parse_response(self, response: list) -> str:
        if len(response) == 1:
            result = self._parse_json(response[0])
        else:
            for entry in response:
                if entry.get("provider") == "eden-ai":
                    result = self._parse_json(entry)
        return result
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        query_params = {"file_url": query, "attributes_as_list": False}
        return self._call_eden_ai(query_params)


Source code for langchain_community.tools.edenai.text_moderation
from __future__ import annotations
import logging
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_community.tools.edenai.edenai_base_tool import EdenaiTool
logger = logging.getLogger(__name__)
[docs]class EdenAiTextModerationTool(EdenaiTool):
    """Tool that queries the Eden AI Explicit text detection.
    for api reference check edenai documentation:
    https://docs.edenai.co/reference/image_explicit_content_create.
    To use, you should have
    the environment variable ``EDENAI_API_KEY`` set with your API token.
    You can find your token here: https://app.edenai.run/admin/account/settings
    """
    name = "edenai_explicit_content_detection_text"
    description = (
        "A wrapper around edenai Services explicit content detection for text. "
        """Useful for when you have to scan text for offensive,
        sexually explicit or suggestive content,
        it checks also if there is any content of self-harm,
        violence, racist or hate speech."""
        """the structure of the output is :
        'the type of the explicit content : the likelihood of it being explicit'
        the likelihood is a number
        between 1 and 5, 1 being the lowest and 5 the highest.
        something is explicit if the likelihood is equal or higher than 3.
        for example :
        nsfw_likelihood: 1
        this is not explicit.
        for example :
        nsfw_likelihood: 3
        this is explicit.
        """
        "Input should be a string."
    )
    language: str
    feature: str = "text"


)
    language: str
    feature: str = "text"
    subfeature: str = "moderation"
    def _parse_response(self, response: list) -> str:
        formatted_result = []
        for result in response:
            if "nsfw_likelihood" in result.keys():
                formatted_result.append(
                    "nsfw_likelihood: " + str(result["nsfw_likelihood"])
                )
            for label, likelihood in zip(result["label"], result["likelihood"]):
                formatted_result.append(f'"{label}": {str(likelihood)}')
        return "\n".join(formatted_result)
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        query_params = {"text": query, "language": self.language}
        return self._call_eden_ai(query_params)


Source code for langchain_community.tools.edenai.image_explicitcontent
from __future__ import annotations
import logging
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_community.tools.edenai.edenai_base_tool import EdenaiTool
logger = logging.getLogger(__name__)
[docs]class EdenAiExplicitImageTool(EdenaiTool):
    """Tool that queries the Eden AI Explicit image detection.
    for api reference check edenai documentation:
    https://docs.edenai.co/reference/image_explicit_content_create.
    To use, you should have
    the environment variable ``EDENAI_API_KEY`` set with your API token.
    You can find your token here: https://app.edenai.run/admin/account/settings
    """
    name = "edenai_image_explicit_content_detection"
    description = (
        "A wrapper around edenai Services Explicit image detection. "
        """Useful for when you have to extract Explicit Content from images.
        it detects adult only content in images,
        that is generally inappropriate for people under
        the age of 18 and includes nudity, sexual activity,
        pornography, violence, gore content, etc."""
        "Input should be the string url of the image ."
    )
    combine_available = True
    feature = "image"
    subfeature = "explicit_content"
    def _parse_json(self, json_data: dict) -> str:
        result_str = f"nsfw_likelihood: {json_data['nsfw_likelihood']}\n"
        for idx, found_obj in enumerate(json_data["items"]):
            label = found_obj["label"].lower()
            likelihood = found_obj["likelihood"]
            result_str += f"{idx}: {label} likelihood {likelihood},\n"


result_str += f"{idx}: {label} likelihood {likelihood},\n"
        return result_str[:-2]
    def _parse_response(self, json_data: list) -> str:
        if len(json_data) == 1:
            result = self._parse_json(json_data[0])
        else:
            for entry in json_data:
                if entry.get("provider") == "eden-ai":
                    result = self._parse_json(entry)
        return result
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        query_params = {"file_url": query, "attributes_as_list": False}
        return self._call_eden_ai(query_params)


Source code for langchain_community.tools.edenai.audio_text_to_speech
from __future__ import annotations
import logging
from typing import Dict, List, Literal, Optional
import requests
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.pydantic_v1 import Field, root_validator, validator
from langchain_community.tools.edenai.edenai_base_tool import EdenaiTool
logger = logging.getLogger(__name__)
[docs]class EdenAiTextToSpeechTool(EdenaiTool):
    """Tool that queries the Eden AI Text to speech API.
    for api reference check edenai documentation:
    https://docs.edenai.co/reference/audio_text_to_speech_create.
    To use, you should have
    the environment variable ``EDENAI_API_KEY`` set with your API token.
    You can find your token here: https://app.edenai.run/admin/account/settings
    """
    name = "edenai_text_to_speech"
    description = (
        "A wrapper around edenai Services text to speech."
        "Useful for when you need to convert text to speech."
        """the output is a string representing the URL of the audio file,
        or the path to the downloaded wav file """
    )
    language: Optional[str] = "en"
    """
    language of the text passed to the model.
    """
    # optional params see api documentation for more info
    return_type: Literal["url", "wav"] = "url"
    rate: Optional[int]
    pitch: Optional[int]
    volume: Optional[int]
    audio_format: Optional[str]
    sampling_rate: Optional[int]
    voice_models: Dict[str, str] = Field(default_factory=dict)
    voice: Literal["MALE", "FEMALE"]


voice: Literal["MALE", "FEMALE"]
    """voice option : 'MALE' or 'FEMALE' """
    feature: str = "audio"
    subfeature: str = "text_to_speech"
    @validator("providers")
    def check_only_one_provider_selected(cls, v: List[str]) -> List[str]:
        """
        This tool has no feature to combine providers results.
        Therefore we only allow one provider
        """
        if len(v) > 1:
            raise ValueError(
                "Please select only one provider. "
                "The feature to combine providers results is not available "
                "for this tool."
            )
        return v
    @root_validator
    def check_voice_models_key_is_provider_name(cls, values: dict) -> dict:
        for key in values.get("voice_models", {}).keys():
            if key not in values.get("providers", []):
                raise ValueError(
                    "voice_model should be formatted like this "
                    "{<provider_name>: <its_voice_model>}"
                )
        return values
    def _download_wav(self, url: str, save_path: str) -> None:
        response = requests.get(url)
        if response.status_code == 200:
            with open(save_path, "wb") as f:
                f.write(response.content)
        else:
            raise ValueError("Error while downloading wav file")
    def _parse_response(self, response: list) -> str:
        result = response[0]
        if self.return_type == "url":
            return result["audio_resource_url"]
        else:
            self._download_wav(result["audio_resource_url"], "audio.wav")
            return "audio.wav"
    def _run(
        self,


return "audio.wav"
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        all_params = {
            "text": query,
            "language": self.language,
            "option": self.voice,
            "return_type": self.return_type,
            "rate": self.rate,
            "pitch": self.pitch,
            "volume": self.volume,
            "audio_format": self.audio_format,
            "sampling_rate": self.sampling_rate,
            "settings": self.voice_models,
        }
        # filter so we don't send val to api when val is `None
        query_params = {k: v for k, v in all_params.items() if v is not None}
        return self._call_eden_ai(query_params)


Source code for langchain_community.tools.google_serper.tool
"""Tool for the Serper.dev Google Search API."""
from typing import Optional
from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.pydantic_v1 import Field
from langchain_core.tools import BaseTool
from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper
[docs]class GoogleSerperRun(BaseTool):
    """Tool that queries the Serper.dev Google search API."""
    name: str = "google_serper"
    description: str = (
        "A low-cost Google Search API."
        "Useful for when you need to answer questions about current events."
        "Input should be a search query."
    )
    api_wrapper: GoogleSerperAPIWrapper
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return str(self.api_wrapper.run(query))
    async def _arun(
        self,
        query: str,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool asynchronously."""
        return (await self.api_wrapper.arun(query)).__str__()
[docs]class GoogleSerperResults(BaseTool):
    """Tool that queries the Serper.dev Google Search API
    and get back json."""
    name: str = "google_serper_results_json"
    description: str = (
        "A low-cost Google Search API."
        "Useful for when you need to answer questions about current events."
        "Input should be a search query. Output is a JSON object of the query results"


"Input should be a search query. Output is a JSON object of the query results"
    )
    api_wrapper: GoogleSerperAPIWrapper = Field(default_factory=GoogleSerperAPIWrapper)
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return str(self.api_wrapper.results(query))
    async def _arun(
        self,
        query: str,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool asynchronously."""
        return (await self.api_wrapper.aresults(query)).__str__()


Source code for langchain_community.tools.searchapi.tool
"""Tool for the SearchApi.io search API."""
from typing import Optional
from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.pydantic_v1 import Field
from langchain_core.tools import BaseTool
from langchain_community.utilities.searchapi import SearchApiAPIWrapper
[docs]class SearchAPIRun(BaseTool):
    """Tool that queries the SearchApi.io search API."""
    name: str = "searchapi"
    description: str = (
        "Google search API provided by SearchApi.io."
        "This tool is handy when you need to answer questions about current events."
        "Input should be a search query."
    )
    api_wrapper: SearchApiAPIWrapper
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.api_wrapper.run(query)
    async def _arun(
        self,
        query: str,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool asynchronously."""
        return await self.api_wrapper.arun(query)
[docs]class SearchAPIResults(BaseTool):
    """Tool that queries the SearchApi.io search API and returns JSON."""
    name: str = "searchapi_results_json"
    description: str = (
        "Google search API provided by SearchApi.io."
        "This tool is handy when you need to answer questions about current events."
        "The input should be a search query and the output is a JSON object "
        "with the query results."
    )


"with the query results."
    )
    api_wrapper: SearchApiAPIWrapper = Field(default_factory=SearchApiAPIWrapper)
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return str(self.api_wrapper.results(query))
    async def _arun(
        self,
        query: str,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool asynchronously."""
        return (await self.api_wrapper.aresults(query)).__str__()


Source code for langchain_community.tools.google_scholar.tool
"""Tool for the Google Scholar"""
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.tools import BaseTool
from langchain_community.utilities.google_scholar import GoogleScholarAPIWrapper
[docs]class GoogleScholarQueryRun(BaseTool):
    """Tool that queries the Google search API."""
    name: str = "google_scholar"
    description: str = (
        "A wrapper around Google Scholar Search. "
        "Useful for when you need to get information about"
        "research papers from Google Scholar"
        "Input should be a search query."
    )
    api_wrapper: GoogleScholarAPIWrapper
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.api_wrapper.run(query)


Source code for langchain_community.tools.sql_database.tool
# flake8: noqa
"""Tools for interacting with a SQL database."""
from typing import Any, Dict, Optional
from langchain_core.pydantic_v1 import BaseModel, Extra, Field, root_validator
from langchain_core.language_models import BaseLanguageModel
from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.prompts import PromptTemplate
from langchain_community.utilities.sql_database import SQLDatabase
from langchain_core.tools import BaseTool
from langchain_community.tools.sql_database.prompt import QUERY_CHECKER
[docs]class BaseSQLDatabaseTool(BaseModel):
    """Base tool for interacting with a SQL database."""
    db: SQLDatabase = Field(exclude=True)
    class Config(BaseTool.Config):
        pass
[docs]class QuerySQLDataBaseTool(BaseSQLDatabaseTool, BaseTool):
    """Tool for querying a SQL database."""
    name: str = "sql_db_query"
    description: str = """
    Input to this tool is a detailed and correct SQL query, output is a result from the database.
    If the query is not correct, an error message will be returned.
    If an error is returned, rewrite the query, check the query, and try again.
    """
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Execute the query, return the results or an error message."""
        return self.db.run_no_throw(query)
[docs]class InfoSQLDatabaseTool(BaseSQLDatabaseTool, BaseTool):
    """Tool for getting metadata about a SQL database."""
    name: str = "sql_db_schema"
    description: str = """


name: str = "sql_db_schema"
    description: str = """
    Input to this tool is a comma-separated list of tables, output is the schema and sample rows for those tables.
    Example Input: "table1, table2, table3"
    """
    def _run(
        self,
        table_names: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Get the schema for tables in a comma-separated list."""
        return self.db.get_table_info_no_throw(
            [t.strip() for t in table_names.split(",")]
        )
[docs]class ListSQLDatabaseTool(BaseSQLDatabaseTool, BaseTool):
    """Tool for getting tables names."""
    name: str = "sql_db_list_tables"
    description: str = "Input is an empty string, output is a comma separated list of tables in the database."
    def _run(
        self,
        tool_input: str = "",
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Get the schema for a specific table."""
        return ", ".join(self.db.get_usable_table_names())
[docs]class QuerySQLCheckerTool(BaseSQLDatabaseTool, BaseTool):
    """Use an LLM to check if a query is correct.
    Adapted from https://www.patterns.app/blog/2023/01/18/crunchbot-sql-analyst-gpt/"""
    template: str = QUERY_CHECKER
    llm: BaseLanguageModel
    llm_chain: Any = Field(init=False)
    name: str = "sql_db_query_checker"
    description: str = """
    Use this tool to double check if your query is correct before executing it.


Use this tool to double check if your query is correct before executing it.
    Always use this tool before executing a query with sql_db_query!
    """
    @root_validator(pre=True)
    def initialize_llm_chain(cls, values: Dict[str, Any]) -> Dict[str, Any]:
        if "llm_chain" not in values:
            from langchain.chains.llm import LLMChain
            values["llm_chain"] = LLMChain(
                llm=values.get("llm"),
                prompt=PromptTemplate(
                    template=QUERY_CHECKER, input_variables=["dialect", "query"]
                ),
            )
        if values["llm_chain"].prompt.input_variables != ["dialect", "query"]:
            raise ValueError(
                "LLM chain for QueryCheckerTool must have input variables ['query', 'dialect']"
            )
        return values
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the LLM to check the query."""
        return self.llm_chain.predict(
            query=query,
            dialect=self.db.dialect,
            callbacks=run_manager.get_child() if run_manager else None,
        )
    async def _arun(
        self,
        query: str,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        return await self.llm_chain.apredict(
            query=query,
            dialect=self.db.dialect,
            callbacks=run_manager.get_child() if run_manager else None,
        )


Source code for langchain_community.tools.eleven_labs.text2speech
import tempfile
from enum import Enum
from typing import Any, Dict, Optional, Union
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.pydantic_v1 import root_validator
from langchain_core.tools import BaseTool
from langchain_core.utils import get_from_dict_or_env
def _import_elevenlabs() -> Any:
    try:
        import elevenlabs
    except ImportError as e:
        raise ImportError(
            "Cannot import elevenlabs, please install `pip install elevenlabs`."
        ) from e
    return elevenlabs
[docs]class ElevenLabsModel(str, Enum):
    """Models available for Eleven Labs Text2Speech."""
    MULTI_LINGUAL = "eleven_multilingual_v1"
    MONO_LINGUAL = "eleven_monolingual_v1"
[docs]class ElevenLabsText2SpeechTool(BaseTool):
    """Tool that queries the Eleven Labs Text2Speech API.
    In order to set this up, follow instructions at:
    https://docs.elevenlabs.io/welcome/introduction
    """
    model: Union[ElevenLabsModel, str] = ElevenLabsModel.MULTI_LINGUAL
    name: str = "eleven_labs_text2speech"
    description: str = (
        "A wrapper around Eleven Labs Text2Speech. "
        "Useful for when you need to convert text to speech. "
        "It supports multiple languages, including English, German, Polish, "
        "Spanish, Italian, French, Portuguese, and Hindi. "
    )
    @root_validator(pre=True)
    def validate_environment(cls, values: Dict) -> Dict:
        """Validate that api key exists in environment."""


"""Validate that api key exists in environment."""
        _ = get_from_dict_or_env(values, "eleven_api_key", "ELEVEN_API_KEY")
        return values
    def _run(
        self, query: str, run_manager: Optional[CallbackManagerForToolRun] = None
    ) -> str:
        """Use the tool."""
        elevenlabs = _import_elevenlabs()
        try:
            speech = elevenlabs.generate(text=query, model=self.model)
            with tempfile.NamedTemporaryFile(
                mode="bx", suffix=".wav", delete=False
            ) as f:
                f.write(speech)
            return f.name
        except Exception as e:
            raise RuntimeError(f"Error while running ElevenLabsText2SpeechTool: {e}")
[docs]    def play(self, speech_file: str) -> None:
        """Play the text as speech."""
        elevenlabs = _import_elevenlabs()
        with open(speech_file, mode="rb") as f:
            speech = f.read()
        elevenlabs.play(speech)
[docs]    def stream_speech(self, query: str) -> None:
        """Stream the text as speech as it is generated.
        Play the text in your speakers."""
        elevenlabs = _import_elevenlabs()
        speech_stream = elevenlabs.generate(text=query, model=self.model, stream=True)
        elevenlabs.stream(speech_stream)


Source code for langchain_community.tools.eleven_labs.models
from enum import Enum
[docs]class ElevenLabsModel(str, Enum):
    """Models available for Eleven Labs Text2Speech."""
    MULTI_LINGUAL = "eleven_multilingual_v1"
    MONO_LINGUAL = "eleven_monolingual_v1"


Source code for langchain_community.tools.powerbi.tool
"""Tools for interacting with a Power BI dataset."""
import logging
from time import perf_counter
from typing import Any, Dict, Optional, Tuple
from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.pydantic_v1 import Field, validator
from langchain_core.tools import BaseTool
from langchain_community.chat_models.openai import _import_tiktoken
from langchain_community.tools.powerbi.prompt import (
    BAD_REQUEST_RESPONSE,
    DEFAULT_FEWSHOT_EXAMPLES,
    RETRY_RESPONSE,
)
from langchain_community.utilities.powerbi import PowerBIDataset, json_to_md
logger = logging.getLogger(__name__)
[docs]class QueryPowerBITool(BaseTool):
    """Tool for querying a Power BI Dataset."""
    name: str = "query_powerbi"
    description: str = """
    Input to this tool is a detailed question about the dataset, output is a result from the dataset. It will try to answer the question using the dataset, and if it cannot, it will ask for clarification.
    Example Input: "How many rows are in table1?"
    """  # noqa: E501
    llm_chain: Any
    powerbi: PowerBIDataset = Field(exclude=True)
    examples: Optional[str] = DEFAULT_FEWSHOT_EXAMPLES
    session_cache: Dict[str, Any] = Field(default_factory=dict, exclude=True)
    max_iterations: int = 5
    output_token_limit: int = 4000
    tiktoken_model_name: Optional[str] = None  # "cl100k_base"
    class Config:
        """Configuration for this pydantic object."""
        arbitrary_types_allowed = True


"""Configuration for this pydantic object."""
        arbitrary_types_allowed = True
    @validator("llm_chain")
    def validate_llm_chain_input_variables(  # pylint: disable=E0213
        cls, llm_chain: Any
    ) -> Any:
        """Make sure the LLM chain has the correct input variables."""
        for var in llm_chain.prompt.input_variables:
            if var not in ["tool_input", "tables", "schemas", "examples"]:
                raise ValueError(
                    "LLM chain for QueryPowerBITool must have input variables ['tool_input', 'tables', 'schemas', 'examples'], found %s",  # noqa: C0301 E501 # pylint: disable=C0301
                    llm_chain.prompt.input_variables,
                )
        return llm_chain
    def _check_cache(self, tool_input: str) -> Optional[str]:
        """Check if the input is present in the cache.
        If the value is a bad request, overwrite with the escalated version,
        if not present return None."""
        if tool_input not in self.session_cache:
            return None
        return self.session_cache[tool_input]
    def _run(
        self,
        tool_input: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
        **kwargs: Any,
    ) -> str:
        """Execute the query, return the results or an error message."""
        if cache := self._check_cache(tool_input):
            logger.debug("Found cached result for %s: %s", tool_input, cache)
            return cache
        try:
            logger.info("Running PBI Query Tool with input: %s", tool_input)
            query = self.llm_chain.predict(
                tool_input=tool_input,


query = self.llm_chain.predict(
                tool_input=tool_input,
                tables=self.powerbi.get_table_names(),
                schemas=self.powerbi.get_schemas(),
                examples=self.examples,
                callbacks=run_manager.get_child() if run_manager else None,
            )
        except Exception as exc:  # pylint: disable=broad-except
            self.session_cache[tool_input] = f"Error on call to LLM: {exc}"
            return self.session_cache[tool_input]
        if query == "I cannot answer this":
            self.session_cache[tool_input] = query
            return self.session_cache[tool_input]
        logger.info("PBI Query:\n%s", query)
        start_time = perf_counter()
        pbi_result = self.powerbi.run(command=query)
        end_time = perf_counter()
        logger.debug("PBI Result: %s", pbi_result)
        logger.debug(f"PBI Query duration: {end_time - start_time:0.6f}")
        result, error = self._parse_output(pbi_result)
        if error is not None and "TokenExpired" in error:
            self.session_cache[
                tool_input
            ] = "Authentication token expired or invalid, please try reauthenticate."
            return self.session_cache[tool_input]
        iterations = kwargs.get("iterations", 0)
        if error and iterations < self.max_iterations:
            return self._run(
                tool_input=RETRY_RESPONSE.format(
                    tool_input=tool_input, query=query, error=error
                ),
                run_manager=run_manager,
                iterations=iterations + 1,
            )
        self.session_cache[tool_input] = (
            result if result else BAD_REQUEST_RESPONSE.format(error=error)
        )


result if result else BAD_REQUEST_RESPONSE.format(error=error)
        )
        return self.session_cache[tool_input]
    async def _arun(
        self,
        tool_input: str,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
        **kwargs: Any,
    ) -> str:
        """Execute the query, return the results or an error message."""
        if cache := self._check_cache(tool_input):
            logger.debug("Found cached result for %s: %s", tool_input, cache)
            return f"{cache}, from cache, you have already asked this question."
        try:
            logger.info("Running PBI Query Tool with input: %s", tool_input)
            query = await self.llm_chain.apredict(
                tool_input=tool_input,
                tables=self.powerbi.get_table_names(),
                schemas=self.powerbi.get_schemas(),
                examples=self.examples,
                callbacks=run_manager.get_child() if run_manager else None,
            )
        except Exception as exc:  # pylint: disable=broad-except
            self.session_cache[tool_input] = f"Error on call to LLM: {exc}"
            return self.session_cache[tool_input]
        if query == "I cannot answer this":
            self.session_cache[tool_input] = query
            return self.session_cache[tool_input]
        logger.info("PBI Query: %s", query)
        start_time = perf_counter()
        pbi_result = await self.powerbi.arun(command=query)
        end_time = perf_counter()
        logger.debug("PBI Result: %s", pbi_result)
        logger.debug(f"PBI Query duration: {end_time - start_time:0.6f}")


result, error = self._parse_output(pbi_result)
        if error is not None and ("TokenExpired" in error or "TokenError" in error):
            self.session_cache[
                tool_input
            ] = "Authentication token expired or invalid, please try to reauthenticate or check the scope of the credential."  # noqa: E501
            return self.session_cache[tool_input]
        iterations = kwargs.get("iterations", 0)
        if error and iterations < self.max_iterations:
            return await self._arun(
                tool_input=RETRY_RESPONSE.format(
                    tool_input=tool_input, query=query, error=error
                ),
                run_manager=run_manager,
                iterations=iterations + 1,
            )
        self.session_cache[tool_input] = (
            result if result else BAD_REQUEST_RESPONSE.format(error=error)
        )
        return self.session_cache[tool_input]
    def _parse_output(
        self, pbi_result: Dict[str, Any]
    ) -> Tuple[Optional[str], Optional[Any]]:
        """Parse the output of the query to a markdown table."""
        if "results" in pbi_result:
            rows = pbi_result["results"][0]["tables"][0]["rows"]
            if len(rows) == 0:
                logger.info("0 records in result, query was valid.")
                return (
                    None,
                    "0 rows returned, this might be correct, but please validate if all filter values were correct?",  # noqa: E501
                )
            result = json_to_md(rows)
            too_long, length = self._result_too_large(result)
            if too_long:
                return (


if too_long:
                return (
                    f"Result too large, please try to be more specific or use the `TOPN` function. The result is {length} tokens long, the limit is {self.output_token_limit} tokens.",  # noqa: E501
                    None,
                )
            return result, None
        if "error" in pbi_result:
            if (
                "pbi.error" in pbi_result["error"]
                and "details" in pbi_result["error"]["pbi.error"]
            ):
                return None, pbi_result["error"]["pbi.error"]["details"][0]["detail"]
            return None, pbi_result["error"]
        return None, pbi_result
    def _result_too_large(self, result: str) -> Tuple[bool, int]:
        """Tokenize the output of the query."""
        if self.tiktoken_model_name:
            tiktoken_ = _import_tiktoken()
            encoding = tiktoken_.encoding_for_model(self.tiktoken_model_name)
            length = len(encoding.encode(result))
            logger.info("Result length: %s", length)
            return length > self.output_token_limit, length
        return False, 0
[docs]class InfoPowerBITool(BaseTool):
    """Tool for getting metadata about a PowerBI Dataset."""
    name: str = "schema_powerbi"
    description: str = """
    Input to this tool is a comma-separated list of tables, output is the schema and sample rows for those tables.
    Be sure that the tables actually exist by calling list_tables_powerbi first!
    Example Input: "table1, table2, table3"
    """  # noqa: E501
    powerbi: PowerBIDataset = Field(exclude=True)


powerbi: PowerBIDataset = Field(exclude=True)
    class Config:
        """Configuration for this pydantic object."""
        arbitrary_types_allowed = True
    def _run(
        self,
        tool_input: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Get the schema for tables in a comma-separated list."""
        return self.powerbi.get_table_info(tool_input.split(", "))
    async def _arun(
        self,
        tool_input: str,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        return await self.powerbi.aget_table_info(tool_input.split(", "))
[docs]class ListPowerBITool(BaseTool):
    """Tool for getting tables names."""
    name: str = "list_tables_powerbi"
    description: str = "Input is an empty string, output is a comma separated list of tables in the database."  # noqa: E501 # pylint: disable=C0301
    powerbi: PowerBIDataset = Field(exclude=True)
    class Config:
        """Configuration for this pydantic object."""
        arbitrary_types_allowed = True
    def _run(
        self,
        tool_input: Optional[str] = None,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Get the names of the tables."""
        return ", ".join(self.powerbi.get_table_names())
    async def _arun(
        self,
        tool_input: Optional[str] = None,
        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,
    ) -> str:
        """Get the names of the tables."""


) -> str:
        """Get the names of the tables."""
        return ", ".join(self.powerbi.get_table_names())


Source code for langchain_community.tools.google_trends.tool
"""Tool for the Google Trends"""
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.tools import BaseTool
from langchain_community.utilities.google_trends import GoogleTrendsAPIWrapper
[docs]class GoogleTrendsQueryRun(BaseTool):
    """Tool that queries the Google trends API."""
    name: str = "google_trends"
    description: str = (
        "A wrapper around Google Trends Search. "
        "Useful for when you need to get information about"
        "google search trends from Google Trends"
        "Input should be a search query."
    )
    api_wrapper: GoogleTrendsAPIWrapper
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.api_wrapper.run(query)


Source code for langchain_community.tools.google_search.tool
"""Tool for the Google search API."""
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.tools import BaseTool
from langchain_community.utilities.google_search import GoogleSearchAPIWrapper
[docs]class GoogleSearchRun(BaseTool):
    """Tool that queries the Google search API."""
    name: str = "google_search"
    description: str = (
        "A wrapper around Google Search. "
        "Useful for when you need to answer questions about current events. "
        "Input should be a search query."
    )
    api_wrapper: GoogleSearchAPIWrapper
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.api_wrapper.run(query)
[docs]class GoogleSearchResults(BaseTool):
    """Tool that queries the Google Search API and gets back json."""
    name: str = "Google Search Results JSON"
    description: str = (
        "A wrapper around Google Search. "
        "Useful for when you need to answer questions about current events. "
        "Input should be a search query. Output is a JSON array of the query results"
    )
    num_results: int = 4
    api_wrapper: GoogleSearchAPIWrapper
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return str(self.api_wrapper.results(query, self.num_results))


Source code for langchain_community.tools.google_finance.tool
"""Tool for the Google Finance"""
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.tools import BaseTool
from langchain_community.utilities.google_finance import GoogleFinanceAPIWrapper
[docs]class GoogleFinanceQueryRun(BaseTool):
    """Tool that queries the Google Finance API."""
    name: str = "google_finance"
    description: str = (
        "A wrapper around Google Finance Search. "
        "Useful for when you need to get information about"
        "google search Finance from Google Finance"
        "Input should be a search query."
    )
    api_wrapper: GoogleFinanceAPIWrapper
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.api_wrapper.run(query)


Source code for langchain_community.tools.google_places.tool
"""Tool for the Google search API."""
from typing import Optional, Type
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_core.tools import BaseTool
from langchain_community.utilities.google_places_api import GooglePlacesAPIWrapper
[docs]class GooglePlacesSchema(BaseModel):
    """Input for GooglePlacesTool."""
    query: str = Field(..., description="Query for google maps")
[docs]class GooglePlacesTool(BaseTool):
    """Tool that queries the Google places API."""
    name: str = "google_places"
    description: str = (
        "A wrapper around Google Places. "
        "Useful for when you need to validate or "
        "discover addressed from ambiguous text. "
        "Input should be a search query."
    )
    api_wrapper: GooglePlacesAPIWrapper = Field(default_factory=GooglePlacesAPIWrapper)
    args_schema: Type[BaseModel] = GooglePlacesSchema
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the tool."""
        return self.api_wrapper.run(query)


Source code for langchain_community.tools.bearly.tool
import base64
import itertools
import json
import re
from pathlib import Path
from typing import Dict, List, Type
import requests
from langchain_core.pydantic_v1 import BaseModel, Field
from langchain_community.tools import Tool
[docs]def strip_markdown_code(md_string: str) -> str:
    """Strip markdown code from a string."""
    stripped_string = re.sub(r"^`{1,3}.*?\n", "", md_string, flags=re.DOTALL)
    stripped_string = re.sub(r"`{1,3}$", "", stripped_string)
    return stripped_string
[docs]def head_file(path: str, n: int) -> List[str]:
    """Get the first n lines of a file."""
    try:
        with open(path, "r") as f:
            return [str(line) for line in itertools.islice(f, n)]
    except Exception:
        return []
[docs]def file_to_base64(path: str) -> str:
    """Convert a file to base64."""
    with open(path, "rb") as f:
        return base64.b64encode(f.read()).decode()
[docs]class BearlyInterpreterToolArguments(BaseModel):
    """Arguments for the BearlyInterpreterTool."""
    python_code: str = Field(
        ...,
        example="print('Hello World')",
        description=(
            "The pure python script to be evaluated. "
            "The contents will be in main.py. "
            "It should not be in markdown format."
        ),
    )
base_description = """Evaluates python code in a sandbox environment. \
The environment resets on every execution. \
You must send the whole script every time and print your outputs. \


You must send the whole script every time and print your outputs. \
Script should be pure python code that can be evaluated. \
It should be in python format NOT markdown. \
The code should NOT be wrapped in backticks. \
All python packages including requests, matplotlib, scipy, numpy, pandas, \
etc are available. \
If you have any files outputted write them to "output/" relative to the execution \
path. Output can only be read from the directory, stdout, and stdin. \
Do not use things like plot.show() as it will \
not work instead write them out `output/` and a link to the file will be returned. \
print() any output and results so you can capture the output."""
[docs]class FileInfo(BaseModel):
    """Information about a file to be uploaded."""
    source_path: str
    description: str
    target_path: str
[docs]class BearlyInterpreterTool:
    """Tool for evaluating python code in a sandbox environment."""
    api_key: str
    endpoint = "https://exec.bearly.ai/v1/interpreter"
    name = "bearly_interpreter"
    args_schema: Type[BaseModel] = BearlyInterpreterToolArguments
    files: Dict[str, FileInfo] = {}
[docs]    def __init__(self, api_key: str):
        self.api_key = api_key
    @property
    def file_description(self) -> str:
        if len(self.files) == 0:
            return ""
        lines = ["The following files available in the evaluation environment:"]
        for target_path, file_info in self.files.items():
            peek_content = head_file(file_info.source_path, 4)
            lines.append(
                f"- path: `{target_path}` \n first four lines: {peek_content}"


f"- path: `{target_path}` \n first four lines: {peek_content}"
                f" \n description: `{file_info.description}`"
            )
        return "\n".join(lines)
    @property
    def description(self) -> str:
        return (base_description + "\n\n" + self.file_description).strip()
[docs]    def make_input_files(self) -> List[dict]:
        files = []
        for target_path, file_info in self.files.items():
            files.append(
                {
                    "pathname": target_path,
                    "contentsBasesixtyfour": file_to_base64(file_info.source_path),
                }
            )
        return files
    def _run(self, python_code: str) -> dict:
        script = strip_markdown_code(python_code)
        resp = requests.post(
            "https://exec.bearly.ai/v1/interpreter",
            data=json.dumps(
                {
                    "fileContents": script,
                    "inputFiles": self.make_input_files(),
                    "outputDir": "output/",
                    "outputAsLinks": True,
                }
            ),
            headers={"Authorization": self.api_key},
        ).json()
        return {
            "stdout": base64.b64decode(resp["stdoutBasesixtyfour"]).decode()
            if resp["stdoutBasesixtyfour"]
            else "",
            "stderr": base64.b64decode(resp["stderrBasesixtyfour"]).decode()
            if resp["stderrBasesixtyfour"]
            else "",
            "fileLinks": resp["fileLinks"],
            "exitCode": resp["exitCode"],
        }
    async def _arun(self, query: str) -> str:
        """Use the tool asynchronously."""


"""Use the tool asynchronously."""
        raise NotImplementedError("custom_search does not support async")
[docs]    def add_file(self, source_path: str, target_path: str, description: str) -> None:
        if target_path in self.files:
            raise ValueError("target_path already exists")
        if not Path(source_path).exists():
            raise ValueError("source_path does not exist")
        self.files[target_path] = FileInfo(
            target_path=target_path, source_path=source_path, description=description
        )
[docs]    def clear_files(self) -> None:
        self.files = {}
    # TODO: this is because we can't have a dynamic description
    #  because of the base pydantic class
[docs]    def as_tool(self) -> Tool:
        return Tool.from_function(
            func=self._run,
            name=self.name,
            description=self.description,
            args_schema=self.args_schema,
        )


Source code for langchain_community.tools.merriam_webster.tool
"""Tool for the Merriam-Webster API."""
from typing import Optional
from langchain_core.callbacks import CallbackManagerForToolRun
from langchain_core.tools import BaseTool
from langchain_community.utilities.merriam_webster import MerriamWebsterAPIWrapper
[docs]class MerriamWebsterQueryRun(BaseTool):
    """Tool that searches the Merriam-Webster API."""
    name: str = "MerriamWebster"
    description: str = (
        "A wrapper around Merriam-Webster. "
        "Useful for when you need to get the definition of a word."
        "Input should be the word you want the definition of."
    )
    api_wrapper: MerriamWebsterAPIWrapper
    def _run(
        self,
        query: str,
        run_manager: Optional[CallbackManagerForToolRun] = None,
    ) -> str:
        """Use the Merriam-Webster tool."""
        return self.api_wrapper.run(query)


Source code for langchain_community.tools.json.tool
# flake8: noqa
"""Tools for working with JSON specs."""
from __future__ import annotations
import json
import re
from pathlib import Path
from typing import Dict, List, Optional, Union
from langchain_core.pydantic_v1 import BaseModel
from langchain_core.callbacks import (
    AsyncCallbackManagerForToolRun,
    CallbackManagerForToolRun,
)
from langchain_core.tools import BaseTool
def _parse_input(text: str) -> List[Union[str, int]]:
    """Parse input of the form data["key1"][0]["key2"] into a list of keys."""
    _res = re.findall(r"\[.*?]", text)
    # strip the brackets and quotes, convert to int if possible
    res = [i[1:-1].replace('"', "").replace("'", "") for i in _res]
    res = [int(i) if i.isdigit() else i for i in res]
    return res
[docs]class JsonSpec(BaseModel):
    """Base class for JSON spec."""
    dict_: Dict
    max_value_length: int = 200
[docs]    @classmethod
    def from_file(cls, path: Path) -> JsonSpec:
        """Create a JsonSpec from a file."""
        if not path.exists():
            raise FileNotFoundError(f"File not found: {path}")
        dict_ = json.loads(path.read_text())
        return cls(dict_=dict_)
[docs]    def keys(self, text: str) -> str:
        """Return the keys of the dict at the given path.
        Args:
            text: Python representation of the path to the dict (e.g. data["key1"][0]["key2"]).
        """
        try: