mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/per-boe/java-servers.git
synced 2025-12-09 19:06:49 +08:00
Compare commits
6 Commits
fceb6ac805
...
8a3899dfd1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a3899dfd1 | ||
|
|
c17a594393 | ||
|
|
09d61ceb9d | ||
|
|
106fde8e6b | ||
|
|
3bf0534d77 | ||
|
|
dd0e10539f |
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public class CaseAiMessageVo {
|
|||||||
/**
|
/**
|
||||||
* 会话时长(秒)
|
* 会话时长(秒)
|
||||||
*/
|
*/
|
||||||
private Long durationSeconds;
|
private Integer durationSeconds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 案例引用列表
|
* 案例引用列表
|
||||||
|
|||||||
@@ -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 -->
|
||||||
|
|||||||
@@ -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 -->
|
||||||
|
|||||||
Reference in New Issue
Block a user