|
@@ -23,127 +23,6 @@ public class DifyServiceImpl implements IDifyService {
|
|
|
.writeTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
|
|
.writeTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
|
|
|
.build();
|
|
.build();
|
|
|
|
|
|
|
|
- public Map<String, String> callWorkflow(String userMessage, Map<String, Object> inputs, Long userId, String conversationId) {
|
|
|
|
|
- try {
|
|
|
|
|
- log.info("调用 Dify 工作流 - userId: {}, conversationId: {}, message: {}", userId, conversationId, userMessage);
|
|
|
|
|
-
|
|
|
|
|
- // 构建请求体
|
|
|
|
|
- JSONObject requestBody = new JSONObject();
|
|
|
|
|
- requestBody.set("inputs", inputs);
|
|
|
|
|
- requestBody.set("query", userMessage);
|
|
|
|
|
- requestBody.set("response_mode", "streaming");
|
|
|
|
|
- requestBody.set("user", "user-" + userId);
|
|
|
|
|
-
|
|
|
|
|
- // 如果有对话ID,添加到请求中以支持上下文回顾
|
|
|
|
|
- if (conversationId != null && !conversationId.isEmpty()) {
|
|
|
|
|
- requestBody.set("conversation_id", conversationId);
|
|
|
|
|
- log.info("添加 conversation_id 到请求: {}", conversationId);
|
|
|
|
|
- } else {
|
|
|
|
|
- log.info("conversationId 为空,这是首次对话");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- log.info("Dify API 请求体: {}", requestBody.toString());
|
|
|
|
|
-
|
|
|
|
|
- // 发送请求
|
|
|
|
|
- Request request = new Request.Builder()
|
|
|
|
|
- .url(difyConfig.getApiUrl() + "/chat-messages")
|
|
|
|
|
- .post(RequestBody.create(
|
|
|
|
|
- requestBody.toString(),
|
|
|
|
|
- MediaType.parse("application/json")))
|
|
|
|
|
- .addHeader("Authorization", "Bearer " + difyConfig.getApiKey())
|
|
|
|
|
- .addHeader("Content-Type", "application/json")
|
|
|
|
|
- .build();
|
|
|
|
|
-
|
|
|
|
|
- // 使用 try-with-resources 确保 response 被正确关闭
|
|
|
|
|
- try (Response response = httpClient.newCall(request).execute()) {
|
|
|
|
|
- // 处理流式响应
|
|
|
|
|
- StringBuilder fullAnswer = new StringBuilder();
|
|
|
|
|
- String newConversationId = null;
|
|
|
|
|
- String ttsVcn = null;
|
|
|
|
|
-
|
|
|
|
|
- try (ResponseBody responseBody = response.body()) {
|
|
|
|
|
- if (responseBody == null) {
|
|
|
|
|
- throw new RuntimeException("响应体为空");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 逐行读取 SSE 流
|
|
|
|
|
- java.io.BufferedReader reader = new java.io.BufferedReader(
|
|
|
|
|
- new java.io.InputStreamReader(responseBody.byteStream(), java.nio.charset.StandardCharsets.UTF_8)
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- String line;
|
|
|
|
|
- while ((line = reader.readLine()) != null) {
|
|
|
|
|
- // SSE 格式: data: {...}
|
|
|
|
|
- if (line.startsWith("data: ")) {
|
|
|
|
|
- String jsonData = line.substring(6); // 去掉 "data: " 前缀
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- JSONObject event = new JSONObject(jsonData);
|
|
|
|
|
- String eventType = event.getStr("event");
|
|
|
|
|
-
|
|
|
|
|
- if ("message".equals(eventType)) {
|
|
|
|
|
- // 累积回复文本
|
|
|
|
|
- String answer = event.getStr("answer");
|
|
|
|
|
- if (answer != null) {
|
|
|
|
|
- fullAnswer.append(answer);
|
|
|
|
|
- }
|
|
|
|
|
- } else if ("message_end".equals(eventType)) {
|
|
|
|
|
- // 最后一个事件,获取 conversation_id
|
|
|
|
|
- newConversationId = event.getStr("conversation_id");
|
|
|
|
|
-
|
|
|
|
|
- // 从 metadata 中获取 outputs
|
|
|
|
|
- if (event.containsKey("metadata")) {
|
|
|
|
|
- JSONObject metadata = event.getJSONObject("metadata");
|
|
|
|
|
- if (metadata != null && metadata.containsKey("outputs")) {
|
|
|
|
|
- JSONObject outputs = metadata.getJSONObject("outputs");
|
|
|
|
|
- if (outputs != null) {
|
|
|
|
|
- ttsVcn = outputs.getStr("ttsVcn");
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } else if ("error".equals(eventType)) {
|
|
|
|
|
- String errorMessage = event.getStr("message");
|
|
|
|
|
- log.error("Dify API 返回错误: {}", errorMessage);
|
|
|
|
|
- throw new RuntimeException("Dify API 错误: " + errorMessage);
|
|
|
|
|
- }
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.warn("解析 SSE 事件失败: {}", line, e);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- Map<String, String> aiResponse = new HashMap<>();
|
|
|
|
|
-
|
|
|
|
|
- String replyText = fullAnswer.toString();
|
|
|
|
|
- if (replyText.isEmpty()) {
|
|
|
|
|
- log.error("Dify API 未返回任何回复文本");
|
|
|
|
|
- throw new RuntimeException("Dify API 响应格式错误");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- aiResponse.put("replyText", replyText);
|
|
|
|
|
-
|
|
|
|
|
- // 如果AI没有返回发言人,使用客服配置中的默认发言人
|
|
|
|
|
- if (ttsVcn == null) {
|
|
|
|
|
- ttsVcn = inputs.get("currentVcn") != null ? inputs.get("currentVcn").toString() : "x4_yezi";
|
|
|
|
|
- }
|
|
|
|
|
- aiResponse.put("ttsVcn", ttsVcn);
|
|
|
|
|
-
|
|
|
|
|
- // 返回对话ID以便前端保存,用于下次请求
|
|
|
|
|
- if (newConversationId != null) {
|
|
|
|
|
- aiResponse.put("conversationId", newConversationId);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- log.info("Dify 流式响应处理完成,回复长度: {}", replyText.length());
|
|
|
|
|
-
|
|
|
|
|
- return aiResponse;
|
|
|
|
|
- } // 关闭 try (Response response = ...)
|
|
|
|
|
- } catch (Exception e) {
|
|
|
|
|
- log.error("调用 Dify 工作流失败", e);
|
|
|
|
|
- throw new RuntimeException("AI 服务调用失败", e);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void callWorkflowStream(String userMessage, String agentGender,
|
|
public void callWorkflowStream(String userMessage, String agentGender,
|
|
|
java.util.List<java.util.Map<String, String>> ttsVcnList,
|
|
java.util.List<java.util.Map<String, String>> ttsVcnList,
|