Rfym21 commited on
Commit
44bdc2c
·
verified ·
1 Parent(s): 32c7fe7

Delete index.js

Browse files
Files changed (1) hide show
  1. index.js +0 -268
index.js DELETED
@@ -1,268 +0,0 @@
1
- import grpc from '@grpc/grpc-js';
2
- import protoLoader from '@grpc/proto-loader';
3
- import { AutoRouter, cors, error, json } from 'itty-router';
4
- import dotenv from 'dotenv';
5
- import { createServerAdapter } from '@whatwg-node/server';
6
- import { createServer } from 'http';
7
-
8
- // 加载环境变量
9
- dotenv.config();
10
- // 初始化配置
11
- class Config {
12
- constructor() {
13
- this.API_PREFIX = process.env.API_PREFIX || '/';
14
- this.API_KEY = process.env.API_KEY || '';
15
- this.MAX_RETRY_COUNT = process.env.MAX_RETRY_COUNT || 3;
16
- this.RETRY_DELAY = process.env.RETRY_DELAY || 5000;
17
- this.COMMON_GRPC = 'runtime-native-io-vertex-inference-grpc-service-lmuw6mcn3q-ul.a.run.app';
18
- this.COMMON_PROTO = './VertexInferenceService.proto';
19
- this.GPT_GRPC = 'runtime-native-io-gpt-inference-grpc-service-lmuw6mcn3q-ul.a.run.app';
20
- this.GPT_PROTO = './GPTInferenceService.proto';
21
- this.PORT = process.env.PORT || 8787;
22
- }
23
- }
24
- class GRPCHandler {
25
- constructor(protoFilePath) {
26
- // 动态加载传入的 .proto 文件路径
27
- this.packageDefinition = protoLoader.loadSync(protoFilePath, {
28
- keepCase: true,
29
- longs: String,
30
- enums: String,
31
- defaults: true,
32
- oneofs: true
33
- });
34
- }
35
- }
36
- const config = new Config();
37
- // 中间件
38
- // 添加运行回源
39
- const { preflight, corsify } = cors({
40
- origin: '*',
41
- allowMethods: '*',
42
- exposeHeaders: '*',
43
- });
44
-
45
- // 添加认证
46
- const withAuth = (request) => {
47
- if (config.API_KEY) {
48
- const authHeader = request.headers.get('Authorization');
49
- if (!authHeader || !authHeader.startsWith('Bearer ')) {
50
- return error(401, 'Unauthorized: Missing or invalid Authorization header');
51
- }
52
- const token = authHeader.substring(7);
53
- if (token !== config.API_KEY) {
54
- return error(403, 'Forbidden: Invalid API key');
55
- }
56
- }
57
- };
58
- // 返回运行信息
59
- const logger = (res, req) => {
60
- console.log(req.method, res.status, req.url, Date.now() - req.start, 'ms');
61
- };
62
- const router = AutoRouter({
63
- before: [preflight, withAuth],
64
- missing: () => error(404, '404 not found.'),
65
- finally: [corsify, logger],
66
- });
67
- // Router路径
68
- router.get('/', () => json({ message: 'API 服务运行中~' }));
69
- router.get('/ping', () => json({ message: 'pong' }));
70
- router.post(config.API_PREFIX + '/v1/chat/completions', (req) => handleCompletion(req));
71
-
72
- async function GrpcToPieces(models, message, rules, stream, temperature, top_p) {
73
- // 在非GPT类型的模型中,temperature和top_p是无效的
74
- // 使用系统的根证书
75
- const credentials = grpc.credentials.createSsl();
76
- let client, request;
77
- if (models.includes('gpt')) {
78
- // 加载proto文件
79
- const packageDefinition = new GRPCHandler(config.GPT_PROTO).packageDefinition;
80
- // 构建请求消息
81
- request = {
82
- models: models,
83
- messages: [
84
- { role: 0, message: rules }, // system
85
- { role: 1, message: message } // user
86
- ],
87
- temperature: temperature || 0.1,
88
- top_p: top_p ?? 1,
89
- }
90
- // 获取gRPC对象
91
- const GRPCobjects = grpc.loadPackageDefinition(packageDefinition).runtime.aot.machine_learning.parents.gpt;
92
- client = new GRPCobjects.GPTInferenceService(config.GPT_GRPC, credentials);
93
- } else {
94
- // 加载proto文件
95
- const packageDefinition = new GRPCHandler(config.COMMON_PROTO).packageDefinition;
96
- // 构建请求消息
97
- request = {
98
- models: models,
99
- args: {
100
- messages: {
101
- unknown: 1,
102
- message: message
103
- },
104
- rules: rules
105
- }
106
- };
107
- // 获取gRPC对象
108
- const GRPCobjects = grpc.loadPackageDefinition(packageDefinition).runtime.aot.machine_learning.parents.vertex;
109
- client = new GRPCobjects.VertexInferenceService(config.COMMON_GRPC, credentials);
110
- }
111
- return await ConvertOpenai(client, request, models, stream);
112
- }
113
-
114
- async function messagesProcess(messages) {
115
- let rules = '';
116
- let message = '';
117
-
118
- for (const msg of messages) {
119
- let role = msg.role;
120
- // 格式化为字符串
121
- const contentStr = Array.isArray(msg.content)
122
- ? msg.content
123
- .filter((item) => item.text)
124
- .map((item) => item.text)
125
- .join('') || ''
126
- : msg.content;
127
- // 判断身份
128
- if (role === 'system') {
129
- rules += `system:${contentStr};\r\n`;
130
- } else if (['user', 'assistant'].includes(role)) {
131
- message += `${role}:${contentStr};\r\n`;
132
- }
133
- }
134
-
135
- return { rules, message };
136
- }
137
-
138
- async function ConvertOpenai(client, request, model, stream) {
139
- for (let i = 0; i < config.MAX_RETRY_COUNT; i++) {
140
- try {
141
- if (stream) {
142
- const call = client.PredictWithStream(request);
143
- const encoder = new TextEncoder();
144
- const ReturnStream = new ReadableStream({
145
- start(controller) {
146
- call.on('data', (response) => {
147
- let response_code = Number(response.response_code);
148
- if (response_code === 204) {
149
- // 如果 response_code 是 204,关闭流
150
- controller.close()
151
- call.destroy()
152
- } else if (response_code === 200) {
153
- let response_message
154
- if (model.includes('gpt')) {
155
- response_message = response.body.message_warpper.message.message;
156
- } else {
157
- response_message = response.args.args.args.message;
158
- }
159
- // 否则,将数据块加入流中
160
- controller.enqueue(encoder.encode(`data: ${JSON.stringify(ChatCompletionStreamWithModel(response_message, model))}\n\n`));
161
- } else {
162
- controller.error(new Error(`Error: stream chunk is not success`));
163
- controller.close()
164
- }
165
- })
166
- }
167
- });
168
- return new Response(ReturnStream, {
169
- headers: {
170
- 'Content-Type': 'text/event-stream',
171
- },
172
- })
173
- } else {
174
- const call = await new Promise((resolve, reject) => {
175
- client.Predict(request, (err, response) => {
176
- if (err) reject(err);
177
- else resolve(response);
178
- });
179
- });
180
- let response_code = Number(call.response_code);
181
- if (response_code === 200) {
182
- let response_message
183
- if (model.includes('gpt')) {
184
- response_message = call.body.message_warpper.message.message;
185
- } else {
186
- response_message = call.args.args.args.message;
187
- }
188
- return new Response(JSON.stringify(ChatCompletionWithModel(response_message, model)), {
189
- headers: {
190
- 'Content-Type': 'application/json',
191
- },
192
- });
193
- }
194
- }
195
- } catch (err) {
196
- console.error(err);
197
- await new Promise((resolve) => setTimeout(resolve, config.RETRY_DELAY));
198
- }
199
- }
200
- return error(500, err.message);
201
- }
202
-
203
- function ChatCompletionWithModel(message, model) {
204
- return {
205
- id: 'Chat-Nekohy',
206
- object: 'chat.completion',
207
- created: Date.now(),
208
- model,
209
- usage: {
210
- prompt_tokens: 0,
211
- completion_tokens: 0,
212
- total_tokens: 0,
213
- },
214
- choices: [
215
- {
216
- message: {
217
- content: message,
218
- role: 'assistant',
219
- },
220
- index: 0,
221
- },
222
- ],
223
- };
224
- }
225
-
226
- function ChatCompletionStreamWithModel(text, model) {
227
- return {
228
- id: 'chatcmpl-QXlha2FBbmROaXhpZUFyZUF3ZXNvbWUK',
229
- object: 'chat.completion.chunk',
230
- created: 0,
231
- model,
232
- choices: [
233
- {
234
- index: 0,
235
- delta: {
236
- content: text,
237
- },
238
- finish_reason: null,
239
- },
240
- ],
241
- };
242
- }
243
-
244
- async function handleCompletion(request) {
245
- try {
246
- // todo stream逆向接口
247
- // 解析openai格式API请求
248
- const { model: inputModel, messages, stream, temperature, top_p } = await request.json();
249
- console.log(inputModel, messages, stream)
250
- // 解析system和user/assistant消息
251
- const { rules, message: content } = await messagesProcess(messages);
252
- console.log(rules, content)
253
- // 响应码,回复的消息
254
- return await GrpcToPieces(inputModel, content, rules, stream, temperature, top_p);
255
- } catch (err) {
256
- return error(500, err.message);
257
- }
258
- }
259
-
260
- (async () => {
261
- //For Cloudflare Workers
262
- if (typeof addEventListener === 'function') return;
263
- // For Nodejs
264
- const ittyServer = createServerAdapter(router.fetch);
265
- console.log(`Listening on http://localhost:${config.PORT}`);
266
- const httpServer = createServer(ittyServer);
267
- httpServer.listen(config.PORT);
268
- })();