mistpe commited on
Commit
3cfb69c
1 Parent(s): eec6c64

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +209 -0
app.py ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ from flask import Flask, request, make_response
4
+ import hashlib
5
+ import time
6
+ import xml.etree.ElementTree as ET
7
+ import os
8
+ import json
9
+ import smtplib
10
+ from email.mime.text import MIMEText
11
+ from email.mime.multipart import MIMEMultipart
12
+ from openai import OpenAI
13
+ from dotenv import load_dotenv
14
+
15
+ # 加载环境变量
16
+ load_dotenv()
17
+
18
+ app = Flask(__name__)
19
+
20
+ # 配置
21
+ TOKEN = os.getenv('TOKEN')
22
+ API_KEY = os.getenv("OPENAI_API_KEY")
23
+ BASE_URL = os.getenv("OPENAI_BASE_URL")
24
+ EMAIL_KEY = os.getenv("EMAIL_KEY")
25
+ client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
26
+
27
+ # 存储用户会话信息
28
+ user_sessions = {}
29
+
30
+ # 定义发送邮件的函数
31
+ FUNCTIONS = [
32
+ {
33
+ "name": "send_email",
34
+ "description": "发送电子邮件。",
35
+ "parameters": {
36
+ "type": "object",
37
+ "properties": {
38
+ "to": {
39
+ "type": "string",
40
+ "description": "收件人邮箱地址"
41
+ },
42
+ "subject": {
43
+ "type": "string",
44
+ "description": "邮件主题"
45
+ },
46
+ "content": {
47
+ "type": "string",
48
+ "description": "邮件内容"
49
+ }
50
+ },
51
+ "required": ["to", "subject", "content"]
52
+ }
53
+ }
54
+ ]
55
+
56
+ def verify_wechat(request):
57
+ # 获取微信服务器发送过来的参数
58
+ data = request.args
59
+ signature = data.get('signature')
60
+ timestamp = data.get('timestamp')
61
+ nonce = data.get('nonce')
62
+ echostr = data.get('echostr')
63
+
64
+ # 对参数进行字典排序,拼接字符串
65
+ temp = [timestamp, nonce, TOKEN]
66
+ temp.sort()
67
+ temp = ''.join(temp)
68
+
69
+ # 加密
70
+ if (hashlib.sha1(temp.encode('utf8')).hexdigest() == signature):
71
+ return echostr
72
+ else:
73
+ return 'error', 403
74
+
75
+ def getUserMessageContentFromXML(xml_content):
76
+ # 解析XML字符串
77
+ root = ET.fromstring(xml_content)
78
+ # 提取数据
79
+ content = root.find('Content').text
80
+ from_user_name = root.find('FromUserName').text
81
+ to_user_name = root.find('ToUserName').text
82
+ return content, from_user_name, to_user_name
83
+
84
+ def generate_response_xml(from_user_name, to_user_name, output_content):
85
+ output_xml = '''
86
+ <xml>
87
+ <ToUserName><![CDATA[%s]]></ToUserName>
88
+ <FromUserName><![CDATA[%s]]></FromUserName>
89
+ <CreateTime>%s</CreateTime>
90
+ <MsgType><![CDATA[text]]></MsgType>
91
+ <Content><![CDATA[%s]]></Content>
92
+ </xml>'''
93
+
94
+ response = make_response(output_xml % (from_user_name, to_user_name, str(int(time.time())), output_content))
95
+ response.content_type = 'application/xml'
96
+ return response
97
+
98
+ def get_openai_response(messages, functions=None, function_call=None):
99
+ try:
100
+ response = client.chat.completions.create(
101
+ model="gpt-4o-mini",
102
+ messages=messages,
103
+ functions=functions,
104
+ function_call=function_call
105
+ )
106
+ return response.choices[0].message
107
+ except Exception as e:
108
+ print(f"调用OpenAI API时出错: {str(e)}")
109
+ return None
110
+
111
+ def send_email(to, subject, content):
112
+ try:
113
+ with smtplib.SMTP('106.15.184.28', 8025) as smtp:
114
+ smtp.login("jwt", EMAIL_KEY)
115
+ message = MIMEMultipart()
116
+ message['From'] = "Me <[email protected]>"
117
+ message['To'] = to
118
+ message['Subject'] = subject
119
+ message.attach(MIMEText(content, 'html'))
120
+ smtp.sendmail("[email protected]", to, message.as_string())
121
+ return True
122
+ except Exception as e:
123
+ print(f"发送邮件时出错: {str(e)}")
124
+ return False
125
+
126
+ def process_function_call(response_message):
127
+ function_name = response_message.function_call.name
128
+ function_args = json.loads(response_message.function_call.arguments)
129
+ if function_name == "send_email":
130
+ to = function_args.get('to', '')
131
+ subject = function_args.get('subject', '')
132
+ content = function_args.get('content', '')
133
+ if not to or not subject or not content:
134
+ return None
135
+ success = send_email(to, subject, content)
136
+ return {
137
+ "success": success,
138
+ "to": to,
139
+ "subject": subject,
140
+ "content": content
141
+ }
142
+ else:
143
+ return None
144
+
145
+ def split_message(message, max_length=500):
146
+ return [message[i:i+max_length] for i in range(0, len(message), max_length)]
147
+
148
+ @app.route('/api/wx', methods=['GET', 'POST'])
149
+ def wechatai():
150
+ if request.method == 'GET':
151
+ return verify_wechat(request)
152
+ else:
153
+ # 处理POST请求
154
+ print("user request data: ", request.data)
155
+ user_message_content, from_user_name, to_user_name = getUserMessageContentFromXML(request.data)
156
+ print("user message content: ", user_message_content)
157
+
158
+ if user_message_content.lower() == '继续':
159
+ if from_user_name in user_sessions and user_sessions[from_user_name]['pending_response']:
160
+ response_content = user_sessions[from_user_name]['pending_response'].pop(0)
161
+ if user_sessions[from_user_name]['pending_response']:
162
+ response_content += '\n\n回复"继续"获取下一部分。'
163
+ else:
164
+ response_content += '\n\n回复结束。'
165
+ else:
166
+ response_content = "没有待发送的消息。"
167
+ else:
168
+ if from_user_name not in user_sessions:
169
+ user_sessions[from_user_name] = {'messages': [], 'pending_response': [], 'email_sent': False}
170
+
171
+ session = user_sessions[from_user_name]
172
+ session['messages'].append({"role": "user", "content": user_message_content})
173
+
174
+ # 检查是否需要调用函数
175
+ decision_response = get_openai_response(session['messages'], functions=FUNCTIONS, function_call="auto")
176
+
177
+ if decision_response.function_call and not session['email_sent']:
178
+ # 处理函数调用
179
+ function_result = process_function_call(decision_response)
180
+ if function_result:
181
+ session['email_sent'] = True
182
+ if function_result['success']:
183
+ response_content = f"邮件已成功发送到 {function_result['to']}。\n\n主题:{function_result['subject']}\n\n内容:\n{function_result['content']}"
184
+ else:
185
+ response_content = "邮件发送失败,请稍后再试。"
186
+ else:
187
+ response_content = "无法处理该请求,请重试。"
188
+ else:
189
+ # 正常的对话响应
190
+ gpt_response = get_openai_response(session['messages'])
191
+ response_content = gpt_response.content if gpt_response else "抱歉,我遇到了一些问题,无法回答您的问题。"
192
+
193
+ session['messages'].append({"role": "assistant", "content": response_content})
194
+
195
+ # 重置email_sent标志,为下一次消息做准备
196
+ session['email_sent'] = False
197
+
198
+ response_parts = split_message(response_content)
199
+
200
+ if len(response_parts) > 1:
201
+ response_content = response_parts[0] + '\n\n回复"继续"获取下一部分。'
202
+ session['pending_response'] = response_parts[1:]
203
+ else:
204
+ response_content = response_parts[0]
205
+
206
+ return generate_response_xml(from_user_name, to_user_name, response_content)
207
+
208
+ if __name__ == '__main__':
209
+ app.run(host='0.0.0.0', port=7860, debug=True)