mistpe commited on
Commit
896b1cc
·
verified ·
1 Parent(s): 773afc8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -58
app.py CHANGED
@@ -5,117 +5,174 @@ import hashlib
5
  import time
6
  import xml.etree.ElementTree as ET
7
  import os
 
8
  from openai import OpenAI
9
  from dotenv import load_dotenv
 
 
 
10
 
11
  # 加载环境变量
12
  load_dotenv()
13
 
14
  app = Flask(__name__)
15
 
16
- # 配置
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
  user_sessions = {}
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  def verify_wechat(request):
26
- # 获取微信服务器发送过来的参数
27
  data = request.args
28
  signature = data.get('signature')
29
  timestamp = data.get('timestamp')
30
  nonce = data.get('nonce')
31
  echostr = data.get('echostr')
32
 
33
- # 对参数进行字典排序,拼接字符串
34
  temp = [timestamp, nonce, TOKEN]
35
  temp.sort()
36
  temp = ''.join(temp)
37
 
38
- # 加密
39
- if (hashlib.sha1(temp.encode('utf8')).hexdigest() == signature):
40
  return echostr
41
- else:
42
- return 'error', 403
43
 
44
- def getUserMessageContentFromXML(xml_content):
45
- # 解析XML字符串
46
  root = ET.fromstring(xml_content)
47
- # 提取数据
48
- content = root.find('Content').text
49
- from_user_name = root.find('FromUserName').text
50
- to_user_name = root.find('ToUserName').text
51
- return content, from_user_name, to_user_name
 
 
52
 
53
- def generate_response_xml(from_user_name, to_user_name, output_content):
54
- output_xml = '''
 
 
55
  <xml>
56
  <ToUserName><![CDATA[%s]]></ToUserName>
57
  <FromUserName><![CDATA[%s]]></FromUserName>
58
  <CreateTime>%s</CreateTime>
59
  <MsgType><![CDATA[text]]></MsgType>
60
  <Content><![CDATA[%s]]></Content>
61
- </xml>'''
62
-
63
- response = make_response(output_xml % (from_user_name, to_user_name, str(int(time.time())), output_content))
 
 
64
  response.content_type = 'application/xml'
65
  return response
66
 
67
- def get_openai_response(messages):
 
68
  try:
69
  response = client.chat.completions.create(
70
  model="gpt-4o-mini",
71
- messages=messages
 
72
  )
73
  return response.choices[0].message.content
74
  except Exception as e:
75
- print(f"调用OpenAI API时出错: {str(e)}")
76
- return "抱歉,我遇到了一些问题,无法回答您的问题。"
77
 
78
  def split_message(message, max_length=500):
 
79
  return [message[i:i+max_length] for i in range(0, len(message), max_length)]
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  @app.route('/api/wx', methods=['GET', 'POST'])
82
  def wechatai():
83
  if request.method == 'GET':
84
  return verify_wechat(request)
85
- else:
86
- # 处理POST请求
87
- print("user request data: ", request.data)
88
- user_message_content, from_user_name, to_user_name = getUserMessageContentFromXML(request.data)
89
- print("user message content: ", user_message_content)
90
-
91
- if user_message_content.lower() == '继续':
92
- if from_user_name in user_sessions and user_sessions[from_user_name]['pending_response']:
93
- response_content = user_sessions[from_user_name]['pending_response'].pop(0)
94
- if user_sessions[from_user_name]['pending_response']:
95
- response_content += '\n\n回复"继续"获取下一部分。'
96
- else:
97
- response_content += '\n\n回复结束。'
98
- else:
99
- response_content = "没有待发送的消息。"
100
- else:
101
- if from_user_name not in user_sessions:
102
- user_sessions[from_user_name] = {'messages': [], 'pending_response': []}
103
-
104
- session = user_sessions[from_user_name]
105
- session['messages'].append({"role": "user", "content": user_message_content})
106
-
107
- gpt_response = get_openai_response(session['messages'])
108
- session['messages'].append({"role": "assistant", "content": gpt_response})
109
-
110
- response_parts = split_message(gpt_response)
111
-
112
- if len(response_parts) > 1:
113
- response_content = response_parts[0] + '\n\n回复"继续"获取下一部分。'
114
- session['pending_response'] = response_parts[1:]
115
- else:
116
- response_content = response_parts[0]
117
-
118
- return generate_response_xml(from_user_name, to_user_name, response_content)
119
 
120
  if __name__ == '__main__':
121
  app.run(host='0.0.0.0', port=7860, debug=True)
 
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
+ from functools import lru_cache
14
 
15
  # 加载环境变量
16
  load_dotenv()
17
 
18
  app = Flask(__name__)
19
 
20
+ # 基础配置
21
  TOKEN = os.getenv('TOKEN')
22
  API_KEY = os.getenv("API_KEY")
23
  BASE_URL = os.getenv("OPENAI_BASE_URL")
24
  client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
25
 
26
+ # 用户会话管理
27
  user_sessions = {}
28
 
29
+ def convert_markdown_to_wechat(md_text):
30
+ """将Markdown转换为微信友好的文本格式"""
31
+ # 转换标题
32
+ md_text = re.sub(r'^# (.*?)$', r'【标题】\1', md_text, flags=re.MULTILINE)
33
+ md_text = re.sub(r'^## (.*?)$', r'【子标题】\1', md_text, flags=re.MULTILINE)
34
+
35
+ # 转换粗体和斜体
36
+ md_text = re.sub(r'\*\*(.*?)\*\*', r'『\1』', md_text)
37
+ md_text = re.sub(r'\*(.*?)\*', r'「\1」', md_text)
38
+
39
+ # 转换列表
40
+ md_text = re.sub(r'^\- ', '• ', md_text, flags=re.MULTILINE)
41
+ md_text = re.sub(r'^\d\. ', '○ ', md_text, flags=re.MULTILINE)
42
+
43
+ # 转换代码块
44
+ md_text = re.sub(r'```(.*?)```', r'【代码】\n\1\n【代码结束】', md_text, flags=re.DOTALL)
45
+
46
+ # 转换引用
47
+ md_text = re.sub(r'^> (.*?)$', r'▎\1', md_text, flags=re.MULTILINE)
48
+
49
+ return md_text
50
+
51
  def verify_wechat(request):
52
+ """验证微信服务器请求"""
53
  data = request.args
54
  signature = data.get('signature')
55
  timestamp = data.get('timestamp')
56
  nonce = data.get('nonce')
57
  echostr = data.get('echostr')
58
 
 
59
  temp = [timestamp, nonce, TOKEN]
60
  temp.sort()
61
  temp = ''.join(temp)
62
 
63
+ if hashlib.sha1(temp.encode('utf8')).hexdigest() == signature:
 
64
  return echostr
65
+ return 'error', 403
 
66
 
67
+ def parse_xml_message(xml_content):
68
+ """解析微信XML消息"""
69
  root = ET.fromstring(xml_content)
70
+ return {
71
+ 'content': root.find('Content').text,
72
+ 'from_user': root.find('FromUserName').text,
73
+ 'to_user': root.find('ToUserName').text,
74
+ 'msg_id': root.find('MsgId').text,
75
+ 'create_time': root.find('CreateTime').text
76
+ }
77
 
78
+ def generate_response_xml(to_user, from_user, content):
79
+ """生成回复的XML消息"""
80
+ response_content = convert_markdown_to_wechat(content)
81
+ xml_template = '''
82
  <xml>
83
  <ToUserName><![CDATA[%s]]></ToUserName>
84
  <FromUserName><![CDATA[%s]]></FromUserName>
85
  <CreateTime>%s</CreateTime>
86
  <MsgType><![CDATA[text]]></MsgType>
87
  <Content><![CDATA[%s]]></Content>
88
+ </xml>
89
+ '''
90
+ response = make_response(
91
+ xml_template % (to_user, from_user, str(int(time.time())), response_content)
92
+ )
93
  response.content_type = 'application/xml'
94
  return response
95
 
96
+ def get_openai_response(messages, timeout=30):
97
+ """获取OpenAI API响应"""
98
  try:
99
  response = client.chat.completions.create(
100
  model="gpt-4o-mini",
101
+ messages=messages,
102
+ timeout=timeout
103
  )
104
  return response.choices[0].message.content
105
  except Exception as e:
106
+ print(f"OpenAI API错误: {str(e)}")
107
+ return "抱歉,我暂时无法回答,请稍后再试。"
108
 
109
  def split_message(message, max_length=500):
110
+ """将长消息分段"""
111
  return [message[i:i+max_length] for i in range(0, len(message), max_length)]
112
 
113
+ def cache_response_parts(user_id, parts):
114
+ """缓存分段消息"""
115
+ if not parts:
116
+ return
117
+ user_sessions[user_id] = {
118
+ 'pending_parts': parts,
119
+ 'timestamp': time.time()
120
+ }
121
+
122
+ def get_cached_response(user_id):
123
+ """获取缓存的消息"""
124
+ session = user_sessions.get(user_id)
125
+ if not session or not session['pending_parts']:
126
+ return None
127
+
128
+ # 检查缓存是否过期(1小时后过期)
129
+ if time.time() - session['timestamp'] > 3600:
130
+ del user_sessions[user_id]
131
+ return None
132
+
133
+ next_part = session['pending_parts'].pop(0)
134
+ if not session['pending_parts']:
135
+ del user_sessions[user_id]
136
+ return next_part
137
+
138
  @app.route('/api/wx', methods=['GET', 'POST'])
139
  def wechatai():
140
  if request.method == 'GET':
141
  return verify_wechat(request)
142
+
143
+ try:
144
+ message_data = parse_xml_message(request.data)
145
+ user_content = message_data['content']
146
+ from_user = message_data['from_user']
147
+ to_user = message_data['to_user']
148
+
149
+ # 处理"继续"指令
150
+ if user_content.strip() == '继续':
151
+ cached_response = get_cached_response(from_user)
152
+ if cached_response:
153
+ return generate_response_xml(
154
+ from_user,
155
+ to_user,
156
+ f"{cached_response}\n\n{'回复"继续"查看下一部分' if user_sessions.get(from_user) else '全部内容已发送完毕'}"
157
+ )
158
+
159
+ # 处理普通消息
160
+ response = get_openai_response([{"role": "user", "content": user_content}])
161
+ if len(response) > 500:
162
+ parts = split_message(response)
163
+ first_part = parts.pop(0)
164
+ cache_response_parts(from_user, parts)
165
+ response = f"{first_part}\n\n回复"继续"查看下一部分"
166
+
167
+ return generate_response_xml(from_user, to_user, response)
168
+
169
+ except Exception as e:
170
+ print(f"处理请求时出错: {str(e)}")
171
+ return generate_response_xml(
172
+ message_data['from_user'],
173
+ message_data['to_user'],
174
+ "抱歉,系统暂时出现问题,请稍后重试。"
175
+ )
176
 
177
  if __name__ == '__main__':
178
  app.run(host='0.0.0.0', port=7860, debug=True)