Clarzis commited on
Commit
d436736
·
verified ·
1 Parent(s): 9dd7073

Create app.js

Browse files
Files changed (1) hide show
  1. app.js +269 -0
app.js ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ function getAuthKey(req) {
31
+ const authHeader = req.headers['authorization'];
32
+ if (authHeader && authHeader.startsWith('Bearer ')) {
33
+ return authHeader.slice(7);
34
+ }
35
+ return null;
36
+ }
37
+
38
+ app.post("/api/v1/messages", (req, res) => {
39
+ const authKey = getAuthKey(req);
40
+ if (authKey !== process.env.AUTH_KEY) {
41
+ return res.status(401).json({ error: 'Unauthorized' });
42
+ }
43
+ req.rawBody = "";
44
+ req.setEncoding("utf8");
45
+
46
+ req.on("data", function (chunk) {
47
+ req.rawBody += chunk;
48
+ });
49
+
50
+ req.on("end", async () => {
51
+ res.setHeader("Content-Type", "text/event-stream;charset=utf-8");
52
+ try {
53
+ let jsonBody = JSON.parse(req.rawBody);
54
+ if (jsonBody.stream == false) {
55
+ res.send(
56
+ JSON.stringify({
57
+ id: uuidv4(),
58
+ content: [
59
+ {
60
+ text: "Please turn on streaming.",
61
+ },
62
+ {
63
+ id: "string",
64
+ name: "string",
65
+ input: {},
66
+ },
67
+ ],
68
+ model: "string",
69
+ stop_reason: "end_turn",
70
+ stop_sequence: "string",
71
+ usage: {
72
+ input_tokens: 0,
73
+ output_tokens: 0,
74
+ },
75
+ })
76
+ );
77
+ } else if (jsonBody.stream == true) {
78
+ // 计算用户消息长度
79
+ let userMessage = [{ question: "", answer: "" }];
80
+ let userQuery = "";
81
+ let lastUpdate = true;
82
+ if (jsonBody.system) {
83
+ // 把系统消息加入messages的首条
84
+ jsonBody.messages.unshift({ role: "system", content: jsonBody.system });
85
+ }
86
+ console.log(jsonBody.messages);
87
+ jsonBody.messages.forEach((msg) => {
88
+ if (msg.role == "system" || msg.role == "user") {
89
+ if (lastUpdate) {
90
+ userMessage[userMessage.length - 1].question += msg.content + "\n";
91
+ } else if (userMessage[userMessage.length - 1].question == "") {
92
+ userMessage[userMessage.length - 1].question += msg.content + "\n";
93
+ } else {
94
+ userMessage.push({ question: msg.content + "\n", answer: "" });
95
+ }
96
+ lastUpdate = true;
97
+ } else if (msg.role == "assistant") {
98
+ if (!lastUpdate) {
99
+ userMessage[userMessage.length - 1].answer += msg.content + "\n";
100
+ } else if (userMessage[userMessage.length - 1].answer == "") {
101
+ userMessage[userMessage.length - 1].answer += msg.content + "\n";
102
+ } else {
103
+ userMessage.push({ question: "", answer: msg.content + "\n" });
104
+ }
105
+ lastUpdate = false;
106
+ }
107
+ });
108
+ // user message to plaintext
109
+ let previousMessages = jsonBody.messages
110
+ .map((msg) => {
111
+ return msg.content
112
+ })
113
+ .join("\n\n");
114
+
115
+ let msgid = uuidv4();
116
+ // send message start
117
+ res.write(
118
+ createEvent("message_start", {
119
+ type: "message_start",
120
+ message: {
121
+ id: msgid,
122
+ type: "message",
123
+ role: "assistant",
124
+ content: [],
125
+ model: "claude-3-opus-20240229",
126
+ stop_reason: null,
127
+ stop_sequence: null,
128
+ usage: { input_tokens: 8, output_tokens: 1 },
129
+ },
130
+ })
131
+ );
132
+ res.write(createEvent("content_block_start", { type: "content_block_start", index: 0, content_block: { type: "text", text: "" } }));
133
+ res.write(createEvent("ping", { type: "ping" }));
134
+
135
+ // proxy response
136
+ var socket = io("wss://www.perplexity.ai/", opts);
137
+
138
+ socket.on("connect", function () {
139
+ console.log(" > [Connected]");
140
+ socket
141
+ .emitWithAck("perplexity_ask", previousMessages, {
142
+ "version": "2.9",
143
+ "source": "default",
144
+ "attachments": [],
145
+ "language": "en-GB",
146
+ "timezone": "Europe/London",
147
+ "search_focus": "writing",
148
+ "frontend_uuid": uuidv4(),
149
+ "mode": "concise",
150
+ "is_related_query": false,
151
+ "is_default_related_query": false,
152
+ "visitor_id": uuidv4(),
153
+ "frontend_context_uuid": uuidv4(),
154
+ "prompt_source": "user",
155
+ "query_source": "home"
156
+ })
157
+ .then((response) => {
158
+
159
+ console.log(response);
160
+ res.write(createEvent("content_block_stop", { type: "content_block_stop", index: 0 }));
161
+ res.write(
162
+ createEvent("message_delta", {
163
+ type: "message_delta",
164
+ delta: { stop_reason: "end_turn", stop_sequence: null },
165
+ usage: { output_tokens: 12 },
166
+ })
167
+ );
168
+ res.write(createEvent("message_stop", { type: "message_stop" }));
169
+
170
+ res.end();
171
+ }).catch((error) => {
172
+ if(error.message != "socket has been disconnected"){
173
+ console.log(error);
174
+ }
175
+ });
176
+ });
177
+ socket.onAny((event, ...args) => {
178
+ console.log(`> [got ${event}]`);
179
+ });
180
+ socket.on("query_progress", (data) => {
181
+ if(data.text){
182
+ var text = JSON.parse(data.text)
183
+ var chunk = text.chunks[text.chunks.length - 1];
184
+ if(chunk){
185
+ chunkJSON = JSON.stringify({
186
+ type: "content_block_delta",
187
+ index: 0,
188
+ delta: { type: "text_delta", text: chunk },
189
+ });
190
+ res.write(createEvent("content_block_delta", chunkJSON));
191
+ }
192
+ }
193
+ });
194
+ socket.on("disconnect", function () {
195
+ console.log(" > [Disconnected]");
196
+ });
197
+ socket.on("error", (error) => {
198
+ chunkJSON = JSON.stringify({
199
+ type: "content_block_delta",
200
+ index: 0,
201
+ delta: { type: "text_delta", text: "Error occured while fetching output 输出时出现错误\nPlease refer to the log for more information 请查看日志以获取更多信息" },
202
+ });
203
+ res.write(createEvent("content_block_delta", chunkJSON));
204
+ res.write(createEvent("content_block_stop", { type: "content_block_stop", index: 0 }));
205
+ res.write(
206
+ createEvent("message_delta", {
207
+ type: "message_delta",
208
+ delta: { stop_reason: "end_turn", stop_sequence: null },
209
+ usage: { output_tokens: 12 },
210
+ })
211
+ );
212
+ res.write(createEvent("message_stop", { type: "message_stop" }));
213
+
214
+ res.end();
215
+ console.log(error);
216
+ });
217
+ socket.on("connect_error", function (error) {
218
+ chunkJSON = JSON.stringify({
219
+ type: "content_block_delta",
220
+ index: 0,
221
+ delta: { type: "text_delta", text: "Failed to connect to the Perplexity.ai 连接到Perplexity失败\nPlease refer to the log for more information 请查看日志以获取更多信息" },
222
+ });
223
+ res.write(createEvent("content_block_delta", chunkJSON));
224
+ res.write(createEvent("content_block_stop", { type: "content_block_stop", index: 0 }));
225
+ res.write(
226
+ createEvent("message_delta", {
227
+ type: "message_delta",
228
+ delta: { stop_reason: "end_turn", stop_sequence: null },
229
+ usage: { output_tokens: 12 },
230
+ })
231
+ );
232
+ res.write(createEvent("message_stop", { type: "message_stop" }));
233
+
234
+ res.end();
235
+ console.log(error);
236
+ });
237
+ res.on("close", function () {
238
+ console.log(" > [Client closed]");
239
+ socket.disconnect();
240
+ });
241
+ } else {
242
+ throw new Error("Invalid request");
243
+ }
244
+ } catch (e) {
245
+ console.log(e);
246
+ res.write(JSON.stringify({ error: e.message }));
247
+ res.end();
248
+ return;
249
+ }
250
+ });
251
+ });
252
+
253
+ // handle other
254
+ app.use((req, res, next) => {
255
+ res.status(404).send("Not Found");
256
+ });
257
+
258
+ app.listen(port, () => {
259
+ console.log(`Perplexity proxy listening on port ${port}`);
260
+ });
261
+
262
+ // eventStream util
263
+ function createEvent(event, data) {
264
+ // if data is object, stringify it
265
+ if (typeof data === "object") {
266
+ data = JSON.stringify(data);
267
+ }
268
+ return `event: ${event}\ndata: ${data}\n\n`;
269
+ }