package com.smtaiserver.smtaiserver.control; 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; 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; 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 ,dim_value_list 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("value_list"); // 开始一个 "value_list" 的 Map String valueList = rec.getString("dim_value_list"); if (!SMTStatic.isNullOrEmpty(valueList)) { Json jsonValueList = null; try { // 解析dim_value_list数据 jsonValueList = Json.read(valueList); } catch (Exception e) { continue; // 如果解析失败则跳过当前记录 } // 如果是Map,包含sql查询 if (jsonValueList.has("sql")) { SMTJsonWriter jsonWriter02 = new SMTJsonWriter(false); Json sqlJson = jsonValueList.getJson("sql"); // 获取 sql 字段 Json sqlQuery = sqlJson.getJson("sql"); // 获取 SQL 查询语句 Json dsId = sqlJson.getJson("ds_id"); // 获取 SQL 查询语句 if (sqlQuery.isString()) { jsonWriter02.addKeyValue("sql", sqlQuery.asString()); // 将SQL语句添加到JSON中 jsonWriter02.addKeyValue("ds_id", dsId.asString()); // 将SQL语句添加到JSON中 jsonWr.addKeyValue("sql",jsonWriter02); } } else if (jsonValueList.has("values")) { // 如果包含 values 数组 Json valuesJson = jsonValueList.getJson("values"); if (valuesJson.isArray()) { jsonWr.beginArray("values"); // 开始 "dimValueList" 的数组 // 遍历 values 数组 for (Json jsonItem : valuesJson.asJsonList()) { jsonWr.addKeyValue(null, jsonItem.asString()); // 将每个值添加到数组 } jsonWr.endArray(); // 结束 "dimValueList" 数组 } } } jsonWr.endMap(); // 结束 "value_list" 的 Map // 处理 alias 部分 jsonWr.beginMap("alias"); // 开始 "alias" 的 Map String sAlias = rec.getString("dim_alias"); if (!SMTStatic.isNullOrEmpty(sAlias)) { Json jsonAliasMap = null; try { jsonAliasMap = Json.read(sAlias); } catch (Exception e) { continue; // 如果解析失败则跳过当前记录 } // 遍历 alias 映射 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(); // 结束 "alias" 的 Map jsonWr.addKeyValue("type", rec.getString("dim_type")); // 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 addDimension(SMTAIServerRequest tranReq) throws Exception { String loginUserId = tranReq.getLoginUserId(); // 解析请求参数 String dimId = tranReq.convParamToString("dim_id", true); String dimTitle = tranReq.convParamToString("dim_title", true); String dimType = tranReq.convParamToString("dim_type", true); String dimAlias = tranReq.convParamToString("dim_alias", false); String dimName = tranReq.convParamToString("dim_name", true); String dimGroup = tranReq.convParamToString("dim_group", false); String dimUnit = tranReq.convParamToString("dim_unit", false); String dimValueList = tranReq.convParamToString("dim_value_list", false); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { // 检查维度ID是否已存在 String selectSql = "SELECT * FROM ai_doc.ai_dimension WHERE dim_id = ?"; Object[] selectParams = {dimId}; if (db.querySQL(selectSql, selectParams).getRowCount() > 0) { return tranReq.returnJsonState(false, "维度ID已存在", null); } // 构建 SQL 语句 String insertSql = "INSERT INTO ai_doc.ai_dimension (dim_id, dim_title, dim_type, dim_alias, dim_name, dim_group, dim_unit, dim_value_list) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; Object[] insertParams = {dimId, dimTitle, dimType, dimAlias, dimName, dimGroup, dimUnit, dimValueList}; // 执行插入操作 db.executeSQL(insertSql, insertParams); // 返回 JSON 结果 SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); return tranReq.returnJson(jsonWr); } finally { db.close(); } } public ModelAndView updateDimension(SMTAIServerRequest tranReq) throws Exception { // 解析请求参数 String dimId = tranReq.convParamToString("dim_id", true); String dimTitle = tranReq.convParamToString("dim_title", false); String dimType = tranReq.convParamToString("dim_type", false); String dimAlias = tranReq.convParamToString("dim_alias", false); String dimName = tranReq.convParamToString("dim_name", false); String dimGroup = tranReq.convParamToString("dim_group", false); String dimUnit = tranReq.convParamToString("dim_unit", false); String dimValueList = tranReq.convParamToString("dim_value_list", false); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { // 检查维度ID是否存在 String selectSql = "SELECT * FROM ai_doc.ai_dimension WHERE dim_id = ?"; Object[] selectParams = {dimId}; if (db.querySQL(selectSql, selectParams).getRowCount() == 0) { return tranReq.returnJsonState(false, "维度ID不存在", null); } // 构建 SQL 语句 String updateSql = "UPDATE ai_doc.ai_dimension SET dim_title = ?, dim_type = ?, dim_alias = ?, dim_name = ?, dim_group = ?, dim_unit = ?, dim_value_list = ? " + "WHERE dim_id = ?"; Object[] updateParams = {dimTitle, dimType, dimAlias, dimName, dimGroup, dimUnit, dimValueList, dimId}; // 执行更新操作 db.executeSQL(updateSql, updateParams); // 返回 JSON 结果 SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); 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(); } } }