package com.smtaiserver.smtaiserver.control; import java.io.File; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.bind.annotation.RequestPart; 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; import com.smtaiserver.smtaiserver.core.SMTAIServerApp; import com.smtaiserver.smtaiserver.core.SMTAIServerRequest; 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; public class SMTJavaAIControl { 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; public SMTChatStreamView(SMTAIServerRequest tranReq) { _tranReq = tranReq; _tranReq.setChunkedMode(true); } @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); 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(); } } } private class SMTAttachFileChatStreamView implements View { private SMTAIServerRequest _tranReq; private List _files; public SMTAttachFileChatStreamView(SMTAIServerRequest tranReq, List files) { _tranReq = tranReq; _files = files; _tranReq.setChunkedMode(true); } @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 { attachFileChatQuestionToJson(_tranReq, true); //Json jsonResult = chatQuestionToJson(_tranReq, true); //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(); } } } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// protected Json attachFileChatQuestionToJson(SMTAIServerRequest tranReq, boolean isStreamMode) 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); Boolean rawMode = tranReq.convParamToBoolean("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); if(rawMode == null) rawMode = false; 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(); } } 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 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); return tranReq.returnJson(jsonOutput); } protected Json chatQuestionToJson(SMTAIServerRequest tranReq, boolean isStreamMode) 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); Boolean rawMode = tranReq.convParamToBoolean("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); if(rawMode == null) rawMode = false; 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", "") + "]的数据"); 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(); 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); 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) throws Exception { return new ModelAndView(new SMTChatStreamView(tranReq)); } 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 testUpload(SMTAIServerRequest tranReq, @RequestPart(value = "files", required=false) List files) throws Exception { return new ModelAndView(new SMTAttachFileChatStreamView(tranReq, files)); } }