mistpe commited on
Commit
f4971d9
1 Parent(s): 8a6ab36

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +9 -289
app.py CHANGED
@@ -1,18 +1,12 @@
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
  from openai import OpenAI
10
  from dotenv import load_dotenv
11
- from duckduckgo_search import DDGS
12
- import requests
13
- import smtplib
14
- from email.mime.text import MIMEText
15
- from email.mime.multipart import MIMEMultipart
16
 
17
  # 加载环境变量
18
  load_dotenv()
@@ -23,138 +17,36 @@ app = Flask(__name__)
23
  TOKEN = os.getenv('TOKEN')
24
  API_KEY = os.getenv("API_KEY")
25
  BASE_URL = os.getenv("OPENAI_BASE_URL")
26
- emailkey = os.getenv("EMAIL_KEY")
27
  client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
28
 
29
  # 定义可用的模型列表
30
  AVAILABLE_MODELS = {
31
- 'gpt-3.5-turbo': 'GPT-3.5 Turbo',
32
- 'gpt-4o': 'GPT-4o',
33
- 'gpt-4o-mini': 'GPT-4o-mini',
34
  }
35
 
36
  # 存储用户会话信息
37
  user_sessions = {}
38
 
39
- # 定义函数
40
- def search_duckduckgo(keywords):
41
- search_term = " ".join(keywords)
42
- with DDGS() as ddgs:
43
- results = list(ddgs.text(keywords=search_term, region="cn-zh", safesearch="on", max_results=5))
44
- return [{"title": result['title'], "body": result['body'].replace('\n', ' ')} for result in results]
45
-
46
- def search_papers(query):
47
- url = f"https://api.crossref.org/works?query={query}"
48
- response = requests.get(url)
49
- if response.status_code == 200:
50
- data = response.json()
51
- papers = data['message']['items']
52
- processed_papers = []
53
- for paper in papers:
54
- processed_paper = {
55
- "标题": paper.get('title', [''])[0],
56
- "作者": ", ".join([f"{author.get('given', '')} {author.get('family', '')}" for author in paper.get('author', [])]),
57
- "DOI": paper.get('DOI', ''),
58
- "摘要": paper.get('abstract', '').replace('<p>', '').replace('</p>', '').replace('<italic>', '*').replace('</italic>', '*')
59
- }
60
- processed_papers.append(processed_paper)
61
- return processed_papers
62
- else:
63
- return []
64
-
65
- def send_email(to, subject, content):
66
- try:
67
- with smtplib.SMTP('106.15.184.28', 8025) as smtp:
68
- smtp.login("jwt", emailkey)
69
- message = MIMEMultipart()
70
- message['From'] = "Me <[email protected]>"
71
- message['To'] = to
72
- message['Subject'] = subject
73
- message.attach(MIMEText(content, 'html'))
74
- smtp.sendmail("[email protected]", to, message.as_string())
75
- return True
76
- except Exception as e:
77
- print(f"发送邮件时出错: {str(e)}")
78
- return False
79
-
80
- # 定义函数列表
81
- FUNCTIONS = [
82
- {
83
- "name": "search_duckduckgo",
84
- "description": "使用DuckDuckGo搜索引擎查询信息。可以搜索最新新闻、文章、博客等内容。",
85
- "parameters": {
86
- "type": "object",
87
- "properties": {
88
- "keywords": {
89
- "type": "array",
90
- "items": {"type": "string"},
91
- "description": "搜索的关键词列表。例如:['Python', '机器学习', '最新进展']。"
92
- }
93
- },
94
- "required": ["keywords"]
95
- }
96
- },
97
- {
98
- "name": "search_papers",
99
- "description": "使用Crossref API搜索学术论文。",
100
- "parameters": {
101
- "type": "object",
102
- "properties": {
103
- "query": {
104
- "type": "string",
105
- "description": "搜索查询字符串。例如:'climate change'。"
106
- }
107
- },
108
- "required": ["query"]
109
- }
110
- },
111
- {
112
- "name": "send_email",
113
- "description": "发送电子邮件。",
114
- "parameters": {
115
- "type": "object",
116
- "properties": {
117
- "to": {
118
- "type": "string",
119
- "description": "收件人邮箱地址"
120
- },
121
- "subject": {
122
- "type": "string",
123
- "description": "邮件主题"
124
- },
125
- "content": {
126
- "type": "string",
127
- "description": "邮件内容"
128
- }
129
- },
130
- "required": ["to", "subject", "content"]
131
- }
132
- }
133
- ]
134
-
135
  def verify_wechat(request):
136
- # 获取微信服务器发送过来的参数
137
  data = request.args
138
  signature = data.get('signature')
139
  timestamp = data.get('timestamp')
140
  nonce = data.get('nonce')
141
  echostr = data.get('echostr')
142
 
143
- # 对参数进行字典排序,拼接字符串
144
  temp = [timestamp, nonce, TOKEN]
145
  temp.sort()
146
  temp = ''.join(temp)
147
 
148
- # 加密
149
  if (hashlib.sha1(temp.encode('utf8')).hexdigest() == signature):
150
  return echostr
151
  else:
152
  return 'error', 403
153
 
154
  def getUserMessageContentFromXML(xml_content):
155
- # 解析XML字符串
156
  root = ET.fromstring(xml_content)
157
- # 提取数据
158
  content = root.find('Content').text
159
  from_user_name = root.find('FromUserName').text
160
  to_user_name = root.find('ToUserName').text
@@ -187,179 +79,11 @@ def get_openai_response(messages, model="gpt-4o-mini", functions=None, function_
187
  print(f"调用OpenAI API时出错: {str(e)}")
188
  return None
189
 
190
- def process_function_call(function_name, function_args):
191
- if function_name == "search_duckduckgo":
192
- keywords = function_args.get('keywords', [])
193
- if not keywords:
194
- return "搜索关键词为空,无法执行搜索。"
195
- return search_duckduckgo(keywords)
196
- elif function_name == "search_papers":
197
- query = function_args.get('query', '')
198
- if not query:
199
- return "搜索查询为空,无法执行论文搜索。"
200
- return search_papers(query)
201
- elif function_name == "send_email":
202
- to = function_args.get('to', '')
203
- subject = function_args.get('subject', '')
204
- content = function_args.get('content', '')
205
- if not to or not subject or not content:
206
- return "邮件信息不完整,无法发送邮件。"
207
- success = send_email(to, subject, content)
208
- return {
209
- "success": success,
210
- "message": "邮件发送成功" if success else "邮件发送失败",
211
- "to": to,
212
- "subject": subject,
213
- "content": content,
214
- "is_email": True
215
- }
216
- else:
217
- return "未知的函数调用。"
218
-
219
  def split_message(message, max_length=500):
220
  return [message[i:i+max_length] for i in range(0, len(message), max_length)]
221
 
222
- # @app.route('/api/wx', methods=['GET', 'POST'])
223
- # def wechatai():
224
- # if request.method == 'GET':
225
- # return verify_wechat(request)
226
- # else:
227
- # # 处理POST请求
228
- # xml_str = request.data
229
- # if not xml_str:
230
- # return ""
231
-
232
- # user_message_content, from_user_name, to_user_name = getUserMessageContentFromXML(xml_str)
233
-
234
- # if from_user_name not in user_sessions:
235
- # user_sessions[from_user_name] = {'model': 'gpt-4o-mini', 'messages': [], 'pending_response': []}
236
-
237
- # session = user_sessions[from_user_name]
238
-
239
- # if user_message_content.lower() == '/models':
240
- # response_content = f"可用的模型列表:\n{list_available_models()}\n\n使用 /model 模型名称 来切换模型"
241
- # return generate_response_xml(from_user_name, to_user_name, response_content)
242
- # elif user_message_content.lower().startswith('/model'):
243
- # model = user_message_content.split(' ')[1]
244
- # if model in AVAILABLE_MODELS:
245
- # session['model'] = model
246
- # response_content = f'模型已切换为 {AVAILABLE_MODELS[model]}'
247
- # else:
248
- # response_content = f'无效的模型名称。可用的模型有:\n{list_available_models()}'
249
- # return generate_response_xml(from_user_name, to_user_name, response_content)
250
- # elif user_message_content.lower() == '继续':
251
- # if session['pending_response']:
252
- # response_content = session['pending_response'].pop(0)
253
- # if session['pending_response']:
254
- # response_content += '\n\n回复"继续"获取下一部分。'
255
- # else:
256
- # response_content += '\n\n回复结束。'
257
- # else:
258
- # response_content = "没有待发送的消息。"
259
- # return generate_response_xml(from_user_name, to_user_name, response_content)
260
-
261
- # session['messages'].append({"role": "user", "content": user_message_content})
262
-
263
- # # 调用OpenAI API
264
- # ai_response = get_openai_response(session['messages'], model=session['model'], functions=FUNCTIONS, function_call="auto")
265
-
266
- # if ai_response.function_call:
267
- # function_name = ai_response.function_call.name
268
- # function_args = json.loads(ai_response.function_call.arguments)
269
- # function_result = process_function_call(function_name, function_args)
270
-
271
- # session['messages'].append(ai_response.model_dump())
272
- # session['messages'].append({
273
- # "role": "function",
274
- # "name": function_name,
275
- # "content": json.dumps(function_result, ensure_ascii=False)
276
- # })
277
-
278
- # final_response = get_openai_response(session['messages'], model=session['model'])
279
- # response_content = final_response.content
280
- # else:
281
- # response_content = ai_response.content
282
-
283
- # session['messages'].append({"role": "assistant", "content": response_content})
284
-
285
- # # 处理长消息
286
- # response_parts = split_message(response_content)
287
- # if len(response_parts) > 1:
288
- # session['pending_response'] = response_parts[1:]
289
- # response_content = response_parts[0] + '\n\n回复"继续"获取下一部分。'
290
-
291
- # return generate_response_xml(from_user_name, to_user_name, response_content)
292
- # @app.route('/api/wx', methods=['GET', 'POST'])
293
- # def wechatai():
294
- # if request.method == 'GET':
295
- # return verify_wechat(request)
296
- # else:
297
- # # 处理POST请求
298
- # xml_str = request.data
299
- # if not xml_str:
300
- # return ""
301
-
302
- # user_message_content, from_user_name, to_user_name = getUserMessageContentFromXML(xml_str)
303
-
304
- # if from_user_name not in user_sessions:
305
- # user_sessions[from_user_name] = {'model': 'gpt-4o-mini', 'messages': [], 'pending_response': []}
306
-
307
- # session = user_sessions[from_user_name]
308
-
309
- # if user_message_content.lower() == '/models':
310
- # response_content = f"可用的模型列表:\n{list_available_models()}\n\n使用 /model 模型名称 来切换模型"
311
- # return generate_response_xml(from_user_name, to_user_name, response_content)
312
- # elif user_message_content.lower().startswith('/model'):
313
- # model = user_message_content.split(' ')[1]
314
- # if model in AVAILABLE_MODELS:
315
- # session['model'] = model
316
- # response_content = f'模型已切换为 {AVAILABLE_MODELS[model]}'
317
- # else:
318
- # response_content = f'无效的模型名称。可用的模型有:\n{list_available_models()}'
319
- # return generate_response_xml(from_user_name, to_user_name, response_content)
320
- # elif user_message_content.lower() == '继续':
321
- # if session['pending_response']:
322
- # response_content = session['pending_response'].pop(0)
323
- # if session['pending_response']:
324
- # response_content += '\n\n回复"继续"获取下一部分。'
325
- # else:
326
- # response_content += '\n\n回复结束。'
327
- # else:
328
- # response_content = "没有待发送的消息。"
329
- # return generate_response_xml(from_user_name, to_user_name, response_content)
330
-
331
- # session['messages'].append({"role": "user", "content": user_message_content})
332
-
333
- # # 调用OpenAI API
334
- # ai_response = get_openai_response(session['messages'], model=session['model'], functions=FUNCTIONS, function_call="auto")
335
-
336
- # if ai_response.function_call:
337
- # function_name = ai_response.function_call.name
338
- # function_args = json.loads(ai_response.function_call.arguments)
339
- # function_result = process_function_call(function_name, function_args)
340
-
341
- # session['messages'].append(ai_response.model_dump())
342
- # session['messages'].append({
343
- # "role": "function",
344
- # "name": function_name,
345
- # "content": json.dumps(function_result, ensure_ascii=False)
346
- # })
347
-
348
- # # 再次调用OpenAI API,将函数执行结果作为上下文
349
- # final_response = get_openai_response(session['messages'], model=session['model'])
350
- # response_content = final_response.content
351
- # else:
352
- # response_content = ai_response.content
353
-
354
- # session['messages'].append({"role": "assistant", "content": response_content})
355
-
356
- # # 处理长消息
357
- # response_parts = split_message(response_content)
358
- # if len(response_parts) > 1:
359
- # session['pending_response'] = response_parts[1:]
360
- # response_content = response_parts[0] + '\n\n回复"继续"获取下一部分。'
361
-
362
- # return generate_response_xml(from_user_name, to_user_name, response_content)
363
 
364
  @app.route('/api/wx', methods=['GET', 'POST'])
365
  def wechatai():
@@ -377,7 +101,6 @@ def wechatai():
377
 
378
  session = user_sessions[from_user_name]
379
 
380
- # 处理特殊命令
381
  if user_message_content.lower() == '/models':
382
  response_content = f"可用的模型列表:\n{list_available_models()}\n\n使用 /model 模型名称 来切换模型"
383
  return generate_response_xml(from_user_name, to_user_name, response_content)
@@ -451,9 +174,6 @@ def wechatai():
451
  response_content = response_parts[0] + '\n\n回复"继续"获取下一部分。'
452
 
453
  return generate_response_xml(from_user_name, to_user_name, response_content)
454
-
455
- def list_available_models():
456
- return "\n".join([f"{key}: {value}" for key, value in AVAILABLE_MODELS.items()])
457
 
458
  if __name__ == '__main__':
459
  app.run(host='0.0.0.0', port=7860, debug=True)
 
1
+ import os
2
+ import json
 
3
  import hashlib
4
  import time
5
  import xml.etree.ElementTree as ET
6
+ from flask import Flask, request, make_response
 
7
  from openai import OpenAI
8
  from dotenv import load_dotenv
9
+ from functions import FUNCTIONS, FUNCTIONS_GROUP_1, FUNCTIONS_GROUP_2, process_function_call
 
 
 
 
10
 
11
  # 加载环境变量
12
  load_dotenv()
 
17
  TOKEN = os.getenv('TOKEN')
18
  API_KEY = os.getenv("API_KEY")
19
  BASE_URL = os.getenv("OPENAI_BASE_URL")
 
20
  client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
21
 
22
  # 定义可用的模型列表
23
  AVAILABLE_MODELS = {
24
+ 'gpt-4o-mini': 'gpt-4o-mini',
25
+ 'gpt-4o-mini': 'gpt-4o-mini',
26
+ 'gpt-4o-mini': 'gpt-4o-mini',
27
  }
28
 
29
  # 存储用户会话信息
30
  user_sessions = {}
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  def verify_wechat(request):
 
33
  data = request.args
34
  signature = data.get('signature')
35
  timestamp = data.get('timestamp')
36
  nonce = data.get('nonce')
37
  echostr = data.get('echostr')
38
 
 
39
  temp = [timestamp, nonce, TOKEN]
40
  temp.sort()
41
  temp = ''.join(temp)
42
 
 
43
  if (hashlib.sha1(temp.encode('utf8')).hexdigest() == signature):
44
  return echostr
45
  else:
46
  return 'error', 403
47
 
48
  def getUserMessageContentFromXML(xml_content):
 
49
  root = ET.fromstring(xml_content)
 
50
  content = root.find('Content').text
51
  from_user_name = root.find('FromUserName').text
52
  to_user_name = root.find('ToUserName').text
 
79
  print(f"调用OpenAI API时出错: {str(e)}")
80
  return None
81
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  def split_message(message, max_length=500):
83
  return [message[i:i+max_length] for i in range(0, len(message), max_length)]
84
 
85
+ def list_available_models():
86
+ return "\n".join([f"{key}: {value}" for key, value in AVAILABLE_MODELS.items()])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  @app.route('/api/wx', methods=['GET', 'POST'])
89
  def wechatai():
 
101
 
102
  session = user_sessions[from_user_name]
103
 
 
104
  if user_message_content.lower() == '/models':
105
  response_content = f"可用的模型列表:\n{list_available_models()}\n\n使用 /model 模型名称 来切换模型"
106
  return generate_response_xml(from_user_name, to_user_name, response_content)
 
174
  response_content = response_parts[0] + '\n\n回复"继续"获取下一部分。'
175
 
176
  return generate_response_xml(from_user_name, to_user_name, response_content)
 
 
 
177
 
178
  if __name__ == '__main__':
179
  app.run(host='0.0.0.0', port=7860, debug=True)