jianwei233 commited on
Commit
eef51bf
·
verified ·
1 Parent(s): ec04397

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +164 -178
index.js CHANGED
@@ -12,7 +12,7 @@ dotenv.config();
12
  const CONFIG = {
13
  API: {
14
  BASE_URL: "wss://api.inkeep.com/graphql",
15
- API_KEY: process.env.API_KEY || "sk-123456", // 仍然从环境变量获取,但保留默认值
16
  },
17
  MODELS: {
18
  'claude-3-5-sonnet-20241022': 'claude-3-5-sonnet-20241022',
@@ -123,7 +123,7 @@ class ResponseHandler {
123
 
124
  let index = 0;
125
  while (index < responseContent.length) {
126
- const chunkSize = Math.floor(Math.random() * (30 - 16)) + 15; // 保留随机 chunk 大小
127
  const chunk = responseContent.slice(index, index + chunkSize);
128
 
129
  res.write(`data: ${JSON.stringify({
@@ -172,135 +172,127 @@ class ResponseHandler {
172
 
173
  // WebSocket工具类
174
  class WebSocketUtils {
175
- // 生成WebSocket密钥
176
- static generateWebSocketKey() {
177
- return randomBytes(16).toString('base64');
178
- }
179
-
180
- // 创建WebSocket客户端
181
- static async createWebSocketClient(requestPayload) {
182
- const websocketKey = this.generateWebSocketKey();
183
- const ws = new WebSocket(CONFIG.API.BASE_URL, 'graphql-transport-ws', { // 保留硬编码
184
- headers: {
185
- ...CONFIG.DEFAULT_HEADERS,
186
- 'Sec-WebSocket-Key': websocketKey,
187
- }
188
- });
189
-
190
- let responseContent = '';
191
- let isComplete = false;
192
-
193
- try {
194
- await new Promise((resolve, reject) => {
195
- ws.on('open', () => {
196
- console.log('WebSocket连接已建立');
197
- const connectionInitMessage = {
198
- type: 'connection_init',
199
- payload: {
200
- headers: {
201
- // 从环境变量获取 API 密钥
202
- Authorization: `Bearer ${CONFIG.API.API_KEY}`
203
- }
204
- }
205
- };
206
- ws.send(JSON.stringify(connectionInitMessage));
207
- });
208
-
209
- ws.on('message', async (data) => {
210
- const message = data.toString();
211
- const parsedMessage = JSON.parse(message);
212
-
213
- switch (parsedMessage.type) {
214
- case 'connection_ack':
215
- console.log('WebSocket连接请求中');
216
- this.sendChatSubscription(ws, requestPayload);
217
- break;
218
- case 'next':
219
- const chatResponse = await this.handleChatResponse(parsedMessage);
220
- if (chatResponse) {
221
- responseContent = chatResponse;
222
- }
223
- break;
224
- case 'complete':
225
- isComplete = true;
226
- ws.close();
227
- resolve(responseContent);
228
- break;
229
- }
230
- });
231
-
232
- ws.on('error', (err) => {
233
- console.error('WebSocket错误:', err);
234
- // 除了记录错误,还可以尝试发送错误信息给客户端
235
- reject(err);
236
- });
237
-
238
- ws.on('close', (code, reason) => {
239
- console.log(`WebSocket连接关闭,代码:${code},原因:${reason}`);
240
- if (!isComplete) {
241
- reject(new Error(`WebSocket closed unexpectedly (code: ${code}, reason: ${reason})`));
242
- } else {
243
- resolve(responseContent); // 在连接正常关闭时也需要 resolve
244
- }
245
- });
246
- });
247
-
248
- return responseContent; // 返回最终的响应内容
249
-
250
- } catch (error) {
251
- console.error('WebSocket处理过程中发生错误:', error);
252
- throw error; // 将错误继续抛出,以便上层处理
253
- }
254
- }
255
-
256
- // 发送聊天订阅
257
- static sendChatSubscription(ws, requestPayload) {
258
- const subscribeMessage = {
259
- id: uuidv4(),
260
- type: 'subscribe',
261
- payload: {
262
- variables: {
263
- messageInput: requestPayload.contextMessages,
264
- messageContext: null,
265
- organizationId: 'org_JfjtEvzbwOikUEUn', // 保留硬编码
266
- integrationId: 'clwtqz9sq001izszu8ms5g4om', // 保留硬编码
267
- chatMode: 'AUTO',
268
- context: requestPayload.systemMessage,
269
- messageAttributes: {},
270
- includeAIAnnotations: false,
271
- environment: 'production'
272
- },
273
- extensions: {},
274
- operationName: 'OnNewSessionChatResult',
275
- query: `subscription OnNewSessionChatResult($messageInput: String!, $messageContext: String, $organizationId: ID!, $integrationId: ID, $chatMode: ChatMode, $filters: ChatFiltersInput, $messageAttributes: JSON, $tags: [String!], $workflowId: String, $context: String, $guidance: String, $includeAIAnnotations: Boolean!, $environment: String) {
276
- newSessionChatResult(
277
- input: {messageInput: $messageInput, messageContext: $messageContext, organizationId: $organizationId, integrationId: $integrationId, chatMode: $chatMode, filters: $filters, messageAttributes: $messageAttributes, tags: $tags, workflowId: $workflowId, context: $context, guidance: $guidance, environment: $environment}
278
- ) {
279
- isEnd
280
- sessionId
281
- message {
282
- id
283
- content
284
- }
285
- __typename
286
  }
287
- }`
288
- }
289
- };
290
-
291
- ws.send(JSON.stringify(subscribeMessage));
292
- }
293
-
294
- // 处理聊天响应
295
- static async handleChatResponse(message) {
296
- if (message.payload && message.payload.data) {
297
- const chatResult = message.payload.data.newSessionChatResult;
298
- if (chatResult && chatResult.isEnd == true && chatResult.message) {
299
- return chatResult.message.content;
300
- }
301
- }
302
- return null;
303
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  }
305
 
306
  // 创建Express应用
@@ -310,67 +302,61 @@ const app = express();
310
  app.use(express.json({ limit: CONFIG.SERVER.BODY_LIMIT }));
311
  app.use(express.urlencoded({ extended: true, limit: CONFIG.SERVER.BODY_LIMIT }));
312
  app.use(cors({
313
- origin: '*',
314
- methods: ['GET', 'POST', 'OPTIONS'],
315
- allowedHeaders: ['Content-Type', 'Authorization']
316
  }));
317
 
318
  // 获取模型列表路由
319
  app.get('/hf/v1/models', (req, res) => {
320
- res.json({
321
- object: "list",
322
- data: [{
323
- id: "claude-3-5-sonnet-20241022",
324
- object: "model",
325
- created: Math.floor(Date.now() / 1000),
326
- owned_by: "claude",
327
- }]
328
- });
329
  });
330
 
331
  // 聊天完成路由
332
  app.post('/hf/v1/chat/completions', async (req, res) => {
333
- try {
334
- const { messages, model, stream } = req.body;
335
- const authToken = req.headers.authorization?.replace('Bearer ', '');
336
-
337
- if (authToken !== CONFIG.API.API_KEY) {
338
- return res.status(401).json({ error: "Unauthorized" });
339
- }
340
-
341
- const apiClient = new AiApiClient(req.body.model);
342
- const requestPayload = await apiClient.transformMessages(req.body);
343
-
344
- const userMessage = messages.reverse().find(message => message.role === 'user')?.content;
345
- if (!userMessage) {
346
- return res.status(400).json({ error: "缺失用户消息" });
347
- }
348
-
349
- const responseContent = await WebSocketUtils.createWebSocketClient(requestPayload);
350
-
351
- if (stream) {
352
- await ResponseHandler.handleStreamResponse(responseContent, model, res);
353
- } else {
354
- await ResponseHandler.handleNormalResponse(userMessage, responseContent, model, res);
355
- }
356
- } catch (error) {
357
- console.error('处理请求时发生错误:', error);
358
- res.status(500).json({ error: "内部服务器错误", details: error.message });
359
- }
360
  });
361
 
362
  // 404处理
363
  app.use((req, res) => {
364
- res.status(404).json({ message: "请使用正确请求路径" });
365
- });
366
-
367
- // 全局错误处理(新增)
368
- app.use((err, req, res, next) => {
369
- console.error(err.stack);
370
- res.status(500).json({ error: '服务器内部错误', details: err.message });
371
  });
372
 
373
  // 启动服务器
374
  app.listen(CONFIG.SERVER.PORT, () => {
375
- console.log(`服务器运行在 http://localhost:${CONFIG.SERVER.PORT}`);
376
- });
 
12
  const CONFIG = {
13
  API: {
14
  BASE_URL: "wss://api.inkeep.com/graphql",
15
+ API_KEY: process.env.API_KEY || "sk-123456",
16
  },
17
  MODELS: {
18
  'claude-3-5-sonnet-20241022': 'claude-3-5-sonnet-20241022',
 
123
 
124
  let index = 0;
125
  while (index < responseContent.length) {
126
+ const chunkSize = Math.floor(Math.random() * (30 - 16)) + 15;
127
  const chunk = responseContent.slice(index, index + chunkSize);
128
 
129
  res.write(`data: ${JSON.stringify({
 
172
 
173
  // WebSocket工具类
174
  class WebSocketUtils {
175
+ // 生成WebSocket密钥
176
+ static generateWebSocketKey() {
177
+ return randomBytes(16).toString('base64');
178
+ }
179
+
180
+ // 创建WebSocket客户端
181
+ static createWebSocketClient(requestPayload) {
182
+ return new Promise((resolve, reject) => {
183
+ const websocketKey = this.generateWebSocketKey();
184
+ const ws = new WebSocket(CONFIG.API.BASE_URL, 'graphql-transport-ws', {
185
+ headers: {
186
+ ...CONFIG.DEFAULT_HEADERS,
187
+ 'Sec-WebSocket-Key': websocketKey,
188
+ }
189
+ });
190
+
191
+ let responseContent = '';
192
+ let isComplete = false;
193
+
194
+ ws.on('open', () => {
195
+ console.log('WebSocket连接已建立');
196
+ const connectionInitMessage = {
197
+ type: 'connection_init',
198
+ payload: {
199
+ headers: {
200
+ Authorization: 'Bearer ee5b7c15ed3553cd6abc407340aad09ac7cb3b9f76d8613a'
201
+ }
202
+ }
203
+ };
204
+ ws.send(JSON.stringify(connectionInitMessage));
205
+ });
206
+
207
+ ws.on('message', async (data) => {
208
+ const message = data.toString();
209
+ const parsedMessage = JSON.parse(message);
210
+
211
+ switch (parsedMessage.type) {
212
+ case 'connection_ack':
213
+ console.log('WebSocket连接请求中');
214
+ this.sendChatSubscription(ws, requestPayload);
215
+ break;
216
+ case 'next':
217
+ const chatResponse = await this.handleChatResponse(parsedMessage);
218
+ if (chatResponse) {
219
+ responseContent = chatResponse;
220
+ // 获取到响应后立即关闭连接
221
+ isComplete = true;
222
+ ws.close();
223
+ resolve(responseContent);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  }
225
+ break;
226
+ case 'complete':
227
+ isComplete = true;
228
+ ws.close();
229
+ resolve(responseContent);
230
+ break;
231
+ }
232
+ });
233
+
234
+ ws.on('error', (err) => {
235
+ console.error('WebSocket错误:', err);
236
+ reject(err);
237
+ });
238
+
239
+ ws.on('close', (code, reason) => {
240
+ console.log('请求完毕,关闭连接');
241
+ if (!isComplete) {
242
+ reject(new Error('WebSocket closed unexpectedly'));
243
+ }
244
+ });
245
+ });
246
+ }
247
+
248
+ // 发送聊天订阅
249
+ static sendChatSubscription(ws, requestPayload) {
250
+ const subscribeMessage = {
251
+ id: uuidv4(),
252
+ type: 'subscribe',
253
+ payload: {
254
+ variables: {
255
+ messageInput: requestPayload.contextMessages,
256
+ messageContext: null,
257
+ organizationId: 'org_JfjtEvzbwOikUEUn',
258
+ integrationId: 'clwtqz9sq001izszu8ms5g4om',
259
+ chatMode: 'AUTO',
260
+ context: requestPayload.systemMessage,
261
+ messageAttributes: {},
262
+ includeAIAnnotations: false,
263
+ environment: 'production'
264
+ },
265
+ extensions: {},
266
+ operationName: 'OnNewSessionChatResult',
267
+ query: `subscription OnNewSessionChatResult($messageInput: String!, $messageContext: String, $organizationId: ID!, $integrationId: ID, $chatMode: ChatMode, $filters: ChatFiltersInput, $messageAttributes: JSON, $tags: [String!], $workflowId: String, $context: String, $guidance: String, $includeAIAnnotations: Boolean!, $environment: String) {
268
+ newSessionChatResult(
269
+ input: {messageInput: $messageInput, messageContext: $messageContext, organizationId: $organizationId, integrationId: $integrationId, chatMode: $chatMode, filters: $filters, messageAttributes: $messageAttributes, tags: $tags, workflowId: $workflowId, context: $context, guidance: $guidance, environment: $environment}
270
+ ) {
271
+ isEnd
272
+ sessionId
273
+ message {
274
+ id
275
+ content
276
+ }
277
+ __typename
278
+ }
279
+ }`
280
+ }
281
+ };
282
+
283
+ ws.send(JSON.stringify(subscribeMessage));
284
+ }
285
+
286
+ // 处理聊天响应
287
+ static async handleChatResponse(message) {
288
+ if (message.payload && message.payload.data) {
289
+ const chatResult = message.payload.data.newSessionChatResult;
290
+ if (chatResult && chatResult.isEnd == true && chatResult.message) {
291
+ return chatResult.message.content;
292
+ }
293
+ }
294
+ return null;
295
+ }
296
  }
297
 
298
  // 创建Express应用
 
302
  app.use(express.json({ limit: CONFIG.SERVER.BODY_LIMIT }));
303
  app.use(express.urlencoded({ extended: true, limit: CONFIG.SERVER.BODY_LIMIT }));
304
  app.use(cors({
305
+ origin: '*',
306
+ methods: ['GET', 'POST', 'OPTIONS'],
307
+ allowedHeaders: ['Content-Type', 'Authorization']
308
  }));
309
 
310
  // 获取模型列表路由
311
  app.get('/hf/v1/models', (req, res) => {
312
+ res.json({
313
+ object: "list",
314
+ data: [{
315
+ id: "claude-3-5-sonnet-20241022",
316
+ object: "model",
317
+ created: Math.floor(Date.now() / 1000),
318
+ owned_by: "claude",
319
+ }]
320
+ });
321
  });
322
 
323
  // 聊天完成路由
324
  app.post('/hf/v1/chat/completions', async (req, res) => {
325
+ try {
326
+ const { messages, model, stream } = req.body;
327
+ const authToken = req.headers.authorization?.replace('Bearer ', '');
328
+
329
+ if (authToken !== CONFIG.API.API_KEY) {
330
+ return res.status(401).json({ error: "Unauthorized" });
331
+ }
332
+
333
+ const apiClient = new AiApiClient(req.body.model);
334
+ const requestPayload = await apiClient.transformMessages(req.body);
335
+
336
+ const userMessage = messages.reverse().find(message => message.role === 'user')?.content;
337
+ if (!userMessage) {
338
+ return res.status(400).json({ error: "缺失用户消息" });
339
+ }
340
+
341
+ const responseContent = await WebSocketUtils.createWebSocketClient(requestPayload);
342
+
343
+ if (stream) {
344
+ await ResponseHandler.handleStreamResponse(responseContent, model, res);
345
+ } else {
346
+ await ResponseHandler.handleNormalResponse(userMessage, responseContent, model, res);
347
+ }
348
+ } catch (error) {
349
+ console.error('处理请求时发生错误:', error);
350
+ res.status(500).json({ error: "内部服务器错误", details: error.message });
351
+ }
352
  });
353
 
354
  // 404处理
355
  app.use((req, res) => {
356
+ res.status(404).json({ message: "服务创建成功运行中,根据规则使用正确请求路径" });
 
 
 
 
 
 
357
  });
358
 
359
  // 启动服务器
360
  app.listen(CONFIG.SERVER.PORT, () => {
361
+ console.log(`服务器运行在 http://localhost:${CONFIG.SERVER.PORT}`);
362
+ });