优化CozeAPI调用记录保存逻辑

- 修复CozeApiCall记录中createBy和updateBy字段未正确设置的问题
- 修复messageId字段未保存的问题
- 重构AiChatServiceImpl,在用户消息创建后再创建API调用记录
- 添加updateApiCallFailure方法处理失败情况
- 提取executeCozeApiCall公共方法减少代码重复
- 确保所有API调用记录都正确保存创建人和更新人信息
- 优化前端聊天记录功能,修复API调用问题
- 重构WebSocketService为接口+实现类模式
- 移除Controller层违反规则的try-catch异常处理
- 优化前端聊天界面自动滚动功能
This commit is contained in:
2025-07-25 18:11:05 +08:00
parent b1f8aa175d
commit 08bbd4df0f
2 changed files with 120 additions and 67 deletions
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -109,10 +109,7 @@ public class AiChatServiceImpl implements AiChatService {
log.info("发送聊天消息: conversationId={}, userId={}, message={}", conversationId, userId, message);
try {
// 调用Coze API
String aiReply = sendMessage(conversationId, message, userId);
// 保存用户消息
// 先保存用户消息
Message userMessage = new Message();
userMessage.setConversationId(conversationId);
userMessage.setCreateBy(userId);
@@ -121,6 +118,9 @@ public class AiChatServiceImpl implements AiChatService {
userMessage.setSender("user");
userMessage = messageService.createMessage(userMessage);
// 调用Coze API(传入messageId
String aiReply = sendMessageWithMessageId(conversationId, userMessage.getId(), message, userId);
// 保存AI回复
Message aiMessage = new Message();
aiMessage.setConversationId(conversationId);
@@ -214,73 +214,97 @@ public class AiChatServiceImpl implements AiChatService {
}
}
/**
* 发送消息到Coze AI(带messageId
*/
private String sendMessageWithMessageId(String conversationId, String messageId, String userMessage, String userId) {
log.info("发送消息到Coze AI: conversationId={}, messageId={}, userId={}", conversationId, messageId, userId);
// 创建API调用记录(包含messageId
CozeApiCall apiCall = createApiCallRecord(conversationId, messageId, userMessage, userId, "chat");
try {
return executeCozeApiCall(apiCall, conversationId, userMessage, userId);
} catch (Exception e) {
log.error("发送消息失败", e);
updateApiCallFailure(apiCall, e.getMessage());
return "抱歉,AI服务暂时不可用,请稍后再试。";
}
}
@Override
public String sendMessage(String conversationId, String userMessage, String userId) {
log.info("发送消息到Coze AI: conversationId={}, userId={}", conversationId, userId);
// 创建API调用记录
CozeApiCall apiCall = createApiCallRecord(conversationId, userMessage, userId, "chat");
// 创建API调用记录(不包含messageId,用于向后兼容)
CozeApiCall apiCall = createApiCallRecord(conversationId, null, userMessage, userId, "chat");
try {
// 构建请求头
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + cozeApiToken);
headers.set("Content-Type", "application/json");
// 构建请求体 - 使用正确的Coze API格式
Map<String, Object> requestBody = buildCozeRequest(conversationId, userMessage, userId);
// 更新API调用记录的请求信息
updateApiCallRequest(apiCall, cozeBaseUrl + chatPath, requestBody, headers);
HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
// 构建完整的API URL
String cozeApiUrl = cozeBaseUrl + chatPath;
log.info("发送Coze请求到: {}, 请求体: {}", cozeApiUrl, requestBody);
// 发送请求
ResponseEntity<String> response = restTemplate.exchange(
cozeApiUrl,
HttpMethod.POST,
request,
String.class);
log.info("收到Coze初始响应: {}", response.getBody());
// 更新API调用记录的响应信息
updateApiCallResponse(apiCall, response);
// 解析响应获取chat_id和conversation_id
JSONObject responseJson = JSON.parseObject(response.getBody());
String chatId = extractChatIdFromResponse(responseJson);
String cozeConversationId = extractConversationIdFromResponse(responseJson);
if (chatId != null && cozeConversationId != null) {
// 更新API调用记录的Coze ID信息
updateApiCallCozeIds(apiCall, chatId, cozeConversationId);
// 轮询聊天状态直到完成并获取回复内容
String aiReply = waitForChatCompletionWithTracking(chatId, cozeConversationId, apiCall);
log.info("Coze AI响应成功: reply={}", aiReply);
// 更新API调用记录的最终结果
updateApiCallSuccess(apiCall, aiReply);
return aiReply;
} else {
log.error("无法从Coze响应中获取chat_id或conversation_id");
updateApiCallError(apiCall, "INVALID_RESPONSE", "无法从Coze响应中获取chat_id或conversation_id");
return "抱歉,AI服务响应异常,请稍后再试。";
}
return executeCozeApiCall(apiCall, conversationId, userMessage, userId);
} catch (Exception e) {
log.error("发送消息到Coze AI失败", e);
updateApiCallError(apiCall, "REQUEST_FAILED", e.getMessage());
log.error("发送消息失败", e);
updateApiCallFailure(apiCall, e.getMessage());
return "抱歉,AI服务暂时不可用,请稍后再试。";
}
}
/**
* 执行Coze API调用的公共逻辑
*/
private String executeCozeApiCall(CozeApiCall apiCall, String conversationId, String userMessage, String userId) {
// 构建请求头
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + cozeApiToken);
headers.set("Content-Type", "application/json");
// 构建请求体 - 使用正确的Coze API格式
Map<String, Object> requestBody = buildCozeRequest(conversationId, userMessage, userId);
// 更新API调用记录的请求信息
updateApiCallRequest(apiCall, cozeBaseUrl + chatPath, requestBody, headers);
HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
// 构建完整的API URL
String cozeApiUrl = cozeBaseUrl + chatPath;
log.info("发送Coze请求到: {}, 请求体: {}", cozeApiUrl, requestBody);
// 发送请求
ResponseEntity<String> response = restTemplate.exchange(
cozeApiUrl,
HttpMethod.POST,
request,
String.class);
log.info("收到Coze初始响应: {}", response.getBody());
// 更新API调用记录的响应信息
updateApiCallResponse(apiCall, response);
// 解析响应获取chat_id和conversation_id
JSONObject responseJson = JSON.parseObject(response.getBody());
String chatId = extractChatIdFromResponse(responseJson);
String cozeConversationId = extractConversationIdFromResponse(responseJson);
if (chatId != null && cozeConversationId != null) {
// 更新API调用记录的Coze ID信息
updateApiCallCozeIds(apiCall, chatId, cozeConversationId);
// 轮询聊天状态直到完成并获取回复内容
String aiReply = waitForChatCompletionWithTracking(chatId, cozeConversationId, apiCall);
log.info("Coze AI响应成功: reply={}", aiReply);
// 更新API调用记录的最终结果
updateApiCallSuccess(apiCall, aiReply);
return aiReply;
} else {
log.error("无法从Coze响应中获取chat_id或conversation_id");
updateApiCallError(apiCall, "INVALID_RESPONSE", "无法从Coze响应中获取chat_id或conversation_id");
return "抱歉,AI服务响应异常,请稍后再试。";
}
}
@Override
public Map<String, Object> guestChat(String message, String clientIp) {
log.info("访客聊天: message={}, clientIp={}", message, clientIp);
@@ -616,8 +640,8 @@ public class AiChatServiceImpl implements AiChatService {
private String sendSummaryMessage(String conversationId, String userMessage, String userId) {
log.info("发送总结消息到Coze AI: conversationId={}, userId={}", conversationId, userId);
// 创建API调用记录
CozeApiCall apiCall = createSummaryApiCallRecord(conversationId, userMessage, userId, "summary");
// 创建API调用记录(总结不需要messageId
CozeApiCall apiCall = createSummaryApiCallRecord(conversationId, null, userMessage, userId, "summary");
try {
// 构建请求头
@@ -732,9 +756,10 @@ public class AiChatServiceImpl implements AiChatService {
/**
* 创建API调用记录
*/
private CozeApiCall createApiCallRecord(String conversationId, String userMessage, String userId, String requestType) {
private CozeApiCall createApiCallRecord(String conversationId, String messageId, String userMessage, String userId, String requestType) {
CozeApiCall apiCall = CozeApiCall.builder()
.conversationId(conversationId)
.messageId(messageId) // 设置messageId
.userId(userId)
.requestType(requestType)
.userMessage(userMessage)
@@ -744,6 +769,8 @@ public class AiChatServiceImpl implements AiChatService {
.status("pending")
.startTime(LocalDateTime.now())
.traceId(UUID.randomUUID().toString())
.createBy(userId) // 设置创建人为当前用户
.updateBy(userId) // 设置更新人为当前用户
.build();
// 获取客户端信息
@@ -760,7 +787,7 @@ public class AiChatServiceImpl implements AiChatService {
// 保存API调用记录
cozeApiCallService.save(apiCall);
log.info("创建API调用记录: id={}, traceId={}", apiCall.getId(), apiCall.getTraceId());
log.info("创建API调用记录: id={}, messageId={}, traceId={}", apiCall.getId(), messageId, apiCall.getTraceId());
return apiCall;
}
@@ -768,9 +795,10 @@ public class AiChatServiceImpl implements AiChatService {
/**
* 创建总结API调用记录
*/
private CozeApiCall createSummaryApiCallRecord(String conversationId, String userMessage, String userId, String requestType) {
private CozeApiCall createSummaryApiCallRecord(String conversationId, String messageId, String userMessage, String userId, String requestType) {
CozeApiCall apiCall = CozeApiCall.builder()
.conversationId(conversationId)
.messageId(messageId) // 设置messageId
.userId(userId)
.requestType(requestType)
.userMessage(userMessage)
@@ -780,6 +808,8 @@ public class AiChatServiceImpl implements AiChatService {
.status("pending")
.startTime(LocalDateTime.now())
.traceId(UUID.randomUUID().toString())
.createBy(userId) // 设置创建人为当前用户
.updateBy(userId) // 设置更新人为当前用户
.build();
// 获取客户端信息
@@ -796,7 +826,7 @@ public class AiChatServiceImpl implements AiChatService {
// 保存API调用记录
cozeApiCallService.save(apiCall);
log.info("创建总结API调用记录: id={}, traceId={}", apiCall.getId(), apiCall.getTraceId());
log.info("创建总结API调用记录: id={}, messageId={}, traceId={}", apiCall.getId(), messageId, apiCall.getTraceId());
return apiCall;
}
@@ -856,6 +886,7 @@ public class AiChatServiceImpl implements AiChatService {
apiCall.setFinalStatus("completed");
apiCall.setEndTime(endTime);
apiCall.setDurationMs((int) durationMs);
apiCall.setUpdateBy(apiCall.getUserId()); // 设置更新人
cozeApiCallService.updateById(apiCall);
log.info("API调用成功: id={}, duration={}ms", apiCall.getId(), durationMs);
@@ -864,6 +895,28 @@ public class AiChatServiceImpl implements AiChatService {
}
}
/**
* 更新API调用记录的失败结果
*/
private void updateApiCallFailure(CozeApiCall apiCall, String errorMessage) {
try {
LocalDateTime endTime = LocalDateTime.now();
long durationMs = java.time.Duration.between(apiCall.getStartTime(), endTime).toMillis();
apiCall.setStatus("failed");
apiCall.setFinalStatus("failed");
apiCall.setEndTime(endTime);
apiCall.setDurationMs((int) durationMs);
apiCall.setErrorMessage(errorMessage);
apiCall.setUpdateBy(apiCall.getUserId()); // 设置更新人
cozeApiCallService.updateById(apiCall);
log.info("API调用失败: id={}, duration={}ms, error={}", apiCall.getId(), durationMs, errorMessage);
} catch (Exception e) {
log.error("更新API调用记录失败结果失败: {}", e.getMessage(), e);
}
}
/**
* 更新API调用记录的错误信息
*/