Нет описания

DifyAssistantServiceImpl.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. package api.service.dify.impl;
  2. import api.entity.database.dify.DifyAssistant;
  3. import api.entity.input.PageInput;
  4. import api.entity.input.dify.*;
  5. import api.entity.view.system.UserView;
  6. import api.mapper.dify.DifyAssistantMapper;
  7. import api.service.dify.IDifyAssistantService;
  8. import api.service.BaseServiceImpl;
  9. import api.util.helper.HttpHelper;
  10. import api.util.helper.StringHelper;
  11. import com.fasterxml.jackson.databind.ObjectMapper;
  12. import com.google.gson.Gson;
  13. import lombok.var;
  14. import org.springframework.stereotype.Service;
  15. import org.springframework.transaction.annotation.Transactional;
  16. import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
  17. import javax.servlet.http.HttpServletResponse;
  18. import java.io.*;
  19. import java.net.HttpURLConnection;
  20. import java.net.URL;
  21. import java.nio.charset.StandardCharsets;
  22. import java.util.Objects;
  23. @Transactional
  24. @Service
  25. public class DifyAssistantServiceImpl extends BaseServiceImpl<DifyAssistantMapper, DifyAssistant> implements IDifyAssistantService{
  26. public DifyAssistantServiceImpl(){ super(false); }
  27. private final Gson gson = new Gson();
  28. //发送对话消息
  29. @Override
  30. public SseEmitter chatMessages(DifyChatMessagesInput difyInput,
  31. UserView userView, HttpServletResponse response) throws IOException {
  32. SseEmitter sseEmitter = new SseEmitter();
  33. // 设置MIME类型为text/event-stream以符合SSE要求
  34. response.setContentType("text/event-stream");
  35. response.setCharacterEncoding("UTF-8");
  36. PrintWriter writer = response.getWriter();
  37. try {
  38. var dify=this .getEntity(difyInput.getId());
  39. // 1. 设置URL和API密钥
  40. String apiUrl = dify.getUrl()+"/chat-messages";
  41. String apiKey = dify.getSecretKey(); // 替换为实际API密钥
  42. String files="[]";
  43. if (difyInput.getFiles()!=null&&difyInput.getFiles().size()>0)
  44. {
  45. StringBuilder builder=new StringBuilder();
  46. builder.append("[");
  47. for (DifyFiles item :difyInput.getFiles())
  48. {
  49. builder.append("{");
  50. builder.append("\"type\": \"").append(item.getType()).append("\",");
  51. builder.append("\"transfer_method\": \"").append(item.getTransfer_method()).append("\",");
  52. if(Objects.equals(item.getTransfer_method(), "remote_url"))
  53. {
  54. builder.append("\"url\": \"").append(item.getUrl()).append("\"");
  55. }
  56. else
  57. {
  58. builder.append("\"upload_file_id\": \"").append(item.getUrl()).append("\"");
  59. }
  60. builder.append("}");
  61. }
  62. builder.append("]");
  63. files=builder.toString();
  64. }
  65. String jsonString="";
  66. if (difyInput.getInputs()!=null)
  67. {
  68. ObjectMapper objectMapper = new ObjectMapper();
  69. jsonString= objectMapper.writeValueAsString(difyInput.getInputs());
  70. }
  71. // 2. 创建JSON请求体
  72. String jsonBody = "{"
  73. + "\"inputs\": "+jsonString+","
  74. + "\"query\": \""+difyInput.getQuery()+"\","
  75. + "\"response_mode\": \"streaming\","
  76. + "\"conversation_id\": \""+difyInput.getConversation_id()+"\","
  77. + "\"user\": \""+userView.getUserName()+"\","
  78. + "\"files\": \""+files+"\","
  79. + "\"auto_generate_name\": \""+difyInput.getAuto_generate_name()+"\""
  80. + "}";
  81. // 3. 创建HTTP连接
  82. URL url = new URL(apiUrl);
  83. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  84. conn.setRequestMethod("POST");
  85. conn.setRequestProperty("Authorization", "Bearer " + apiKey);
  86. conn.setRequestProperty("Content-Type", "application/json");
  87. conn.setDoOutput(true);
  88. // 4. 发送请求体
  89. try (OutputStream os = conn.getOutputStream()) {
  90. byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
  91. os.write(input, 0, input.length);
  92. }
  93. // 获取响应码
  94. int responseCode = conn.getResponseCode();
  95. if (responseCode == HttpURLConnection.HTTP_OK) {
  96. // 获取响应输入流
  97. InputStream inputStream = conn.getInputStream();
  98. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
  99. String line;
  100. try {
  101. while ((line = reader.readLine()) != null) {
  102. if (line.startsWith("data: {\"event\": \"message\"") ||line.startsWith("data: {\"event\": \"message_end\"")) {
  103. writer.write(unicodeToString(line)+"\n");
  104. // sseEmitter.send(unicodeToString(line)); // 实时发送单条结果
  105. System.out.println(unicodeToString(line));
  106. writer.flush();
  107. }
  108. }
  109. } catch (IOException e) {
  110. e.printStackTrace();
  111. }
  112. } else {
  113. System.out.println("POST Request is not successful");
  114. }
  115. conn.disconnect();
  116. } catch (Exception e) {
  117. e.printStackTrace();
  118. }
  119. sseEmitter.complete();
  120. return sseEmitter;
  121. }
  122. //发送工作流
  123. @Override
  124. public SseEmitter workflows(WorkflowsInput difyInput,
  125. UserView userView, HttpServletResponse response) throws IOException {
  126. SseEmitter sseEmitter = new SseEmitter();
  127. // 设置MIME类型为text/event-stream以符合SSE要求
  128. response.setContentType("text/event-stream");
  129. response.setCharacterEncoding("UTF-8");
  130. PrintWriter writer = response.getWriter();
  131. try {
  132. var dify=this .getEntity(difyInput.getId());
  133. // 1. 设置URL和API密钥
  134. String apiUrl = dify.getUrl()+"/workflows/run";
  135. String apiKey = dify.getSecretKey(); // 替换为实际API密钥
  136. String jsonString="";
  137. if (difyInput.getInputs()!=null)
  138. {
  139. ObjectMapper objectMapper = new ObjectMapper();
  140. jsonString= objectMapper.writeValueAsString(difyInput.getInputs());
  141. }
  142. // 2. 创建JSON请求体
  143. String jsonBody = "{"
  144. + "\"inputs\": "+jsonString+","
  145. + "\"response_mode\": \"streaming\","
  146. + "\"user\": \""+userView.getUserName()+"\""
  147. + "}";
  148. // 3. 创建HTTP连接
  149. URL url = new URL(apiUrl);
  150. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  151. conn.setRequestMethod("POST");
  152. conn.setRequestProperty("Authorization", "Bearer " + apiKey);
  153. conn.setRequestProperty("Content-Type", "application/json");
  154. conn.setDoOutput(true);
  155. // 4. 发送请求体
  156. try (OutputStream os = conn.getOutputStream()) {
  157. byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
  158. os.write(input, 0, input.length);
  159. }
  160. // 获取响应码
  161. int responseCode = conn.getResponseCode();
  162. if (responseCode == HttpURLConnection.HTTP_OK) {
  163. // 获取响应输入流
  164. InputStream inputStream = conn.getInputStream();
  165. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
  166. String line;
  167. try {
  168. while ((line = reader.readLine()) != null) {
  169. writer.write(unicodeToString(line)+"\n");
  170. // sseEmitter.send(unicodeToString(line)); // 实时发送单条结果
  171. System.out.println(unicodeToString(line));
  172. writer.flush();
  173. }
  174. } catch (IOException e) {
  175. e.printStackTrace();
  176. }
  177. } else {
  178. System.out.println("POST Request is not successful");
  179. }
  180. conn.disconnect();
  181. } catch (Exception e) {
  182. e.printStackTrace();
  183. }
  184. sseEmitter.complete();
  185. return sseEmitter;
  186. }
  187. private static String unicodeToString(String unicode) {
  188. StringBuilder sb = new StringBuilder();
  189. int i = -1;
  190. int pos = 0;
  191. while ((i = unicode.indexOf("\\u", pos)) != -1) {
  192. sb.append(unicode.substring(pos, i));
  193. if (i + 5 > unicode.length()) {
  194. pos = i + 2;
  195. continue;
  196. }
  197. String hex = unicode.substring(i + 2, i + 6);
  198. try {
  199. sb.append((char) Integer.parseInt(hex, 16));
  200. pos = i + 6;
  201. } catch (NumberFormatException e) {
  202. sb.append(unicode.substring(i, i + 2));
  203. pos = i + 2;
  204. }
  205. }
  206. sb.append(unicode.substring(pos));
  207. return sb.toString();
  208. }
  209. //消息反馈
  210. @Override
  211. public String feedbacks(DifyFeedbacksInput input,
  212. UserView userView) throws IOException {
  213. var dify=this .getEntity(input.getId());
  214. String apiUrl = dify.getUrl()+"/messages/"+input.getMessage_id()+"/feedbacks";
  215. String apiKey = dify.getSecretKey(); // 替换为实际API密钥
  216. // 2. 创建JSON请求体
  217. String jsonBody = "{\n" +
  218. " \"rating\": \""+input.getRating()+"\",\n" +
  219. " \"user\": \""+userView.getUserName()+"\",\n" +
  220. " \"content\": \""+input.getContent()+"\"\n" +
  221. "}";
  222. return HttpHelper.DifyHttpPost(apiUrl,apiKey,jsonBody);
  223. }
  224. //获取APP的消息点赞和反馈
  225. @Override
  226. public String appFeedbacks(PageInput pageInput,long id
  227. ) throws Exception {
  228. var dify=this .getEntity(id);
  229. String apiUrl = dify.getUrl()+"/app/feedbacks?page="+pageInput.getPageNum()+"&limit="+pageInput.getPageSize();
  230. return HttpHelper.DifyHttpGet(apiUrl,dify.getSecretKey());
  231. }
  232. @Override
  233. public String suggested(long id, String message_id, UserView userView) throws Exception {
  234. var dify=this .getEntity(id);
  235. String apiUrl = dify.getUrl()+"/messages/"+message_id+"/suggested?user="+userView.getUserName();
  236. return HttpHelper.DifyHttpGet(apiUrl,dify.getSecretKey());
  237. }
  238. //获取会话历史消息
  239. @Override
  240. public String History(DifyHistoryInput input, UserView userView) throws Exception {
  241. var dify=this .getEntity(input.getId());
  242. StringBuilder builder=new StringBuilder();
  243. if (StringHelper.isNotEmpty(input.getFirst_id()))
  244. {
  245. builder.append("&first_id").append(input.getFirst_id());
  246. }
  247. if (input.getLimit()!=null&&input.getLimit()>0)
  248. {
  249. builder.append("&limit").append(input.getLimit());
  250. }
  251. String url=builder.toString();
  252. String apiUrl = dify.getUrl()+"/messages?user="+userView.getUserName()+"&conversation_id="+input.getConversation_id()+url;
  253. return HttpHelper.DifyHttpGet(apiUrl,dify.getSecretKey());
  254. }
  255. @Override
  256. public String conversations(DifyConversationsInput input, UserView userView) throws Exception {
  257. var dify=this .getEntity(input.getId());
  258. StringBuilder builder=new StringBuilder();
  259. if (StringHelper.isNotEmpty(input.getLast_id()))
  260. {
  261. builder.append("&last_id").append(input.getLast_id());
  262. }
  263. if (input.getLimit()!=null&&input.getLimit()>0)
  264. {
  265. builder.append("&limit").append(input.getLimit());
  266. }
  267. if (StringHelper.isNotEmpty(input.getSort_by()))
  268. {
  269. builder.append("&sort_by").append(input.getSort_by());
  270. }
  271. String url=builder.toString();
  272. String apiUrl = dify.getUrl()+"/conversations?user="+userView.getUserName()+ url;
  273. return HttpHelper.DifyHttpGet(apiUrl,dify.getSecretKey());
  274. }
  275. //删除会话
  276. @Override
  277. public Boolean DelConversations(long id, String conversation_id, UserView userView) throws Exception {
  278. var dify=this .getEntity(id);
  279. String apiUrl = dify.getUrl()+"/conversations/"+conversation_id;
  280. String requestBody = String.format("{ \"user\": \"%s\" }", userView.getUserName());
  281. return HttpHelper.DifyHttpDelete(apiUrl,dify.getSecretKey(),requestBody);
  282. }
  283. //会话重命名
  284. @Override
  285. public String Rename(DifyRenameInput input, UserView userView) throws Exception {
  286. var dify=this .getEntity(input.getId());
  287. String apiUrl = dify.getUrl()+"/conversations/"+input.getConversation_id()+"/name";
  288. String apiKey = dify.getSecretKey(); // 替换为实际API密钥
  289. // 2. 创建JSON请求体
  290. String jsonBody = "{\n" +
  291. " \"name\": \""+input.getName()+"\",\n" +
  292. " \"auto_generate\": \""+input.getAuto_generate()+"\",\n" +
  293. " \"user\": \""+userView.getUserName()+"\"\n" +
  294. "}";
  295. return HttpHelper.DifyHttpPost(apiUrl,apiKey,jsonBody);
  296. }
  297. }