UNPKG

mm_os

Version:

MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。

1,548 lines (1,391 loc) 43.7 kB
require('mm_matchs'); const Item = require('mm_machine').Drive; /** * 指令驱动类 * @augments {Item} * @class */ class Drive extends Item { static config = { // 应用名称 例如:demo_app 'app': 'server', // 插件名称 例如:demo_plugin 'plugin': 'sys', // 时态, 分before之前、main主要、after之后三个时态, 'tense': 'main', // 分组 'group': 'default', // 类型: query便民查询,action执行,game游戏,orther其他,为空表示未分类 'type': '', // 匹配关键词 'match': [], // 不含关键词 'not_match': [], // 去除关键词 'remove': [], // 摘取 'extract': [], // 阶段 'stage': [ // 第一阶段 { // 方式 'mode': 'fill', // 验证参数集 'param': [ // { // 参数名 // "name": "name", // 参数介绍名 // "title": "名称", // 是否必填, 1为必填, 0为选填 // "required": 1, // 参数描述, 用于提示AI该参数的作用 // "desc": "请输入快递单号", // 示例, 用于提示用户该参数的格式 // "example": "123456789012345678", // // 参数格式 // "format": "", // // 缺少参数提示语,传键值对,例如:{ number: "快递单号多少?" } // "not_tip": "", // // 错误提示 // "error_tip": "", // // 监听语法 // "listen": "", // // 校验函数明 // "func_name": "" // }, ] }, // 第二阶段 { // 方式 'mode': 'update', // 验证参数集 'param': [] }, // 第三阶段 { // 方式 'mode': 'fill', // 验证参数集 'param': [] } ] }; /** * 构造函数 * @param {object} config 配置参数 * @param {object} parent 父对象 * @class */ constructor(config, parent) { super({ ...Drive.config, ...config }, parent); // 默认启用热更新 this.mode = 3; } }; /** * 创建一个参数模型 * @returns {object} 参数模型 */ Drive.prototype.model = function () { return { // 参数名 'name': 'default', // 参数介绍名 'title': '参数显示名称', // 应用名称 例如:demo_app 'app': '', // 插件名称 例如:demo_plugin 'plugin': '', // 是否必填, 1为必填, 0为选填 'required': 1, // 参数描述, 用于提示AI该参数的作用 'desc': '', // 示例, 用于提示用户该参数的格式 'example': '', // 排序 'sort': 10, // 监听语法 'listen': '', // 参数格式 'format': '', // 缺少参数提示语 'not_tip': '', // 更新提示 'update_tip': '', // 错误提示 'error_tip': '' }; }; /** * 校验是否匹配指令 * @param {object} content 请求的正文 * @param {object} db 数据管理器 * @returns {boolean} 匹配返回true,不匹配返回false */ Drive.prototype.match = function (content, db) { var word; var arr = this.config.match; // 如果匹配规则为空,使用智能匹配 if (!arr || arr.length === 0) { return this._smartMatch(content, db); } for (var i = 0; i < arr.length; i++) { var format = arr[i]; var str = content.match(format); if (str) { word = str; break; } } return word; }; /** * 增强的指令匹配方法,支持上下文匹配 * @param {object} msg 消息对象 * @param {object} db 数据管理器 * @returns {boolean} 匹配返回true,不匹配返回false */ Drive.prototype.enhancedMatch = function (msg, db) { // 首先检查标准匹配 var standard_match = this.match(msg.content, db); if (standard_match) { return standard_match; } // 使用上下文信息进行增强匹配 return this._contextAwareMatch(msg, db); }; /** * 基于上下文的智能匹配 * @param {object} msg 消息对象 * @param {object} db 数据管理器 * @returns {boolean} 匹配返回true,不匹配返回false * @private */ Drive.prototype._contextAwareMatch = function (msg, db) { var name = this.config.name.toLowerCase(); var title = this.config.title.toLowerCase(); // var description = this.config.description.toLowerCase(); // var content = (msg.content || '').toLowerCase(); // 1. 基于消息类型的匹配 if (this._matchByMsgType(msg, name, title)) { return true; } // 2. 基于会话上下文的匹配 if (this._matchBySessionContext(msg, name, title)) { return true; } // 3. 基于历史状态的匹配 if (this._matchByHistoryState(msg, name, title, db)) { return true; } // 4. 基于关键词和表单数据的匹配 if (this._matchByKeywordsAndForm(msg, name, title)) { return true; } return false; }; /** * 基于消息类型的匹配 * @param {object} msg 消息对象 * @param {string} name 指令名称 * @param {string} title 指令标题 * @returns {boolean} 匹配返回true * @private */ Drive.prototype._matchByMsgType = function (msg, name, title) { var msg_type = msg.msg_type || 'text'; // 根据指令类型推断支持的消息类型 var supported_types = this._getSupportedMsgTypes(name); // 如果指令支持当前消息类型,增加匹配权重 if (supported_types.includes(msg_type)) { return this._checkContentRelevance(msg.content, title); } return false; }; /** * 获取指令支持的消息类型 * @param {string} name 指令名称 * @returns {Array} 返回支持的消息类型数组 * @private */ Drive.prototype._getSupportedMsgTypes = function (name) { var name_lower = name.toLowerCase(); if (name_lower.includes('image') || name_lower.includes('pic') || name_lower.includes('photo')) { return ['image']; } else if (name_lower.includes('voice') || name_lower.includes('audio')) { return ['voice']; } else if (name_lower.includes('video')) { return ['video']; } else if (name_lower.includes('file') || name_lower.includes('document')) { return ['file']; } else if (name_lower.includes('location') || name_lower.includes('map')) { return ['location']; } else if (name_lower.includes('link') || name_lower.includes('url')) { return ['link']; } else if (name_lower.includes('event')) { return ['event']; } // 默认支持文本类型 return ['text']; }; /** * 检查内容相关性 * @param {string} content 消息内容 * @param {string} title 指令标题 * @returns {boolean} 相关返回true * @private */ Drive.prototype._checkContentRelevance = function (content, title) { if (!content) return false; var content = content.toLowerCase(); var title_lower = title.toLowerCase(); // 简单的关键词匹配 var keywords = title_lower.split(/[\s_\-]+/).filter(function (word) { return word.length > 1; }); for (var i = 0; i < keywords.length; i++) { if (content.includes(keywords[i])) { return true; } } return false; }; /** * 基于会话上下文的匹配 * @param {object} msg 消息对象 * @param {string} name 指令名称 * @param {string} title 指令标题 * @returns {boolean} 匹配返回true * @private */ Drive.prototype._matchBySessionContext = function (msg, name, title) { // 检查群组匹配 if (msg.group && this._isGroupSpecificCmd(name)) { return this._checkContentRelevance(msg.content, title); } // 检查会话类型匹配 var session_type = msg.type === 1 ? 'permanent' : 'temporary'; if (this._isSessionTypeSpecificCmd(name, session_type)) { return this._checkContentRelevance(msg.content, title); } return false; }; /** * 判断是否为群组特定指令 * @param {string} name 指令名称 * @returns {boolean} 是群组特定指令返回true * @private */ Drive.prototype._isGroupSpecificCmd = function (name) { var name_lower = name.toLowerCase(); return name_lower.includes('group') || name_lower.includes('群') || name_lower.includes('broadcast') || name_lower.includes('广播'); }; /** * 判断是否为会话类型特定指令 * @param {string} name 指令名称 * @param {string} session_type 会话类型 * @returns {boolean} 是会话类型特定指令返回true * @private */ Drive.prototype._isSessionTypeSpecificCmd = function (name, session_type) { var name_lower = name.toLowerCase(); if (session_type === 'permanent') { return name_lower.includes('permanent') || name_lower.includes('永久') || name_lower.includes('persistent') || name_lower.includes('持久'); } else { return name_lower.includes('temporary') || name_lower.includes('临时') || name_lower.includes('temp') || name_lower.includes('暂时'); } }; /** * 基于历史状态的匹配 * @param {object} msg 消息对象 * @param {string} name 指令名称 * @param {string} title 指令标题 * @param {object} db 数据管理器 * @returns {boolean} 匹配返回true * @private */ Drive.prototype._matchByHistoryState = function (msg, name, title, db) { // 检查阶段匹配 if (msg.stage && this._isStageSpecificCmd(name, msg.stage)) { return this._checkContentRelevance(msg.content, title); } // 检查结束状态匹配 if (msg.end !== undefined && this._isEndStateSpecificCmd(name, msg.end)) { return this._checkContentRelevance(msg.content, title); } return false; }; /** * 判断是否为阶段特定指令 * @param {string} name 指令名称 * @param {number} stage 当前阶段 * @returns {boolean} 是阶段特定指令返回true * @private */ Drive.prototype._isStageSpecificCmd = function (name, stage) { var name_lower = name.toLowerCase(); // 根据阶段推断指令类型 if (stage === 1) { return name_lower.includes('init') || name_lower.includes('开始') || name_lower.includes('start') || name_lower.includes('启动'); } else if (stage >= 2 && stage <= 8) { return name_lower.includes('process') || name_lower.includes('处理') || name_lower.includes('execute') || name_lower.includes('执行'); } else if (stage === 9) { return name_lower.includes('final') || name_lower.includes('结束') || name_lower.includes('complete') || name_lower.includes('完成'); } return false; }; /** * 判断是否为结束状态特定指令 * @param {string} name 指令名称 * @param {number} end_state 结束状态 * @returns {boolean} 是结束状态特定指令返回true * @private */ Drive.prototype._isEndStateSpecificCmd = function (name, end_state) { var name_lower = name.toLowerCase(); if (end_state === 0) { return name_lower.includes('continue') || name_lower.includes('继续') || name_lower.includes('resume') || name_lower.includes('恢复'); } else { return name_lower.includes('end') || name_lower.includes('结束') || name_lower.includes('stop') || name_lower.includes('停止'); } }; /** * 基于关键词和表单数据的匹配 * @param {object} msg 消息对象 * @param {string} name 指令名称 * @param {string} title 指令标题 * @returns {boolean} 匹配返回true * @private */ Drive.prototype._matchByKeywordsAndForm = function (msg, name, title) { // 检查关键词匹配 if (msg.keyword && this._matchByKeywords(msg.keyword, title)) { return true; } // 检查表单数据匹配 if (msg.form && this._matchByFormData(msg.form, name)) { return true; } return false; }; /** * 基于关键词的匹配 * @param {string} keyword 关键词 * @param {string} title 指令标题 * @returns {boolean} 匹配返回true * @private */ Drive.prototype._matchByKeywords = function (keyword, title) { if (!keyword) return false; var keyword_lower = keyword.toLowerCase(); var title_lower = title.toLowerCase(); var keywords = keyword_lower.split(/\s+/); var title_words = title_lower.split(/[\s_\-]+/); // 检查关键词与指令标题的匹配度 for (var i = 0; i < keywords.length; i++) { for (var j = 0; j < title_words.length; j++) { if (keywords[i] === title_words[j] && keywords[i].length > 1) { return true; } } } return false; }; /** * 基于表单数据的匹配 * @param {string|object} form 表单数据 * @param {string} name 指令名称 * @returns {boolean} 匹配返回true * @private */ Drive.prototype._matchByFormData = function (form, name) { try { var form_data = typeof form === 'string' ? JSON.parse(form) : form; // 检查表单数据是否包含与指令相关的字段 var cmd_fields = this._getCmdSpecificFields(name); for (var field in form_data) { if (form_data.hasOwnProperty(field) && cmd_fields.includes(field)) { return true; } } } catch (e) { // 表单数据解析失败 } return false; }; /** * 获取指令特定的字段 * @param {string} name 指令名称 * @returns {Array} 返回字段数组 * @private */ Drive.prototype._getCmdSpecificFields = function (name) { var name_lower = name.toLowerCase(); var fields = []; // 根据指令名称推断相关字段 if (name_lower.includes('user')) { fields.push('user_id', 'user_name', 'from_user', 'to_user'); } if (name_lower.includes('group')) { fields.push('group', 'chatid'); } if (name_lower.includes('time') || name_lower.includes('date')) { fields.push('create_time', 'update_time'); } if (name_lower.includes('media')) { fields.push('media_id', 'msg_type'); } return fields; }; /** * 智能匹配指令 * @param {string} content 请求正文 * @param {object} db 数据管理器 * @returns {string|boolean} 匹配返回关键词,不匹配返回false * @private */ Drive.prototype._smartMatch = function (content, db) { // 基于指令名称和描述的智能匹配 var name = this.config.name.toLowerCase(); var title = this.config.title.toLowerCase(); var description = this.config.description.toLowerCase(); var content = content.toLowerCase(); // 检查是否包含指令关键词 var keywords = this._extractKeywords(name, title, description); for (var i = 0; i < keywords.length; i++) { var keyword = keywords[i]; if (content.includes(keyword)) { return keyword; } } // 增强的自然语言理解匹配 return this._enhancedNLPMatch(content, name, title); }; /** * 增强的自然语言理解匹配 * @param {string} content 请求正文 * @param {string} name 指令名称 * @param {string} title 指令标题 * @returns {string|boolean} 匹配返回关键词,不匹配返回false * @private */ Drive.prototype._enhancedNLPMatch = function (content, name, title) { var content = content.toLowerCase(); // 根据指令类型进行语义匹配 var patterns = this._getPatternsByCmdType(name, title); var keyword = this._getKeywordByCmdType(name, title); return this._matchPatterns(content, patterns, keyword); }; /** * 根据指令类型获取匹配模式 * @param {string} name 指令名称 * @param {string} title 指令标题 * @returns {Array} 返回正则表达式模式数组 * @private */ Drive.prototype._getPatternsByCmdType = function (name, title) { // 根据指令名称推断指令类型 var cmd_type = this._inferCmdType(name); switch (cmd_type) { case 'open': // 打开类指令的语义匹配 return [ new RegExp('(?:打开|开启|启动|点亮)(?:.*?)' + this._escapeRegex(title)), new RegExp('(?:把|将)(?:.*?)' + this._escapeRegex(title) + '(?:打开|开启|启动)'), new RegExp('(?:需要|想要)(?:.*?)' + this._escapeRegex(title) + '(?:打开|开启|启动)') ]; case 'close': // 关闭类指令的语义匹配 return [ new RegExp('(?:关闭|关掉|熄灭|停止)(?:.*?)' + this._escapeRegex(title)), new RegExp('(?:把|将)(?:.*?)' + this._escapeRegex(title) + '(?:关闭|关掉|熄灭|停止)'), new RegExp('(?:需要|想要)(?:.*?)' + this._escapeRegex(title) + '(?:关闭|关掉|熄灭|停止)') ]; case 'set': // 设置类指令的语义匹配 return [ new RegExp('(?:把|将)(?:.*?)' + this._escapeRegex(title) + '(?:调到|设置为|设为)(\\d+)'), new RegExp('(?:设置|调整)(?:.*?)' + this._escapeRegex(title) + '(?:为|到)(\\d+)'), new RegExp('(?:需要|想要)(?:.*?)' + this._escapeRegex(title) + '(?:为|到)(\\d+)') ]; case 'play': // 播放类指令的语义匹配 return [ new RegExp('(?:播放|放|听)(?:.*?)' + this._escapeRegex(title)), new RegExp('(?:想听|要听|需要)(?:.*?)' + this._escapeRegex(title)), new RegExp('(?:播放|放)(?:.*?)(?:的)' + this._escapeRegex(title)) ]; case 'query': // 查询类指令的语义匹配 return [ new RegExp('(?:查询|查一下|看看)(?:.*?)' + this._escapeRegex(title)), new RegExp('(?:今天|明天|后天)(?:.*?)' + this._escapeRegex(title) + '(?:怎么样|如何)'), new RegExp('(?:需要|想要)(?:.*?)' + this._escapeRegex(title) + '(?:信息|情况)') ]; default: // 通用语义匹配 return [ new RegExp('(?:执行|运行|启动|使用)' + this._escapeRegex(title)), new RegExp('(?:需要|想要)' + this._escapeRegex(title)), new RegExp('(?:帮我|请帮我)' + this._escapeRegex(title)) ]; } }; /** * 根据指令类型获取关键词 * @param {string} name 指令名称 * @param {string} title 指令标题 * @returns {string} 返回关键词 * @private */ Drive.prototype._getKeywordByCmdType = function (name, title) { var cmd_type = this._inferCmdType(name); switch (cmd_type) { case 'open': return '打开' + title; case 'close': return '关闭' + title; case 'set': return '设置' + title; case 'play': return '播放' + title; case 'query': return '查询' + title; default: return title; } }; /** * 推断指令类型 * @param {string} name 指令名称 * @returns {string} 返回指令类型 * @private */ Drive.prototype._inferCmdType = function (name) { var name_lower = name.toLowerCase(); if (name_lower.includes('open') || name_lower.includes('start') || name_lower.includes('begin')) { return 'open'; } else if (name_lower.includes('close') || name_lower.includes('stop') || name_lower.includes('end')) { return 'close'; } else if (name_lower.includes('set') || name_lower.includes('adjust') || name_lower.includes('config')) { return 'set'; } else if (name_lower.includes('play') || name_lower.includes('show') || name_lower.includes('display')) { return 'play'; } else if (name_lower.includes('get') || name_lower.includes('query') || name_lower.includes('search')) { return 'query'; } return 'general'; }; /** * 转义正则表达式特殊字符 * @param {string} str 原始字符串 * @returns {string} 返回转义后的字符串 * @private */ Drive.prototype._escapeRegex = function (str) { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }; /** * 匹配模式列表 * @param {string} content 请求正文 * @param {Array} patterns 正则表达式模式数组 * @param {string} keyword 关键词 * @returns {string|boolean} 匹配返回关键词,不匹配返回false * @private */ Drive.prototype._matchPatterns = function (content, patterns, keyword) { for (var i = 0; i < patterns.length; i++) { if (patterns[i].test(content)) { return keyword; } } return false; }; /** * 提取关键词 * @param {string} name 指令名称 * @param {string} title 指令标题 * @param {string} desc 指令描述 * @returns {Array} 返回关键词数组 * @private */ Drive.prototype._extractKeywords = function (name, title, desc) { var keywords = []; // 从名称中提取关键词 var name_words = name.split(/[\s_\-]+/).filter(function (word) { return word.length > 1 && !['的', '和', '与', '或', '在', '从', '到', '为'].includes(word); }); // 从标题中提取关键词 var title_words = title.split(/[\s_\-]+/).filter(function (word) { return word.length > 1 && !['的', '和', '与', '或', '在', '从', '到', '为'].includes(word); }); // 合并关键词 keywords = keywords.concat(name_words); keywords = keywords.concat(title_words); // 去重 keywords = keywords.filter(function (item, index, self) { return self.indexOf(item) === index; }); return keywords; }; /** * 校验是否不含关键词 * @param {object} content 请求的正文 * @param {object} db 数据管理器 * @returns {boolean} 不含返回true,含有返回false */ Drive.prototype.notMatch = function (content, db) { var bl = true; var arr = this.config.not_match; if (!arr || arr.length === 0) { return bl; } for (var i = 0; i < arr.length; i++) { var format = arr[i]; if (content.match(format)) { bl = false; break; } } return bl; }; /** * 抽取主要内容 * @param {string} content 正文 * @param {object} db 数据管理器 * @returns {object} 返回过滤后的参数 */ Drive.prototype.extract = async function (content, db) { var list = this.config.extract; if (!list || !list.length) { return content; } var result = content; for (var i = 0; i < list.length; i++) { var format = list[i]; var ret = content.match(format); if (ret) { result = ret; } } return result; }; /** * 移除关键词 * @param {Array} content 内容 * @returns {object} 返回过滤后的参数 */ Drive.prototype.remove = async function (content) { var ct = content; var list = this.config.remove; if (!list || !list.length) { return ct; } for (var i = 0; i < list.length; i++) { var format = list[i]; if (format.indexOf('/') === 0) { var fmt = format.replace(/\//g, '\\/').replace(/\r/g, '\\r').replace(/\n/g, '\\n') .replace(/\*/g, '.*').replace( /\{[a-zA-Z\u4e00-\u9fa5_]+\}/g, '[\s\S]*'); var rx = eval(fmt); ct = ct.replace(rx, '').trim(); } else { ct = ct.replace(format, '').trim(); } } return ct; }; /** * 修改提示 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @param {string} tip 提示模板 * @returns {object|string} 返回过滤后的参数 */ Drive.prototype.viewTip = async function (msg, db, tip) { var form = this.view(msg, db); return tip.replace('{form}', form); }; /** * 1. 检验阶段, 判断条件是否满足 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {string} 验证失败返回错误提示 */ Drive.prototype.check = async function (msg, db) { // 校验是否匹配指令 var word = await this.match(msg.content, db); if (word) { var bl = await this.notMatch(msg.content, db); if (!bl) { return; } } return word; }; /** * 2. 过滤阶段, 抽出主要的内容 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 返回过滤后的参数 */ Drive.prototype.filter = async function (msg, db) { var content = await this.extract(msg.content); content = await this.remove(content); if (content) { msg.keyword = content; } return content; }; /** * 3.1 信息补全阶段 用于通知用户补全执行的必要条件 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @param {object} stage 阶段参数 * @returns {object} 返回参数表单 */ Drive.prototype.fill = async function (msg, db, stage) { if (!stage || !stage.param || stage.param.length === 0) { return ''; } var form = this._getForm(msg); var ct = msg.content_last || ''; var result = await this._processFillParams(stage.param, form, ct, msg, db); this._updateMsgForm(msg, db, result.form, result.keyword); return result.tip; }; /** * 获取表单 * @param {object} msg 消息上下文 * @returns {object} 表单数据 * @private */ Drive.prototype._getForm = function (msg) { if (msg.form) { return msg.form.toJson(); } return {}; }; /** * 处理填充参数 * @param {Array} paramList 参数列表 * @param {object} form 表单数据 * @param {string} ct 内容 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 处理结果 * @private */ Drive.prototype._processFillParams = async function (paramList, form, ct, msg, db) { var keyword = ''; var tip = ''; var new_ct = ct; var new_form = { ...form }; for (var i = 0; i < paramList.length; i++) { var o = paramList[i]; var k = o.name; if (!new_form[k]) { var result = await this._processParam(o, new_ct, msg, db); if (result.value) { new_form[k] = result.value; new_ct = ''; } else { tip = result.tip; if (new_ct) { break; } else { keyword = k; break; } } } } return { keyword, tip, form: new_form }; }; /** * 处理单个参数 * @param {object} param 参数对象 * @param {string} ct 内容 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 处理结果 * @private */ Drive.prototype._processParam = async function (param, ct, msg, db) { if (ct) { var value = ct; if (param.format) { value = value.matchs(param.format); } if (value) { return { value, tip: '' }; } else if (param.error_tip) { var tip = await this.viewTip(msg, db, param.error_tip); return { value: null, tip }; } else if (param.not_tip) { var tip = await this.viewTip(msg, db, param.not_tip); return { value: null, tip }; } } else if (param.not_tip) { var tip = await this.viewTip(msg, db, param.not_tip); return { value: null, tip }; } return { value: null, tip: '' }; }; /** * 更新消息表单 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @param {object} form 表单数据 * @param {string} keyword 关键词 * @private */ Drive.prototype._updateMsgForm = function (msg, db, form, keyword) { msg.form = JSON.stringify(form); db.form = form; msg.keyword = keyword; }; /** * 3.2 更新信息 用于用户更改完善 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @param {object} stage 阶段参数 * @returns {object} 返回参数表单 */ Drive.prototype.set = async function (msg, db, stage) { if (!stage || !stage.param || stage.param.length === 0) { return ''; } var form = this._getForm(msg); var ct = msg.content_last || ''; var result = await this._processSetParams(stage.param, form, ct, msg); this._updateMsgFormOnly(msg, db, result.form); return result.tip; }; /** * 处理设置参数 * @param {Array} paramList 参数列表 * @param {object} form 表单数据 * @param {string} ct 内容 * @param {object} msg 消息上下文 * @returns {object} 处理结果 * @private */ Drive.prototype._processSetParams = async function (paramList, form, ct = '', msg = {}) { var new_form = { ...form }; for (var i = 0; i < paramList.length; i++) { var o = paramList[i]; var k = o.name; if (new_form[k]) { var value = ct.matchs(o.listen); if (value) { var tip = this._generateUpdateTip(o, value); msg.note = k; return { tip, form: new_form }; } else if (msg.note == k && o.format) { value = ct.matchs(o.format); if (value) { new_form[k] = value; } } } } return { tip: '', form: new_form }; }; /** * 生成更新提示 * @param {object} param 参数对象 * @param {string} value 值 * @returns {string} 提示信息 * @private */ Drive.prototype._generateUpdateTip = function (param, value) { if (param.update_tip) { return param.update_tip; } return '那' + value.replace(value.matchs('{不对}'), '是?'); }; /** * 仅更新消息表单 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @param {object} form 表单数据 * @private */ Drive.prototype._updateMsgFormOnly = function (msg, db, form) { msg.form = JSON.stringify(form); db.form = form; }; /** * 4. 执行阶段 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 返回执行结果 */ Drive.prototype.chat = async function (msg, db) { // 如果有表单数据,使用表单执行 if (msg.form) { return await this._execForm(msg, db); } // 否则使用自然语言理解执行 return await this._execNLP(msg, db); }; /** * 执行指令主函数 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 执行结果 */ Drive.prototype.main = async function (msg, db) { console.log('执行指令主函数', msg.content, db.ret); }; /** * 使用表单数据执行指令 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 返回执行结果 * @private */ Drive.prototype._execForm = async function (msg, db) { var form_data = msg.form.toJson(); // 这里可以根据具体的指令逻辑进行处理 // 示例:返回表单数据确认 var result = '指令执行完成,参数如下:\\n'; for (var key in form_data) { if (form_data.hasOwnProperty(key)) { result += `${key}: ${form_data[key]}\\n`; } } return result; }; /** * 使用自然语言理解执行指令 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 返回执行结果 * @private */ Drive.prototype._execNLP = async function (msg, db) { // 分析用户意图 var intent = this._analyzeIntent(msg.content); // 根据意图执行相应的逻辑 switch (intent.type) { case 'query': return await this._handleQueryIntent(intent, msg, db); case 'action': return await this._handleActionIntent(intent, msg, db); case 'help': return await this._handleHelpIntent(intent, msg, db); default: return await this._handleDefaultIntent(intent, msg, db); } }; /** * 分析用户意图 * @param {string} content 消息内容 * @returns {object} 返回意图分析结果 * @private */ Drive.prototype._analyzeIntent = function (content) { var intent = { type: 'unknown', confidence: 0.5, entities: [], keywords: [] }; var content = content.toLowerCase(); // 查询类意图 var query_keywords = ['查询', '查找', '搜索', '查一下', '找一下', '什么是', '哪里', '什么时候']; // 操作类意图 var action_keywords = ['执行', '运行', '启动', '打开', '关闭', '设置', '配置']; // 帮助类意图 var help_keywords = ['帮助', '怎么用', '如何使用', '说明', '介绍']; // 检查意图类型 for (var i = 0; i < query_keywords.length; i++) { if (content.includes(query_keywords[i])) { intent.type = 'query'; intent.confidence = 0.8; break; } } for (var i = 0; i < action_keywords.length; i++) { if (content.includes(action_keywords[i])) { intent.type = 'action'; intent.confidence = 0.8; break; } } for (var i = 0; i < help_keywords.length; i++) { if (content.includes(help_keywords[i])) { intent.type = 'help'; intent.confidence = 0.9; break; } } // 提取实体和关键词 intent.entities = this._extractEntities(content); intent.keywords = this._extractKeywords(content); return intent; }; /** * 提取实体 * @param {string} content 消息内容 * @returns {Array} 返回实体数组 * @private */ Drive.prototype._extractEntities = function (content) { var entities = []; // 提取时间实体 var time_patterns = [/\d{4}-\d{2}-\d{2}/, /\d{2}:\d{2}/, /今天|明天|昨天|本周|本月|今年/]; // 提取数字实体 var number_patterns = [/\d+/]; // 提取地点实体 var location_patterns = [/在.+?(?:市|区|县|街道|路|号)/]; // 这里可以添加更复杂的实体提取逻辑 return entities; }; /** * 从内容中提取关键词 * @param {string} content 消息内容 * @returns {Array} 返回关键词数组 * @private */ Drive.prototype._extractKeywords = function (content) { var words = content.split(/[\s\p{P}]/u).filter(function (word) { return word.length > 1 && !['的', '了', '在', '是', '有', '和', '与', '或'].includes(word); }); return words; }; /** * 处理查询意图 * @param {object} intent 意图对象 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {string} 返回查询结果 * @private */ Drive.prototype._handleQueryIntent = async function (intent, msg, db) { return `正在为您查询关于"${msg.content}"的信息...`; }; /** * 处理操作意图 * @param {object} intent 意图对象 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {string} 返回操作结果 * @private */ Drive.prototype._handleActionIntent = async function (intent, msg, db) { return `正在执行"${msg.content}"操作...`; }; /** * 处理帮助意图 * @param {object} intent 意图对象 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {string} 返回帮助信息 * @private */ Drive.prototype._handleHelpIntent = async function (intent, msg, db) { var help_text = `指令帮助:${this.config.title}\\n`; help_text += `描述:${this.config.description}\\n`; help_text += `使用方法:${this._generateUsageExamples()}`; return help_text; }; /** * 处理默认意图 * @param {object} intent 意图对象 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {string} 返回默认回复 * @private */ Drive.prototype._handleDefaultIntent = async function (intent, msg, db) { return `已收到您的指令:${msg.content}`; }; /** * 生成使用示例 * @returns {string} 返回使用示例 * @private */ Drive.prototype._generateUsageExamples = function () { var examples = []; // 根据指令类型生成不同的示例 switch (this.config.type) { case 'query': examples.push('• 查询信息:"查询天气"'); examples.push('• 搜索内容:"搜索新闻"'); break; case 'action': examples.push('• 执行操作:"执行任务"'); examples.push('• 启动功能:"启动服务"'); break; case 'game': examples.push('• 开始游戏:"开始游戏"'); examples.push('• 游戏操作:"移动角色"'); break; default: examples.push('• 使用指令:直接说出您的需求'); examples.push('• 获取帮助:"帮助"或"怎么用"'); } return examples.join('\\n'); }; /** * 5. 结束阶段 用来判断是否结束会话 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @param {object} ret 执行结果 * @returns {boolean} 返回会话结果 */ Drive.prototype.end = async function (msg, db, ret) { if (ret) { var txt = ''; if (typeof (ret) == 'object') { txt = JSON.stringify(ret); } else { txt = ret; } if (this.config.tense == 'main') { if (txt.indexOf('?') === -1 && txt.indexOf('?') === -1) { msg.end = 0; } } } return ret; }; /** * 执行前 用于有历史信息时,直接获取,不重复询问 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 执行结果, 如果有结果则直接跳过其他步骤,并返回 */ Drive.prototype.runBefore = async function (msg, db) { return null; }; /** * 执行后, 用于特殊情况下的不结束会话 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @param {object} ret 执行结果 * @returns {object|string} 返回执行结果 */ Drive.prototype.runAfter = async function (msg, db, ret) { return ret; }; /** * 执行 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 返回执行结果 */ Drive.prototype.run = async function (msg, db) { var ret; try { // 第一步, 验证阶段 var match = await this.check(msg, db); if (!match) { return; } msg.match = typeof match === 'string' ? match.substring(0, 255) : JSON.stringify(match).substring(0, 255); // 第二步, 过滤阶段 await this.filter(msg, db); // 执行前 ret = await this.runBefore(msg, db); if (!ret) { // 第三步, 信息补全或更新阶段 var stages = this.config.stage; if (stages.length >= msg.stage) { var stage = stages[msg.stage - 1]; if (stage) { var mode = stage.mode ? stage.mode : 'fill'; if (this[mode]) { ret = await this[mode](msg, db, stage); } } } if (!ret) { // 第四步, 执行阶段 ret = await this.main(msg, db); // 第五步, 结束会话阶段 ret = this.end(msg, db, ret); } } // 执行后 ret = await this.runAfter(msg, db, ret); } catch (error) { this.log('error', '指令执行失败!', this.config.name, error); // 错误处理:如果指令执行失败,可以回退到AI处理 if (this._shouldFallbackToAI(error)) { ret = await this._fallbackToAI(msg, db); } else { ret = '指令执行失败,请稍后重试'; } } return ret; }; /** * 判断是否应该回退到AI处理 * @param {Error} error 错误对象 * @returns {boolean} 返回是否应该回退 * @private */ Drive.prototype._shouldFallbackToAI = function (error) { // 检查是否配置了AI回退 var cmd = this.getCmdManager(); if (!cmd || !cmd.config.deepseek.enable) { return false; } // 检查错误类型,如果是可恢复的错误,允许回退 var recoverable_errors = [ '参数缺失', '格式错误', '无法理解', '未找到' ]; var error_message = error.message.toLowerCase(); for (var i = 0; i < recoverable_errors.length; i++) { if (error_message.includes(recoverable_errors[i].toLowerCase())) { return true; } } return false; }; /** * 回退到AI处理 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {string} 返回AI的回复 * @private */ Drive.prototype._fallbackToAI = async function (msg, db) { var cmd = this.getCmdManager(); if (!cmd) { return '指令执行失败,无法回退到AI处理'; } // 构建包含指令信息的上下文 var enhanced_msg = { ...msg, content: `指令"${this.config.title}"执行失败,用户原话:${msg.content}` }; return await cmd._runAI(enhanced_msg, db); }; /** * 获取Cmd管理器 * @returns {object} 返回Cmd管理器实例 * @private */ Drive.prototype.getCmdManager = function () { // 这里需要根据实际的项目结构来获取Cmd管理器 // 假设可以通过全局对象或父级引用获取 if (typeof $ !== 'undefined' && $.admin && $.admin.cmd) { return $.admin.cmd(); } return null; }; /** * 增强的过滤方法,支持自然语言理解 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 返回过滤后的参数 */ Drive.prototype.enhancedFilter = async function (msg, db) { // 先执行原有的过滤逻辑 var result = await this.filter(msg, db); // 如果过滤后没有结果,尝试使用NLP提取关键信息 if (!result || result === msg.content) { var nlp_result = await this._extractNLP(msg.content); if (nlp_result) { msg.keyword = nlp_result; return nlp_result; } } return result; }; /** * 使用NLP提取关键信息 * @param {string} content 消息内容 * @returns {string} 返回提取的关键信息 * @private */ Drive.prototype._extractNLP = async function (content) { // 这里可以集成更复杂的NLP处理 // 目前使用简单的关键词提取 // 移除常见的语气词和连接词 var stop_words = ['请', '帮', '我', '想要', '需要', '可以', '吗', '呢', '吧', '啊']; var words = content.split(/[\s\p{P}]/u).filter(function (word) { return word.length > 0 && !stop_words.includes(word); }); return words.join(' '); }; /** * 查看参数 * @param {object} msg 消息上下文 * @param {object} db 数据管理器 * @returns {object} 返回结构化参数 */ Drive.prototype.view = function (msg, db) { var ret = ''; if (msg.form) { var json = msg.form.toJson(); var stage = this.config.stage; if (stage && stage.length >= msg.stage) { var list = stage[msg.stage - 1].param; if (list) { for (var i = 0; i < list.length; i++) { var o = list[i]; var value = json[o.name]; if (value) { ret += o.title + ': ' + value + '\r\n'; } } } } } return ret.trim(); }; /** * 获取插件 * @param {string} app 应用名称 * @param {string} name 插件名称 * @returns {object} 返回获取到的插件 */ Drive.prototype.plugin = function (app, name) { var l = $.slash; var app_name = app || this.config_file.between('app' + l, l); var plugin_name = name || this.config_file.between('plugin' + l, l); var plus; var plugins = $.pool.plugin[app_name]; if (plugins) { plus = plugins.get(plugin_name); } return plus; }; /** * 获取模型 * @param {string} type 模型类型 * @returns {object} 返回获取到的模型 */ Drive.prototype.getModel = function (type) { let model = { ...this.config }; let dir = this.getDir(); let l = $.slash; let app_name = dir.between('app' + l, l); let plugin_name = dir.between('plugin' + l, l); let name = dir.basename(); model.app = app_name; model.plugin = plugin_name; model.name = model.name || name; return model; }; module.exports = Drive;