使用openai的function calling实现自动发送邮件,并用twilio实现自动拨打电话

1)自动发送邮件
用的是126邮箱,开启服务

帮助中心_常见问题

然后写代码,记得在.env写入对应的key值

import os
from dotenv import load_dotenv

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

import json
from openai import OpenAI


GPT_MODEL = "gpt-4o-mini"

load_dotenv()
# 获取环境变量
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
AUTHORIZATION_CODE = os.getenv("AUTHORIZATION_CODE")

client = OpenAI(api_key=OPENAI_API_KEY)

tools = [
    {
        "type": "function",
        "function": {
            "name": "send_email",
            "description": "Send an email to the specified email with the subject and content",
            "parameters":{
                "type": "object",
                "properties": {
                    "FromEmail": {
                        "type": "string",
                        "description": "The email address, eg., rememeber0101@126.com",
                    },
                    "Subject": {
                        "type": "string",
                        "description": "Subject of the email",
                    },
                    "Body": {
                        "type": "string",
                        "description": "The content of the email",
                    },
                    "Recipients": {
                        "type": "string",
                        "description": "The recipients' email addresses",
                    }
                },
                "required": ["FromEmail", "Subject", "Body", "Recipients"],
            },
        }
    }
]


def chat_completion_request(messages, tools=None, tool_choice=None, model=GPT_MODEL):
    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            tools=tools,
            tool_choice=tool_choice,
        )
        return response
    except Exception as e:
        print("Unable to generate ChatCompletion response")
        print(f"Exception: {e}")
        return e


def send_email(sender_email, sender_authorization_code, recipient_email, subject, body):
    # 创建 MIMEMultipart 对象
    message = MIMEMultipart()
    message["From"] = sender_email
    message["To"] = recipient_email
    message["Subject"] = subject

    message.attach(MIMEText(body, "plain"))

    # 创建 SMTP_SSL 会话
    with smtplib.SMTP_SSL("smtp.126.com", 465) as server:
        server.login(sender_email, sender_authorization_code)
        text = message.as_string()
        server.sendmail(sender_email, recipient_email, text)


def main():
    messages = []
    
    while True:
        msg = input("【You】: ")
        messages.append({"role": "user", "content": msg})
        response = chat_completion_request(
            messages=messages,
            tools=tools
        )
        if content := response.choices[0].message.content:
            print(f"【AI】: {content}")
            messages.append({"role": "assistant", "content": content})
        else:
            fn_name = response.choices[0].message.tool_calls[0].function.name
            fn_args = response.choices[0].message.tool_calls[0].function.arguments
            # print(f"【Debug info】: fn_name - {fn_name}")
            # print(f"【Debug info】: fn_args - {fn_args}")
        
            if fn_name == "send_email":
                try:
                    args = json.loads(fn_args)
                    # 返回将要发送的邮件内容给用户确认
                    print("【AI】: 邮件内容如下:")
                    print(f"发件人: {args['FromEmail']}")
                    print(f"收件人: {args['Recipients']}")
                    print(f"主题: {args['Subject']}")
                    print(f"内容: {args['Body']}")
                    
                    confirm = input("AI: 确认发送邮件吗? (yes/no): ").strip().lower()
                    if confirm == "yes":
                        send_email(
                            sender_email=args["FromEmail"],
                            sender_authorization_code=AUTHORIZATION_CODE, 
                            recipient_email=args["Recipients"], 
                            subject=args["Subject"], 
                            body=args["Body"],
                        )
                        print("邮件已发送,还需要什么帮助吗?")
                        messages.append({"role": "assistant", "content": "邮件已发送,还需要什么帮助吗?"})
                    else:
                        print("邮件发送已取消,还需要什么帮助吗?")
                        messages.append({"role": "assistant", "content": "邮件发送已取消,还需要什么帮助吗?"})
                except Exception as e:
                    print(f"发送邮件时出错:{e}")
                    messages.append({"role": "assistant", "content": "抱歉,功能异常!"})    


if __name__ == "__main__":
    main()


# 帮我发送一封邮件
# 发件人: remember0202@126.com, 收件人:remember0101@126.com, 发送内容写着一封来自未来胖虎的问候邮件,主题随便

下面是streamlit版本

import os
from dotenv import load_dotenv

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

import json
import openai

import streamlit as st

GPT_MODEL = "gpt-4o-mini"

load_dotenv()
# 获取环境变量
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
AUTHORIZATION_CODE = os.getenv("AUTHORIZATION_CODE")

client = openai.OpenAI(api_key=OPENAI_API_KEY)

tools = [
    {
        "type": "function",
        "function": {
            "name": "send_email",
            "description": "Send an email to the specified email with the subject and content",
            "parameters": {
                "type": "object",
                "properties": {
                    "FromEmail": {
                        "type": "string",
                        "description": "The email address, eg., remember0101@126.com",
                    },
                    "Subject": {
                        "type": "string",
                        "description": "Subject of the email",
                    },
                    "Body": {
                        "type": "string",
                        "description": "The content of the email",
                    },
                    "Recipients": {
                        "type": "string",
                        "description": "The recipients' email addresses",
                    }
                },
                "required": ["FromEmail", "Subject", "Body", "Recipients"],
            },
        }
    }
]

st.sidebar.header("📃 Dialgue Session:")

def chat_completion_request(messages, tools=None, tool_choice=None, model=GPT_MODEL):
    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            tools=tools,
            tool_choice=tool_choice,
        )
        return response
    except Exception as e:
        print("Unable to generate ChatCompletion response")
        print(f"Exception: {e}")
        return e

def send_email(sender_email, sender_authorization_code, recipient_email, subject, body):
    # 创建 MIMEMultipart 对象
    message = MIMEMultipart()
    message["From"] = sender_email
    message["To"] = recipient_email
    message["Subject"] = subject

    message.attach(MIMEText(body, "plain"))

    # 创建 SMTP_SSL 会话
    with smtplib.SMTP_SSL("smtp.126.com", 465) as server:
        server.login(sender_email, sender_authorization_code)
        text = message.as_string()
        server.sendmail(sender_email, recipient_email, text)

def main():
    st.title("🪪 AI Assistant")

    # Initialize chat history
    if "messages" not in st.session_state:
        st.session_state.messages = []

    # Display chat messages from history on app rerun
    for message in st.session_state.messages:
        with st.chat_message(message["role"]):
            st.markdown(message["content"])

    # React to user input
    if prompt := st.chat_input("What is your message?"):
        # Display user message in chat message container
        st.chat_message("user").markdown(prompt)
        # Add user message to chat history
        st.session_state.messages.append({"role": "user", "content": prompt})

        response = chat_completion_request(
            messages=st.session_state.messages,
            tools=tools
        )
        st.sidebar.json(st.session_state)
        st.sidebar.write(response)
        # Display assistant response in chat message container
        with st.chat_message("assistant"):
            if content := response.choices[0].message.content:
                st.markdown(content)
                st.session_state.messages.append({"role": "assistant", "content": content})
            else:
                fn_name = response.choices[0].message.tool_calls[0].function.name
                fn_args = response.choices[0].message.tool_calls[0].function.arguments

                def confirm_send_fn():
                    send_email(
                                sender_email=args["FromEmail"],
                                sender_authorization_code=AUTHORIZATION_CODE,
                                recipient_email=args["Recipients"],
                                subject=args["Subject"],
                                body=args["Body"],
                            )
                    st.success("邮件已发送")
                    st.session_state.messages.append({"role": "assistant", "content": "邮件已发送,还需要什么帮助吗?"})
                    # reflash sidebar
                    st.sidebar.json(st.session_state)
                    st.sidebar.write(response)
                    
                
                def cancel_send_fn():    
                    st.warning("邮件发送已取消")
                    st.session_state.messages.append({"role": "assistant", "content": "邮件已取消,还需要什么帮助吗?"})
                    # reflash sidebar
                    st.sidebar.json(st.session_state)
                    st.sidebar.write(response)
                    
                if fn_name == "send_email":
                    args = json.loads(fn_args)
                    st.markdown("邮件内容如下:")
                    st.markdown(f"发件人: {args['FromEmail']}")
                    st.markdown(f"收件人: {args['Recipients']}")
                    st.markdown(f"主题: {args['Subject']}")
                    st.markdown(f"内容: {args['Body']}")

                    col1, col2 = st.columns(2)
                    with col1:
                        st.button(
                            label="✅确认发送邮件", 
                            on_click=confirm_send_fn)
                    with col2:
                        st.button(
                            label="❌取消发送邮件",
                            on_click=cancel_send_fn
                        )

if __name__ == "__main__":
    main()

streamlit run app.py打开

下面是打电话的代码

import os
from dotenv import load_dotenv

import json
from openai import OpenAI
from twilio.rest import Client

GPT_MODEL = "gpt-4o-mini"

load_dotenv()
# 获取环境变量
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
TWILIO_ACCOUNT_SID = os.getenv("TWILIO_ACCOUNT_SID")
TWILIO_AUTH_TOKEN = os.getenv("TWILIO_AUTH_TOKEN")
TWILIO_PHONE_NUMBER = os.getenv("TWILIO_PHONE_NUMBER")

client = OpenAI(api_key=OPENAI_API_KEY)
twilio_client = Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN)

tools = [
    {
        "type": "function",
        "function": {
            "name": "make_call",
            "description": "Make a phone call to the specified phone number with the given message",
            "parameters":{
                "type": "object",
                "properties": {
                    "ToPhoneNumber": {
                        "type": "string",
                        "description": "The phone number to call, eg., +1234567890",
                    },
                    "Message": {
                        "type": "string",
                        "description": "The message to be spoken during the call",
                    }
                },
                "required": ["ToPhoneNumber", "Message"],
            },
        }
    }
]

def chat_completion_request(messages, tools=None, tool_choice=None, model=GPT_MODEL):
    try:
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            tools=tools,
            tool_choice=tool_choice,
        )
        return response
    except Exception as e:
        print("Unable to generate ChatCompletion response")
        print(f"Exception: {e}")
        return e

def make_call(to_phone_number, message):
    call = twilio_client.calls.create(
        to=to_phone_number,
        from_=TWILIO_PHONE_NUMBER,
        twiml=f'<Response><Say>{message}</Say></Response>'
    )
    return call.sid

def main():
    messages = []
    
    while True:
        msg = input("【You】: ")
        messages.append({"role": "user", "content": msg})
        response = chat_completion_request(
            messages=messages,
            tools=tools
        )
        if content := response.choices[0].message.content:
            print(f"【AI】: {content}")
            messages.append({"role": "assistant", "content": content})
        else:
            fn_name = response.choices[0].message.tool_calls[0].function.name
            fn_args = response.choices[0].message.tool_calls[0].function.arguments
        
            if fn_name == "make_call":
                try:
                    args = json.loads(fn_args)
                    # 返回将要拨打的电话内容给用户确认
                    print("【AI】: 电话内容如下:")
                    print(f"拨打号码: {args['ToPhoneNumber']}")
                    print(f"内容: {args['Message']}")
                    
                    confirm = input("AI: 确认拨打电话吗? (yes/no): ").strip().lower()
                    if confirm == "yes":
                        call_sid = make_call(
                            to_phone_number=args["ToPhoneNumber"],
                            message=args["Message"]
                        )
                        print(f"电话已拨打,SID: {call_sid},还需要什么帮助吗?")
                        messages.append({"role": "assistant", "content": f"电话已拨打,SID: {call_sid},还需要什么帮助吗?"})
                    else:
                        print("电话拨打已取消,还需要什么帮助吗?")
                        messages.append({"role": "assistant", "content": "电话拨打已取消,还需要什么帮助吗?"})
                except Exception as e:
                    print(f"拨打电话时出错:{e}")
                    messages.append({"role": "assistant", "content": "抱歉,功能异常!"})    

if __name__ == "__main__":
    main()


代码来源https://github.com/echonoshy/cgft-llm/blob/master/function-calling/app.py

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值