package com.smtaiserver.smtaiserver.control;
|
|
import java.io.ByteArrayOutputStream;
|
import java.io.File;
|
import java.io.InputStream;
|
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.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;
|
|
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;
|
|
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<String, ?> 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 fileId = SMTStatic.newUUID();
|
String fileName = new File(file.getOriginalFilename()).getName();
|
byte[] fileData = readAttachFile(file);
|
String fileText = new String(fileData, "UTF-8");
|
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;
|
}
|
|
_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<String, ?> 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 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<String> mapResult = new HashSet<>();
|
Map<String, Map<String, SMTMetricsDef>> mapAgent2Id2MetricDef = SMTAIServerApp.getApp().getMetricsMapGroupMap();
|
for(Map<String, SMTMetricsDef> 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);
|
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;
|
|
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", "") + "]的数据");
|
|
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<Json> 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<String> 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<SMTJsonWriter> 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<String> 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("<HTML><BODY>Page can't be found : " + id + "</BODY></HTML>");
|
|
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<String> 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<Json> 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<Object> 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<String> 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<String, String[]> 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<String, String[]> 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);
|
}
|
|
}
|