doomiaichat 2.1.0 → 2.3.0
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/dist/azureai.js +3 -9
- package/dist/baiduai.d.ts +35 -0
- package/dist/baiduai.js +113 -0
- package/dist/declare.d.ts +41 -2
- package/dist/declare.js +33 -0
- package/dist/gptbase.d.ts +63 -0
- package/dist/gptbase.js +12 -0
- package/dist/gptprovider.d.ts +20 -0
- package/dist/gptprovider.js +44 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -2
- package/dist/openai.d.ts +16 -4
- package/dist/openai.js +115 -59
- package/dist/openaiprovider.d.ts +3 -5
- package/dist/openaiprovider.js +7 -3
- package/package.json +1 -1
- package/src/azureai.ts +3 -11
- package/src/baiduai.ts +106 -0
- package/src/declare.ts +56 -1
- package/src/gptbase.ts +65 -0
- package/src/gptprovider.ts +38 -0
- package/src/index.ts +2 -1
- package/src/openai.ts +121 -74
- package/src/openaiprovider.ts +0 -32
package/dist/openai.js
CHANGED
|
@@ -8,9 +8,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
const openai_1 = require("openai");
|
|
13
|
-
|
|
16
|
+
// import { EventEmitter } from "events";
|
|
17
|
+
const gptbase_1 = __importDefault(require("./gptbase"));
|
|
14
18
|
const SECTION_LENGTH = 1600; ///每2400个字符分成一组
|
|
15
19
|
const MESSAGE_LENGTH = 1; ///每次送8句话给openai 进行解析,送多了,会报错
|
|
16
20
|
//请将答案放在最后,标记为答案:()
|
|
@@ -21,7 +25,7 @@ const QUESTION_TEXT_MAPPING = {
|
|
|
21
25
|
completion: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道填空题和对应答案,输出结果必须是JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]的结构输出' //请将答案放在最后,标记为答案:()
|
|
22
26
|
};
|
|
23
27
|
const QUESTION_TYPE = ['singlechoice', 'multiplechoice', 'trueorfalse', 'completion'];
|
|
24
|
-
class OpenAIGpt extends
|
|
28
|
+
class OpenAIGpt extends gptbase_1.default {
|
|
25
29
|
/**
|
|
26
30
|
*
|
|
27
31
|
* @param apiKey 调用OpenAI 的key
|
|
@@ -71,6 +75,40 @@ class OpenAIGpt extends events_1.EventEmitter {
|
|
|
71
75
|
}
|
|
72
76
|
});
|
|
73
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* 点评问题回答的评价
|
|
80
|
+
* @param question
|
|
81
|
+
* @param answer
|
|
82
|
+
* @param axiosOption
|
|
83
|
+
*/
|
|
84
|
+
commentQuestionAnswer(question, answer, axiosOption = { timeout: 30000 }) {
|
|
85
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
86
|
+
if (!question || !answer)
|
|
87
|
+
return { successed: false, error: { errcode: 2, errmsg: '缺失参数' } };
|
|
88
|
+
let message = [
|
|
89
|
+
{ role: 'system', content: '你是一名专业的培训师。' },
|
|
90
|
+
{ role: 'user', content: `问题题干:“${question}”` },
|
|
91
|
+
{ role: 'user', content: `回答内容:“${answer}”` },
|
|
92
|
+
{ role: 'user', content: `请根据以上的回答内容进行点评,给出一段不超过200字的评语,以及0-100的得分。最终结果按照{"comment":"评语","score":80}的JSON结构输出` }
|
|
93
|
+
];
|
|
94
|
+
const result = yield this.chatRequest(message, {}, axiosOption);
|
|
95
|
+
if (result.successed && result.message) {
|
|
96
|
+
let value = result.message[0].message.content.trim();
|
|
97
|
+
let replyJson = this.fixedJsonString(value);
|
|
98
|
+
///能够提取到内容
|
|
99
|
+
if (replyJson.length)
|
|
100
|
+
return Object.assign({ successed: true }, replyJson[0]);
|
|
101
|
+
///回答的内容非JSON格式,自己来提取算了
|
|
102
|
+
console.log('自己组装');
|
|
103
|
+
let matched = value.match(/\d+分/g), score = 0;
|
|
104
|
+
if (matched && matched.length) {
|
|
105
|
+
score = Number(matched[0].replace('分', ''));
|
|
106
|
+
}
|
|
107
|
+
return { successed: true, comment: value, score };
|
|
108
|
+
}
|
|
109
|
+
return { successed: false };
|
|
110
|
+
});
|
|
111
|
+
}
|
|
74
112
|
/**
|
|
75
113
|
* 判断一句话的表达情绪
|
|
76
114
|
* @param {*} s1
|
|
@@ -195,7 +233,7 @@ class OpenAIGpt extends events_1.EventEmitter {
|
|
|
195
233
|
//subarray.push({ role: 'user', content:'请根据上述内容,给出一道提问与答案以及答案关键词,按照先问题内容,再标准答案,再关键词的顺序输出,关键词之间用、分开'})
|
|
196
234
|
subarray.unshift({ role: 'system', content: `你是一位专业培训师,从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON数组结构输出。` });
|
|
197
235
|
//subarray.unshift({ role: 'system', content: `你是一位专业程序开发工程师,根据以下内容,按照[{"question":"问题内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]JSON数组结构,给出${itemCount}条提问问题及答案以及答案关键词` })
|
|
198
|
-
console.log('subarray', subarray)
|
|
236
|
+
// console.log('subarray', subarray)
|
|
199
237
|
let result = yield this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
|
|
200
238
|
if (result.successed && result.message) {
|
|
201
239
|
// console.log('result is ', result.message[0].message.content)
|
|
@@ -213,7 +251,7 @@ class OpenAIGpt extends events_1.EventEmitter {
|
|
|
213
251
|
arrContent = []; /// 释放内存
|
|
214
252
|
///发出信号,解析完毕
|
|
215
253
|
this.emit('parseover', { type: 'qa', items: faqs });
|
|
216
|
-
return { successed: true, message: faqs };
|
|
254
|
+
return { successed: true, message: faqs.slice(0, count) };
|
|
217
255
|
});
|
|
218
256
|
}
|
|
219
257
|
/**
|
|
@@ -255,16 +293,18 @@ class OpenAIGpt extends events_1.EventEmitter {
|
|
|
255
293
|
*/
|
|
256
294
|
pickUpFaqContent(messages) {
|
|
257
295
|
let answerString = messages[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
258
|
-
const firstsybmol = answerString.indexOf("[");
|
|
259
|
-
const lastsybmol = answerString.lastIndexOf("]");
|
|
260
|
-
console.log('answerString', answerString)
|
|
261
|
-
if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol)
|
|
296
|
+
// const firstsybmol = answerString.indexOf("["); ////必须过滤出来数组
|
|
297
|
+
// const lastsybmol = answerString.lastIndexOf("]");
|
|
298
|
+
// console.log('answerString', answerString)
|
|
299
|
+
// if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol) return [];
|
|
300
|
+
// answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
301
|
+
// console.log('answerString', answerString)
|
|
302
|
+
let jsonObj = this.fixedJsonString(answerString);
|
|
303
|
+
if (!jsonObj.length)
|
|
262
304
|
return [];
|
|
263
|
-
answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
264
|
-
console.log('answerString', answerString);
|
|
265
305
|
try {
|
|
266
306
|
//let jsonObj = JSON.parse(answerString);
|
|
267
|
-
let jsonObj = eval(answerString);
|
|
307
|
+
//let jsonObj = eval(answerString);
|
|
268
308
|
jsonObj.map((item) => {
|
|
269
309
|
let realKeyword = [];
|
|
270
310
|
let keywords = (item.keywords + '').split(',');
|
|
@@ -364,29 +404,32 @@ class OpenAIGpt extends events_1.EventEmitter {
|
|
|
364
404
|
*/
|
|
365
405
|
pickUpQuestions(result, count, questiontype, score = 1) {
|
|
366
406
|
let answerString = result[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
367
|
-
const firstsybmol = answerString.indexOf("[");
|
|
368
|
-
const lastsybmol = answerString.lastIndexOf("]");
|
|
369
|
-
console.log('answerString', answerString)
|
|
370
|
-
if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol)
|
|
407
|
+
// const firstsybmol = answerString.indexOf("["); ////必须过滤出来数组
|
|
408
|
+
// const lastsybmol = answerString.lastIndexOf("]");
|
|
409
|
+
// console.log('answerString', answerString)
|
|
410
|
+
// if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol) return [];
|
|
411
|
+
// answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
412
|
+
// console.log('answerString', answerString)
|
|
413
|
+
let jsonObj = this.fixedJsonString(answerString);
|
|
414
|
+
if (!jsonObj.length)
|
|
371
415
|
return [];
|
|
372
|
-
answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
373
|
-
console.log('answerString', answerString);
|
|
374
416
|
let returnItems = [];
|
|
375
417
|
try {
|
|
376
|
-
let jsonObj = JSON.parse(answerString);
|
|
418
|
+
// let jsonObj = JSON.parse(answerString);
|
|
377
419
|
returnItems = jsonObj.map((questionitem) => {
|
|
378
|
-
console.log('answer item', questionitem);
|
|
420
|
+
console.log('answer item from jsonObj', questionitem);
|
|
379
421
|
if (questionitem.choice && Array.isArray(questionitem.choice) && questiontype != 'completion') {
|
|
380
422
|
questionitem.fullanswer = (questionitem.answer + '').replace(/,|[^ABCDE]/g, '');
|
|
381
423
|
questionitem.score = score;
|
|
382
424
|
if (questionitem.choice) {
|
|
383
425
|
questionitem.choice = questionitem.choice.map((item, index) => {
|
|
384
|
-
let seqNo = String.fromCharCode(65 + index);
|
|
426
|
+
let seqNo = 'ABCDEFG'[index]; //String.fromCharCode(65 + index);
|
|
385
427
|
let correctReg = new RegExp(`${seqNo}.|${seqNo}`, 'ig');
|
|
428
|
+
// console.log('itemitemitem', item)
|
|
386
429
|
//let answer = jsonObj.fullanswer
|
|
387
430
|
return {
|
|
388
431
|
id: seqNo,
|
|
389
|
-
content: item.replace(correctReg, '').trim(),
|
|
432
|
+
content: (item + '').replace(correctReg, '').trim(),
|
|
390
433
|
iscorrect: (questionitem.fullanswer || '').indexOf(seqNo) >= 0 ? 1 : 0
|
|
391
434
|
//|| jsonObj.fullanswer.indexOf(m))
|
|
392
435
|
};
|
|
@@ -411,7 +454,7 @@ class OpenAIGpt extends events_1.EventEmitter {
|
|
|
411
454
|
}
|
|
412
455
|
///单选题验证
|
|
413
456
|
if (questiontype == 'singlechoice') {
|
|
414
|
-
let rightAnswer = questionitem.choice ? questionitem.choice.filter(item => { return item.iscorrect === 1; }) : [];
|
|
457
|
+
let rightAnswer = questionitem.choice ? questionitem.choice.filter((item) => { return item.iscorrect === 1; }) : [];
|
|
415
458
|
///单选题的正确选项大于了1个
|
|
416
459
|
if (rightAnswer.length != 1 || !questionitem.answer || questionitem.answer.length !== 1)
|
|
417
460
|
return null;
|
|
@@ -421,7 +464,7 @@ class OpenAIGpt extends events_1.EventEmitter {
|
|
|
421
464
|
}
|
|
422
465
|
///多选题验证
|
|
423
466
|
if (questiontype == 'multiplechoice') {
|
|
424
|
-
let rightAnswer = questionitem.choice ? questionitem.choice.filter(item => { return item.iscorrect === 1; }) : [];
|
|
467
|
+
let rightAnswer = questionitem.choice ? questionitem.choice.filter((item) => { return item.iscorrect === 1; }) : [];
|
|
425
468
|
///单选题的正确选项大于了1个
|
|
426
469
|
if (rightAnswer.length === 0 || !questionitem.answer || questionitem.answer.length === 0)
|
|
427
470
|
return null;
|
|
@@ -433,42 +476,55 @@ class OpenAIGpt extends events_1.EventEmitter {
|
|
|
433
476
|
console.log('error happened:', err);
|
|
434
477
|
}
|
|
435
478
|
return returnItems.filter(i => { return i != null; }).slice(0, count);
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* 验证JSON字符串是否是真正可转换为JSON的合法格式
|
|
482
|
+
* 这里只能做一个最简单的处理,就是用两端的符号
|
|
483
|
+
* @param jsonstr
|
|
484
|
+
*/
|
|
485
|
+
fixedJsonString(jsonstr) {
|
|
486
|
+
console.log('original json string:', jsonstr);
|
|
487
|
+
///检查返回的是不是一个数组对象(我们需要的是数组对象)
|
|
488
|
+
let firstBracketSymbol = jsonstr.indexOf("["); ////必须过滤出来数组
|
|
489
|
+
let lastBracketSymbol = jsonstr.lastIndexOf("]");
|
|
490
|
+
///第一个花括号出现的位置,如果花括号出现的位置早于 [ ,则默认返回的对象不是一个数组,仅仅是一个对象,
|
|
491
|
+
///则需要我们用中括号包住
|
|
492
|
+
let firstBraceSymbol = jsonstr.indexOf("{");
|
|
493
|
+
let lastBraceSymbol = jsonstr.lastIndexOf("}");
|
|
494
|
+
///返回的不是一个数组结构的,只是一个{},我们帮他完成数组拼接
|
|
495
|
+
if (firstBraceSymbol >= 0 &&
|
|
496
|
+
firstBraceSymbol < (firstBracketSymbol >= 0 ? firstBracketSymbol : 1000) &&
|
|
497
|
+
lastBraceSymbol > firstBraceSymbol &&
|
|
498
|
+
lastBraceSymbol >= 0 && lastBraceSymbol > lastBracketSymbol) {
|
|
499
|
+
jsonstr = '[' + jsonstr.substr(firstBraceSymbol, lastBraceSymbol - firstBraceSymbol + 1);
|
|
500
|
+
+']';
|
|
501
|
+
firstBracketSymbol = 0;
|
|
502
|
+
lastBracketSymbol = jsonstr.length - 1;
|
|
503
|
+
}
|
|
504
|
+
else if (firstBracketSymbol < 0 || lastBracketSymbol < 0 || lastBracketSymbol <= firstBracketSymbol) {
|
|
505
|
+
return [];
|
|
506
|
+
}
|
|
507
|
+
jsonstr = jsonstr.substr(firstBracketSymbol, lastBracketSymbol - firstBracketSymbol + 1);
|
|
508
|
+
///尽量处理一些能够一眼识别出来的JSON错误
|
|
509
|
+
jsonstr = jsonstr.replace(/}{/g, '},{');
|
|
510
|
+
let mutilitems = jsonstr.split('][');
|
|
511
|
+
///确实存在多个数组拼接在一起,中间没有逗号隔开的了
|
|
512
|
+
let retObject = [];
|
|
513
|
+
for (let str of mutilitems) {
|
|
514
|
+
if (!str.startsWith('['))
|
|
515
|
+
str = '[' + str;
|
|
516
|
+
if (!str.endsWith(']'))
|
|
517
|
+
str = str + ']';
|
|
518
|
+
// console.log('json str', str)
|
|
519
|
+
try {
|
|
520
|
+
let jsonObj = eval(str);
|
|
521
|
+
retObject = retObject.concat(jsonObj);
|
|
522
|
+
}
|
|
523
|
+
catch (err) {
|
|
524
|
+
console.log('json error', str);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
return retObject;
|
|
472
528
|
}
|
|
473
529
|
/**
|
|
474
530
|
* 将一段很长的文本,按1024长度来划分到多个中
|
package/dist/openaiprovider.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*/
|
|
4
|
-
import OpenAIGpt from './openai';
|
|
1
|
+
import { ApiCredential } from './baiduai';
|
|
2
|
+
import GptBase from './gptbase';
|
|
5
3
|
/**
|
|
6
4
|
* OpenAI/NLP 的服务提供商 OpenAI,微软,百度文心(待接入),google(待接入)
|
|
7
5
|
*/
|
|
@@ -19,4 +17,4 @@ export type AIProviderEnum = typeof AIProviderEnum[keyof typeof AIProviderEnum];
|
|
|
19
17
|
* @param {*} setting
|
|
20
18
|
* @returns
|
|
21
19
|
*/
|
|
22
|
-
export declare function createAIInstance(provider: AIProviderEnum, apikey: string, setting: any):
|
|
20
|
+
export declare function createAIInstance(provider: AIProviderEnum, apikey: string | ApiCredential, setting: any): GptBase | null;
|
package/dist/openaiprovider.js
CHANGED
|
@@ -9,6 +9,7 @@ exports.createAIInstance = exports.AIProviderEnum = void 0;
|
|
|
9
9
|
*/
|
|
10
10
|
const openai_1 = __importDefault(require("./openai"));
|
|
11
11
|
const azureai_1 = __importDefault(require("./azureai"));
|
|
12
|
+
const baiduai_1 = __importDefault(require("./baiduai"));
|
|
12
13
|
/**
|
|
13
14
|
* OpenAI/NLP 的服务提供商 OpenAI,微软,百度文心(待接入),google(待接入)
|
|
14
15
|
*/
|
|
@@ -26,12 +27,15 @@ exports.AIProviderEnum = {
|
|
|
26
27
|
* @returns
|
|
27
28
|
*/
|
|
28
29
|
function createAIInstance(provider, apikey, setting) {
|
|
29
|
-
let { model, maxtoken, temperature, endpoint, engine, version } = setting;
|
|
30
|
+
let { model, maxtoken, temperature, endpoint, engine, version } = setting || {};
|
|
30
31
|
switch (provider) {
|
|
31
32
|
case exports.AIProviderEnum.OPENAI:
|
|
32
|
-
return new openai_1.default(apikey, { model, maxtoken, temperature });
|
|
33
|
+
return new openai_1.default(apikey + '', { model, maxtoken, temperature });
|
|
33
34
|
case exports.AIProviderEnum.MICROSOFT:
|
|
34
|
-
return new azureai_1.default(apikey, { endpoint, engine, version }, { model, maxtoken, temperature });
|
|
35
|
+
return new azureai_1.default(apikey + '', { endpoint, engine, version }, { model, maxtoken, temperature });
|
|
36
|
+
case exports.AIProviderEnum.BAIDU:
|
|
37
|
+
let cred = typeof (apikey) === 'string' ? { apikey, securitykey: apikey } : apikey;
|
|
38
|
+
return new baiduai_1.default(cred);
|
|
35
39
|
default: return null;
|
|
36
40
|
}
|
|
37
41
|
}
|
package/package.json
CHANGED
package/src/azureai.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { AzureOpenAIPatameters, ChatReponse, OpenAIApiParameters } from "./declare";
|
|
2
|
-
import axios from 'axios';
|
|
1
|
+
import { AzureOpenAIPatameters, ChatReponse, OpenAIApiParameters, request } from "./declare";
|
|
3
2
|
import OpenAIGpt from "./openai"
|
|
4
3
|
import { ChatCompletionRequestMessage } from "openai";
|
|
5
4
|
export default class AzureAI extends OpenAIGpt {
|
|
@@ -32,13 +31,7 @@ export default class AzureAI extends OpenAIGpt {
|
|
|
32
31
|
|
|
33
32
|
let messages: Array<ChatCompletionRequestMessage> = typeof (chatText) == 'string' ?
|
|
34
33
|
[{ role: 'user', content: chatText }] : chatText;
|
|
35
|
-
//let axios = new Axios(axiosOption)
|
|
36
34
|
try{
|
|
37
|
-
// const response = await axios.post(this.BaseUrl, {
|
|
38
|
-
// messages,
|
|
39
|
-
// temperature: Number(paramOption?.temperature || this.temperature),
|
|
40
|
-
// max_tokens: Number(paramOption?.maxtoken || this.maxtoken),
|
|
41
|
-
// })
|
|
42
35
|
let param = {
|
|
43
36
|
...axiosOption,
|
|
44
37
|
method: "post",
|
|
@@ -49,9 +42,8 @@ export default class AzureAI extends OpenAIGpt {
|
|
|
49
42
|
},
|
|
50
43
|
url: this.BaseUrl
|
|
51
44
|
};
|
|
52
|
-
console.log('axiosOption', param)
|
|
53
|
-
|
|
54
|
-
const response = await axios(param)
|
|
45
|
+
// console.log('axiosOption', param)
|
|
46
|
+
const response =await request(param)
|
|
55
47
|
if (response.data.choices){
|
|
56
48
|
return { successed: true, message: response.data.choices };
|
|
57
49
|
}
|
package/src/baiduai.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { EmotionResult, SimilarityResult, ChatReponse, SummaryReponse, ExaminationPaperResult, ApiResult, CacheProvider, request, CommentResult } from "./declare";
|
|
2
|
+
import GptBase from "./gptbase"
|
|
3
|
+
const TOKEN_CACHE_KEY = "key:_doomisoft:baiduwenxin:"
|
|
4
|
+
export default class BaiduWenXinAI extends GptBase {
|
|
5
|
+
protected credential: ApiCredential;
|
|
6
|
+
private Cacher: CacheProvider|undefined;
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param credential 调用OpenAI 的key
|
|
10
|
+
* @param cacher 用作accesstoken的缓存
|
|
11
|
+
* @param apiOption 用作accesstoken的缓存
|
|
12
|
+
*/
|
|
13
|
+
constructor(credential: ApiCredential, cacher?:CacheProvider) {
|
|
14
|
+
super();
|
|
15
|
+
this.credential = credential;
|
|
16
|
+
this.Cacher = cacher;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 获取调用Api的Token
|
|
20
|
+
*/
|
|
21
|
+
async getAccessToken():Promise<AccessTokenResult>{
|
|
22
|
+
////如果当前应用是一个委托到第三方的
|
|
23
|
+
///公众号或小程序,则需要用关联的第三方平台来获取api调用的accesstoken
|
|
24
|
+
////如果是需要缓存token,则首先看缓存中是否有AccessToken
|
|
25
|
+
const accesstoken = this.Cacher ? (await this.Cacher.get(TOKEN_CACHE_KEY+this.credential.apikey)):null;
|
|
26
|
+
if (accesstoken) return { successed: true, access_token: accesstoken };
|
|
27
|
+
const option = {
|
|
28
|
+
url: `https://wenxin.baidu.com/moduleApi/portal/api/oauth/token?grant_type=client_credentials&client_id=${this.credential.apikey}&client_secret=${this.credential.securitykey}`,
|
|
29
|
+
method:"post",
|
|
30
|
+
};
|
|
31
|
+
const tokenData = await request(option);
|
|
32
|
+
if (tokenData.successed == true && !tokenData.data.code) {
|
|
33
|
+
///把api accesstoken缓存起来
|
|
34
|
+
if (this.Cacher){
|
|
35
|
+
this.Cacher.set(TOKEN_CACHE_KEY + this.credential.apikey, tokenData.data.data,3600*20);
|
|
36
|
+
}
|
|
37
|
+
return { successed: true, access_token: tokenData.data.data };
|
|
38
|
+
}
|
|
39
|
+
return { successed: false, error: tokenData.data.msg }
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 请求GPT接口
|
|
43
|
+
*/
|
|
44
|
+
public async chatRequest(chatText: string | Array<any>, _paramOption: any, axiosOption: any = {}): Promise<ApiResult> {
|
|
45
|
+
console.log('call baidu')
|
|
46
|
+
if (!chatText) return { successed: false, error: { errcode: 2, errmsg: '缺失聊天的内容' } };
|
|
47
|
+
const accessToken = await this.getAccessToken();
|
|
48
|
+
if (!accessToken.successed || !accessToken.access_token) return {successed:false,error:'accesstoken get failed'}
|
|
49
|
+
try {
|
|
50
|
+
let param = {
|
|
51
|
+
...axiosOption,
|
|
52
|
+
method: "post",
|
|
53
|
+
data: {
|
|
54
|
+
text: `问题:${chatText}\n回答:`,
|
|
55
|
+
seq_len: 512,
|
|
56
|
+
topp: 0.5,
|
|
57
|
+
penalty_score: 1.2,
|
|
58
|
+
min_dec_len: 12,
|
|
59
|
+
min_dec_penalty_text: "。?:![<S>]",
|
|
60
|
+
task_prompt: "qa",
|
|
61
|
+
mask_type: "paragraph"
|
|
62
|
+
},
|
|
63
|
+
url:`https://wenxin.baidu.com/moduleApi/portal/api/rest/1.0/ernie/3.0.25/zeus?access_token=${accessToken.access_token}`
|
|
64
|
+
};
|
|
65
|
+
console.log('param', param)
|
|
66
|
+
const response = await request(param)
|
|
67
|
+
if (response.successed && !response.data.code) {
|
|
68
|
+
return { successed: true, ...response.data };
|
|
69
|
+
}
|
|
70
|
+
return { successed: false, ...response.data };
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.log('result is error ', error)
|
|
73
|
+
return { successed: false, error };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
}
|
|
77
|
+
commentQuestionAnswer(_question: string, _answer: string, _axiosOption: any): Promise<CommentResult>{
|
|
78
|
+
throw new Error("Method not implemented.");
|
|
79
|
+
}
|
|
80
|
+
getScentenceEmotional(_s1: string, _axiosOption: any): Promise<EmotionResult> {
|
|
81
|
+
throw new Error("Method not implemented.");
|
|
82
|
+
}
|
|
83
|
+
getScentenseSimilarity(_s1: string, _s2: string, _axiosOption: any): Promise<SimilarityResult> {
|
|
84
|
+
throw new Error("Method not implemented.");
|
|
85
|
+
}
|
|
86
|
+
getSimilarityContent(_content: string, _count: number, _axiosOption: any): Promise<ChatReponse> {
|
|
87
|
+
throw new Error("Method not implemented.");
|
|
88
|
+
}
|
|
89
|
+
getSummaryOfContent(_content: string | any[], _axiosOption: any): Promise<SummaryReponse> {
|
|
90
|
+
throw new Error("Method not implemented.");
|
|
91
|
+
}
|
|
92
|
+
generateQuestionsFromContent(_content: string, _count: number, _axiosOption: any): Promise<ChatReponse> {
|
|
93
|
+
throw new Error("Method not implemented.");
|
|
94
|
+
}
|
|
95
|
+
generateExaminationPaperFromContent(_content: string, _paperOption: any, _axiosOption: any): Promise<ExaminationPaperResult> {
|
|
96
|
+
throw new Error("Method not implemented.");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
export interface AccessTokenResult extends ApiResult {
|
|
101
|
+
'access_token'?: string
|
|
102
|
+
}
|
|
103
|
+
export interface ApiCredential{
|
|
104
|
+
'apikey':string,
|
|
105
|
+
'securitykey': string
|
|
106
|
+
}
|
package/src/declare.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
export interface ApiResult {
|
|
3
4
|
/**
|
|
4
5
|
* return the result of api called
|
|
5
6
|
* @type {boolean}
|
|
@@ -97,9 +98,63 @@ export interface SimilarityResult extends ApiResult {
|
|
|
97
98
|
'value'?: number; ///相识度的值
|
|
98
99
|
}
|
|
99
100
|
|
|
101
|
+
/**
|
|
102
|
+
* 调用OpenAI Api的参数约定
|
|
103
|
+
*/
|
|
104
|
+
export interface CommentResult extends ApiResult {
|
|
105
|
+
'score'?:number,
|
|
106
|
+
'comment'?: string; ///评价内容
|
|
107
|
+
}
|
|
100
108
|
/**
|
|
101
109
|
* 调用OpenAI Api的参数约定
|
|
102
110
|
*/
|
|
103
111
|
export interface EmotionResult extends ApiResult {
|
|
104
112
|
'emotion'?: string; ///情绪
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 远程请求的返回
|
|
116
|
+
*/
|
|
117
|
+
export interface RpcResult extends ApiResult {
|
|
118
|
+
'data'?: any;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Axios远程请求封装
|
|
123
|
+
* @param opts
|
|
124
|
+
* @returns
|
|
125
|
+
*/
|
|
126
|
+
export async function request(opts: any = {}): Promise<RpcResult> {
|
|
127
|
+
if (!opts.data) opts.data = opts.body;
|
|
128
|
+
try {
|
|
129
|
+
let result = await axios(opts);
|
|
130
|
+
return { successed: true, data: result.data }
|
|
131
|
+
} catch (err) {
|
|
132
|
+
return { successed: false, error: err }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 数据缓存提供者接口
|
|
139
|
+
*/
|
|
140
|
+
export interface CacheProvider {
|
|
141
|
+
/**
|
|
142
|
+
* 缓存数据
|
|
143
|
+
* @param key 数据的键名称
|
|
144
|
+
* @param value 数据的键值
|
|
145
|
+
*/
|
|
146
|
+
set(key: string, value: string | object, exp?: number): void;
|
|
147
|
+
/**
|
|
148
|
+
* 从缓存中读取数据
|
|
149
|
+
* @param key 数据的键名称
|
|
150
|
+
*/
|
|
151
|
+
get(key: string): Promise<string | null>;
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* 删除缓存信息
|
|
156
|
+
* @param key 数据的键名称
|
|
157
|
+
*/
|
|
158
|
+
delete(key: string): void;
|
|
159
|
+
|
|
105
160
|
}
|
package/src/gptbase.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { EventEmitter } from "events"
|
|
2
|
+
import { ChatReponse, SummaryReponse, ExaminationPaperResult, EmotionResult, SimilarityResult, ApiResult, CommentResult } from './declare'
|
|
3
|
+
|
|
4
|
+
export default abstract class GptBase extends EventEmitter {
|
|
5
|
+
/**
|
|
6
|
+
* 构造函数
|
|
7
|
+
*/
|
|
8
|
+
constructor() {
|
|
9
|
+
super();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 自由聊天模式
|
|
13
|
+
* @param chatText
|
|
14
|
+
* @param _paramOption
|
|
15
|
+
* @param axiosOption
|
|
16
|
+
*/
|
|
17
|
+
abstract chatRequest(chatText: string | Array<any>, _paramOption: any, axiosOption: any): Promise<ApiResult>;
|
|
18
|
+
/**
|
|
19
|
+
* 点评问题回答的评价
|
|
20
|
+
* @param question 问题题干
|
|
21
|
+
* @param answer 回答内容
|
|
22
|
+
* @param axiosOption
|
|
23
|
+
*/
|
|
24
|
+
abstract commentQuestionAnswer(question: string, answer: string, axiosOption: any): Promise<CommentResult>;
|
|
25
|
+
/**
|
|
26
|
+
* 获取句子的情感
|
|
27
|
+
* @param s1
|
|
28
|
+
* @param axiosOption
|
|
29
|
+
*/
|
|
30
|
+
abstract getScentenceEmotional(s1: string, axiosOption: any ): Promise<EmotionResult> ;
|
|
31
|
+
/**
|
|
32
|
+
* 获取两段文本的相似度
|
|
33
|
+
* @param s1
|
|
34
|
+
* @param s2
|
|
35
|
+
* @param axiosOption
|
|
36
|
+
*/
|
|
37
|
+
abstract getScentenseSimilarity(s1: string, s2: string, axiosOption: any): Promise<SimilarityResult>;
|
|
38
|
+
/**
|
|
39
|
+
* 获取一段文本的相似内容
|
|
40
|
+
* @param content
|
|
41
|
+
* @param count
|
|
42
|
+
* @param axiosOption
|
|
43
|
+
*/
|
|
44
|
+
abstract getSimilarityContent(content: string, count: number, axiosOption: any): Promise<ChatReponse>;
|
|
45
|
+
/**
|
|
46
|
+
* 获取内容的摘要
|
|
47
|
+
* @param content
|
|
48
|
+
* @param axiosOption
|
|
49
|
+
*/
|
|
50
|
+
abstract getSummaryOfContent(content: string | Array<any>, axiosOption: any): Promise<SummaryReponse>;
|
|
51
|
+
/**
|
|
52
|
+
* 从内容中提取问题和答案及管件子
|
|
53
|
+
* @param content
|
|
54
|
+
* @param count
|
|
55
|
+
* @param axiosOption
|
|
56
|
+
*/
|
|
57
|
+
abstract generateQuestionsFromContent(content: string, count: number, axiosOption: any): Promise<ChatReponse>;
|
|
58
|
+
/**
|
|
59
|
+
* 从内容中提取单选多选判断填空题
|
|
60
|
+
* @param content
|
|
61
|
+
* @param paperOption
|
|
62
|
+
* @param axiosOption
|
|
63
|
+
*/
|
|
64
|
+
abstract generateExaminationPaperFromContent(content: string, paperOption: any, axiosOption: any): Promise<ExaminationPaperResult>;
|
|
65
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//ts check
|
|
2
|
+
/**
|
|
3
|
+
* 语音转文字服务商工厂
|
|
4
|
+
*/
|
|
5
|
+
import OpenAIGpt from './openai';
|
|
6
|
+
import AzureAI from './azureai'
|
|
7
|
+
import BaiduWenXinAI, { ApiCredential } from './baiduai'
|
|
8
|
+
import GptBase from './gptbase';
|
|
9
|
+
/**
|
|
10
|
+
* OpenAI/NLP 的服务提供商 OpenAI,微软,百度文心(待接入),google(待接入)
|
|
11
|
+
*/
|
|
12
|
+
export const GptProviderEnum = {
|
|
13
|
+
OPENAI: 'openai',
|
|
14
|
+
MICROSOFT: 'microsoft',
|
|
15
|
+
BAIDU: 'baidu',
|
|
16
|
+
GOOGLE:'google'
|
|
17
|
+
} as const;
|
|
18
|
+
export type GptProviderEnum = typeof GptProviderEnum[keyof typeof GptProviderEnum];
|
|
19
|
+
/**
|
|
20
|
+
* 根据类型创建不同的TTS引擎对象
|
|
21
|
+
* @param {*} provider
|
|
22
|
+
* @param {*} apikey
|
|
23
|
+
* @param {*} setting
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
export function createGpt(provider: GptProviderEnum, apikey: string|ApiCredential, setting: any): GptBase | null {
|
|
27
|
+
let { model, maxtoken, temperature,endpoint,engine,version } = setting || {};
|
|
28
|
+
switch (provider) {
|
|
29
|
+
case GptProviderEnum.OPENAI:
|
|
30
|
+
return new OpenAIGpt(apikey+'', { model, maxtoken, temperature });
|
|
31
|
+
case GptProviderEnum.MICROSOFT:
|
|
32
|
+
return new AzureAI(apikey+'', { endpoint, engine, version }, { model, maxtoken, temperature }, );
|
|
33
|
+
case GptProviderEnum.BAIDU:
|
|
34
|
+
let cred: ApiCredential = typeof (apikey) === 'string' ? { apikey, securitykey: apikey } : apikey
|
|
35
|
+
return new BaiduWenXinAI(cred);
|
|
36
|
+
default: return null;
|
|
37
|
+
}
|
|
38
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export * as
|
|
1
|
+
export * as GptFactory from "./gptprovider";
|
|
2
|
+
export * as GptBase from "./gptbase";
|