package com.smtaiserver.smtaiserver.control; import com.smtaiserver.smtaiserver.attach.SMTAIAttachMetricDef; import com.smtaiserver.smtaiserver.attach.SMTAIAttachTableDef; import com.smtaiserver.smtaiserver.attach.SMTAIAttachTableDef.SMTAIAttachTableColumn; import com.smtaiserver.smtaiserver.core.SMTAIServerApp; import com.smtaiserver.smtaiserver.core.SMTAIServerRequest; import com.smtaiserver.smtaiserver.core.SMTAIServerRequest.AIAttachFile; 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.SMTJavaAIChat; import com.smtaiserver.smtaiserver.javaai.SMTJavaAIError; import com.smtaiserver.smtaiserver.javaai.llm.core.SMTLLMConnect; import com.smtaiserver.smtaiserver.javaai.metrics.base.SMTMetricsDef; import com.smtaiserver.smtaiserver.javaai.querydetail.SMTAIQueryDetail; import com.smtaiserver.smtaiserver.javaai.qwen.SMTQwenAgentManager; import com.smtaiserver.smtaiserver.javaai.qwen.agent.SMTQwenAgent; import com.smtaiserver.smtaiserver.javaai.sse.SMTSSEBroadcastChat; import com.smtservlet.util.Json; import com.smtservlet.util.SMTJsonWriter; import com.smtservlet.util.SMTStatic; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.InputStream; import java.util.*; import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.View; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; public class SMTJavaAIControl { private class SMTCallAgentArgStreamView implements View { private SMTAIServerRequest _tranReq; public SMTCallAgentArgStreamView(SMTAIServerRequest tranReq) { _tranReq = tranReq; _tranReq.setChunkedMode(true); } @Override public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { String agentId = _tranReq.convParamToString("agent_id", true); Json jsonArgs = _tranReq.convParamToJson("call_args", true); response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain;charset=UTF-8"); response.setHeader("smtstream", "chunked"); try { SMTQwenAgent agent = SMTAIServerApp.getApp().getQwenAgentManager().getAgentById(agentId); if(agent == null) throw new Exception("can't find agent : " + agentId); SMTLLMConnect llm = SMTAIServerApp.getApp().allocLLMConnect(null); if(!jsonArgs.has("question")) jsonArgs.set("question", ""); agent.callAgents("/", jsonArgs, llm, "", _tranReq); } catch(Exception ex) { _tranReq.traceLLMDebug("call chat stream excetion : \n" + SMTStatic.toString(ex)); _tranReq.sendChunkedBlock("error", ex.getMessage()); } _tranReq.sendChunkedBlock("finish", ""); } } private class SMTAgentStreamView implements View { private SMTAIServerRequest _tranReq; public SMTAgentStreamView(SMTAIServerRequest tranReq) { _tranReq = tranReq; _tranReq.setChunkedMode(true); } @Override public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { String agentId = _tranReq.convParamToString("agent_id", true); String question = _tranReq.convParamToString("question", true); response.setCharacterEncoding("UTF-8"); response.setContentType("text/plain;charset=UTF-8"); response.setHeader("smtstream", "chunked"); try { SMTQwenAgent agent = SMTAIServerApp.getApp().getQwenAgentManager().getAgentById(agentId); SMTLLMConnect llm = SMTAIServerApp.getApp().allocLLMConnect(null); Json jsonArgs = Json.object("question", question); agent.callAgents("/", jsonArgs, llm, question, _tranReq); } catch(Exception ex) { _tranReq.traceLLMDebug("call chat stream excetion : \n" + SMTStatic.toString(ex)); _tranReq.sendChunkedBlock("error", ex.getMessage()); } _tranReq.sendChunkedBlock("finish", ""); } } private class SMTChatStreamView implements View { private SMTAIServerRequest _tranReq; private boolean _mustRawMode = false; public SMTChatStreamView(SMTAIServerRequest tranReq, MultipartFile[] files) throws Exception { // 如果文件存在,则将文件保存 if(files != null && files.length > 0) { try(SMTDatabase db = SMTAIServerApp.getApp().allocDatabase()) { db.beginTran(); try { for(MultipartFile file : files) { String fileText=""; String fileSuffix = (String) SMTAIServerApp.getApp().getGlobalConfig("file_suffix", false); String fileName = new File(file.getOriginalFilename()).getName(); byte[] fileData = readAttachFile(file); if (fileSuffix.contains(fileName.substring(fileName.lastIndexOf(".") + 1))) { fileText = SMTAIServerApp.fileTranslTxt(file); } String fileId = SMTStatic.newUUID(); db.executeSQL( " INSERT INTO chat_history_attach(attach_id, attach_type, attach_title, attach_bytes)" + " VALUES(?,?,?,?)", new Object[] { fileId, "FILE", fileName, fileData }); tranReq.addAttachFile(new AIAttachFile(fileId, fileName, fileText)); } db.commitTran(); } catch(Exception ex) { db.rollbackDB(ex); } } _mustRawMode = true; } Json jsonTables = tranReq.convParamToJson("tables", false); if(jsonTables != null) { tranReq.setAttachTables(jsonTables); _mustRawMode = true; } Json jsonMetrics = tranReq.convParamToJson("metrics", false); if(jsonMetrics != null) { tranReq.setJsonAttachMetrics(jsonMetrics); _mustRawMode = true; } _tranReq = tranReq; _tranReq.setChunkedMode(true); } private byte[] readAttachFile(MultipartFile file) throws Exception { InputStream is = file.getInputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] data = new byte[1024 * 1024]; while(true) { int size = is.read(data); if(size <= 0) return bos.toByteArray(); bos.write(data, 0, size); } } @Override public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception { response.setCharacterEncoding("UTF-8"); //response.setHeader("Transfer-Encoding", "chunked"); response.setContentType("text/plain;charset=UTF-8"); //response.setContentType("application/json;charset=UTF-8"); response.setHeader("smtstream", "chunked"); String userId = _tranReq.getLoginUserId(); { SMTSSEBroadcastChat chat = SMTAIServerApp.getApp().getBroadcastChat(userId); if(chat != null) { SMTJsonWriter jsonWr = new SMTJsonWriter(false); String from = (String) _tranReq.getSessionAttribute("login_from"); if(SMTStatic.isNullOrEmpty(from)) from = "手机"; jsonWr.addKeyValue("type", "chat_start"); jsonWr.addKeyValue("from", from); jsonWr.addKeyValue("sender", _tranReq.getSessionId()); jsonWr.addKeyValue("question", _tranReq.convParamToString("question", true)); jsonWr.addKeyValue("history_group_id", _tranReq.convParamToString("history_group_id", true)); chat.sendChatNotify(_tranReq.getSessionId(), jsonWr.getFullJson()); } } try { Json jsonResult = chatQuestionToJson(_tranReq, true, _mustRawMode); if(!jsonResult.safeGetBoolean("json_ok", false)) _tranReq.sendChunkedBlock("error", jsonResult.safeGetStr("json_msg", "内部错误")); } catch(Exception ex) { _tranReq.traceLLMDebug("call chat stream excetion : \n" + SMTStatic.toString(ex)); _tranReq.sendChunkedBlock("error", ex.getMessage()); } _tranReq.sendChunkedBlock("finish", ""); // 广播通知所有同用户对话 SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { String sql = " SELECT history_id, D.group_id, D.create_time FROM chat_history_detail D INNER JOIN chat_history_group G" + " ON D.group_id=G.group_id AND user_id=? AND D.create_time >= ?::timestamp + '-1 hours'" + " ORDER BY D.create_time"; Date time = new Date(); DBRecords recs = db.querySQL(sql, new Object[] { _tranReq.getLoginUserId(), time }); SMTSSEBroadcastChat chat = SMTAIServerApp.getApp().getBroadcastChat(userId); if(chat != null) { if(recs.getRowCount() > 0) { SMTJsonWriter jsonWr = new SMTJsonWriter(false); String from = (String) _tranReq.getSessionAttribute("login_from"); if(SMTStatic.isNullOrEmpty(from)) from = "手机"; jsonWr.addKeyValue("type", "chat_history_id"); jsonWr.addKeyValue("from", from); jsonWr.addKeyValue("sender", _tranReq.getSessionId()); jsonWr.beginArray("id_list"); for(DBRecord rec : recs.getRecords()) { jsonWr.beginMap(null); { jsonWr.addKeyValue("history_id", rec.getString("history_id")); jsonWr.addKeyValue("group_id", rec.getString("group_id")); jsonWr.addKeyValue("time", rec.getString("create_time")); } jsonWr.endMap(); } jsonWr.endArray(); chat.sendChatNotify(_tranReq.getSessionId(), jsonWr.getFullJson()); } } } finally { db.close(); } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// public ModelAndView systemPing(SMTAIServerRequest tranReq) throws Exception { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.addKeyValue("is_login", tranReq.getLoginUserId() != null); return tranReq.returnJson(jsonWr); } public ModelAndView createOrder(SMTAIServerRequest tranReq) throws Exception { // String title = tranReq.convParamToString("title", true); // String wstypeid = tranReq.convParamToString("wstypeid", false); // String wstypename = tranReq.convParamToString("wstypename", false); // String urgencylevel = tranReq.convParamToString("urgencylevel", false); // String shape = tranReq.convParamToString("shape", false); // String deadline = tranReq.convParamToString("deadline", false); // String stepstatus = tranReq.convParamToString("stepstatus", false); // String originatetypetext = tranReq.convParamToString("originatetypetext", false); // String content = tranReq.convParamToString("content", false); // String address = tranReq.convParamToString("address", false); // String stepid = tranReq.convParamToString("stepid", false); // String org = tranReq.convParamToString("org", false); // String deptname = tranReq.convParamToString("deptname", false); // String dealtime = tranReq.convParamToString("dealtime", false); // String username = tranReq.convParamToString("username", false); // String contactname = tranReq.convParamToString("contactname", false); // String contactphone = tranReq.convParamToString("contactphone", false); // String acceptuserid = tranReq.convParamToString("acceptuserid", false); // String acceptusername = tranReq.convParamToString("acceptusername", false); // String acceptuseraccount = tranReq.convParamToString("acceptuseraccount", false); // String dealuserid = tranReq.convParamToString("dealuserid", false); // String dealusername = tranReq.convParamToString("dealusername", false); // String dealuseraccount = tranReq.convParamToString("dealuseraccount", false); // String flowstatus = tranReq.convParamToString("flowstatus", false); // String attachment = tranReq.convParamToString("attachment", false); // String creator = tranReq.convParamToString("creator", false); // String createtime = tranReq.convParamToString("createtime", false); // String isplan = tranReq.convParamToString("isplan", false); // String originateid = tranReq.convParamToString("originateid", false); // String appointstarttime = tranReq.convParamToString("appointstarttime", false); // String appointendtime = tranReq.convParamToString("appointendtime", false); // String parentid = tranReq.convParamToString("parentid", false); // String relateids = tranReq.convParamToString("relateids", false); // String oname = tranReq.convParamToString("oname", false); // String otype = tranReq.convParamToString("otype", false); // // SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); // try { // db.executeSQL( // "INSERT INTO work_order_list(" // + "order_id, title, wstypeid, wstypename, urgencylevel, shape, deadline, stepstatus, " // + "originatetypetext, content, address, step_id, org, deptname, dealtime, username, contactname, " // + "contactphone, acceptuserid, acceptusername, acceptuseraccount, dealuserid, dealusername, " // + "dealuseraccount, flowstatus, attachment, creator, createtime, isplan, originateid, " // + "appointstarttime, appointendtime, parentid, relateids,is_notify,oname,otype" // + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)", // new Object[] { // SMTStatic.newUUID(), // title, // wstypeid, // wstypename, // urgencylevel, // shape, // deadline, // stepstatus, // originatetypetext, // content, // address, // stepid, // org, // deptname, // dealtime, // username, // contactname, // contactphone, // acceptuserid, // acceptusername, // acceptuseraccount, // dealuserid, // dealusername, // dealuseraccount, // flowstatus, // attachment, // creator, // new Date(), // isplan, // originateid, // appointstarttime, // appointendtime, // parentid, // relateids, // "N", // oname, // otype // }); // } catch (Exception e) { // throw new Exception("数据库错误", e); // } // // return tranReq.returnJsonState(true, null, null); return tranReq.returnJsonState(true, null, null); } public ModelAndView updateOrderStatus(SMTAIServerRequest tranReq) throws Exception { String id = tranReq.convParamToString("id", true); Integer stepstatus = tranReq.convParamToInteger("stepstatus", true); // 状态代号,如已完成 SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { DBRecords dbRecords = db.querySQL("select * from work_order_list where order_id = ?", new Object[]{id}); Integer statusBeforeModification = dbRecords.getRecords().get(0).getInteger("stepstatus"); db.executeSQL( "UPDATE work_order_list SET stepstatus = ? , status_update_time = ? , is_notify = 'N' WHERE order_id = ?", new Object[] {stepstatus, new Date(),id}); String sql = "INSERT INTO ai_sys.work_order_detail (order_id, status_before_modification, status_after_modification,createTime) VALUES (?, ?, ?, ?)"; db.executeSQL(sql, new Object[] {id, statusBeforeModification, stepstatus, new Date()}); } catch (Exception e) { throw new Exception("更新工单状态失败", e); } return tranReq.returnJsonState(true, null, null); } public ModelAndView updateOrder(SMTAIServerRequest tranReq) throws Exception { String title = tranReq.convParamToString("title", true); String orderId = tranReq.convParamToString("orderId", true); String wstypeid = tranReq.convParamToString("wstypeid", false); String wstypename = tranReq.convParamToString("wstypename", false); String urgencylevel = tranReq.convParamToString("urgencylevel", false); String shape = tranReq.convParamToString("shape", false); String deadline = tranReq.convParamToString("deadline", false); String stepstatus = tranReq.convParamToString("stepstatus", false); String originatetypetext = tranReq.convParamToString("originatetypetext", false); String content = tranReq.convParamToString("content", false); String address = tranReq.convParamToString("address", false); String stepid = tranReq.convParamToString("stepid", false); String org = tranReq.convParamToString("org", false); String deptname = tranReq.convParamToString("deptname", false); String dealtime = tranReq.convParamToString("dealtime", false); String username = tranReq.convParamToString("username", false); String contactname = tranReq.convParamToString("contactname", false); String contactphone = tranReq.convParamToString("contactphone", false); String acceptuserid = tranReq.convParamToString("acceptuserid", false); String acceptusername = tranReq.convParamToString("acceptusername", false); String acceptuseraccount = tranReq.convParamToString("acceptuseraccount", false); String dealuserid = tranReq.convParamToString("dealuserid", false); String dealusername = tranReq.convParamToString("dealusername", false); String dealuseraccount = tranReq.convParamToString("dealuseraccount", false); String flowstatus = tranReq.convParamToString("flowstatus", false); String attachment = tranReq.convParamToString("attachment", false); String creator = tranReq.convParamToString("creator", false); String isplan = tranReq.convParamToString("isplan", false); String originateid = tranReq.convParamToString("originateid", false); String appointstarttime = tranReq.convParamToString("appointstarttime", false); String appointendtime = tranReq.convParamToString("appointendtime", false); String parentid = tranReq.convParamToString("parentid", false); String relateids = tranReq.convParamToString("relateids", false); String oname = tranReq.convParamToString("oname", false); String otype = tranReq.convParamToString("otype", false); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { db.executeSQL( "UPDATE work_order_list SET " + "title = ?, " + "wstypeid = ?, " + "wstypename = ?, " + "urgencylevel = ?, " + "shape = ?, " + "deadline = ?, " + "stepstatus = ?, " + "originatetypetext = ?, " + "content = ?, " + "address = ?, " + "step_id = ?, " + "org = ?, " + "deptname = ?, " + "dealtime = ?, " + "username = ?, " + "contactname = ?, " + "contactphone = ?, " + "acceptuserid = ?, " + "acceptusername = ?, " + "acceptuseraccount = ?, " + "dealuserid = ?, " + "dealusername = ?, " + "dealuseraccount = ?, " + "flowstatus = ?, " + "attachment = ?, " + "creator = ?, " + "createtime = ?, " + "isplan = ?, " + "originateid = ?, " + "appointstarttime = ?, " + "appointendtime = ?, " + "parentid = ?, " + "relateids = ?, " + "is_notify = ?, " + "oname = ?, " + "otype = ? " + "WHERE order_id = ?", new Object[]{ title, wstypeid, wstypename, urgencylevel, shape, deadline, stepstatus, originatetypetext, content, address, stepid, org, deptname, dealtime, username, contactname, contactphone, acceptuserid, acceptusername, acceptuseraccount, dealuserid, dealusername, dealuseraccount, flowstatus, attachment, creator, new Date(), isplan, originateid, appointstarttime, appointendtime, parentid, relateids, "N", oname, otype, orderId }); } finally { db.close(); } return tranReq.returnJsonState(true, null, null); } public ModelAndView getOrderList(SMTAIServerRequest tranReq) throws Exception { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { DBRecords recs = db.querySQL("SELECT * FROM work_order_list", null); if (recs.getRowCount() != 0) { jsonWr.beginArray("values"); // 开始一个数组,key为 "values" for (DBRecord rec : recs.getRecords()) { jsonWr.beginMap(null); // 每条记录是一个对象 for (String colName : rec.getColNames()) { jsonWr.addKeyValue(colName, rec.getString(colName)); // 添加每个字段 } jsonWr.endMap(); // 结束一个对象 } jsonWr.endArray(); // 结束数组 return tranReq.returnJson(jsonWr); // return tranReq.returnJsonState(true, "成功", jsonWr.getRootJson()); } else { return tranReq.returnJsonState(false, "未找到工单", null); } } catch (Exception e) { throw new Exception("查询工单失败", e); } } public ModelAndView disconnectBroadcastChat(SMTAIServerRequest tranReq) throws Exception { String userId = tranReq.getLoginUserId(); String sessionId = tranReq.getSessionId(); SMTSSEBroadcastChat chat = SMTAIServerApp.getApp().allocBroadcastChat(userId); if(chat != null) { chat.removeSSEConnect(sessionId); } return tranReq.returnJsonState(true, null, null); } public SseEmitter connectBroadcastChat(SMTAIServerRequest tranReq) throws Exception { SseEmitter emitter = new SseEmitter(Long.MAX_VALUE); String from = (String)tranReq.getSessionAttribute("login_from"); if(SMTStatic.isNullOrEmpty(from)) from = "未知"; String userId = tranReq.getLoginUserId(); SMTSSEBroadcastChat chat = SMTAIServerApp.getApp().allocBroadcastChat(userId); chat.addSSEConnect(tranReq.getSessionId(), from, emitter); return emitter; } public ModelAndView getMetricsNames(SMTAIServerRequest tranReq) throws Exception { Set mapResult = new HashSet<>(); Map> mapAgent2Id2MetricDef = SMTAIServerApp.getApp().getMetricsMapGroupMap(); for(Map mapId2MetricDef : mapAgent2Id2MetricDef.values()) { for(SMTMetricsDef metricDef : mapId2MetricDef.values()) { for(String alias : metricDef.getMetricsAliasSet()) { mapResult.add(alias); } mapResult.add(metricDef.getTitle()); } } SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginArray("values"); for(String title : mapResult) { jsonWr.addKeyValue(null, title); } jsonWr.endArray(); return tranReq.returnJson(jsonWr); } public ModelAndView restartSupervisorPrompt(SMTAIServerRequest tranReq) throws Exception { SMTAIServerApp.getApp().clearQwenAgentManager(); return tranReq.returnJsonState(true, null, null); } public ModelAndView getSupervisorPrompt(SMTAIServerRequest tranReq) throws Exception { SMTQwenAgentManager agentManager = SMTAIServerApp.getApp().getQwenAgentManager(); String[] agentPrompt = agentManager.getSupervisorPrompt(null, null, null, null, true).replace("\r\n", "\n").split("\n"); SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginArray("values"); for(String line : agentPrompt) { jsonWr.addKeyValue(null, line); } jsonWr.endArray(); return tranReq.returnJson(jsonWr); } public ModelAndView chatQuestion(SMTAIServerRequest tranReq) throws Exception { Json jsonOutput = chatQuestionToJson(tranReq, false, false); return tranReq.returnJson(jsonOutput); } protected Json chatQuestionToJson(SMTAIServerRequest tranReq, boolean isStreamMode, boolean mustRawMode) throws Exception { try { tranReq.clearChatStreamReplyValue(); String sampleId = tranReq.convParamToString("sample_id", false); String llmId = tranReq.convParamToString("llm_id", false); String historyGroupId = tranReq.convParamToString("history_group_id", true); String question = tranReq.convParamToString("question", true); String processId = tranReq.convParamToString("process_id", false); String sRawMode = tranReq.convParamToString("raw_mode", false); String prevQuestion = tranReq.convParamToString("prev_question", false); String groupType = tranReq.convParamToString("group_type", false); double[] curPos = tranReq.convParamToDoubleArray("cur_pos", false); if(SMTStatic.isNullOrEmpty(groupType)) groupType = "业务场景"; tranReq.setCurQuestionPos(curPos); tranReq.setCurGroupType(groupType); question = SMTAIServerApp.getApp().getQueryAIQuestionReplace().replaceQuestion(groupType, question); boolean rawMode = false; if(sRawMode != null) { if("AI".equals(sRawMode)) { rawMode = false; } else { rawMode = "true".equals(sRawMode); if(mustRawMode) rawMode = true; } } tranReq.setAsynProcessId(processId); Json jsonResult = null; Exception exResult = null; long ticket = System.currentTimeMillis(); tranReq.setAsynProcessText("开始分析"); tranReq.setAIQuestion(question); jsonResult = SMTJavaAIChat.questionChat("aliyun", tranReq.getAgentGroupSet(), groupType, question, prevQuestion, rawMode, tranReq); Json jsonOutput = afterCallChat(isStreamMode, ticket, groupType, historyGroupId, jsonResult, sampleId, llmId, tranReq, exResult); return jsonOutput; } finally { tranReq.closeQuestionResource(); } } private SMTJavaAIError parseRecordsetTypeConclusionWithLLM(String agentKey, SMTLLMConnect llm, Json jsonSummary, SMTAIServerRequest tranReq, SMTJsonWriter jsonWrConclusion) throws Exception { tranReq.sendChunkedBlock("begin", "分析[" + jsonSummary.safeGetStr("title", "") + "]的数据"); boolean set = tranReq.setSendStarStream(true); try { StringBuilder sbQuestion = new StringBuilder(); sbQuestion.append("以下是[" + jsonSummary.safeGetStr("title", "") + "]的数据,请对其进行分析,并提炼出最精简的结果。\n"); boolean isFirst = true; int maxCol = 0; for(Json jsonCol : jsonSummary.getJson("cols").asJsonList()) { if(isFirst) isFirst = false; else sbQuestion.append(","); sbQuestion.append(jsonCol.safeGetStr("title", "值")); maxCol ++; } sbQuestion.append("\n"); for(Json jsonRow : jsonSummary.getJson("values").asJsonList()) { List listJsonRow = jsonRow.asJsonList(); for(int i = 0; i < maxCol; i ++) { if(i > 0) sbQuestion.append(","); Json jsonValue = listJsonRow.get(i); if(jsonValue.isNull()) { sbQuestion.append(""); } else { sbQuestion.append(listJsonRow.get(i).asString()); } } sbQuestion.append("\n"); if(sbQuestion.length() > 4096) break; } String answer = llm.callWithMessage(null, sbQuestion.toString(), tranReq).replace("\r", ""); jsonWrConclusion.beginMap(null); { jsonWrConclusion.addKeyValue("agent_key", agentKey); jsonWrConclusion.addKeyValue("report", answer); } jsonWrConclusion.endMap(); } finally { tranReq.setSendStarStream(set); } return null; } private Json afterCallChat(boolean isStreamMode, long ticket, String groupType, String historyGroupId, Json jsonResult, String sampleId, String llmId, SMTAIServerRequest tranReq, Exception exResult) throws Exception { int runMS = 0; if(llmId == null) llmId = (String)SMTAIServerApp.getApp().getDefaultLLMId(); try { runMS = (int)(System.currentTimeMillis() - ticket); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { DBRecords recs = db.querySQL("SELECT group_id FROM chat_history_group WHERE user_id=? AND group_id=?", new Object[] { tranReq.getLoginUserId(), historyGroupId }); if(recs.getRowCount() == 0) return Json.object("json_ok", false, "json_msg", "对话分组id[" + historyGroupId + "]不存在或不属于[" + tranReq.getLoginUserId() + "]分组"); tranReq.setAsynProcessText("记录历史"); String historyId = tranReq.getChatHistoryId(); Json jsonSqlParams = null; if(jsonResult != null) { jsonResult.set("question", tranReq.getAIQuestion()); jsonResult.set("history_id", historyId); tranReq.addAttachMessageToJson(jsonResult); jsonSqlParams = tranReq.getParamJson(); Json jsonExtCallList = tranReq.getExtCallJsonWriter(); if(jsonExtCallList != null) { Set setExtCallKey = new HashSet<>(); SMTJsonWriter jsonWrExtCall = new SMTJsonWriter(true); for(Json jsonExtCall : jsonExtCallList.asJsonList()) { String key = jsonExtCall.getJson("ext_call_key").asString(); if(setExtCallKey.contains(key)) continue; setExtCallKey.add(key); jsonExtCall.delAt("ext_call_key"); jsonWrExtCall.addKeyRaw(null, jsonExtCall); } jsonResult.set("ext_call_list", jsonWrExtCall.getRootJson()); } } // 输出结果 { SMTJsonWriter jsonWrResult = tranReq.finishResultJsonWr(); if(jsonWrResult != null) { tranReq.sendChunkedBlock("result", jsonWrResult.getRootJson()); } } // 输出总结 tranReq.sendChunkedBlock("summary", jsonResult); // 将result列表加入jsonResult List listReport = tranReq.getResultJsonWrList(); Json jsonFirstReport = null; jsonResult.set("answer_type", "report_list"); if(listReport != null) { Json jsonReports = Json.array(); for(SMTJsonWriter jsonWrResult : tranReq.getResultJsonWrList()) { if(jsonFirstReport == null) jsonFirstReport = jsonWrResult.getRootJson(); jsonReports.asJsonList().add(jsonWrResult.getRootJson()); } jsonResult.set("reports", jsonReports); } else { jsonResult.set("reports", Json.array()); } SMTJsonWriter jsonAsyncQuery = tranReq.getAsyncQueryJson(); boolean state = (jsonResult == null) ? false : jsonResult.safeGetBoolean("json_ok", false); db.executeSQL( "INSERT INTO chat_history_detail(history_id,group_id,question,sample_id,create_time,llm_id,ask_json,run_ms,trace_llm,chat_state,param_json,async_query_json,group_type)" + "VALUES(?,?,?,?,?,?,?::jsonb,?,?,?,?, ?,?)", new Object[] { historyId, historyGroupId, tranReq.getAIQuestion(), sampleId, new Date(), llmId, jsonResult == null ? null : jsonResult.toString(), runMS, tranReq.getTraceLLMDebug(), state ? "OK" : "NG", jsonSqlParams == null ? null : jsonSqlParams.toString(), jsonAsyncQuery == null ? null : jsonAsyncQuery.getFullJson(), groupType }); // 如果是流模式,则首先输出结果,然后再更新评估报告 if(state && jsonFirstReport != null && !tranReq.isDisableConclusion() && "true".equals(SMTAIServerApp.getApp().getGlobalConfig("llm.recorset.conclusion", "false")) && "summary".equals(jsonFirstReport.safeGetStr("answer_type", "")) ) { tranReq.traceLLMDebug("开始评估:================="); Set setExistAgentKey = new HashSet<>(); SMTJsonWriter jsonWrConclusion = new SMTJsonWriter(true); for(Json jsonSummary : jsonFirstReport.getJson("summary").asJsonList()) { String agentKey = jsonSummary.safeGetStr("agent_key", ""); if(setExistAgentKey.contains(agentKey)) continue; if(!"recordset".equals(jsonSummary.safeGetStr("type", ""))) continue; setExistAgentKey.add(agentKey); SMTLLMConnect llm = SMTAIServerApp.getApp().allocLLMConnect(null); try { parseRecordsetTypeConclusionWithLLM(agentKey, llm, jsonSummary, tranReq, jsonWrConclusion); } finally { llm.close(); } } if(isStreamMode) { tranReq.sendChunkedBlock("conclusion", jsonWrConclusion.getRootJson()); } jsonFirstReport.set("conclusion", jsonWrConclusion.getRootJson()); db.executeSQL("UPDATE chat_history_detail SET ask_json=?::jsonb WHERE history_id=?", new Object[] {jsonFirstReport.toString(), historyId}); tranReq.traceLLMDebug("评估完成:================="); } } finally { db.close(); } if(exResult != null) throw exResult; return jsonResult; } finally { tranReq.removeAsynProcessId(); } } public ModelAndView getAIHtmlPage(SMTAIServerRequest tranReq) throws Exception { String id = tranReq.convParamToString("id", true); String htmlPath = (String) SMTAIServerApp.getApp().getGlobalConfig("ai_html_path"); File file = new File(htmlPath, id + ".html"); if(!file.exists()) return tranReq.returnHtml("Page can't be found : " + id + ""); return tranReq.returnHtml(SMTStatic.readAllText(file)); } public ModelAndView chatExtCallQuery(SMTAIServerRequest tranReq) throws Exception { String historyGroupId = tranReq.convParamToString("history_group_id", true); String question = tranReq.convParamToString("question", true); String callExtId = tranReq.convParamToString("call_ext_id", true); Json callExtJson = tranReq.convParamToJson("call_ext_args", true); Exception exResult = null; Json jsonResult = null; long ticket = System.currentTimeMillis(); try { tranReq.setAsynProcessText("开始分析"); tranReq.setAIQuestion(question); jsonResult = SMTJavaAIChat.callExtChat(null, question, callExtId, callExtJson, tranReq); } catch(Exception ex) { tranReq.traceLLMDebug("exception:\n" + SMTStatic.toString(ex)); exResult = ex; } Json jsonOutput = afterCallChat(false, ticket, null, historyGroupId, jsonResult, null, null, tranReq, exResult); return tranReq.returnJson(jsonOutput); } public ModelAndView chatAsyncQuery(SMTAIServerRequest tranReq) throws Exception { String historyId = tranReq.convParamToString("history_id", true); String recId = tranReq.convParamToString("rec_id", true); //Integer page = tranReq.convParamToInteger("page", false); //Integer count = tranReq.convParamToInteger("perPage", false); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { String sJsonValues; if("__AGENT_CHECK_MODE__".equals(historyId)) { sJsonValues = (String) tranReq.getSessionAttribute("QWEN_ASYNC_JSON"); if(SMTStatic.isNullOrEmpty(sJsonValues)) return tranReq.returnJsonState(false, "无结果保存", null); } else { DBRecords recs = db.querySQL("SELECT async_query_json FROM chat_history_detail WHERE history_id=? AND async_query_json is not null", new Object[] {historyId}); if(recs.getRowCount() == 0) return tranReq.returnJsonState(false, "history id error", null); sJsonValues = recs.getRecord(0).getString(0); } Json jsonValues = Json.read(sJsonValues); Json jsonValue = jsonValues.safeGetJson(recId); if(jsonValue == null) return tranReq.returnJsonState(false, "rec id error", null); List colNames = new ArrayList<>(); for(Json jsonColumn : jsonValue.getJson("columns").asJsonList()) { colNames.add(jsonColumn.asString().toLowerCase()); } SMTJsonWriter jsonWr = new SMTJsonWriter(true); for(Json jsonRows : jsonValue.getJson("values").asJsonList()) { jsonWr.beginMap(null); for(int i = 0; i < colNames.size(); i ++) { Object value = jsonRows.at(i).getValue(); jsonWr.addKeyValue(colNames.get(i), value); } jsonWr.endMap(); } return tranReq.returnJson(jsonWr); } finally { db.close(); } } private void updateCallFuncArg_Set(Json jsonCallFuncBase, Json jsonFilter) { String value = jsonFilter.safeGetStr("value", null); if(SMTStatic.isNullOrEmpty(value)) return; for(Json jsonPath : jsonFilter.getJson("path").asJsonList()) { Json jsonCallFunc = jsonCallFuncBase; String[] pathList = jsonPath.asString().split("/"); for(int i = 0; i < pathList.length - 1; i ++) { String path = pathList[i]; if(SMTStatic.isNullOrEmpty(path)) continue; if(path.charAt(0) == '#') { jsonCallFunc = jsonCallFunc.asJsonList().get(SMTStatic.toInt(path.substring(1))); } else { jsonCallFunc = jsonCallFunc.getJson(path); } } jsonCallFunc.set(pathList[pathList.length - 1], value); jsonCallFunc.set(pathList[pathList.length - 1] + "__eq", true); } } public ModelAndView chatSupervisorJson(SMTAIServerRequest tranReq) throws Exception { String historyId = tranReq.convParamToString("history_id", true); String agentKey = tranReq.convParamToString("agent_key", true); Json jsonFilters = tranReq.convParamToJson("filter_json", true); String[] orderDimName = tranReq.convParamToStringArray("order_dim_name", false); Integer resultGroupIndex = tranReq.convParamToInteger("result_group_index", false); if(orderDimName != null) tranReq.setChatOrderDimName(orderDimName[0], orderDimName[1]); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); DBRecords recs = db.querySQL("SELECT ask_json FROM chat_history_detail WHERE history_id=? AND ask_json IS NOT NULL", new Object[] { historyId }); if(recs.getRowCount() == 0) return tranReq.returnJsonState(false, "未发现当前对话", null); Json jsonAsk = Json.read(recs.getRecord(0).getString("ask_json")); String answerType = jsonAsk.getJson("answer_type").asString(); // 执行对话 Json jsonCallFuncMap = null; if("report_list".equals(answerType)) { Json jsonCallFuncMapList = jsonAsk.safeGetJson("reports"); if(jsonCallFuncMapList != null) { jsonCallFuncMap = jsonCallFuncMapList.asJsonList().get(resultGroupIndex).safeGetJson("call_func"); } } else { jsonCallFuncMap = jsonAsk.safeGetJson("call_func"); } Json jsonCallFunc = null; if(jsonCallFuncMap != null) jsonCallFunc = jsonCallFuncMap.safeGetJson(agentKey); // 修改参数 for(Json jsonFilter : jsonFilters.asJsonList()) { String updateMode = jsonFilter.safeGetStr("update", "set"); if("set".equals(updateMode)) { updateCallFuncArg_Set(jsonCallFunc, jsonFilter); } else { throw new Exception("unknow update mode"); } } String agentId =""; if(jsonCallFunc.isArray()) { List listCallFunc = jsonCallFunc.asJsonList(); if(listCallFunc.size() > 0) agentId = listCallFunc.get(0).safeGetStr("agent_id", agentId); } SMTJavaAIError error = SMTAIServerApp.getApp().getQwenAgentManager().callSupervisorJson(agentId, agentKey, jsonCallFunc , jsonWr, tranReq); if(error != null) { jsonWr.addKeyValue("json_ok", false); error.appendToResonse(jsonWr); } else { SMTJsonWriter jsonWrResult = tranReq.getResultJsonWr(); if(jsonWrResult != null) { jsonWr.addRawJson(jsonWrResult.getRootJson()); } } return tranReq.returnJson(jsonWr); } finally { db.close(); } } public ModelAndView deleteUserSample(SMTAIServerRequest tranReq) throws Exception { String sampleId = tranReq.convParamToString("sample_id", true); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { db.executeSQL("DELETE FROM ai_user_sample WHERE sample_user=? AND sample_id=?", new Object[] { tranReq.getLoginUserId(), sampleId }); return tranReq.returnJsonState(true, null, null); } finally { db.close(); } } public ModelAndView updateUserSample(SMTAIServerRequest tranReq) throws Exception { String sampleId = tranReq.convParamToString("sample_id", true); String question = tranReq.convParamToString("question", true); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { db.executeSQL("UPDATE ai_user_sample SET sample_question=? WHERE sample_user=? AND sample_id=?", new Object[] { question, tranReq.getLoginUserId(), sampleId }); return tranReq.returnJsonState(true, null, null); } finally { db.close(); } } public ModelAndView listUserSample(SMTAIServerRequest tranReq) throws Exception { String groupType = tranReq.convParamToString("group_type", false); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); List sqlParams = new ArrayList<>(); String sql = "SELECT sample_id, sample_question, group_type, create_time FROM ai_user_sample WHERE sample_user=?"; sqlParams.add(tranReq.getLoginUserId()); if(!SMTStatic.isNullOrEmpty(groupType)) { sql += " AND group_type=?"; sqlParams.add(groupType); } sql += " ORDER BY create_time DESC"; DBRecords recs = db.querySQL(sql, sqlParams.toArray(new Object[sqlParams.size()])); jsonWr.beginArray("values"); for(DBRecord rec : recs.getRecords()) { jsonWr.beginMap(null); { jsonWr.addKeyValue("id", rec.getString("sample_id")); jsonWr.addKeyValue("question", rec.getString("sample_question")); jsonWr.addKeyValue("group_type", rec.getString("group_type")); jsonWr.addKeyValue("create_time", rec.getString("create_time")); } jsonWr.endMap(); } jsonWr.endArray(); return tranReq.returnJson(jsonWr); } finally { db.close(); } } public ModelAndView addUserSample(SMTAIServerRequest tranReq) throws Exception { String question = tranReq.convParamToString("question", true); String groupType = tranReq.convParamToString("group_type", false); if(SMTStatic.isNullOrEmpty(groupType)) groupType = "业务场景"; SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); String sampleId = SMTStatic.newUUID(); db.executeSQL("INSERT INTO ai_user_sample(sample_id, sample_question, sample_user, create_time, group_type)VALUES(?,?,?,?,?)" , new Object[] {sampleId, question, tranReq.getLoginUserId(), new Date(), groupType}); jsonWr.addKeyValue("sample_id", sampleId); return tranReq.returnJson(jsonWr); } finally { db.close(); } } public ModelAndView chatQuestionStream(SMTAIServerRequest tranReq, @RequestParam(value="files", required=false) MultipartFile[] files) throws Exception { return new ModelAndView(new SMTChatStreamView(tranReq, files)); } public ModelAndView chatAgentStream(SMTAIServerRequest tranReq) throws Exception { return new ModelAndView(new SMTAgentStreamView(tranReq)); } public ModelAndView shareChatHistory(SMTAIServerRequest tranReq) throws Exception { String[] historyIdList = tranReq.convParamToStringArray("history_ids", true); int shareDays = tranReq.convParamToInteger("share_days", true); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); db.executeSQL("BEGIN", null); try { jsonWr.beginMap("values"); for(String historyId : historyIdList) { DBRecords recsHistory = db.querySQL( "SELECT A.ask_json FROM (SELECT ask_json::text, group_id FROM chat_history_detail WHERE history_id=?) A INNER JOIN chat_history_group B ON A.group_id=B.group_id AND B.user_id=?", new Object[] {historyId, tranReq.getLoginUserId()}); if(recsHistory.getRowCount() == 0) return tranReq.returnJsonState(false, "未发现指定的历史记录", null); String shareId = SMTStatic.newUUID(); String asjJson = recsHistory.getRecord(0).getString("ask_json") .replace("/chat/chat_async_query?", "/chat/share_async_query?") .replace("history_id=" + historyId, "share_id=" + shareId) ; Date curTime = new Date(); Date expireTime = SMTStatic.calculateTime(curTime, SMTStatic.SMTCalcTime.ZERO_TIME, 0, SMTStatic.SMTCalcTime.ADD_DATE, shareDays + 1); db.executeSQL( " INSERT INTO chat_share_detail" + " (share_id,question,sample_id,create_time,llm_id,ask_json,answer_state,trace_llm,chat_state,param_json,async_query_json,group_type,share_time,share_user,expire_time)" + " SELECT ?, question,sample_id,create_time,llm_id,?::jsonb,answer_state,trace_llm,chat_state,param_json,async_query_json,group_type,?::timestamp,?,?::timestamp" + " FROM chat_history_detail WHERE history_id=?" , new Object[] { shareId, asjJson, curTime, tranReq.getLoginUserId(), expireTime, historyId, }); jsonWr.addKeyValue(historyId, shareId); } jsonWr.endMap(); db.executeSQL("COMMIT", null); } catch(Exception ex) { db.rollbackDB(ex); } return tranReq.returnJson(jsonWr); } finally { db.close(); } } public ModelAndView getShareChatJson(SMTAIServerRequest tranReq) throws Exception { String shareId = tranReq.convParamToString("share_id", true); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); DBRecords recs = db.querySQL( "SELECT ask_json FROM chat_share_detail WHERE share_id=? AND expire_time > ?", new Object[] {shareId, new Date()}); if(recs.getRowCount() == 0) return tranReq.returnJsonState(false, "未发现共享数据或已经失效", null); jsonWr.addKeyRaw("values", recs.getRecord(0).getString("ask_json")); return tranReq.returnJson(jsonWr); } finally { db.close(); } } public ModelAndView shareAsyncQuery(SMTAIServerRequest tranReq) throws Exception { String shareId = tranReq.convParamToString("share_id", true); String recId = tranReq.convParamToString("rec_id", true); //Integer page = tranReq.convParamToInteger("page", false); //Integer count = tranReq.convParamToInteger("perPage", false); SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { String sJsonValues; if("__AGENT_CHECK_MODE__".equals(shareId)) { sJsonValues = (String) tranReq.getSessionAttribute("QWEN_ASYNC_JSON"); if(SMTStatic.isNullOrEmpty(sJsonValues)) return tranReq.returnJsonState(false, "无结果保存", null); } else { DBRecords recs = db.querySQL("SELECT async_query_json FROM chat_share_detail WHERE share_id=? AND async_query_json is not null", new Object[] {shareId}); if(recs.getRowCount() == 0) return tranReq.returnJsonState(false, "history id error", null); sJsonValues = recs.getRecord(0).getString(0); } Json jsonValues = Json.read(sJsonValues); Json jsonValue = jsonValues.safeGetJson(recId); if(jsonValue == null) return tranReq.returnJsonState(false, "rec id error", null); List colNames = new ArrayList<>(); for(Json jsonColumn : jsonValue.getJson("columns").asJsonList()) { colNames.add(jsonColumn.asString().toLowerCase()); } SMTJsonWriter jsonWr = new SMTJsonWriter(true); for(Json jsonRows : jsonValue.getJson("values").asJsonList()) { jsonWr.beginMap(null); for(int i = 0; i < colNames.size(); i ++) { Object value = jsonRows.at(i).getValue(); jsonWr.addKeyValue(colNames.get(i), value); } jsonWr.endMap(); } return tranReq.returnJson(jsonWr); } finally { db.close(); } } public ModelAndView queryDetailValues(SMTAIServerRequest tranReq) throws Exception { // 获取参数 String queryId = tranReq.convParamToString("query_id", true); Json queryArgs = tranReq.convParamToJson("query_args", false); // 如果参数不是通过query_args设置的,则获取所有参数 if(queryArgs == null) { queryArgs = Json.object(); for(Entry entry : tranReq.getParameterMap().entrySet()) { String key = entry.getKey(); String value = entry.getValue()[0]; if(SMTStatic.isNullOrEmpty(value)) continue; if("query_id".equals(key) || "query_args".equals(key)) continue; queryArgs.set(key, value); } } // 执行查询 SMTAIQueryDetail queryDetail = SMTAIServerApp.getApp().getQueryDetail(queryId); return queryDetail.executeQuery(tranReq, queryArgs); } public ModelAndView questionStreamReply(SMTAIServerRequest tranReq) throws Exception { // 获取参数 String replyId = tranReq.convParamToString("reply_id", true); Json replyArgs = tranReq.convParamToJson("reply_args", false); // 如果参数不是通过reply_args设置的,则获取所有参数 if(replyArgs == null) { replyArgs = Json.object(); for(Entry entry : tranReq.getParameterMap().entrySet()) { String key = entry.getKey(); String value = entry.getValue()[0]; if(SMTStatic.isNullOrEmpty(value)) continue; if("query_id".equals(key) || "query_args".equals(key)) continue; replyArgs.set(key, value); } } replyArgs.set("json_reply", true); tranReq.setChatStreamReplyValue(replyId, replyArgs); return tranReq.returnJsonState(true, null, null); } public ModelAndView getGlobalConfig(SMTAIServerRequest tranReq) throws Exception { String[] configKeyList = tranReq.convParamToStringArray("config_key_list", true); SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginMap("values"); for(String configKey : configKeyList) { if(!configKey.startsWith("ui.")) throw new Exception("only ui. can query"); Object oValue = SMTAIServerApp.getApp().getGlobalConfig(configKey); if(oValue instanceof Json) jsonWr.addKeyRaw(configKey, (Json)oValue); else jsonWr.addKeyValue(configKey, SMTStatic.toString(oValue)); } jsonWr.endMap(); return tranReq.returnJson(jsonWr); } public ModelAndView getAttachTableList(SMTAIServerRequest tranReq) throws Exception { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginArray("tables"); for(SMTAIAttachTableDef attachTableDef : SMTAIServerApp.getApp().getAttachTableDefMap().values()) { jsonWr.beginMap(null); { jsonWr.addKeyValue("id", attachTableDef.getId()); jsonWr.addKeyValue("title", attachTableDef.getTitle()); jsonWr.addKeyValue("group", attachTableDef.getGroup()); jsonWr.addKeyValue("is_chart", attachTableDef.isChartTable()); jsonWr.beginArray("columns"); for(SMTAIAttachTableColumn columnDef : attachTableDef.getColumnList()) { jsonWr.beginMap(null); { jsonWr.addKeyValue("name", columnDef.getName()); jsonWr.addKeyValue("title", columnDef.getTitle()); jsonWr.addKeyValue("filter", columnDef.getFilter()); jsonWr.addKeyValue("chart_type", columnDef.getChartType()); } jsonWr.endMap(); } jsonWr.endArray(); } jsonWr.endMap(); } jsonWr.endArray(); return tranReq.returnJson(jsonWr); } public ModelAndView queryAttachTableRecords(SMTAIServerRequest tranReq) throws Exception { String attachTableId = tranReq.convParamToString("id", true); Json jsonFilters = tranReq.convParamToJson("filter", false); Json jsonOrders = tranReq.convParamToJson("order", false); Integer limit = tranReq.convParamToInteger("limit", false); SMTAIAttachTableDef attachTableDef = (SMTAIAttachTableDef) SMTAIServerApp.getApp().getAttachTableDef(attachTableId); if (limit==null) limit=100; SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); attachTableDef.queryRecordsToJson(jsonFilters, jsonOrders, jsonWr,limit); return tranReq.returnJson(jsonWr); } public ModelAndView getAttachMetricList(SMTAIServerRequest tranReq) throws Exception { SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginArray("metrics"); for(SMTAIAttachMetricDef attachMetricDef : SMTAIServerApp.getApp().getAttachMetricDefMap().values()) { jsonWr.beginMap(null); { jsonWr.addKeyValue("id", attachMetricDef.getId()); jsonWr.addKeyValue("title", attachMetricDef.getTitle()); jsonWr.addKeyValue("group", attachMetricDef.getGroup()); } jsonWr.endMap(); } jsonWr.endArray(); return tranReq.returnJson(jsonWr); } public ModelAndView queryAttachMetricNames(SMTAIServerRequest tranReq) throws Exception { String attachMetricId = tranReq.convParamToString("id", true); String queryName = tranReq.convParamToString("name", true); SMTAIAttachMetricDef attachMetricDef = SMTAIServerApp.getApp().getAttachMetricDef(attachMetricId); SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginArray("values"); attachMetricDef.queryNameToJson(queryName, jsonWr); jsonWr.endArray(); return tranReq.returnJson(jsonWr); } public ModelAndView queryAttachMetricValues(SMTAIServerRequest tranReq) throws Exception { String attachMetricId = tranReq.convParamToString("id", true); Date startTime = tranReq.convParamToDate("start_time", true); Date endTime = tranReq.convParamToDate("end_time", true); Json jsonQuotaKeys = tranReq.convParamToJson("quota_keys", true); Integer limit = tranReq.convParamToInteger("limit", false); if (limit==null) limit=100; SMTAIAttachMetricDef attachMetricDef = SMTAIServerApp.getApp().getAttachMetricDef(attachMetricId); SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); attachMetricDef.queryValueToJson(startTime, endTime, jsonQuotaKeys, jsonWr,limit); return tranReq.returnJson(jsonWr); } public ModelAndView callLLM(SMTAIServerRequest tranReq) throws Exception { String llmId = tranReq.convParamToString("llm_id", false); Json jsonSystems = tranReq.convParamToJson("system_json", false); String question = tranReq.convParamToString("question", true); boolean answerIsJson = tranReq.convParamToBoolean("answer_is_json", true); SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); SMTLLMConnect conn = SMTAIServerApp.getApp().allocLLMConnect(llmId); List listSystem = new ArrayList<>(); if(jsonSystems != null) { for(Json jsonSystem : jsonSystems.asJsonList()) { listSystem.add(jsonSystem.asString()); } } String answer = conn.callWithMessage(listSystem, question, tranReq); if(answerIsJson) { jsonWr.addKeyRaw("answer", SMTStatic.convLLMAnswerToJson(answer, false)); } else { jsonWr.addKeyValue("answer", answer); } return tranReq.returnJson(jsonWr); } public ModelAndView downloadFileByFileId(SMTAIServerRequest tranReq, HttpServletResponse response) throws Exception { String fileId = tranReq.convParamToString("file_id", true); // 获取请求中的file_id SMTDatabase db = SMTAIServerApp.getApp().allocDatabase(); try { // 查询指定file_id的文件记录 DBRecords dbRecords = db.querySQL("SELECT * FROM ai_times.chat_history_attach WHERE attach_id=?", new Object[]{fileId}); if (dbRecords.getRecords().isEmpty()) { throw new Exception("文件不存在"); } // 获取文件信息 DBRecord fileRecord = dbRecords.getRecords().get(0); String attachTitle = fileRecord.getString("attach_title"); // 获取文件标题 String extension = attachTitle.substring(attachTitle.lastIndexOf(".") + 1); // 扩展名和 MIME 类型映射 Object fileTypeMapping = SMTAIServerApp.getApp().getGlobalConfig("file_type_mapping", false); Json json = Json.read(fileTypeMapping.toString()); Map mimeTypes = json.asMap(); String mimeType = (String) mimeTypes.getOrDefault(extension.toLowerCase(), "application/octet-stream"); // 获取文件的字节数据,假设返回的是字节数组 byte[] bytes = (byte[]) fileRecord.getValue("attach_bytes"); // 获取字节数据 return tranReq.returnDownloadByteArray(bytes, attachTitle, mimeType); // // 设置响应头和文件名 // String fileName = attachTitle != null ? attachTitle : "downloaded_file"; // response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); // response.setContentType("application/octet-stream"); // response.getOutputStream().write(bytes); // 写入字节数据 // response.getOutputStream().flush(); } catch (Exception e) { throw new Exception("Error processing file download: " + e.getMessage()); } } public ModelAndView chatCallAgent(SMTAIServerRequest tranReq) throws Exception { String agentId = tranReq.convParamToString("agent_id", true); Json jsonArgs = tranReq.convParamToJson("args", false); SMTQwenAgent agent = SMTAIServerApp.getApp().getQwenAgentManager().getAgentById(agentId); if(agent == null) throw new Exception("can't find agent : " + agentId); SMTLLMConnect llm = SMTAIServerApp.getApp().allocLLMConnect(null); if(jsonArgs == null) jsonArgs = Json.object("question", ""); if(!jsonArgs.has("question")) jsonArgs.set("question", ""); agent.callAgents("/", jsonArgs, llm, "", tranReq); List listResult = tranReq.getResultJsonWrList(); SMTJsonWriter jsonWr = tranReq.newReturnJsonWriter(true, null, null); jsonWr.beginArray("results"); if(listResult != null && listResult.size() > 0) { for(SMTJsonWriter jsonWrResult : listResult) { jsonWr.addKeyRaw(null, jsonWrResult.getRootJson()); } } jsonWr.endArray(); return tranReq.returnJson(jsonWr); } public ModelAndView callAgentArgStream(SMTAIServerRequest tranReq) throws Exception { return new ModelAndView(new SMTCallAgentArgStreamView(tranReq)); } }