tmaiplugin
Version:
TrainingMaster AIGC Component
139 lines (138 loc) • 7.35 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FaqPlugin = void 0;
const stringutil_1 = require("./util/stringutil");
const aipluginbase_1 = __importDefault(require("./aipluginbase"));
const FAQ_ROLE_DEFINE = [
'你是一位精通各行业的培训专家,擅长根据文档内容提取重点要点,形成培训问题及答案',
'你是一位程序设计专家,特别擅长数据分析,内容组织并进行结构化设计,形成Json格式的数据'
];
const PROMPT_LINK = [
`根据以下内容提炼{{COUNT}}道问题、答案和答案的关键词。要求如下:
1、问题偏口语化,问题需要与所给的资料相关,绝不能问超出所给资料的范围;所提问题需要准确、完整、清晰,绝不能有歧义;意思相近的问题不要重复给出;
2、对应的答案必须要在资料中能找到,绝对不能给出在资料里没有的答案,答案的关键词必须完整在所给的答案中出现,绝不能给出不在答案里的关键词;
3、生成问题的时候,请出具有代表性的问题,对于一些无关紧要的问题可以忽略。特别注意资料中关于数字、参数、特点等关键信息的提取,在给出的问题中尽可能覆盖;
4、输出结果包括:问题、答案、答案关键词;
5、如果无法从内容中提炼任何问题,仅需返回"NO"。
内容如下:"""
{{CONTENT}}
"""`,
`请将内容按照[{"question":"提问内容","answer":"答案内容","keywords":["关键词1","关键词2"]}]的标准Json数组结构输出。
内容如下:"""
{{CONTENT}}
"""`
];
/**
* Faq问题的提取器插件
*/
class FaqPlugin extends aipluginbase_1.default {
/**
* 从指定的文本内容中生成相关的问答
* @param {*} content
* @param {*} count
* @param {*} axiosOption
* @returns
*/ //并在答案末尾处必须给出答案内容中的关键词
execute(params) {
return __awaiter(this, void 0, void 0, function* () {
let { content, count, sectionlength, axios } = params;
sectionlength = sectionlength || 1024;
if (!this.gptInstance)
return null;
let arrContent = (0, stringutil_1.splitLongText)(content, sectionlength);
///每一句话需要产生的题目
let questions4EverySentense = count / arrContent.length; //Math.ceil(arrContent.length / 20);
let faqs = [], gotted = 0;
while (arrContent.length > 0 && gotted < count) {
questions4EverySentense = (count - gotted) / arrContent.length;
////每次最多送MESSAGE_LENGTH句话给openai
let itemCount = Math.min(Math.ceil(questions4EverySentense), count - gotted);
let subarray = [
{ role: 'system', content: FAQ_ROLE_DEFINE[0] },
{ role: 'user', content: PROMPT_LINK[0].replace('{{COUNT}}', itemCount).replace('{{CONTENT}}', arrContent.slice(0, 1)[0]) },
];
console.log('Faq Question Pick Prompt:', subarray);
let result = yield this.gptInstance.chatRequest(subarray, { replyCounts: 1 }, axios);
///如果请求发生了网络错误(不是内容合规问题),则再重试一次,如果任然有错则放弃
if (!result.successed && result.error != 'content_filter') {
console.log('network error,retry onemore time');
result = yield this.gptInstance.chatRequest(subarray, { replyCounts: 1 }, axios);
}
if (result.successed && result.message) {
let msgs = yield this.pickUpFaqContent(result.message);
if (msgs.length) {
///对外发送检出问答题的信号
this.emit('parseout', { type: 'qa', items: msgs });
gotted += msgs.length; //result.message.length;
faqs = faqs.concat(msgs);
}
}
////删除已经处理的文本
arrContent.splice(0, 1);
}
arrContent = []; /// 释放内存
///发出信号,解析完毕
this.emit('parseover', { type: 'qa', items: faqs });
return { successed: true, message: faqs.slice(0, count) };
});
}
/**
* 解析Faq返回的问题
* @param {*} messages
* @returns
*/
pickUpFaqContent(messages) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
if (!this.gptInstance || !((_b = (_a = messages[0]) === null || _a === void 0 ? void 0 : _a.message) === null || _b === void 0 ? void 0 : _b.content))
return [];
let answerString = messages[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
if (answerString.includes('NO'))
return [];
let orgJsonPrompt = [
{ role: 'system', content: FAQ_ROLE_DEFINE[1] },
{ role: 'user', content: PROMPT_LINK[1].replace('{{CONTENT}}', answerString) }
];
console.log('orgJsonPrompt', orgJsonPrompt);
let fixedJsonResult = yield this.gptInstance.chatRequest(orgJsonPrompt, { replyCounts: 1 }, {});
if (fixedJsonResult.successed) {
answerString = fixedJsonResult.message[0].message.content.trim().replace(/\t|\n|\v|\r|\f/g, '');
}
let jsonObj = fixedJsonResult.successed ? (0, stringutil_1.fixedJsonString)(answerString) : [];
if (!jsonObj.length)
return [];
try {
jsonObj.map((item) => {
let realKeyword = [];
let keywords = (item.keywords + '').split(',');
let answer = item.answer || '';
item.question = item.question.replace(/^问题\s*\d*\s*(:|:)*/, '');
for (const k of keywords) {
if (k && answer.indexOf(k) >= 0)
realKeyword.push(k);
}
item.keywords = realKeyword;
return item;
});
return jsonObj;
}
catch (err) {
console.log('JSON error', err);
return [];
}
});
}
}
exports.FaqPlugin = FaqPlugin;