Compare commits

...

6 Commits

Author SHA1 Message Date
liu.zixi
8a3899dfd1 fix: 日志转储 2025-11-25 17:46:42 +08:00
liu.zixi
c17a594393 fix: 解决报错 2025-11-25 16:52:11 +08:00
liu.zixi
09d61ceb9d fix: 完善错误信息提示的处理方式 2025-11-25 16:51:16 +08:00
liu.zixi
106fde8e6b fix: 报错时也记录 2025-11-25 14:03:53 +08:00
liu.zixi
3bf0534d77 fix: 修复ES数据类型解析的问题 2025-11-25 13:30:41 +08:00
liu.zixi
dd0e10539f fix: 修复下载excel接口入参问题 2025-11-25 12:09:32 +08:00
7 changed files with 57 additions and 41 deletions

View File

@@ -18,6 +18,7 @@ import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
/** /**
@@ -105,8 +106,9 @@ public class CaseAiChatApi extends ApiBaseController {
public void downloadConversationExcel(@RequestParam String startTime, public void downloadConversationExcel(@RequestParam String startTime,
@RequestParam String endTime, @RequestParam String endTime,
HttpServletResponse response) { HttpServletResponse response) {
LocalDate startDate = LocalDate.parse(startTime); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate endDate = LocalDate.parse(endTime); LocalDate startDate = LocalDate.parse(startTime, formatter);
LocalDate endDate = LocalDate.parse(endTime, formatter);
caseAiChatService.getConversationExcel(startDate.atStartOfDay(), endDate.atTime(23, 59, 59), response); caseAiChatService.getConversationExcel(startDate.atStartOfDay(), endDate.atTime(23, 59, 59), response);
} }

View File

@@ -22,7 +22,7 @@ import java.util.concurrent.TimeUnit;
@EnableConfigurationProperties({CaseAiProperties.class}) @EnableConfigurationProperties({CaseAiProperties.class})
@Service @Service
@Slf4j @Slf4j(topic = "caseAiChatLogger")
public class AiAccessTokenServiceImpl implements IAiAccessTokenService { public class AiAccessTokenServiceImpl implements IAiAccessTokenService {
private static final String ACCESS_TOKEN_CACHE_KEY = "case_ai_access_token"; private static final String ACCESS_TOKEN_CACHE_KEY = "case_ai_access_token";

View File

@@ -122,7 +122,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
conversationId = getOrCreateConversationId(caseAiChatDto, currentUser); conversationId = getOrCreateConversationId(caseAiChatDto, currentUser);
} catch (Exception e) { } catch (Exception e) {
log.error("获取会话ID失败", e); log.error("获取会话ID失败", e);
errMessage(sseEmitter, SYS_ERR_MSG); errMessage(sseEmitter, null, SYS_ERR_MSG);
sseEmitter.complete(); sseEmitter.complete();
return sseEmitter; return sseEmitter;
} }
@@ -132,6 +132,13 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
// 3. 构建请求参数 // 3. 构建请求参数
String userId = currentUser.getCode(); String userId = currentUser.getCode();
// 6. 用于收集对话数据的容器
AiChatConversationData conversationData = new AiChatConversationData();
conversationData.setQuery(caseAiChatDto.getQuery());
conversationData.setConversationId(conversationId);
conversationData.setUserId(userId);
String kId = caseAiProperties.getCaseKnowledgeId(); String kId = caseAiProperties.getCaseKnowledgeId();
JSONObject chatParam = new JSONObject(); JSONObject chatParam = new JSONObject();
chatParam.put("userId", userId); chatParam.put("userId", userId);
@@ -162,9 +169,18 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
String accessToken; String accessToken;
try { try {
accessToken = aiAccessTokenService.getAccessToken(); accessToken = aiAccessTokenService.getAccessToken();
if (org.apache.commons.lang3.StringUtils.isBlank(accessToken)) {
errMessage(sseEmitter, conversationId, SYS_ERR_MSG);
sseEmitter.complete();
conversationData.appendAnswer(SYS_ERR_MSG);
elasticSearchIndexService.createData(conversationData);
return sseEmitter;
}
} catch (Exception e) { } catch (Exception e) {
log.error("获取access_token失败", e); log.error("获取access_token失败", e);
errMessage(sseEmitter, SYS_ERR_MSG); errMessage(sseEmitter, conversationId, SYS_ERR_MSG);
conversationData.appendAnswer(SYS_ERR_MSG);
elasticSearchIndexService.createData(conversationData);
sseEmitter.complete(); sseEmitter.complete();
return sseEmitter; return sseEmitter;
} }
@@ -177,13 +193,6 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
builder.post(bodyRequestBody); builder.post(bodyRequestBody);
Request request = builder.build(); Request request = builder.build();
// 6. 用于收集对话数据的容器
AiChatConversationData conversationData = new AiChatConversationData();
conversationData.setQuery(caseAiChatDto.getQuery());
conversationData.setConversationId(conversationId);
conversationData.setUserId(userId);
// 7. 创建事件监听器 // 7. 创建事件监听器
EventSourceListener listener = new EventSourceListener() { EventSourceListener listener = new EventSourceListener() {
@Override @Override
@@ -236,7 +245,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
} else { } else {
// 异常问题取message内容 // 异常问题取message内容
String message = jsonData.getString("message"); String message = jsonData.getString("message");
errMessage(sseEmitter, message); errMessage(sseEmitter, conversationId, message);
return; return;
} }
} }
@@ -265,12 +274,13 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
log.error("调用接口 [{}] 接口异常", request.url(), e); log.error("调用接口 [{}] 接口异常", request.url(), e);
if (isTimeoutException(e)) { if (isTimeoutException(e)) {
log.warn("接口调用超时conversationId: {}", conversationId); log.warn("接口调用超时conversationId: {}", conversationId);
errMessage(sseEmitter, SYS_ERR_MSG); errMessage(sseEmitter, conversationId, SYS_ERR_MSG);
sseEmitter.complete(); sseEmitter.complete();
// 从Map中移除失败的会话 // 从Map中移除失败的会话
conversationEventSourceMap.remove(conversationId); conversationEventSourceMap.remove(conversationId);
// 即使失败也要将已有的对话数据保存到ES // 即使失败也要将已有的对话数据保存到ES
conversationData.appendAnswer(SYS_ERR_MSG);
elasticSearchIndexService.createData(conversationData); elasticSearchIndexService.createData(conversationData);
return; return;
} }
@@ -282,16 +292,17 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
// 从Map中移除失败的会话 // 从Map中移除失败的会话
conversationEventSourceMap.remove(conversationId); conversationEventSourceMap.remove(conversationId);
// 即使失败也要将已有的对话数据保存到ES // 即使失败也要将已有的对话数据保存到ES
conversationData.appendAnswer(SYS_ERR_MSG);
elasticSearchIndexService.createData(conversationData); elasticSearchIndexService.createData(conversationData);
return; return;
} }
sseEmitter.completeWithError(e);
// 从Map中移除失败的会话 // 从Map中移除失败的会话
conversationEventSourceMap.remove(conversationId); conversationEventSourceMap.remove(conversationId);
// 即使失败也要将已有的对话数据保存到ES // 即使失败也要将已有的对话数据保存到ES
elasticSearchIndexService.createData(conversationData); elasticSearchIndexService.createData(conversationData);
sseEmitter.completeWithError(e);
} }
}; };
@@ -663,7 +674,7 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
// 将响应内容原封不动地推送到 SseEmitter // 将响应内容原封不动地推送到 SseEmitter
JSONObject responseData = JSONObject.parseObject(responseBody); JSONObject responseData = JSONObject.parseObject(responseBody);
if (responseBody.contains("message")) { if (responseBody.contains("message")) {
errMessage(sseEmitter, responseData.getString("message")); errMessage(sseEmitter, conversationData.getConversationId(), responseData.getString("message"));
sseEmitter.complete(); sseEmitter.complete();
return; return;
} }
@@ -679,12 +690,23 @@ public class CaseAiChatServiceImpl implements ICaseAiChatService {
} }
} }
private void errMessage(SseEmitter sseEmitter, String message) { private void errMessage(SseEmitter sseEmitter, String conversationId, String message) {
JSONObject conversationData = new JSONObject();
conversationData.put("conversationId", conversationId);
conversationData.put("content", "");
conversationData.put("status", 0);
JSONObject jsonData = new JSONObject(); JSONObject jsonData = new JSONObject();
jsonData.put("status", 1); jsonData.put("status", 1);
jsonData.put("content", message); jsonData.put("content", message);
JSONObject finishData = new JSONObject();
jsonData.put("status", 4);
jsonData.put("content", "");
try { try {
sseEmitter.send(conversationData.toJSONString());
sseEmitter.send(jsonData.toJSONString()); sseEmitter.send(jsonData.toJSONString());
sseEmitter.send(finishData.toJSONString());
} catch (IOException e) { } catch (IOException e) {
log.error("发送错误信息异常", e); log.error("发送错误信息异常", e);
sseEmitter.completeWithError(e); sseEmitter.completeWithError(e);

View File

@@ -216,7 +216,7 @@ public class ElasticSearchIndexServiceImpl implements IElasticSearchIndexService
messageVo.setStartTime(LocalDateTime.parse(startTimeStr)); messageVo.setStartTime(LocalDateTime.parse(startTimeStr));
} }
if (sourceMap.containsKey("durationSeconds")) { if (sourceMap.containsKey("durationSeconds")) {
messageVo.setDurationSeconds((Long) sourceMap.get("durationSeconds")); messageVo.setDurationSeconds((Integer) sourceMap.get("durationSeconds"));
} }
// 解析 suggestions // 解析 suggestions

View File

@@ -29,7 +29,7 @@ public class CaseAiMessageVo {
/** /**
* 会话时长(秒) * 会话时长(秒)
*/ */
private Long durationSeconds; private Integer durationSeconds;
/** /**
* 案例引用列表 * 案例引用列表

View File

@@ -31,20 +31,16 @@
</encoder> </encoder>
</appender> </appender>
<!-- Log file error output --> <appender name="caseAiChat"
<appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender"> class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder> <encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern> <pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder> </encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <File>${log.path}/caseAiChat.log</File>
<level>ERROR</level> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
</filter> <FileNamePattern>${log.path}/caseAiChat.%d{yyyy-MM-dd}.log</FileNamePattern>
</rollingPolicy>
</appender> </appender>
<!-- Log file error output --> <!-- Log file error output -->

View File

@@ -47,20 +47,16 @@
</filter> </filter>
</appender> </appender>
<!-- Log file error output --> <appender name="caseAiChat"
<appender name="caseAiChat" class="ch.qos.logback.core.rolling.RollingFileAppender"> class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/caseAiChat.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${log.path}/%d{yyyy-MM}/caseAiChat.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder> <encoder>
<pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern> <pattern>%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder> </encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <File>${log.path}/caseAiChat.log</File>
<level>ERROR</level> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
</filter> <FileNamePattern>${log.path}/caseAiChat.%d{yyyy-MM-dd}.log</FileNamePattern>
</rollingPolicy>
</appender> </appender>
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 --> <!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->