Files
AI0814_jiaoan_public/w1_d3/9.py
T
2026-09-23 21:27:55 +08:00

126 lines
3.9 KiB
Python

import smtplib
from email.mime.text import MIMEText
from openai import OpenAI
import os
import json
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(
api_key=os.environ.get("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com",
)
# 1. 定义工具描述
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string", "description": "城市名,如杭州"},
},
"required": ["location"],
},
},
},
{
"type": "function",
"function": {
"name": "send_email_qq",
"description": "使用QQ邮箱SMTP发送纯文本邮件",
"parameters": {
"type": "object",
"properties": {
"text": {"type": "string", "description": "邮件正文内容"},
"subject": {"type": "string", "description": "邮件主题"},
},
"required": ["text", "subject"],
},
},
}
]
# 工具实现
def get_weather(location: str) -> str:
return f"{location}的天气为 8℃"
def send_email_qq(text, subject):
mail_host = "smtp.qq.com"
mail_port = 465
mail_user = "wolin105@qq.com"
mail_pass = "pingnllumhbzbceg" # QQ邮箱授权码
sender = mail_user
receivers = "jzk.jie@qq.com"
message = MIMEText(text, 'plain', 'utf-8')
message["From"] = sender
message["To"] = receivers
message["Subject"] = subject
try:
smtp = smtplib.SMTP_SSL(mail_host, mail_port)
smtp.login(mail_user, mail_pass)
smtp.sendmail(sender, [receivers], message.as_string())
smtp.quit()
print("邮件发送成功")
return "邮件发送成功"
except Exception as e:
err_msg = f"邮件发送失败: {e}"
print(err_msg)
return err_msg
tools_map = {'get_weather': get_weather, 'send_email_qq': send_email_qq}
def execute_tool_calls(tool_calls, tools_map: dict) -> list:
"""执行模型返回的tool_calls,返回tool角色消息字典列表"""
tool_messages = []
for tool_call in tool_calls:
func_name = tool_call.function.name
print(f"\n调用工具:{func_name}")
args = json.loads(tool_call.function.arguments)
print(f"参数:{args}")
func = tools_map[func_name]
result = func(**args)
tool_msg = {
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
}
tool_messages.append(tool_msg)
return tool_messages
if __name__ == "__main__":
messages = [
{"role": "user", "content": "帮我发一个邮件,邮件内容是描述今天学了functioncalling的心得,主题是学习心得,只输出文本即可"}
]
# ✅ while循环自动多轮工具调用,直到模型不再返回tool_calls
while True:
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=messages,
tools=tools,
)
assistant_msg = response.choices[0].message
print("\n=====模型返回assistant消息对象=====")
print(assistant_msg)
# ✅ 关键修复:转成字典,再追加到messages,不能直接append对象!
messages.append(assistant_msg.model_dump())
# 判断是否还有工具调用
if not assistant_msg.tool_calls:
# 没有工具调用,拿到最终回答,退出循环
print("\n模型最终回复:", assistant_msg.content)
break
# 执行工具,拿到tool消息
tool_msg_list = execute_tool_calls(assistant_msg.tool_calls, tools_map)
messages.extend(tool_msg_list)