From 7929b26017ef4d82b53d3d95510ae020e855d172 Mon Sep 17 00:00:00 2001 From: Leonid Ganeline Date: Tue, 28 Nov 2023 08:49:24 -0800 Subject: [PATCH] office365 toolkit bug fixes (#13618) Several bug fixes: - emails: instead of `bcc` the `cc` is used. - errors in the truncation descriptions - no truncation of the `message_search` Several updates: - generalized UTC format - truncation limit can be changed now in _call() --- .../tools/office365/create_draft_message.py | 2 +- .../tools/office365/events_search.py | 23 +++++++++---------- .../tools/office365/messages_search.py | 9 ++++---- .../langchain/tools/office365/send_event.py | 5 ++-- .../langchain/tools/office365/send_message.py | 2 +- .../langchain/tools/office365/utils.py | 4 ++++ 6 files changed, 25 insertions(+), 20 deletions(-) diff --git a/libs/langchain/langchain/tools/office365/create_draft_message.py b/libs/langchain/langchain/tools/office365/create_draft_message.py index 6585b048225..26d72c604ad 100644 --- a/libs/langchain/langchain/tools/office365/create_draft_message.py +++ b/libs/langchain/langchain/tools/office365/create_draft_message.py @@ -60,7 +60,7 @@ class O365CreateDraftMessage(O365BaseTool): if cc is not None: message.cc.add(cc) if bcc is not None: - message.bcc.add(cc) + message.bcc.add(bcc) message.save_draft() diff --git a/libs/langchain/langchain/tools/office365/events_search.py b/libs/langchain/langchain/tools/office365/events_search.py index 0438b911624..e758cc3fd37 100644 --- a/libs/langchain/langchain/tools/office365/events_search.py +++ b/libs/langchain/langchain/tools/office365/events_search.py @@ -11,13 +11,13 @@ from langchain_core.pydantic_v1 import BaseModel, Extra, Field from langchain.callbacks.manager import CallbackManagerForToolRun from langchain.tools.office365.base import O365BaseTool -from langchain.tools.office365.utils import clean_body +from langchain.tools.office365.utils import UTC_FORMAT, clean_body class SearchEventsInput(BaseModel): - """Input for SearchEmails Tool.""" + """Input for SearchEmails Tool. - """From https://learn.microsoft.com/en-us/graph/search-query-parameter""" + From https://learn.microsoft.com/en-us/graph/search-query-parameter""" start_datetime: str = Field( description=( @@ -47,7 +47,7 @@ class SearchEventsInput(BaseModel): default=True, description=( "Whether the event's body is truncated to meet token number limits. Set to " - "False for searches that will retrieve very few results, otherwise, set to " + "False for searches that will retrieve small events, otherwise, set to " "True." ), ) @@ -82,16 +82,15 @@ class O365SearchEvents(O365BaseTool): max_results: int = 10, truncate: bool = True, run_manager: Optional[CallbackManagerForToolRun] = None, + truncate_limit: int = 150, ) -> List[Dict[str, Any]]: - TRUNCATE_LIMIT = 150 - # Get calendar object schedule = self.account.schedule() calendar = schedule.get_default_calendar() # Process the date range parameters - start_datetime_query = dt.strptime(start_datetime, "%Y-%m-%dT%H:%M:%S%z") - end_datetime_query = dt.strptime(end_datetime, "%Y-%m-%dT%H:%M:%S%z") + start_datetime_query = dt.strptime(start_datetime, UTC_FORMAT) + end_datetime_query = dt.strptime(end_datetime, UTC_FORMAT) # Run the query q = calendar.new_query("start").greater_equal(start_datetime_query) @@ -107,7 +106,7 @@ class O365SearchEvents(O365BaseTool): output_event["subject"] = event.subject if truncate: - output_event["body"] = clean_body(event.body)[:TRUNCATE_LIMIT] + output_event["body"] = clean_body(event.body)[:truncate_limit] else: output_event["body"] = clean_body(event.body) @@ -115,14 +114,14 @@ class O365SearchEvents(O365BaseTool): time_zone = start_datetime_query.tzinfo # Assign the datetimes in the search time zone output_event["start_datetime"] = event.start.astimezone(time_zone).strftime( - "%Y-%m-%dT%H:%M:%S%z" + UTC_FORMAT ) output_event["end_datetime"] = event.end.astimezone(time_zone).strftime( - "%Y-%m-%dT%H:%M:%S%z" + UTC_FORMAT ) output_event["modified_date"] = event.modified.astimezone( time_zone - ).strftime("%Y-%m-%dT%H:%M:%S%z") + ).strftime(UTC_FORMAT) output_events.append(output_event) diff --git a/libs/langchain/langchain/tools/office365/messages_search.py b/libs/langchain/langchain/tools/office365/messages_search.py index 66cdb9dbb03..0bf266ddcdb 100644 --- a/libs/langchain/langchain/tools/office365/messages_search.py +++ b/libs/langchain/langchain/tools/office365/messages_search.py @@ -10,7 +10,7 @@ from langchain_core.pydantic_v1 import BaseModel, Extra, Field from langchain.callbacks.manager import CallbackManagerForToolRun from langchain.tools.office365.base import O365BaseTool -from langchain.tools.office365.utils import clean_body +from langchain.tools.office365.utils import UTC_FORMAT, clean_body class SearchEmailsInput(BaseModel): @@ -46,7 +46,7 @@ class SearchEmailsInput(BaseModel): default=True, description=( "Whether the email body is truncated to meet token number limits. Set to " - "False for searches that will retrieve very few results, otherwise, set to " + "False for searches that will retrieve small messages, otherwise, set to " "True" ), ) @@ -78,6 +78,7 @@ class O365SearchEmails(O365BaseTool): max_results: int = 10, truncate: bool = True, run_manager: Optional[CallbackManagerForToolRun] = None, + truncate_limit: int = 150, ) -> List[Dict[str, Any]]: # Get mailbox object mailbox = self.account.mailbox() @@ -97,13 +98,13 @@ class O365SearchEmails(O365BaseTool): output_message["from"] = message.sender if truncate: - output_message["body"] = message.body_preview + output_message["body"] = message.body_preview[:truncate_limit] else: output_message["body"] = clean_body(message.body) output_message["subject"] = message.subject - output_message["date"] = message.modified.strftime("%Y-%m-%dT%H:%M:%S%z") + output_message["date"] = message.modified.strftime(UTC_FORMAT) output_message["to"] = [] for recipient in message.to._recipients: diff --git a/libs/langchain/langchain/tools/office365/send_event.py b/libs/langchain/langchain/tools/office365/send_event.py index 29565311949..86f06fd996e 100644 --- a/libs/langchain/langchain/tools/office365/send_event.py +++ b/libs/langchain/langchain/tools/office365/send_event.py @@ -11,6 +11,7 @@ from langchain_core.pydantic_v1 import BaseModel, Field from langchain.callbacks.manager import CallbackManagerForToolRun from langchain.tools.office365.base import O365BaseTool +from langchain.tools.office365.utils import UTC_FORMAT class SendEventSchema(BaseModel): @@ -72,8 +73,8 @@ class O365SendEvent(O365BaseTool): event.body = body event.subject = subject - event.start = dt.strptime(start_datetime, "%Y-%m-%dT%H:%M:%S%z") - event.end = dt.strptime(end_datetime, "%Y-%m-%dT%H:%M:%S%z") + event.start = dt.strptime(start_datetime, UTC_FORMAT) + event.end = dt.strptime(end_datetime, UTC_FORMAT) for attendee in attendees: event.attendees.add(attendee) diff --git a/libs/langchain/langchain/tools/office365/send_message.py b/libs/langchain/langchain/tools/office365/send_message.py index b00c9853073..96e8344073e 100644 --- a/libs/langchain/langchain/tools/office365/send_message.py +++ b/libs/langchain/langchain/tools/office365/send_message.py @@ -60,7 +60,7 @@ class O365SendMessage(O365BaseTool): if cc is not None: message.cc.add(cc) if bcc is not None: - message.bcc.add(cc) + message.bcc.add(bcc) message.send() diff --git a/libs/langchain/langchain/tools/office365/utils.py b/libs/langchain/langchain/tools/office365/utils.py index 16a772857e2..127fb6dba1f 100644 --- a/libs/langchain/langchain/tools/office365/utils.py +++ b/libs/langchain/langchain/tools/office365/utils.py @@ -72,3 +72,7 @@ def authenticate() -> Account: return account else: return account + + +UTC_FORMAT = "%Y-%m-%dT%H:%M:%S%z" +"""UTC format for datetime objects."""