community[patch]: tools imports (#21156)

Issue: we have several helper functions to import third-party libraries
like tools.gmail.utils.import_google in
[community.tools](https://api.python.langchain.com/en/latest/community_api_reference.html#id37).
And we have core.utils.utils.guard_import that works exactly for this
purpose.
The import_<package> functions work inconsistently and rather be private
functions.
Change: replaced these functions with the guard_import function.

Related to #21133
This commit is contained in:
Leonid Ganeline 2024-05-03 14:22:45 -07:00 committed by GitHub
parent 3ef8b24277
commit 9639457222
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 40 deletions

View File

@ -1,10 +1,13 @@
"""Gmail tool utils.""" """Gmail tool utils."""
from __future__ import annotations from __future__ import annotations
import logging import logging
import os import os
from typing import TYPE_CHECKING, List, Optional, Tuple from typing import TYPE_CHECKING, List, Optional, Tuple
from langchain_core.utils import guard_import
if TYPE_CHECKING: if TYPE_CHECKING:
from google.auth.transport.requests import Request from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials from google.oauth2.credentials import Credentials
@ -21,16 +24,15 @@ def import_google() -> Tuple[Request, Credentials]:
Returns: Returns:
Tuple[Request, Credentials]: Request and Credentials classes. Tuple[Request, Credentials]: Request and Credentials classes.
""" """
# google-auth-httplib2 return (
try: guard_import(
from google.auth.transport.requests import Request module_name="google.auth.transport.requests",
from google.oauth2.credentials import Credentials pip_name="google-auth-httplib2",
except ImportError: ).Request,
raise ImportError( guard_import(
"You need to install google-auth-httplib2 to use this toolkit. " module_name="google.oauth2.credentials", pip_name="google-auth-httplib2"
"Try running pip install --upgrade google-auth-httplib2" ).Credentials,
) )
return Request, Credentials
def import_installed_app_flow() -> InstalledAppFlow: def import_installed_app_flow() -> InstalledAppFlow:
@ -39,14 +41,9 @@ def import_installed_app_flow() -> InstalledAppFlow:
Returns: Returns:
InstalledAppFlow: InstalledAppFlow class. InstalledAppFlow: InstalledAppFlow class.
""" """
try: return guard_import(
from google_auth_oauthlib.flow import InstalledAppFlow module_name="google_auth_oauthlib.flow", pip_name="google-auth-oauthlib"
except ImportError: ).InstalledAppFlow
raise ImportError(
"You need to install google-auth-oauthlib to use this toolkit. "
"Try running pip install --upgrade google-auth-oauthlib"
)
return InstalledAppFlow
def import_googleapiclient_resource_builder() -> build_resource: def import_googleapiclient_resource_builder() -> build_resource:
@ -55,14 +52,9 @@ def import_googleapiclient_resource_builder() -> build_resource:
Returns: Returns:
build_resource: googleapiclient.discovery.build function. build_resource: googleapiclient.discovery.build function.
""" """
try: return guard_import(
from googleapiclient.discovery import build module_name="googleapiclient.discovery", pip_name="google-api-python-client"
except ImportError: ).build
raise ImportError(
"You need to install googleapiclient to use this toolkit. "
"Try running pip install --upgrade google-api-python-client"
)
return build
DEFAULT_SCOPES = ["https://mail.google.com/"] DEFAULT_SCOPES = ["https://mail.google.com/"]
@ -77,8 +69,19 @@ def get_gmail_credentials(
) -> Credentials: ) -> Credentials:
"""Get credentials.""" """Get credentials."""
# From https://developers.google.com/gmail/api/quickstart/python # From https://developers.google.com/gmail/api/quickstart/python
Request, Credentials = import_google() Request, Credentials = (
InstalledAppFlow = import_installed_app_flow() guard_import(
module_name="google.auth.transport.requests",
pip_name="google-auth-httplib2",
).Request,
guard_import(
module_name="google.oauth2.credentials", pip_name="google-auth-httplib2"
).Credentials,
)
InstalledAppFlow = guard_import(
module_name="google_auth_oauthlib.flow", pip_name="google-auth-oauthlib"
).InstalledAppFlow
creds = None creds = None
scopes = scopes or DEFAULT_SCOPES scopes = scopes or DEFAULT_SCOPES
token_file = token_file or DEFAULT_CREDS_TOKEN_FILE token_file = token_file or DEFAULT_CREDS_TOKEN_FILE
@ -111,7 +114,9 @@ def build_resource_service(
) -> Resource: ) -> Resource:
"""Build a Gmail service.""" """Build a Gmail service."""
credentials = credentials or get_gmail_credentials() credentials = credentials or get_gmail_credentials()
builder = import_googleapiclient_resource_builder() builder = guard_import(
module_name="googleapiclient.discovery", pip_name="google-api-python-client"
).build
return builder(service_name, service_version, credentials=credentials) return builder(service_name, service_version, credentials=credentials)

View File

@ -4,6 +4,7 @@ from typing import TYPE_CHECKING, Optional, Tuple, Type
from langchain_core.pydantic_v1 import root_validator from langchain_core.pydantic_v1 import root_validator
from langchain_core.tools import BaseTool from langchain_core.tools import BaseTool
from langchain_core.utils import guard_import
if TYPE_CHECKING: if TYPE_CHECKING:
from playwright.async_api import Browser as AsyncBrowser from playwright.async_api import Browser as AsyncBrowser
@ -25,15 +26,10 @@ def lazy_import_playwright_browsers() -> Tuple[Type[AsyncBrowser], Type[SyncBrow
Tuple[Type[AsyncBrowser], Type[SyncBrowser]]: Tuple[Type[AsyncBrowser], Type[SyncBrowser]]:
AsyncBrowser and SyncBrowser classes. AsyncBrowser and SyncBrowser classes.
""" """
try: return (
from playwright.async_api import Browser as AsyncBrowser guard_import(module_name="playwright.async_api").AsyncBrowser,
from playwright.sync_api import Browser as SyncBrowser guard_import(module_name="playwright.sync_api").SyncBrowser,
except ImportError: )
raise ImportError(
"The 'playwright' package is required to use the playwright tools."
" Please install it with 'pip install playwright'."
)
return AsyncBrowser, SyncBrowser
class BaseBrowserTool(BaseTool): class BaseBrowserTool(BaseTool):
@ -45,7 +41,8 @@ class BaseBrowserTool(BaseTool):
@root_validator @root_validator
def validate_browser_provided(cls, values: dict) -> dict: def validate_browser_provided(cls, values: dict) -> dict:
"""Check that the arguments are valid.""" """Check that the arguments are valid."""
lazy_import_playwright_browsers() guard_import(module_name="playwright.async_api").AsyncBrowser
guard_import(module_name="playwright.sync_api").SyncBrowser
if values.get("async_browser") is None and values.get("sync_browser") is None: if values.get("async_browser") is None and values.get("sync_browser") is None:
raise ValueError("Either async_browser or sync_browser must be specified.") raise ValueError("Either async_browser or sync_browser must be specified.")
return values return values
@ -57,5 +54,6 @@ class BaseBrowserTool(BaseTool):
async_browser: Optional[AsyncBrowser] = None, async_browser: Optional[AsyncBrowser] = None,
) -> BaseBrowserTool: ) -> BaseBrowserTool:
"""Instantiate the tool.""" """Instantiate the tool."""
lazy_import_playwright_browsers() guard_import(module_name="playwright.async_api").AsyncBrowser
guard_import(module_name="playwright.sync_api").SyncBrowser
return cls(sync_browser=sync_browser, async_browser=async_browser) return cls(sync_browser=sync_browser, async_browser=async_browser)