| | |
| | | import com.smtaiserver.smtaiserver.database.SMTDatabase.DBRecords; |
| | | import com.smtaiserver.smtaiserver.javaai.ast.ASTDBMap; |
| | | import com.smtaiserver.smtaiserver.javaai.llm.core.SMTLLMConnect; |
| | | import com.smtaiserver.smtaiserver.vo.MediaVo; |
| | | import com.smtaiserver.smtaiserver.vo.WechatMessageVO; |
| | | import com.smtservlet.core.SMTRequest; |
| | | import com.smtservlet.util.Json; |
| | | import com.smtservlet.util.SMTJsonWriter; |
| | |
| | | import org.dom4j.DocumentException; |
| | | import org.dom4j.Element; |
| | | import org.dom4j.io.SAXReader; |
| | | import org.springframework.boot.configurationprocessor.json.JSONException; |
| | | import org.springframework.boot.configurationprocessor.json.JSONObject; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.web.servlet.ModelAndView; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.ServletInputStream; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.xml.bind.JAXBContext; |
| | | import javax.xml.bind.JAXBException; |
| | | import javax.xml.bind.Marshaller; |
| | | import javax.xml.crypto.Data; |
| | | import java.io.IOException; |
| | | import java.io.OutputStream; |
| | | import java.io.StringWriter; |
| | |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.util.*; |
| | | import java.util.concurrent.CompletableFuture; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | import static java.util.Arrays.sort; |
| | | |
| | |
| | | private static final String TO_USER_NAME = "ToUserName"; |
| | | private static final String CONTENT = "Content"; |
| | | private static Logger _logger = LogManager.getLogger(SMTAIServerControl.class); |
| | | |
| | | private Object _lockToken = new Object(); |
| | | private String _tokenValue = null; |
| | | private long _tokenTicket = 0; |
| | | |
| | | |
| | | private Object _lockToken = new Object(); |
| | | private String _tokenValue = null; |
| | | private long _tokenTicket = 0; |
| | | |
| | | /** 微信éªè¯ */ |
| | | public ModelAndView weChatNotify(SMTAIServerRequest tranReq) throws Exception { |
| | |
| | | if (requestMap.isEmpty()) { |
| | | return null; |
| | | } |
| | | |
| | | // wechatMessage.setFromUserName(requestMap.get(TO_USER_NAME)); |
| | | // wechatMessage.setToUserName(requestMap.get(FROM_USER_NAME)); |
| | | // wechatMessage.setCreateTime(System.currentTimeMillis() / 1000); |
| | | String xmltemp = |
| | | "<xml>\n" |
| | | + " <ToUserName><![CDATA[{{{toUser}}}]]></ToUserName>\n" |
| | | + " <FromUserName><![CDATA[{{{fromUser}}}]]></FromUserName>\n" |
| | | + " <CreateTime>{{{CreateTime}}}</CreateTime>\n" |
| | | + " <MsgType><![CDATA[text]]></MsgType>\n" |
| | | + " <Content><![CDATA[ææ£å¨æèå¦~请ç¨çâ¦â¦]]></Content>\n" |
| | | + "</xml>"; |
| | | long l = System.currentTimeMillis() / 1000; |
| | | String createTimeStr = String.valueOf(l); // å° long 转æ¢ä¸º String |
| | | // æ¿æ¢å ä½ç¬¦ |
| | | String result = |
| | | xmltemp |
| | | .replace("{{{toUser}}}", requestMap.get(TO_USER_NAME)) |
| | | .replace("{{{fromUser}}}", requestMap.get(FROM_USER_NAME)) |
| | | .replace("{{{CreateTime}}}", createTimeStr); |
| | | String reqContent = requestMap.get(CONTENT); |
| | | WechatMessageVO wechatMessage = new WechatMessageVO(); |
| | | wechatMessage.setFromUserName(requestMap.get(TO_USER_NAME)); |
| | | wechatMessage.setToUserName(requestMap.get(FROM_USER_NAME)); |
| | | // è®¾ç½®æ¶æ¯ç±»å |
| | | switch (reqContent) { |
| | | case "æå": |
| | | wechatMessage.setMsgType("text"); |
| | | break; |
| | | case "å¾ç": |
| | | wechatMessage.setMsgType("image"); |
| | | break; |
| | | case "è¯é³": |
| | | wechatMessage.setMsgType("voice"); |
| | | break; |
| | | case "è§é¢": |
| | | wechatMessage.setMsgType("video"); |
| | | break; |
| | | case "é³ä¹": |
| | | wechatMessage.setMsgType("music"); |
| | | break; |
| | | case "徿": |
| | | wechatMessage.setMsgType("news"); |
| | | break; |
| | | default: |
| | | wechatMessage.setMsgType("text"); |
| | | break; |
| | | } |
| | | // switch (reqContent) { |
| | | // case "æå": |
| | | // wechatMessage.setMsgType("text"); |
| | | // break; |
| | | // case "å¾ç": |
| | | // wechatMessage.setMsgType("image"); |
| | | // break; |
| | | // case "è¯é³": |
| | | // wechatMessage.setMsgType("voice"); |
| | | // break; |
| | | // case "è§é¢": |
| | | // wechatMessage.setMsgType("video"); |
| | | // break; |
| | | // case "é³ä¹": |
| | | // wechatMessage.setMsgType("music"); |
| | | // break; |
| | | // case "徿": |
| | | // wechatMessage.setMsgType("news"); |
| | | // break; |
| | | // default: |
| | | // wechatMessage.setMsgType("text"); |
| | | // break; |
| | | // } |
| | | |
| | | wechatMessage.setCreateTime(System.currentTimeMillis() / 1000); |
| | | MediaVo media = new MediaVo(); |
| | | wechatMessage.setContent("ææ£å¨æèå¦~请ç¨çâ¦â¦"); |
| | | // MediaVo media = new MediaVo(); |
| | | // wechatMessage.setContent("ææ£å¨æèå¦~请ç¨çâ¦â¦"); |
| | | // 弿¥è°ç¨ aiReplyToTheUserASecondTime |
| | | CompletableFuture.runAsync( |
| | | () -> { |
| | |
| | | |
| | | try { |
| | | // å° WechatMessageVO 对象转æ¢ä¸º XML |
| | | JAXBContext jaxbContext = JAXBContext.newInstance(WechatMessageVO.class); |
| | | Marshaller marshaller = jaxbContext.createMarshaller(); |
| | | marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); |
| | | StringWriter sw = new StringWriter(); |
| | | marshaller.marshal(wechatMessage, sw); |
| | | _logger.info("å¾®ä¿¡æ¶æ¯è¿åï¼" + sw); |
| | | // JAXBContext jaxbContext = JAXBContext.newInstance(WechatMessageVO.class); |
| | | // Marshaller marshaller = jaxbContext.createMarshaller(); |
| | | // marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); |
| | | // StringWriter sw = new StringWriter(); |
| | | // marshaller.marshal(wechatMessage, sw); |
| | | _logger.info("å¾®ä¿¡æ¶æ¯è¿åï¼" + xmltemp); |
| | | // è¿å XML å符串 |
| | | return tranReq.returnText(sw.toString()); |
| | | } catch (JAXBException e) { |
| | | return tranReq.returnText(xmltemp.toString()); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** aiåå¤ |
| | | * @throws Exception */ |
| | | private String callAIForAnswerQuestion(String question, SMTAIServerRequest tranReq) throws Exception |
| | | { |
| | | String callFunc = |
| | | "query_water_fee:\n" |
| | | + " åè½ï¼\n" |
| | | + " æ¥è¯¢ç¨æ·ç¨æ°´éåæ°´è´¹ä¿¡æ¯\n" |
| | | + " åæ°:\n" |
| | | + " question:ç¨æ·é®é¢\n" |
| | | + " user_name:ç¨æ·å\n" |
| | | + " value_title:'ç¨æ°´é'æ'æ°´è´¹'\n" |
| | | + " value_name:ç¨æ°´éï¼volume, æ°´è´¹:amount\n" |
| | | + " start_time:æ¥è¯¢èµ·å§æ¥æï¼æ ¼å¼ï¼å¹´-æ-æ¥\n" |
| | | + " end_time:æ¥è¯¢ç»ææ¶é´ï¼æ ¼å¼ï¼å¹´-æ-æ¥\n" |
| | | ; |
| | | |
| | | String prompt = ((String) SMTAIServerApp.getApp().getGlobalConfig("prompt.agent_tools")) |
| | | .replace("{{{AGENT_TOOL_DEFINE_LIST}}}", callFunc); |
| | | |
| | | SMTLLMConnect llm = SMTAIServerApp.getApp().allocLLMConnect(null); |
| | | String answer = llm.callWithMessage(new String[] {prompt}, question, tranReq); |
| | | tranReq.traceLLMDebug(answer); |
| | | Json oASTList = SMTStatic.convLLMAnswerToJson(answer, true); |
| | | if(oASTList != null && oASTList.isArray()) |
| | | { |
| | | List<Json> jsonASTList = oASTList.asJsonList(); |
| | | if(jsonASTList.size() > 0) |
| | | { |
| | | Json jsonAST = jsonASTList.get(0); |
| | | if("query_water_fee".equals(jsonAST.safeGetStr("call", null))) |
| | | { |
| | | jsonAST = jsonAST.getJson("args"); |
| | | try(ASTDBMap dbMap = new ASTDBMap()) |
| | | { |
| | | SMTDatabase db = dbMap.getDatabase("DS_74_CHENGTOU"); |
| | | DBRecords recs = db.querySQL( |
| | | " SELECT ROUND(SUM(" + jsonAST.getJson("value_name").asString() + ")::NUMERIC(10, 2), 2) AS TOTAL" |
| | | + " FROM chengtou_data.bill_data WHERE billing_date BETWEEN ? AND ?" |
| | | , new Object[] { |
| | | SMTStatic.toDate(jsonAST.getJson("start_time").asString()), |
| | | SMTStatic.toDate(jsonAST.getJson("end_time").asString()) |
| | | }); |
| | | |
| | | if(recs.getRowCount() == 0) |
| | | return "ä»" + jsonAST.getJson("start_time").asString() + "å°" + jsonAST.getJson("end_time").asString() + "ç" + jsonAST.getJson("value_title").asString() + "æªæ¥å°ä»»ä½æ°æ®"; |
| | | |
| | | return "ä»" + jsonAST.getJson("start_time").asString() + "å°" + jsonAST.getJson("end_time").asString() + "ç" + jsonAST.getJson("value_title").asString() |
| | | + "æ»è®¡" + recs.getRecord(0).getString(0); |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | answer = llm.callWithMessage(null, question, tranReq); |
| | | |
| | | return answer; |
| | | /** |
| | | * aiåå¤ |
| | | * |
| | | * @throws Exception |
| | | */ |
| | | private String callAIForAnswerQuestion(String question, SMTAIServerRequest tranReq) |
| | | throws Exception { |
| | | String callFunc = |
| | | "query_water_fee:\n" |
| | | + " åè½ï¼\n" |
| | | + " æ¥è¯¢ç¨æ·ç¨æ°´éåæ°´è´¹ä¿¡æ¯\n" |
| | | + " åæ°:\n" |
| | | + " question:ç¨æ·é®é¢\n" |
| | | + " user_name:ç¨æ·å\n" |
| | | + " value_title:'ç¨æ°´é'æ'æ°´è´¹'\n" |
| | | + " value_name:ç¨æ°´éï¼volume, æ°´è´¹:amount\n" |
| | | + " start_time:æ¥è¯¢èµ·å§æ¥æï¼æ ¼å¼ï¼å¹´-æ-æ¥\n" |
| | | + " end_time:æ¥è¯¢ç»ææ¶é´ï¼æ ¼å¼ï¼å¹´-æ-æ¥\n"; |
| | | |
| | | String prompt = |
| | | ((String) SMTAIServerApp.getApp().getGlobalConfig("prompt.agent_tools")) |
| | | .replace("{{{AGENT_TOOL_DEFINE_LIST}}}", callFunc); |
| | | |
| | | SMTLLMConnect llm = SMTAIServerApp.getApp().allocLLMConnect(null); |
| | | String answer = llm.callWithMessage(new String[] {prompt}, question, tranReq); |
| | | tranReq.traceLLMDebug(answer); |
| | | List<Json> jsonASTList = SMTStatic.convLLMAnswerToJson(answer, true).asJsonList(); |
| | | if (jsonASTList.size() > 0) { |
| | | Json jsonAST = jsonASTList.get(0); |
| | | if ("query_water_fee".equals(jsonAST.safeGetStr("call", null))) { |
| | | jsonAST = jsonAST.getJson("args"); |
| | | try (ASTDBMap dbMap = new ASTDBMap()) { |
| | | SMTDatabase db = dbMap.getDatabase("DS_74_CHENGTOU"); |
| | | DBRecords recs = |
| | | db.querySQL( |
| | | " SELECT ROUND(SUM(" |
| | | + jsonAST.getJson("value_name").asString() |
| | | + ")::NUMERIC(10, 2), 2) AS TOTAL" |
| | | + " FROM chengtou_data.bill_data WHERE billing_date BETWEEN ? AND ?", |
| | | new Object[] { |
| | | SMTStatic.toDate(jsonAST.getJson("start_time").asString()), |
| | | SMTStatic.toDate(jsonAST.getJson("end_time").asString()) |
| | | }); |
| | | |
| | | if (recs.getRowCount() == 0) |
| | | return "ä»" |
| | | + jsonAST.getJson("start_time").asString() |
| | | + "å°" |
| | | + jsonAST.getJson("end_time").asString() |
| | | + "ç" |
| | | + jsonAST.getJson("value_title").asString() |
| | | + "æªæ¥å°ä»»ä½æ°æ®"; |
| | | |
| | | return "ä»" |
| | | + jsonAST.getJson("start_time").asString() |
| | | + "å°" |
| | | + jsonAST.getJson("end_time").asString() |
| | | + "ç" |
| | | + jsonAST.getJson("value_title").asString() |
| | | + "æ»è®¡" |
| | | + recs.getRecord(0).getString(0); |
| | | } |
| | | } |
| | | } |
| | | answer = llm.callWithMessage(null, question, tranReq); |
| | | |
| | | return answer; |
| | | } |
| | | |
| | | /** äºæ¬¡åå¤ */ |
| | | public ModelAndView aiReplyToTheUserASecondTime(String answer, String fromUserName) |
| | | throws Exception { |
| | | String accessToken = getAccessToken(); |
| | | |
| | | |
| | | SMTJsonWriter jsonWr = new SMTJsonWriter(false); |
| | | jsonWr.addKeyValue("touser", fromUserName); |
| | | jsonWr.addKeyValue("msgtype", "text"); |
| | | jsonWr.beginMap("text"); |
| | | { |
| | | jsonWr.addKeyValue("content", answer); |
| | | jsonWr.addKeyValue("content", answer); |
| | | } |
| | | jsonWr.endMap(); |
| | | // JSONObject jsonObject = new JSONObject(); |
| | | // jsonObject.put("touser", fromUserName); |
| | | // jsonObject.put("msgtype", "text"); |
| | | // JSONObject jsonObject1 = new JSONObject(); |
| | | // jsonObject1.put("content", answer); |
| | | // jsonObject.put("text", jsonObject1); |
| | | // _logger.info("jsonObject: {}", jsonObject); |
| | | // JSONObject jsonObject = new JSONObject(); |
| | | // jsonObject.put("touser", fromUserName); |
| | | // jsonObject.put("msgtype", "text"); |
| | | // JSONObject jsonObject1 = new JSONObject(); |
| | | // jsonObject1.put("content", answer); |
| | | // jsonObject.put("text", jsonObject1); |
| | | // _logger.info("jsonObject: {}", jsonObject); |
| | | String url = |
| | | String.format( |
| | | "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s", accessToken); |
| | | //Map<String, Object> stringObjectMap = jsonObjectToMap(jsonWr.getRootJson()); |
| | | // Map<String, Object> stringObjectMap = jsonObjectToMap(jsonWr.getRootJson()); |
| | | String s = sendPost(url, jsonWr.getRootJson()); |
| | | _logger.info("ä¸ä¼ ç»æ: {}", s); |
| | | return null; |
| | |
| | | return tranReq.returnText(""); |
| | | } |
| | | |
| | | public String getAccessToken() throws Exception |
| | | { |
| | | synchronized(this._lockToken) |
| | | { |
| | | if(_tokenValue == null || (System.currentTimeMillis() - _tokenTicket) > 3600 * 1000) |
| | | { |
| | | HashMap<String, String> weixinParam = getWeixinParam(); |
| | | String url = |
| | | "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" |
| | | + weixinParam.get("appId") |
| | | + "&secret=" |
| | | + weixinParam.get("secret"); |
| | | String response = HttpUtil.get(url); |
| | | JSONObject jsonObject = new JSONObject(response); |
| | | if (jsonObject.has("access_token")) { |
| | | String accessToken = jsonObject.getString("access_token"); |
| | | |
| | | _tokenValue = accessToken; |
| | | } |
| | | else |
| | | { |
| | | throw new Exception("can't get weixin token"); |
| | | } |
| | | _tokenTicket = System.currentTimeMillis(); |
| | | } |
| | | return _tokenValue; |
| | | } |
| | | public String getAccessToken() throws Exception { |
| | | synchronized (this._lockToken) { |
| | | if (_tokenValue == null || (System.currentTimeMillis() - _tokenTicket) > 3600 * 1000) { |
| | | HashMap<String, String> weixinParam = getWeixinParam(); |
| | | String url = |
| | | "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" |
| | | + weixinParam.get("appId") |
| | | + "&secret=" |
| | | + weixinParam.get("secret"); |
| | | String response = HttpUtil.get(url); |
| | | JSONObject jsonObject = new JSONObject(response); |
| | | if (jsonObject.has("access_token")) { |
| | | String accessToken = jsonObject.getString("access_token"); |
| | | |
| | | _tokenValue = accessToken; |
| | | } else { |
| | | throw new Exception("can't get weixin token"); |
| | | } |
| | | _tokenTicket = System.currentTimeMillis(); |
| | | } |
| | | return _tokenValue; |
| | | } |
| | | } |
| | | |
| | | // public static Map<String, Object> jsonObjectToMap(JSONObject jsonObject) throws JSONException { |
| | | // Map<String, Object> map = new HashMap<>(); |
| | | // Iterator<String> keys = jsonObject.keys(); |
| | | // |
| | | // while (keys.hasNext()) { |
| | | // String key = keys.next(); |
| | | // Object value = jsonObject.get(key); |
| | | // |
| | | // // 妿弿¯ JSONObjectï¼éå½è½¬æ¢ä¸º Map |
| | | // if (value instanceof JSONObject) { |
| | | // value = jsonObjectToMap((JSONObject) value); |
| | | // } |
| | | // |
| | | // map.put(key, value); |
| | | // } |
| | | // |
| | | // return map; |
| | | // } |
| | | |
| | | |
| | | /** |
| | | * éªè¯ç¾åutil |
| | | * |
| | | * @param signature |
| | | * @param timestamp |
| | | * @param nonce |
| | | * @return |
| | | */ |
| | | /** éªè¯ç¾åutil */ |
| | | public static boolean checkSignature(String signature, String timestamp, String nonce) |
| | | throws Exception { |
| | | HashMap<String, String> weixinParam = getWeixinParam(); |
| | |
| | | |
| | | public static String sendPost(String urlString, Json jsonParam) throws Exception { |
| | | // å°åæ°è½¬æ¢ä¸º JSON æ ¼å¼å符串 |
| | | // JSONObject jsonParams = new JSONObject(params); |
| | | // JSONObject jsonParams = new JSONObject(params); |
| | | String payload = jsonParam.toString(); |
| | | // åå»ºè¿æ¥ |
| | | URL url = new URL(urlString); |