优化CozeAPI调用记录保存逻辑
- 修复CozeApiCall记录中createBy和updateBy字段未正确设置的问题 - 修复messageId字段未保存的问题 - 重构AiChatServiceImpl,在用户消息创建后再创建API调用记录 - 添加updateApiCallFailure方法处理失败情况 - 提取executeCozeApiCall公共方法减少代码重复 - 确保所有API调用记录都正确保存创建人和更新人信息 - 优化前端聊天记录功能,修复API调用问题 - 重构WebSocketService为接口+实现类模式 - 移除Controller层违反规则的try-catch异常处理 - 优化前端聊天界面自动滚动功能
This commit is contained in:
@@ -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调用记录的错误信息
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user