190 lines
7.5 KiB
Java
190 lines
7.5 KiB
Java
package com.rj.service.biz.impl;
|
||
|
||
|
||
|
||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||
import com.fasterxml.jackson.databind.JsonNode;
|
||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||
import com.rj.controller.biz.dto.ConsultingScenarioRequest;
|
||
import com.rj.entity.bz.ConsultingScenario;
|
||
import com.rj.mapper.biz.ConsultingScenarioMapper;
|
||
import com.rj.service.biz.IConsultingScenarioService;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.springframework.beans.factory.annotation.Value;
|
||
import org.springframework.http.*;
|
||
import org.springframework.stereotype.Service;
|
||
import org.springframework.web.client.RestTemplate;
|
||
|
||
import java.util.HashMap;
|
||
import java.util.Map;
|
||
import java.util.UUID;
|
||
import java.util.Iterator;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
import java.time.LocalDateTime;
|
||
|
||
/**
|
||
* Author: 李中华 wx: spllzh email(qq): 28668817@qq.com
|
||
* Date: 2025/9/2 19:56
|
||
**/
|
||
@Service
|
||
@Slf4j
|
||
public class ConsultingScenarioServiceImpl
|
||
extends ServiceImpl<ConsultingScenarioMapper, ConsultingScenario> implements IConsultingScenarioService {
|
||
|
||
// Dify API 配置
|
||
@Value("${dify.api.base-url}")
|
||
private String difyApiUrlBase;
|
||
|
||
@Value("${dify.api.workflow-endpoint-consultingScenar}")
|
||
private String difyApiUrlEndPoint;
|
||
|
||
@Value("${dify.api.apikey-consultingScenar}") //【AI】DCC用户问题分类提取
|
||
private String difyApiKey;
|
||
|
||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||
|
||
@Override
|
||
public Object processConsultingScenario(ConsultingScenarioRequest request) {
|
||
log.info("开始处理咨询场景请求: chat={}, businessType={}, sourceCorpusId={}, sourceCorpusTime={}",
|
||
request.getChat(), request.getBusinessType(), request.getSourceCorpusId(), request.getSourceCorpusTime());
|
||
|
||
try {
|
||
// 构造调用Dify工作流的请求
|
||
Map<String, Object> requestBody = new HashMap<>();
|
||
requestBody.put("inputs", Map.of(
|
||
"chat", request.getChat(),
|
||
// Dify 要求在 inputs 中提供 businessType
|
||
"businessType", request.getBusinessType(),
|
||
"sourceCorpusId", request.getSourceCorpusId(),
|
||
"sourceCorpusTime", request.getSourceCorpusTime()
|
||
));
|
||
requestBody.put("response_mode", "blocking");
|
||
requestBody.put("user", "api_user");
|
||
|
||
// 发起HTTP请求调用Dify工作流
|
||
RestTemplate restTemplate = new RestTemplate();
|
||
HttpHeaders headers = new HttpHeaders();
|
||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||
headers.set("Authorization", "Bearer " + difyApiKey);
|
||
|
||
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
|
||
String difyApiUrl = difyApiUrlBase + difyApiUrlEndPoint;
|
||
log.info("调用Dify工作流: url={}, requestBody={}", difyApiUrl, requestBody);
|
||
|
||
ResponseEntity<String> response = restTemplate.postForEntity(difyApiUrl, entity, String.class);
|
||
|
||
// 解析响应并打印到控制台
|
||
JsonNode jsonResponse = objectMapper.readTree(response.getBody());
|
||
log.info("Dify工作流响应结果: {}", jsonResponse.toPrettyString());
|
||
|
||
// 从响应中提取 outputs.text
|
||
JsonNode outputsNode = jsonResponse.path("data").path("outputs");
|
||
String textBlock = outputsNode.path("text").asText(null);
|
||
|
||
if (textBlock == null || textBlock.isEmpty()) {
|
||
log.warn("未在响应中找到 outputs.text,返回原始响应");
|
||
return jsonResponse;
|
||
}
|
||
|
||
// 提取代码块中的 JSON(优先 ```json ... ```,否则回退到最外层花括号)
|
||
String extractedJson = extractJsonString(textBlock);
|
||
if (extractedJson == null) {
|
||
log.warn("未能从文本中提取 JSON,返回原始响应");
|
||
return jsonResponse;
|
||
}
|
||
|
||
JsonNode parsedNode = objectMapper.readTree(extractedJson);
|
||
|
||
// 映射到实体并保存
|
||
com.rj.entity.bz.ConsultingScenario entityToSave = mapToEntity(parsedNode);
|
||
// 主键与时间戳
|
||
if (entityToSave.getId() == null || entityToSave.getId().isEmpty()) {
|
||
entityToSave.setId(UUID.randomUUID().toString());
|
||
}
|
||
entityToSave.setCreatedAt(LocalDateTime.now());
|
||
entityToSave.setUpdatedAt(LocalDateTime.now());
|
||
|
||
boolean saved = this.save(entityToSave);
|
||
log.info("ConsultingScenario 保存结果: {}", saved);
|
||
|
||
Map<String, Object> result = new HashMap<>();
|
||
result.put("saved", saved);
|
||
result.put("entity", entityToSave);
|
||
result.put("difyResponse", jsonResponse);
|
||
return result;
|
||
} catch (Exception e) {
|
||
log.error("调用Dify工作流时发生错误", e);
|
||
throw new RuntimeException("调用Dify工作流失败: " + e.getMessage(), e);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 从包含思考与代码块的文本中提取 JSON 字符串
|
||
*/
|
||
private String extractJsonString(String text) {
|
||
try {
|
||
String startFlag = "```json";
|
||
String fence = "```";
|
||
int start = text.indexOf(startFlag);
|
||
if (start >= 0) {
|
||
int jsonStart = start + startFlag.length();
|
||
int end = text.indexOf(fence, jsonStart);
|
||
if (end > jsonStart) {
|
||
return text.substring(jsonStart, end).trim();
|
||
}
|
||
}
|
||
// 回退方案:提取第一个 '{' 到最后一个 '}'
|
||
int firstBrace = text.indexOf('{');
|
||
int lastBrace = text.lastIndexOf('}');
|
||
if (firstBrace >= 0 && lastBrace > firstBrace) {
|
||
return text.substring(firstBrace, lastBrace + 1);
|
||
}
|
||
return null;
|
||
} catch (Exception e) {
|
||
log.warn("提取 JSON 文本失败", e);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 将解析后的 JSON 映射为 ConsultingScenario 实体
|
||
*/
|
||
private com.rj.entity.bz.ConsultingScenario mapToEntity(JsonNode root) {
|
||
com.rj.entity.bz.ConsultingScenario entity = new com.rj.entity.bz.ConsultingScenario();
|
||
|
||
// consultingScenario 主体
|
||
JsonNode cs = root.path("consultingScenario");
|
||
if (cs.isObject()) {
|
||
entity.setMainCategory(cs.path("mainCategory").asText(null));
|
||
entity.setSubCategory(cs.path("subCategory").asText(null));
|
||
entity.setConfidence(cs.path("confidence").asText(null));
|
||
}
|
||
|
||
entity.setUserDemand(root.path("userDemand").asText(null));
|
||
entity.setConsultingContent(joinArray(root.path("consultingContent")));
|
||
entity.setInvolvedVehicleModels(joinArray(root.path("involvedVehicleModels")));
|
||
entity.setKnowledgeGap(joinArray(root.path("knowledgeGap")));
|
||
entity.setPriority(root.path("priority").asText(null));
|
||
entity.setRemarks(root.path("remarks").asText(null));
|
||
|
||
return entity;
|
||
}
|
||
|
||
private String joinArray(JsonNode node) {
|
||
if (node == null || !node.isArray()) {
|
||
return null;
|
||
}
|
||
List<String> list = new ArrayList<>();
|
||
Iterator<JsonNode> it = node.elements();
|
||
while (it.hasNext()) {
|
||
JsonNode n = it.next();
|
||
if (n.isTextual()) {
|
||
list.add(n.asText());
|
||
} else {
|
||
list.add(n.toString());
|
||
}
|
||
}
|
||
return String.join("\n", list);
|
||
}
|
||
} |