KBYKB commited on
Commit
7059faa
·
verified ·
1 Parent(s): 4942697

Upload 8 files

Browse files
Files changed (8) hide show
  1. .gitignore +5 -0
  2. README.md +11 -10
  3. docker-build.sh +1 -0
  4. index.js +257 -0
  5. package.json +17 -0
  6. start.bat +6 -0
  7. start.sh +6 -0
  8. usage.md +57 -0
.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ node_modules
2
+ package-lock.json
3
+ .vscode
4
+ config
5
+ test.js
README.md CHANGED
@@ -1,10 +1,11 @@
1
- ---
2
- title: T1
3
- emoji: 👀
4
- colorFrom: green
5
- colorTo: indigo
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
+ # PPLX-Proxy
2
+
3
+ A proxy for Perplexity AI
4
+
5
+ Perplexity 转换为 Anthropic 格式的通用代理。
6
+
7
+ [**Usage 使用方法**](usage.md)
8
+
9
+ **It is forbidden to use this project for profit.**
10
+
11
+ **仅供个人部署用于访问自己合法取得的订阅,严禁用于转售或其他商业用途。不提供任何技术支持、不为任何违规使用导致的封号负责。**
docker-build.sh ADDED
@@ -0,0 +1 @@
 
 
1
+ docker build . -t 'archeb/pplx-proxy'
index.js ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const express = require("express");
2
+ const { io } = require("socket.io-client");
3
+ const { v4: uuidv4 } = require("uuid");
4
+ const { ProxyAgent } = require("proxy-agent");
5
+ const agent = new ProxyAgent();
6
+
7
+ const app = express();
8
+ const port = process.env.PORT || 8081;
9
+
10
+ var opts = {
11
+ agent: agent,
12
+ auth: {
13
+ jwt: "anonymous-ask-user",
14
+ },
15
+ reconnection: false,
16
+ transports: ["websocket"],
17
+ path: "/socket.io",
18
+ hostname: "www.perplexity.ai",
19
+ secure: true,
20
+ port: "443",
21
+ extraHeaders: {
22
+ Cookie: process.env.PPLX_COOKIE,
23
+ "User-Agent": process.env.USER_AGENT,
24
+ Accept: "*/*",
25
+ priority: "u=1, i",
26
+ Referer: "https://www.perplexity.ai/",
27
+ },
28
+ };
29
+
30
+ app.post("/v1/messages", (req, res) => {
31
+ req.rawBody = "";
32
+ req.setEncoding("utf8");
33
+
34
+ req.on("data", function (chunk) {
35
+ req.rawBody += chunk;
36
+ });
37
+
38
+ req.on("end", async () => {
39
+ res.setHeader("Content-Type", "text/event-stream;charset=utf-8");
40
+ try {
41
+ let jsonBody = JSON.parse(req.rawBody);
42
+ if (jsonBody.stream == false) {
43
+ res.send(
44
+ JSON.stringify({
45
+ id: uuidv4(),
46
+ content: [
47
+ {
48
+ text: "Please turn on streaming.",
49
+ },
50
+ {
51
+ id: "string",
52
+ name: "string",
53
+ input: {},
54
+ },
55
+ ],
56
+ model: "string",
57
+ stop_reason: "end_turn",
58
+ stop_sequence: "string",
59
+ usage: {
60
+ input_tokens: 0,
61
+ output_tokens: 0,
62
+ },
63
+ })
64
+ );
65
+ } else if (jsonBody.stream == true) {
66
+ // 计算用户消息长度
67
+ let userMessage = [{ question: "", answer: "" }];
68
+ let userQuery = "";
69
+ let lastUpdate = true;
70
+ if (jsonBody.system) {
71
+ // 把系统消息加入messages的首条
72
+ jsonBody.messages.unshift({ role: "system", content: jsonBody.system });
73
+ }
74
+ console.log(jsonBody.messages);
75
+ jsonBody.messages.forEach((msg) => {
76
+ if (msg.role == "system" || msg.role == "user") {
77
+ if (lastUpdate) {
78
+ userMessage[userMessage.length - 1].question += msg.content + "\n";
79
+ } else if (userMessage[userMessage.length - 1].question == "") {
80
+ userMessage[userMessage.length - 1].question += msg.content + "\n";
81
+ } else {
82
+ userMessage.push({ question: msg.content + "\n", answer: "" });
83
+ }
84
+ lastUpdate = true;
85
+ } else if (msg.role == "assistant") {
86
+ if (!lastUpdate) {
87
+ userMessage[userMessage.length - 1].answer += msg.content + "\n";
88
+ } else if (userMessage[userMessage.length - 1].answer == "") {
89
+ userMessage[userMessage.length - 1].answer += msg.content + "\n";
90
+ } else {
91
+ userMessage.push({ question: "", answer: msg.content + "\n" });
92
+ }
93
+ lastUpdate = false;
94
+ }
95
+ });
96
+ // user message to plaintext
97
+ let previousMessages = jsonBody.messages
98
+ .map((msg) => {
99
+ return msg.content
100
+ })
101
+ .join("\n\n");
102
+
103
+ let msgid = uuidv4();
104
+ // send message start
105
+ res.write(
106
+ createEvent("message_start", {
107
+ type: "message_start",
108
+ message: {
109
+ id: msgid,
110
+ type: "message",
111
+ role: "assistant",
112
+ content: [],
113
+ model: "claude-3-opus-20240229",
114
+ stop_reason: null,
115
+ stop_sequence: null,
116
+ usage: { input_tokens: 8, output_tokens: 1 },
117
+ },
118
+ })
119
+ );
120
+ res.write(createEvent("content_block_start", { type: "content_block_start", index: 0, content_block: { type: "text", text: "" } }));
121
+ res.write(createEvent("ping", { type: "ping" }));
122
+
123
+ // proxy response
124
+ var socket = io("wss://www.perplexity.ai/", opts);
125
+
126
+ socket.on("connect", function () {
127
+ console.log(" > [Connected]");
128
+ socket
129
+ .emitWithAck("perplexity_ask", previousMessages, {
130
+ "version": "2.9",
131
+ "source": "default",
132
+ "attachments": [],
133
+ "language": "en-GB",
134
+ "timezone": "Europe/London",
135
+ "search_focus": "writing",
136
+ "frontend_uuid": uuidv4(),
137
+ "mode": "concise",
138
+ "is_related_query": false,
139
+ "is_default_related_query": false,
140
+ "visitor_id": uuidv4(),
141
+ "frontend_context_uuid": uuidv4(),
142
+ "prompt_source": "user",
143
+ "query_source": "home"
144
+ })
145
+ .then((response) => {
146
+
147
+ console.log(response);
148
+ res.write(createEvent("content_block_stop", { type: "content_block_stop", index: 0 }));
149
+ res.write(
150
+ createEvent("message_delta", {
151
+ type: "message_delta",
152
+ delta: { stop_reason: "end_turn", stop_sequence: null },
153
+ usage: { output_tokens: 12 },
154
+ })
155
+ );
156
+ res.write(createEvent("message_stop", { type: "message_stop" }));
157
+
158
+ res.end();
159
+ }).catch((error) => {
160
+ if(error.message != "socket has been disconnected"){
161
+ console.log(error);
162
+ }
163
+ });
164
+ });
165
+ socket.onAny((event, ...args) => {
166
+ console.log(`> [got ${event}]`);
167
+ });
168
+ socket.on("query_progress", (data) => {
169
+ if(data.text){
170
+ var text = JSON.parse(data.text)
171
+ var chunk = text.chunks[text.chunks.length - 1];
172
+ if(chunk){
173
+ chunkJSON = JSON.stringify({
174
+ type: "content_block_delta",
175
+ index: 0,
176
+ delta: { type: "text_delta", text: chunk },
177
+ });
178
+ res.write(createEvent("content_block_delta", chunkJSON));
179
+ }
180
+ }
181
+ });
182
+ socket.on("disconnect", function () {
183
+ console.log(" > [Disconnected]");
184
+ });
185
+ socket.on("error", (error) => {
186
+ chunkJSON = JSON.stringify({
187
+ type: "content_block_delta",
188
+ index: 0,
189
+ delta: { type: "text_delta", text: "Error occured while fetching output 输出时出现错误\nPlease refer to the log for more information 请查看日志以获取更多信息" },
190
+ });
191
+ res.write(createEvent("content_block_delta", chunkJSON));
192
+ res.write(createEvent("content_block_stop", { type: "content_block_stop", index: 0 }));
193
+ res.write(
194
+ createEvent("message_delta", {
195
+ type: "message_delta",
196
+ delta: { stop_reason: "end_turn", stop_sequence: null },
197
+ usage: { output_tokens: 12 },
198
+ })
199
+ );
200
+ res.write(createEvent("message_stop", { type: "message_stop" }));
201
+
202
+ res.end();
203
+ console.log(error);
204
+ });
205
+ socket.on("connect_error", function (error) {
206
+ chunkJSON = JSON.stringify({
207
+ type: "content_block_delta",
208
+ index: 0,
209
+ delta: { type: "text_delta", text: "Failed to connect to the Perplexity.ai 连接到Perplexity失败\nPlease refer to the log for more information 请查看日志以获取更多信息" },
210
+ });
211
+ res.write(createEvent("content_block_delta", chunkJSON));
212
+ res.write(createEvent("content_block_stop", { type: "content_block_stop", index: 0 }));
213
+ res.write(
214
+ createEvent("message_delta", {
215
+ type: "message_delta",
216
+ delta: { stop_reason: "end_turn", stop_sequence: null },
217
+ usage: { output_tokens: 12 },
218
+ })
219
+ );
220
+ res.write(createEvent("message_stop", { type: "message_stop" }));
221
+
222
+ res.end();
223
+ console.log(error);
224
+ });
225
+ res.on("close", function () {
226
+ console.log(" > [Client closed]");
227
+ socket.disconnect();
228
+ });
229
+ } else {
230
+ throw new Error("Invalid request");
231
+ }
232
+ } catch (e) {
233
+ console.log(e);
234
+ res.write(JSON.stringify({ error: e.message }));
235
+ res.end();
236
+ return;
237
+ }
238
+ });
239
+ });
240
+
241
+ // handle other
242
+ app.use((req, res, next) => {
243
+ res.status(404).send("Not Found");
244
+ });
245
+
246
+ app.listen(port, () => {
247
+ console.log(`Perplexity proxy listening on port ${port}`);
248
+ });
249
+
250
+ // eventStream util
251
+ function createEvent(event, data) {
252
+ // if data is object, stringify it
253
+ if (typeof data === "object") {
254
+ data = JSON.stringify(data);
255
+ }
256
+ return `event: ${event}\ndata: ${data}\n\n`;
257
+ }
package.json ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "pplx-proxy",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "scripts": {
6
+ "test": "echo \"Error: no test specified\" && exit 1"
7
+ },
8
+ "author": "",
9
+ "license": "ISC",
10
+ "description": "",
11
+ "dependencies": {
12
+ "express": "^4.19.2",
13
+ "proxy-agent": "^6.4.0",
14
+ "socket.io-client": "^4.7.5",
15
+ "uuid": "^9.0.1"
16
+ }
17
+ }
start.bat ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ call npm install
2
+ set PPLX_COOKIE=Your Cookie
3
+ set USER_AGENT=Your User-Agent
4
+ set all_proxy=
5
+ node index
6
+ pause
start.sh ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ npm install
3
+ export PPLX_COOKIE="Your Cookie"
4
+ export USER_AGENT="Your User-Agent"
5
+ export all_proxy=""
6
+ node index
usage.md ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 使用方法
2
+
3
+ 1. 获得一个 Perplexity 账户并且订阅,登录。
4
+
5
+ 2. 打开 F12(DevTools),找到 “Network(网络)”、刷新一下页面,找到“www.perplexity.ai”这个项目
6
+
7
+ 3. 点进去,往下滑找到 "Cookie",完整的复制后面的内容。
8
+
9
+ 4. 用同样的方法找到 "User-Agent",完整的复制后面的内容。
10
+
11
+ 5. 下载或Clone本项目代码,解压
12
+
13
+ 6. 编辑 `start.bat` 文件,把上面的 Cookie 和 User Agent 粘贴进去
14
+
15
+ 7. 启动 start.bat (Linux/macOS用户使用 start.sh)
16
+
17
+ 8. 酒馆中选择 Claude,反向代理地址填 http://127.0.0.1:8081/v1。反代密码必须填,随便什么都可以。
18
+
19
+ 9. 开始使用。如果失败了/没有结果/403/Warning 就多重试几次。
20
+
21
+ # 使用代理
22
+
23
+ 可以使用本地的socks5或http(s)代理。只需在 start.bat 中设置 `all_proxy` 环境变量。
24
+
25
+ 比如,如要使用 Clash 的默认本地SOCKS5代理,则应设置为 `set all_proxy=socks5://127.0.0.1:7890`
26
+
27
+ ## 注意事项
28
+
29
+ 出现 403 错误请重新抓 COOKIE 或者更换代理出口 IP。
30
+
31
+ # Usage
32
+
33
+ 1. Get a Perplexity account and subscribe, log in.
34
+
35
+ 2. Open F12 (DevTools), find “Network”, refresh the page, and find “www.perplexity.ai”.
36
+
37
+ 3. Click on it, scroll down and find “Cookie:”, and copy the entire contents.
38
+
39
+ 4. Find the "user-agnet" in the same way.
40
+
41
+ 5. Download or Clone the code of this project and unzip it.
42
+
43
+ 6. Edit the `start.bat` file and paste the cookie and User Agent into it.
44
+
45
+ 7. Start start.bat
46
+
47
+ 8. Select Claude in the Tavern and put http://127.0.0.1:8081/v1 as the address of the reverse proxy. Use any random string for password.
48
+
49
+ 9. Enjoy it. If it fails/no result/403/Warning, try again.
50
+
51
+ # Use custom proxy
52
+
53
+ Use the `all_proxy` env to set custom proxy. Refer to https://www.npmjs.com/package/proxy-from-env for detail.
54
+
55
+ ## Caution
56
+
57
+ If you get 403 errors, consider getting the cookie again or changing your IP.