tianlong12 commited on
Commit
084ae67
1 Parent(s): ebfcda6

Create index.js

Browse files
Files changed (1) hide show
  1. index.js +329 -0
index.js ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+
6
+ // 创建代理实例
7
+ const 代理 = new ProxyAgent();
8
+
9
+ // 获取环境变量值并赋给中文变量名
10
+ const 曲奇池 = process.env.COOKIE_POOL || '';
11
+ const 用户代理 = process.env.USER_AGENT || '';
12
+ const 全局代理 = process.env.ALL_PROXY || '';
13
+
14
+ const 应用 = express();
15
+ const 端口 = process.env.PORT || 7860;
16
+
17
+ // 解析曲奇池,支持单个或多个曲奇(用逗号分隔)
18
+ const cookiePool = 曲奇池
19
+ ? 曲奇池.split(',').map(cookie => cookie.trim()).filter(cookie => cookie.length > 0)
20
+ : [];
21
+
22
+ if (cookiePool.length === 0) {
23
+ console.error("错误:环境变量 曲奇池 未设置或为空。");
24
+ process.exit(1);
25
+ }
26
+
27
+ // 创建事件流的工具函数
28
+ function 创建事件(事件, 数据) {
29
+ if (typeof 数据 === "object") {
30
+ 数据 = JSON.stringify(数据);
31
+ }
32
+ return `event: ${事件}\ndata: ${数据}\n\n`;
33
+ }
34
+
35
+ // 处理 POST 请求的路由 /v1/messages
36
+ 应用.post("/v1/messages", (请求, 响应) => {
37
+ 请求.rawBody = "";
38
+ 请求.setEncoding("utf8");
39
+
40
+ // 收集请求的原始数据
41
+ 请求.on("data", function (片段) {
42
+ 请求.rawBody += 片段;
43
+ });
44
+
45
+ 请求.on("end", async () => {
46
+ 响应.setHeader("Content-Type", "text/event-stream;charset=utf-8");
47
+ try {
48
+ let 请求数据 = JSON.parse(请求.rawBody);
49
+ if (请求数据.stream == false) {
50
+ // 当 stream 为 false 时,返回固定的响应
51
+ 响应.send(
52
+ JSON.stringify({
53
+ id: uuidv4(),
54
+ content: [
55
+ {
56
+ text: "请开启流式传输。",
57
+ },
58
+ {
59
+ id: "string",
60
+ name: "string",
61
+ input: {},
62
+ },
63
+ ],
64
+ model: "string",
65
+ stop_reason: "end_turn",
66
+ stop_sequence: "string",
67
+ usage: {
68
+ input_tokens: 0,
69
+ output_tokens: 0,
70
+ },
71
+ })
72
+ );
73
+ } else if (请求数据.stream == true) {
74
+ // 处理 stream 为 true 的情况
75
+ let 用户消息 = [{ 问题: "", 回答: "" }];
76
+ let 最后更新 = true;
77
+
78
+ if (请求数据.system) {
79
+ // 将系统消息添加到消息列表的首位
80
+ 请求数据.messages.unshift({ role: "system", content: 请求数据.system });
81
+ }
82
+
83
+ console.log(请求数据.messages);
84
+
85
+ // 遍历消息列表,构建用户和助手的问答对
86
+ 请求数据.messages.forEach((消息) => {
87
+ if (消息.role == "system" || 消息.role == "user") {
88
+ if (最后更新) {
89
+ 用户消息[用户消息.length - 1].问题 += 消息.content + "\n";
90
+ } else if (用户消息[用户消息.length - 1].问题 == "") {
91
+ 用户消息[用户消息.length - 1].问题 += 消息.content + "\n";
92
+ } else {
93
+ 用户消息.push({ 问题: 消息.content + "\n", 回答: "" });
94
+ }
95
+ 最后更新 = true;
96
+ } else if (消息.role == "assistant") {
97
+ if (!最后更新) {
98
+ 用户消息[用户消息.length - 1].回答 += 消息.content + "\n";
99
+ } else if (用户消息[用户消息.length - 1].回答 == "") {
100
+ 用户消息[用户消息.length - 1].回答 += 消息.content + "\n";
101
+ } else {
102
+ 用户消息.push({ 问题: "", 回答: 消息.content + "\n" });
103
+ }
104
+ 最后更新 = false;
105
+ }
106
+ });
107
+
108
+ // 查找最新的用户消息
109
+ const 最新用户消息 = 请求数据.messages
110
+ .slice().reverse()
111
+ .find(消息 => 消息.role === "user");
112
+
113
+ if (!最新用户消息) {
114
+ throw new Error("请求中未找到用户消息。");
115
+ }
116
+
117
+ // 获取最新用户消息的索引
118
+ const 最新用户索引 = 请求数据.messages.lastIndexOf(最新用户消息);
119
+
120
+ // 构建除最新用户消息外的所有消息
121
+ const 先前消息列表 = 请求数据.messages.slice(0, 最新用户索引);
122
+
123
+ // 改进上下文拼接格式,增加提示并避免重复
124
+ let 先前消息 = 先前消息列表
125
+ .map((消息) => {
126
+ if (消息.role === "user") {
127
+ return `用户: ${消息.content}`;
128
+ } else if (消息.role === "assistant") {
129
+ return `助手: ${消息.content}`;
130
+ } else if (消息.role === "system") {
131
+ return `系统: ${消息.content}`;
132
+ }
133
+ return 消息.content;
134
+ })
135
+ .join("\n\n");
136
+
137
+ // 在上下文末尾添加提示,不再重复添加最新的用户消息
138
+ 先前消息 += `\n\n# ↓请关注用户最新的消息↓\n\n`;
139
+
140
+ // 追加最新的用户消息
141
+ 先前消息 += `用户: ${最新用户消息.content}`;
142
+
143
+ let 消息ID = uuidv4();
144
+
145
+ // 发送消息开始的事件
146
+ 响应.write(
147
+ 创建事件("message_start", {
148
+ type: "message_start",
149
+ message: {
150
+ id: 消息ID,
151
+ type: "message",
152
+ role: "assistant",
153
+ content: [],
154
+ model: "claude-3-opus-20240229",
155
+ stop_reason: null,
156
+ stop_sequence: null,
157
+ usage: { input_tokens: 8, output_tokens: 1 },
158
+ },
159
+ })
160
+ );
161
+ 响应.write(创建事件("content_block_start", { type: "content_block_start", index: 0, content_block: { type: "text", text: "" } }));
162
+ 响应.write(创建事件("ping", { type: "ping" }));
163
+
164
+ // 随机选择一个曲奇
165
+ const 随机曲奇 = cookiePool[Math.floor(Math.random() * cookiePool.length)];
166
+
167
+ // 配置 Socket.IO 客户端选项
168
+ var 选项 = {
169
+ agent: 代理,
170
+ auth: {
171
+ jwt: "anonymous-ask-user",
172
+ },
173
+ reconnection: false,
174
+ transports: ["websocket"],
175
+ path: "/socket.io",
176
+ hostname: "www.perplexity.ai",
177
+ secure: true,
178
+ port: "443",
179
+ extraHeaders: {
180
+ Cookie: 随机曲奇, // 使用随机选择的曲奇
181
+ "User-Agent": 用户代理,
182
+ Accept: "*/*",
183
+ priority: "u=1, i",
184
+ Referer: "https://www.perplexity.ai/",
185
+ },
186
+ };
187
+
188
+ // 通过 Socket.IO 连接 Perplexity.ai 的 WebSocket
189
+ var socket = io("wss://www.perplexity.ai/", 选项);
190
+
191
+ socket.on("connect", function () {
192
+ console.log(" > [已连接]");
193
+ socket
194
+ .emitWithAck("perplexity_ask", 先前消息, {
195
+ "version": "2.9",
196
+ "source": "default",
197
+ "attachments": [],
198
+ "language": "en-GB",
199
+ "timezone": "Europe/London",
200
+ "search_focus": "writing",
201
+ "frontend_uuid": uuidv4(),
202
+ "mode": "concise",
203
+ "is_related_query": false,
204
+ "is_default_related_query": false,
205
+ "visitor_id": uuidv4(),
206
+ "frontend_context_uuid": uuidv4(),
207
+ "prompt_source": "user",
208
+ "query_source": "home"
209
+ })
210
+ .then((响应数据) => {
211
+ console.log(响应数据);
212
+ 响应.write(创建事件("content_block_stop", { type: "content_block_stop", index: 0 }));
213
+ 响应.write(
214
+ 创建事件("message_delta", {
215
+ type: "message_delta",
216
+ delta: { stop_reason: "end_turn", stop_sequence: null },
217
+ usage: { output_tokens: 12 },
218
+ })
219
+ );
220
+ 响应.write(创建事件("message_stop", { type: "message_stop" }));
221
+
222
+ 响应.end();
223
+ }).catch((错误) => {
224
+ if(错误.message != "socket has been disconnected"){
225
+ console.log(错误);
226
+ }
227
+ });
228
+ });
229
+
230
+ // 监听所有事件,记录日志
231
+ socket.onAny((事件, ...参数) => {
232
+ console.log(`> [收到事件: ${事件}]`);
233
+ });
234
+
235
+ // 监听查询进度事件,处理返回的文本块
236
+ socket.on("query_progress", (数据) => {
237
+ if(数据.text){
238
+ try {
239
+ var 文本 = JSON.parse(数据.text)
240
+ var 块 = 文本.chunks[文本.chunks.length - 1];
241
+ if (块) {
242
+ let 块JSON = JSON.stringify({
243
+ type: "content_block_delta",
244
+ index: 0,
245
+ delta: { type: "text_delta", text: 块 },
246
+ });
247
+ 响应.write(创建事件("content_block_delta", 块JSON));
248
+ }
249
+ } catch (错误) {
250
+ console.log("解析 query_progress 数据时出错:", 错误);
251
+ }
252
+ }
253
+ });
254
+
255
+ // 监听断开连接事件
256
+ socket.on("disconnect", function () {
257
+ console.log(" > [已断开连接]");
258
+ });
259
+
260
+ // 监听错误事件,返回错误信息给客户端
261
+ socket.on("error", (错误) => {
262
+ let 块JSON = JSON.stringify({
263
+ type: "content_block_delta",
264
+ index: 0,
265
+ delta: { type: "text_delta", text: "获取输出时出现错误\n请查看日志以获取更多信息" },
266
+ });
267
+ 响应.write(创建事件("content_block_delta", 块JSON));
268
+ 响应.write(创建事件("content_block_stop", { type: "content_block_stop", index: 0 }));
269
+ 响应.write(
270
+ 创建事件("message_delta", {
271
+ type: "message_delta",
272
+ delta: { stop_reason: "end_turn", stop_sequence: null },
273
+ usage: { output_tokens: 12 },
274
+ })
275
+ );
276
+ 响应.write(创建事件("message_stop", { type: "message_stop" }));
277
+
278
+ 响应.end();
279
+ console.log(错误);
280
+ });
281
+
282
+ // 监听连接错误事件,返回错误信息给客户端
283
+ socket.on("connect_error", function (错误) {
284
+ let 块JSON = JSON.stringify({
285
+ type: "content_block_delta",
286
+ index: 0,
287
+ delta: { type: "text_delta", text: "连接到 Perplexity.ai 失败\n请查看日志以获取更多信息" },
288
+ });
289
+ 响应.write(创建事件("content_block_delta", 块JSON));
290
+ 响应.write(创建事件("content_block_stop", { type: "content_block_stop", index: 0 }));
291
+ 响应.write(
292
+ 创建事件("message_delta", {
293
+ type: "message_delta",
294
+ delta: { stop_reason: "end_turn", stop_sequence: null },
295
+ usage: { output_tokens: 12 },
296
+ })
297
+ );
298
+ 响应.write(创建事件("message_stop", { type: "message_stop" }));
299
+
300
+ 响应.end();
301
+ console.log(错误);
302
+ });
303
+
304
+ // 监听客户端关闭事件,断开 Socket 连接
305
+ 响应.on("close", function () {
306
+ console.log(" > [客户端已关闭连接]");
307
+ socket.disconnect();
308
+ });
309
+ } else {
310
+ throw new Error("无效的请求");
311
+ }
312
+ } catch (错误) {
313
+ console.log(错误);
314
+ 响应.write(JSON.stringify({ error: 错误.message }));
315
+ 响应.end();
316
+ return;
317
+ }
318
+ });
319
+ });
320
+
321
+ // 处理所有未定义的路由,返回 418
322
+ 应用.use((请求, 响应, 下一个) => {
323
+ 响应.status(418).send("418 I'm a teapot");
324
+ });
325
+
326
+ // 启动服务器,监听指定端口
327
+ 应用.listen(端口, () => {
328
+ console.log(`Perplexity 代理服务器正在监听端口 ${端口}`);
329
+ });