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 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: 'content filter' };
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: (((_a = paperOption.singlechoice) === null || _a === void 0 ? void 0 : _a.count) || 0) / arrContent.length,
496
- multiplechoice: (((_b = paperOption.multiplechoice) === null || _b === void 0 ? void 0 : _b.count) || 0) / arrContent.length,
497
- trueorfalse: (((_c = paperOption.trueorfalse) === null || _c === void 0 ? void 0 : _c.count) || 0) / arrContent.length,
498
- completion: (((_d = paperOption.completion) === null || _d === void 0 ? void 0 : _d.count) || 0) / arrContent.length
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: ((_e = paperOption.singlechoice) === null || _e === void 0 ? void 0 : _e.count) || 0,
503
- multiplechoice: ((_f = paperOption.multiplechoice) === null || _f === void 0 ? void 0 : _f.count) || 0,
504
- trueorfalse: ((_g = paperOption.trueorfalse) === null || _g === void 0 ? void 0 : _g.count) || 0,
505
- completion: ((_h = paperOption.completion) === null || _h === void 0 ? void 0 : _h.count) || 0
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: ((_j = paperOption.singlechoice) === null || _j === void 0 ? void 0 : _j.score) || 0,
510
- multiplechoice: ((_k = paperOption.multiplechoice) === null || _k === void 0 ? void 0 : _k.score) || 0,
511
- trueorfalse: ((_l = paperOption.trueorfalse) === null || _l === void 0 ? void 0 : _l.score) || 0,
512
- completion: ((_m = paperOption.completion) === null || _m === void 0 ? void 0 : _m.score) || 0
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doomiaichat",
3
- "version": "4.8.0",
3
+ "version": "4.9.0",
4
4
  "description": "Doomisoft OpenAI",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
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:'content filter'}
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
  })