mirror of
https://github.com/hwchase17/langchain
synced 2024-11-10 01:10:59 +00:00
9639457222
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
138 lines
4.4 KiB
Python
138 lines
4.4 KiB
Python
"""Gmail tool utils."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
from typing import TYPE_CHECKING, List, Optional, Tuple
|
|
|
|
from langchain_core.utils import guard_import
|
|
|
|
if TYPE_CHECKING:
|
|
from google.auth.transport.requests import Request
|
|
from google.oauth2.credentials import Credentials
|
|
from google_auth_oauthlib.flow import InstalledAppFlow
|
|
from googleapiclient.discovery import Resource
|
|
from googleapiclient.discovery import build as build_resource
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def import_google() -> Tuple[Request, Credentials]:
|
|
"""Import google libraries.
|
|
|
|
Returns:
|
|
Tuple[Request, Credentials]: Request and Credentials classes.
|
|
"""
|
|
return (
|
|
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,
|
|
)
|
|
|
|
|
|
def import_installed_app_flow() -> InstalledAppFlow:
|
|
"""Import InstalledAppFlow class.
|
|
|
|
Returns:
|
|
InstalledAppFlow: InstalledAppFlow class.
|
|
"""
|
|
return guard_import(
|
|
module_name="google_auth_oauthlib.flow", pip_name="google-auth-oauthlib"
|
|
).InstalledAppFlow
|
|
|
|
|
|
def import_googleapiclient_resource_builder() -> build_resource:
|
|
"""Import googleapiclient.discovery.build function.
|
|
|
|
Returns:
|
|
build_resource: googleapiclient.discovery.build function.
|
|
"""
|
|
return guard_import(
|
|
module_name="googleapiclient.discovery", pip_name="google-api-python-client"
|
|
).build
|
|
|
|
|
|
DEFAULT_SCOPES = ["https://mail.google.com/"]
|
|
DEFAULT_CREDS_TOKEN_FILE = "token.json"
|
|
DEFAULT_CLIENT_SECRETS_FILE = "credentials.json"
|
|
|
|
|
|
def get_gmail_credentials(
|
|
token_file: Optional[str] = None,
|
|
client_secrets_file: Optional[str] = None,
|
|
scopes: Optional[List[str]] = None,
|
|
) -> Credentials:
|
|
"""Get credentials."""
|
|
# From https://developers.google.com/gmail/api/quickstart/python
|
|
Request, Credentials = (
|
|
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
|
|
scopes = scopes or DEFAULT_SCOPES
|
|
token_file = token_file or DEFAULT_CREDS_TOKEN_FILE
|
|
client_secrets_file = client_secrets_file or DEFAULT_CLIENT_SECRETS_FILE
|
|
# The file token.json stores the user's access and refresh tokens, and is
|
|
# created automatically when the authorization flow completes for the first
|
|
# time.
|
|
if os.path.exists(token_file):
|
|
creds = Credentials.from_authorized_user_file(token_file, scopes)
|
|
# If there are no (valid) credentials available, let the user log in.
|
|
if not creds or not creds.valid:
|
|
if creds and creds.expired and creds.refresh_token:
|
|
creds.refresh(Request())
|
|
else:
|
|
# https://developers.google.com/gmail/api/quickstart/python#authorize_credentials_for_a_desktop_application # noqa
|
|
flow = InstalledAppFlow.from_client_secrets_file(
|
|
client_secrets_file, scopes
|
|
)
|
|
creds = flow.run_local_server(port=0)
|
|
# Save the credentials for the next run
|
|
with open(token_file, "w") as token:
|
|
token.write(creds.to_json())
|
|
return creds
|
|
|
|
|
|
def build_resource_service(
|
|
credentials: Optional[Credentials] = None,
|
|
service_name: str = "gmail",
|
|
service_version: str = "v1",
|
|
) -> Resource:
|
|
"""Build a Gmail service."""
|
|
credentials = credentials or get_gmail_credentials()
|
|
builder = guard_import(
|
|
module_name="googleapiclient.discovery", pip_name="google-api-python-client"
|
|
).build
|
|
return builder(service_name, service_version, credentials=credentials)
|
|
|
|
|
|
def clean_email_body(body: str) -> str:
|
|
"""Clean email body."""
|
|
try:
|
|
from bs4 import BeautifulSoup
|
|
|
|
try:
|
|
soup = BeautifulSoup(str(body), "html.parser")
|
|
body = soup.get_text()
|
|
return str(body)
|
|
except Exception as e:
|
|
logger.error(e)
|
|
return str(body)
|
|
except ImportError:
|
|
logger.warning("BeautifulSoup not installed. Skipping cleaning.")
|
|
return str(body)
|