@@ -0,0 +1,189 @@
package com.rj.service.biz ;
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 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} " )
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 ) ;
}
}