-4.6 C
New York
Monday, December 23, 2024

Automating E-mail Sorting and Labelling with CrewAI


Introduction

By no means would have the inventor of e-mail –Ray Tomlinson– considered how far this piece of tech would attain sooner or later. At the moment, e-mail is the prime pillar of company {and professional} communications and is utilized in innumerable sides of the working world. And this has propelled the creation of an entire set of instruments and plugins to optimise your e-mail inbox! With the appearance of generative AI, the most recent discuss on the town is in regards to the widespread use of AI Brokers to optimise emails. On this weblog, I’ll clarify the craft of automating e-mail sorting and labelling by constructing brokers utilizing crewAI.

Overview

  • Discover ways to give your purposes entry to your Gmail utilizing Google Cloud Console’s OAuth 2.0
  • Perceive the code and construct an agent that makes use of an LLM to learn and categorise mails into pre-defined classes.
  • Discover ways to automate the method of e-mail sorting and labelling utilizing crewAI by merely operating a Python script.

Understanding the Context

If you’re not residing beneath a rock and have an e-mail handle, you understand how flooded your inbox tends to get after an evening’s sleep. Advertising emails, private messages, skilled communications, and so forth, particularly in case you are a busy working skilled. The frustration of a cluttered inbox will be felt within the picture beneath:

Automating Email Sorting and Labelling with CrewAI

The worst half is that even after creating related labels within the e-mail (Gmail within the case of the writer), one has to take the time to assign these emails to the right label. With the developments in generative AI, shouldn’t it’s a lot simpler to kind and label emails in Gmail? Why don’t we cut back the steps of sorting related emails to a single click on?  

Let me illustrate how we are able to use crewAI to construct an LLM agent and automate this course of. The top objective is robotically sorting our unread emails utilizing crewAI into three classes: ‘Reply Instantly’, ‘No Reply’, and ‘Irrelevant’We then add these categorised emails to Gmail and the respective labels. 

Be aware: We manually created these labels –  ‘Reply Instantly’, ‘No Reply’, and ‘Irrelevant’ – in Gmail.

Automating Email Sorting and Labelling with CrewAI

Additionally Learn: Prime 10 AI E-mail Automation Instruments to Use in 2024

Steps for Google Authentication

Earlier than we leap to the code to kind emails in Gmail, it’s worthwhile to allow the Gmail API and generate the OAuth 2.0 credentials. It will assist your e-mail sorting agentic system entry your emails. Listed below are the steps to do that.

Step 1: Create a New Venture in Google Cloud

Step one in a Google authentication course of is to create a brand new mission in Google Cloud.

  • 1. Go to the Google Cloud console and log in along with your e-mail handle. First-time customers should create an account.
  • Then choose “New Venture” within the dropdown, give it a reputation, and click on Create. This mission could have the required API-related configurations. Whereas including the brand new mission, select your organisation title as the placement, as we’ve got chosen analyticsvidhya.com
Automating Email Sorting and Labelling with CrewAI | Steps for Google Authentication
Automating Email Sorting and Labelling with CrewAI | Steps for Google Authentication

Step 2: Allow Gmail API

The subsequent step is to allow Gmail API.

  • 1. Click on the Navigation Menu from the console’s Dashboard to Discover and Allow APIs beneath “Getting Began.
  • On the left aspect of the display screen, choose Library and seek for “Gmail API.” Then, please allow it for the mission you created.
Automating Email Sorting and Labelling with CrewAI | Steps for Google Authentication

Step 3: Set Up OAuth 2.0 Credentials

The final step in Google Authentication is to arrange OAuth 2.0 credentials.

  • First, arrange the OAuth consent display screen beneath APIs & Providers >. Click on Configure Consent Display.
Automating Email Sorting and Labelling with CrewAI | Steps for Google Authentication
  • Select the sort (e.g., Exterior for apps utilized by anybody). We selected Inside since we’re utilizing it for our e-mail ID. Then Click on Create.
  • Identify your app and add the Person help e-mail and Developer contact info. Ideally, it is best to add your work e-mail ID. Click on SAVE AND CONTINUE on the backside of the display screen.
Automating Email Sorting and Labelling with CrewAI | Steps for Google Authentication
  • Now, Outline the scopes within the consent display screen setup. Scopes within the context of Google Console dictate what the API can entry. For email-related duties, you’ll want the next: ‘https://www.googleapis.com/auth/gmail.modify‘. This scope will enable our e-mail sorting and labelling system to ship and modify emails in your Gmail account.

Click on on ADD OR REMOVE SCOPES after which choose the scope talked about above.

  • Click on on Replace. You may see the scope has been added. Press SAVE AND CONTINUE.
Automating Email Sorting and Labelling with CrewAI | Steps for Google Authentication
  • Undergo the abstract and click on BACK TO DASHBOARD.

Step 4: Creating Credentials

  • Now, select Credentials beneath APIs & Providers and click on CREATE CREDENTIALS.
  • For native improvement, we are going to select the Desktop App possibility. After which press CREATE.
Automating Email Sorting and Labelling with CrewAI | Steps for Google Authentication

Step 5: Obtain the Credential.json

  • Now obtain the JSON file and put it aside regionally at your most popular location.

Python Code for Sorting and Labelling Emails Utilizing crewAI

We are going to now start coding the e-mail sorting and labelling system utilizing crewAI. Guarantee you will have put in crewAI and utils.

Set up crewAI

#pip set up crewai==0.28.8 crewai_tools==0.1.6

#pip set up utils

#pip set up google-auth-oauthlib

#pip set up google-api-python-client

Import Libraries

Now, we are going to import the related libraries.

# Import commonplace libraries

import json                   # For working with JSON information

import os                     # For interacting with the working system

import os.path                # For manipulating filesystem pathnames

import pickle                 # For serializing and deserializing Python objects

# Import Google API shopper libraries for authentication and API requests

from google.auth.transport.requests import Request            # For making authenticated HTTP requests

from google.oauth2.credentials import Credentials             # For dealing with OAuth 2.0 credentials

from google_auth_oauthlib.stream import InstalledAppFlow        # For managing OAuth 2.0 authorization flows

from googleapiclient.discovery import construct                   # For establishing a Useful resource object for interacting with an API

from googleapiclient.errors import HttpError                  # For dealing with HTTP errors from API requests

# Import customized libraries (assuming these are your individual modules or third-party packages)

from crewai import Agent, Job, Crew                          # For managing brokers, duties, and crews

from crewai_tools import Instrument                                 # For added instruments and utilities

# Import pandas library

import pandas as pd                                           # For information manipulation and evaluation

Entry to LLM

After this, we are going to give our e-mail sorter and labeller entry to an LLM. I’m utilizing the GPT 4o mannequin for this job, however you may select the LLM of your alternative.

# Set OpenAI API key

os.environ['OPENAI_API_KEY'] = "Your API Key"

os.environ["OPENAI_MODEL_NAME"] = 'Mannequin Identify’'

Now, we are going to create the EmailCollector job, which makes use of Google’s API to work together with Gmail and fetch unread emails.

class EmailCollector:

    def __init__(self):

        self.creds = None

        self._authenticate()

    def _authenticate(self):

        SCOPES = ['https://www.googleapis.com/auth/gmail.modify']  # Use modify to replace emails

        if os.path.exists('token.pickle'):

            with open('token.pickle', 'rb') as token:

                self.creds = pickle.load(token)

        if not self.creds or not self.creds.legitimate:

            if self.creds and self.creds.expired and self.creds.refresh_token:

                self.creds.refresh(Request())

            else:

                stream = InstalledAppFlow.from_client_secrets_file(

                    '/Customers/admin/Desktop/Blogs/credentials.json', SCOPES)

                self.creds = stream.run_local_server(port=0)

            with open('token.pickle', 'wb') as token:

                pickle.dump(self.creds, token)

    def get_unread_emails(self):

        service = construct('gmail', 'v1', credentials=self.creds)

        outcomes = service.customers().messages().checklist(userId='me', q='is:unread').execute()

        messages = outcomes.get('messages', [])

        email_list = []

        if not messages:

            print('No unread emails discovered.')

        else:

            for message in messages:

                msg = service.customers().messages().get(userId='me', id=message['id'], format="full").execute()

                email_list.append(msg)

        return email_list

Code Clarification

Here’s what the above code does:

  1. First, the EmailCollector initialises with self.creds = None and calls the _authenticate methodology to deal with authentication.
  2. Then, the  _authenticate methodology checks if a token.pickle file exists. If it exists, it hundreds the saved credentials from the file utilizing pickle.
  3. If credentials are expired or lacking, it checks if a refresh token is accessible to refresh them. If not, it initiates an OAuth stream utilizing InstalledAppFlow, prompting the consumer to log in.
  4. After acquiring the credentials (new or refreshed), they’re saved to the token pickle for future use.
  5. The get_unread_emails methodology retrieves an inventory of unread emails after connecting to the Gmail API utilizing the authenticated credentials.
  6. It loops by way of every unread e-mail, retrieves full message particulars, and shops them within the email_list.
  7. Lastly, the checklist of unread emails is returned for additional use.

Create Mail Knowledge Gatherer

Now, we are going to create the mailDataGatherer() operate to assemble the unread emails and save them as a .csv file.

def mailDataGatherer():

    # Create the E-mail Collector occasion

    email_collector_instance = EmailCollector()

    # Get unread emails

    email_list = email_collector_instance.get_unread_emails()

    # Put together information for DataFrame

    emails_data = []

    for e-mail in email_list:

        topic = subsequent(header['value'] for header in e-mail['payload']['headers'] if header['name'] == 'Topic')

        physique = ''

        if 'elements' in e-mail['payload']:

            for half in e-mail['payload']['parts']:

                if half['mimeType'] == 'textual content/plain':

                    physique = half['body']['data']

                    break

        else:

            physique = e-mail['payload']['body']['data']

        import base64

        physique = base64.urlsafe_b64decode(physique).decode('utf-8')

        emails_data.append({

            'Topic': topic,

            'Physique': physique

        })

    # Create a DataFrame

    df = pd.DataFrame(emails_data)

    # Save DataFrame to CSV

    df.to_csv('unread_emails.csv', index=False)

    df.fillna("",inplace=True)

    # Print the DataFrame

    return df

Code Clarification

Right here is an evidence of the above code:

  • First, the operate handles authentication and retrieves unread emails utilizing an occasion of the EmailCollector class.
  • Then, we fetch the unread emails utilizing the get_unread_emails() methodology from the EmailCollector occasion.
  • After that, we course of the e-mail information contained in the loop, which is
    1. The operate extracts the topic from the e-mail headers for every e-mail within the checklist.
    2. It checks the e-mail’s physique, decoding it from base64 format to get the precise textual content.
    3. It collects each the topic and physique of the emails.
  • We are going to retailer the processed e-mail information (topic and physique) in a Pandas DataFrame.
  • The DataFrame is saved as a CSV file known as unread_emails.csv, and any lacking values are crammed with empty strings.
  • Lastly, the operate returns the DataFrame for additional use or viewing.

Now, we are going to create the extract_mail_tool for our agent utilizing the Instrument performance inside crewAI. This instrument will use the emaiDataGatherer operate to assemble the topic and physique of the unread e-mail.

# Create the Extract Topics instrument

extract_mail_tool = Instrument(

    title="mailDataGatherer",

    description="Get all the topics and physique content material of unread emails.",

    func=mailDataGatherer

)

Now, we are going to create a operate that takes within the JSON illustration of the unread emails. It then decodes the emails and labels the corresponding emails in our Gmail inbox as per the pre-defined classes –  ‘Reply Instantly’, ‘No Reply’, and ‘Irrelevan.t’ 

def push_mail_label(dfjson):

    emails = pd.DataFrame(json.hundreds(dfjson.change("```","").change("json","")))

    SCOPES = ['https://www.googleapis.com/auth/gmail.modify']  # Use modify to replace emails

    #Change the title and path of your file beneath accordingly

    stream = InstalledAppFlow.from_client_secrets_file(

                        '/Customers/admin/Desktop/Blogs/credentials.json', SCOPES)

    creds = stream.run_local_server(port=0)

    service = construct('gmail', 'v1', credentials=creds)

    labels = service.customers().labels().checklist(userId='me').execute().get('labels', [])

    label_map = {label['name']: label['id'] for label in labels}

    def get_or_create_label(label_name):

        if label_name in label_map:

            return label_map[label_name]

        else:

            # Create new label if it would not exist

            new_label = {

                'labelListVisibility': 'labelShow',

                'messageListVisibility': 'present',

                'title': label_name

            }

            created_label = service.customers().labels().create(userId='me', physique=new_label).execute()

            return created_label['id']

    # Map the classes to Gmail labels, creating them if they do not exist

    category_label_map = {

        "Reply Instantly": get_or_create_label("Reply Instantly"),

        "No Reply": get_or_create_label("No Reply"),

        "Irrelevant": get_or_create_label("Irrelevant")

    }

    

    for i in vary(emails.form[0]):

        topic = emails.iloc[i]['Subject']

        physique = emails.iloc[i]['Body']

        class = emails.iloc[i]['Category']

        search_query = f'topic:("{topic}")'

        outcomes = service.customers().messages().checklist(userId='me', q=search_query).execute()

        message_id = outcomes['messages'][0]['id']  # Get the primary matching message ID

        label_id = category_label_map.get(class, None)

        # Apply label based mostly on class

        if label_id:

            service.customers().messages().modify(

                userId='me',

                id=message_id,

                physique={

                    'addLabelIds': [label_id],

                    'removeLabelIds': []  # Optionally add label elimination logic right here

                }

            ).execute()

            print(f'Up to date e-mail with topic: {topic} to label: {class}')

        else:

            print(f'Class {class} doesn't match any Gmail labels.')

        

    return

How does this operate work?

The operate works as follows:

  1. The dfjson string is first cleaned of additional characters. It’s then parsed right into a Pandas DataFrame that accommodates columns like Topic, Physique, and Class for every e-mail.
  2. Then, with Google OAuth 2.0, the operate authenticates with Gmail by way of InstalledAppFlow utilizing the gmail.modify scope. This permits it to switch emails (including labels in our case).
  3. Subsequent, the operate retrieves all current Gmail labels from the consumer’s account and shops them in a label_map dictionary (label title to label ID).
  4. After that, the get_or_create_label() operate checks if a label already exists. If not, it creates a brand new one utilizing the Gmail API.
  5. Subsequent, it maps the classes within the e-mail information to their respective Gmail labels (Reply Instantly, No Reply, Irrelevant), creating them if needed.
  6. For every e-mail, the operate searches Gmail for an identical message by the topic, retrieves the message ID and applies the corresponding label based mostly on the class.
  7. On the finish, the operate prints a message indicating success or failure for every e-mail it processes.

Defining the E-mail Sorting Agent

This agent will classify the unread emails into three classes we’ve got outlined. The agent makes use of the extract_mail_tool to entry the emails, which makes use of the mailDataGatherer() operate to get the emails. Since this agent makes use of LLM, you will need to give correct directions on what is predicted to be accomplished. For instance, one express instruction I’ve added is in regards to the sort of mail that have to be included in each bit of content material. You may learn the directions additional within the agent’s backstory parameter. 

sorter = Agent(

    position="E-mail Sorter",

    objective="Clasify the emails into one of many 3  classes supplied",

    instruments=[extract_mail_tool],  # Add instruments if wanted

    verbose=True,

    backstory=(

        "You might be an skilled private assistant working for a busy company skilled."

        "You might be dealing with the private e-mail account of the CEO."

        "You may have been assigned a job to categorise the unread emails into one of many three classes."

        "Listing of the three classes is : ['Reply Immediately', 'No Reply' and 'Irrelevant']"

        "'Reply Instantly' ought to embrace unread emails from inside the group and out of doors. This could be a normal inquiry, question and calender invitations."

        "'No Reply' contains unread emails the place somebody is letting me know of some improvement inside the firm. It additionally contains Newsletters that I've subscribed to."

        "'Irrelevant' accommodates unread emails which can be from exterior companies advertising there merchandise."

        "You may apply your individual intelligence whereas sorting the unread emails."

        "You get the info of unread mails in a pandas dataframe utilizing the instrument mailDataGatherer."

        "You'll get 'Topic' and 'Physique' columns within the dataframe returned by instrument."

        "It's best to classify the mails on foundation of topic and physique and name it 'Class'."

        "There isn't a instrument which you should utilize for classification. Use your individual intelligence to do it."

        "Lastly you come back a json with 3 keys for every mail: 'Topic', 'Physique', 'Class'"

    )

)

Be aware that we’ve got set verbose = True, which helps us view how the mannequin thinks. 

Outline the Job

Now, we are going to outline the Job that the sorter agent will carry out. We now have added the precise checklist of duties, which you’ll learn within the code beneath.

# Job for Sorter: Kind Emails

sort_task = Job(

    objective="Kind the categorised emails into: ['Reply Immediately', 'No Reply' and 'Irrelevant'] ",

    description= "1. At first, get the dataframe of unread emails utilizing the 'mailDataGatherer'."

                    "2. Don't use the instrument once more after getting obtained the topic and physique"

                    "3. Classify the emails into one of many above classes: ['Reply Immediately', 'No Reply' and 'Irrelevant']."

                    "4. There isn't a instrument which you should utilize for classification. Use the directions and your individual intelligence to do it."

                    "5. Lastly, return a json with three keys for every row: ['Subject', 'Body', 'Category']"

                    "6. All of the emails should strictly be labeled into certainly one of above three classes solely.",

    expected_output = "A json file with all of the unread emails. There must be 3 keys for every mail- Topic, Physique and Class ",

    agent=sorter,

    

    async_execution=False

)

Allow Collaboration in CrewAI

Subsequent, we are going to use crewAI’s performance to allow collaboration and let the sorter agent carry out the duties outlined within the sort_task operate above.

# Create the Crew

email_sorting_crew = Crew(

    brokers=[sorter],

    duties=[sort_task],

    verbose=True

)

Lastly, we are going to kickoff our crew to let it kind the unread emails robotically and save the output within the end result variable.

# Working the crew

end result = email_sorting_crew.kickoff()

Since verbose = True for all components in our agent, we get to see how our agent performs.

Python Code for Sorting and Labelling Emails Using crewAI
Python Code for Sorting and Labelling Emails Using crewAI

Now, we push this end result into our Gmail utilizing the push_mail_label() operate.

#push the outcomes

push_mail_label(end result)

Be aware that all through the execution, you may be twice redirected to a special window to offer the mandatory permissions. As soon as the code can reaccess the emails, the unread emails might be pushed beneath the related labels.

And Voila! We now have the emails with labels connected. For privateness, I cannot show my complete inbox.

Conclusion

Keep in mind the frustration we mentioned earlier within the weblog? Properly, crewAI’s e-mail sorting and labelling agentic system permits us to save lots of a major period of time.

With LLM brokers, the chances of job automation are countless. It is dependent upon how nicely you assume and construction your agentic system. As a subsequent step, you may strive constructing an agent that checks whether or not the primary agent’s categorisation is right. Or, you may also strive creating an agent that prepares an e-mail for the ‘Reply Instantly’ class and pushes it to the drafts in Gmail. Sounds bold? So, go on and get your fingers soiled. Glad studying!!

Continuously Requested Questions

Q1. What’s crewAI?

A. crewAI is an open-source Python framework that helps growing and managing multi-agent AI methods. Utilizing crewAI, you may construct LLM-backed AI brokers that may autonomously make choices inside an setting based mostly on the variables current.

Q2. Can I exploit crewAI to kind my Gmail emails?

A. Sure! You need to use crewAI to construct LLM-backed brokers to automate e-mail sorting and labelling duties.

Q3. What number of brokers do I must construct utilizing crewAI to kind emails in Gmail?

A. Relying in your agentic system construction, you should utilize as many brokers as you prefer to kind emails in Gmail. Nevertheless, it is strongly recommended that you simply construct one agent per job. 

This fall. What duties can CrewAI do?

A. CrewAI can carry out numerous duties, together with sorting and writing emails, planning tasks, producing articles, scheduling and posting social media content material, and extra.

Q5. How does sorting and labelling emails in Gmail utilizing crewAI save time?

A. Since GenAI brokers utilizing crewAI make choices utilizing LLMs, it reduces the requirement to allocate human sources to undergo emails and make choices.

Q6. How can e-mail sorting be automated utilizing crewAI?

A. To automate e-mail sorting utilizing crewAI, you will need to outline the brokers with a descriptive backstory inside the Agent operate, outline duties for every agent utilizing the Job performance, after which create a Crew to allow totally different brokers to collaborate.

My title is Abhiraj. I’m presently a supervisor for the Instruction Design staff at Analytics Vidhya. My pursuits embrace badminton, voracious studying, and assembly new individuals. Each day I like studying new issues and spreading my information.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles