doomiaichat 4.6.0 → 4.8.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.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { OpenAIApi, ChatCompletionRequestMessage } from "azure-openai";
1
+ import { OpenAIApi } from "azure-openai";
2
2
  import GptBase from "./gptbase";
3
3
  import { OpenAIApiParameters, ChatReponse, SummaryReponse, FaqItem, ExaminationPaperResult, EmotionResult, SimilarityResult, QuestionItem, CommentResult, EmbeddingResult } from './declare';
4
4
  export default class OpenAIGpt extends GptBase {
@@ -82,7 +82,7 @@ export default class OpenAIGpt extends GptBase {
82
82
  * @param {*} messages
83
83
  * @returns
84
84
  */
85
- protected pickUpFaqContent(messages: Array<any>): Array<FaqItem>;
85
+ protected pickUpFaqContent(messages: Array<any>): Promise<Array<FaqItem>>;
86
86
  /**
87
87
  * 从指定的文本内容中生成一张试卷
88
88
  * @param {*} content
@@ -97,7 +97,7 @@ export default class OpenAIGpt extends GptBase {
97
97
  * @param {*} result
98
98
  *
99
99
  */
100
- protected pickUpQuestions(result: Array<any>, count: number, questiontype: string, score?: number): Array<QuestionItem>;
100
+ protected pickUpQuestions(result: Array<any>, count: number, questiontype: string, score?: number): Promise<Array<QuestionItem>>;
101
101
  /**
102
102
  * 验证JSON字符串是否是真正可转换为JSON的合法格式
103
103
  * 这里只能做一个最简单的处理,就是用两端的符号
@@ -108,5 +108,5 @@ export default class OpenAIGpt extends GptBase {
108
108
  * 将一段很长的文本,按1024长度来划分到多个中
109
109
  * @param {*} content
110
110
  */
111
- protected splitLongText(content: string, len?: number): Array<ChatCompletionRequestMessage>;
111
+ protected splitLongText(content: string, len?: number): string[];
112
112
  }
package/dist/openai.js CHANGED
@@ -18,11 +18,65 @@ const gptbase_1 = __importDefault(require("./gptbase"));
18
18
  const SECTION_LENGTH = 1024; ///每2400个字符分成一组
19
19
  const MESSAGE_LENGTH = 1; ///每次送8句话给openai 进行解析,送多了,会报错
20
20
  //请将答案放在最后,标记为答案:()
21
- const QUESTION_TEXT_MAPPING = {
22
- singlechoice: '你是一名专业的出题老师,根据以下内容,生成@ITEMCOUNT@道单选题,每道题目4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题一个正确答案,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出',
23
- multiplechoice: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道多选题,提供4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题的答案至少有两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出',
24
- trueorfalse: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道判断题,每道题正确和错误两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]的结构输出',
25
- completion: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道填空题和对应答案,输出结果必须是JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]的结构输出' //请将答案放在最后,标记为答案:()
21
+ // const QUESTION_TEXT_MAPPING: any = {
22
+ // singlechoice: '你是一名专业的出题老师,根据以下内容,生成@ITEMCOUNT@道单选题,每道题目4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题一个正确答案,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出',
23
+ // multiplechoice: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道多选题,提供4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题的答案至少有两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出', //请将答案放在最后,标记为答案:()
24
+ // trueorfalse: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道判断题,每道题正确和错误两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]的结构输出', //标记为答案:(正确或错误)
25
+ // completion: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道填空题和对应答案,输出结果必须是JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]的结构输出' //请将答案放在最后,标记为答案:()
26
+ // }
27
+ const FAQ_ROLE_DEFINE = `
28
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的问题及对应的答案和答案的关键词。请记住:
29
+ 1、问题需要偏口语化,问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
30
+ 2、对应的答案必须要在资料中能找到,绝对不能给出在资料里没有的答案,答案的关键词必须完整在所给的答案中出现,绝不能给出不在答案里的关键词;
31
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
32
+ 4、生成的结果严格按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的标准JSON数组结构输出。
33
+ `;
34
+ const QUESTION_ROLE_DEFINE = {
35
+ singlechoice: `
36
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的单选题,每道题包括一个问题和四个选项,其中只有一个选项是正确的。请记住:
37
+ 1、问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
38
+ 2、四个选项用大写字母ABCD开头,其中只有一个是正确的选项,而且这个正确的选项必须要在资料中能找到,绝对不能给出在资料里没有的正确选项;
39
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
40
+ 4、生成的结果严格按照标准JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出`,
41
+ multiplechoice: `
42
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的多选题,每道题包括一个问题和四个选项,其中至少有两个选项是正确的。请记住:
43
+ 1、问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
44
+ 2、四个选项用大写字母ABCD开头,其中至少有两个是正确的选项,而且正确的选项必须要在资料中能找到,绝对不能给出在资料里没有的正确选项;
45
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
46
+ 4、生成的结果严格按照标准JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出
47
+ `,
48
+ trueorfalse: `
49
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的判断题,每道题包括一个问题和一个正确和一个错误的两个选项。请记住:
50
+ 1、问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
51
+ 2、两个选项必须为“正确”和“错误”这两个,正确答案必须是其中一个;
52
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
53
+ 5、生成的结果严格按照标准JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]的结构输出'
54
+ `,
55
+ completion: `
56
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的填空题及对应的答案。请记住:
57
+ 1、问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
58
+ 2、对应的答案必须要在资料中能找到,绝对不能给出在资料里没有的答案,答案尽量选择数字、词组等,字数不超过10个字,避免出现过长的答案;
59
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
60
+ 4、生成的结果严格按照标准JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]的结构输出'
61
+ `
62
+ };
63
+ /**
64
+ * 问题生成的Prompt
65
+ */
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"]}]的结构输出'
71
+ };
72
+ /**
73
+ * 问题生成的Prompt
74
+ */
75
+ const QUESTION_PROMPT_FIXED = {
76
+ singlechoice: '[{"question":"","choice":[],"answer":[]}]',
77
+ multiplechoice: '[{"question":"","choice":[],"answer":[]}]',
78
+ trueorfalse: '[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]',
79
+ completion: '[{"question":"","answer":["填空答案1","填空答案2"]}]'
26
80
  };
27
81
  const QUESTION_TYPE = ['singlechoice', 'multiplechoice', 'trueorfalse', 'completion'];
28
82
  class OpenAIGpt extends gptbase_1.default {
@@ -92,6 +146,12 @@ class OpenAIGpt extends gptbase_1.default {
92
146
  max_tokens: Number((callChatOption === null || callChatOption === void 0 ? void 0 : callChatOption.maxtoken) || this.maxtoken),
93
147
  n: Number((callChatOption === null || callChatOption === void 0 ? void 0 : callChatOption.replyCounts) || 1) || 1
94
148
  }, axiosOption);
149
+ // console.log('finish_reason==>', response.data.choices)
150
+ ////输出的内容不合规
151
+ if (response.data.choices[0].finish_reason === 'content_filter') {
152
+ console.log('content_filter');
153
+ return { successed: false, error: 'content filter' };
154
+ }
95
155
  return { successed: true, message: response.data.choices, usage: response.data.usage };
96
156
  }
97
157
  catch (error) {
@@ -287,7 +347,16 @@ class OpenAIGpt extends gptbase_1.default {
287
347
  */
288
348
  getSummaryOfContent(content, axiosOption = {}) {
289
349
  return __awaiter(this, void 0, void 0, function* () {
290
- const arrContent = typeof (content) == 'string' ? this.splitLongText(content) : content;
350
+ let arrContent = [];
351
+ if (typeof (content) == 'string') {
352
+ let splittext = this.splitLongText(content);
353
+ for (const string of splittext) {
354
+ arrContent.push({ role: 'user', content: string });
355
+ }
356
+ }
357
+ else {
358
+ arrContent = content;
359
+ }
291
360
  let summary = [];
292
361
  while (arrContent.length > 0) {
293
362
  let subarray = arrContent.slice(0, MESSAGE_LENGTH);
@@ -327,16 +396,23 @@ class OpenAIGpt extends gptbase_1.default {
327
396
  while (arrContent.length > 0 && gotted < count) {
328
397
  questions4EverySentense = (count - gotted) / arrContent.length;
329
398
  ////每次最多送MESSAGE_LENGTH句话给openai
330
- let subarray = arrContent.slice(0, 1);
331
- let itemCount = Math.min(Math.ceil(subarray.length * questions4EverySentense), count - gotted);
399
+ let itemCount = Math.min(Math.ceil(questions4EverySentense), count - gotted);
400
+ let subarray = [
401
+ { 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
+ }
405
+ ];
406
+ console.log('Faq Question Pick Prompt:', subarray);
332
407
  //subarray.push({ role: 'user', content:'请根据上述内容,给出一道提问与答案以及答案关键词,按照先问题内容,再标准答案,再关键词的顺序输出,关键词之间用、分开'})
333
- subarray.unshift({ role: 'system', content: `你是一位专业培训师,从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON数组结构输出。` });
408
+ //subarray.unshift({ role: 'system', content: `你是一位专业培训师,从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON数组结构输出。` })
409
+ // subarray.unshift({role: 'system', content: FAQ_ROLE_DEFINE});
334
410
  //subarray.unshift({ role: 'system', content: `你是一位专业程序开发工程师,根据以下内容,按照[{"question":"问题内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]JSON数组结构,给出${itemCount}条提问问题及答案以及答案关键词` })
335
411
  // console.log('subarray', subarray)
336
412
  let result = yield this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
337
413
  if (result.successed && result.message) {
338
414
  // console.log('result is ', result.message[0].message.content)
339
- let msgs = this.pickUpFaqContent(result.message);
415
+ let msgs = yield this.pickUpFaqContent(result.message);
340
416
  if (msgs.length) {
341
417
  ///对外发送检出问答题的信号
342
418
  this.emit('parseout', { type: 'qa', items: msgs });
@@ -345,7 +421,7 @@ class OpenAIGpt extends gptbase_1.default {
345
421
  }
346
422
  }
347
423
  ////删除已经处理的文本
348
- arrContent.splice(0, 4);
424
+ arrContent.splice(0, 1);
349
425
  }
350
426
  arrContent = []; /// 释放内存
351
427
  ///发出信号,解析完毕
@@ -360,32 +436,47 @@ class OpenAIGpt extends gptbase_1.default {
360
436
  */
361
437
  pickUpFaqContent(messages) {
362
438
  var _a, _b;
363
- if (!((_b = (_a = messages[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content))
364
- return [];
365
- let answerString = messages[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
366
- let jsonObj = this.fixedJsonString(answerString);
367
- if (!jsonObj.length)
368
- return [];
369
- try {
370
- //let jsonObj = JSON.parse(answerString);
371
- //let jsonObj = eval(answerString);
372
- jsonObj.map((item) => {
373
- let realKeyword = [];
374
- let keywords = (item.keywords + '').split(',');
375
- let answer = item.answer || '';
376
- for (const k of keywords) {
377
- if (k && answer.indexOf(k) >= 0)
378
- realKeyword.push(k);
439
+ return __awaiter(this, void 0, void 0, function* () {
440
+ if (!((_b = (_a = messages[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content))
441
+ return [];
442
+ let answerString = messages[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
443
+ let jsonObj = this.fixedJsonString(answerString);
444
+ if (!jsonObj.length) {
445
+ let fixedAsk = [
446
+ { role: 'system', content: '角色扮演:假设你是一位高级JSON数据分析师' },
447
+ { role: 'user', content: `请分析以下内容,严格按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的标准JSON数组结构输出。` },
448
+ { role: 'user', content: answerString },
449
+ ];
450
+ console.log('pickUpFaqContent fixedAsk', fixedAsk);
451
+ let fixedJsonResult = yield this.chatRequest(fixedAsk, { replyCounts: 1 }, {});
452
+ if (fixedJsonResult.successed) {
453
+ answerString = fixedJsonResult.message[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
454
+ jsonObj = this.fixedJsonString(answerString);
379
455
  }
380
- item.keywords = realKeyword;
381
- return item;
382
- });
383
- return jsonObj;
384
- }
385
- catch (err) {
386
- console.log('JSON error', err);
387
- return [];
388
- }
456
+ if (!jsonObj.length)
457
+ return [];
458
+ }
459
+ try {
460
+ //let jsonObj = JSON.parse(answerString);
461
+ //let jsonObj = eval(answerString);
462
+ jsonObj.map((item) => {
463
+ let realKeyword = [];
464
+ let keywords = (item.keywords + '').split(',');
465
+ let answer = item.answer || '';
466
+ for (const k of keywords) {
467
+ if (k && answer.indexOf(k) >= 0)
468
+ realKeyword.push(k);
469
+ }
470
+ item.keywords = realKeyword;
471
+ return item;
472
+ });
473
+ return jsonObj;
474
+ }
475
+ catch (err) {
476
+ console.log('JSON error', err);
477
+ return [];
478
+ }
479
+ });
389
480
  }
390
481
  /**
391
482
  * 从指定的文本内容中生成一张试卷
@@ -426,7 +517,6 @@ class OpenAIGpt extends gptbase_1.default {
426
517
  }, noMoreQuestionRetrive = false, totalscore = 0;
427
518
  while (arrContent.length > 0 && !noMoreQuestionRetrive) {
428
519
  ////每次最多送MESSAGE_LENGTH句话给openai
429
- let subarray = arrContent.slice(0, MESSAGE_LENGTH);
430
520
  /**
431
521
  * 每种类型的题目进行遍历
432
522
  */
@@ -436,14 +526,20 @@ class OpenAIGpt extends gptbase_1.default {
436
526
  ///还需要抓取题目
437
527
  if (remainCount[key] > 0) {
438
528
  noMoreQuestionRetrive = false;
439
- let itemCount = Math.min(remainCount[key], Math.ceil(subarray.length * sectionCount[key]));
440
- subarray.unshift({ role: 'system', content: QUESTION_TEXT_MAPPING[key].replace('@ITEMCOUNT@', itemCount) });
529
+ //let itemCount = Math.min(remainCount[key], Math.ceil(subarray.length * sectionCount[key]));
530
+ let itemCount = Math.min(remainCount[key], Math.ceil(sectionCount[key]));
531
+ let subarray = [
532
+ { role: 'system', content: QUESTION_ROLE_DEFINE[key] },
533
+ { role: 'user', content: QUESTION_PROMPT[key].replace('@ITEMCOUNT@', itemCount) },
534
+ { role: 'user', content: arrContent.slice(0, 1)[0] }
535
+ ];
536
+ // subarray.unshift()
441
537
  console.log('subarray', subarray);
442
538
  let result = yield this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
443
539
  console.log('subarray returned', result.successed);
444
540
  if (result.successed && result.message) {
445
541
  //console.log('paper result', key, result.message.length)
446
- let pickedQuestions = this.pickUpQuestions(result.message, itemCount, key, ITEM_SCORE[key]);
542
+ let pickedQuestions = yield this.pickUpQuestions(result.message, itemCount, key, ITEM_SCORE[key]);
447
543
  if (pickedQuestions.length) {
448
544
  ///对外发送检出题目的信号
449
545
  this.emit('parseout', { type: 'question', name: key, items: pickedQuestions });
@@ -452,7 +548,7 @@ class OpenAIGpt extends gptbase_1.default {
452
548
  totalscore = totalscore + pickedQuestions.length * ITEM_SCORE[key];
453
549
  }
454
550
  }
455
- subarray.splice(0, 1); ///把第一个角色定位的问法删除
551
+ //subarray.splice(0, 1); ///把第一个角色定位的问法删除
456
552
  // subarray.splice(subarray.length - 1, 1); ///把第一个角色定位的问法删除
457
553
  }
458
554
  }
@@ -472,76 +568,92 @@ class OpenAIGpt extends gptbase_1.default {
472
568
  */
473
569
  pickUpQuestions(result, count, questiontype, score = 1) {
474
570
  var _a, _b;
475
- if (!((_b = (_a = result[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content))
476
- return [];
477
- let answerString = result[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
478
- let jsonObj = this.fixedJsonString(answerString);
479
- if (!jsonObj.length)
480
- return [];
481
- let returnItems = [];
482
- try {
483
- // let jsonObj = JSON.parse(answerString);
484
- returnItems = jsonObj.map((questionitem) => {
485
- console.log('answer item from jsonObj', questionitem);
486
- if (questionitem.choice && Array.isArray(questionitem.choice) && questiontype != 'completion') {
487
- questionitem.fullanswer = (questionitem.answer + '').replace(/,|[^ABCDE]/g, '');
488
- questionitem.score = score;
489
- if (questionitem.choice) {
490
- questionitem.choice = questionitem.choice.map((item, index) => {
491
- let seqNo = 'ABCDEFG'[index]; //String.fromCharCode(65 + index);
492
- let correctReg = new RegExp(`${seqNo}.|${seqNo}`, 'ig');
493
- // console.log('itemitemitem', item)
494
- //let answer = jsonObj.fullanswer
495
- return {
496
- id: seqNo,
497
- content: (item + '').replace(correctReg, '').trim(),
498
- iscorrect: (questionitem.fullanswer || '').indexOf(seqNo) >= 0 ? 1 : 0
499
- //|| jsonObj.fullanswer.indexOf(m))
500
- };
501
- });
571
+ return __awaiter(this, void 0, void 0, function* () {
572
+ if (!((_b = (_a = result[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content))
573
+ return [];
574
+ let answerString = result[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
575
+ let jsonObj = this.fixedJsonString(answerString);
576
+ ////修复的结果无法用程序修复,请求GPT来分析修复一下这个结果
577
+ if (!jsonObj.length) {
578
+ let fixedAsk = [
579
+ { role: 'system', content: '角色扮演:假设你是一位高级JSON数据分析师' },
580
+ { role: 'user', content: `请分析以下内容,严格按照${QUESTION_PROMPT_FIXED[questiontype]}的标准JSON数组结构输出。` },
581
+ { role: 'user', content: answerString },
582
+ ];
583
+ console.log('fixedAsk', fixedAsk);
584
+ let fixedJsonResult = yield this.chatRequest(fixedAsk, { replyCounts: 1 }, {});
585
+ if (fixedJsonResult.successed) {
586
+ answerString = fixedJsonResult.message[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
587
+ jsonObj = this.fixedJsonString(answerString);
588
+ }
589
+ if (!jsonObj.length)
590
+ return [];
591
+ }
592
+ let returnItems = [];
593
+ try {
594
+ // let jsonObj = JSON.parse(answerString);
595
+ returnItems = jsonObj.map((questionitem) => {
596
+ console.log('answer item from jsonObj', questionitem);
597
+ if (questionitem.choice && Array.isArray(questionitem.choice) && questiontype != 'completion') {
598
+ questionitem.fullanswer = (questionitem.answer + '').replace(/,|[^ABCDE]/g, '');
599
+ questionitem.score = score;
600
+ if (questionitem.choice) {
601
+ questionitem.choice = questionitem.choice.map((item, index) => {
602
+ let seqNo = 'ABCDEFG'[index]; //String.fromCharCode(65 + index);
603
+ let correctReg = new RegExp(`${seqNo}.|${seqNo}`, 'ig');
604
+ // console.log('itemitemitem', item)
605
+ //let answer = jsonObj.fullanswer
606
+ return {
607
+ id: seqNo,
608
+ content: (item + '').replace(correctReg, '').trim(),
609
+ iscorrect: (questionitem.fullanswer || '').indexOf(seqNo) >= 0 ? 1 : 0
610
+ //|| jsonObj.fullanswer.indexOf(m))
611
+ };
612
+ });
613
+ }
614
+ ///如果是非判断题,题目的选项数量小于2 ,则无效
615
+ ///如果是判断题,题目的选项必须=2
616
+ if (!questionitem.choice || (questiontype != 'trueorfalse' && questionitem.choice.length < 3) || (questiontype == 'trueorfalse' && questionitem.choice.length != 2)) {
617
+ return null;
618
+ }
502
619
  }
503
- ///如果是非判断题,题目的选项数量小于2 ,则无效
504
- ///如果是判断题,题目的选项必须=2
505
- if (!questionitem.choice || (questiontype != 'trueorfalse' && questionitem.choice.length < 3) || (questiontype == 'trueorfalse' && questionitem.choice.length != 2)) {
506
- return null;
620
+ switch (questiontype) {
621
+ case 'singlechoice':
622
+ questionitem.answer = (questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('').slice(0, 1);
623
+ break;
624
+ case 'multiplechoice':
625
+ questionitem.answer = (questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('');
626
+ break;
627
+ case 'trueorfalse':
628
+ let rightItem = questionitem.choice.find((x) => { return x.iscorrect == 1; });
629
+ questionitem.answer = [(rightItem === null || rightItem === void 0 ? void 0 : rightItem.id) || 'Z']; //[(questionitem.answer + '').indexOf('正确') >= 0 ? 'A' : 'B']
630
+ break;
507
631
  }
508
- }
509
- switch (questiontype) {
510
- case 'singlechoice':
511
- questionitem.answer = (questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('').slice(0, 1);
512
- break;
513
- case 'multiplechoice':
514
- questionitem.answer = (questionitem.answer + '').replace(/,|[^ABCDEFG]/g, '').split('');
515
- break;
516
- case 'trueorfalse':
517
- let rightItem = questionitem.choice.find((x) => { return x.iscorrect == 1; });
518
- questionitem.answer = [(rightItem === null || rightItem === void 0 ? void 0 : rightItem.id) || 'Z']; //[(questionitem.answer + '').indexOf('正确') >= 0 ? 'A' : 'B']
519
- break;
520
- }
521
- ///单选题验证
522
- if (questiontype == 'singlechoice') {
523
- let rightAnswer = questionitem.choice ? questionitem.choice.filter((item) => { return item.iscorrect === 1; }) : [];
524
- ///单选题的正确选项大于了1个
525
- if (rightAnswer.length != 1 || !questionitem.answer || questionitem.answer.length !== 1)
526
- return null;
527
- ///正确选项和答案不一致
528
- if (rightAnswer[0].id.toUpperCase() != (questionitem.answer[0] || '').toUpperCase())
529
- return null;
530
- }
531
- ///多选题验证
532
- if (questiontype == 'multiplechoice') {
533
- let rightAnswer = questionitem.choice ? questionitem.choice.filter((item) => { return item.iscorrect === 1; }) : [];
534
- ///单选题的正确选项大于了1个
535
- if (rightAnswer.length === 0 || !questionitem.answer || questionitem.answer.length === 0)
536
- return null;
537
- }
538
- return questionitem;
539
- });
540
- }
541
- catch (err) {
542
- console.log('error happened:', err);
543
- }
544
- return returnItems.filter(i => { return i != null; }).slice(0, count);
632
+ ///单选题验证
633
+ if (questiontype == 'singlechoice') {
634
+ let rightAnswer = questionitem.choice ? questionitem.choice.filter((item) => { return item.iscorrect === 1; }) : [];
635
+ ///单选题的正确选项大于了1
636
+ if (rightAnswer.length != 1 || !questionitem.answer || questionitem.answer.length !== 1)
637
+ return null;
638
+ ///正确选项和答案不一致
639
+ if (rightAnswer[0].id.toUpperCase() != (questionitem.answer[0] || '').toUpperCase())
640
+ return null;
641
+ }
642
+ ///多选题验证
643
+ if (questiontype == 'multiplechoice') {
644
+ let rightAnswer = questionitem.choice ? questionitem.choice.filter((item) => { return item.iscorrect === 1; }) : [];
645
+ ///单选题的正确选项大于了1个
646
+ if (rightAnswer.length === 0 || !questionitem.answer || questionitem.answer.length === 0)
647
+ return null;
648
+ }
649
+ return questionitem;
650
+ });
651
+ }
652
+ catch (err) {
653
+ console.log('error happened:', err);
654
+ }
655
+ return returnItems.filter(i => { return i != null; }).slice(0, count);
656
+ });
545
657
  }
546
658
  /**
547
659
  * 验证JSON字符串是否是真正可转换为JSON的合法格式
@@ -607,9 +719,9 @@ class OpenAIGpt extends gptbase_1.default {
607
719
  break;
608
720
  }
609
721
  }
610
- const subtext = content.substr(start, realLength);
722
+ const subtext = content.substr(start, realLength).replace(/\t|\n|\v|\r|\f/g, '');
611
723
  if (subtext)
612
- message.push({ role: 'user', content: subtext });
724
+ message.push(subtext); //message.push({ role: 'user', content: subtext })
613
725
  start += realLength || len;
614
726
  }
615
727
  return message;
@@ -31,7 +31,7 @@ class StabilityPlusAI extends stabilityai_1.default {
31
31
  try {
32
32
  let param = Object.assign(Object.assign({}, axiosOption), { method: "post", url: `${paramOption.endpoint || this.apiSetting.endpoint}/sdapi/v1/txt2img`, data: {
33
33
  "enable_hr": false,
34
- "denoising_strength": paramOption.denoising_strength || this.apiOption.denoising_strength || 0,
34
+ "denoising_strength": paramOption.denoising_strength || this.apiOption.denoising_strength || 0.5,
35
35
  "firstphase_width": 0,
36
36
  "firstphase_height": 0,
37
37
  "hr_scale": paramOption.hr_scale || this.apiOption.hr_scale || 2,
@@ -46,10 +46,10 @@ class StabilityPlusAI extends stabilityai_1.default {
46
46
  "subseed_strength": 0,
47
47
  "seed_resize_from_h": -1,
48
48
  "seed_resize_from_w": -1,
49
- "sampler_name": paramOption.sampler || this.apiOption.sampler || "Euler",
49
+ "sampler_name": paramOption.sampler || this.apiOption.sampler || "Euler a",
50
50
  "batch_size": 1,
51
51
  "n_iter": paramOption.samples || this.apiOption.samples || 1,
52
- "steps": paramOption.steps || this.apiOption.steps || 50,
52
+ "steps": paramOption.steps || this.apiOption.steps || 20,
53
53
  "cfg_scale": paramOption.cfg_scale || this.apiOption.cfg_scale || 7,
54
54
  "width": paramOption.width || this.apiOption.width || 512,
55
55
  "height": paramOption.height || this.apiOption.height || 512,
@@ -69,11 +69,11 @@ class StabilityPlusAI extends stabilityai_1.default {
69
69
  // "save_images": false,
70
70
  // "alwayson_scripts": {}
71
71
  } });
72
- console.log('param', param);
73
72
  const response = yield (0, declare_1.request)(param);
74
73
  if (response.successed) {
75
74
  return { successed: true, type: 'image', data: response.data.images, };
76
75
  }
76
+ console.log('response result ', response.data);
77
77
  return Object.assign({ successed: false }, response.data);
78
78
  }
79
79
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doomiaichat",
3
- "version": "4.6.0",
3
+ "version": "4.8.0",
4
4
  "description": "Doomisoft OpenAI",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
package/src/openai.ts CHANGED
@@ -5,13 +5,68 @@ import { OpenAIApiParameters, ChatReponse, OutlineSummaryItem, SummaryReponse, F
5
5
  const SECTION_LENGTH = 1024; ///每2400个字符分成一组
6
6
  const MESSAGE_LENGTH = 1; ///每次送8句话给openai 进行解析,送多了,会报错
7
7
  //请将答案放在最后,标记为答案:()
8
- const QUESTION_TEXT_MAPPING: any = {
9
- singlechoice: '你是一名专业的出题老师,根据以下内容,生成@ITEMCOUNT@道单选题,每道题目4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题一个正确答案,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出',
10
- multiplechoice: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道多选题,提供4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题的答案至少有两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出', //请将答案放在最后,标记为答案:()
11
- trueorfalse: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道判断题,每道题正确和错误两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]的结构输出', //标记为答案:(正确或错误)
12
- completion: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道填空题和对应答案,输出结果必须是JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]的结构输出' //请将答案放在最后,标记为答案:()
8
+ // const QUESTION_TEXT_MAPPING: any = {
9
+ // singlechoice: '你是一名专业的出题老师,根据以下内容,生成@ITEMCOUNT@道单选题,每道题目4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题一个正确答案,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出',
10
+ // multiplechoice: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道多选题,提供4个选项,每道题的选项中的元素用大写字母ABCD开头,每道题的答案至少有两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出', //请将答案放在最后,标记为答案:()
11
+ // trueorfalse: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道判断题,每道题正确和错误两个选项,输出结果必须是JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]的结构输出', //标记为答案:(正确或错误)
12
+ // completion: '你是一名专业的出题老师,根据以下内容,请生成@ITEMCOUNT@道填空题和对应答案,输出结果必须是JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]的结构输出' //请将答案放在最后,标记为答案:()
13
+ // }
14
+ const FAQ_ROLE_DEFINE = `
15
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的问题及对应的答案和答案的关键词。请记住:
16
+ 1、问题需要偏口语化,问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
17
+ 2、对应的答案必须要在资料中能找到,绝对不能给出在资料里没有的答案,答案的关键词必须完整在所给的答案中出现,绝不能给出不在答案里的关键词;
18
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
19
+ 4、生成的结果严格按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的标准JSON数组结构输出。
20
+ `
21
+
22
+ const QUESTION_ROLE_DEFINE: any = {
23
+ singlechoice: `
24
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的单选题,每道题包括一个问题和四个选项,其中只有一个选项是正确的。请记住:
25
+ 1、问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
26
+ 2、四个选项用大写字母ABCD开头,其中只有一个是正确的选项,而且这个正确的选项必须要在资料中能找到,绝对不能给出在资料里没有的正确选项;
27
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
28
+ 4、生成的结果严格按照标准JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出`,
29
+ multiplechoice: `
30
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的多选题,每道题包括一个问题和四个选项,其中至少有两个选项是正确的。请记住:
31
+ 1、问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
32
+ 2、四个选项用大写字母ABCD开头,其中至少有两个是正确的选项,而且正确的选项必须要在资料中能找到,绝对不能给出在资料里没有的正确选项;
33
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
34
+ 4、生成的结果严格按照标准JSON数组并按照[{"question":"","choice":[],"answer":[]}]的结构输出
35
+ `,
36
+ trueorfalse: `
37
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的判断题,每道题包括一个问题和一个正确和一个错误的两个选项。请记住:
38
+ 1、问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
39
+ 2、两个选项必须为“正确”和“错误”这两个,正确答案必须是其中一个;
40
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
41
+ 5、生成的结果严格按照标准JSON数组并按照[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]的结构输出'
42
+ `,
43
+ completion: `
44
+ 角色扮演:你是一位精通各行业的培训专家,你擅长从资料里提取重点要点,并形成用于培训员工的填空题及对应的答案。请记住:
45
+ 1、问题需要与所给的资料相关,绝不能问超出所给资料的范围;每个问题需要有主语,所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
46
+ 2、对应的答案必须要在资料中能找到,绝对不能给出在资料里没有的答案,答案尽量选择数字、词组等,字数不超过10个字,避免出现过长的答案;
47
+ 3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
48
+ 4、生成的结果严格按照标准JSON数组并按照[{"question":"","answer":["填空答案1","填空答案2"]}]的结构输出'
49
+ `
50
+ }
51
+ /**
52
+ * 问题生成的Prompt
53
+ */
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"]}]的结构输出'
13
59
  }
14
60
 
61
+ /**
62
+ * 问题生成的Prompt
63
+ */
64
+ const QUESTION_PROMPT_FIXED: any = {
65
+ singlechoice: '[{"question":"","choice":[],"answer":[]}]',
66
+ multiplechoice: '[{"question":"","choice":[],"answer":[]}]',
67
+ trueorfalse: '[{"question":"","choice":["A.正确","B.错误"],"answer":[]}]',
68
+ completion: '[{"question":"","answer":["填空答案1","填空答案2"]}]'
69
+ }
15
70
  const QUESTION_TYPE: string[] = ['singlechoice', 'multiplechoice', 'trueorfalse', 'completion']
16
71
 
17
72
  export default class OpenAIGpt extends GptBase {
@@ -84,6 +139,12 @@ export default class OpenAIGpt extends GptBase {
84
139
  max_tokens: Number(callChatOption?.maxtoken || this.maxtoken),
85
140
  n: Number(callChatOption?.replyCounts || 1) || 1
86
141
  }, axiosOption);
142
+ // console.log('finish_reason==>', response.data.choices)
143
+ ////输出的内容不合规
144
+ if (response.data.choices[0].finish_reason ==='content_filter') {
145
+ console.log('content_filter')
146
+ return {successed:false,error:'content filter'}
147
+ }
87
148
  return { successed: true, message: response.data.choices, usage: response.data.usage };
88
149
  } catch (error) {
89
150
  console.log('result is error ', error)
@@ -260,7 +321,15 @@ export default class OpenAIGpt extends GptBase {
260
321
  * @param axiosOption
261
322
  */
262
323
  override async getSummaryOfContent(content: string | Array<any>, axiosOption: any = {}): Promise<SummaryReponse> {
263
- const arrContent = typeof (content) == 'string' ? this.splitLongText(content) : content;
324
+ let arrContent:any[] =[];
325
+ if (typeof (content) == 'string'){
326
+ let splittext = this.splitLongText(content);
327
+ for (const string of splittext){
328
+ arrContent.push({ role: 'user', content: string })
329
+ }
330
+ }else{
331
+ arrContent = content;
332
+ }
264
333
  let summary: Array<OutlineSummaryItem> = [];
265
334
  while (arrContent.length > 0) {
266
335
  let subarray = arrContent.slice(0, MESSAGE_LENGTH);
@@ -296,16 +365,23 @@ export default class OpenAIGpt extends GptBase {
296
365
  while (arrContent.length > 0 && gotted < count) {
297
366
  questions4EverySentense = (count - gotted) / arrContent.length
298
367
  ////每次最多送MESSAGE_LENGTH句话给openai
299
- let subarray = arrContent.slice(0, 1);
300
- let itemCount = Math.min(Math.ceil(subarray.length * questions4EverySentense), count - gotted);
368
+ let itemCount = Math.min(Math.ceil(questions4EverySentense), count - gotted);
369
+ let subarray = [
370
+ { 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
+ }
374
+ ]
375
+ console.log('Faq Question Pick Prompt:', subarray)
301
376
  //subarray.push({ role: 'user', content:'请根据上述内容,给出一道提问与答案以及答案关键词,按照先问题内容,再标准答案,再关键词的顺序输出,关键词之间用、分开'})
302
- subarray.unshift({ role: 'system', content: `你是一位专业培训师,从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON数组结构输出。` })
377
+ //subarray.unshift({ role: 'system', content: `你是一位专业培训师,从以下内容中提取${itemCount}条提问及答案,并从答案内容提取出至少2个关键词,最终结果按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的JSON数组结构输出。` })
378
+ // subarray.unshift({role: 'system', content: FAQ_ROLE_DEFINE});
303
379
  //subarray.unshift({ role: 'system', content: `你是一位专业程序开发工程师,根据以下内容,按照[{"question":"问题内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]JSON数组结构,给出${itemCount}条提问问题及答案以及答案关键词` })
304
380
  // console.log('subarray', subarray)
305
381
  let result = await this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
306
382
  if (result.successed && result.message) {
307
383
  // console.log('result is ', result.message[0].message.content)
308
- let msgs = this.pickUpFaqContent(result.message);
384
+ let msgs = await this.pickUpFaqContent(result.message);
309
385
  if (msgs.length) {
310
386
  ///对外发送检出问答题的信号
311
387
  this.emit('parseout', { type: 'qa', items: msgs })
@@ -316,7 +392,7 @@ export default class OpenAIGpt extends GptBase {
316
392
  }
317
393
 
318
394
  ////删除已经处理的文本
319
- arrContent.splice(0, 4);
395
+ arrContent.splice(0, 1);
320
396
  }
321
397
  arrContent = []; /// 释放内存
322
398
  ///发出信号,解析完毕
@@ -329,11 +405,26 @@ export default class OpenAIGpt extends GptBase {
329
405
  * @param {*} messages
330
406
  * @returns
331
407
  */
332
- protected pickUpFaqContent(messages: Array<any>): Array<FaqItem> {
408
+ protected async pickUpFaqContent(messages: Array<any>): Promise<Array<FaqItem>> {
333
409
  if (!messages[0]?.message?.content) return [];
334
410
  let answerString = messages[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
335
411
  let jsonObj = this.fixedJsonString(answerString);
336
- if (!jsonObj.length) return []
412
+ if (!jsonObj.length){
413
+ let fixedAsk = [
414
+ { role: 'system', content: '角色扮演:假设你是一位高级JSON数据分析师' },
415
+ { role: 'user', content: `请分析以下内容,严格按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的标准JSON数组结构输出。` },
416
+ { role: 'user', content: answerString },
417
+ ]
418
+ console.log('pickUpFaqContent fixedAsk', fixedAsk)
419
+ let fixedJsonResult: any = await this.chatRequest(fixedAsk, { replyCounts: 1 }, {})
420
+ if (fixedJsonResult.successed) {
421
+ answerString = fixedJsonResult.message[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
422
+ jsonObj = this.fixedJsonString(answerString);
423
+ }
424
+ if (!jsonObj.length) return []
425
+ }
426
+
427
+
337
428
  try {
338
429
  //let jsonObj = JSON.parse(answerString);
339
430
  //let jsonObj = eval(answerString);
@@ -393,7 +484,6 @@ export default class OpenAIGpt extends GptBase {
393
484
 
394
485
  while (arrContent.length > 0 && !noMoreQuestionRetrive) {
395
486
  ////每次最多送MESSAGE_LENGTH句话给openai
396
- let subarray = arrContent.slice(0, MESSAGE_LENGTH);
397
487
  /**
398
488
  * 每种类型的题目进行遍历
399
489
  */
@@ -404,14 +494,20 @@ export default class OpenAIGpt extends GptBase {
404
494
  if (remainCount[key] > 0) {
405
495
  noMoreQuestionRetrive = false;
406
496
 
407
- let itemCount = Math.min(remainCount[key], Math.ceil(subarray.length * sectionCount[key]));
408
- subarray.unshift({ role: 'system', content: QUESTION_TEXT_MAPPING[key].replace('@ITEMCOUNT@', itemCount) })
497
+ //let itemCount = Math.min(remainCount[key], Math.ceil(subarray.length * sectionCount[key]));
498
+ let itemCount = Math.min(remainCount[key], Math.ceil(sectionCount[key]));
499
+ let subarray:any[] = [
500
+ { role: 'system', content: QUESTION_ROLE_DEFINE[key] },
501
+ { role: 'user', content: QUESTION_PROMPT[key].replace('@ITEMCOUNT@', itemCount) },
502
+ { role: 'user', content: arrContent.slice(0, 1)[0] }
503
+ ]
504
+ // subarray.unshift()
409
505
  console.log('subarray', subarray)
410
506
  let result = await this.chatRequest(subarray, { replyCounts: 1 }, axiosOption);
411
507
  console.log('subarray returned', result.successed)
412
508
  if (result.successed && result.message) {
413
509
  //console.log('paper result', key, result.message.length)
414
- let pickedQuestions = this.pickUpQuestions(result.message, itemCount, key, ITEM_SCORE[key]);
510
+ let pickedQuestions = await this.pickUpQuestions(result.message, itemCount, key, ITEM_SCORE[key]);
415
511
  if (pickedQuestions.length) {
416
512
  ///对外发送检出题目的信号
417
513
  this.emit('parseout', { type: 'question', name: key, items: pickedQuestions })
@@ -420,7 +516,7 @@ export default class OpenAIGpt extends GptBase {
420
516
  totalscore = totalscore + pickedQuestions.length * ITEM_SCORE[key];
421
517
  }
422
518
  }
423
- subarray.splice(0, 1); ///把第一个角色定位的问法删除
519
+ //subarray.splice(0, 1); ///把第一个角色定位的问法删除
424
520
  // subarray.splice(subarray.length - 1, 1); ///把第一个角色定位的问法删除
425
521
  }
426
522
  }
@@ -438,11 +534,25 @@ export default class OpenAIGpt extends GptBase {
438
534
  * @param {*} result
439
535
  *
440
536
  */
441
- protected pickUpQuestions(result: Array<any>, count: number, questiontype: string, score: number = 1): Array<QuestionItem> {
537
+ protected async pickUpQuestions(result: Array<any>, count: number, questiontype: string, score: number = 1): Promise<Array<QuestionItem>> {
442
538
  if (!result[0]?.message?.content) return [];
443
539
  let answerString = result[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
444
540
  let jsonObj = this.fixedJsonString(answerString);
445
- if (!jsonObj.length) return []
541
+ ////修复的结果无法用程序修复,请求GPT来分析修复一下这个结果
542
+ if (!jsonObj.length){
543
+ let fixedAsk = [
544
+ {role:'system',content:'角色扮演:假设你是一位高级JSON数据分析师'},
545
+ { role: 'user', content: `请分析以下内容,严格按照${QUESTION_PROMPT_FIXED[questiontype]}的标准JSON数组结构输出。` },
546
+ { role: 'user', content: answerString },
547
+ ]
548
+ console.log('fixedAsk', fixedAsk)
549
+ let fixedJsonResult:any =await this.chatRequest(fixedAsk,{replyCounts:1},{})
550
+ if (fixedJsonResult.successed){
551
+ answerString = fixedJsonResult.message[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
552
+ jsonObj = this.fixedJsonString(answerString);
553
+ }
554
+ if (!jsonObj.length) return []
555
+ }
446
556
  let returnItems: QuestionItem[] = [];
447
557
  try {
448
558
  // let jsonObj = JSON.parse(answerString);
@@ -557,8 +667,8 @@ export default class OpenAIGpt extends GptBase {
557
667
  * 将一段很长的文本,按1024长度来划分到多个中
558
668
  * @param {*} content
559
669
  */
560
- protected splitLongText(content: string, len = SECTION_LENGTH): Array<ChatCompletionRequestMessage> {
561
- let start = 0, message: Array<ChatCompletionRequestMessage> = [], length = content.length;
670
+ protected splitLongText(content: string, len = SECTION_LENGTH): string[]{ //Array<ChatCompletionRequestMessage> {
671
+ let start = 0, message: string[] = [], length = content.length;
562
672
  while (start < length) {
563
673
 
564
674
  let realLength: number = len;
@@ -569,8 +679,8 @@ export default class OpenAIGpt extends GptBase {
569
679
  break;
570
680
  }
571
681
  }
572
- const subtext = content.substr(start, realLength);
573
- if (subtext) message.push({ role: 'user', content: subtext })
682
+ const subtext = content.substr(start, realLength).replace(/\t|\n|\v|\r|\f/g, '')
683
+ if (subtext) message.push(subtext); //message.push({ role: 'user', content: subtext })
574
684
  start += realLength || len;
575
685
  }
576
686
  return message;
@@ -20,7 +20,7 @@ export default class StabilityPlusAI extends StabilityAI {
20
20
  url: `${paramOption.endpoint || this.apiSetting.endpoint}/sdapi/v1/txt2img`,
21
21
  data: {
22
22
  "enable_hr": false,
23
- "denoising_strength": paramOption.denoising_strength || this.apiOption.denoising_strength || 0,
23
+ "denoising_strength": paramOption.denoising_strength || this.apiOption.denoising_strength || 0.5,
24
24
  "firstphase_width": 0,
25
25
  "firstphase_height": 0,
26
26
  "hr_scale": paramOption.hr_scale || this.apiOption.hr_scale || 2,
@@ -35,10 +35,10 @@ export default class StabilityPlusAI extends StabilityAI {
35
35
  "subseed_strength": 0,
36
36
  "seed_resize_from_h": -1,
37
37
  "seed_resize_from_w": -1,
38
- "sampler_name": paramOption.sampler || this.apiOption.sampler || "Euler", //"Euler",
38
+ "sampler_name": paramOption.sampler || this.apiOption.sampler || "Euler a", //"Euler",
39
39
  "batch_size": 1,
40
40
  "n_iter": paramOption.samples || this.apiOption.samples || 1, //生成的数量
41
- "steps": paramOption.steps || this.apiOption.steps || 50,
41
+ "steps": paramOption.steps || this.apiOption.steps || 20,
42
42
  "cfg_scale": paramOption.cfg_scale || this.apiOption.cfg_scale || 7,
43
43
  "width": paramOption.width || this.apiOption.width || 512,
44
44
  "height": paramOption.height || this.apiOption.height || 512,
@@ -60,11 +60,11 @@ export default class StabilityPlusAI extends StabilityAI {
60
60
  },
61
61
 
62
62
  };
63
- console.log('param', param)
64
63
  const response: any = await request(param)
65
64
  if (response.successed) {
66
65
  return { successed: true, type: 'image', data: response.data.images, };
67
66
  }
67
+ console.log('response result ', response.data)
68
68
  return { successed: false, ...response.data };
69
69
  } catch (error) {
70
70
  console.log('result is error ', error)