mm_os
Version:
MM_OS服务端架构,用于快速构建应用程序,支持网站建设、小程序后台、AI应用、物联网(IOT/AIOT)、游戏服务端等多种场景。
1,548 lines (1,391 loc) • 43.7 kB
JavaScript
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;