package com.ch.jedge.jbot2.intent; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.ch.jedge.utils.JedgeLlmUtil; import com.changhong.jedge.JMgbusModual; import com.changhong.jedge.JMgbusService; import com.changhong.jedge.JMgbusUtil; import com.changhong.jedge.MgbusApi; import com.changhong.qlib.QData; import com.changhong.qlib.intf.QIData; import com.changhong.qlib.intf.QIDataList; import com.changhong.qlib.util.StringUtils; import com.changhong.qlib.util.sync.SystemUtils; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.ch.jedge.utils.JedgeBotConst.sval_default_jbot_jedge; public class JedgeJBotCBService extends JMgbusService { private boolean is_active_ = false; private boolean is_online_ = false; private final Object quitCtrl = new Object(); //已扫描到的Domain信息 private final Map registeredDomainMap = new HashMap<>(); //已扫描到的Domain信息 private final Map registeredDmDomainMap = new HashMap<>(); //已扫描到的数据集信息 private final Map registeredObjectsMap = new HashMap<>(); private final Map registeredClassesMap = new HashMap<>(); //数据集获取API的信息 private final Map DataGetterMap = new HashMap<>(); //已读取的数据集 private final Map ObjModDataMap = new HashMap<>(); private final Map ClsModDataMap = new HashMap<>(); public JedgeJBotCBService(JMgbusModual holder) { super(holder); auto_remove_call_info = false; watchLocalEvent("OnModuleConnected", (w, keyVal, msg) -> { String host = msg.getString("host"); int port = msg.getInteger("port"); is_online_ = true; watchMgbusEvent("online", "jbot!", qiData -> { synchronized (quitCtrl) { if (!is_active_) { is_active_= true; module.postThread(this::refreshJBotRegister); } } synchronized (quitCtrl) { quitCtrl.notifyAll(); } }); //要注意定时刷新 return true; }); watchLocalEvent("OnModuleDisconnected", (w, keyVal, msg) -> { String host = msg.getString("host"); int port = msg.getInteger("port"); is_online_ = false; synchronized (quitCtrl) { quitCtrl.notifyAll(); } return true; }); } @Override public void onServiceStop() { is_online_ = false; quitCtrl.notifyAll(); super.onServiceStop(); } private void prepareDomainInfo() { JedgeDomain domain = this.getClass().getAnnotation(JedgeDomain.class); if(domain!=null) { String dmList = domain.domains(); if(StringUtils.isValidStr(dmList)) { for(String dmDef : dmList.split(",")) { registerDynamicDomain(dmDef); } } } } private void registerDynamicDomain(String dmDef) { if(!StringUtils.isValidStr(dmDef)) return; File file = new File(dmDef + '/' + "domain.json"); if(!file.exists()) { module.errLog("domain def not exists %s", dmDef); return; } QIData df = QData.fromFile(file); if(df.isEmpty()) { module.errLog("domain def is empty : %s", dmDef); return; } synchronized (registeredDomainMap) { registeredDomainMap.put(df.getKey(), df); } synchronized (registeredDmDomainMap) { registeredDmDomainMap.put(df.getKey(), df); } } private void refreshJBotRegister() { while(is_online_) { //准备数据集API prepareDataSetMethods(); //注册领域 prepareDomainInfo(); //注册API回调信息 autoRegisterJBotAPIDomains(); //注册数据集(允许提取的常量参数或对象的状态等) autoRegisterJBotDataSets(); SystemUtils.tryWaitforSingal(quitCtrl, 90 * 1000); } is_active_ = false; } private void prepareDataSetMethods() { Class cls = this.getClass(); while(JMgbusService.class.isAssignableFrom(cls)) { Method[] methods = cls.getDeclaredMethods(); for (Method m : methods) { JDataGetter a = m.getAnnotation(JDataGetter.class); if (a != null) { Class r = m.getReturnType(); Class[] pm = m.getParameterTypes(); if (List.class.isAssignableFrom(r) && pm.length == 0) { registerJBotDataGetter(a, m.getName(), m); } } } cls = cls.getSuperclass(); } } private void autoRegisterJBotDataSets() { Class cls = this.getClass(); while(JedgeJBotCBService.class.isAssignableFrom(cls)) { Method[] methods = cls.getDeclaredMethods(); for (Method m : methods) { JbotClass c = m.getAnnotation(JbotClass.class); if(c!=null) { Class r = m.getReturnType(); Class[] pm = m.getParameterTypes(); if (List.class.isAssignableFrom(r) && pm.length == 0) { String cbUri = String.format("/%s/%s", getName(), m.getName()); registerJBotClasses(c, m.getName(), module.getName(), cbUri); } } JbotObject a = m.getAnnotation(JbotObject.class); if (a != null) { Class r = m.getReturnType(); Class[] pm = m.getParameterTypes(); if (List.class.isAssignableFrom(r) && pm.length == 0) { String cbUri = String.format("/%s/%s", getName(), m.getName()); registerJBotObjects(a, m.getName(), module.getName(), cbUri); } } } cls = cls.getSuperclass(); } } protected void autoRegisterJBotAPIDomains() { Class cls = this.getClass(); while(JMgbusService.class.isAssignableFrom(cls)) { Method[] methods = cls.getDeclaredMethods(); for (Method m : methods) { JbotApi a = m.getAnnotation(JbotApi.class); if (a != null) { Class r = m.getReturnType(); Class[] pm = m.getParameterTypes(); if (QIData.class.isAssignableFrom(r) && pm.length == 1 && QIData.class.isAssignableFrom(pm[0])) { String cbUri = String.format("/%s/%s", getName(), m.getName()); String domain = a.domain(); //注册知识世界领域 registerJBotKnDomain(domain, module.getName(), cbUri); //先注册模型世界领域 registerJBotDmDomain(domain, module.getName(), cbUri); } } } cls = cls.getSuperclass(); } } private void registerJBotKnDomain(String domain, String moduleName, String cbUri) { QIData req = new QData().putString("cbUri", cbUri).putString("src", moduleName) .putString("key", domain); synchronized (registeredDomainMap){ if(registeredDomainMap.containsKey(domain)) { req.copyFrom(registeredDomainMap.get(domain), "picker","dmid"); } } StringBuilder disc = new StringBuilder("可选实体列表如下:"); synchronized (ObjModDataMap) { QIData objData = ObjModDataMap.get(domain); if(objData!=null) { List keys = JedgeLlmUtil.getSortedKeyList(objData); if(keys!=null) { for (String ok : keys) { JSONArray data = objData.getJsonArray(ok); if (data != null) { for (Object od : data) { if (od instanceof String) { QIData odd = QData.fromString((String) od); disc.append(String.format("实体对象:%s,实体类型:%s, 动实体作:%s," ,odd.getName(), odd.getString("class"), odd.getString("disc"))); } } } } } //, // 实体对象:电视,实体类型:电视控制器, 动实体作:电视控制(打开或关闭电视), // 实体对象:声音,实体类型:声音控制器, 动实体作:电视音量设置(大小或具体数字), // 实体对象:屏幕,实体类型:屏幕控制器, 动实体作:电视亮度设置(大小或具体数字),屏幕色彩(亮丽,普通,柔和模式设置), // 实体对象:源,实体类型源控制器, 动实体作:执行切换源(可以切换到:ATV,HDMI)等动作" } } req.putString("disc", disc.toString()); QIData re = postServiceRequest(sval_default_jbot_jedge, "/gpt/registerDomain", req); if(!JMgbusUtil.isMgbusResultOk(re)) { module.errLog(String.format("知识领域注册失败 (%s) to %s : %s " , domain, sval_default_jbot_jedge, re.getString("msg"))); } else { int dmId = re.getInteger("dmid"); if(dmId>-1) { synchronized (registeredDomainMap) { registeredDomainMap.get(domain).putInteger("dmid", dmId); //也可能更新module } } module.exMarkLog(String.format("知识领域注册成功:%s (%d)", domain, dmId)); } } private void registerJBotDmDomain(String domain, String moduleName, String cbUri) { QIData req = new QData().putString("cbUri", cbUri).putString("src", moduleName) .putString("key", domain); synchronized (registeredDmDomainMap){ if(registeredDmDomainMap.containsKey(domain)) { req.copyFrom(registeredDmDomainMap.get(domain), "disc","picker","dmid"); } } QIData re = postServiceRequest(sval_default_jbot_jedge, "/gpt/registerDmDomain", req); if(!JMgbusUtil.isMgbusResultOk(re)) { module.errLog(String.format("模型领域注册失败 (%s) to %s : %s " , domain, sval_default_jbot_jedge, re.getString("msg"))); } else { int dmId = re.getInteger("dmid"); if(dmId>-1) { synchronized (registeredDmDomainMap) { registeredDmDomainMap.get(domain).putInteger("dmid", dmId); //也可能更新module } } module.highLog(String.format("模型领域注册成功:%s (%d)", domain, dmId)); } } private void registerJBotObjects(JbotObject a, String initSet, String moduleName, String cbUri) { String words = a.words(); String domain = a.domain(); boolean isNullable = a.nullable(); // 调用初始化函数得到 JSONArray initData = null; synchronized (DataGetterMap) { Method m = DataGetterMap.get(initSet); if (m != null) { if(ObjModDataMap.containsKey(domain)) { QIData objData = ObjModDataMap.get(domain); if(objData!=null) { initData = objData.getJsonArray(words); } } if(initData==null) { try { Object re = m.invoke(this); if (re instanceof List) { initData = JedgeLlmUtil.JsonArrayFromStringList((List) re); } } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } } } QIData req = new QData().putString("domain", domain).putString("cbUri", cbUri) .putString("src", moduleName).putString("key", words) .putBoolean("na", isNullable); if(initData!=null) req.put("payload", initData); synchronized (registeredDmDomainMap){ if(registeredDmDomainMap.containsKey(domain)) { req.copyFrom( registeredDmDomainMap.get(domain),"dmid"); } else { module.errLog(String.format("Fail to register DataSet!! (%s) to %s : domain %s 尚未注册 " , words, sval_default_jbot_jedge, domain)); return; } } synchronized (registeredObjectsMap) { if(registeredObjectsMap.containsKey(words)) { req.put("doid", registeredObjectsMap.get(words)); } } QIData re = postServiceRequest(sval_default_jbot_jedge, "/gpt/registerDmObject", req); if(!JMgbusUtil.isMgbusResultOk(re)) { module.errLog(String.format("模型对象集注册失败!! (%s) to %s : %s " , words, sval_default_jbot_jedge, re.getString("msg"))); } else { JSONArray dsId = re.getJsonArray("doid"); if(dsId!=null && !dsId.isEmpty()) { synchronized (registeredObjectsMap) { registeredObjectsMap.put(words, dsId); //也可能更新module } } module.markLog(String.format("模型对象集注册成功:%s(%s)", words, dsId)); } } private void registerJBotClasses(JbotClass a, String initSet, String moduleName, String cbUri) { String words = a.words(); String domain = a.domain(); boolean isNullable = a.nullable(); // 调用初始化函数得到 JSONArray initData = null; synchronized (DataGetterMap) { Method m = DataGetterMap.get(initSet); if (m != null) { if(ClsModDataMap.containsKey(domain)) { QIData objData = ClsModDataMap.get(domain); if(objData!=null) { initData = objData.getJsonArray(words); } } if(initData==null) { try { Object re = m.invoke(this); if (re instanceof List) { initData = JedgeLlmUtil.JsonArrayFromStringList((List) re); } } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } } } if(initData!=null && !initData.isEmpty()) { QIData req = new QData().putString("domain", domain).putString("cbUri", cbUri) .putString("src", moduleName).putString("key", words) .putBoolean("na", isNullable); req.put("payload", initData); synchronized (registeredDomainMap) { if (registeredDomainMap.containsKey(domain)) { req.copyFrom(registeredDomainMap.get(domain), "dmid"); } else { module.errLog(String.format("Fail to register DataSet (%s) to %s : domain %s 尚未注册 ", words, sval_default_jbot_jedge, domain)); return; } } synchronized (registeredDomainMap) { if (registeredDomainMap.containsKey(words)) { req.putInteger("dsid", registeredClassesMap.get(words)); } } QIData re = postServiceRequest(sval_default_jbot_jedge, "/gpt/registerKnClass", req); if (!JMgbusUtil.isMgbusResultOk(re)) { module.errLog(String.format("世界类说明注册失败!! (%s) to %s : %s ", words, sval_default_jbot_jedge, re.getString("msg"))); } else { int dsId = re.getInteger("dsid"); if (dsId > -1) { synchronized (registeredClassesMap) { registeredClassesMap.put(words, dsId); //也可能更新module } } module.markLog(String.format("世界对象模型说明注册成功:%s(%d)", words, dsId)); } } } //刷新数据集(从Jbot向本地重新请求数据) @MgbusApi public QIData refreshDataSet(QIData eMsg) { String dsKey = eMsg.getKey(); module.warnLog("Fresh Data set by : %s", dsKey); //从数据集名称到dsKey名称 if(StringUtils.isValidStr(dsKey)) { JSONArray initData = null; synchronized (DataGetterMap) { Method m = DataGetterMap.get(dsKey); if (m != null) { try { Object re = m.invoke(this); if(re instanceof List) { initData =JedgeLlmUtil.JsonArrayFromStringList((List)re); } } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } } return JMgbusUtil.MgbusResult(200, "").put("payload", initData); } // return JMgbusUtil.MgbusResult(401, "No Key"); } private void registerJBotDataGetter(JDataGetter a, String DGetterKey, Method m) { synchronized (DataGetterMap) { DataGetterMap.put(DGetterKey, m); } JbotObject oa = m.getAnnotation(JbotObject.class); if(oa!=null) { try { Object re = m.invoke(this); if(re instanceof List) { JSONArray objListData = JedgeLlmUtil.JsonArrayFromStringList((List) re); String domainKey = oa.domain(); String objKey = oa.words(); synchronized (ObjModDataMap) { QIData objData = ObjModDataMap.get(domainKey); if(objData==null) { objData = new QData(); ObjModDataMap.put(domainKey, objData); } objData.put(objKey, objListData); } } } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } } } //扫描所有的无模型模板,并注册到jbot protected List loadClassInfoFromFile(String clsPath) { return new ArrayList<>(); } protected void addTVCtrlDeviceDef(List re, String ctrlName,String objClass, String disc) { String devInfo = new QData() .setKey(ctrlName) .setName(ctrlName) .putString("class", objClass) .putString("disc", disc) .toJSONString(); re.add(devInfo); module.exMarkLog("设备信息=%s", devInfo); } public static List loadDataSetFromString(String dsStr) { List re = new ArrayList<>(); QIData d = QData.fromString(dsStr); if(d instanceof QIDataList) { for(Object o : ((QIDataList) d).asJsonArray()) { if(o instanceof JSONObject) { re.add(((JSONObject) o).toJSONString()); } } } else { re.add(d.toJSONString()); } return re; } //两种情况,一种是json,一种是每行是json public static List loadDataSetFromFile(String fn) { File dsFile = new File(fn); if(dsFile.exists()) { if(fn.endsWith(".ds")) { List lines = StringUtils.readStringLinesFromFile(fn); List re = new ArrayList<>(); for(String l : lines) { l = l.trim(); if(StringUtils.isNotValidStr(l) || l.charAt(0) == '#') continue; QIData d = QData.fromString(l); re.add(d.toJSONString()); } return re; } else if(fn.endsWith(".json")) { String dsStr = StringUtils.readStringFromFile(dsFile); return loadDataSetFromString(dsStr); } } return new ArrayList<>(); } }