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 +4 -4
- package/dist/openai.js +223 -111
- package/dist/stabilityplusai.js +4 -4
- package/package.json +1 -1
- package/src/openai.ts +134 -24
- package/src/stabilityplusai.ts +4 -4
package/dist/openai.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OpenAIApi
|
|
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):
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
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
|
|
331
|
-
let
|
|
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,
|
|
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
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
let
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
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
|
-
|
|
381
|
-
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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
|
-
|
|
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
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
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
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
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
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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;
|
package/dist/stabilityplusai.js
CHANGED
|
@@ -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 ||
|
|
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
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
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
|
|
300
|
-
let
|
|
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,
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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;
|
package/src/stabilityplusai.ts
CHANGED
|
@@ -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 ||
|
|
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)
|