|
@@ -0,0 +1,299 @@
|
|
|
+package cn.cslg.pas.service.common;
|
|
|
+
|
|
|
+
|
|
|
+import cn.cslg.pas.common.model.dify.ChatMessageDTO;
|
|
|
+import cn.cslg.pas.common.model.dify.DifyChatMessageDTO;
|
|
|
+import cn.cslg.pas.common.model.dify.DifyHistoryMessageDTO;
|
|
|
+
|
|
|
+import cn.cslg.pas.common.utils.DataUtils;
|
|
|
+import cn.cslg.pas.domain.business.TechnicalCase;
|
|
|
+import cn.cslg.pas.domain.report.AssoProjectConfession;
|
|
|
+import cn.cslg.pas.service.business.TechnicalCaseService;
|
|
|
+import cn.cslg.pas.service.dify.DifySessionService;
|
|
|
+import cn.cslg.pas.service.report.AssoProjectConfessionService;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.google.gson.Gson;
|
|
|
+import com.google.gson.GsonBuilder;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import okhttp3.*;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+import org.springframework.web.reactive.function.client.WebClient;
|
|
|
+import reactor.core.publisher.Flux;
|
|
|
+
|
|
|
+import java.io.*;
|
|
|
+
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Okhttp调用FMS上传文件接口
|
|
|
+ *
|
|
|
+ * @Author lrj
|
|
|
+ * @Date 2025/4/10
|
|
|
+ */
|
|
|
+@RequiredArgsConstructor
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class DifyService {
|
|
|
+ @Value("${DIFY.apiKey}")
|
|
|
+ private String apiKey;
|
|
|
+ @Value("${DIFY.url}")
|
|
|
+ private String url;
|
|
|
+ @Value("${FileDownloadUrl}")
|
|
|
+ private String fileDownloadUrl;
|
|
|
+ private final DifySessionService difySessionService;
|
|
|
+ private final TechnicalCaseService technicalCaseService;
|
|
|
+ private final AssoProjectConfessionService assoProjectConfessionService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 调用文件系统删除文件接口
|
|
|
+ */
|
|
|
+ public String chatMessage(DifyChatMessageDTO difyChatMessageDTO) throws IOException {
|
|
|
+ String param = new Gson().toJson(difyChatMessageDTO);
|
|
|
+ RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
|
|
|
+ OkHttpClient okHttpClient = new OkHttpClient.Builder()
|
|
|
+ .connectTimeout(60, TimeUnit.SECONDS)
|
|
|
+ .writeTimeout(60, TimeUnit.SECONDS)
|
|
|
+ .readTimeout(60, TimeUnit.SECONDS)
|
|
|
+ .build();
|
|
|
+ Request request = new Request.Builder()
|
|
|
+ .url(url + "chat-messages")
|
|
|
+ .post(requestBody)
|
|
|
+ .addHeader("Authorization", "Bearer " + apiKey)
|
|
|
+ .build();
|
|
|
+ return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 调用文件系统删除文件接口
|
|
|
+ */
|
|
|
+ public String queryHistoryMessage(DifyHistoryMessageDTO difyChatMessageDTO) throws IOException {
|
|
|
+ difyChatMessageDTO.setUser("1");
|
|
|
+ OkHttpClient okHttpClient = new OkHttpClient.Builder()
|
|
|
+ .connectTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .writeTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .readTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .build();
|
|
|
+ String path = "messages?conversation_id=" + difyChatMessageDTO.getConversationId() + "&user=" + difyChatMessageDTO.getUser() + "&limit=" + difyChatMessageDTO.getLimit();
|
|
|
+ if (difyChatMessageDTO.getFirstId() != null) {
|
|
|
+ path += "&first_id=" + difyChatMessageDTO.getFirstId();
|
|
|
+ }
|
|
|
+ Request request = new Request.Builder()
|
|
|
+ .url(url + path)
|
|
|
+ .get()
|
|
|
+ .addHeader("Authorization", "Bearer " + apiKey)
|
|
|
+ .build();
|
|
|
+ return Objects.requireNonNull(okHttpClient.newCall(request).execute().body()).string();
|
|
|
+ }
|
|
|
+
|
|
|
+ public Flux<String> chatMessageStream(DifyChatMessageDTO difyChatMessageDTO) {
|
|
|
+ Gson gson = new GsonBuilder()
|
|
|
+ .disableHtmlEscaping() // 禁用 HTML 转义
|
|
|
+ .setPrettyPrinting()
|
|
|
+ .create();
|
|
|
+
|
|
|
+ return WebClient.create().post().uri(url + "chat-messages").header("Authorization", "Bearer " + apiKey).header(HttpHeaders.CONTENT_TYPE, "application/json").bodyValue(gson.toJson(difyChatMessageDTO))
|
|
|
+ .retrieve().bodyToFlux(String.class) // 接收原始字节
|
|
|
+ .map(string -> {
|
|
|
+ String chinese = "";
|
|
|
+ try {
|
|
|
+ ObjectMapper mapper = new ObjectMapper();
|
|
|
+ JsonNode node = mapper.readTree(string);
|
|
|
+ String prettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
|
|
|
+
|
|
|
+ chinese = prettyJson;
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ return chinese;
|
|
|
+ })// 这里指定编码
|
|
|
+ .doOnNext(System.out::println).doFinally(data -> {
|
|
|
+ System.out.println("数据接收完毕,可以在这里执行后续操作");
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public Flux<String> getOkhttp(ChatMessageDTO chatMessageDTO) {
|
|
|
+ Integer projectId = chatMessageDTO.getProjectId();
|
|
|
+ String conversationId = chatMessageDTO.getConversationId();
|
|
|
+ String userId = "1";
|
|
|
+ String query = chatMessageDTO.getQuery();
|
|
|
+ if (conversationId == null) {
|
|
|
+ conversationId = difySessionService.getSessionId(projectId, userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ String temConversationId = conversationId;
|
|
|
+ OkHttpClient client = new OkHttpClient.Builder()
|
|
|
+ .connectTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .writeTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .readTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .build();
|
|
|
+
|
|
|
+ DifyChatMessageDTO difyChatMessageDTO = new DifyChatMessageDTO();
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ String fileContent = this.getConfression(projectId);
|
|
|
+ String inventionPoint = this.getInventPoint(projectId);
|
|
|
+ map.put("file_path", fileContent);
|
|
|
+ map.put("invention_point", inventionPoint);
|
|
|
+ difyChatMessageDTO.setInputs(map);
|
|
|
+ difyChatMessageDTO.setConversationId(conversationId);
|
|
|
+ difyChatMessageDTO.setResponseMode("streaming");
|
|
|
+ difyChatMessageDTO.setUser(userId);
|
|
|
+ difyChatMessageDTO.setQuery(query);
|
|
|
+ difyChatMessageDTO.setFiles(new ArrayList<>());
|
|
|
+
|
|
|
+ String param = new Gson().toJson(difyChatMessageDTO);
|
|
|
+ RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
|
|
|
+ Request request = this.getChatMessageRequest(requestBody);
|
|
|
+ return Flux.create(emitter -> {
|
|
|
+ client.newCall(request).enqueue(new Callback() {
|
|
|
+ @Override
|
|
|
+ public void onFailure(Call call, IOException e) {
|
|
|
+ emitter.error(e);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onResponse(Call call, Response response) throws IOException {
|
|
|
+ if (!response.isSuccessful()) {
|
|
|
+ emitter.error(new IOException("Unexpected code: " + response));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try (Reader reader = response.body().charStream()) {
|
|
|
+ BufferedReader bufferedReader = new BufferedReader(reader);
|
|
|
+ String line;
|
|
|
+ String temConversationId2 = temConversationId;
|
|
|
+ String prefixToRemove = "data: ";
|
|
|
+ while ((line = bufferedReader.readLine()) != null) {
|
|
|
+ if (line.isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (line.startsWith(prefixToRemove)) {
|
|
|
+ line = line.substring(prefixToRemove.length());
|
|
|
+ }
|
|
|
+ if (temConversationId2 == null) {
|
|
|
+ try {
|
|
|
+ JSONObject jsonObject = JSON.parseObject(line);
|
|
|
+ temConversationId2 = jsonObject.get("conversation_id").toString();
|
|
|
+ difySessionService.addDifySession(projectId, userId, temConversationId2);
|
|
|
+ } catch (Exception e) {
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ emitter.next(line); // 将每行数据发送到 Flux
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ emitter.error(e);
|
|
|
+ } finally {
|
|
|
+ emitter.complete();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public String getInventPoint(Integer projectId) {
|
|
|
+ String re = "";
|
|
|
+ TechnicalCase technicalCase = technicalCaseService.getByProjectId(projectId);
|
|
|
+ if (technicalCase != null) {
|
|
|
+ if (technicalCase.getInventionPoint() != null) {
|
|
|
+ re = technicalCase.getInventionPoint();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return re;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String getConfression(Integer projectId) {
|
|
|
+ String url = "";
|
|
|
+ AssoProjectConfession assoProjectConfession = assoProjectConfessionService.queryAssoProjectConfession(projectId);
|
|
|
+ if (assoProjectConfession != null) {
|
|
|
+ url = fileDownloadUrl + assoProjectConfession.getFileGuid();
|
|
|
+ }
|
|
|
+
|
|
|
+ return url;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Request getChatMessageRequest(RequestBody requestBody) {
|
|
|
+ Request request = new Request.Builder()
|
|
|
+ .url(url + "chat-messages")
|
|
|
+ .addHeader("Authorization", "Bearer " + apiKey).addHeader(HttpHeaders.CONTENT_TYPE, "application/json")
|
|
|
+ .post(requestBody)
|
|
|
+ .build();
|
|
|
+ return request;
|
|
|
+ }
|
|
|
+
|
|
|
+ public JSONObject stopMessage(String taskId) throws IOException {
|
|
|
+ OkHttpClient client = new OkHttpClient.Builder()
|
|
|
+ .connectTimeout(60, TimeUnit.SECONDS)
|
|
|
+ .writeTimeout(60, TimeUnit.SECONDS)
|
|
|
+ .readTimeout(60, TimeUnit.SECONDS)
|
|
|
+ .build();
|
|
|
+ DifyChatMessageDTO difyChatMessageDTO = new DifyChatMessageDTO();
|
|
|
+ difyChatMessageDTO.setUser("1");
|
|
|
+ String param = new Gson().toJson(difyChatMessageDTO);
|
|
|
+ RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
|
|
|
+ Request request = new Request.Builder()
|
|
|
+ .url(url + "chat-messages/" + taskId + "/stop")
|
|
|
+ .addHeader("Authorization", "Bearer " + apiKey).addHeader(HttpHeaders.CONTENT_TYPE, "application/json")
|
|
|
+ .post(requestBody)
|
|
|
+ .build();
|
|
|
+ String json = Objects.requireNonNull(client.newCall(request).execute().body()).string();
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(json);
|
|
|
+ return jsonObject;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public Map<String, Object> generateInventionPoint(ChatMessageDTO chatMessageDTO) throws IOException {
|
|
|
+ Integer projectId = chatMessageDTO.getProjectId();
|
|
|
+ String query = "生成发明点";
|
|
|
+ String userId = "1";
|
|
|
+ String conversationId = chatMessageDTO.getConversationId();
|
|
|
+ DifyChatMessageDTO difyChatMessageDTO = new DifyChatMessageDTO();
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+ String fileContent = this.getConfression(projectId);
|
|
|
+ map.put("file_path", fileContent);
|
|
|
+ difyChatMessageDTO.setInputs(map);
|
|
|
+ difyChatMessageDTO.setConversationId(conversationId);
|
|
|
+ difyChatMessageDTO.setResponseMode("blocking");
|
|
|
+ difyChatMessageDTO.setUser(userId);
|
|
|
+ difyChatMessageDTO.setQuery(query);
|
|
|
+ difyChatMessageDTO.setFiles(new ArrayList<>());
|
|
|
+
|
|
|
+
|
|
|
+ OkHttpClient client = new OkHttpClient.Builder()
|
|
|
+ .connectTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .writeTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .readTimeout(600, TimeUnit.SECONDS)
|
|
|
+ .build();
|
|
|
+ String param = new Gson().toJson(difyChatMessageDTO);
|
|
|
+ RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), param);
|
|
|
+ Request request = this.getChatMessageRequest(requestBody);
|
|
|
+ String res = Objects.requireNonNull(client.newCall(request).execute().body()).string();
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(res);
|
|
|
+ String inventionPoint = jsonObject.get("answer").toString();
|
|
|
+ inventionPoint = DataUtils.getMarkDownText(inventionPoint);
|
|
|
+ if (conversationId == null) {
|
|
|
+ conversationId = jsonObject.get("conversation_id").toString();
|
|
|
+ difySessionService.addDifySession(projectId, userId, conversationId);
|
|
|
+ }
|
|
|
+ Map<String, Object> map1 = new HashMap<>();
|
|
|
+ map1.put("invention_point", inventionPoint);
|
|
|
+ technicalCaseService.updateInventionPoint(projectId, inventionPoint);
|
|
|
+ map1.put("conversation_id", conversationId);
|
|
|
+ return map1;
|
|
|
+ }
|
|
|
+}
|