mistpe commited on
Commit
b8ec0c8
1 Parent(s): 13d316e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +338 -0
app.py ADDED
@@ -0,0 +1,338 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Hugging Face's logo
2
+ Hugging Face
3
+ Search models, datasets, users...
4
+ Models
5
+ Datasets
6
+ Spaces
7
+ Posts
8
+ Docs
9
+ Pricing
10
+
11
+
12
+
13
+ Spaces:
14
+
15
+ mistpe
16
+ /
17
+ functioncall1
18
+
19
+ private
20
+
21
+ App
22
+ Files
23
+ Community
24
+ Settings
25
+ functioncall1
26
+ /
27
+ app.py
28
+
29
+ mistpe's picture
30
+ mistpe
31
+ Update app.py
32
+ 0bd5c33
33
+ verified
34
+ 8 minutes ago
35
+ raw
36
+
37
+ Copy download link
38
+ history
39
+ blame
40
+ edit
41
+ delete
42
+
43
+ 11.9 kB
44
+ import os
45
+ import json
46
+ import requests
47
+ import smtplib
48
+ from email.mime.text import MIMEText
49
+ from email.mime.multipart import MIMEMultipart
50
+ from flask import Flask, request, jsonify, send_from_directory
51
+ from openai import OpenAI
52
+ from bs4 import BeautifulSoup
53
+ import random
54
+ from functions import FUNCTIONS_GROUP_1, FUNCTIONS_GROUP_2, get_function_descriptions
55
+
56
+ app = Flask(__name__)
57
+ API_KEY = os.getenv("OPENAI_API_KEY")
58
+ BASE_URL = os.getenv("OPENAI_BASE_URL")
59
+ emailkey = os.getenv("EMAIL_KEY")
60
+ client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
61
+
62
+ def search_duckduckgo(keywords):
63
+ search_term = " ".join(keywords)
64
+ url = "https://www.bing.com/search"
65
+
66
+ user_agents = [
67
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
68
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
69
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15",
70
+ ]
71
+ headers = {
72
+ "User-Agent": random.choice(user_agents)
73
+ }
74
+
75
+ params = {
76
+ "q": search_term,
77
+ "setlang": "zh-CN"
78
+ }
79
+
80
+ response = requests.get(url, params=params, headers=headers)
81
+
82
+ results = []
83
+ if response.status_code == 200:
84
+ soup = BeautifulSoup(response.text, 'html.parser')
85
+ for item in soup.select('.b_algo')[:5]: # Limit to 5 results
86
+ title_elem = item.select_one('h2 a')
87
+ snippet_elem = item.select_one('.b_caption p')
88
+
89
+ if title_elem and snippet_elem:
90
+ results.append({
91
+ "title": title_elem.text,
92
+ "href": title_elem['href'],
93
+ "body": snippet_elem.text
94
+ })
95
+ return results
96
+
97
+ def search_papers(query):
98
+ url = f"https://api.crossref.org/works?query={query}"
99
+ response = requests.get(url)
100
+ if response.status_code == 200:
101
+ data = response.json()
102
+ papers = data['message']['items']
103
+ processed_papers = []
104
+ for paper in papers:
105
+ processed_paper = {
106
+ "标题": paper.get('title', [''])[0],
107
+ "作者": ", ".join([f"{author.get('given', '')} {author.get('family', '')}" for author in paper.get('author', [])]),
108
+ "DOI": paper.get('DOI', ''),
109
+ "ISBN": ", ".join(paper.get('ISBN', [])),
110
+ "摘要": paper.get('abstract', '').replace('<p>', '').replace('</p>', '').replace('<italic>', '').replace('</italic>', '')
111
+ }
112
+ processed_papers.append(processed_paper)
113
+ return processed_papers
114
+ else:
115
+ return []
116
+
117
+ def send_email(to, subject, content):
118
+ try:
119
+ with smtplib.SMTP('106.15.184.28', 8025) as smtp:
120
+ smtp.login("jwt", emailkey)
121
+ message = MIMEMultipart()
122
+ message['From'] = "Me <[email protected]>"
123
+ message['To'] = to
124
+ message['Subject'] = subject
125
+ message.attach(MIMEText(content, 'html'))
126
+ smtp.sendmail("[email protected]", to, message.as_string())
127
+ return True
128
+ except Exception as e:
129
+ print(f"发送邮件时出错: {str(e)}")
130
+ return False
131
+
132
+ def get_openai_response(messages, model="gpt-4o-mini", functions=None, function_call=None):
133
+ try:
134
+ response = client.chat.completions.create(
135
+ model=model,
136
+ messages=messages,
137
+ functions=functions,
138
+ function_call=function_call
139
+ )
140
+ return response.choices[0].message
141
+ except Exception as e:
142
+ print(f"调用OpenAI API时出错: {str(e)}")
143
+ return None
144
+
145
+ def process_function_call(function_name, function_args):
146
+ if function_name == "search_duckduckgo":
147
+ keywords = function_args.get('keywords', [])
148
+ if not keywords:
149
+ return "搜索关键词为空,无法执行搜索。"
150
+ return search_duckduckgo(keywords)
151
+ elif function_name == "search_papers":
152
+ query = function_args.get('query', '')
153
+ if not query:
154
+ return "搜索查询为空,无法执行论文搜索。"
155
+ return search_papers(query)
156
+ elif function_name == "send_email":
157
+ to = function_args.get('to', '')
158
+ subject = function_args.get('subject', '')
159
+ content = function_args.get('content', '')
160
+ if not to or not subject or not content:
161
+ return "邮件信息不完整,无法发送邮件。"
162
+ success = send_email(to, subject, content)
163
+ return {
164
+ "success": success,
165
+ "message": "邮件发送成功" if success else "邮件发送失败",
166
+ "to": to,
167
+ "subject": subject,
168
+ "content": content,
169
+ "is_email": True
170
+ }
171
+ else:
172
+ return "未知的函数调用。"
173
+
174
+ @app.route('/')
175
+ def index():
176
+ return send_from_directory('.', 'index.html')
177
+
178
+ @app.route('/chat', methods=['POST'])
179
+ def chat():
180
+ data = request.json
181
+ question = data['question']
182
+ history = data.get('history', [])
183
+ messages = history + [{"role": "user", "content": question}]
184
+
185
+ status_log = []
186
+
187
+ # 次级模型1: 处理搜索相关函数
188
+ status_log.append("次级模型1:正在判断是否需要选调第一组函数")
189
+ sub_model_1_response = get_openai_response(messages, model="gpt-4o-mini", functions=FUNCTIONS_GROUP_1, function_call="auto")
190
+
191
+ # 次级模型2: 处理邮件发送相关函数
192
+ status_log.append("次级模型2:正在判断是否需要选调第二组函数")
193
+ sub_model_2_response = get_openai_response(messages, model="gpt-4o-mini", functions=FUNCTIONS_GROUP_2, function_call="auto")
194
+
195
+ function_call_1 = sub_model_1_response.function_call if sub_model_1_response and sub_model_1_response.function_call else None
196
+ function_call_2 = sub_model_2_response.function_call if sub_model_2_response and sub_model_2_response.function_call else None
197
+
198
+ if not function_call_1:
199
+ status_log.append("次级模型1:判断不需要选调第一组函数")
200
+ if not function_call_2:
201
+ status_log.append("次级模型2:判断不需要选调第二组函数")
202
+
203
+ final_function_call = None
204
+ response = None
205
+ search_results = None
206
+ email_sent = False
207
+
208
+ if function_call_1 and function_call_2:
209
+ # 裁决模型: 决定使用哪个函数调用
210
+ status_log.append("裁决模型:正在决定使用哪个函数调用")
211
+ arbitration_messages = messages + [
212
+ {"role": "system", "content": "两个次级模型都建议使用函数。请决定使用哪个函数更合适。"},
213
+ {"role": "assistant", "content": f"次级模型1建议使用函数:{function_call_1.name}"},
214
+ {"role": "assistant", "content": f"次级模型2建议使用函数:{function_call_2.name}"}
215
+ ]
216
+ arbitration_response = get_openai_response(arbitration_messages, model="gpt-4o-mini")
217
+ if "模型1" in arbitration_response.content or function_call_1.name in arbitration_response.content:
218
+ final_function_call = function_call_1
219
+ status_log.append(f"裁决模型:决定使用函数 {function_call_1.name}")
220
+ else:
221
+ final_function_call = function_call_2
222
+ status_log.append(f"裁决模型:决定使用函数 {function_call_2.name}")
223
+ elif function_call_1:
224
+ final_function_call = function_call_1
225
+ status_log.append(f"次级模型1:决定使用函数 {function_call_1.name}")
226
+ elif function_call_2:
227
+ final_function_call = function_call_2
228
+ status_log.append(f"次级模型2:决定使用函数 {function_call_2.name}")
229
+ else:
230
+ status_log.append("所有次级模型:判断不需要进行任何函数调用")
231
+
232
+ if final_function_call:
233
+ function_name = final_function_call.name
234
+ function_args = json.loads(final_function_call.arguments)
235
+ status_log.append(f"正在执行函数 {function_name}")
236
+ result = process_function_call(function_name, function_args)
237
+ status_log.append(f"函数 {function_name} 执行完成")
238
+
239
+ if isinstance(result, dict) and result.get("is_email", False):
240
+ response = f"邮件{'已成功' if result['success'] else '未能成功'}发送到 {result['to']}。\n\n主题:{result['subject']}\n\n内容:\n{result['content']}"
241
+ email_sent = result['success']
242
+ elif isinstance(result, list):
243
+ search_results = result
244
+ messages.append({
245
+ "role": "function",
246
+ "name": function_name,
247
+ "content": json.dumps(result, ensure_ascii=False)
248
+ })
249
+ else:
250
+ messages.append({
251
+ "role": "function",
252
+ "name": function_name,
253
+ "content": str(result)
254
+ })
255
+
256
+ # 只有在没有邮件发送结果时才调用主模型
257
+ if not response:
258
+ status_log.append("主模型:正在生成回答")
259
+ final_response = get_openai_response(messages, model="gpt-4o-mini")
260
+ response = final_response.content if final_response else "Error occurred"
261
+ status_log.append("主模型:回答生成完成")
262
+
263
+ return jsonify({
264
+ "response": response,
265
+ "status_log": status_log,
266
+ "search_results": search_results,
267
+ "search_used": bool(search_results),
268
+ "email_sent": email_sent
269
+ })
270
+
271
+ @app.route('/settings', methods=['POST'])
272
+ def update_settings():
273
+ data = request.json
274
+ max_history = data.get('max_history', 10)
275
+ return jsonify({"status": "success", "max_history": max_history})
276
+
277
+ if __name__ == '__main__':
278
+ app.run(host='0.0.0.0', port=7860, debug=True)
279
+ # from flask import Flask, request, jsonify, send_from_directory
280
+ # import requests
281
+ # from bs4 import BeautifulSoup
282
+ # import random
283
+ # import time
284
+
285
+ # app = Flask(__name__)
286
+
287
+ # def perform_bing_search(keywords):
288
+ # search_term = " ".join(keywords)
289
+ # url = "https://www.bing.com/search"
290
+ # user_agents = [
291
+ # "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
292
+ # "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0",
293
+ # "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15",
294
+ # ]
295
+ # headers = {"User-Agent": random.choice(user_agents)}
296
+ # params = {"q": search_term, "setlang": "zh-CN"}
297
+
298
+ # response = requests.get(url, params=params, headers=headers)
299
+ # if response.status_code == 200:
300
+ # soup = BeautifulSoup(response.text, 'html.parser')
301
+ # results = soup.select('.b_algo')
302
+ # search_results = []
303
+ # for result in results[:5]: # 只取前5个结果
304
+ # title = result.select_one('h2 a')
305
+ # snippet = result.select_one('.b_caption p')
306
+ # if title and snippet:
307
+ # search_results.append({
308
+ # "title": title.text,
309
+ # "url": title['href'],
310
+ # "snippet": snippet.text
311
+ # })
312
+ # return search_results
313
+ # return []
314
+
315
+ # @app.route('/')
316
+ # def index():
317
+ # return send_from_directory('.', 'we.html')
318
+
319
+ # @app.route('/start_test', methods=['POST'])
320
+ # def start_test():
321
+ # data = request.json
322
+ # keywords = data['keywords'].split()
323
+ # interval = int(data['interval'])
324
+
325
+ # first_search = perform_bing_search(keywords)
326
+ # time.sleep(interval)
327
+ # second_search = perform_bing_search(keywords)
328
+
329
+ # success = len(first_search) > 0 and len(second_search) > 0
330
+ # return jsonify({
331
+ # "success": success,
332
+ # "first_search": first_search,
333
+ # "second_search": second_search
334
+ # })
335
+
336
+ # if __name__ == '__main__':
337
+ # app.run(host='0.0.0.0', port=7860, debug=True)
338
+