viho-llm 1.0.9 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +332 -50
- package/package.json +2 -2
- package/src/index.js +1 -0
- package/src/models/liblib-util.js +224 -0
- package/src/models/liblib.js +60 -0
- package/src/models/openai.js +6 -2
package/index.js
CHANGED
|
@@ -4,9 +4,11 @@ var genai = require('@google/genai');
|
|
|
4
4
|
var mime = require('mime-types');
|
|
5
5
|
var qiao_log_js = require('qiao.log.js');
|
|
6
6
|
var OpenAI = require('openai');
|
|
7
|
+
var crypto = require('crypto');
|
|
8
|
+
var https = require('https');
|
|
7
9
|
|
|
8
10
|
// gemini
|
|
9
|
-
const logger$
|
|
11
|
+
const logger$6 = qiao_log_js.Logger('gemini-util.js');
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* chat
|
|
@@ -20,19 +22,19 @@ const chat$1 = async (client, modelName, chatOptions) => {
|
|
|
20
22
|
|
|
21
23
|
// check
|
|
22
24
|
if (!client) {
|
|
23
|
-
logger$
|
|
25
|
+
logger$6.error(methodName, 'need client');
|
|
24
26
|
return;
|
|
25
27
|
}
|
|
26
28
|
if (!modelName) {
|
|
27
|
-
logger$
|
|
29
|
+
logger$6.error(methodName, 'need modelName');
|
|
28
30
|
return;
|
|
29
31
|
}
|
|
30
32
|
if (!chatOptions) {
|
|
31
|
-
logger$
|
|
33
|
+
logger$6.error(methodName, 'need chatOptions');
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
36
|
if (!chatOptions.contents) {
|
|
35
|
-
logger$
|
|
37
|
+
logger$6.error(methodName, 'need chatOptions.contents');
|
|
36
38
|
return;
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -48,13 +50,13 @@ const chat$1 = async (client, modelName, chatOptions) => {
|
|
|
48
50
|
// gen
|
|
49
51
|
const response = await client.models.generateContent(options);
|
|
50
52
|
if (!response || !response.text) {
|
|
51
|
-
logger$
|
|
53
|
+
logger$6.error(methodName, 'invalid response');
|
|
52
54
|
return;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
return response.text;
|
|
56
58
|
} catch (error) {
|
|
57
|
-
logger$
|
|
59
|
+
logger$6.error(methodName, 'error', error);
|
|
58
60
|
}
|
|
59
61
|
};
|
|
60
62
|
|
|
@@ -71,23 +73,23 @@ const chatWithStreaming$1 = async (client, modelName, chatOptions, callbackOptio
|
|
|
71
73
|
|
|
72
74
|
// check
|
|
73
75
|
if (!client) {
|
|
74
|
-
logger$
|
|
76
|
+
logger$6.error(methodName, 'need client');
|
|
75
77
|
return;
|
|
76
78
|
}
|
|
77
79
|
if (!modelName) {
|
|
78
|
-
logger$
|
|
80
|
+
logger$6.error(methodName, 'need modelName');
|
|
79
81
|
return;
|
|
80
82
|
}
|
|
81
83
|
if (!chatOptions) {
|
|
82
|
-
logger$
|
|
84
|
+
logger$6.error(methodName, 'need chatOptions');
|
|
83
85
|
return;
|
|
84
86
|
}
|
|
85
87
|
if (!chatOptions.contents) {
|
|
86
|
-
logger$
|
|
88
|
+
logger$6.error(methodName, 'need chatOptions.contents');
|
|
87
89
|
return;
|
|
88
90
|
}
|
|
89
91
|
if (!callbackOptions) {
|
|
90
|
-
logger$
|
|
92
|
+
logger$6.error(methodName, 'need callbackOptions');
|
|
91
93
|
return;
|
|
92
94
|
}
|
|
93
95
|
|
|
@@ -145,38 +147,38 @@ const cacheAdd = async (client, modelName, cacheOptions) => {
|
|
|
145
147
|
|
|
146
148
|
// check
|
|
147
149
|
if (!client) {
|
|
148
|
-
logger$
|
|
150
|
+
logger$6.error(methodName, 'need client');
|
|
149
151
|
return;
|
|
150
152
|
}
|
|
151
153
|
if (!modelName) {
|
|
152
|
-
logger$
|
|
154
|
+
logger$6.error(methodName, 'need modelName');
|
|
153
155
|
return;
|
|
154
156
|
}
|
|
155
157
|
if (!cacheOptions) {
|
|
156
|
-
logger$
|
|
158
|
+
logger$6.error(methodName, 'need cacheOptions');
|
|
157
159
|
return;
|
|
158
160
|
}
|
|
159
161
|
if (!cacheOptions.gsPath) {
|
|
160
|
-
logger$
|
|
162
|
+
logger$6.error(methodName, 'need cacheOptions.gsPath');
|
|
161
163
|
return;
|
|
162
164
|
}
|
|
163
165
|
if (!cacheOptions.systemPrompt) {
|
|
164
|
-
logger$
|
|
166
|
+
logger$6.error(methodName, 'need cacheOptions.systemPrompt');
|
|
165
167
|
return;
|
|
166
168
|
}
|
|
167
169
|
if (!cacheOptions.cacheName) {
|
|
168
|
-
logger$
|
|
170
|
+
logger$6.error(methodName, 'need cacheOptions.cacheName');
|
|
169
171
|
return;
|
|
170
172
|
}
|
|
171
173
|
if (!cacheOptions.cacheTTL) {
|
|
172
|
-
logger$
|
|
174
|
+
logger$6.error(methodName, 'need cacheOptions.cacheTTL');
|
|
173
175
|
return;
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
// const
|
|
177
179
|
const mimeType = mime.lookup(cacheOptions.gsPath);
|
|
178
|
-
logger$
|
|
179
|
-
logger$
|
|
180
|
+
logger$6.info(methodName, 'cacheOptions', cacheOptions);
|
|
181
|
+
logger$6.info(methodName, 'mimeType', mimeType);
|
|
180
182
|
|
|
181
183
|
try {
|
|
182
184
|
// cache add
|
|
@@ -192,7 +194,7 @@ const cacheAdd = async (client, modelName, cacheOptions) => {
|
|
|
192
194
|
|
|
193
195
|
return cache;
|
|
194
196
|
} catch (error) {
|
|
195
|
-
logger$
|
|
197
|
+
logger$6.error(methodName, 'error', error);
|
|
196
198
|
}
|
|
197
199
|
};
|
|
198
200
|
|
|
@@ -206,7 +208,7 @@ const cacheList = async (client) => {
|
|
|
206
208
|
|
|
207
209
|
// check
|
|
208
210
|
if (!client) {
|
|
209
|
-
logger$
|
|
211
|
+
logger$6.error(methodName, 'need client');
|
|
210
212
|
return;
|
|
211
213
|
}
|
|
212
214
|
|
|
@@ -220,7 +222,7 @@ const cacheList = async (client) => {
|
|
|
220
222
|
|
|
221
223
|
return cacheObjs;
|
|
222
224
|
} catch (error) {
|
|
223
|
-
logger$
|
|
225
|
+
logger$6.error(methodName, 'error', error);
|
|
224
226
|
}
|
|
225
227
|
};
|
|
226
228
|
|
|
@@ -236,15 +238,15 @@ const cacheUpdate = async (client, cacheName, cacheOptions) => {
|
|
|
236
238
|
|
|
237
239
|
// check
|
|
238
240
|
if (!client) {
|
|
239
|
-
logger$
|
|
241
|
+
logger$6.error(methodName, 'need client');
|
|
240
242
|
return;
|
|
241
243
|
}
|
|
242
244
|
if (!cacheName) {
|
|
243
|
-
logger$
|
|
245
|
+
logger$6.error(methodName, 'need cacheName');
|
|
244
246
|
return;
|
|
245
247
|
}
|
|
246
248
|
if (!cacheOptions) {
|
|
247
|
-
logger$
|
|
249
|
+
logger$6.error(methodName, 'need cacheOptions');
|
|
248
250
|
return;
|
|
249
251
|
}
|
|
250
252
|
|
|
@@ -257,12 +259,12 @@ const cacheUpdate = async (client, cacheName, cacheOptions) => {
|
|
|
257
259
|
|
|
258
260
|
return res;
|
|
259
261
|
} catch (error) {
|
|
260
|
-
logger$
|
|
262
|
+
logger$6.error(methodName, 'error', error);
|
|
261
263
|
}
|
|
262
264
|
};
|
|
263
265
|
|
|
264
266
|
// gemini
|
|
265
|
-
const logger$
|
|
267
|
+
const logger$5 = qiao_log_js.Logger('gemini-api.js');
|
|
266
268
|
|
|
267
269
|
/**
|
|
268
270
|
* GeminiAPI
|
|
@@ -274,15 +276,15 @@ const GeminiAPI = (options) => {
|
|
|
274
276
|
|
|
275
277
|
// check
|
|
276
278
|
if (!options) {
|
|
277
|
-
logger$
|
|
279
|
+
logger$5.error(methodName, 'need options');
|
|
278
280
|
return;
|
|
279
281
|
}
|
|
280
282
|
if (!options.apiKey) {
|
|
281
|
-
logger$
|
|
283
|
+
logger$5.error(methodName, 'need options.apiKey');
|
|
282
284
|
return;
|
|
283
285
|
}
|
|
284
286
|
if (!options.modelName) {
|
|
285
|
-
logger$
|
|
287
|
+
logger$5.error(methodName, 'need options.modelName');
|
|
286
288
|
return;
|
|
287
289
|
}
|
|
288
290
|
|
|
@@ -305,7 +307,7 @@ const GeminiAPI = (options) => {
|
|
|
305
307
|
};
|
|
306
308
|
|
|
307
309
|
// gemini
|
|
308
|
-
const logger$
|
|
310
|
+
const logger$4 = qiao_log_js.Logger('viho-llm');
|
|
309
311
|
|
|
310
312
|
/**
|
|
311
313
|
* GeminiVertex
|
|
@@ -317,19 +319,19 @@ const GeminiVertex = (options) => {
|
|
|
317
319
|
|
|
318
320
|
// check
|
|
319
321
|
if (!options) {
|
|
320
|
-
logger$
|
|
322
|
+
logger$4.error(methodName, 'need options');
|
|
321
323
|
return;
|
|
322
324
|
}
|
|
323
325
|
if (!options.projectId) {
|
|
324
|
-
logger$
|
|
326
|
+
logger$4.error(methodName, 'need options.projectId');
|
|
325
327
|
return;
|
|
326
328
|
}
|
|
327
329
|
if (!options.location) {
|
|
328
|
-
logger$
|
|
330
|
+
logger$4.error(methodName, 'need options.location');
|
|
329
331
|
return;
|
|
330
332
|
}
|
|
331
333
|
if (!options.modelName) {
|
|
332
|
-
logger$
|
|
334
|
+
logger$4.error(methodName, 'need options.modelName');
|
|
333
335
|
return;
|
|
334
336
|
}
|
|
335
337
|
|
|
@@ -365,7 +367,7 @@ const GeminiVertex = (options) => {
|
|
|
365
367
|
};
|
|
366
368
|
|
|
367
369
|
// Logger
|
|
368
|
-
const logger$
|
|
370
|
+
const logger$3 = qiao_log_js.Logger('openai-util.js');
|
|
369
371
|
|
|
370
372
|
/**
|
|
371
373
|
* chat
|
|
@@ -378,11 +380,11 @@ const chat = async (client, chatOptions) => {
|
|
|
378
380
|
|
|
379
381
|
// check
|
|
380
382
|
if (!client) {
|
|
381
|
-
logger$
|
|
383
|
+
logger$3.error(methodName, 'need client');
|
|
382
384
|
return;
|
|
383
385
|
}
|
|
384
386
|
if (!chatOptions) {
|
|
385
|
-
logger$
|
|
387
|
+
logger$3.error(methodName, 'need chatOptions');
|
|
386
388
|
return;
|
|
387
389
|
}
|
|
388
390
|
|
|
@@ -391,7 +393,7 @@ const chat = async (client, chatOptions) => {
|
|
|
391
393
|
const completion = await client.chat.completions.create(chatOptions);
|
|
392
394
|
return completion.choices[0]?.message;
|
|
393
395
|
} catch (error) {
|
|
394
|
-
logger$
|
|
396
|
+
logger$3.error(methodName, 'error', error);
|
|
395
397
|
}
|
|
396
398
|
};
|
|
397
399
|
|
|
@@ -407,15 +409,15 @@ const chatWithStreaming = async (client, chatOptions, callbackOptions) => {
|
|
|
407
409
|
|
|
408
410
|
// check
|
|
409
411
|
if (!client) {
|
|
410
|
-
logger$
|
|
412
|
+
logger$3.error(methodName, 'need client');
|
|
411
413
|
return;
|
|
412
414
|
}
|
|
413
415
|
if (!chatOptions) {
|
|
414
|
-
logger$
|
|
416
|
+
logger$3.error(methodName, 'need chatOptions');
|
|
415
417
|
return;
|
|
416
418
|
}
|
|
417
419
|
if (!callbackOptions) {
|
|
418
|
-
logger$
|
|
420
|
+
logger$3.error(methodName, 'need callbackOptions');
|
|
419
421
|
return;
|
|
420
422
|
}
|
|
421
423
|
|
|
@@ -469,7 +471,7 @@ const chatWithStreaming = async (client, chatOptions, callbackOptions) => {
|
|
|
469
471
|
};
|
|
470
472
|
|
|
471
473
|
// openai
|
|
472
|
-
const logger = qiao_log_js.Logger('openai.js');
|
|
474
|
+
const logger$2 = qiao_log_js.Logger('openai.js');
|
|
473
475
|
|
|
474
476
|
/**
|
|
475
477
|
* OpenAI
|
|
@@ -481,24 +483,28 @@ const OpenAIAPI = (options) => {
|
|
|
481
483
|
|
|
482
484
|
// check
|
|
483
485
|
if (!options) {
|
|
484
|
-
logger.error(methodName, 'need options');
|
|
486
|
+
logger$2.error(methodName, 'need options');
|
|
485
487
|
return;
|
|
486
488
|
}
|
|
487
489
|
if (!options.apiKey) {
|
|
488
|
-
logger.error(methodName, 'need options.apiKey');
|
|
490
|
+
logger$2.error(methodName, 'need options.apiKey');
|
|
489
491
|
return;
|
|
490
492
|
}
|
|
491
493
|
if (!options.baseURL) {
|
|
492
|
-
logger.error(methodName, 'need options.baseURL');
|
|
494
|
+
logger$2.error(methodName, 'need options.baseURL');
|
|
493
495
|
return;
|
|
494
496
|
}
|
|
495
497
|
|
|
496
498
|
// openai
|
|
497
499
|
const openai = {};
|
|
498
|
-
|
|
500
|
+
const clientOptions = {
|
|
499
501
|
apiKey: options.apiKey,
|
|
500
502
|
baseURL: options.baseURL,
|
|
501
|
-
}
|
|
503
|
+
};
|
|
504
|
+
if (options.defaultHeaders) {
|
|
505
|
+
clientOptions.defaultHeaders = options.defaultHeaders;
|
|
506
|
+
}
|
|
507
|
+
openai.client = new OpenAI(clientOptions);
|
|
502
508
|
|
|
503
509
|
// chat
|
|
504
510
|
openai.chat = async (chatOptions) => {
|
|
@@ -514,6 +520,281 @@ const OpenAIAPI = (options) => {
|
|
|
514
520
|
return openai;
|
|
515
521
|
};
|
|
516
522
|
|
|
523
|
+
// crypto
|
|
524
|
+
const logger$1 = qiao_log_js.Logger('liblib-util.js');
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* generateSignature
|
|
528
|
+
* @param {*} uri
|
|
529
|
+
* @param {*} secretKey
|
|
530
|
+
* @returns
|
|
531
|
+
*/
|
|
532
|
+
const generateSignature = (uri, secretKey) => {
|
|
533
|
+
const timestamp = String(Date.now());
|
|
534
|
+
const signatureNonce = crypto.randomBytes(8).toString('hex');
|
|
535
|
+
const content = `${uri}&${timestamp}&${signatureNonce}`;
|
|
536
|
+
|
|
537
|
+
const hmac = crypto.createHmac('sha1', secretKey);
|
|
538
|
+
hmac.update(content);
|
|
539
|
+
const signature = hmac.digest('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
540
|
+
|
|
541
|
+
return { signature, timestamp, signatureNonce };
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* request
|
|
546
|
+
* @param {*} baseURL
|
|
547
|
+
* @param {*} accessKey
|
|
548
|
+
* @param {*} secretKey
|
|
549
|
+
* @param {*} uri
|
|
550
|
+
* @param {*} body
|
|
551
|
+
* @returns
|
|
552
|
+
*/
|
|
553
|
+
const request = (baseURL, accessKey, secretKey, uri, body) => {
|
|
554
|
+
const methodName = 'request';
|
|
555
|
+
|
|
556
|
+
return new Promise((resolve, reject) => {
|
|
557
|
+
const { signature, timestamp, signatureNonce } = generateSignature(uri, secretKey);
|
|
558
|
+
const query =
|
|
559
|
+
`AccessKey=${accessKey}` +
|
|
560
|
+
`&Signature=${signature}` +
|
|
561
|
+
`&Timestamp=${timestamp}` +
|
|
562
|
+
`&SignatureNonce=${signatureNonce}`;
|
|
563
|
+
|
|
564
|
+
const postData = JSON.stringify(body);
|
|
565
|
+
|
|
566
|
+
const options = {
|
|
567
|
+
hostname: baseURL,
|
|
568
|
+
path: `${uri}?${query}`,
|
|
569
|
+
method: 'POST',
|
|
570
|
+
headers: {
|
|
571
|
+
'Content-Type': 'application/json',
|
|
572
|
+
'Content-Length': Buffer.byteLength(postData),
|
|
573
|
+
},
|
|
574
|
+
};
|
|
575
|
+
|
|
576
|
+
const req = https.request(options, (res) => {
|
|
577
|
+
let data = '';
|
|
578
|
+
res.on('data', (chunk) => {
|
|
579
|
+
data += chunk;
|
|
580
|
+
});
|
|
581
|
+
res.on('end', () => {
|
|
582
|
+
try {
|
|
583
|
+
resolve(JSON.parse(data));
|
|
584
|
+
} catch (e) {
|
|
585
|
+
logger$1.error(methodName, 'JSON parse error', data);
|
|
586
|
+
reject(new Error('JSON parse error: ' + data));
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
req.on('error', (error) => {
|
|
592
|
+
logger$1.error(methodName, 'request error', error);
|
|
593
|
+
reject(error);
|
|
594
|
+
});
|
|
595
|
+
req.write(postData);
|
|
596
|
+
req.end();
|
|
597
|
+
});
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* text2img
|
|
602
|
+
* @param {*} baseURL
|
|
603
|
+
* @param {*} accessKey
|
|
604
|
+
* @param {*} secretKey
|
|
605
|
+
* @param {*} prompt
|
|
606
|
+
* @param {*} options
|
|
607
|
+
* @returns
|
|
608
|
+
*/
|
|
609
|
+
const text2img = (baseURL, accessKey, secretKey, prompt, options) => {
|
|
610
|
+
const methodName = 'text2img';
|
|
611
|
+
|
|
612
|
+
// check
|
|
613
|
+
if (!prompt) {
|
|
614
|
+
logger$1.error(methodName, 'need prompt');
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
options = options || {};
|
|
619
|
+
const generateParams = {
|
|
620
|
+
prompt: prompt,
|
|
621
|
+
aspectRatio: options.aspectRatio || 'portrait',
|
|
622
|
+
imgCount: options.imgCount || 1,
|
|
623
|
+
steps: options.steps || 30,
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
if (options.width && options.height) {
|
|
627
|
+
delete generateParams.aspectRatio;
|
|
628
|
+
generateParams.imageSize = {
|
|
629
|
+
width: options.width,
|
|
630
|
+
height: options.height,
|
|
631
|
+
};
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
if (options.controlnet) {
|
|
635
|
+
generateParams.controlnet = options.controlnet;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
return request(baseURL, accessKey, secretKey, '/api/generate/webui/text2img/ultra', {
|
|
639
|
+
templateUuid: '5d7e67009b344550bc1aa6ccbfa1d7f4',
|
|
640
|
+
generateParams: generateParams,
|
|
641
|
+
});
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* img2img
|
|
646
|
+
* @param {*} baseURL
|
|
647
|
+
* @param {*} accessKey
|
|
648
|
+
* @param {*} secretKey
|
|
649
|
+
* @param {*} prompt
|
|
650
|
+
* @param {*} sourceImage
|
|
651
|
+
* @param {*} options
|
|
652
|
+
* @returns
|
|
653
|
+
*/
|
|
654
|
+
const img2img = (baseURL, accessKey, secretKey, prompt, sourceImage, options) => {
|
|
655
|
+
const methodName = 'img2img';
|
|
656
|
+
|
|
657
|
+
// check
|
|
658
|
+
if (!prompt) {
|
|
659
|
+
logger$1.error(methodName, 'need prompt');
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
if (!sourceImage) {
|
|
663
|
+
logger$1.error(methodName, 'need sourceImage');
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
options = options || {};
|
|
668
|
+
const generateParams = {
|
|
669
|
+
prompt: prompt,
|
|
670
|
+
sourceImage: sourceImage,
|
|
671
|
+
imgCount: options.imgCount || 1,
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
if (options.controlnet) {
|
|
675
|
+
generateParams.controlnet = options.controlnet;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
return request(baseURL, accessKey, secretKey, '/api/generate/webui/img2img/ultra', {
|
|
679
|
+
templateUuid: '07e00af4fc464c7ab55ff906f8acf1b7',
|
|
680
|
+
generateParams: generateParams,
|
|
681
|
+
});
|
|
682
|
+
};
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* queryStatus
|
|
686
|
+
* @param {*} baseURL
|
|
687
|
+
* @param {*} accessKey
|
|
688
|
+
* @param {*} secretKey
|
|
689
|
+
* @param {*} generateUuid
|
|
690
|
+
* @returns
|
|
691
|
+
*/
|
|
692
|
+
const queryStatus = (baseURL, accessKey, secretKey, generateUuid) => {
|
|
693
|
+
return request(baseURL, accessKey, secretKey, '/api/generate/webui/status', {
|
|
694
|
+
generateUuid: generateUuid,
|
|
695
|
+
});
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* waitForResult
|
|
700
|
+
* @param {*} baseURL
|
|
701
|
+
* @param {*} accessKey
|
|
702
|
+
* @param {*} secretKey
|
|
703
|
+
* @param {*} generateUuid
|
|
704
|
+
* @param {*} intervalMs
|
|
705
|
+
* @param {*} maxRetries
|
|
706
|
+
* @returns
|
|
707
|
+
*/
|
|
708
|
+
const waitForResult = (baseURL, accessKey, secretKey, generateUuid, intervalMs, maxRetries) => {
|
|
709
|
+
intervalMs = intervalMs || 3000;
|
|
710
|
+
maxRetries = maxRetries || 60;
|
|
711
|
+
|
|
712
|
+
return new Promise((resolve, reject) => {
|
|
713
|
+
let attempt = 0;
|
|
714
|
+
|
|
715
|
+
function poll() {
|
|
716
|
+
attempt++;
|
|
717
|
+
queryStatus(baseURL, accessKey, secretKey, generateUuid)
|
|
718
|
+
.then((res) => {
|
|
719
|
+
const status = res.data && res.data.generateStatus;
|
|
720
|
+
|
|
721
|
+
if (status === 5) {
|
|
722
|
+
return resolve(res.data);
|
|
723
|
+
}
|
|
724
|
+
if (status === 6 || status === 7) {
|
|
725
|
+
return reject(new Error('Generation failed: ' + (res.data.generateMsg || 'unknown')));
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if (attempt >= maxRetries) {
|
|
729
|
+
return reject(new Error('Polling timeout after ' + maxRetries + ' retries'));
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
setTimeout(poll, intervalMs);
|
|
733
|
+
})
|
|
734
|
+
.catch(reject);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
poll();
|
|
738
|
+
});
|
|
739
|
+
};
|
|
740
|
+
|
|
741
|
+
// util
|
|
742
|
+
const logger = qiao_log_js.Logger('liblib.js');
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* LibLibAPI
|
|
746
|
+
* @param {*} options
|
|
747
|
+
* @returns
|
|
748
|
+
*/
|
|
749
|
+
const LibLibAPI = (options) => {
|
|
750
|
+
const methodName = 'LibLibAPI';
|
|
751
|
+
|
|
752
|
+
// check
|
|
753
|
+
if (!options) {
|
|
754
|
+
logger.error(methodName, 'need options');
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
if (!options.accessKey) {
|
|
758
|
+
logger.error(methodName, 'need options.accessKey');
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
if (!options.secretKey) {
|
|
762
|
+
logger.error(methodName, 'need options.secretKey');
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// config
|
|
767
|
+
const baseURL = options.baseURL || 'openapi.liblibai.cloud';
|
|
768
|
+
const accessKey = options.accessKey;
|
|
769
|
+
const secretKey = options.secretKey;
|
|
770
|
+
|
|
771
|
+
// liblib
|
|
772
|
+
const liblib = {};
|
|
773
|
+
|
|
774
|
+
// text2img
|
|
775
|
+
liblib.text2img = async (prompt, imgOptions) => {
|
|
776
|
+
return await text2img(baseURL, accessKey, secretKey, prompt, imgOptions);
|
|
777
|
+
};
|
|
778
|
+
|
|
779
|
+
// img2img
|
|
780
|
+
liblib.img2img = async (prompt, sourceImage, imgOptions) => {
|
|
781
|
+
return await img2img(baseURL, accessKey, secretKey, prompt, sourceImage, imgOptions);
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
// queryStatus
|
|
785
|
+
liblib.queryStatus = async (generateUuid) => {
|
|
786
|
+
return await queryStatus(baseURL, accessKey, secretKey, generateUuid);
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
// waitForResult
|
|
790
|
+
liblib.waitForResult = async (generateUuid, intervalMs, maxRetries) => {
|
|
791
|
+
return await waitForResult(baseURL, accessKey, secretKey, generateUuid, intervalMs, maxRetries);
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
//
|
|
795
|
+
return liblib;
|
|
796
|
+
};
|
|
797
|
+
|
|
517
798
|
/**
|
|
518
799
|
* callLLM
|
|
519
800
|
* @param {*} options
|
|
@@ -608,5 +889,6 @@ const runAgents = async (agents) => {
|
|
|
608
889
|
|
|
609
890
|
exports.GeminiAPI = GeminiAPI;
|
|
610
891
|
exports.GeminiVertex = GeminiVertex;
|
|
892
|
+
exports.LibLibAPI = LibLibAPI;
|
|
611
893
|
exports.OpenAIAPI = OpenAIAPI;
|
|
612
894
|
exports.runAgents = runAgents;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "viho-llm",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Utility library for working with multiple LLM providers (Google Gemini and OpenAI), providing common tools and helpers for AI interactions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"llm",
|
|
@@ -68,5 +68,5 @@
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
},
|
|
71
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "990e74da184751aaee5085fe87a4a9f87fa33064"
|
|
72
72
|
}
|
package/src/index.js
CHANGED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// crypto
|
|
2
|
+
import crypto from 'crypto';
|
|
3
|
+
|
|
4
|
+
// https
|
|
5
|
+
import https from 'https';
|
|
6
|
+
|
|
7
|
+
// Logger
|
|
8
|
+
import { Logger } from 'qiao.log.js';
|
|
9
|
+
const logger = Logger('liblib-util.js');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* generateSignature
|
|
13
|
+
* @param {*} uri
|
|
14
|
+
* @param {*} secretKey
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
export const generateSignature = (uri, secretKey) => {
|
|
18
|
+
const timestamp = String(Date.now());
|
|
19
|
+
const signatureNonce = crypto.randomBytes(8).toString('hex');
|
|
20
|
+
const content = `${uri}&${timestamp}&${signatureNonce}`;
|
|
21
|
+
|
|
22
|
+
const hmac = crypto.createHmac('sha1', secretKey);
|
|
23
|
+
hmac.update(content);
|
|
24
|
+
const signature = hmac.digest('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
25
|
+
|
|
26
|
+
return { signature, timestamp, signatureNonce };
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* request
|
|
31
|
+
* @param {*} baseURL
|
|
32
|
+
* @param {*} accessKey
|
|
33
|
+
* @param {*} secretKey
|
|
34
|
+
* @param {*} uri
|
|
35
|
+
* @param {*} body
|
|
36
|
+
* @returns
|
|
37
|
+
*/
|
|
38
|
+
export const request = (baseURL, accessKey, secretKey, uri, body) => {
|
|
39
|
+
const methodName = 'request';
|
|
40
|
+
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const { signature, timestamp, signatureNonce } = generateSignature(uri, secretKey);
|
|
43
|
+
const query =
|
|
44
|
+
`AccessKey=${accessKey}` +
|
|
45
|
+
`&Signature=${signature}` +
|
|
46
|
+
`&Timestamp=${timestamp}` +
|
|
47
|
+
`&SignatureNonce=${signatureNonce}`;
|
|
48
|
+
|
|
49
|
+
const postData = JSON.stringify(body);
|
|
50
|
+
|
|
51
|
+
const options = {
|
|
52
|
+
hostname: baseURL,
|
|
53
|
+
path: `${uri}?${query}`,
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: {
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
'Content-Length': Buffer.byteLength(postData),
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const req = https.request(options, (res) => {
|
|
62
|
+
let data = '';
|
|
63
|
+
res.on('data', (chunk) => {
|
|
64
|
+
data += chunk;
|
|
65
|
+
});
|
|
66
|
+
res.on('end', () => {
|
|
67
|
+
try {
|
|
68
|
+
resolve(JSON.parse(data));
|
|
69
|
+
} catch (e) {
|
|
70
|
+
logger.error(methodName, 'JSON parse error', data);
|
|
71
|
+
reject(new Error('JSON parse error: ' + data));
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
req.on('error', (error) => {
|
|
77
|
+
logger.error(methodName, 'request error', error);
|
|
78
|
+
reject(error);
|
|
79
|
+
});
|
|
80
|
+
req.write(postData);
|
|
81
|
+
req.end();
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* text2img
|
|
87
|
+
* @param {*} baseURL
|
|
88
|
+
* @param {*} accessKey
|
|
89
|
+
* @param {*} secretKey
|
|
90
|
+
* @param {*} prompt
|
|
91
|
+
* @param {*} options
|
|
92
|
+
* @returns
|
|
93
|
+
*/
|
|
94
|
+
export const text2img = (baseURL, accessKey, secretKey, prompt, options) => {
|
|
95
|
+
const methodName = 'text2img';
|
|
96
|
+
|
|
97
|
+
// check
|
|
98
|
+
if (!prompt) {
|
|
99
|
+
logger.error(methodName, 'need prompt');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
options = options || {};
|
|
104
|
+
const generateParams = {
|
|
105
|
+
prompt: prompt,
|
|
106
|
+
aspectRatio: options.aspectRatio || 'portrait',
|
|
107
|
+
imgCount: options.imgCount || 1,
|
|
108
|
+
steps: options.steps || 30,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
if (options.width && options.height) {
|
|
112
|
+
delete generateParams.aspectRatio;
|
|
113
|
+
generateParams.imageSize = {
|
|
114
|
+
width: options.width,
|
|
115
|
+
height: options.height,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (options.controlnet) {
|
|
120
|
+
generateParams.controlnet = options.controlnet;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return request(baseURL, accessKey, secretKey, '/api/generate/webui/text2img/ultra', {
|
|
124
|
+
templateUuid: '5d7e67009b344550bc1aa6ccbfa1d7f4',
|
|
125
|
+
generateParams: generateParams,
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* img2img
|
|
131
|
+
* @param {*} baseURL
|
|
132
|
+
* @param {*} accessKey
|
|
133
|
+
* @param {*} secretKey
|
|
134
|
+
* @param {*} prompt
|
|
135
|
+
* @param {*} sourceImage
|
|
136
|
+
* @param {*} options
|
|
137
|
+
* @returns
|
|
138
|
+
*/
|
|
139
|
+
export const img2img = (baseURL, accessKey, secretKey, prompt, sourceImage, options) => {
|
|
140
|
+
const methodName = 'img2img';
|
|
141
|
+
|
|
142
|
+
// check
|
|
143
|
+
if (!prompt) {
|
|
144
|
+
logger.error(methodName, 'need prompt');
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (!sourceImage) {
|
|
148
|
+
logger.error(methodName, 'need sourceImage');
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
options = options || {};
|
|
153
|
+
const generateParams = {
|
|
154
|
+
prompt: prompt,
|
|
155
|
+
sourceImage: sourceImage,
|
|
156
|
+
imgCount: options.imgCount || 1,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
if (options.controlnet) {
|
|
160
|
+
generateParams.controlnet = options.controlnet;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return request(baseURL, accessKey, secretKey, '/api/generate/webui/img2img/ultra', {
|
|
164
|
+
templateUuid: '07e00af4fc464c7ab55ff906f8acf1b7',
|
|
165
|
+
generateParams: generateParams,
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* queryStatus
|
|
171
|
+
* @param {*} baseURL
|
|
172
|
+
* @param {*} accessKey
|
|
173
|
+
* @param {*} secretKey
|
|
174
|
+
* @param {*} generateUuid
|
|
175
|
+
* @returns
|
|
176
|
+
*/
|
|
177
|
+
export const queryStatus = (baseURL, accessKey, secretKey, generateUuid) => {
|
|
178
|
+
return request(baseURL, accessKey, secretKey, '/api/generate/webui/status', {
|
|
179
|
+
generateUuid: generateUuid,
|
|
180
|
+
});
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* waitForResult
|
|
185
|
+
* @param {*} baseURL
|
|
186
|
+
* @param {*} accessKey
|
|
187
|
+
* @param {*} secretKey
|
|
188
|
+
* @param {*} generateUuid
|
|
189
|
+
* @param {*} intervalMs
|
|
190
|
+
* @param {*} maxRetries
|
|
191
|
+
* @returns
|
|
192
|
+
*/
|
|
193
|
+
export const waitForResult = (baseURL, accessKey, secretKey, generateUuid, intervalMs, maxRetries) => {
|
|
194
|
+
intervalMs = intervalMs || 3000;
|
|
195
|
+
maxRetries = maxRetries || 60;
|
|
196
|
+
|
|
197
|
+
return new Promise((resolve, reject) => {
|
|
198
|
+
let attempt = 0;
|
|
199
|
+
|
|
200
|
+
function poll() {
|
|
201
|
+
attempt++;
|
|
202
|
+
queryStatus(baseURL, accessKey, secretKey, generateUuid)
|
|
203
|
+
.then((res) => {
|
|
204
|
+
const status = res.data && res.data.generateStatus;
|
|
205
|
+
|
|
206
|
+
if (status === 5) {
|
|
207
|
+
return resolve(res.data);
|
|
208
|
+
}
|
|
209
|
+
if (status === 6 || status === 7) {
|
|
210
|
+
return reject(new Error('Generation failed: ' + (res.data.generateMsg || 'unknown')));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (attempt >= maxRetries) {
|
|
214
|
+
return reject(new Error('Polling timeout after ' + maxRetries + ' retries'));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
setTimeout(poll, intervalMs);
|
|
218
|
+
})
|
|
219
|
+
.catch(reject);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
poll();
|
|
223
|
+
});
|
|
224
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// util
|
|
2
|
+
import { text2img, img2img, queryStatus, waitForResult } from './liblib-util.js';
|
|
3
|
+
|
|
4
|
+
// Logger
|
|
5
|
+
import { Logger } from 'qiao.log.js';
|
|
6
|
+
const logger = Logger('liblib.js');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* LibLibAPI
|
|
10
|
+
* @param {*} options
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
export const LibLibAPI = (options) => {
|
|
14
|
+
const methodName = 'LibLibAPI';
|
|
15
|
+
|
|
16
|
+
// check
|
|
17
|
+
if (!options) {
|
|
18
|
+
logger.error(methodName, 'need options');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!options.accessKey) {
|
|
22
|
+
logger.error(methodName, 'need options.accessKey');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (!options.secretKey) {
|
|
26
|
+
logger.error(methodName, 'need options.secretKey');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// config
|
|
31
|
+
const baseURL = options.baseURL || 'openapi.liblibai.cloud';
|
|
32
|
+
const accessKey = options.accessKey;
|
|
33
|
+
const secretKey = options.secretKey;
|
|
34
|
+
|
|
35
|
+
// liblib
|
|
36
|
+
const liblib = {};
|
|
37
|
+
|
|
38
|
+
// text2img
|
|
39
|
+
liblib.text2img = async (prompt, imgOptions) => {
|
|
40
|
+
return await text2img(baseURL, accessKey, secretKey, prompt, imgOptions);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// img2img
|
|
44
|
+
liblib.img2img = async (prompt, sourceImage, imgOptions) => {
|
|
45
|
+
return await img2img(baseURL, accessKey, secretKey, prompt, sourceImage, imgOptions);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// queryStatus
|
|
49
|
+
liblib.queryStatus = async (generateUuid) => {
|
|
50
|
+
return await queryStatus(baseURL, accessKey, secretKey, generateUuid);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// waitForResult
|
|
54
|
+
liblib.waitForResult = async (generateUuid, intervalMs, maxRetries) => {
|
|
55
|
+
return await waitForResult(baseURL, accessKey, secretKey, generateUuid, intervalMs, maxRetries);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
//
|
|
59
|
+
return liblib;
|
|
60
|
+
};
|
package/src/models/openai.js
CHANGED
|
@@ -32,10 +32,14 @@ export const OpenAIAPI = (options) => {
|
|
|
32
32
|
|
|
33
33
|
// openai
|
|
34
34
|
const openai = {};
|
|
35
|
-
|
|
35
|
+
const clientOptions = {
|
|
36
36
|
apiKey: options.apiKey,
|
|
37
37
|
baseURL: options.baseURL,
|
|
38
|
-
}
|
|
38
|
+
};
|
|
39
|
+
if (options.defaultHeaders) {
|
|
40
|
+
clientOptions.defaultHeaders = options.defaultHeaders;
|
|
41
|
+
}
|
|
42
|
+
openai.client = new OpenAI(clientOptions);
|
|
39
43
|
|
|
40
44
|
// chat
|
|
41
45
|
openai.chat = async (chatOptions) => {
|