mistpe commited on
Commit
b40cb3e
·
verified ·
1 Parent(s): 30f5685

Create app必须发查询的版本.py

Browse files
Files changed (1) hide show
  1. app必须发查询的版本.py +1287 -0
app必须发查询的版本.py ADDED
@@ -0,0 +1,1287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 markdown import markdown
12
+ # import re
13
+ # import threading
14
+ # import logging
15
+ # from datetime import datetime
16
+
17
+ # # 配置日志记录
18
+ # logging.basicConfig(
19
+ # level=logging.INFO,
20
+ # format='%(asctime)s - %(levelname)s - %(message)s',
21
+ # handlers=[
22
+ # logging.FileHandler('wechat_service.log'),
23
+ # logging.StreamHandler()
24
+ # ]
25
+ # )
26
+
27
+ # # 加载环境变量
28
+ # load_dotenv()
29
+
30
+ # app = Flask(__name__)
31
+
32
+ # # 基础配置
33
+ # TOKEN = os.getenv('TOKEN')
34
+ # API_KEY = os.getenv("API_KEY")
35
+ # BASE_URL = os.getenv("OPENAI_BASE_URL")
36
+ # client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
37
+
38
+ # class UserSession:
39
+ # def __init__(self):
40
+ # self.messages = [{"role": "system", "content": "You are a helpful assistant."}]
41
+ # self.pending_parts = []
42
+ # self.last_active = time.time()
43
+
44
+ # class SessionManager:
45
+ # def __init__(self):
46
+ # self.sessions = {}
47
+ # self.session_timeout = 3600 # 1小时会话超时
48
+ # self._lock = threading.Lock()
49
+
50
+ # def get_session(self, user_id):
51
+ # with self._lock:
52
+ # if user_id not in self.sessions:
53
+ # self.sessions[user_id] = UserSession()
54
+ # session = self.sessions[user_id]
55
+ # session.last_active = time.time()
56
+ # return session
57
+
58
+ # def clear_session(self, user_id):
59
+ # with self._lock:
60
+ # if user_id in self.sessions:
61
+ # self.sessions[user_id] = UserSession()
62
+
63
+ # def cleanup_expired_sessions(self):
64
+ # with self._lock:
65
+ # current_time = time.time()
66
+ # expired_users = [
67
+ # user_id for user_id, session in self.sessions.items()
68
+ # if current_time - session.last_active > self.session_timeout
69
+ # ]
70
+ # for user_id in expired_users:
71
+ # del self.sessions[user_id]
72
+ # logging.info(f"已清理过期会话: {user_id}")
73
+
74
+ # session_manager = SessionManager()
75
+
76
+ # def convert_markdown_to_wechat(md_text):
77
+ # """将Markdown转换为微信友好的文本格式"""
78
+ # md_text = re.sub(r'^# (.*?)$', r'【标题】\1', md_text, flags=re.MULTILINE)
79
+ # md_text = re.sub(r'^## (.*?)$', r'【子标题】\1', md_text, flags=re.MULTILINE)
80
+ # md_text = re.sub(r'\*\*(.*?)\*\*', r'『\1』', md_text)
81
+ # md_text = re.sub(r'\*(.*?)\*', r'「\1」', md_text)
82
+ # md_text = re.sub(r'^\- ', '• ', md_text, flags=re.MULTILINE)
83
+ # md_text = re.sub(r'^\d\. ', '○ ', md_text, flags=re.MULTILINE)
84
+ # md_text = re.sub(r'```(.*?)```', r'【代码】\n\1\n【代码结束】', md_text, flags=re.DOTALL)
85
+ # md_text = re.sub(r'^> (.*?)$', r'▎\1', md_text, flags=re.MULTILINE)
86
+ # return md_text
87
+
88
+ # def verify_wechat(request):
89
+ # """验证微信服务器请求"""
90
+ # data = request.args
91
+ # signature = data.get('signature')
92
+ # timestamp = data.get('timestamp')
93
+ # nonce = data.get('nonce')
94
+ # echostr = data.get('echostr')
95
+
96
+ # temp = [timestamp, nonce, TOKEN]
97
+ # temp.sort()
98
+ # temp = ''.join(temp)
99
+
100
+ # if hashlib.sha1(temp.encode('utf8')).hexdigest() == signature:
101
+ # return echostr
102
+ # return 'error', 403
103
+
104
+ # def parse_xml_message(xml_content):
105
+ # """解析微信XML消息"""
106
+ # root = ET.fromstring(xml_content)
107
+ # return {
108
+ # 'content': root.find('Content').text,
109
+ # 'from_user': root.find('FromUserName').text,
110
+ # 'to_user': root.find('ToUserName').text,
111
+ # 'msg_id': root.find('MsgId').text,
112
+ # 'create_time': root.find('CreateTime').text
113
+ # }
114
+
115
+ # def generate_response_xml(to_user, from_user, content):
116
+ # """生成回复的XML消息"""
117
+ # response_content = convert_markdown_to_wechat(content)
118
+ # xml_template = '''
119
+ # <xml>
120
+ # <ToUserName><![CDATA[%s]]></ToUserName>
121
+ # <FromUserName><![CDATA[%s]]></FromUserName>
122
+ # <CreateTime>%s</CreateTime>
123
+ # <MsgType><![CDATA[text]]></MsgType>
124
+ # <Content><![CDATA[%s]]></Content>
125
+ # </xml>
126
+ # '''
127
+ # response = make_response(
128
+ # xml_template % (to_user, from_user, str(int(time.time())), response_content)
129
+ # )
130
+ # response.content_type = 'application/xml'
131
+ # return response
132
+
133
+ # def get_openai_response(messages, timeout=30):
134
+ # """获取OpenAI API响应"""
135
+ # try:
136
+ # response = client.chat.completions.create(
137
+ # model="gpt-4o-mini",
138
+ # messages=messages,
139
+ # timeout=timeout
140
+ # )
141
+ # return response.choices[0].message.content
142
+ # except Exception as e:
143
+ # logging.error(f"OpenAI API错误: {str(e)}")
144
+ # return "抱歉,我暂时无法回答,请稍后再试。"
145
+
146
+ # def split_message(message, max_length=500):
147
+ # """将长消息分段"""
148
+ # return [message[i:i+max_length] for i in range(0, len(message), max_length)]
149
+
150
+ # def append_status_message(content, has_pending_parts=False):
151
+ # """添加状态提示信息"""
152
+ # status_message = "\n\n-------------------\n"
153
+ # if has_pending_parts:
154
+ # status_message += "当前消息已截断,发送’继续‘查看后续内容\n"
155
+ # status_message += "发送’新对话‘开始新的对话"
156
+ # return content + status_message
157
+
158
+ # @app.route('/api/wx', methods=['GET', 'POST'])
159
+ # def wechatai():
160
+ # if request.method == 'GET':
161
+ # return verify_wechat(request)
162
+
163
+ # try:
164
+ # message_data = parse_xml_message(request.data)
165
+ # user_content = message_data['content']
166
+ # from_user = message_data['from_user']
167
+ # to_user = message_data['to_user']
168
+
169
+ # logging.info(f"收到用户({from_user})消息: {user_content}")
170
+
171
+ # session = session_manager.get_session(from_user)
172
+
173
+ # if user_content.strip() == '新对话':
174
+ # session_manager.clear_session(from_user)
175
+ # return generate_response_xml(
176
+ # from_user,
177
+ # to_user,
178
+ # append_status_message("已开始新的对话。请描述您的问题。")
179
+ # )
180
+
181
+ # if user_content.strip() == '继续':
182
+ # if session.pending_parts:
183
+ # next_part = session.pending_parts.pop(0)
184
+ # has_more = bool(session.pending_parts)
185
+ # return generate_response_xml(
186
+ # from_user,
187
+ # to_user,
188
+ # append_status_message(next_part, has_more)
189
+ # )
190
+ # return generate_response_xml(
191
+ # from_user,
192
+ # to_user,
193
+ # append_status_message("没有更多内容了。请继续您的问题。")
194
+ # )
195
+
196
+ # session.messages.append({"role": "user", "content": user_content})
197
+ # response = get_openai_response(session.messages)
198
+ # session.messages.append({"role": "assistant", "content": response})
199
+
200
+ # if len(response) > 500:
201
+ # parts = split_message(response)
202
+ # first_part = parts.pop(0)
203
+ # session.pending_parts = parts
204
+ # return generate_response_xml(
205
+ # from_user,
206
+ # to_user,
207
+ # append_status_message(first_part, True)
208
+ # )
209
+
210
+ # return generate_response_xml(
211
+ # from_user,
212
+ # to_user,
213
+ # append_status_message(response)
214
+ # )
215
+
216
+ # except Exception as e:
217
+ # logging.error(f"处理请求时出错: {str(e)}")
218
+ # return generate_response_xml(
219
+ # message_data['from_user'],
220
+ # message_data['to_user'],
221
+ # append_status_message("抱歉,系统暂时出现问题,请稍后重试。")
222
+ # )
223
+
224
+ # def cleanup_sessions():
225
+ # """定期清理过期会话"""
226
+ # while True:
227
+ # time.sleep(3600)
228
+ # session_manager.cleanup_expired_sessions()
229
+
230
+ # if __name__ == '__main__':
231
+ # # 启动清理线程
232
+ # cleanup_thread = threading.Thread(target=cleanup_sessions, daemon=True)
233
+ # cleanup_thread.start()
234
+
235
+ # app.run(host='0.0.0.0', port=7860, debug=True)
236
+ #!/usr/bin/env python
237
+ # -*- coding: utf-8 -*-
238
+ # from flask import Flask, request, make_response
239
+ # import hashlib
240
+ # import time
241
+ # import xml.etree.ElementTree as ET
242
+ # import os
243
+ # import json
244
+ # from openai import OpenAI
245
+ # from dotenv import load_dotenv
246
+ # from markdown import markdown
247
+ # import re
248
+ # import threading
249
+ # import logging
250
+ # from datetime import datetime
251
+ # import asyncio
252
+ # from concurrent.futures import ThreadPoolExecutor
253
+ # import queue
254
+ # import uuid
255
+
256
+ # # 配置日志记录
257
+ # logging.basicConfig(
258
+ # level=logging.INFO,
259
+ # format='%(asctime)s - %(levelname)s - %(message)s',
260
+ # handlers=[
261
+ # logging.FileHandler('wechat_service.log'),
262
+ # logging.StreamHandler()
263
+ # ]
264
+ # )
265
+
266
+ # # 加载环境变量
267
+ # load_dotenv()
268
+
269
+ # app = Flask(__name__)
270
+
271
+ # # 基础配置
272
+ # TOKEN = os.getenv('TOKEN')
273
+ # API_KEY = os.getenv("API_KEY")
274
+ # BASE_URL = os.getenv("OPENAI_BASE_URL")
275
+ # client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
276
+
277
+ # # 创建线程池
278
+ # executor = ThreadPoolExecutor(max_workers=10)
279
+
280
+ # def convert_markdown_to_wechat(md_text):
281
+ # """将Markdown转换为微信友好的文本格式"""
282
+ # if not md_text:
283
+ # return md_text
284
+
285
+ # # 处理标题
286
+ # md_text = re.sub(r'^# (.*?)$', r'【标题】\1', md_text, flags=re.MULTILINE)
287
+ # md_text = re.sub(r'^## (.*?)$', r'【子标题】\1', md_text, flags=re.MULTILINE)
288
+ # md_text = re.sub(r'^### (.*?)$', r'【小标题】\1', md_text, flags=re.MULTILINE)
289
+
290
+ # # 处理强调语法
291
+ # md_text = re.sub(r'\*\*(.*?)\*\*', r'『\1』', md_text) # 粗体
292
+ # md_text = re.sub(r'\*(.*?)\*', r'「\1」', md_text) # 斜体
293
+ # md_text = re.sub(r'`(.*?)`', r'「\1」', md_text) # 行内代码
294
+
295
+ # # 处理列表
296
+ # md_text = re.sub(r'^\- ', '• ', md_text, flags=re.MULTILINE) # 无序列表
297
+ # md_text = re.sub(r'^\d\. ', '○ ', md_text, flags=re.MULTILINE) # 有序列表
298
+
299
+ # # 处理代码块
300
+ # md_text = re.sub(r'```[\w]*\n(.*?)```', r'【代码开始】\n\1\n【代码结束】', md_text, flags=re.DOTALL)
301
+
302
+ # # 处理引用
303
+ # md_text = re.sub(r'^> (.*?)$', r'▎\1', md_text, flags=re.MULTILINE)
304
+
305
+ # # 处理分隔线
306
+ # md_text = re.sub(r'^-{3,}$', r'—————————', md_text, flags=re.MULTILINE)
307
+
308
+ # # 处理链接
309
+ # md_text = re.sub(r'\[(.*?)\]\((.*?)\)', r'\1(\2)', md_text)
310
+
311
+ # # 净化处理:去除多余的空行
312
+ # md_text = re.sub(r'\n{3,}', '\n\n', md_text)
313
+
314
+ # return md_text
315
+
316
+ # class AsyncResponse:
317
+ # def __init__(self):
318
+ # self.status = "processing" # processing, completed, failed
319
+ # self.result = None
320
+ # self.error = None
321
+
322
+ # class UserSession:
323
+ # def __init__(self):
324
+ # self.messages = [{"role": "system", "content": "You are a helpful assistant."}]
325
+ # self.pending_parts = []
326
+ # self.last_active = time.time()
327
+ # self.current_task = None # 存储当前正在处理的任务ID
328
+ # self.response_queue = {} # 存储异步响应
329
+
330
+ # class SessionManager:
331
+ # def __init__(self):
332
+ # self.sessions = {}
333
+ # self.session_timeout = 3600 # 1小时会话超时
334
+ # self._lock = threading.Lock()
335
+
336
+ # def get_session(self, user_id):
337
+ # with self._lock:
338
+ # if user_id not in self.sessions:
339
+ # self.sessions[user_id] = UserSession()
340
+ # session = self.sessions[user_id]
341
+ # session.last_active = time.time()
342
+ # return session
343
+
344
+ # def clear_session(self, user_id):
345
+ # with self._lock:
346
+ # if user_id in self.sessions:
347
+ # self.sessions[user_id] = UserSession()
348
+
349
+ # def cleanup_expired_sessions(self):
350
+ # with self._lock:
351
+ # current_time = time.time()
352
+ # expired_users = [
353
+ # user_id for user_id, session in self.sessions.items()
354
+ # if current_time - session.last_active > self.session_timeout
355
+ # ]
356
+ # for user_id in expired_users:
357
+ # del self.sessions[user_id]
358
+ # logging.info(f"已清理过期会话: {user_id}")
359
+
360
+ # session_manager = SessionManager()
361
+
362
+ # def verify_wechat(request):
363
+ # """验证微信服务器请求"""
364
+ # data = request.args
365
+ # signature = data.get('signature')
366
+ # timestamp = data.get('timestamp')
367
+ # nonce = data.get('nonce')
368
+ # echostr = data.get('echostr')
369
+
370
+ # temp = [timestamp, nonce, TOKEN]
371
+ # temp.sort()
372
+ # temp = ''.join(temp)
373
+
374
+ # if hashlib.sha1(temp.encode('utf8')).hexdigest() == signature:
375
+ # return echostr
376
+ # return 'error', 403
377
+
378
+ # def parse_xml_message(xml_content):
379
+ # """解析微信XML消息"""
380
+ # root = ET.fromstring(xml_content)
381
+ # return {
382
+ # 'content': root.find('Content').text,
383
+ # 'from_user': root.find('FromUserName').text,
384
+ # 'to_user': root.find('ToUserName').text,
385
+ # 'msg_id': root.find('MsgId').text,
386
+ # 'create_time': root.find('CreateTime').text
387
+ # }
388
+
389
+ # def generate_response_xml(to_user, from_user, content):
390
+ # """生成回复的XML消息"""
391
+ # formatted_content = convert_markdown_to_wechat(content)
392
+ # xml_template = '''
393
+ # <xml>
394
+ # <ToUserName><![CDATA[%s]]></ToUserName>
395
+ # <FromUserName><![CDATA[%s]]></FromUserName>
396
+ # <CreateTime>%s</CreateTime>
397
+ # <MsgType><![CDATA[text]]></MsgType>
398
+ # <Content><![CDATA[%s]]></Content>
399
+ # </xml>
400
+ # '''
401
+ # response = make_response(
402
+ # xml_template % (to_user, from_user, str(int(time.time())), formatted_content)
403
+ # )
404
+ # response.content_type = 'application/xml'
405
+ # return response
406
+
407
+ # def process_long_running_task(messages):
408
+ # """处理耗时任务"""
409
+ # try:
410
+ # response = client.chat.completions.create(
411
+ # model="gpt-4o-mini",
412
+ # messages=messages,
413
+ # timeout=60
414
+ # )
415
+ # return response.choices[0].message.content
416
+ # except Exception as e:
417
+ # logging.error(f"API调用错误: {str(e)}")
418
+ # raise
419
+
420
+ # def handle_async_task(session, task_id, messages):
421
+ # """异步任务处理函数"""
422
+ # try:
423
+ # result = process_long_running_task(messages)
424
+ # session.response_queue[task_id].status = "completed"
425
+ # session.response_queue[task_id].result = result
426
+ # except Exception as e:
427
+ # session.response_queue[task_id].status = "failed"
428
+ # session.response_queue[task_id].error = str(e)
429
+
430
+ # def generate_initial_response():
431
+ # """生成初始响应消息"""
432
+ # return "您的���求正在处理中,请稍后回复’查询‘获取结果。"
433
+
434
+ # def split_message(message, max_length=500):
435
+ # """将长消息分段"""
436
+ # return [message[i:i+max_length] for i in range(0, len(message), max_length)]
437
+
438
+ # def append_status_message(content, has_pending_parts=False, is_processing=False):
439
+ # """添加状态提示信息"""
440
+ # status_message = "\n\n-------------------\n"
441
+ # if is_processing:
442
+ # status_message += "您的请求正在处理中,请回复’查询‘获取结果\n"
443
+ # elif has_pending_parts:
444
+ # status_message += "当前消息已截断,发送’继续‘查看后续内容\n"
445
+ # status_message += "发送‘新对话’开始新的对话"
446
+ # return content + status_message
447
+
448
+ # @app.route('/api/wx', methods=['GET', 'POST'])
449
+ # def wechatai():
450
+ # if request.method == 'GET':
451
+ # return verify_wechat(request)
452
+
453
+ # try:
454
+ # message_data = parse_xml_message(request.data)
455
+ # user_content = message_data['content'].strip()
456
+ # from_user = message_data['from_user']
457
+ # to_user = message_data['to_user']
458
+
459
+ # logging.info(f"收到用户({from_user})消息: {user_content}")
460
+ # session = session_manager.get_session(from_user)
461
+
462
+ # # 处理特殊命令
463
+ # if user_content == '新对话':
464
+ # session_manager.clear_session(from_user)
465
+ # return generate_response_xml(
466
+ # from_user,
467
+ # to_user,
468
+ # append_status_message("已开始新的对话。请描述您的问题。")
469
+ # )
470
+
471
+ # if user_content == '继续':
472
+ # if session.pending_parts:
473
+ # next_part = session.pending_parts.pop(0)
474
+ # has_more = bool(session.pending_parts)
475
+ # return generate_response_xml(
476
+ # from_user,
477
+ # to_user,
478
+ # append_status_message(next_part, has_more)
479
+ # )
480
+ # return generate_response_xml(
481
+ # from_user,
482
+ # to_user,
483
+ # append_status_message("没有更多内容了。请继续您的问题。")
484
+ # )
485
+
486
+ # if user_content == '查询':
487
+ # if session.current_task:
488
+ # task_response = session.response_queue.get(session.current_task)
489
+ # if task_response:
490
+ # if task_response.status == "completed":
491
+ # response = task_response.result
492
+ # # 清理完成的任务
493
+ # del session.response_queue[session.current_task]
494
+ # session.current_task = None
495
+
496
+ # # 处理长消息
497
+ # if len(response) > 500:
498
+ # parts = split_message(response)
499
+ # first_part = parts.pop(0)
500
+ # session.pending_parts = parts
501
+ # return generate_response_xml(
502
+ # from_user,
503
+ # to_user,
504
+ # append_status_message(first_part, True)
505
+ # )
506
+ # return generate_response_xml(
507
+ # from_user,
508
+ # to_user,
509
+ # append_status_message(response)
510
+ # )
511
+ # elif task_response.status == "failed":
512
+ # error_message = "处理过程中出现错误,请重新提问。"
513
+ # # 清理失败的任务
514
+ # del session.response_queue[session.current_task]
515
+ # session.current_task = None
516
+ # return generate_response_xml(
517
+ # from_user,
518
+ # to_user,
519
+ # append_status_message(error_message)
520
+ # )
521
+ # else:
522
+ # return generate_response_xml(
523
+ # from_user,
524
+ # to_user,
525
+ # append_status_message("正在处理中,请稍后再次查询。", is_processing=True)
526
+ # )
527
+ # return generate_response_xml(
528
+ # from_user,
529
+ # to_user,
530
+ # append_status_message("没有正在处理的请求。")
531
+ # )
532
+
533
+ # # 处理新的用户消息
534
+ # session.messages.append({"role": "user", "content": user_content})
535
+
536
+ # # 创建新的异步任务
537
+ # task_id = str(uuid.uuid4())
538
+ # session.current_task = task_id
539
+ # session.response_queue[task_id] = AsyncResponse()
540
+
541
+ # # 启动异步处理
542
+ # executor.submit(handle_async_task, session, task_id, session.messages.copy())
543
+
544
+ # # 返回初始响应
545
+ # return generate_response_xml(
546
+ # from_user,
547
+ # to_user,
548
+ # append_status_message(generate_initial_response(), is_processing=True)
549
+ # )
550
+
551
+ # except Exception as e:
552
+ # logging.error(f"处理请求时出错: {str(e)}")
553
+ # return generate_response_xml(
554
+ # message_data['from_user'],
555
+ # message_data['to_user'],
556
+ # append_status_message("抱歉,系统暂时出现问题,请稍后重试。")
557
+ # )
558
+
559
+ # def cleanup_sessions():
560
+ # """定期清理过期会话"""
561
+ # while True:
562
+ # time.sleep(3600) # 每小时清理一次
563
+ # try:
564
+ # session_manager.cleanup_expired_sessions()
565
+ # except Exception as e:
566
+ # logging.error(f"清理会话时出错: {str(e)}")
567
+
568
+ # if __name__ == '__main__':
569
+ # # 启动清理线程
570
+ # cleanup_thread = threading.Thread(target=cleanup_sessions, daemon=True)
571
+ # cleanup_thread.start()
572
+
573
+ # # 启动Flask应用
574
+ # app.run(host='0.0.0.0', port=7860, debug=True)
575
+ # #!/usr/bin/env python
576
+ # # -*- coding: utf-8 -*-
577
+ # from flask import Flask, request, make_response
578
+ # import hashlib
579
+ # import time
580
+ # import xml.etree.ElementTree as ET
581
+ # import os
582
+ # import json
583
+ # from openai import OpenAI
584
+ # from dotenv import load_dotenv
585
+ # from markdown import markdown
586
+ # import re
587
+ # import threading
588
+ # import logging
589
+ # from datetime import datetime
590
+ # import asyncio
591
+ # from concurrent.futures import ThreadPoolExecutor
592
+ # import queue
593
+ # import uuid
594
+
595
+ # # 配置日志记录
596
+ # logging.basicConfig(
597
+ # level=logging.INFO,
598
+ # format='%(asctime)s - %(levelname)s - %(message)s',
599
+ # handlers=[
600
+ # logging.FileHandler('wechat_service.log'),
601
+ # logging.StreamHandler()
602
+ # ]
603
+ # )
604
+
605
+ # # 加载环境变量
606
+ # load_dotenv()
607
+
608
+ # app = Flask(__name__)
609
+
610
+ # # 基础配置
611
+ # TOKEN = os.getenv('TOKEN')
612
+ # API_KEY = os.getenv("API_KEY")
613
+ # BASE_URL = os.getenv("OPENAI_BASE_URL")
614
+ # client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
615
+
616
+ # # 创建线程池
617
+ # executor = ThreadPoolExecutor(max_workers=10)
618
+
619
+ # def convert_markdown_to_wechat(md_text):
620
+ # """将Markdown转换为微信友好的文本格式"""
621
+ # if not md_text:
622
+ # return md_text
623
+
624
+ # # 处理标题
625
+ # md_text = re.sub(r'^# (.*?)$', r'【标题】\1', md_text, flags=re.MULTILINE)
626
+ # md_text = re.sub(r'^## (.*?)$', r'【子标题】\1', md_text, flags=re.MULTILINE)
627
+ # md_text = re.sub(r'^### (.*?)$', r'【小标题】\1', md_text, flags=re.MULTILINE)
628
+
629
+ # # 处理强调语法
630
+ # md_text = re.sub(r'\*\*(.*?)\*\*', r'『\1』', md_text) # 粗体
631
+ # md_text = re.sub(r'\*(.*?)\*', r'「\1」', md_text) # 斜体
632
+ # md_text = re.sub(r'`(.*?)`', r'「\1」', md_text) # 行内代码
633
+
634
+ # # 处理列表
635
+ # md_text = re.sub(r'^\- ', '• ', md_text, flags=re.MULTILINE) # 无序列表
636
+ # md_text = re.sub(r'^\d\. ', '○ ', md_text, flags=re.MULTILINE) # 有序列表
637
+
638
+ # # 处理代码块
639
+ # md_text = re.sub(r'```[\w]*\n(.*?)```', r'【代码开始】\n\1\n【代码结束】', md_text, flags=re.DOTALL)
640
+
641
+ # # 处理引用
642
+ # md_text = re.sub(r'^> (.*?)$', r'▎\1', md_text, flags=re.MULTILINE)
643
+
644
+ # # 处理分隔线
645
+ # md_text = re.sub(r'^-{3,}$', r'—————————', md_text, flags=re.MULTILINE)
646
+
647
+ # # 处理链接
648
+ # md_text = re.sub(r'\[(.*?)\]\((.*?)\)', r'\1(\2)', md_text)
649
+
650
+ # # 净化处理:去除多余的空行
651
+ # md_text = re.sub(r'\n{3,}', '\n\n', md_text)
652
+
653
+ # return md_text
654
+
655
+ # class AsyncResponse:
656
+ # def __init__(self):
657
+ # self.status = "processing" # processing, completed, failed
658
+ # self.result = None
659
+ # self.error = None
660
+
661
+ # class UserSession:
662
+ # def __init__(self):
663
+ # self.messages = [{"role": "system", "content": "You are a helpful assistant."}]
664
+ # self.pending_parts = []
665
+ # self.last_active = time.time()
666
+ # self.current_task = None
667
+ # self.response_queue = {}
668
+
669
+ # class SessionManager:
670
+ # def __init__(self):
671
+ # self.sessions = {}
672
+ # self.session_timeout = 3600
673
+ # self._lock = threading.Lock()
674
+
675
+ # def get_session(self, user_id):
676
+ # with self._lock:
677
+ # if user_id not in self.sessions:
678
+ # self.sessions[user_id] = UserSession()
679
+ # session = self.sessions[user_id]
680
+ # session.last_active = time.time()
681
+ # return session
682
+
683
+ # def clear_session(self, user_id):
684
+ # with self._lock:
685
+ # if user_id in self.sessions:
686
+ # self.sessions[user_id] = UserSession()
687
+
688
+ # def cleanup_expired_sessions(self):
689
+ # with self._lock:
690
+ # current_time = time.time()
691
+ # expired_users = [
692
+ # user_id for user_id, session in self.sessions.items()
693
+ # if current_time - session.last_active > self.session_timeout
694
+ # ]
695
+ # for user_id in expired_users:
696
+ # del self.sessions[user_id]
697
+ # logging.info(f"已清理过期会话: {user_id}")
698
+
699
+ # session_manager = SessionManager()
700
+
701
+ # def verify_wechat(request):
702
+ # """验证微信服务器请求"""
703
+ # data = request.args
704
+ # signature = data.get('signature')
705
+ # timestamp = data.get('timestamp')
706
+ # nonce = data.get('nonce')
707
+ # echostr = data.get('echostr')
708
+
709
+ # temp = [timestamp, nonce, TOKEN]
710
+ # temp.sort()
711
+ # temp = ''.join(temp)
712
+
713
+ # if hashlib.sha1(temp.encode('utf8')).hexdigest() == signature:
714
+ # return echostr
715
+ # return 'error', 403
716
+
717
+ # def parse_xml_message(xml_content):
718
+ # """解析微信XML消息"""
719
+ # root = ET.fromstring(xml_content)
720
+ # return {
721
+ # 'content': root.find('Content').text,
722
+ # 'from_user': root.find('FromUserName').text,
723
+ # 'to_user': root.find('ToUserName').text,
724
+ # 'msg_id': root.find('MsgId').text,
725
+ # 'create_time': root.find('CreateTime').text
726
+ # }
727
+
728
+ # def generate_response_xml(to_user, from_user, content):
729
+ # """生成回复的XML消息"""
730
+ # formatted_content = convert_markdown_to_wechat(content)
731
+ # xml_template = '''
732
+ # <xml>
733
+ # <ToUserName><![CDATA[%s]]></ToUserName>
734
+ # <FromUserName><![CDATA[%s]]></FromUserName>
735
+ # <CreateTime>%s</CreateTime>
736
+ # <MsgType><![CDATA[text]]></MsgType>
737
+ # <Content><![CDATA[%s]]></Content>
738
+ # </xml>
739
+ # '''
740
+ # response = make_response(
741
+ # xml_template % (to_user, from_user, str(int(time.time())), formatted_content)
742
+ # )
743
+ # response.content_type = 'application/xml'
744
+ # return response
745
+
746
+ # def process_long_running_task(messages):
747
+ # """处理耗时任务"""
748
+ # try:
749
+ # response = client.chat.completions.create(
750
+ # model="gpt-4o-mini",
751
+ # messages=messages,
752
+ # timeout=60
753
+ # )
754
+ # return response.choices[0].message.content
755
+ # except Exception as e:
756
+ # logging.error(f"API调用错误: {str(e)}")
757
+ # raise
758
+
759
+ # def handle_async_task(session, task_id, messages):
760
+ # """异步任务处理函数"""
761
+ # try:
762
+ # result = process_long_running_task(messages)
763
+ # session.response_queue[task_id].status = "completed"
764
+ # session.response_queue[task_id].result = result
765
+ # except Exception as e:
766
+ # session.response_queue[task_id].status = "failed"
767
+ # session.response_queue[task_id].error = str(e)
768
+
769
+ # def generate_initial_response():
770
+ # """生成初始响应消息"""
771
+ # return "您的请求正在处理中"
772
+
773
+ # def split_message(message, max_length=500):
774
+ # """将长消息分段"""
775
+ # return [message[i:i+max_length] for i in range(0, len(message), max_length)]
776
+
777
+ # def append_status_message(content, has_pending_parts=False, is_processing=False):
778
+ # """添加状态提示信息"""
779
+ # status_message = "\n\n-------------------"
780
+ # if is_processing:
781
+ # status_message += "\n请回复'查询'获取结果"
782
+ # elif has_pending_parts:
783
+ # status_message += "\n当前消息已截断,发送'继续'查看后续内容"
784
+ # status_message += "\n发送'新对话'开始新的对话"
785
+ # return content + status_message
786
+
787
+ # @app.route('/api/wx', methods=['GET', 'POST'])
788
+ # def wechatai():
789
+ # if request.method == 'GET':
790
+ # return verify_wechat(request)
791
+
792
+ # try:
793
+ # message_data = parse_xml_message(request.data)
794
+ # user_content = message_data['content'].strip()
795
+ # from_user = message_data['from_user']
796
+ # to_user = message_data['to_user']
797
+
798
+ # logging.info(f"收到用户({from_user})消息: {user_content}")
799
+ # session = session_manager.get_session(from_user)
800
+
801
+ # if user_content == '新对话':
802
+ # session_manager.clear_session(from_user)
803
+ # return generate_response_xml(
804
+ # from_user,
805
+ # to_user,
806
+ # append_status_message('已开始新的对话。请描述您的问题。')
807
+ # )
808
+
809
+ # if user_content == '继续':
810
+ # if session.pending_parts:
811
+ # next_part = session.pending_parts.pop(0)
812
+ # has_more = bool(session.pending_parts)
813
+ # return generate_response_xml(
814
+ # from_user,
815
+ # to_user,
816
+ # append_status_message(next_part, has_more)
817
+ # )
818
+ # return generate_response_xml(
819
+ # from_user,
820
+ # to_user,
821
+ # append_status_message('没有更多内容了。请继续您的问题。')
822
+ # )
823
+
824
+ # if user_content == '查询':
825
+ # if session.current_task:
826
+ # task_response = session.response_queue.get(session.current_task)
827
+ # if task_response:
828
+ # if task_response.status == "completed":
829
+ # response = task_response.result
830
+ # del session.response_queue[session.current_task]
831
+ # session.current_task = None
832
+
833
+ # if len(response) > 500:
834
+ # parts = split_message(response)
835
+ # first_part = parts.pop(0)
836
+ # session.pending_parts = parts
837
+ # return generate_response_xml(
838
+ # from_user,
839
+ # to_user,
840
+ # append_status_message(first_part, True)
841
+ # )
842
+ # return generate_response_xml(
843
+ # from_user,
844
+ # to_user,
845
+ # append_status_message(response)
846
+ # )
847
+ # elif task_response.status == "failed":
848
+ # error_message = '处理过程中出现错误,请重新提问。'
849
+ # del session.response_queue[session.current_task]
850
+ # session.current_task = None
851
+ # return generate_response_xml(
852
+ # from_user,
853
+ # to_user,
854
+ # append_status_message(error_message)
855
+ # )
856
+ # else:
857
+ # return generate_response_xml(
858
+ # from_user,
859
+ # to_user,
860
+ # append_status_message('正在处理中,请稍后再次查询。', is_processing=True)
861
+ # )
862
+ # return generate_response_xml(
863
+ # from_user,
864
+ # to_user,
865
+ # append_status_message('没有正在处理的请求。')
866
+ # )
867
+
868
+ # session.messages.append({"role": "user", "content": user_content})
869
+
870
+ # task_id = str(uuid.uuid4())
871
+ # session.current_task = task_id
872
+ # session.response_queue[task_id] = AsyncResponse()
873
+
874
+ # executor.submit(handle_async_task, session, task_id, session.messages.copy())
875
+
876
+ # return generate_response_xml(
877
+ # from_user,
878
+ # to_user,
879
+ # append_status_message(generate_initial_response(), is_processing=True)
880
+ # )
881
+
882
+ # except Exception as e:
883
+ # logging.error(f"处理请求时出错: {str(e)}")
884
+ # return generate_response_xml(
885
+ # message_data['from_user'],
886
+ # message_data['to_user'],
887
+ # append_status_message('抱歉,系统暂时出现问题,请稍后重试。')
888
+ # )
889
+
890
+ # def cleanup_sessions():
891
+ # """定期清理过期会话"""
892
+ # while True:
893
+ # time.sleep(3600)
894
+ # try:
895
+ # session_manager.cleanup_expired_sessions()
896
+ # except Exception as e:
897
+ # logging.error(f"清理会话时出错: {str(e)}")
898
+
899
+ # if __name__ == '__main__':
900
+ # cleanup_thread = threading.Thread(target=cleanup_sessions, daemon=True)
901
+ # cleanup_thread.start()
902
+
903
+ # app.run(host='0.0.0.0', port=7860, debug=True)
904
+ #下面这个代码解决的是响应查询时重复回应的情况
905
+ #!/usr/bin/env python
906
+ # -*- coding: utf-8 -*-
907
+ #
908
+ #下面这个代码是告诉用户超时后就需要重新回答了
909
+ #!/usr/bin/env python
910
+ # -*- coding: utf-8 -*-
911
+ from flask import Flask, request, make_response
912
+ import hashlib
913
+ import time
914
+ import xml.etree.ElementTree as ET
915
+ import os
916
+ import json
917
+ from openai import OpenAI
918
+ from dotenv import load_dotenv
919
+ from markdown import markdown
920
+ import re
921
+ import threading
922
+ import logging
923
+ from datetime import datetime
924
+ import asyncio
925
+ from concurrent.futures import ThreadPoolExecutor
926
+ import queue
927
+ import uuid
928
+
929
+ # 配置日志记录
930
+ logging.basicConfig(
931
+ level=logging.INFO,
932
+ format='%(asctime)s - %(levelname)s - %(message)s',
933
+ handlers=[
934
+ logging.FileHandler('wechat_service.log'),
935
+ logging.StreamHandler()
936
+ ]
937
+ )
938
+
939
+ # 加载环境变量
940
+ load_dotenv()
941
+
942
+ app = Flask(__name__)
943
+
944
+ # 基础配置
945
+ TOKEN = os.getenv('TOKEN')
946
+ API_KEY = os.getenv("API_KEY")
947
+ BASE_URL = os.getenv("OPENAI_BASE_URL")
948
+ client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
949
+
950
+ # 创建线程池
951
+ executor = ThreadPoolExecutor(max_workers=10)
952
+
953
+ class AsyncResponse:
954
+ def __init__(self):
955
+ self.status = "processing" # processing, completed, failed
956
+ self.result = None
957
+ self.error = None
958
+ self.create_time = time.time() # 任务创建时间
959
+ self.timeout = 3600 # 任务超时时间(1小时)
960
+
961
+ def is_expired(self):
962
+ """检查任务是否过期"""
963
+ return time.time() - self.create_time > self.timeout
964
+
965
+ class UserSession:
966
+ def __init__(self):
967
+ self.messages = [{"role": "system", "content": "You are a helpful assistant."}]
968
+ self.pending_parts = []
969
+ self.last_active = time.time()
970
+ self.current_task = None
971
+ self.response_queue = {}
972
+ self.session_timeout = 3600 # 会话超时时间(1小时)
973
+
974
+ def is_expired(self):
975
+ """检查会话是否过期"""
976
+ return time.time() - self.last_active > self.session_timeout
977
+
978
+ def cleanup_expired_tasks(self):
979
+ """清理过期的任务"""
980
+ expired_tasks = [
981
+ task_id for task_id, response in self.response_queue.items()
982
+ if response.is_expired()
983
+ ]
984
+ for task_id in expired_tasks:
985
+ del self.response_queue[task_id]
986
+ if self.current_task == task_id:
987
+ self.current_task = None
988
+
989
+ class SessionManager:
990
+ def __init__(self):
991
+ self.sessions = {}
992
+ self._lock = threading.Lock()
993
+
994
+ def get_session(self, user_id):
995
+ with self._lock:
996
+ current_time = time.time()
997
+ if user_id in self.sessions:
998
+ session = self.sessions[user_id]
999
+ if session.is_expired():
1000
+ session = UserSession() # 创建新会话
1001
+ else:
1002
+ session.cleanup_expired_tasks() # 清理过期任务
1003
+ else:
1004
+ session = UserSession()
1005
+ session.last_active = current_time
1006
+ self.sessions[user_id] = session
1007
+ return session
1008
+
1009
+ def clear_session(self, user_id):
1010
+ with self._lock:
1011
+ if user_id in self.sessions:
1012
+ self.sessions[user_id] = UserSession()
1013
+
1014
+ def cleanup_expired_sessions(self):
1015
+ with self._lock:
1016
+ current_time = time.time()
1017
+ expired_users = [
1018
+ user_id for user_id, session in self.sessions.items()
1019
+ if session.is_expired()
1020
+ ]
1021
+ for user_id in expired_users:
1022
+ del self.sessions[user_id]
1023
+ logging.info(f"已清理过期会话: {user_id}")
1024
+
1025
+ session_manager = SessionManager()
1026
+
1027
+ def convert_markdown_to_wechat(md_text):
1028
+ """将Markdown转换为微信友好的文本格式"""
1029
+ if not md_text:
1030
+ return md_text
1031
+
1032
+ # 处理标题
1033
+ md_text = re.sub(r'^# (.*?)$', r'【标题】\1', md_text, flags=re.MULTILINE)
1034
+ md_text = re.sub(r'^## (.*?)$', r'【子标题】\1', md_text, flags=re.MULTILINE)
1035
+ md_text = re.sub(r'^### (.*?)$', r'【小标题】\1', md_text, flags=re.MULTILINE)
1036
+
1037
+ # 处理强调语法
1038
+ md_text = re.sub(r'\*\*(.*?)\*\*', r'『\1』', md_text) # 粗体
1039
+ md_text = re.sub(r'\*(.*?)\*', r'「\1」', md_text) # 斜体
1040
+ md_text = re.sub(r'`(.*?)`', r'「\1」', md_text) # 行内代码
1041
+
1042
+ # 处理列表
1043
+ md_text = re.sub(r'^\- ', '• ', md_text, flags=re.MULTILINE) # 无序列表
1044
+ md_text = re.sub(r'^\d\. ', '○ ', md_text, flags=re.MULTILINE) # 有序列表
1045
+
1046
+ # 处理代码块
1047
+ md_text = re.sub(r'```[\w]*\n(.*?)```', r'【代码开始】\n\1\n【代码结束】', md_text, flags=re.DOTALL)
1048
+
1049
+ # 处理引用
1050
+ md_text = re.sub(r'^> (.*?)$', r'▎\1', md_text, flags=re.MULTILINE)
1051
+
1052
+ # 处理分隔线
1053
+ md_text = re.sub(r'^-{3,}$', r'—————————', md_text, flags=re.MULTILINE)
1054
+
1055
+ # 处理链接
1056
+ md_text = re.sub(r'\[(.*?)\]\((.*?)\)', r'\1(\2)', md_text)
1057
+
1058
+ # 净化处理:去除多余的空行
1059
+ md_text = re.sub(r'\n{3,}', '\n\n', md_text)
1060
+
1061
+ return md_text
1062
+
1063
+ def verify_wechat(request):
1064
+ """验证微信服务器请求"""
1065
+ data = request.args
1066
+ signature = data.get('signature')
1067
+ timestamp = data.get('timestamp')
1068
+ nonce = data.get('nonce')
1069
+ echostr = data.get('echostr')
1070
+
1071
+ temp = [timestamp, nonce, TOKEN]
1072
+ temp.sort()
1073
+ temp = ''.join(temp)
1074
+
1075
+ if hashlib.sha1(temp.encode('utf8')).hexdigest() == signature:
1076
+ return echostr
1077
+ return 'error', 403
1078
+
1079
+ def parse_xml_message(xml_content):
1080
+ """解析微信XML消息"""
1081
+ root = ET.fromstring(xml_content)
1082
+ return {
1083
+ 'content': root.find('Content').text,
1084
+ 'from_user': root.find('FromUserName').text,
1085
+ 'to_user': root.find('ToUserName').text,
1086
+ 'msg_id': root.find('MsgId').text,
1087
+ 'create_time': root.find('CreateTime').text
1088
+ }
1089
+
1090
+ def generate_response_xml(to_user, from_user, content):
1091
+ """生成回复的XML消息"""
1092
+ formatted_content = convert_markdown_to_wechat(content)
1093
+ xml_template = '''
1094
+ <xml>
1095
+ <ToUserName><![CDATA[%s]]></ToUserName>
1096
+ <FromUserName><![CDATA[%s]]></FromUserName>
1097
+ <CreateTime>%s</CreateTime>
1098
+ <MsgType><![CDATA[text]]></MsgType>
1099
+ <Content><![CDATA[%s]]></Content>
1100
+ </xml>
1101
+ '''
1102
+ response = make_response(
1103
+ xml_template % (to_user, from_user, str(int(time.time())), formatted_content)
1104
+ )
1105
+ response.content_type = 'application/xml'
1106
+ return response
1107
+
1108
+ def process_long_running_task(messages):
1109
+ """处理耗时任务"""
1110
+ try:
1111
+ response = client.chat.completions.create(
1112
+ model="gpt-4o-mini",
1113
+ messages=messages,
1114
+ timeout=60
1115
+ )
1116
+ return response.choices[0].message.content
1117
+ except Exception as e:
1118
+ logging.error(f"API调用错误: {str(e)}")
1119
+ raise
1120
+
1121
+ def handle_async_task(session, task_id, messages):
1122
+ """异步任务处理函数"""
1123
+ try:
1124
+ if task_id not in session.response_queue:
1125
+ return
1126
+
1127
+ result = process_long_running_task(messages)
1128
+
1129
+ if task_id in session.response_queue and not session.response_queue[task_id].is_expired():
1130
+ session.response_queue[task_id].status = "completed"
1131
+ session.response_queue[task_id].result = result
1132
+ except Exception as e:
1133
+ if task_id in session.response_queue:
1134
+ session.response_queue[task_id].status = "failed"
1135
+ session.response_queue[task_id].error = str(e)
1136
+
1137
+ def generate_initial_response():
1138
+ """生成初始响应消息"""
1139
+ return "您的请求正在处理中,请回复'查询'获取结果"
1140
+
1141
+ def split_message(message, max_length=500):
1142
+ """将长消息分段"""
1143
+ return [message[i:i+max_length] for i in range(0, len(message), max_length)]
1144
+
1145
+ def append_status_message(content, has_pending_parts=False, is_processing=False):
1146
+ """添加状态提示信息"""
1147
+ if "您的请求正在处理中" in content:
1148
+ return content + "\n\n-------------------\n发送'新对话'开始新的对话"
1149
+
1150
+ status_message = "\n\n-------------------"
1151
+ if is_processing:
1152
+ status_message += "\n请回复'查询'获取结果"
1153
+ elif has_pending_parts:
1154
+ status_message += "\n当前消息已截断,发送'继续'查看后续内容"
1155
+ status_message += "\n发送'新对话'开始新的对话"
1156
+ return content + status_message
1157
+
1158
+ @app.route('/api/wx', methods=['GET', 'POST'])
1159
+ def wechatai():
1160
+ if request.method == 'GET':
1161
+ return verify_wechat(request)
1162
+
1163
+ try:
1164
+ message_data = parse_xml_message(request.data)
1165
+ user_content = message_data['content'].strip()
1166
+ from_user = message_data['from_user']
1167
+ to_user = message_data['to_user']
1168
+
1169
+ logging.info(f"收到用户({from_user})消息: {user_content}")
1170
+ session = session_manager.get_session(from_user)
1171
+
1172
+ if user_content == '新对话':
1173
+ session_manager.clear_session(from_user)
1174
+ return generate_response_xml(
1175
+ from_user,
1176
+ to_user,
1177
+ append_status_message('已开始新的对话。请描述您的问题。')
1178
+ )
1179
+
1180
+ if user_content == '继续':
1181
+ if session.pending_parts:
1182
+ next_part = session.pending_parts.pop(0)
1183
+ has_more = bool(session.pending_parts)
1184
+ return generate_response_xml(
1185
+ from_user,
1186
+ to_user,
1187
+ append_status_message(next_part, has_more)
1188
+ )
1189
+ return generate_response_xml(
1190
+ from_user,
1191
+ to_user,
1192
+ append_status_message('没有更多内容了。请继续您的问题。')
1193
+ )
1194
+
1195
+ if user_content == '查询':
1196
+ if session.current_task:
1197
+ task_response = session.response_queue.get(session.current_task)
1198
+ if task_response:
1199
+ if task_response.is_expired():
1200
+ # 处理过期任务
1201
+ del session.response_queue[session.current_task]
1202
+ session.current_task = None
1203
+ return generate_response_xml(
1204
+ from_user,
1205
+ to_user,
1206
+ append_status_message('请求已过期,请重新提问。')
1207
+ )
1208
+
1209
+ if task_response.status == "completed":
1210
+ response = task_response.result
1211
+ del session.response_queue[session.current_task]
1212
+ session.current_task = None
1213
+ session.messages.append({"role": "assistant", "content": response})
1214
+
1215
+ if len(response) > 500:
1216
+ parts = split_message(response)
1217
+ first_part = parts.pop(0)
1218
+ session.pending_parts = parts
1219
+ return generate_response_xml(
1220
+ from_user,
1221
+ to_user,
1222
+ append_status_message(first_part, True)
1223
+ )
1224
+ return generate_response_xml(
1225
+ from_user,
1226
+ to_user,
1227
+ append_status_message(response)
1228
+ )
1229
+ elif task_response.status == "failed":
1230
+ error_message = '处理过程中出现错误,请重新提问。'
1231
+ del session.response_queue[session.current_task]
1232
+ session.current_task = None
1233
+ return generate_response_xml(
1234
+ from_user,
1235
+ to_user,
1236
+ append_status_message(error_message)
1237
+ )
1238
+ else:
1239
+ return generate_response_xml(
1240
+ from_user,
1241
+ to_user,
1242
+ append_status_message('正在处理中,请稍后再次查询。', is_processing=True)
1243
+ )
1244
+ return generate_response_xml(
1245
+ from_user,
1246
+ to_user,
1247
+ append_status_message('没有正在处理的请求。')
1248
+ )
1249
+
1250
+ session.messages.append({"role": "user", "content": user_content})
1251
+
1252
+ task_id = str(uuid.uuid4())
1253
+ session.current_task = task_id
1254
+ session.response_queue[task_id] = AsyncResponse()
1255
+
1256
+ executor.submit(handle_async_task, session, task_id, session.messages.copy())
1257
+
1258
+ return generate_response_xml(
1259
+ from_user,
1260
+ to_user,
1261
+ append_status_message(generate_initial_response(), is_processing=True)
1262
+ )
1263
+
1264
+ except Exception as e:
1265
+ logging.error(f"处理请求时出错: {str(e)}")
1266
+ return generate_response_xml(
1267
+ message_data['from_user'],
1268
+ message_data['to_user'],
1269
+ append_status_message('抱歉,系统暂时出现问题,请稍后重试。')
1270
+ )
1271
+
1272
+ def cleanup_sessions():
1273
+ """定期清理过期会话"""
1274
+ while True:
1275
+ time.sleep(3600) # 每小时清理一次
1276
+ try:
1277
+ session_manager.cleanup_expired_sessions()
1278
+ except Exception as e:
1279
+ logging.error(f"清理会话时出错: {str(e)}")
1280
+
1281
+ if __name__ == '__main__':
1282
+ # 启动清理线程
1283
+ cleanup_thread = threading.Thread(target=cleanup_sessions, daemon=True)
1284
+ cleanup_thread.start()
1285
+
1286
+ # 启动Flask应用
1287
+ app.run(host='0.0.0.0', port=7860, debug=True)