From d2f10ea90ca1ffa8e5b571017f2ab548db8d1897 Mon Sep 17 00:00:00 2001 From: yzlin Date: Thu, 8 Feb 2024 00:05:00 +0800 Subject: [PATCH] add ocr example, modify email example --- examples/ci/email_summary.py | 14 ++++-- examples/ci/ocr_receipt.py | 19 ++++++++ metagpt/tools/libs/email_login.py | 14 ++---- requirements.txt | 1 + tests/metagpt/tools/libs/test_email_login.py | 49 ++------------------ 5 files changed, 37 insertions(+), 60 deletions(-) create mode 100644 examples/ci/ocr_receipt.py diff --git a/examples/ci/email_summary.py b/examples/ci/email_summary.py index dd8dd8c8e..d6fa283ca 100644 --- a/examples/ci/email_summary.py +++ b/examples/ci/email_summary.py @@ -4,17 +4,23 @@ @Author : Tuo Zhou @File : email_summary.py """ +import os from metagpt.roles.ci.code_interpreter import CodeInterpreter async def main(): - # For email response prompt email_account = "your_email_account" - # prompt = f"""I will give you your Outlook email account({email_account}) and password(email_password item in the environment variable). You need to find the latest email in my inbox with the sender's suffix @qq.com and reply to him "Thank you! I have received your email~""""" - prompt = f"""I will give you your Outlook email account({email_account}) and password(email_password item in the environment variable). + # your password will stay only on your device and not go to LLM api + os.environ["email_password"] = "your_email_password" + + ### Prompt for automatic email reply, uncomment to try this too ### + # prompt = f"""I will give you your Outlook email account ({email_account}) and password (email_password item in the environment variable). You need to find the latest email in my inbox with the sender's suffix @gmail.com and reply "Thank you! I have received your email~""""" + + ### Prompt for automatic email summary ### + prompt = f"""I will give you your Outlook email account ({email_account}) and password (email_password item in the environment variable). Firstly, Please help me fetch the latest 5 senders and full letter contents. - Then, summarize each of the 5 emails into one sentence(you can do this by yourself, no need import other models to do this) and output them in a markdown format.""" + Then, summarize each of the 5 emails into one sentence (you can do this by yourself, no need to import other models to do this) and output them in a markdown format.""" ci = CodeInterpreter(use_tools=True) diff --git a/examples/ci/ocr_receipt.py b/examples/ci/ocr_receipt.py new file mode 100644 index 000000000..dc2db2d01 --- /dev/null +++ b/examples/ci/ocr_receipt.py @@ -0,0 +1,19 @@ +from metagpt.roles.ci.code_interpreter import CodeInterpreter + + +async def main(): + # Notice: pip install metagpt[ocr] before using this example + image_path = "image.jpg" + language = "English" + requirement = f"""This is a {language} invoice image. + Your goal is to perform OCR on images using PaddleOCR, then extract the total amount from ocr text results, and finally save as table. Image path: {image_path}. + NOTE: The environments for Paddle and PaddleOCR are all ready and has been fully installed.""" + ci = CodeInterpreter() + + await ci.run(requirement) + + +if __name__ == "__main__": + import asyncio + + asyncio.run(main()) diff --git a/metagpt/tools/libs/email_login.py b/metagpt/tools/libs/email_login.py index 8fd77274c..79734665e 100644 --- a/metagpt/tools/libs/email_login.py +++ b/metagpt/tools/libs/email_login.py @@ -1,6 +1,5 @@ from imap_tools import MailBox -from metagpt.logs import logger from metagpt.tools.tool_registry import register_tool from metagpt.tools.tool_type import ToolType @@ -44,15 +43,8 @@ def email_login_imap(email_address, email_password): # Determine the correct IMAP server imap_server = IMAP_SERVERS.get(domain) - if not imap_server: - logger.error(f"IMAP server for {domain} not found.") - return None + assert imap_server, f"IMAP server for {domain} not found." # Attempt to log in to the email account - try: - mailbox = MailBox(imap_server).login(email_address, email_password) - logger.info("Login successful") - return mailbox - except Exception as e: - logger.error(f"Login failed: {e}") - return None + mailbox = MailBox(imap_server).login(email_address, email_password) + return mailbox diff --git a/requirements.txt b/requirements.txt index 6cb25d52b..1357f2e5d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -67,3 +67,4 @@ google-generativeai==0.3.2 anytree ipywidgets==8.1.1 Pillow +imap_tools==1.5.0 # Used by metagpt/tools/libs/email_login.py diff --git a/tests/metagpt/tools/libs/test_email_login.py b/tests/metagpt/tools/libs/test_email_login.py index c18d15c7d..e98820f70 100644 --- a/tests/metagpt/tools/libs/test_email_login.py +++ b/tests/metagpt/tools/libs/test_email_login.py @@ -1,48 +1,7 @@ -import os - -import pytest - from metagpt.tools.libs.email_login import email_login_imap -# Configuration for the test IMAP servers -TEST_IMAP_SERVERS = {"outlook.com": "imap-mail.outlook.com"} -# Setup correct and incorrect email information -correct_email_address = "englishgpt@outlook.com" -correct_email_password = os.environ.get("outlook_email_password") -incorrect_email_address = "test@unknown.com" -incorrect_email_password = "incorrect_password" - - -@pytest.fixture -def imap_server_setup(mocker): - # Use the mocker fixture to mock the MailBox class - mock_mailbox = mocker.patch("metagpt.tools.libs.email_login.MailBox") - mock_mail_instance = mocker.Mock() - mock_mail_instance.login.return_value = mock_mail_instance - mock_mailbox.return_value = mock_mail_instance - return mock_mail_instance - - -def test_email_login_imap_success(imap_server_setup): - # Mock successful login - mailbox = email_login_imap(correct_email_address, correct_email_password) - assert mailbox is not None - # Correctly assert that the login method of the MailBox mock was called with the correct arguments - imap_server_setup.login.assert_called_with(correct_email_address, correct_email_password) - - -def test_email_login_imap_failure_due_to_incorrect_server(imap_server_setup): - # Attempt to login with an incorrect server - mailbox = email_login_imap(incorrect_email_address, incorrect_email_password) - assert mailbox is None - - -def test_email_login_imap_failure_due_to_wrong_credentials(imap_server_setup): - # Configure mock to throw an exception to simulate login failure due to incorrect credentials - imap_server_setup.login.side_effect = Exception("Login failed") - # Attempt to login which should simulate a failure - mailbox = email_login_imap(correct_email_address, incorrect_email_password) - assert mailbox is None - # Verify that the login method was called with the expected arguments - imap_server_setup.login.assert_called_with(correct_email_address, incorrect_email_password) +def test_email_login(mocker): + mock_mailbox = mocker.patch("metagpt.tools.libs.email_login.MailBox.login") + mock_mailbox.login.return_value = mocker.Mock() + email_login_imap("test@outlook.com", "test_password")