package com.smtaiserver.smtaiserver.control; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.tree.DefaultText; import org.springframework.web.servlet.ModelAndView; import com.smtaiserver.smtaiserver.core.SMTAIServerApp; import com.smtaiserver.smtaiserver.core.SMTAIServerRequest; import com.smtaiserver.smtaiserver.core.SMTCheckChatStreamView; import com.smtaiserver.smtaiserver.database.SMTDatabase; import com.smtaiserver.smtaiserver.database.SMTDatabase.DBRecord; import com.smtaiserver.smtaiserver.database.SMTDatabase.DBRecords; import com.smtaiserver.smtaiserver.javaai.SMTJavaAIError; import com.smtaiserver.smtaiserver.javaai.ast.ASTDBMap; import com.smtaiserver.smtaiserver.javaai.duckdb.DuckMergeResult; import com.smtaiserver.smtaiserver.javaai.duckdb.DuckResult; import com.smtaiserver.smtaiserver.javaai.metrics.base.SMTDimensionDef; import com.smtaiserver.smtaiserver.javaai.metrics.base.SMTMetricsDef; import com.smtaiserver.smtaiserver.javaai.qwen.agent.SMTQwenAgent; import com.smtservlet.core.SMTRequest; import com.smtservlet.util.Json; import com.smtservlet.util.SMTJsonWriter; import com.smtservlet.util.SMTStatic; public class SMTMetricsManagerControl { public ModelAndView getDimensionList(SMTAIServerRequest tranReq) throws Exception { SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { DBRecords recs = db.querySQL("SELECT dim_id, dim_title, dim_type, dim_alias, dim_name, dim_unit, dim_group FROM ai_dimension", null); SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginArray("values"); for(DBRecord rec : recs.getRecords()) { jsonWr.beginMap(null); { jsonWr.addKeyValue("id", rec.getString("dim_id")); jsonWr.addKeyValue("title", rec.getString("dim_name")); jsonWr.addKeyValue("prompt", rec.getString("dim_title")); jsonWr.addKeyValue("unit", rec.getString("dim_unit")); jsonWr.addKeyValue("group", rec.getString("dim_group")); jsonWr.beginMap("alias"); String sAlias = rec.getString("dim_alias"); if(!SMTStatic.isNullOrEmpty(sAlias)) { Json jsonAliasMap = Json.read(sAlias); for( Entry entry : jsonAliasMap.asJsonMap().entrySet()) { jsonWr.beginArray(entry.getKey()); for(Json jsonAliasValue : entry.getValue().asJsonList()) { jsonWr.addKeyValue(null, jsonAliasValue.asString()); } jsonWr.endArray(); } } jsonWr.endMap(); switch(rec.getString("dim_type").charAt(0)) { case 'S': jsonWr.addKeyValue("type", "字符串"); break; case 'D': jsonWr.addKeyValue("type", "浮点数"); break; case 'I': jsonWr.addKeyValue("type", "整数"); break; case 'L': jsonWr.addKeyValue("type", "长整数"); break; case 'T': jsonWr.addKeyValue("type", "时间"); break; } } jsonWr.endMap(); } jsonWr.endArray(); return tranReq.returnJson(jsonWr); } finally { db.close(); } } public ModelAndView checkMetricsAgentValidate(SMTAIServerRequest tranReq) throws Exception { String agentId = tranReq.convParamToString("agent_id", true); String question = tranReq.convParamToString("question", true); DBRecords recs; SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { recs = db.querySQL("SELECT * FROM ai_agent_metrics WHERE agent_id=?", new Object[] { agentId }); if(recs.getRowCount() == 0) return tranReq.returnJsonState(false, "未发现记录", null); } finally { db.close(); } DBRecord rec = recs.getRecord(0); SMTQwenAgent agent = (SMTQwenAgent) Class.forName(rec.getString("clz_name")).newInstance(); agent.initInstance(rec); Map mapId2Agent = new HashMap<>(); mapId2Agent.put(agent.getAgentId(), agent); return new ModelAndView(new SMTCheckChatStreamView(tranReq, question, mapId2Agent)); } private void addMetricsNameByRec(DBRecord rec, SMTJsonWriter jsonWr) throws Exception { jsonWr.addKeyValue("id", rec.getString("metrics_id")); jsonWr.addKeyValue("title", rec.getString("metrics_title")); jsonWr.addKeyValue("full_name", rec.getString("full_name")); jsonWr.addKeyValue("metrics_define", rec.getString("metrics_define")); jsonWr.addKeyValue("calcu_method", rec.getString("calcu_method")); jsonWr.addKeyValue("metrics_important", rec.getString("metrics_important")); jsonWr.addKeyValue("metrics_type", rec.getString("metrics_type")); jsonWr.addKeyValue("metrics_group", rec.getString("metrics_group")); jsonWr.addKeyValue("create_user", rec.getString("user_name")); jsonWr.addKeyValue("create_time", rec.getString("create_time")); jsonWr.addKeyValue("metrics_unit", rec.getString("metrics_unit")); //metrics_class SMTMetricsDef metricsDef = (SMTMetricsDef)Class.forName(rec.getString("metrics_class")).newInstance(); jsonWr.addKeyValue("is_time_values", metricsDef.isTimeValues()); jsonWr.addKeyValue("is_chart_values", metricsDef.isChartValues()); String sJsonMacro = rec.getString("metrics_macro"); Json jsonMacro = SMTStatic.isNullOrEmpty(sJsonMacro) ? null : Json.read(sJsonMacro); String sXmlConfig = SMTAIServerApp.getApp().convGlobalMacroString(rec.getString("metrics_config"), jsonMacro); Document doc = SMTStatic.convStrToXmlDoc("" + sXmlConfig + ""); jsonWr.beginArray("dimensions"); for(Node nodeDimName : doc.selectNodes("ROOT/DIM_NAMES/DIM_NAME")) { String dimName = SMTStatic.getXmlAttr((Element)nodeDimName, "id"); String filterType = SMTStatic.getXmlAttr((Element)nodeDimName, "filter_type", null); SMTDimensionDef dimDef = SMTAIServerApp.getApp().getDimensionDef(dimName); jsonWr.beginMap(null); { jsonWr.addKeyValue("id", dimDef.getId()); jsonWr.addKeyValue("title", dimDef.getName()); jsonWr.addKeyValue("type_id", String.format("%c", dimDef.getType())); if(!SMTStatic.isNullOrEmpty(filterType)) jsonWr.addKeyValue("filter_type", filterType); switch(dimDef.getType()) { case 'S': jsonWr.addKeyValue("type", "字符串"); break; case 'D': jsonWr.addKeyValue("type", "浮点数"); break; case 'I': jsonWr.addKeyValue("type", "整数"); break; case 'L': jsonWr.addKeyValue("type", "长整数"); break; case 'T': jsonWr.addKeyValue("type", "时间"); break; } } jsonWr.endMap(); } jsonWr.endArray(); } public ModelAndView getMetricsNameList(SMTRequest tranReq) throws Exception { String agentId = tranReq.convParamToString("agent_id", false); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { DBRecords recs; if(SMTStatic.isNullOrEmpty(agentId)) { recs = db.querySQL( " SELECT A.metrics_id, A.metrics_title, A.metrics_config, A.metrics_match, A.full_name, A.metrics_define, A.calcu_method, A.metrics_macro, A.metrics_unit" + " ,A.is_publish, A.metrics_type, A.metrics_important, A.metrics_group, C.user_name, A.create_time, A.metrics_class" + " FROM ai_metrics_def A" + " INNER JOIN ai_ref_agent_metrics B ON A.metrics_id=B.metrics_id" + " LEFT JOIN sys_user_info C ON A.create_user=C.user_id" , null); } else { recs = db.querySQL( " SELECT A.metrics_id, A.metrics_title, A.metrics_config, A.metrics_match, A.full_name, A.metrics_define, A.calcu_method, A.metrics_macro, A.metrics_unit" + ", A.is_publish, A.metrics_type, A.metrics_important, A.metrics_group, NULL user_name, NULL create_time, A.metrics_class" + " FROM ai_metrics_def A INNER JOIN ai_ref_agent_metrics B ON A.metrics_id=B.metrics_id AND B.agent_id=?" , new Object[] {agentId}); } SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginArray("values"); for(DBRecord rec : recs.getRecords()) { jsonWr.beginMap(null); { addMetricsNameByRec(rec, jsonWr); } jsonWr.endMap(); } jsonWr.endArray(); return tranReq.returnJson(jsonWr); } finally { db.close(); } } public ModelAndView getMetricsAgentList(SMTRequest tranReq) throws Exception { SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { DBRecords recs = db.querySQL("SELECT A.agent_id, A.agent_title, A.agent_xml, A.clz_arguments, A.create_time, A.update_time, A.agent_note, A.agent_order, A.agent_group, B.user_name, A.inner_call FROM ai_agent_metrics A LEFT JOIN sys_user_info B ON A.create_user=B.user_id", null); SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginArray("values"); for(DBRecord rec : recs.getRecords()) { jsonWr.beginMap(null); { jsonWr.addKeyValue("id", rec.getString("agent_id")); jsonWr.addKeyValue("title", rec.getString("agent_title")); jsonWr.addKeyValue("create_user", rec.getString("user_name")); jsonWr.addKeyValue("create_time", rec.getString("create_time")); jsonWr.addKeyValue("note", rec.getString("agent_note")); jsonWr.addKeyValue("agent_group", rec.getString("agent_group")); jsonWr.addKeyValue("inner_call", rec.getString("inner_call")); jsonWr.addKeyValue("published", (rec.getInteger("agent_order") > 0) ? "Y" : "N"); jsonWr.beginMap("supervisor"); { Document doc = SMTStatic.convStrToXmlDoc("" + rec.getString("agent_xml") + ""); String prompt = SMTStatic.trimStrLines(doc.selectSingleNode("ROOT/TITLE").getText()); jsonWr.addKeyValue("prompt", prompt); jsonWr.beginArray("args"); for(Node nodeArg : doc.selectNodes("ROOT/ARGS/ARG")) { Element xmlArg = (Element)nodeArg; jsonWr.beginMap(null); { jsonWr.addKeyValue("name", SMTStatic.getXmlAttr(xmlArg, "name")); jsonWr.addKeyValue("prompt", SMTStatic.trimStrLines(xmlArg.getText())); jsonWr.addKeyValue("check", SMTStatic.getXmlAttr(xmlArg, "check", "")); } jsonWr.endMap(); } jsonWr.endArray(); } jsonWr.endMap(); { Document doc = SMTStatic.convStrToXmlDoc("" + recs.getRecord(0).getString("clz_arguments") + ""); Element xmlPromptSection = (Element)doc.selectSingleNode("ROOT/PROMPT_SECTION"); if(xmlPromptSection != null) { String prompt = loadPromptSection(xmlPromptSection, rec.getString("agent_id")); jsonWr.addKeyValue("metrics_prompt", prompt); } else { Element xmlPrompt = (Element)doc.selectSingleNode("ROOT/PROMPT"); String prompt = xmlPrompt == null ? "" : xmlPrompt.getText() .replace("{{{DIM_NAME_LIST}}}", getDimNameList(rec.getString("agent_id"))) .replace("{{{METRICS_NAME_LIST}}}", getMetricsAliasList(rec.getString("agent_id"))) ; jsonWr.addKeyValue("metrics_prompt", prompt); } } } jsonWr.endMap(); } jsonWr.endArray(); return tranReq.returnJson(jsonWr); } finally { db.close(); } } private String replacePromptSectionDefine(Node nodeFunction, String value) throws Exception { for(Node nodeDefine : nodeFunction.selectNodes("DEFINE")) { String id = SMTStatic.getXmlAttr((Element)nodeDefine, "id"); value = value.replace("{{{" + id + "}}}" , ((Element)nodeDefine).getText()); } if(value.indexOf("{{{") >= 0) throw new Exception("can't replace all macro for : \n" + value); return value; } private String loadPromptSection(Element xmlPromptSection, String agentId) throws Exception { StringBuilder sbPrompt = new StringBuilder(); for (Iterator iterInner = xmlPromptSection.nodeIterator(); iterInner.hasNext();) { Node nodeInner = iterInner.next(); if(nodeInner.getNodeType() == Node.TEXT_NODE) { String text = ((DefaultText)nodeInner).getText(); sbPrompt.append(text); } else if(nodeInner.getNodeType() == Node.ELEMENT_NODE) { Element xmlInner = (Element)nodeInner; String name = xmlInner.getName().toUpperCase(); if("CONFIG".equals(name)) { String key = SMTStatic.getXmlAttr(xmlInner, "key"); String value = (String) SMTAIServerApp.getApp().getGlobalConfig(key); value = replacePromptSectionDefine(xmlInner, value); sbPrompt.append(value); } else if("DIM_NAME_LIST".equals(name)) { sbPrompt.append("以下是可用于函数调用参数的维度列表:\n" + getDimNameList(agentId)); } else if("METRICS_NAME_LIST".equals(name)) { sbPrompt.append("以下是可用于解析的指标列表::\n" + getMetricsAliasList(agentId)); } else if("FUNCTION_LIST".equals(name)) { sbPrompt.append("以下是可以用于解析语法树的函数,请在这些函数中选择需要的操作,禁止捏造不存在的函数\n"); for(Node nodeFunction : xmlInner.selectNodes("FUNCTION")) { String key = SMTStatic.getXmlAttr((Element)nodeFunction, "name"); if(!key.startsWith("prompt_section.")) key = "prompt_section.function." + key; String value = (String) SMTAIServerApp.getApp().getGlobalConfig(key); value = replacePromptSectionDefine(nodeFunction, value); sbPrompt.append(value + "\n"); } } else if("SAMPLE_LIST".equals(name)) { sbPrompt.append("以下是语法树例子:\n"); for(Node nodeSample : xmlInner.selectNodes("SAMPLE")) { String key = SMTStatic.getXmlAttr((Element)nodeSample, "name"); if(!key.startsWith("prompt_section.")) key = "prompt_section.sample." + key; String value = (String) SMTAIServerApp.getApp().getGlobalConfig(key); value = replacePromptSectionDefine(nodeSample, value); sbPrompt.append(value + "\n"); } } else { throw new Exception("unknow PROPMT_SECTION : " + name); } } } return sbPrompt.toString(); } private String getMetricsAliasList(String agentId) throws Exception { Set setAlias = new HashSet<>(); StringBuilder sbResult = new StringBuilder(); Map mapId2Metrics = SMTAIServerApp.getApp().getMetricsMap(agentId); for(SMTMetricsDef metricsDef : mapId2Metrics.values()) { metricsDef.addMetricsAliasToSet(setAlias); } for(String alias : setAlias) { sbResult.append(alias + "\n"); } return sbResult.toString(); } private String getDimNameList(String agentId) throws Exception { Set setExistDim = new HashSet<>(); StringBuilder sbResult = new StringBuilder(); Map mapId2Metrics = SMTAIServerApp.getApp().getMetricsMap(agentId); for(SMTMetricsDef metricsDef : mapId2Metrics.values()) { Map mapId2DimDef = metricsDef.getDimensionMap(); if(mapId2DimDef == null) continue; for(SMTDimensionDef dimDef : mapId2DimDef.values()) { if(setExistDim.contains(dimDef.getId())) continue; setExistDim.add(dimDef.getId()); sbResult.append(" " + dimDef.getId() + ":" + dimDef.getPrompt() + "\n"); } } return sbResult.toString(); } public ModelAndView chatMetricsJson(SMTAIServerRequest tranReq) throws Exception { String metricsId = tranReq.convParamToString("metrics_id", true); String[] groupDimList = tranReq.convParamToStringArray("group_dims", false); Json jsonFilterDims = tranReq.convParamToJson("filter_dims", false); Json jsonFilterValue = tranReq.convParamToJson("filter_value", false); Date timeS = tranReq.convParamToDate("start_time", false); Date timeE = tranReq.convParamToDate("end_time", false); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { // 生成语法树 SMTJsonWriter jsonArgs = new SMTJsonWriter(false); // 插入时间范围 if(timeS != null) jsonArgs.addKeyValue("start_time", timeS); if(timeE != null) jsonArgs.addKeyValue("end_time", timeE); // 插入dim_list if(groupDimList != null && groupDimList.length > 0) { jsonArgs.beginArray("dim_list"); for(String dimId : groupDimList) { jsonArgs.addKeyValue(null, dimId); } jsonArgs.endArray(); } // 插入维度过滤 if(jsonFilterDims != null) { for(Entry entry : jsonFilterDims.asJsonMap().entrySet()) { jsonArgs.addKeyRaw(entry.getKey(), entry.getValue()); } } // 插入值过滤 if(jsonFilterValue != null) { jsonArgs.addKeyRaw("value", jsonFilterValue); } // 从数据库获取指标记录 DBRecords recs = db.querySQL("SELECT * FROM ai_metrics_def WHERE metrics_id=?", new Object[] {metricsId}); if(recs.getRowCount() == 0) return tranReq.returnJsonState(false, "未发现指标:" + metricsId, null); // 创建指标实例 DBRecord rec = recs.getRecord(0); SMTMetricsDef metricsDef = (SMTMetricsDef)Class.forName(rec.getString("metrics_class")).newInstance(); metricsDef.initInstance(rec); // 执行查询 ASTDBMap dbMap = new ASTDBMap(); try { // 查询结果 DuckResult astResult = new DuckResult(); SMTJavaAIError error = metricsDef.queryMetrics("#0/", dbMap, jsonArgs.getRootJson(), null, tranReq, astResult); if(error != null) { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.addKeyValue("json_ok", false); error.appendToResonse(jsonWr); return tranReq.returnJson(jsonWr); } // 输出合并结果 { SMTJsonWriter jsonWr = tranReq.getResultJsonWr(); DuckMergeResult mergeResult = new DuckMergeResult(); jsonWr.beginArray("summary"); mergeResult.outputResultToJson("#0/", astResult, tranReq); jsonWr.endArray(); jsonWr.addKeyValue("json_ok", true); return tranReq.returnJson(jsonWr); } } finally { dbMap.close(); } } finally { db.close(); } } }