smgc commited on
Commit
78d0798
1 Parent(s): 22d15b3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -42
app.py CHANGED
@@ -1,17 +1,17 @@
1
  import os
2
  import json
3
  import uuid
 
4
  from datetime import datetime
5
  from flask import Flask, request, Response, jsonify
6
  import socketio
7
  import requests
8
  import logging
9
- from threading import Event, Timer
10
  import re
11
 
12
  app = Flask(__name__)
13
 
14
- # 自定义日志格式化器
15
  class CustomFormatter(logging.Formatter):
16
  def format(self, record):
17
  log_data = {
@@ -38,18 +38,11 @@ def setup_logging():
38
 
39
  logger = logging.getLogger(__name__)
40
 
41
- # 从环境变量中获取API密钥
42
  API_KEY = os.environ.get('PPLX_KEY')
43
-
44
- # 代理设置
45
  proxy_url = os.environ.get('PROXY_URL')
46
 
47
- # 设置代理
48
  if proxy_url:
49
- proxies = {
50
- 'http': proxy_url,
51
- 'https': proxy_url
52
- }
53
  transport = requests.Session()
54
  transport.proxies.update(proxies)
55
  else:
@@ -57,12 +50,8 @@ else:
57
 
58
  sio = socketio.Client(http_session=transport, logger=False, engineio_logger=False)
59
 
60
- # 连接选项
61
- connect_opts = {
62
- 'transports': ['websocket', 'polling'],
63
- }
64
 
65
- # 其他选项
66
  sio_opts = {
67
  'extraHeaders': {
68
  'Cookie': os.environ.get('PPLX_COOKIE'),
@@ -106,8 +95,7 @@ def calculate_tokens(text):
106
  if re.search(r'[^\x00-\x7F]', text):
107
  return len(text)
108
  else:
109
- tokens = text.split()
110
- return len(tokens)
111
 
112
  def create_event(event, data):
113
  if isinstance(data, dict):
@@ -129,8 +117,8 @@ def root():
129
  },
130
  "body": {
131
  "messages": "Array of message objects",
132
- "stream": "Boolean (true for streaming response)",
133
- "model": "Model to be used (optional, defaults to claude-3-opus-20240229)"
134
  }
135
  }
136
  }
@@ -152,7 +140,6 @@ def messages():
152
 
153
  msg_id = str(uuid.uuid4())
154
  response_event = Event()
155
- timeout_event = Event()
156
  response_text = []
157
  total_output_tokens = 0
158
 
@@ -163,6 +150,9 @@ def messages():
163
 
164
  def generate():
165
  nonlocal total_output_tokens
 
 
 
166
 
167
  def send_event(event_type, data):
168
  event = create_event(event_type, data)
@@ -172,7 +162,6 @@ def messages():
172
  })
173
  yield event
174
 
175
- # Send initial events
176
  yield from send_event("message_start", {
177
  "type": "message_start",
178
  "message": {
@@ -190,7 +179,8 @@ def messages():
190
  yield from send_event("ping", {"type": "ping"})
191
 
192
  def on_query_progress(data):
193
- nonlocal total_output_tokens, response_text
 
194
  if 'text' in data:
195
  text = json.loads(data['text'])
196
  chunk = text['chunks'][-1] if text['chunks'] else None
@@ -243,18 +233,13 @@ def messages():
243
  sio.on('connect', on_connect)
244
  sio.on('query_progress', on_query_progress)
245
 
246
- def timeout_handler():
247
- logger.warning("Request timed out", extra={'event_type': 'request_timeout'})
248
- timeout_event.set()
249
- response_event.set()
250
-
251
- timer = Timer(30, timeout_handler) # 30 seconds timeout
252
- timer.start()
253
-
254
  try:
255
  sio.connect('wss://www.perplexity.ai/', **connect_opts, headers=sio_opts['extraHeaders'])
256
 
257
- while not response_event.is_set() and not timeout_event.is_set():
 
 
 
258
  sio.sleep(0.1)
259
  while response_text:
260
  chunk = response_text.pop(0)
@@ -264,13 +249,22 @@ def messages():
264
  "delta": {"type": "text_delta", "text": chunk},
265
  })
266
 
267
- if timeout_event.is_set():
 
 
 
 
 
 
 
 
 
268
  yield from send_event("content_block_delta", {
269
  "type": "content_block_delta",
270
  "index": 0,
271
- "delta": {"type": "text_delta", "text": "Request timed out"},
272
  })
273
-
274
  except Exception as e:
275
  logger.error(f"Error during socket connection: {str(e)}", exc_info=True)
276
  yield from send_event("content_block_delta", {
@@ -279,11 +273,9 @@ def messages():
279
  "delta": {"type": "text_delta", "text": f"Error during socket connection: {str(e)}"},
280
  })
281
  finally:
282
- timer.cancel()
283
  if sio.connected:
284
  sio.disconnect()
285
 
286
- # Send final events
287
  yield from send_event("content_block_stop", {"type": "content_block_stop", "index": 0})
288
  yield from send_event("message_delta", {
289
  "type": "message_delta",
@@ -304,6 +296,8 @@ def handle_non_stream(previous_messages, msg_id, model, input_tokens):
304
  response_event = Event()
305
  response_text = []
306
  total_output_tokens = 0
 
 
307
 
308
  def on_query_progress(data):
309
  nonlocal total_output_tokens, response_text
@@ -314,6 +308,14 @@ def handle_non_stream(previous_messages, msg_id, model, input_tokens):
314
  response_text.append(chunk)
315
  chunk_tokens = calculate_tokens(chunk)
316
  total_output_tokens += chunk_tokens
 
 
 
 
 
 
 
 
317
 
318
  if data.get('final', False):
319
  response_event.set()
@@ -342,11 +344,18 @@ def handle_non_stream(previous_messages, msg_id, model, input_tokens):
342
  sio.connect('wss://www.perplexity.ai/', **connect_opts, headers=sio_opts['extraHeaders'])
343
 
344
  # Wait for response with timeout
345
- response_event.wait(timeout=30)
346
 
347
  if not response_text:
348
- logger.warning("No response received (non-stream)", extra={'event_type': 'no_response_non_stream'})
349
- return jsonify({"error": "No response received"}), 504
 
 
 
 
 
 
 
350
 
351
  full_response = {
352
  "content": [{"text": ''.join(response_text), "type": "text"}],
@@ -363,11 +372,14 @@ def handle_non_stream(previous_messages, msg_id, model, input_tokens):
363
  }
364
  logger.info("Sending non-stream response", extra={
365
  'event_type': 'non_stream_response',
366
- 'data': {'content': full_response}
 
 
 
367
  })
368
  return Response(json.dumps(full_response, ensure_ascii=False), content_type='application/json')
369
 
370
- except Exception as e:
371
  logger.error(f"Error during non-stream socket connection: {str(e)}", exc_info=True)
372
  return jsonify({"error": str(e)}), 500
373
  finally:
@@ -394,4 +406,5 @@ if __name__ == '__main__':
394
  })
395
  if not API_KEY:
396
  logger.warning("PPLX_KEY environment variable is not set", extra={'event_type': 'config_warning'})
397
- app.run(host='0.0.0.0', port=port)
 
 
1
  import os
2
  import json
3
  import uuid
4
+ import time
5
  from datetime import datetime
6
  from flask import Flask, request, Response, jsonify
7
  import socketio
8
  import requests
9
  import logging
10
+ from threading import Event
11
  import re
12
 
13
  app = Flask(__name__)
14
 
 
15
  class CustomFormatter(logging.Formatter):
16
  def format(self, record):
17
  log_data = {
 
38
 
39
  logger = logging.getLogger(__name__)
40
 
 
41
  API_KEY = os.environ.get('PPLX_KEY')
 
 
42
  proxy_url = os.environ.get('PROXY_URL')
43
 
 
44
  if proxy_url:
45
+ proxies = {'http': proxy_url, 'https': proxy_url}
 
 
 
46
  transport = requests.Session()
47
  transport.proxies.update(proxies)
48
  else:
 
50
 
51
  sio = socketio.Client(http_session=transport, logger=False, engineio_logger=False)
52
 
53
+ connect_opts = {'transports': ['websocket', 'polling']}
 
 
 
54
 
 
55
  sio_opts = {
56
  'extraHeaders': {
57
  'Cookie': os.environ.get('PPLX_COOKIE'),
 
95
  if re.search(r'[^\x00-\x7F]', text):
96
  return len(text)
97
  else:
98
+ return len(text.split())
 
99
 
100
  def create_event(event, data):
101
  if isinstance(data, dict):
 
117
  },
118
  "body": {
119
  "messages": "Array of message objects",
120
+ "stream": "Boolean (optional, defaults to false)",
121
+ "model": "Model to be used (optional, defaults to claude-3-5-sonnet-20240620)"
122
  }
123
  }
124
  }
 
140
 
141
  msg_id = str(uuid.uuid4())
142
  response_event = Event()
 
143
  response_text = []
144
  total_output_tokens = 0
145
 
 
150
 
151
  def generate():
152
  nonlocal total_output_tokens
153
+ start_time = time.time()
154
+ last_activity_time = start_time
155
+ timeout = max(60, input_tokens / 1000) # 动态设置超时时间,最少60秒
156
 
157
  def send_event(event_type, data):
158
  event = create_event(event_type, data)
 
162
  })
163
  yield event
164
 
 
165
  yield from send_event("message_start", {
166
  "type": "message_start",
167
  "message": {
 
179
  yield from send_event("ping", {"type": "ping"})
180
 
181
  def on_query_progress(data):
182
+ nonlocal total_output_tokens, response_text, last_activity_time
183
+ last_activity_time = time.time()
184
  if 'text' in data:
185
  text = json.loads(data['text'])
186
  chunk = text['chunks'][-1] if text['chunks'] else None
 
233
  sio.on('connect', on_connect)
234
  sio.on('query_progress', on_query_progress)
235
 
 
 
 
 
 
 
 
 
236
  try:
237
  sio.connect('wss://www.perplexity.ai/', **connect_opts, headers=sio_opts['extraHeaders'])
238
 
239
+ while not response_event.is_set() and (time.time() - start_time) < timeout:
240
+ current_time = time.time()
241
+ if current_time - last_activity_time > 10: # 如果10秒内没有活动,记录警告
242
+ logger.warning("No activity for 10 seconds", extra={'event_type': 'inactivity_warning'})
243
  sio.sleep(0.1)
244
  while response_text:
245
  chunk = response_text.pop(0)
 
249
  "delta": {"type": "text_delta", "text": chunk},
250
  })
251
 
252
+ if not response_event.is_set():
253
+ logger.warning(f"Request timed out after {timeout} seconds", extra={
254
+ 'event_type': 'request_timeout',
255
+ 'data': {
256
+ 'timeout': timeout,
257
+ 'input_tokens': input_tokens,
258
+ 'output_tokens': total_output_tokens,
259
+ 'elapsed_time': time.time() - start_time
260
+ }
261
+ })
262
  yield from send_event("content_block_delta", {
263
  "type": "content_block_delta",
264
  "index": 0,
265
+ "delta": {"type": "text_delta", "text": f"Request timed out after {timeout} seconds"},
266
  })
267
+
268
  except Exception as e:
269
  logger.error(f"Error during socket connection: {str(e)}", exc_info=True)
270
  yield from send_event("content_block_delta", {
 
273
  "delta": {"type": "text_delta", "text": f"Error during socket connection: {str(e)}"},
274
  })
275
  finally:
 
276
  if sio.connected:
277
  sio.disconnect()
278
 
 
279
  yield from send_event("content_block_stop", {"type": "content_block_stop", "index": 0})
280
  yield from send_event("message_delta", {
281
  "type": "message_delta",
 
296
  response_event = Event()
297
  response_text = []
298
  total_output_tokens = 0
299
+ start_time = time.time()
300
+ timeout = max(60, input_tokens / 1000) # 动态设置超时时间,最少60秒
301
 
302
  def on_query_progress(data):
303
  nonlocal total_output_tokens, response_text
 
308
  response_text.append(chunk)
309
  chunk_tokens = calculate_tokens(chunk)
310
  total_output_tokens += chunk_tokens
311
+ logger.info("Received chunk (non-stream)", extra={
312
+ 'event_type': 'chunk_received_non_stream',
313
+ 'data': {
314
+ 'chunk': chunk,
315
+ 'tokens': chunk_tokens,
316
+ 'total_tokens': total_output_tokens
317
+ }
318
+ })
319
 
320
  if data.get('final', False):
321
  response_event.set()
 
344
  sio.connect('wss://www.perplexity.ai/', **connect_opts, headers=sio_opts['extraHeaders'])
345
 
346
  # Wait for response with timeout
347
+ response_event.wait(timeout=timeout)
348
 
349
  if not response_text:
350
+ logger.warning(f"No response received (non-stream) after {timeout} seconds", extra={
351
+ 'event_type': 'no_response_non_stream',
352
+ 'data': {
353
+ 'timeout': timeout,
354
+ 'input_tokens': input_tokens,
355
+ 'elapsed_time': time.time() - start_time
356
+ }
357
+ })
358
+ return jsonify({"error": f"No response received after {timeout} seconds"}), 504
359
 
360
  full_response = {
361
  "content": [{"text": ''.join(response_text), "type": "text"}],
 
372
  }
373
  logger.info("Sending non-stream response", extra={
374
  'event_type': 'non_stream_response',
375
+ 'data': {
376
+ 'content': full_response,
377
+ 'elapsed_time': time.time() - start_time
378
+ }
379
  })
380
  return Response(json.dumps(full_response, ensure_ascii=False), content_type='application/json')
381
 
382
+ except Exception as e:
383
  logger.error(f"Error during non-stream socket connection: {str(e)}", exc_info=True)
384
  return jsonify({"error": str(e)}), 500
385
  finally:
 
406
  })
407
  if not API_KEY:
408
  logger.warning("PPLX_KEY environment variable is not set", extra={'event_type': 'config_warning'})
409
+ app.run(host='0.0.0.0', port=port)
410
+