smgc commited on
Commit
67440e8
1 Parent(s): dba8e6a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -76
app.py CHANGED
@@ -1,37 +1,52 @@
1
  import os
2
  import json
3
  import uuid
4
- from flask import Flask, request, Response, jsonify, stream_with_context
5
- from flask_limiter import Limiter
6
- from flask_limiter.util import get_remote_address
7
  import socketio
8
- import requests
9
- from requests.exceptions import RequestException
10
 
11
  app = Flask(__name__)
 
12
 
13
- # 从环境变量中获取配置
14
  API_KEY = os.environ.get('PPLX_KEY')
15
- PPLX_COOKIE = os.environ.get('PPLX_COOKIE')
16
- USER_AGENT = os.environ.get('USER_AGENT')
17
- PROXY = os.environ.get('PROXY')
18
-
19
- # 设置限流
20
- limiter = Limiter(
21
- get_remote_address,
22
- app=app,
23
- default_limits=["100 per 5 minutes"],
24
- storage_uri="memory://"
25
- )
26
-
27
- # Socket.IO 客户端设置
28
- sio = socketio.Client()
29
 
30
  # 代理设置
31
- proxies = {'https': PROXY} if PROXY else None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  @app.route('/')
34
- def home():
 
35
  return jsonify({
36
  "message": "Welcome to the Perplexity AI Proxy API",
37
  "endpoints": {
@@ -50,25 +65,16 @@ def home():
50
  }
51
  })
52
 
53
- @app.route('/health')
54
- def health_check():
55
- return jsonify({"status": "OK"}), 200
56
-
57
- def validate_api_key():
58
- api_key = request.headers.get('x-api-key')
59
- if api_key != API_KEY:
60
- return jsonify({"error": "Invalid API key"}), 401
61
-
62
  @app.route('/ai/v1/messages', methods=['POST'])
63
- @limiter.limit("100 per 15 minutes")
64
- def ai_messages():
65
- auth_result = validate_api_key()
66
- if auth_result:
67
- return auth_result
68
 
69
  try:
70
- data = request.json
71
- if not data.get('stream', False):
 
72
  return jsonify({
73
  "id": str(uuid.uuid4()),
74
  "content": [
@@ -80,9 +86,9 @@ def ai_messages():
80
  "stop_sequence": "string",
81
  "usage": {"input_tokens": 0, "output_tokens": 0}
82
  })
83
-
84
  def generate():
85
- previous_messages = "\n\n".join([msg['content'] for msg in data['messages']])
86
  msg_id = str(uuid.uuid4())
87
 
88
  yield create_event("message_start", {
@@ -101,14 +107,8 @@ def ai_messages():
101
  yield create_event("content_block_start", {"type": "content_block_start", "index": 0, "content_block": {"type": "text", "text": ""}})
102
  yield create_event("ping", {"type": "ping"})
103
 
104
- try:
105
- sio.connect('wss://www.perplexity.ai', transports=['websocket'],
106
- headers={
107
- 'Cookie': PPLX_COOKIE,
108
- 'User-Agent': USER_AGENT
109
- },
110
- http_session=requests.Session() if PROXY else None,
111
- proxies=proxies)
112
  sio.emit('perplexity_ask', previous_messages, {
113
  "version": "2.9",
114
  "source": "default",
@@ -126,29 +126,42 @@ def ai_messages():
126
  "query_source": "home"
127
  })
128
 
129
- @sio.on('query_progress')
130
- def on_query_progress(data):
131
- if data.get('text'):
132
- text = json.loads(data['text'])
133
- chunk = text['chunks'][-1] if text['chunks'] else None
134
- if chunk:
135
- yield create_event("content_block_delta", {
136
- "type": "content_block_delta",
137
- "index": 0,
138
- "delta": {"type": "text_delta", "text": chunk},
139
- })
140
-
141
- sio.wait()
142
-
143
- except Exception as e:
144
- print(f"Socket error: {e}")
 
 
 
145
  yield create_event("content_block_delta", {
146
  "type": "content_block_delta",
147
  "index": 0,
148
- "delta": {"type": "text_delta", "text": "An error occurred while processing your request"},
 
 
 
 
 
 
149
  })
150
- finally:
151
- sio.disconnect()
 
 
 
 
152
 
153
  yield create_event("content_block_stop", {"type": "content_block_stop", "index": 0})
154
  yield create_event("message_delta", {
@@ -157,26 +170,34 @@ def ai_messages():
157
  "usage": {"output_tokens": 12},
158
  })
159
  yield create_event("message_stop", {"type": "message_stop"})
 
160
 
161
- return Response(stream_with_context(generate()), content_type='text/event-stream')
162
 
163
  except Exception as e:
164
- print(f"Request error: {e}")
 
165
  return jsonify({"error": str(e)}), 400
166
 
167
- def create_event(event, data):
168
- if isinstance(data, dict):
169
- data = json.dumps(data)
170
- return f"event: {event}\ndata: {data}\n\n"
171
-
172
  @app.errorhandler(404)
173
  def not_found(error):
174
- return jsonify({"error": "Not Found"}), 404
 
175
 
176
  @app.errorhandler(500)
177
  def server_error(error):
178
- return jsonify({"error": "Internal Server Error"}), 500
 
 
 
 
 
 
 
179
 
180
  if __name__ == '__main__':
181
  port = int(os.environ.get('PORT', 8081))
 
 
 
182
  app.run(host='0.0.0.0', port=port)
 
1
  import os
2
  import json
3
  import uuid
4
+ from flask import Flask, request, Response, jsonify
 
 
5
  import socketio
6
+ from aiohttp import web
7
+ from aiohttp_socks import ProxyConnector
8
 
9
  app = Flask(__name__)
10
+ sio = socketio.Client()
11
 
12
+ # 从环境变量中获取API密钥
13
  API_KEY = os.environ.get('PPLX_KEY')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  # 代理设置
16
+ proxy_url = os.environ.get('PROXY_URL')
17
+ connector = ProxyConnector.from_url(proxy_url) if proxy_url else None
18
+
19
+ sio_opts = {
20
+ 'auth': {
21
+ 'jwt': 'anonymous-ask-user',
22
+ },
23
+ 'reconnection': False,
24
+ 'transports': ['websocket'],
25
+ 'extraHeaders': {
26
+ 'Cookie': os.environ.get('PPLX_COOKIE'),
27
+ 'User-Agent': os.environ.get('USER_AGENT'),
28
+ 'Accept': '*/*',
29
+ 'priority': 'u=1, i',
30
+ 'Referer': 'https://www.perplexity.ai/',
31
+ }
32
+ }
33
+
34
+ def log_request(req, status):
35
+ timestamp = datetime.now().isoformat()
36
+ ip = req.remote_addr
37
+ route = req.path
38
+ print(f"{timestamp} - {ip} - {route} - {status}")
39
+
40
+ def validate_api_key():
41
+ api_key = request.headers.get('x-api-key')
42
+ if api_key != API_KEY:
43
+ log_request(request, 401)
44
+ return jsonify({"error": "Invalid API key"}), 401
45
+ return None
46
 
47
  @app.route('/')
48
+ def root():
49
+ log_request(request, 200)
50
  return jsonify({
51
  "message": "Welcome to the Perplexity AI Proxy API",
52
  "endpoints": {
 
65
  }
66
  })
67
 
 
 
 
 
 
 
 
 
 
68
  @app.route('/ai/v1/messages', methods=['POST'])
69
+ def messages():
70
+ auth_error = validate_api_key()
71
+ if auth_error:
72
+ return auth_error
 
73
 
74
  try:
75
+ json_body = request.json
76
+ if not json_body.get('stream', False):
77
+ log_request(request, 200)
78
  return jsonify({
79
  "id": str(uuid.uuid4()),
80
  "content": [
 
86
  "stop_sequence": "string",
87
  "usage": {"input_tokens": 0, "output_tokens": 0}
88
  })
89
+
90
  def generate():
91
+ previous_messages = "\n\n".join([msg['content'] for msg in json_body['messages']])
92
  msg_id = str(uuid.uuid4())
93
 
94
  yield create_event("message_start", {
 
107
  yield create_event("content_block_start", {"type": "content_block_start", "index": 0, "content_block": {"type": "text", "text": ""}})
108
  yield create_event("ping", {"type": "ping"})
109
 
110
+ @sio.on('connect')
111
+ def on_connect():
 
 
 
 
 
 
112
  sio.emit('perplexity_ask', previous_messages, {
113
  "version": "2.9",
114
  "source": "default",
 
126
  "query_source": "home"
127
  })
128
 
129
+ @sio.on('query_progress')
130
+ def on_query_progress(data):
131
+ if 'text' in data:
132
+ text = json.loads(data['text'])
133
+ chunk = text['chunks'][-1] if text['chunks'] else None
134
+ if chunk:
135
+ yield create_event("content_block_delta", {
136
+ "type": "content_block_delta",
137
+ "index": 0,
138
+ "delta": {"type": "text_delta", "text": chunk},
139
+ })
140
+
141
+ @sio.on('disconnect')
142
+ def on_disconnect():
143
+ print(" > [Disconnected]")
144
+
145
+ @sio.on('error')
146
+ def on_error(error):
147
+ print(f"Socket error: {error}")
148
  yield create_event("content_block_delta", {
149
  "type": "content_block_delta",
150
  "index": 0,
151
+ "delta": {"type": "text_delta", "text": "Error occurred while fetching output 输出时出现错误\nPlease refer to the log for more information 请查看日志以获取更多信息"},
152
+ })
153
+ yield create_event("content_block_stop", {"type": "content_block_stop", "index": 0})
154
+ yield create_event("message_delta", {
155
+ "type": "message_delta",
156
+ "delta": {"stop_reason": "end_turn", "stop_sequence": None},
157
+ "usage": {"output_tokens": 12},
158
  })
159
+ yield create_event("message_stop", {"type": "message_stop"})
160
+ log_request(request, 500)
161
+
162
+ sio.connect('wss://www.perplexity.ai/', **sio_opts)
163
+ sio.wait()
164
+ sio.disconnect()
165
 
166
  yield create_event("content_block_stop", {"type": "content_block_stop", "index": 0})
167
  yield create_event("message_delta", {
 
170
  "usage": {"output_tokens": 12},
171
  })
172
  yield create_event("message_stop", {"type": "message_stop"})
173
+ log_request(request, 200)
174
 
175
+ return Response(generate(), content_type='text/event-stream')
176
 
177
  except Exception as e:
178
+ print(f"Request error: {str(e)}")
179
+ log_request(request, 400)
180
  return jsonify({"error": str(e)}), 400
181
 
 
 
 
 
 
182
  @app.errorhandler(404)
183
  def not_found(error):
184
+ log_request(request, 404)
185
+ return "Not Found", 404
186
 
187
  @app.errorhandler(500)
188
  def server_error(error):
189
+ print(f"Server error: {str(error)}")
190
+ log_request(request, 500)
191
+ return "Something broke!", 500
192
+
193
+ def create_event(event, data):
194
+ if isinstance(data, dict):
195
+ data = json.dumps(data)
196
+ return f"event: {event}\ndata: {data}\n\n"
197
 
198
  if __name__ == '__main__':
199
  port = int(os.environ.get('PORT', 8081))
200
+ print(f"Perplexity proxy listening on port {port}")
201
+ if not API_KEY:
202
+ print("Warning: PPLX_KEY environment variable is not set. API key validation will fail.")
203
  app.run(host='0.0.0.0', port=port)