doomiaichat 4.8.0 → 4.9.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/openai.js +53 -31
- package/package.json +1 -1
- package/src/openai.ts +36 -20
package/dist/openai.js
CHANGED
|
@@ -64,10 +64,10 @@ const QUESTION_ROLE_DEFINE = {
|
|
|
64
64
|
* 问题生成的Prompt
|
|
65
65
|
*/
|
|
66
66
|
const QUESTION_PROMPT = {
|
|
67
|
-
singlechoice: '根据以下内容,生成@ITEMCOUNT@道单选题,每道题目4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题一个正确答案,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]
|
|
68
|
-
multiplechoice: '根据以下内容,请生成@ITEMCOUNT@道多选题,提供4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题的答案至少有两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]
|
|
69
|
-
trueorfalse: '根据以下内容,请生成@ITEMCOUNT@道判断题,每道题正确和错误两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]
|
|
70
|
-
completion: '根据以下内容,请生成@ITEMCOUNT@道填空题和对应答案,输出结果必须是JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]
|
|
67
|
+
singlechoice: '根据以下内容,生成@ITEMCOUNT@道单选题,每道题目4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题一个正确答案,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组。',
|
|
68
|
+
multiplechoice: '根据以下内容,请生成@ITEMCOUNT@道多选题,提供4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题的答案至少有两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组。',
|
|
69
|
+
trueorfalse: '根据以下内容,请生成@ITEMCOUNT@道判断题,每道题正确和错误两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]的结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组。',
|
|
70
|
+
completion: '根据以下内容,请生成@ITEMCOUNT@道填空题和对应答案,输出结果必须是JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]的结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组。'
|
|
71
71
|
};
|
|
72
72
|
/**
|
|
73
73
|
* 问题生成的Prompt
|
|
@@ -150,7 +150,7 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
150
150
|
////输出的内容不合规
|
|
151
151
|
if (response.data.choices[0].finish_reason === 'content_filter') {
|
|
152
152
|
console.log('content_filter');
|
|
153
|
-
return { successed: false, error: '
|
|
153
|
+
return { successed: false, error: 'content_filter' };
|
|
154
154
|
}
|
|
155
155
|
return { successed: true, message: response.data.choices, usage: response.data.usage };
|
|
156
156
|
}
|
|
@@ -387,8 +387,15 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
387
387
|
* @returns
|
|
388
388
|
*/ //并在答案末尾处必须给出答案内容中的关键词
|
|
389
389
|
generateQuestionsFromContent(content, count = 1, everyContentLength = SECTION_LENGTH, axiosOption = {}) {
|
|
390
|
+
var _a;
|
|
390
391
|
return __awaiter(this, void 0, void 0, function* () {
|
|
391
392
|
let arrContent = this.splitLongText(content, everyContentLength || SECTION_LENGTH);
|
|
393
|
+
///如果最后一段的文字内容过短,则把最后一段内容追加到前一段中,并删除最后一段
|
|
394
|
+
let totalLen = arrContent.length;
|
|
395
|
+
if (totalLen >= 2 && (((_a = arrContent[totalLen - 1]) === null || _a === void 0 ? void 0 : _a.length) || 0) < 100) {
|
|
396
|
+
arrContent[totalLen - 2] += arrContent[totalLen - 1];
|
|
397
|
+
arrContent.splice(totalLen - 1, 1);
|
|
398
|
+
}
|
|
392
399
|
///没20句话分为一组,适应大文件内容多次请求组合结果
|
|
393
400
|
///每一句话需要产生的题目
|
|
394
401
|
let questions4EverySentense = count / arrContent.length; //Math.ceil(arrContent.length / 20);
|
|
@@ -399,19 +406,17 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
399
406
|
let itemCount = Math.min(Math.ceil(questions4EverySentense), count - gotted);
|
|
400
407
|
let subarray = [
|
|
401
408
|
{ role: 'system', content: FAQ_ROLE_DEFINE },
|
|
402
|
-
{ role: 'user', content: `从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON
|
|
403
|
-
{ role: 'user', content: arrContent.slice(0, 1)[0]
|
|
404
|
-
}
|
|
409
|
+
{ role: 'user', content: `从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON数组结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组 []。` },
|
|
410
|
+
{ role: 'user', content: arrContent.slice(0, 1)[0] }
|
|
405
411
|
];
|
|
406
412
|
console.log('Faq Question Pick Prompt:', subarray);
|
|
407
|
-
//subarray.push({ role: 'user', content:'请根据上述内容,给出一道提问与答案以及答案关键词,按照先问题内容,再标准答案,再关键词的顺序输出,关键词之间用、分开'})
|
|
408
|
-
//subarray.unshift({ role: 'system', content: `你是一位专业培训师,从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON数组结构输出。` })
|
|
409
|
-
// subarray.unshift({role: 'system', content: FAQ_ROLE_DEFINE});
|
|
410
|
-
//subarray.unshift({ role: 'system', content: `你是一位专业程序开发工程师,根据以下内容,按照[{"question":"问题内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]JSON数组结构,给出${itemCount}条提问问题及答案以及答案关键词` })
|
|
411
|
-
// console.log('subarray', subarray)
|
|
412
413
|
let result = yield this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
|
|
414
|
+
///如果请求发生了网络错误(不是内容合规问题),则再重试一次,如果任然有错则放弃
|
|
415
|
+
if (!result.successed && result.error != 'content_filter') {
|
|
416
|
+
console.log('network error,retry onemore time');
|
|
417
|
+
result = yield this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
|
|
418
|
+
}
|
|
413
419
|
if (result.successed && result.message) {
|
|
414
|
-
// console.log('result is ', result.message[0].message.content)
|
|
415
420
|
let msgs = yield this.pickUpFaqContent(result.message);
|
|
416
421
|
if (msgs.length) {
|
|
417
422
|
///对外发送检出问答题的信号
|
|
@@ -440,11 +445,13 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
440
445
|
if (!((_b = (_a = messages[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content))
|
|
441
446
|
return [];
|
|
442
447
|
let answerString = messages[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
448
|
+
if (answerString === '[]')
|
|
449
|
+
return [];
|
|
443
450
|
let jsonObj = this.fixedJsonString(answerString);
|
|
444
451
|
if (!jsonObj.length) {
|
|
445
452
|
let fixedAsk = [
|
|
446
453
|
{ role: 'system', content: '角色扮演:假设你是一位高级JSON数据分析师' },
|
|
447
|
-
{ role: 'user', content: `请分析以下内容,严格按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的标准JSON
|
|
454
|
+
{ role: 'user', content: `请分析以下内容,严格按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的标准JSON数组结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组,无需提供参考。` },
|
|
448
455
|
{ role: 'user', content: answerString },
|
|
449
456
|
];
|
|
450
457
|
console.log('pickUpFaqContent fixedAsk', fixedAsk);
|
|
@@ -488,28 +495,34 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
488
495
|
* @returns
|
|
489
496
|
*/ //并在答案末尾处必须给出答案内容中的关键词
|
|
490
497
|
generateExaminationPaperFromContent(content, paperOption = {}, everyContentLength = SECTION_LENGTH, axiosOption = {}) {
|
|
491
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
498
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
492
499
|
return __awaiter(this, void 0, void 0, function* () {
|
|
493
500
|
let arrContent = this.splitLongText(content, everyContentLength || SECTION_LENGTH);
|
|
501
|
+
///如果最后一段的文字内容过短,则把最后一段内容追加到前一段中,并删除最后一段
|
|
502
|
+
let totalLen = arrContent.length;
|
|
503
|
+
if (totalLen >= 2 && (((_a = arrContent[totalLen - 1]) === null || _a === void 0 ? void 0 : _a.length) || 0) < 100) {
|
|
504
|
+
arrContent[totalLen - 2] += arrContent[totalLen - 1];
|
|
505
|
+
arrContent.splice(totalLen - 1, 1);
|
|
506
|
+
}
|
|
494
507
|
let sectionCount = {
|
|
495
|
-
singlechoice: (((
|
|
496
|
-
multiplechoice: (((
|
|
497
|
-
trueorfalse: (((
|
|
498
|
-
completion: (((
|
|
508
|
+
singlechoice: (((_b = paperOption.singlechoice) === null || _b === void 0 ? void 0 : _b.count) || 0) / arrContent.length,
|
|
509
|
+
multiplechoice: (((_c = paperOption.multiplechoice) === null || _c === void 0 ? void 0 : _c.count) || 0) / arrContent.length,
|
|
510
|
+
trueorfalse: (((_d = paperOption.trueorfalse) === null || _d === void 0 ? void 0 : _d.count) || 0) / arrContent.length,
|
|
511
|
+
completion: (((_e = paperOption.completion) === null || _e === void 0 ? void 0 : _e.count) || 0) / arrContent.length
|
|
499
512
|
};
|
|
500
513
|
///剩余待生成的题目数量
|
|
501
514
|
let remainCount = {
|
|
502
|
-
singlechoice: ((
|
|
503
|
-
multiplechoice: ((
|
|
504
|
-
trueorfalse: ((
|
|
505
|
-
completion: ((
|
|
515
|
+
singlechoice: ((_f = paperOption.singlechoice) === null || _f === void 0 ? void 0 : _f.count) || 0,
|
|
516
|
+
multiplechoice: ((_g = paperOption.multiplechoice) === null || _g === void 0 ? void 0 : _g.count) || 0,
|
|
517
|
+
trueorfalse: ((_h = paperOption.trueorfalse) === null || _h === void 0 ? void 0 : _h.count) || 0,
|
|
518
|
+
completion: ((_j = paperOption.completion) === null || _j === void 0 ? void 0 : _j.count) || 0
|
|
506
519
|
};
|
|
507
520
|
///每种类型的题目的分数
|
|
508
521
|
let ITEM_SCORE = {
|
|
509
|
-
singlechoice: ((
|
|
510
|
-
multiplechoice: ((
|
|
511
|
-
trueorfalse: ((
|
|
512
|
-
completion: ((
|
|
522
|
+
singlechoice: ((_k = paperOption.singlechoice) === null || _k === void 0 ? void 0 : _k.score) || 0,
|
|
523
|
+
multiplechoice: ((_l = paperOption.multiplechoice) === null || _l === void 0 ? void 0 : _l.score) || 0,
|
|
524
|
+
trueorfalse: ((_m = paperOption.trueorfalse) === null || _m === void 0 ? void 0 : _m.score) || 0,
|
|
525
|
+
completion: ((_o = paperOption.completion) === null || _o === void 0 ? void 0 : _o.score) || 0
|
|
513
526
|
};
|
|
514
527
|
///最后生成出来的结果
|
|
515
528
|
let paperReturned = {
|
|
@@ -520,7 +533,6 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
520
533
|
/**
|
|
521
534
|
* 每种类型的题目进行遍历
|
|
522
535
|
*/
|
|
523
|
-
console.log('arrContent.length', arrContent.length);
|
|
524
536
|
noMoreQuestionRetrive = true;
|
|
525
537
|
for (const key of QUESTION_TYPE) {
|
|
526
538
|
///还需要抓取题目
|
|
@@ -536,6 +548,11 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
536
548
|
// subarray.unshift()
|
|
537
549
|
console.log('subarray', subarray);
|
|
538
550
|
let result = yield this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
|
|
551
|
+
///如果请求发生了网络错误(不是内容合规问题),则再重试一次,如果任然有错则放弃
|
|
552
|
+
if (!result.successed && result.error != 'content_filter') {
|
|
553
|
+
console.log('network error,retry onemore time');
|
|
554
|
+
result = yield this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
|
|
555
|
+
}
|
|
539
556
|
console.log('subarray returned', result.successed);
|
|
540
557
|
if (result.successed && result.message) {
|
|
541
558
|
//console.log('paper result', key, result.message.length)
|
|
@@ -572,12 +589,14 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
572
589
|
if (!((_b = (_a = result[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content))
|
|
573
590
|
return [];
|
|
574
591
|
let answerString = result[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
592
|
+
if (answerString === '[]')
|
|
593
|
+
return [];
|
|
575
594
|
let jsonObj = this.fixedJsonString(answerString);
|
|
576
595
|
////修复的结果无法用程序修复,请求GPT来分析修复一下这个结果
|
|
577
596
|
if (!jsonObj.length) {
|
|
578
597
|
let fixedAsk = [
|
|
579
598
|
{ role: 'system', content: '角色扮演:假设你是一位高级JSON数据分析师' },
|
|
580
|
-
{ role: 'user', content: `请分析以下内容,严格按照${QUESTION_PROMPT_FIXED[questiontype]}的标准JSON
|
|
599
|
+
{ role: 'user', content: `请分析以下内容,严格按照${QUESTION_PROMPT_FIXED[questiontype]}的标准JSON数组结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组,无需提供参考。` },
|
|
581
600
|
{ role: 'user', content: answerString },
|
|
582
601
|
];
|
|
583
602
|
console.log('fixedAsk', fixedAsk);
|
|
@@ -622,7 +641,7 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
622
641
|
questionitem.answer = (questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('').slice(0, 1);
|
|
623
642
|
break;
|
|
624
643
|
case 'multiplechoice':
|
|
625
|
-
questionitem.answer = (questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('');
|
|
644
|
+
questionitem.answer = Array.from(new Set((questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('')));
|
|
626
645
|
break;
|
|
627
646
|
case 'trueorfalse':
|
|
628
647
|
let rightItem = questionitem.choice.find((x) => { return x.iscorrect == 1; });
|
|
@@ -646,6 +665,9 @@ class OpenAIGpt extends gptbase_1.default {
|
|
|
646
665
|
if (rightAnswer.length === 0 || !questionitem.answer || questionitem.answer.length === 0)
|
|
647
666
|
return null;
|
|
648
667
|
}
|
|
668
|
+
///判断题验证:防止没有答案的
|
|
669
|
+
if (questiontype == 'trueorfalse' && !questionitem.answer.length)
|
|
670
|
+
return null;
|
|
649
671
|
return questionitem;
|
|
650
672
|
});
|
|
651
673
|
}
|
package/package.json
CHANGED
package/src/openai.ts
CHANGED
|
@@ -52,10 +52,10 @@ const QUESTION_ROLE_DEFINE: any = {
|
|
|
52
52
|
* 问题生成的Prompt
|
|
53
53
|
*/
|
|
54
54
|
const QUESTION_PROMPT: any ={
|
|
55
|
-
singlechoice:'根据以下内容,生成@ITEMCOUNT@道单选题,每道题目4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题一个正确答案,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]
|
|
56
|
-
multiplechoice: '根据以下内容,请生成@ITEMCOUNT@道多选题,提供4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题的答案至少有两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]
|
|
57
|
-
trueorfalse: '根据以下内容,请生成@ITEMCOUNT@道判断题,每道题正确和错误两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]
|
|
58
|
-
completion: '根据以下内容,请生成@ITEMCOUNT@道填空题和对应答案,输出结果必须是JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]
|
|
55
|
+
singlechoice:'根据以下内容,生成@ITEMCOUNT@道单选题,每道题目4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题一个正确答案,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组。',
|
|
56
|
+
multiplechoice: '根据以下内容,请生成@ITEMCOUNT@道多选题,提供4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题的答案至少有两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组。',
|
|
57
|
+
trueorfalse: '根据以下内容,请生成@ITEMCOUNT@道判断题,每道题正确和错误两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]的结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组。',
|
|
58
|
+
completion: '根据以下内容,请生成@ITEMCOUNT@道填空题和对应答案,输出结果必须是JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]的结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组。'
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
/**
|
|
@@ -143,7 +143,7 @@ export default class OpenAIGpt extends GptBase {
|
|
|
143
143
|
////输出的内容不合规
|
|
144
144
|
if (response.data.choices[0].finish_reason ==='content_filter') {
|
|
145
145
|
console.log('content_filter')
|
|
146
|
-
return {successed:false,error:'
|
|
146
|
+
return { successed: false, error:'content_filter'}
|
|
147
147
|
}
|
|
148
148
|
return { successed: true, message: response.data.choices, usage: response.data.usage };
|
|
149
149
|
} catch (error) {
|
|
@@ -358,6 +358,12 @@ export default class OpenAIGpt extends GptBase {
|
|
|
358
358
|
*///并在答案末尾处必须给出答案内容中的关键词
|
|
359
359
|
override async generateQuestionsFromContent(content: string, count: number = 1, everyContentLength: number = SECTION_LENGTH, axiosOption: any = {}): Promise<ChatReponse> {
|
|
360
360
|
let arrContent = this.splitLongText(content, everyContentLength || SECTION_LENGTH);
|
|
361
|
+
///如果最后一段的文字内容过短,则把最后一段内容追加到前一段中,并删除最后一段
|
|
362
|
+
let totalLen = arrContent.length;
|
|
363
|
+
if (totalLen>=2 && (arrContent[totalLen-1]?.length||0)<100){
|
|
364
|
+
arrContent[totalLen - 2] += arrContent[totalLen - 1];
|
|
365
|
+
arrContent.splice(totalLen-1,1);
|
|
366
|
+
}
|
|
361
367
|
///没20句话分为一组,适应大文件内容多次请求组合结果
|
|
362
368
|
///每一句话需要产生的题目
|
|
363
369
|
let questions4EverySentense: number = count / arrContent.length; //Math.ceil(arrContent.length / 20);
|
|
@@ -368,29 +374,25 @@ export default class OpenAIGpt extends GptBase {
|
|
|
368
374
|
let itemCount = Math.min(Math.ceil(questions4EverySentense), count - gotted);
|
|
369
375
|
let subarray = [
|
|
370
376
|
{ role: 'system', content: FAQ_ROLE_DEFINE },
|
|
371
|
-
{ role: 'user', content: `从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON
|
|
372
|
-
{ role: 'user', content: arrContent.slice(0, 1)[0]
|
|
373
|
-
}
|
|
377
|
+
{ role: 'user', content: `从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON数组结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组 []。`},
|
|
378
|
+
{ role: 'user', content: arrContent.slice(0, 1)[0]}
|
|
374
379
|
]
|
|
375
380
|
console.log('Faq Question Pick Prompt:', subarray)
|
|
376
|
-
//subarray.push({ role: 'user', content:'请根据上述内容,给出一道提问与答案以及答案关键词,按照先问题内容,再标准答案,再关键词的顺序输出,关键词之间用、分开'})
|
|
377
|
-
//subarray.unshift({ role: 'system', content: `你是一位专业培训师,从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON数组结构输出。` })
|
|
378
|
-
// subarray.unshift({role: 'system', content: FAQ_ROLE_DEFINE});
|
|
379
|
-
//subarray.unshift({ role: 'system', content: `你是一位专业程序开发工程师,根据以下内容,按照[{"question":"问题内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]JSON数组结构,给出${itemCount}条提问问题及答案以及答案关键词` })
|
|
380
|
-
// console.log('subarray', subarray)
|
|
381
381
|
let result = await this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
|
|
382
|
+
///如果请求发生了网络错误(不是内容合规问题),则再重试一次,如果任然有错则放弃
|
|
383
|
+
if (!result.successed && result.error!='content_filter'){
|
|
384
|
+
console.log('network error,retry onemore time')
|
|
385
|
+
result = await this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
|
|
386
|
+
}
|
|
382
387
|
if (result.successed && result.message) {
|
|
383
|
-
// console.log('result is ', result.message[0].message.content)
|
|
384
388
|
let msgs = await this.pickUpFaqContent(result.message);
|
|
385
389
|
if (msgs.length) {
|
|
386
390
|
///对外发送检出问答题的信号
|
|
387
391
|
this.emit('parseout', { type: 'qa', items: msgs })
|
|
388
392
|
gotted += msgs.length; //result.message.length;
|
|
389
393
|
faqs = faqs.concat(msgs);
|
|
390
|
-
|
|
391
394
|
}
|
|
392
395
|
}
|
|
393
|
-
|
|
394
396
|
////删除已经处理的文本
|
|
395
397
|
arrContent.splice(0, 1);
|
|
396
398
|
}
|
|
@@ -408,11 +410,12 @@ export default class OpenAIGpt extends GptBase {
|
|
|
408
410
|
protected async pickUpFaqContent(messages: Array<any>): Promise<Array<FaqItem>> {
|
|
409
411
|
if (!messages[0]?.message?.content) return [];
|
|
410
412
|
let answerString = messages[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
413
|
+
if (answerString==='[]') return [];
|
|
411
414
|
let jsonObj = this.fixedJsonString(answerString);
|
|
412
415
|
if (!jsonObj.length){
|
|
413
416
|
let fixedAsk = [
|
|
414
417
|
{ role: 'system', content: '角色扮演:假设你是一位高级JSON数据分析师' },
|
|
415
|
-
{ role: 'user', content: `请分析以下内容,严格按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的标准JSON
|
|
418
|
+
{ role: 'user', content: `请分析以下内容,严格按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的标准JSON数组结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组,无需提供参考。` },
|
|
416
419
|
{ role: 'user', content: answerString },
|
|
417
420
|
]
|
|
418
421
|
console.log('pickUpFaqContent fixedAsk', fixedAsk)
|
|
@@ -456,6 +459,12 @@ export default class OpenAIGpt extends GptBase {
|
|
|
456
459
|
*///并在答案末尾处必须给出答案内容中的关键词
|
|
457
460
|
override async generateExaminationPaperFromContent(content: string, paperOption: any = {}, everyContentLength: number = SECTION_LENGTH, axiosOption: any = {}): Promise<ExaminationPaperResult> {
|
|
458
461
|
let arrContent = this.splitLongText(content, everyContentLength || SECTION_LENGTH);
|
|
462
|
+
///如果最后一段的文字内容过短,则把最后一段内容追加到前一段中,并删除最后一段
|
|
463
|
+
let totalLen = arrContent.length;
|
|
464
|
+
if (totalLen >= 2 && (arrContent[totalLen - 1]?.length || 0) < 100) {
|
|
465
|
+
arrContent[totalLen - 2] += arrContent[totalLen - 1];
|
|
466
|
+
arrContent.splice(totalLen - 1, 1);
|
|
467
|
+
}
|
|
459
468
|
let sectionCount: any = {
|
|
460
469
|
singlechoice: (paperOption.singlechoice?.count || 0) / arrContent.length,
|
|
461
470
|
multiplechoice: (paperOption.multiplechoice?.count || 0) / arrContent.length,
|
|
@@ -487,7 +496,6 @@ export default class OpenAIGpt extends GptBase {
|
|
|
487
496
|
/**
|
|
488
497
|
* 每种类型的题目进行遍历
|
|
489
498
|
*/
|
|
490
|
-
console.log('arrContent.length', arrContent.length)
|
|
491
499
|
noMoreQuestionRetrive = true;
|
|
492
500
|
for (const key of QUESTION_TYPE) {
|
|
493
501
|
///还需要抓取题目
|
|
@@ -504,6 +512,11 @@ export default class OpenAIGpt extends GptBase {
|
|
|
504
512
|
// subarray.unshift()
|
|
505
513
|
console.log('subarray', subarray)
|
|
506
514
|
let result = await this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
|
|
515
|
+
///如果请求发生了网络错误(不是内容合规问题),则再重试一次,如果任然有错则放弃
|
|
516
|
+
if (!result.successed && result.error != 'content_filter') {
|
|
517
|
+
console.log('network error,retry onemore time')
|
|
518
|
+
result = await this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
|
|
519
|
+
}
|
|
507
520
|
console.log('subarray returned', result.successed)
|
|
508
521
|
if (result.successed && result.message) {
|
|
509
522
|
//console.log('paper result', key, result.message.length)
|
|
@@ -537,12 +550,13 @@ export default class OpenAIGpt extends GptBase {
|
|
|
537
550
|
protected async pickUpQuestions(result: Array<any>, count: number, questiontype: string, score: number = 1): Promise<Array<QuestionItem>> {
|
|
538
551
|
if (!result[0]?.message?.content) return [];
|
|
539
552
|
let answerString = result[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
|
|
553
|
+
if (answerString === '[]') return [];
|
|
540
554
|
let jsonObj = this.fixedJsonString(answerString);
|
|
541
555
|
////修复的结果无法用程序修复,请求GPT来分析修复一下这个结果
|
|
542
556
|
if (!jsonObj.length){
|
|
543
557
|
let fixedAsk = [
|
|
544
558
|
{role:'system',content:'角色扮演:假设你是一位高级JSON数据分析师'},
|
|
545
|
-
{ role: 'user', content: `请分析以下内容,严格按照${QUESTION_PROMPT_FIXED[questiontype]}的标准JSON
|
|
559
|
+
{ role: 'user', content: `请分析以下内容,严格按照${QUESTION_PROMPT_FIXED[questiontype]}的标准JSON数组结构输出。如果内容不足以提取问题和答案,请直接输出JSON空数组,无需提供参考。` },
|
|
546
560
|
{ role: 'user', content: answerString },
|
|
547
561
|
]
|
|
548
562
|
console.log('fixedAsk', fixedAsk)
|
|
@@ -587,7 +601,7 @@ export default class OpenAIGpt extends GptBase {
|
|
|
587
601
|
questionitem.answer = (questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('').slice(0, 1);
|
|
588
602
|
break;
|
|
589
603
|
case 'multiplechoice':
|
|
590
|
-
questionitem.answer = (questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('');
|
|
604
|
+
questionitem.answer =Array.from(new Set((questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('')));
|
|
591
605
|
break;
|
|
592
606
|
case 'trueorfalse':
|
|
593
607
|
let rightItem = questionitem.choice.find((x: any) => { return x.iscorrect == 1 });
|
|
@@ -608,6 +622,8 @@ export default class OpenAIGpt extends GptBase {
|
|
|
608
622
|
///单选题的正确选项大于了1个
|
|
609
623
|
if (rightAnswer.length === 0 || !questionitem.answer || questionitem.answer.length === 0) return null;
|
|
610
624
|
}
|
|
625
|
+
///判断题验证:防止没有答案的
|
|
626
|
+
if (questiontype == 'trueorfalse' && !questionitem.answer.length ) return null;
|
|
611
627
|
|
|
612
628
|
return questionitem;
|
|
613
629
|
})
|