Update app.py
Browse files
app.py
CHANGED
@@ -9,8 +9,29 @@ import logging
|
|
9 |
from threading import Event
|
10 |
import re
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
app = Flask(__name__)
|
13 |
-
logging.
|
14 |
|
15 |
# 从环境变量中获取API密钥
|
16 |
API_KEY = os.environ.get('PPLX_KEY')
|
@@ -29,7 +50,7 @@ if proxy_url:
|
|
29 |
else:
|
30 |
transport = None
|
31 |
|
32 |
-
sio = socketio.Client(http_session=transport, logger=
|
33 |
|
34 |
# 连接选项
|
35 |
connect_opts = {
|
@@ -48,8 +69,14 @@ sio_opts = {
|
|
48 |
}
|
49 |
|
50 |
def log_request(ip, route, status):
|
51 |
-
|
52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
def validate_api_key():
|
55 |
api_key = request.headers.get('x-api-key')
|
@@ -154,12 +181,26 @@ def messages():
|
|
154 |
response_text.append(chunk)
|
155 |
chunk_tokens = calculate_tokens(chunk)
|
156 |
total_output_tokens += chunk_tokens
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
|
158 |
if data.get('final', False):
|
|
|
|
|
|
|
|
|
|
|
|
|
159 |
response_event.set()
|
160 |
|
161 |
def on_connect():
|
162 |
-
|
163 |
emit_data = {
|
164 |
"version": "2.9",
|
165 |
"source": "default",
|
@@ -175,6 +216,12 @@ def messages():
|
|
175 |
"query_source": "home"
|
176 |
}
|
177 |
sio.emit('perplexity_ask', (previous_messages, emit_data))
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
sio.on('connect', on_connect)
|
180 |
sio.on('query_progress', on_query_progress)
|
@@ -193,7 +240,10 @@ def messages():
|
|
193 |
})
|
194 |
|
195 |
except Exception as e:
|
196 |
-
|
|
|
|
|
|
|
197 |
yield create_event("content_block_delta", {
|
198 |
"type": "content_block_delta",
|
199 |
"index": 0,
|
@@ -214,7 +264,10 @@ def messages():
|
|
214 |
return Response(generate(), content_type='text/event-stream')
|
215 |
|
216 |
except Exception as e:
|
217 |
-
|
|
|
|
|
|
|
218 |
log_request(request.remote_addr, request.path, 400)
|
219 |
return jsonify({"error": str(e)}), 400
|
220 |
|
@@ -238,7 +291,7 @@ def handle_non_stream(previous_messages, msg_id, model, input_tokens):
|
|
238 |
response_event.set()
|
239 |
|
240 |
def on_connect():
|
241 |
-
|
242 |
emit_data = {
|
243 |
"version": "2.9",
|
244 |
"source": "default",
|
@@ -278,7 +331,10 @@ def handle_non_stream(previous_messages, msg_id, model, input_tokens):
|
|
278 |
return Response(json.dumps(full_response, ensure_ascii=False), content_type='application/json')
|
279 |
|
280 |
except Exception as e:
|
281 |
-
|
|
|
|
|
|
|
282 |
return jsonify({"error": str(e)}), 500
|
283 |
finally:
|
284 |
if sio.connected:
|
@@ -291,13 +347,20 @@ def not_found(error):
|
|
291 |
|
292 |
@app.errorhandler(500)
|
293 |
def server_error(error):
|
294 |
-
|
|
|
|
|
|
|
295 |
log_request(request.remote_addr, request.path, 500)
|
296 |
return "Something broke!", 500
|
297 |
|
298 |
if __name__ == '__main__':
|
|
|
299 |
port = int(os.environ.get('PORT', 8081))
|
300 |
-
|
|
|
|
|
|
|
301 |
if not API_KEY:
|
302 |
-
|
303 |
-
app.run(host='0.0.0.0', port=port)
|
|
|
9 |
from threading import Event
|
10 |
import re
|
11 |
|
12 |
+
# 自定义日志格式化器
|
13 |
+
class CustomFormatter(logging.Formatter):
|
14 |
+
def format(self, record):
|
15 |
+
log_data = {
|
16 |
+
"timestamp": self.formatTime(record, self.datefmt),
|
17 |
+
"level": record.levelname,
|
18 |
+
"message": record.getMessage(),
|
19 |
+
}
|
20 |
+
if hasattr(record, 'event_type'):
|
21 |
+
log_data['event_type'] = record.event_type
|
22 |
+
if hasattr(record, 'data'):
|
23 |
+
log_data['data'] = record.data
|
24 |
+
return json.dumps(log_data, ensure_ascii=False, indent=2)
|
25 |
+
|
26 |
+
def setup_logging():
|
27 |
+
logger = logging.getLogger()
|
28 |
+
logger.setLevel(logging.INFO)
|
29 |
+
handler = logging.StreamHandler()
|
30 |
+
handler.setFormatter(CustomFormatter())
|
31 |
+
logger.addHandler(handler)
|
32 |
+
|
33 |
app = Flask(__name__)
|
34 |
+
logger = logging.getLogger(__name__)
|
35 |
|
36 |
# 从环境变量中获取API密钥
|
37 |
API_KEY = os.environ.get('PPLX_KEY')
|
|
|
50 |
else:
|
51 |
transport = None
|
52 |
|
53 |
+
sio = socketio.Client(http_session=transport, logger=False, engineio_logger=False)
|
54 |
|
55 |
# 连接选项
|
56 |
connect_opts = {
|
|
|
69 |
}
|
70 |
|
71 |
def log_request(ip, route, status):
|
72 |
+
logger.info(f"HTTP Request", extra={
|
73 |
+
'event_type': 'http_request',
|
74 |
+
'data': {
|
75 |
+
'ip': ip,
|
76 |
+
'route': route,
|
77 |
+
'status': status
|
78 |
+
}
|
79 |
+
})
|
80 |
|
81 |
def validate_api_key():
|
82 |
api_key = request.headers.get('x-api-key')
|
|
|
181 |
response_text.append(chunk)
|
182 |
chunk_tokens = calculate_tokens(chunk)
|
183 |
total_output_tokens += chunk_tokens
|
184 |
+
logger.info("Received chunk", extra={
|
185 |
+
'event_type': 'chunk_received',
|
186 |
+
'data': {
|
187 |
+
'chunk': chunk,
|
188 |
+
'tokens': chunk_tokens,
|
189 |
+
'total_tokens': total_output_tokens
|
190 |
+
}
|
191 |
+
})
|
192 |
|
193 |
if data.get('final', False):
|
194 |
+
logger.info("Final response received", extra={
|
195 |
+
'event_type': 'response_complete',
|
196 |
+
'data': {
|
197 |
+
'total_tokens': total_output_tokens
|
198 |
+
}
|
199 |
+
})
|
200 |
response_event.set()
|
201 |
|
202 |
def on_connect():
|
203 |
+
logger.info("Connected to Perplexity AI", extra={'event_type': 'connection_established'})
|
204 |
emit_data = {
|
205 |
"version": "2.9",
|
206 |
"source": "default",
|
|
|
216 |
"query_source": "home"
|
217 |
}
|
218 |
sio.emit('perplexity_ask', (previous_messages, emit_data))
|
219 |
+
logger.info("Sent query to Perplexity AI", extra={
|
220 |
+
'event_type': 'query_sent',
|
221 |
+
'data': {
|
222 |
+
'message': previous_messages[:100] + '...' if len(previous_messages) > 100 else previous_messages
|
223 |
+
}
|
224 |
+
})
|
225 |
|
226 |
sio.on('connect', on_connect)
|
227 |
sio.on('query_progress', on_query_progress)
|
|
|
240 |
})
|
241 |
|
242 |
except Exception as e:
|
243 |
+
logger.error(f"Error during socket connection", extra={
|
244 |
+
'event_type': 'connection_error',
|
245 |
+
'data': {'error': str(e)}
|
246 |
+
})
|
247 |
yield create_event("content_block_delta", {
|
248 |
"type": "content_block_delta",
|
249 |
"index": 0,
|
|
|
264 |
return Response(generate(), content_type='text/event-stream')
|
265 |
|
266 |
except Exception as e:
|
267 |
+
logger.error(f"Request error", extra={
|
268 |
+
'event_type': 'request_error',
|
269 |
+
'data': {'error': str(e)}
|
270 |
+
})
|
271 |
log_request(request.remote_addr, request.path, 400)
|
272 |
return jsonify({"error": str(e)}), 400
|
273 |
|
|
|
291 |
response_event.set()
|
292 |
|
293 |
def on_connect():
|
294 |
+
logger.info("Connected to Perplexity AI (non-stream)", extra={'event_type': 'connection_established_non_stream'})
|
295 |
emit_data = {
|
296 |
"version": "2.9",
|
297 |
"source": "default",
|
|
|
331 |
return Response(json.dumps(full_response, ensure_ascii=False), content_type='application/json')
|
332 |
|
333 |
except Exception as e:
|
334 |
+
logger.error(f"Error during non-stream socket connection", extra={
|
335 |
+
'event_type': 'non_stream_connection_error',
|
336 |
+
'data': {'error': str(e)}
|
337 |
+
})
|
338 |
return jsonify({"error": str(e)}), 500
|
339 |
finally:
|
340 |
if sio.connected:
|
|
|
347 |
|
348 |
@app.errorhandler(500)
|
349 |
def server_error(error):
|
350 |
+
logger.error(f"Server error", extra={
|
351 |
+
'event_type': 'server_error',
|
352 |
+
'data': {'error': str(error)}
|
353 |
+
})
|
354 |
log_request(request.remote_addr, request.path, 500)
|
355 |
return "Something broke!", 500
|
356 |
|
357 |
if __name__ == '__main__':
|
358 |
+
setup_logging()
|
359 |
port = int(os.environ.get('PORT', 8081))
|
360 |
+
logger.info(f"Perplexity proxy starting", extra={
|
361 |
+
'event_type': 'server_start',
|
362 |
+
'data': {'port': port}
|
363 |
+
})
|
364 |
if not API_KEY:
|
365 |
+
logger.warning("PPLX_KEY environment variable is not set", extra={'event_type': 'config_warning'})
|
366 |
+
app.run(host='0.0.0.0', port=port)
|