✨我用不到 65 行代码构建了一个 AI 机器人,它可以检查我的新电子邮件并向人们发送邀请📧🚀

2025-05-24

✨我用不到 65 行代码构建了一个 AI 机器人,它可以检查我的新电子邮件并向人们发送邀请📧🚀

最近我的日程安排变得非常紧张,真的需要一些帮助来管理。事实上,我发现这个问题在Composio的同事中非常普遍。
我们收到了大量与各种活动相关的电子邮件,管理它们简直就是一场噩梦。

我着手创建一个自动化程序,它可以读取我收到的电子邮件,了解其内容,确定是否需要安排事件,并最终起草一封带有邀请链接的电子邮件。

我收到了一封电子邮件 GIF

传统方法对于这项任务来说并不有效,因为涉及以下挑战:

  • 需要了解电子邮件的上下文。
  • 需要与 Gmail 和 Google 日历无缝集成。

我选择了大型语言模型 (LLM) 来应对第一个挑战。然而,真正的复杂性在于将 Gmail 和日历与 LLM 集成,尤其是考虑到这些服务可能非常挑剔。

现在,想象一下一个可以为你处理 Google OAuth 的库,简化 API 端点与 LLM 的集成。这会是一场颠覆性的变革,对吧?

这正是我们在 Composio 所提供的。


Composio - 第一个人工智能集成平台

以下是我们的简要介绍。

Composio 是一个开源工具基础架构,用于构建稳健可靠的 AI 应用程序。我们提供 100 多种工具和集成,涵盖 CRM、HRM、销售、生产力、开发和社交媒体等各个行业。

我们负责所有这些应用程序的用户身份验证和授权,并使所有 API 端点与各种 AI 模型和框架的连接变得简单。因此,您可以将更多时间用于创造股东价值,而不是排查不必要的错误。

男人挣扎的 gif

请帮我们加一颗星。🥹

这将有助于我们创作更多这样的文章💖

为 Composio.dev 仓库加星标⭐


LangGraph - 构建可用于生产的 AI 应用的框架

要完成该项目,您将需要另一个依赖项 LangGraph。

LangGraph 是一个用于构建有状态 AI 工作流的开源框架。它使用模块化图形架构定义工作流,从而更轻松地控制工作流中的每个步骤。
关键组件

  • 状态:
    • 代表应用程序当前快照的共享数据结构。
    • 它可以是任何 Python 类型,但通常是TypedDictPydantic BaseModel
  • 节点:
    • 对代理的逻辑进行编码的 Python 函数。
    • 它们接收当前状态作为输入,执行一些计算或副作用,并返回更新的状态。
  • 边缘:
    • 根据当前状态确定下一步执行哪个节点的 Python 函数。
    • 它们可以是条件分支或固定转换。

强烈建议您在继续之前先阅读本指南。

在本文中,您将构建一个端到端的 AI 机器人,它可以读取传入的电子邮件、处理它们、决定是否需要安排它们,并最终使用日历链接起草一封邀请电子邮件给收件人。


总体工作流程

让我们看一下整体工作流程。

  • 使用 Composio 连接 Gmail 和 Google 日历。
  • 在 Composio 中启用触发器来接收邮件。
  • 使用 LangGraph 创建 AI 机器人。
  • 该机器人会轮询 Gmail 中是否有收到的电子邮件。
  • 电子邮件被传递给机器人进行进一步分析。
  • 如果电子邮件包含活动安排信息:
    • 是的:机器人从日历中获取空闲时段并起草一封带有预定活动邀请链接的合适电子邮件。
    • 否:忽略。

电子邮件调度代理


构建人工智能机器人的先决条件

您需要满足以下要求才能完成该项目。

  • Composio 用户帐户。点击此处免费创建。
  • OpenAI API 积分。您也可以使用 Groq 的 Llama 等开源 LLM。

让我们构建它!

设置环境

Python 开发的第一条规则始终是创建虚拟环境。

python -m venv gmail-bot

cd gmail-bot
source bit/activate
Enter fullscreen mode Exit fullscreen mode

现在,安装依赖项。

pip install composio-core 
pip install composio-langgraph
pip install python-dotenv

Enter fullscreen mode Exit fullscreen mode
  • composio-core:Composio 所有功能的核心库。
  • composio-langgraph:Composio 的 LangGraph 插件。
  • python-dotenv:从文件设置环境变量.env

创建一个 .env 文件并设置 OpenAI API 密钥。

OPENAI_API_KEY="YOUR_KEY"
Enter fullscreen mode Exit fullscreen mode

集成 Gmail 和 Google 日历

为了集成 Gmail 和日历,我们将使用 Composio 的专用 CLI,但在此之前请登录到您的用户帐户。

composio login
Enter fullscreen mode Exit fullscreen mode

完成登录流程即可继续下一步。现在,刷新应用程序。

composio apps update
Enter fullscreen mode Exit fullscreen mode

集成 Gmail

composio add gmail
Enter fullscreen mode Exit fullscreen mode

集成 Google 日历

composio add googlecalendar
Enter fullscreen mode Exit fullscreen mode

完成集成流程以将这些服务添加到您的用户帐户。

Composio 最好的一点是您可以在仪表板上监控这些集成。

用于集成的 Composio 仪表板

接下来,启用触发器以在有人发送电子邮件时接收电子邮件。

composio triggers enable gmail_new_gmail_message
Enter fullscreen mode Exit fullscreen mode

您甚至可以从仪表板监控触发器。


构建人工智能机器人

正如我们之前讨论的,LangGraph 使用节点和边定义工作流。

该工作流程将有四个关键组件:开始、结束、工具节点和调度程序节点。

  • 开始:工作流的入口点。
  • 工具节点:处理调用 LLM 可用的工具。
  • 调度程序节点:管理处理来自电子邮件、工具调用等的文本输入。
  • END:工作流程的出口点。

当调度程序节点确定需要调用某个工具时,它会将控制权移交给工具节点,然后工具节点执行该工具并将结果和控制权发送回调度程序节点。

一旦执行完成,调度节点就会终止该进程。

这是一个高级示意图。

LangGraph工作流程图

现在,让我们开始编写工作流程代码。


导入库

首先,导入所需的库并使用.env 设置环境变量。

from typing import Literal, Annotated, Sequence, TypedDict
import operator
import re
from datetime import datetime
from dotenv import load_dotenv
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, ToolMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, StateGraph
from langgraph.prebuilt import ToolNode
from composio_langgraph import Action, ComposioToolSet
from composio.client.collections import TriggerEventData

# Setup
load_dotenv()
Enter fullscreen mode Exit fullscreen mode

现在,定义常量。

# Constants
SCHEDULER_AGENT_NAME = "Scheduler"
TOOL_NODE_NAME = "ToolNode"
DATE_TIME = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
Enter fullscreen mode Exit fullscreen mode

定义工具

接下来,我们将定义用于安排事件和起草电子邮件的工具和工具节点。

# Initialize LLM and tools
llm = ChatOpenAI(model="gpt-4-turbo")
composio_toolset = ComposioToolSet()

schedule_tools = composio_toolset.get_actions(
    actions=[
        Action.GOOGLECALENDAR_FIND_FREE_SLOTS,
        Action.GOOGLECALENDAR_CREATE_EVENT,
    ]
)
email_tools = composio_toolset.get_actions(actions=[Action.GMAIL_CREATE_EMAIL_DRAFT])
tools = [*schedule_tools, *email_tools]

tool_node = ToolNode(tools)
Enter fullscreen mode Exit fullscreen mode

上面的代码块,

  • 使用 OpenAI 的 GPT-4 Turbo 模型初始化大型语言模型 (LLM)。
  • 创建 Composio 工具集的实例,该工具集提供对 Google 服务集成的访问。
  • 从与 Google 日历相关的 Composio 工具集中获取查找空闲时段和创建事件的操作。
  • 获取在 Gmail 中创建电子邮件草稿的操作。
  • 创建一个包含 LangGraph 中要使用的所有操作的工具节点。

注意:工具节点抽象了 LLM 的调用和处理工具调用。


定义提示

接下来,定义系统提示符。这很重要,因为它将为 LLM 提供处理收到的邮件所需的上下文。

# System prompt
scheduler_system_prompt = f"""
You are an AI assistant specialized in analyzing emails, creating calendar events, and drafting response emails. Your primary tasks are:

1. Analyze email content:
   a. Understand the email received from the sender. 
   b. Determine if an event should be created based on the email content.
   c. Extract relevant information such as proposed meeting times, topics, and participants.

2. Manage calendar events:
   a. If an event should be created, use the Google Calendar Find Free Slots action to identify available time slots.
   b. Once a suitable slot is found, use the Google Calendar Create Event action to schedule the event.
   c. Ensure to invite the email sender and any other relevant participants to the event.

3. Draft response emails:
   a. If an event was created, draft a confirmation email for the sender.
   b. The email should include:
      - A clear subject line (e.g., "Meeting Scheduled")
      - A brief description of the scheduled meeting's purpose
      - The date, time, and duration of the event
      - Any other relevant details or instructions for the participants

Remember:
- The current date and time is {DATE_TIME}.
- All conversations and scheduling occur in the IST timezone.
- Be courteous and professional in all communications.
- If you encounter any errors when making function calls, try passing an empty config ({{"config": {{}}}}).
- Always provide a FINAL ANSWER when you've completed all necessary tasks.

You aim to efficiently manage scheduling and communication, ensuring a smooth experience for all parties involved.
"""
Enter fullscreen mode Exit fullscreen mode

我们定义了一个清晰且循序渐进的系统提示来指导 LLM。


定义 AgentState 和辅助函数

在 LangGraph 中,AgentState 会跟踪任何给定点的代理工作流的状态。

# Define AgentState
class AgentState(TypedDict):
    messages: Annotated[Sequence[BaseMessage], operator.add]
    sender: str

# Helper functions
def create_agent_node(agent, name):
    def agent_node(state):
        result = agent.invoke(state)
        if not isinstance(result, ToolMessage):
            result = AIMessage(**result.dict(exclude={"type", "name"}), name=name)
        return {"messages": [result], "sender": name}
    return agent_node

def create_agent(system_prompt, tools):
    prompt = ChatPromptTemplate.from_messages([
        ("system", system_prompt),
        MessagesPlaceholder(variable_name="messages"),
    ])
    return prompt | llm.bind_tools(tools)
Enter fullscreen mode Exit fullscreen mode

事情是这样的,

  • AgentState(TypedDict):定义代理状态的字典结构,包含消息列表和发件人的姓名。
  • create_agent_node(agent, name):创建一个处理代理状态的函数,调用代理,并将结果格式化为以代理名称作为发件人的消息。
  • create_agent(system_prompt, tools):该函数通过从系统指令和消息创建提示模板并将LLM绑定到指定的工具来构建代理。

使用系统提示、工具和代理节点使用scheduler_agent和常量SCHEDULER_AGENT_NAME创建代理。

scheduler_agent = create_agent(scheduler_system_prompt, tools)
scheduler_node = create_agent_node(scheduler_agent, SCHEDULER_AGENT_NAME)
Enter fullscreen mode Exit fullscreen mode

该节点处理与安排 Google 日历事件相关的所有事务,从检查时段到确认事件。


定义节点、边和工作流

众所周知,LangGraph 遵循有向图结构,其中每个节点包含一个可执行文件(可执行的代码)和引导信息流的边。

# Create workflow
workflow = StateGraph(AgentState)

workflow.add_node(SCHEDULER_AGENT_NAME, scheduler_node)
workflow.add_node(TOOL_NODE_NAME, tool_node)

Enter fullscreen mode Exit fullscreen mode

在上面的代码块中,

  • 我们使用 定义了工作流图StateGraph(AgentState)。AgentState 跟踪状态对象。
  • 添加了tool_node和scheduler_node两个节点。

现在,定义边来引导信息流。

# Router function
def router(state) -> Literal["call_tool", "__end__", "continue"]:
    last_message = state["messages"][-1]
    if last_message.tool_calls:
        return "call_tool"
    if "FINAL ANSWER" in last_message.content:
        return "__end__"
    return "continue"

workflow.add_edge(START, SCHEDULER_AGENT_NAME)
workflow.add_edge(SCHEDULER_AGENT_NAME, END)

Enter fullscreen mode Exit fullscreen mode

这是定义我们的工作流程边缘的代码。

  • 路由器从代理状态返回节点名称。这有助于导航工作流。它还可以将流控制权从一个节点转移到另一个节点,并结束工作流。
  • 我们定义了两个从 START→SCHEDULER_AGENT_NAME→END 移动的正常边。

条件边

该工作流程包括两个关键条件边缘:

  • 从到各个节点的条件边SCHEDULER_AGENT_NAME

    pythonCopy code
    workflow.add_conditional_edges(
        SCHEDULER_AGENT_NAME,
        router,
        {
            "continue": SCHEDULER_AGENT_NAME,
            "call_tool": TOOL_NODE_NAME,
        },
    )
    
    
    • 目的:此边决定调度代理处理当前状态后的下一步。
    • 条件:router函数检查状态中最后一条消息的内容。
    • 可能的结果:
      • “continue”:如果router函数返回"continue",则工作流停留在SCHEDULER_AGENT_NAME节点中,允许代理继续处理。
      • “call_tool”:如果router函数返回"call_tool",工作流将转换到TOOL_NODE_NAME调用相关工具(例如,查找空闲插槽或创建事件)的节点。
  • 条件边从TOOL_NODE_NAMESCHEDULER_AGENT_NAME

    pythonCopy code
    workflow.add_conditional_edges(
        TOOL_NODE_NAME,
        lambda x: x["sender"],
        {SCHEDULER_AGENT_NAME: SCHEDULER_AGENT_NAME},
    )
    
    • 目的:此边缘决定调用工具(如 Google 日历或 Gmail)后将工作流程路由到何处。
    • 条件: lambda 函数lambda x: x["sender"]检查最后一条消息的发送者。
    • 结果:如果发送者是SCHEDULER_AGENT_NAME,则工作流返回节点SCHEDULER_AGENT_NAME继续处理。

最后,编译工作流程。

app = workflow.compile()
Enter fullscreen mode Exit fullscreen mode

设置事件监听器

下一步是定义事件监听器。当有人向您关联的 Gmail 帐户发送电子邮件时,它将负责获取邮件。

def extract_sender_email(payload):
    if not any(header.get("name") == "Delivered-To" and header.get("value") for header in payload["headers"]):
        return None

    for header in payload["headers"]:
        if header["name"] == "From":
            match = re.search(r"[\w\.-]+@[\w\.-]+", header["value"])
            return match.group(0) if match else None
    return None

def process_email(email_sender, email_content, thread_id):
    final_state = app.invoke({
        "messages": [
            HumanMessage(content=f"""                              
Please process the email 
Email sender: {email_sender} 
Email content: {email_content}
Thread id: {thread_id}
""")
        ]
    })
    return final_state["messages"][-1].content

listener = composio_toolset.create_trigger_listener()

@listener.callback(filters={"trigger_name": "gmail_new_gmail_message"})
def callback_new_message(event: TriggerEventData) -> None:
    payload = event.payload
    thread_id = payload.get("threadId")
    email_content = payload.get("snippet")
    email_sender = extract_sender_email(payload["payload"])

    if email_sender is None:
        print("No sender email found")
        return

    print(f"Processing email from: {email_sender}")
    output = process_email(email_sender, email_content, thread_id)
    print("Final output:", output)

listener.listen()
Enter fullscreen mode Exit fullscreen mode

以下是上述代码块的解释

  • extract_sender_email(payload)从电子邮件有效负载标头中提取发件人的电子邮件地址,如果找到则返回,None如果找不到则返回。
  • process_email(email_sender, email_content, thread_id)使用电子邮件详细信息调用工作流并返回最终处理的消息内容。
  • 监听器设置(listener = composio_toolset.create_trigger_listener()):创建一个监听器来监视特定事件,例如新的 Gmail 消息。
  • @listener.callback(filters={"trigger_name": "gmail_new_gmail_message"})定义一个回调函数,当检测到新的 Gmail 消息事件时触发,通过工作流处理电子邮件。
  • listener.listen()此命令启动监听器并通过调用回调函数使其主动监听和响应新的 Gmail 消息。

完成所有步骤后,运行 Python 文件来设置事件监听器。

下次您向已配置的 Gmail 帐户发送电子邮件时,机器人会处理该邮件,并确定是安排活动还是直接转发。如果已安排活动,系统会准备一份电子邮件草稿供您审核,以便您根据需要发送。

您可以在这里找到完整的代码:Scheduling Agent


感谢您的阅读!🎉


帮帮我!

如果您觉得本文能帮助您更好地理解 AI 驱动的事件自动化,请给我们一颗星,我将非常高兴!请在评论区留言告诉我。

我需要你的帮助 GIF

为 Composio.dev 仓库加星标⭐

文章来源:https://dev.to/composiodev/i-built-an-ai-bot-under-65-lines-of-code-that-c​​hecks-my-new-emails-and-send-people-invites-ghh
PREV
我开发了一个 AI 工具来处理我妈妈的发票,帮她节省了 20 个小时的工作时间!😲
NEXT
我构建了一个 AI 代理来验证我的 PR,而无需亲自执行🚀⚡