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<String, Json> 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<String, SMTQwenAgent> 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("<ROOT>" + sXmlConfig + "</ROOT>");
|
|
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("<ROOT>" + rec.getString("agent_xml") + "</ROOT>");
|
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("<ROOT>" + recs.getRecord(0).getString("clz_arguments") + "</ROOT>");
|
|
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<Node> 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<String> setAlias = new HashSet<>();
|
StringBuilder sbResult = new StringBuilder();
|
Map<String, SMTMetricsDef> 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<String> setExistDim = new HashSet<>();
|
StringBuilder sbResult = new StringBuilder();
|
Map<String, SMTMetricsDef> mapId2Metrics = SMTAIServerApp.getApp().getMetricsMap(agentId);
|
for(SMTMetricsDef metricsDef : mapId2Metrics.values())
|
{
|
Map<String, SMTDimensionDef> 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<String, Json> 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();
|
}
|
|
}
|
}
|