doomiaichat 2.2.0 → 2.4.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.d.ts +11 -0
- package/dist/azureai.js +40 -0
- package/dist/baiduai.d.ts +2 -1
- package/dist/baiduai.js +3 -0
- package/dist/declare.d.ts +7 -0
- package/dist/gptbase.d.ts +8 -1
- package/dist/openai.d.ts +14 -1
- package/dist/openai.js +108 -19
- package/package.json +1 -1
- package/src/azureai.ts +37 -0
- package/src/baiduai.ts +4 -1
- package/src/declare.ts +7 -0
- package/src/gptbase.ts +8 -1
- package/src/openai.ts +116 -33
package/dist/azureai.d.ts
CHANGED
|
@@ -11,4 +11,15 @@ export default class AzureAI extends OpenAIGpt {
|
|
|
11
11
|
* 请求GPT接口
|
|
12
12
|
*/
|
|
13
13
|
chatRequest(chatText: string | Array<any>, paramOption: OpenAIApiParameters, axiosOption?: any): Promise<ChatReponse>;
|
|
14
|
+
/**
|
|
15
|
+
* 获得一种内容的相似说法
|
|
16
|
+
* 微软的AI参数中已经没有了n的参数
|
|
17
|
+
* 比如:
|
|
18
|
+
* 你今年多大?
|
|
19
|
+
* 相似问法:您是哪一年出生的
|
|
20
|
+
* 您今年贵庚?
|
|
21
|
+
* @param {*} content
|
|
22
|
+
* @param {需要出来的数量} count
|
|
23
|
+
*/
|
|
24
|
+
getSimilarityContent(content: string, count?: number, axiosOption?: any): Promise<ChatReponse>;
|
|
14
25
|
}
|
package/dist/azureai.js
CHANGED
|
@@ -63,5 +63,45 @@ class AzureAI extends openai_1.default {
|
|
|
63
63
|
}
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* 获得一种内容的相似说法
|
|
68
|
+
* 微软的AI参数中已经没有了n的参数
|
|
69
|
+
* 比如:
|
|
70
|
+
* 你今年多大?
|
|
71
|
+
* 相似问法:您是哪一年出生的
|
|
72
|
+
* 您今年贵庚?
|
|
73
|
+
* @param {*} content
|
|
74
|
+
* @param {需要出来的数量} count
|
|
75
|
+
*/
|
|
76
|
+
getSimilarityContent(content, count = 1, axiosOption = {}) {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
let chnReg = /([\u4e00-\u9fa5]|[\ufe30-\uffa0])/.test(content); ///检查源话是否含有中文内容
|
|
79
|
+
let engReg = /[a-zA-Z]/.test(content); ///检查源话是否含有英文内容
|
|
80
|
+
///如果源话是全中文,那么结果中不应该出来英文的相似说法,如果源话是全英文,则结果不能出现全中文的说法
|
|
81
|
+
let prefix = (!chnReg && engReg) ? `请用英文提供${count}句` : ((chnReg && !engReg) ? `请用中文提供${count}句` : `请提供${count}句`);
|
|
82
|
+
const text = `${prefix}与"${content}"意思相同的内容`;
|
|
83
|
+
const messages = [
|
|
84
|
+
{ role: 'system', content: '忘记我们的聊天,你现在是一名专业的语言大师' },
|
|
85
|
+
{ role: 'user', content: text },
|
|
86
|
+
{ role: 'user', content: '最终结果按照["意思相同语句","意思相同语句"]的JSON数组的格式输出。' } //如:"今天天气真好"的相同2句内容,输出结果为:["今天晴空万里无云","今天的天气适合出游"]。' },
|
|
87
|
+
];
|
|
88
|
+
let result = yield this.chatRequest(messages, {}, axiosOption);
|
|
89
|
+
if (!result.successed || !result.message)
|
|
90
|
+
return result;
|
|
91
|
+
let value = result.message[0].message.content.trim();
|
|
92
|
+
let replyJson = this.fixedJsonString(value);
|
|
93
|
+
///能够提取到内容
|
|
94
|
+
if (replyJson.length)
|
|
95
|
+
return { successed: true, message: replyJson };
|
|
96
|
+
///回答的内容非JSON格式,自己来提取算了
|
|
97
|
+
console.log('自己组装', value);
|
|
98
|
+
let sentences = value.split(/",|\n/g); ///用换行或",来割分文本内容
|
|
99
|
+
// let matched = value.match(/\d+分/g), score = 0;
|
|
100
|
+
// if (matched && matched.length) {
|
|
101
|
+
// score = Number(matched[0].replace('分', ''));
|
|
102
|
+
// }
|
|
103
|
+
return { successed: true, message: sentences };
|
|
104
|
+
});
|
|
105
|
+
}
|
|
66
106
|
}
|
|
67
107
|
exports.default = AzureAI;
|
package/dist/baiduai.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EmotionResult, SimilarityResult, ChatReponse, SummaryReponse, ExaminationPaperResult, ApiResult, CacheProvider } from "./declare";
|
|
1
|
+
import { EmotionResult, SimilarityResult, ChatReponse, SummaryReponse, ExaminationPaperResult, ApiResult, CacheProvider, CommentResult } from "./declare";
|
|
2
2
|
import GptBase from "./gptbase";
|
|
3
3
|
export default class BaiduWenXinAI extends GptBase {
|
|
4
4
|
protected credential: ApiCredential;
|
|
@@ -18,6 +18,7 @@ export default class BaiduWenXinAI extends GptBase {
|
|
|
18
18
|
* 请求GPT接口
|
|
19
19
|
*/
|
|
20
20
|
chatRequest(chatText: string | Array<any>, _paramOption: any, axiosOption?: any): Promise<ApiResult>;
|
|
21
|
+
commentQuestionAnswer(_question: string, _answer: string, _axiosOption: any): Promise<CommentResult>;
|
|
21
22
|
getScentenceEmotional(_s1: string, _axiosOption: any): Promise<EmotionResult>;
|
|
22
23
|
getScentenseSimilarity(_s1: string, _s2: string, _axiosOption: any): Promise<SimilarityResult>;
|
|
23
24
|
getSimilarityContent(_content: string, _count: number, _axiosOption: any): Promise<ChatReponse>;
|
package/dist/baiduai.js
CHANGED
|
@@ -88,6 +88,9 @@ class BaiduWenXinAI extends gptbase_1.default {
|
|
|
88
88
|
}
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
|
+
commentQuestionAnswer(_question, _answer, _axiosOption) {
|
|
92
|
+
throw new Error("Method not implemented.");
|
|
93
|
+
}
|
|
91
94
|
getScentenceEmotional(_s1, _axiosOption) {
|
|
92
95
|
throw new Error("Method not implemented.");
|
|
93
96
|
}
|
package/dist/declare.d.ts
CHANGED
|
@@ -90,6 +90,13 @@ export interface QuestionItem {
|
|
|
90
90
|
export interface SimilarityResult extends ApiResult {
|
|
91
91
|
'value'?: number;
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* 调用OpenAI Api的参数约定
|
|
95
|
+
*/
|
|
96
|
+
export interface CommentResult extends ApiResult {
|
|
97
|
+
'score'?: number;
|
|
98
|
+
'comment'?: string;
|
|
99
|
+
}
|
|
93
100
|
/**
|
|
94
101
|
* 调用OpenAI Api的参数约定
|
|
95
102
|
*/
|
package/dist/gptbase.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { EventEmitter } from "events";
|
|
3
|
-
import { ChatReponse, SummaryReponse, ExaminationPaperResult, EmotionResult, SimilarityResult, ApiResult } from './declare';
|
|
3
|
+
import { ChatReponse, SummaryReponse, ExaminationPaperResult, EmotionResult, SimilarityResult, ApiResult, CommentResult } from './declare';
|
|
4
4
|
export default abstract class GptBase extends EventEmitter {
|
|
5
5
|
/**
|
|
6
6
|
* 构造函数
|
|
@@ -13,6 +13,13 @@ export default abstract class GptBase extends EventEmitter {
|
|
|
13
13
|
* @param axiosOption
|
|
14
14
|
*/
|
|
15
15
|
abstract chatRequest(chatText: string | Array<any>, _paramOption: any, axiosOption: any): Promise<ApiResult>;
|
|
16
|
+
/**
|
|
17
|
+
* 点评问题回答的评价
|
|
18
|
+
* @param question 问题题干
|
|
19
|
+
* @param answer 回答内容
|
|
20
|
+
* @param axiosOption
|
|
21
|
+
*/
|
|
22
|
+
abstract commentQuestionAnswer(question: string, answer: string, axiosOption: any): Promise<CommentResult>;
|
|
16
23
|
/**
|
|
17
24
|
* 获取句子的情感
|
|
18
25
|
* @param s1
|
package/dist/openai.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OpenAIApi, ChatCompletionRequestMessage } from "openai";
|
|
2
2
|
import GptBase from "./gptbase";
|
|
3
|
-
import { OpenAIApiParameters, ChatReponse, SummaryReponse, FaqItem, ExaminationPaperResult, EmotionResult, SimilarityResult, QuestionItem } from './declare';
|
|
3
|
+
import { OpenAIApiParameters, ChatReponse, SummaryReponse, FaqItem, ExaminationPaperResult, EmotionResult, SimilarityResult, QuestionItem, CommentResult } from './declare';
|
|
4
4
|
export default class OpenAIGpt extends GptBase {
|
|
5
5
|
protected readonly apiKey: string;
|
|
6
6
|
private aiApi;
|
|
@@ -22,6 +22,13 @@ export default class OpenAIGpt extends GptBase {
|
|
|
22
22
|
* @param {*} chatText
|
|
23
23
|
*/
|
|
24
24
|
chatRequest(chatText: string | Array<any>, callChatOption: OpenAIApiParameters, axiosOption?: any): Promise<ChatReponse>;
|
|
25
|
+
/**
|
|
26
|
+
* 点评问题回答的评价
|
|
27
|
+
* @param question
|
|
28
|
+
* @param answer
|
|
29
|
+
* @param axiosOption
|
|
30
|
+
*/
|
|
31
|
+
commentQuestionAnswer(question: string, answer: string, axiosOption?: any): Promise<CommentResult>;
|
|
25
32
|
/**
|
|
26
33
|
* 判断一句话的表达情绪
|
|
27
34
|
* @param {*} s1
|
|
@@ -85,6 +92,12 @@ export default class OpenAIGpt extends GptBase {
|
|
|
85
92
|
*
|
|
86
93
|
*/
|
|
87
94
|
protected pickUpQuestions(result: Array<any>, count: number, questiontype: string, score?: number): Array<QuestionItem>;
|
|
95
|
+
/**
|
|
96
|
+
* 验证JSON字符串是否是真正可转换为JSON的合法格式
|
|
97
|
+
* 这里只能做一个最简单的处理,就是用两端的符号
|
|
98
|
+
* @param jsonstr
|
|
99
|
+
*/
|
|
100
|
+
protected fixedJsonString(jsonstr: string): any[];
|
|
88
101
|
/**
|
|
89
102
|
* 将一段很长的文本,按1024长度来划分到多个中
|
|
90
103
|
* @param {*} content
|
package/dist/openai.js
CHANGED
|
@@ -75,6 +75,40 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
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
|
+
}
|
|
78
112
|
/**
|
|
79
113
|
* 判断一句话的表达情绪
|
|
80
114
|
* @param {*} s1
|
|
@@ -110,6 +144,7 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
110
144
|
if (!s1 || !s2)
|
|
111
145
|
return { successed: false, error: { errcode: 2, errmsg: '缺失参数' } };
|
|
112
146
|
const messages = [
|
|
147
|
+
{ role: 'system', content: '你是一名专业的语言分析大师' },
|
|
113
148
|
{ role: 'user', content: s1 },
|
|
114
149
|
{ role: 'user', content: s2 },
|
|
115
150
|
{ role: 'user', content: '请从语义上对比以上两句话的相似度,请仅输出0至100之间的整数对比结果即可' },
|
|
@@ -259,16 +294,18 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
259
294
|
*/
|
|
260
295
|
pickUpFaqContent(messages) {
|
|
261
296
|
let answerString = messages[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
262
|
-
const firstsybmol = answerString.indexOf("[");
|
|
263
|
-
const lastsybmol = answerString.lastIndexOf("]");
|
|
264
|
-
console.log('answerString', answerString)
|
|
265
|
-
if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol)
|
|
297
|
+
// const firstsybmol = answerString.indexOf("["); ////必须过滤出来数组
|
|
298
|
+
// const lastsybmol = answerString.lastIndexOf("]");
|
|
299
|
+
// console.log('answerString', answerString)
|
|
300
|
+
// if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol) return [];
|
|
301
|
+
// answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
302
|
+
// console.log('answerString', answerString)
|
|
303
|
+
let jsonObj = this.fixedJsonString(answerString);
|
|
304
|
+
if (!jsonObj.length)
|
|
266
305
|
return [];
|
|
267
|
-
answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
268
|
-
console.log('answerString', answerString);
|
|
269
306
|
try {
|
|
270
307
|
//let jsonObj = JSON.parse(answerString);
|
|
271
|
-
let jsonObj = eval(answerString);
|
|
308
|
+
//let jsonObj = eval(answerString);
|
|
272
309
|
jsonObj.map((item) => {
|
|
273
310
|
let realKeyword = [];
|
|
274
311
|
let keywords = (item.keywords + '').split(',');
|
|
@@ -368,29 +405,32 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
368
405
|
*/
|
|
369
406
|
pickUpQuestions(result, count, questiontype, score = 1) {
|
|
370
407
|
let answerString = result[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
371
|
-
const firstsybmol = answerString.indexOf("[");
|
|
372
|
-
const lastsybmol = answerString.lastIndexOf("]");
|
|
373
|
-
console.log('answerString', answerString)
|
|
374
|
-
if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol)
|
|
408
|
+
// const firstsybmol = answerString.indexOf("["); ////必须过滤出来数组
|
|
409
|
+
// const lastsybmol = answerString.lastIndexOf("]");
|
|
410
|
+
// console.log('answerString', answerString)
|
|
411
|
+
// if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol) return [];
|
|
412
|
+
// answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
413
|
+
// console.log('answerString', answerString)
|
|
414
|
+
let jsonObj = this.fixedJsonString(answerString);
|
|
415
|
+
if (!jsonObj.length)
|
|
375
416
|
return [];
|
|
376
|
-
answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
377
|
-
console.log('answerString', answerString);
|
|
378
417
|
let returnItems = [];
|
|
379
418
|
try {
|
|
380
|
-
let jsonObj = JSON.parse(answerString);
|
|
419
|
+
// let jsonObj = JSON.parse(answerString);
|
|
381
420
|
returnItems = jsonObj.map((questionitem) => {
|
|
382
|
-
console.log('answer item', questionitem);
|
|
421
|
+
console.log('answer item from jsonObj', questionitem);
|
|
383
422
|
if (questionitem.choice && Array.isArray(questionitem.choice) && questiontype != 'completion') {
|
|
384
423
|
questionitem.fullanswer = (questionitem.answer + '').replace(/,|[^ABCDE]/g, '');
|
|
385
424
|
questionitem.score = score;
|
|
386
425
|
if (questionitem.choice) {
|
|
387
426
|
questionitem.choice = questionitem.choice.map((item, index) => {
|
|
388
|
-
let seqNo = String.fromCharCode(65 + index);
|
|
427
|
+
let seqNo = 'ABCDEFG'[index]; //String.fromCharCode(65 + index);
|
|
389
428
|
let correctReg = new RegExp(`${seqNo}.|${seqNo}`, 'ig');
|
|
429
|
+
// console.log('itemitemitem', item)
|
|
390
430
|
//let answer = jsonObj.fullanswer
|
|
391
431
|
return {
|
|
392
432
|
id: seqNo,
|
|
393
|
-
content: item.replace(correctReg, '').trim(),
|
|
433
|
+
content: (item + '').replace(correctReg, '').trim(),
|
|
394
434
|
iscorrect: (questionitem.fullanswer || '').indexOf(seqNo) >= 0 ? 1 : 0
|
|
395
435
|
//|| jsonObj.fullanswer.indexOf(m))
|
|
396
436
|
};
|
|
@@ -415,7 +455,7 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
415
455
|
}
|
|
416
456
|
///单选题验证
|
|
417
457
|
if (questiontype == 'singlechoice') {
|
|
418
|
-
let rightAnswer = questionitem.choice ? questionitem.choice.filter(item => { return item.iscorrect === 1; }) : [];
|
|
458
|
+
let rightAnswer = questionitem.choice ? questionitem.choice.filter((item) => { return item.iscorrect === 1; }) : [];
|
|
419
459
|
///单选题的正确选项大于了1个
|
|
420
460
|
if (rightAnswer.length != 1 || !questionitem.answer || questionitem.answer.length !== 1)
|
|
421
461
|
return null;
|
|
@@ -425,7 +465,7 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
425
465
|
}
|
|
426
466
|
///多选题验证
|
|
427
467
|
if (questiontype == 'multiplechoice') {
|
|
428
|
-
let rightAnswer = questionitem.choice ? questionitem.choice.filter(item => { return item.iscorrect === 1; }) : [];
|
|
468
|
+
let rightAnswer = questionitem.choice ? questionitem.choice.filter((item) => { return item.iscorrect === 1; }) : [];
|
|
429
469
|
///单选题的正确选项大于了1个
|
|
430
470
|
if (rightAnswer.length === 0 || !questionitem.answer || questionitem.answer.length === 0)
|
|
431
471
|
return null;
|
|
@@ -438,6 +478,55 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
438
478
|
}
|
|
439
479
|
return returnItems.filter(i => { return i != null; }).slice(0, count);
|
|
440
480
|
}
|
|
481
|
+
/**
|
|
482
|
+
* 验证JSON字符串是否是真正可转换为JSON的合法格式
|
|
483
|
+
* 这里只能做一个最简单的处理,就是用两端的符号
|
|
484
|
+
* @param jsonstr
|
|
485
|
+
*/
|
|
486
|
+
fixedJsonString(jsonstr) {
|
|
487
|
+
console.log('original json string:', jsonstr);
|
|
488
|
+
///检查返回的是不是一个数组对象(我们需要的是数组对象)
|
|
489
|
+
let firstBracketSymbol = jsonstr.indexOf("["); ////必须过滤出来数组
|
|
490
|
+
let lastBracketSymbol = jsonstr.lastIndexOf("]");
|
|
491
|
+
///第一个花括号出现的位置,如果花括号出现的位置早于 [ ,则默认返回的对象不是一个数组,仅仅是一个对象,
|
|
492
|
+
///则需要我们用中括号包住
|
|
493
|
+
let firstBraceSymbol = jsonstr.indexOf("{");
|
|
494
|
+
let lastBraceSymbol = jsonstr.lastIndexOf("}");
|
|
495
|
+
///返回的不是一个数组结构的,只是一个{},我们帮他完成数组拼接
|
|
496
|
+
if (firstBraceSymbol >= 0 &&
|
|
497
|
+
firstBraceSymbol < (firstBracketSymbol >= 0 ? firstBracketSymbol : 1000) &&
|
|
498
|
+
lastBraceSymbol > firstBraceSymbol &&
|
|
499
|
+
lastBraceSymbol >= 0 && lastBraceSymbol > lastBracketSymbol) {
|
|
500
|
+
jsonstr = '[' + jsonstr.substr(firstBraceSymbol, lastBraceSymbol - firstBraceSymbol + 1);
|
|
501
|
+
+']';
|
|
502
|
+
firstBracketSymbol = 0;
|
|
503
|
+
lastBracketSymbol = jsonstr.length - 1;
|
|
504
|
+
}
|
|
505
|
+
else if (firstBracketSymbol < 0 || lastBracketSymbol < 0 || lastBracketSymbol <= firstBracketSymbol) {
|
|
506
|
+
return [];
|
|
507
|
+
}
|
|
508
|
+
jsonstr = jsonstr.substr(firstBracketSymbol, lastBracketSymbol - firstBracketSymbol + 1);
|
|
509
|
+
///尽量处理一些能够一眼识别出来的JSON错误
|
|
510
|
+
jsonstr = jsonstr.replace(/}{/g, '},{');
|
|
511
|
+
let mutilitems = jsonstr.split('][');
|
|
512
|
+
///确实存在多个数组拼接在一起,中间没有逗号隔开的了
|
|
513
|
+
let retObject = [];
|
|
514
|
+
for (let str of mutilitems) {
|
|
515
|
+
if (!str.startsWith('['))
|
|
516
|
+
str = '[' + str;
|
|
517
|
+
if (!str.endsWith(']'))
|
|
518
|
+
str = str + ']';
|
|
519
|
+
// console.log('json str', str)
|
|
520
|
+
try {
|
|
521
|
+
let jsonObj = eval(str);
|
|
522
|
+
retObject = retObject.concat(jsonObj);
|
|
523
|
+
}
|
|
524
|
+
catch (err) {
|
|
525
|
+
console.log('json error', str);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return retObject;
|
|
529
|
+
}
|
|
441
530
|
/**
|
|
442
531
|
* 将一段很长的文本,按1024长度来划分到多个中
|
|
443
532
|
* @param {*} content
|
package/package.json
CHANGED
package/src/azureai.ts
CHANGED
|
@@ -54,4 +54,41 @@ export default class AzureAI extends OpenAIGpt {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* 获得一种内容的相似说法
|
|
59
|
+
* 微软的AI参数中已经没有了n的参数
|
|
60
|
+
* 比如:
|
|
61
|
+
* 你今年多大?
|
|
62
|
+
* 相似问法:您是哪一年出生的
|
|
63
|
+
* 您今年贵庚?
|
|
64
|
+
* @param {*} content
|
|
65
|
+
* @param {需要出来的数量} count
|
|
66
|
+
*/
|
|
67
|
+
override async getSimilarityContent(content: string, count: number = 1, axiosOption: any = {}): Promise<ChatReponse> {
|
|
68
|
+
let chnReg: boolean = /([\u4e00-\u9fa5]|[\ufe30-\uffa0])/.test(content) ///检查源话是否含有中文内容
|
|
69
|
+
let engReg: boolean = /[a-zA-Z]/.test(content) ///检查源话是否含有英文内容
|
|
70
|
+
///如果源话是全中文,那么结果中不应该出来英文的相似说法,如果源话是全英文,则结果不能出现全中文的说法
|
|
71
|
+
let prefix = (!chnReg && engReg) ? `请用英文提供${count}句` : ((chnReg && !engReg) ? `请用中文提供${count}句` : `请提供${count}句`)
|
|
72
|
+
const text = `${prefix}与"${content}"意思相同的内容`
|
|
73
|
+
const messages = [
|
|
74
|
+
{ role: 'system', content: '忘记我们的聊天,你现在是一名专业的语言大师' },
|
|
75
|
+
{ role: 'user', content: text },
|
|
76
|
+
{ role: 'user', content: '最终结果按照["意思相同语句","意思相同语句"]的JSON数组的格式输出。'}//如:"今天天气真好"的相同2句内容,输出结果为:["今天晴空万里无云","今天的天气适合出游"]。' },
|
|
77
|
+
]
|
|
78
|
+
let result = await this.chatRequest(messages, {}, axiosOption);
|
|
79
|
+
if (!result.successed || !result.message) return result;
|
|
80
|
+
let value = result.message[0].message.content.trim();
|
|
81
|
+
let replyJson = this.fixedJsonString(value);
|
|
82
|
+
///能够提取到内容
|
|
83
|
+
if (replyJson.length) return { successed: true, message:replyJson }
|
|
84
|
+
///回答的内容非JSON格式,自己来提取算了
|
|
85
|
+
|
|
86
|
+
console.log('自己组装', value);
|
|
87
|
+
let sentences = value.split(/",|\n/g) ///用换行或",来割分文本内容
|
|
88
|
+
// let matched = value.match(/\d+分/g), score = 0;
|
|
89
|
+
// if (matched && matched.length) {
|
|
90
|
+
// score = Number(matched[0].replace('分', ''));
|
|
91
|
+
// }
|
|
92
|
+
return { successed: true, message: sentences }
|
|
93
|
+
}
|
|
57
94
|
}
|
package/src/baiduai.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EmotionResult, SimilarityResult, ChatReponse, SummaryReponse, ExaminationPaperResult, ApiResult, CacheProvider, request } from "./declare";
|
|
1
|
+
import { EmotionResult, SimilarityResult, ChatReponse, SummaryReponse, ExaminationPaperResult, ApiResult, CacheProvider, request, CommentResult } from "./declare";
|
|
2
2
|
import GptBase from "./gptbase"
|
|
3
3
|
const TOKEN_CACHE_KEY = "key:_doomisoft:baiduwenxin:"
|
|
4
4
|
export default class BaiduWenXinAI extends GptBase {
|
|
@@ -74,6 +74,9 @@ export default class BaiduWenXinAI extends GptBase {
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
}
|
|
77
|
+
commentQuestionAnswer(_question: string, _answer: string, _axiosOption: any): Promise<CommentResult>{
|
|
78
|
+
throw new Error("Method not implemented.");
|
|
79
|
+
}
|
|
77
80
|
getScentenceEmotional(_s1: string, _axiosOption: any): Promise<EmotionResult> {
|
|
78
81
|
throw new Error("Method not implemented.");
|
|
79
82
|
}
|
package/src/declare.ts
CHANGED
|
@@ -98,6 +98,13 @@ export interface SimilarityResult extends ApiResult {
|
|
|
98
98
|
'value'?: number; ///相识度的值
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* 调用OpenAI Api的参数约定
|
|
103
|
+
*/
|
|
104
|
+
export interface CommentResult extends ApiResult {
|
|
105
|
+
'score'?:number,
|
|
106
|
+
'comment'?: string; ///评价内容
|
|
107
|
+
}
|
|
101
108
|
/**
|
|
102
109
|
* 调用OpenAI Api的参数约定
|
|
103
110
|
*/
|
package/src/gptbase.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from "events"
|
|
2
|
-
import { ChatReponse, SummaryReponse, ExaminationPaperResult, EmotionResult, SimilarityResult, ApiResult } from './declare'
|
|
2
|
+
import { ChatReponse, SummaryReponse, ExaminationPaperResult, EmotionResult, SimilarityResult, ApiResult, CommentResult } from './declare'
|
|
3
3
|
|
|
4
4
|
export default abstract class GptBase extends EventEmitter {
|
|
5
5
|
/**
|
|
@@ -15,6 +15,13 @@ export default abstract class GptBase extends EventEmitter {
|
|
|
15
15
|
* @param axiosOption
|
|
16
16
|
*/
|
|
17
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>;
|
|
18
25
|
/**
|
|
19
26
|
* 获取句子的情感
|
|
20
27
|
* @param s1
|
package/src/openai.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Configuration, OpenAIApi, ChatCompletionRequestMessage } from "openai"
|
|
2
2
|
// import { EventEmitter } from "events";
|
|
3
3
|
import GptBase from "./gptbase"
|
|
4
|
-
import { OpenAIApiParameters, ChatReponse, OutlineSummaryItem, SummaryReponse, FaqItem, ExaminationPaperResult, EmotionResult, SimilarityResult, QuestionItem } from './declare'
|
|
4
|
+
import { OpenAIApiParameters, ChatReponse, OutlineSummaryItem, SummaryReponse, FaqItem, ExaminationPaperResult, EmotionResult, SimilarityResult, QuestionItem, CommentResult } from './declare'
|
|
5
5
|
const SECTION_LENGTH = 1600; ///每2400个字符分成一组
|
|
6
6
|
const MESSAGE_LENGTH = 1; ///每次送8句话给openai 进行解析,送多了,会报错
|
|
7
7
|
//请将答案放在最后,标记为答案:()
|
|
@@ -35,8 +35,8 @@ export default class OpenAIGpt extends GptBase {
|
|
|
35
35
|
/**
|
|
36
36
|
* 初始化OpenAI 的聊天对象Api
|
|
37
37
|
*/
|
|
38
|
-
createOpenAI(apiKey:string):OpenAIApi {
|
|
39
|
-
return
|
|
38
|
+
createOpenAI(apiKey: string): OpenAIApi {
|
|
39
|
+
return new OpenAIApi(new Configuration({ apiKey }))
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
42
|
* 向OpenAI发送一个聊天请求
|
|
@@ -44,22 +44,22 @@ export default class OpenAIGpt extends GptBase {
|
|
|
44
44
|
*/
|
|
45
45
|
public async chatRequest(chatText: string | Array<any>, callChatOption: OpenAIApiParameters, axiosOption: any = {}): Promise<ChatReponse> {
|
|
46
46
|
if (!chatText) return { successed: false, error: { errcode: 2, errmsg: '缺失聊天的内容' } };
|
|
47
|
-
if (!this.aiApi){
|
|
47
|
+
if (!this.aiApi) {
|
|
48
48
|
this.aiApi = this.createOpenAI(this.apiKey);
|
|
49
49
|
//return { successed: false, error: { errcode: 1, errmsg: '聊天机器人无效' } };
|
|
50
|
-
}
|
|
50
|
+
}
|
|
51
51
|
|
|
52
52
|
let message: Array<ChatCompletionRequestMessage> = typeof (chatText) == 'string' ?
|
|
53
53
|
[{ role: 'user', content: chatText }] : chatText;
|
|
54
54
|
// console.log('message', message)
|
|
55
55
|
try {
|
|
56
|
-
const response= await this.aiApi.createChatCompletion({
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
const response = await this.aiApi.createChatCompletion({
|
|
57
|
+
model: callChatOption?.model || this.chatModel,
|
|
58
|
+
messages: message,
|
|
59
|
+
temperature: Number(callChatOption?.temperature || this.temperature),
|
|
60
|
+
max_tokens: Number(callChatOption?.maxtoken || this.maxtoken),
|
|
61
|
+
n: Number(callChatOption?.replyCounts || 1) || 1
|
|
62
|
+
}, axiosOption);
|
|
63
63
|
return { successed: true, message: response.data.choices };
|
|
64
64
|
} catch (error) {
|
|
65
65
|
console.log('result is error ', error)
|
|
@@ -68,7 +68,36 @@ export default class OpenAIGpt extends GptBase {
|
|
|
68
68
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
/**
|
|
72
|
+
* 点评问题回答的评价
|
|
73
|
+
* @param question
|
|
74
|
+
* @param answer
|
|
75
|
+
* @param axiosOption
|
|
76
|
+
*/
|
|
77
|
+
async commentQuestionAnswer(question: string, answer: string, axiosOption: any = { timeout: 30000 }): Promise<CommentResult>{
|
|
78
|
+
if (!question || !answer) return { successed: false, error: { errcode: 2, errmsg: '缺失参数' } }
|
|
79
|
+
let message = [
|
|
80
|
+
{role:'system',content:'你是一名专业的培训师。'},
|
|
81
|
+
{ role: 'user', content: `问题题干:“${question}”`},
|
|
82
|
+
{ role: 'user', content: `回答内容:“${answer}”` },
|
|
83
|
+
{ role: 'user', content: `请根据以上的回答内容进行点评,给出一段不超过200字的评语,以及0-100的得分。最终结果按照{"comment":"评语","score":80}的JSON结构输出` }
|
|
84
|
+
]
|
|
85
|
+
const result = await this.chatRequest(message, {}, axiosOption);
|
|
86
|
+
if (result.successed && result.message) {
|
|
87
|
+
let value = result.message[0].message.content.trim();
|
|
88
|
+
let replyJson = this.fixedJsonString(value);
|
|
89
|
+
///能够提取到内容
|
|
90
|
+
if (replyJson.length)return { successed: true,...replyJson[0] }
|
|
91
|
+
///回答的内容非JSON格式,自己来提取算了
|
|
92
|
+
console.log('自己组装')
|
|
93
|
+
let matched = value.match(/\d+分/g),score=0;
|
|
94
|
+
if (matched && matched.length){
|
|
95
|
+
score =Number(matched[0].replace('分',''));
|
|
96
|
+
}
|
|
97
|
+
return {successed:true,comment:value,score}
|
|
98
|
+
}
|
|
99
|
+
return { successed: false};
|
|
100
|
+
}
|
|
72
101
|
/**
|
|
73
102
|
* 判断一句话的表达情绪
|
|
74
103
|
* @param {*} s1
|
|
@@ -99,6 +128,7 @@ export default class OpenAIGpt extends GptBase {
|
|
|
99
128
|
async getScentenseSimilarity(s1: string, s2: string, axiosOption: any = { timeout: 30000 }): Promise<SimilarityResult> {
|
|
100
129
|
if (!s1 || !s2) return { successed: false, error: { errcode: 2, errmsg: '缺失参数' } }
|
|
101
130
|
const messages = [
|
|
131
|
+
{ role: 'system', content: '你是一名专业的语言分析大师' },
|
|
102
132
|
{ role: 'user', content: s1 },
|
|
103
133
|
{ role: 'user', content: s2 },
|
|
104
134
|
{ role: 'user', content: '请从语义上对比以上两句话的相似度,请仅输出0至100之间的整数对比结果即可' },
|
|
@@ -241,16 +271,18 @@ export default class OpenAIGpt extends GptBase {
|
|
|
241
271
|
*/
|
|
242
272
|
protected pickUpFaqContent(messages: Array<any>): Array<FaqItem> {
|
|
243
273
|
let answerString = messages[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
244
|
-
const firstsybmol = answerString.indexOf("["); ////必须过滤出来数组
|
|
245
|
-
const lastsybmol = answerString.lastIndexOf("]");
|
|
274
|
+
// const firstsybmol = answerString.indexOf("["); ////必须过滤出来数组
|
|
275
|
+
// const lastsybmol = answerString.lastIndexOf("]");
|
|
246
276
|
|
|
247
|
-
console.log('answerString', answerString)
|
|
248
|
-
if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol) return [];
|
|
249
|
-
answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
250
|
-
console.log('answerString', answerString)
|
|
277
|
+
// console.log('answerString', answerString)
|
|
278
|
+
// if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol) return [];
|
|
279
|
+
// answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
280
|
+
// console.log('answerString', answerString)
|
|
281
|
+
let jsonObj = this.fixedJsonString(answerString);
|
|
282
|
+
if (!jsonObj.length) return []
|
|
251
283
|
try {
|
|
252
284
|
//let jsonObj = JSON.parse(answerString);
|
|
253
|
-
let jsonObj = eval(answerString);
|
|
285
|
+
//let jsonObj = eval(answerString);
|
|
254
286
|
jsonObj.map((item: FaqItem) => {
|
|
255
287
|
let realKeyword: string[] = [];
|
|
256
288
|
let keywords: string[] = (item.keywords + '').split(',');
|
|
@@ -349,29 +381,32 @@ export default class OpenAIGpt extends GptBase {
|
|
|
349
381
|
*/
|
|
350
382
|
protected pickUpQuestions(result: Array<any>, count: number, questiontype: string, score: number = 1): Array<QuestionItem> {
|
|
351
383
|
let answerString = result[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
352
|
-
const firstsybmol = answerString.indexOf("["); ////必须过滤出来数组
|
|
353
|
-
const lastsybmol = answerString.lastIndexOf("]");
|
|
384
|
+
// const firstsybmol = answerString.indexOf("["); ////必须过滤出来数组
|
|
385
|
+
// const lastsybmol = answerString.lastIndexOf("]");
|
|
354
386
|
|
|
355
|
-
console.log('answerString', answerString)
|
|
356
|
-
if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol) return [];
|
|
357
|
-
answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
358
|
-
console.log('answerString', answerString)
|
|
387
|
+
// console.log('answerString', answerString)
|
|
388
|
+
// if (firstsybmol < 0 || lastsybmol < 0 || lastsybmol <= firstsybmol) return [];
|
|
389
|
+
// answerString = answerString.substr(firstsybmol, lastsybmol - firstsybmol + 1);
|
|
390
|
+
// console.log('answerString', answerString)
|
|
391
|
+
let jsonObj = this.fixedJsonString(answerString);
|
|
392
|
+
if (!jsonObj.length) return []
|
|
359
393
|
let returnItems: QuestionItem[] = [];
|
|
360
394
|
try {
|
|
361
|
-
let jsonObj = JSON.parse(answerString);
|
|
362
|
-
returnItems = jsonObj.map((questionitem:
|
|
363
|
-
console.log('answer item', questionitem);
|
|
395
|
+
// let jsonObj = JSON.parse(answerString);
|
|
396
|
+
returnItems = jsonObj.map((questionitem: any) => {
|
|
397
|
+
console.log('answer item from jsonObj', questionitem);
|
|
364
398
|
if (questionitem.choice && Array.isArray(questionitem.choice) && questiontype != 'completion') {
|
|
365
399
|
questionitem.fullanswer = (questionitem.answer + '').replace(/,|[^ABCDE]/g, '');
|
|
366
400
|
questionitem.score = score;
|
|
367
401
|
if (questionitem.choice) {
|
|
368
402
|
questionitem.choice = questionitem.choice.map((item: string, index: number) => {
|
|
369
|
-
let seqNo = String.fromCharCode(65 + index);
|
|
403
|
+
let seqNo = 'ABCDEFG'[index]; //String.fromCharCode(65 + index);
|
|
370
404
|
let correctReg = new RegExp(`${seqNo}.|${seqNo}`, 'ig')
|
|
405
|
+
// console.log('itemitemitem', item)
|
|
371
406
|
//let answer = jsonObj.fullanswer
|
|
372
407
|
return {
|
|
373
408
|
id: seqNo,
|
|
374
|
-
content: item.replace(correctReg, '').trim(),
|
|
409
|
+
content: (item + '').replace(correctReg, '').trim(),
|
|
375
410
|
iscorrect: (questionitem.fullanswer || '').indexOf(seqNo) >= 0 ? 1 : 0
|
|
376
411
|
//|| jsonObj.fullanswer.indexOf(m))
|
|
377
412
|
}
|
|
@@ -397,7 +432,7 @@ export default class OpenAIGpt extends GptBase {
|
|
|
397
432
|
}
|
|
398
433
|
///单选题验证
|
|
399
434
|
if (questiontype == 'singlechoice') {
|
|
400
|
-
let rightAnswer = questionitem.choice ? questionitem.choice.filter(item => { return item.iscorrect === 1 }) : [];
|
|
435
|
+
let rightAnswer = questionitem.choice ? questionitem.choice.filter((item: { iscorrect: number; }) => { return item.iscorrect === 1 }) : [];
|
|
401
436
|
///单选题的正确选项大于了1个
|
|
402
437
|
if (rightAnswer.length != 1 || !questionitem.answer || questionitem.answer.length !== 1) return null;
|
|
403
438
|
///正确选项和答案不一致
|
|
@@ -405,7 +440,7 @@ export default class OpenAIGpt extends GptBase {
|
|
|
405
440
|
}
|
|
406
441
|
///多选题验证
|
|
407
442
|
if (questiontype == 'multiplechoice') {
|
|
408
|
-
let rightAnswer = questionitem.choice ? questionitem.choice.filter(item => { return item.iscorrect === 1 }) : [];
|
|
443
|
+
let rightAnswer = questionitem.choice ? questionitem.choice.filter((item: { iscorrect: number; }) => { return item.iscorrect === 1 }) : [];
|
|
409
444
|
///单选题的正确选项大于了1个
|
|
410
445
|
if (rightAnswer.length === 0 || !questionitem.answer || questionitem.answer.length === 0) return null;
|
|
411
446
|
}
|
|
@@ -417,6 +452,53 @@ export default class OpenAIGpt extends GptBase {
|
|
|
417
452
|
}
|
|
418
453
|
return returnItems.filter(i => { return i != null; }).slice(0, count);
|
|
419
454
|
}
|
|
455
|
+
/**
|
|
456
|
+
* 验证JSON字符串是否是真正可转换为JSON的合法格式
|
|
457
|
+
* 这里只能做一个最简单的处理,就是用两端的符号
|
|
458
|
+
* @param jsonstr
|
|
459
|
+
*/
|
|
460
|
+
protected fixedJsonString(jsonstr: string): any[] {
|
|
461
|
+
console.log('original json string:', jsonstr)
|
|
462
|
+
///检查返回的是不是一个数组对象(我们需要的是数组对象)
|
|
463
|
+
let firstBracketSymbol = jsonstr.indexOf("["); ////必须过滤出来数组
|
|
464
|
+
let lastBracketSymbol = jsonstr.lastIndexOf("]");
|
|
465
|
+
///第一个花括号出现的位置,如果花括号出现的位置早于 [ ,则默认返回的对象不是一个数组,仅仅是一个对象,
|
|
466
|
+
///则需要我们用中括号包住
|
|
467
|
+
let firstBraceSymbol = jsonstr.indexOf("{");
|
|
468
|
+
let lastBraceSymbol = jsonstr.lastIndexOf("}");
|
|
469
|
+
///返回的不是一个数组结构的,只是一个{},我们帮他完成数组拼接
|
|
470
|
+
if (firstBraceSymbol >= 0 &&
|
|
471
|
+
firstBraceSymbol < (firstBracketSymbol >= 0 ? firstBracketSymbol:1000) &&
|
|
472
|
+
lastBraceSymbol > firstBraceSymbol &&
|
|
473
|
+
lastBraceSymbol >= 0 && lastBraceSymbol > lastBracketSymbol){
|
|
474
|
+
|
|
475
|
+
jsonstr = '[' + jsonstr.substr(firstBraceSymbol, lastBraceSymbol - firstBraceSymbol + 1); +']';
|
|
476
|
+
firstBracketSymbol = 0;
|
|
477
|
+
lastBracketSymbol = jsonstr.length-1;
|
|
478
|
+
}
|
|
479
|
+
else if (firstBracketSymbol < 0 || lastBracketSymbol < 0 || lastBracketSymbol <= firstBracketSymbol){
|
|
480
|
+
return [];
|
|
481
|
+
}
|
|
482
|
+
jsonstr = jsonstr.substr(firstBracketSymbol, lastBracketSymbol - firstBracketSymbol + 1);
|
|
483
|
+
///尽量处理一些能够一眼识别出来的JSON错误
|
|
484
|
+
jsonstr = jsonstr.replace(/}{/g,'},{');
|
|
485
|
+
let mutilitems = jsonstr.split('][');
|
|
486
|
+
///确实存在多个数组拼接在一起,中间没有逗号隔开的了
|
|
487
|
+
let retObject:any[] = [];
|
|
488
|
+
for(let str of mutilitems){
|
|
489
|
+
if (!str.startsWith('[')) str = '[' + str;
|
|
490
|
+
if (!str.endsWith(']')) str = str+']';
|
|
491
|
+
// console.log('json str', str)
|
|
492
|
+
try{
|
|
493
|
+
let jsonObj = eval(str);
|
|
494
|
+
retObject = retObject.concat(jsonObj);
|
|
495
|
+
}catch(err){
|
|
496
|
+
console.log('json error', str)
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
return retObject;
|
|
500
|
+
}
|
|
501
|
+
|
|
420
502
|
/**
|
|
421
503
|
* 将一段很长的文本,按1024长度来划分到多个中
|
|
422
504
|
* @param {*} content
|
|
@@ -439,4 +521,5 @@ export default class OpenAIGpt extends GptBase {
|
|
|
439
521
|
}
|
|
440
522
|
return message;
|
|
441
523
|
}
|
|
524
|
+
|
|
442
525
|
}
|