feat(MCA): TASK-033 删除旧 AiService 和 AiConfig
- 删除旧的 AiService 类 - 删除旧的 AiConfig 类 - 更新 MessageRouterServiceImpl 使用 AiServiceClient - 更新 DebugController 移除 AiService 引用 - 无编译错误
This commit is contained in:
parent
1fbdf4777a
commit
4b1fcf453f
|
|
@ -1,30 +0,0 @@
|
|||
package com.wecom.robot.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Data
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "ai")
|
||||
public class AiConfig {
|
||||
|
||||
private boolean enabled;
|
||||
private String provider;
|
||||
private DeepSeekConfig deepseek;
|
||||
private OpenAiConfig openai;
|
||||
|
||||
@Data
|
||||
public static class DeepSeekConfig {
|
||||
private String apiKey;
|
||||
private String baseUrl;
|
||||
private String model;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class OpenAiConfig {
|
||||
private String apiKey;
|
||||
private String baseUrl;
|
||||
private String model;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,7 @@ package com.wecom.robot.controller;
|
|||
|
||||
import com.wecom.robot.config.WecomConfig;
|
||||
import com.wecom.robot.dto.ApiResponse;
|
||||
import com.wecom.robot.dto.ChatCompletionRequest;
|
||||
import com.wecom.robot.entity.Message;
|
||||
import com.wecom.robot.service.AiService;
|
||||
import com.wecom.robot.service.SessionManagerService;
|
||||
import com.wecom.robot.util.WXBizMsgCrypt;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
|
@ -23,7 +21,6 @@ import java.util.Map;
|
|||
public class DebugController {
|
||||
|
||||
private final WecomConfig wecomConfig;
|
||||
private final AiService aiService;
|
||||
private final SessionManagerService sessionManagerService;
|
||||
|
||||
@GetMapping("/config")
|
||||
|
|
@ -108,38 +105,13 @@ public class DebugController {
|
|||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
@GetMapping("/ai/context")
|
||||
public ApiResponse<Map<String, Object>> getLastAiContext() {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
result.put("systemPrompt", aiService.getSystemPrompt());
|
||||
result.put("lastRequestJson", aiService.getLastRequestJson());
|
||||
result.put("lastConfidence", aiService.getLastConfidence());
|
||||
|
||||
List<ChatCompletionRequest.Message> messages = aiService.getLastRequestMessages();
|
||||
result.put("messageCount", messages.size());
|
||||
|
||||
List<Map<String, String>> messageList = new java.util.ArrayList<>();
|
||||
for (ChatCompletionRequest.Message msg : messages) {
|
||||
Map<String, String> msgMap = new HashMap<>();
|
||||
msgMap.put("role", msg.getRole());
|
||||
msgMap.put("content", msg.getContent());
|
||||
messageList.add(msgMap);
|
||||
}
|
||||
result.put("messages", messageList);
|
||||
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
@GetMapping("/ai/session/{sessionId}/context")
|
||||
public ApiResponse<Map<String, Object>> getSessionAiContext(
|
||||
@PathVariable String sessionId,
|
||||
@RequestParam(required = false, defaultValue = "测试消息") String testMessage) {
|
||||
@PathVariable String sessionId) {
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
result.put("sessionId", sessionId);
|
||||
result.put("systemPrompt", aiService.getSystemPrompt());
|
||||
|
||||
List<Message> history = sessionManagerService.getSessionMessages(sessionId);
|
||||
result.put("historyCount", history.size());
|
||||
|
|
@ -156,18 +128,6 @@ public class DebugController {
|
|||
}
|
||||
result.put("history", historyList);
|
||||
|
||||
List<ChatCompletionRequest.Message> contextMessages = aiService.buildMessagesForTest(history, testMessage);
|
||||
result.put("contextMessageCount", contextMessages.size());
|
||||
|
||||
List<Map<String, String>> contextList = new java.util.ArrayList<>();
|
||||
for (ChatCompletionRequest.Message msg : contextMessages) {
|
||||
Map<String, String> msgMap = new HashMap<>();
|
||||
msgMap.put("role", msg.getRole());
|
||||
msgMap.put("content", msg.getContent());
|
||||
contextList.add(msgMap);
|
||||
}
|
||||
result.put("contextMessages", contextList);
|
||||
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,155 +0,0 @@
|
|||
package com.wecom.robot.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.wecom.robot.config.AiConfig;
|
||||
import com.wecom.robot.dto.ChatCompletionRequest;
|
||||
import com.wecom.robot.dto.ChatCompletionResponse;
|
||||
import com.wecom.robot.entity.Message;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AiService {
|
||||
|
||||
private static final String SYSTEM_PROMPT = "你是ash超脑的客服,请用简洁、友好的语言回答客户的问题。" +
|
||||
"如果不确定答案,请诚实告知客户。" +
|
||||
"回答要准确、专业,避免过于冗长,要尽量拟人化口语化,自然回答问题。";
|
||||
|
||||
private final AiConfig aiConfig;
|
||||
private final RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
private double lastConfidence = 1.0;
|
||||
private List<ChatCompletionRequest.Message> lastRequestMessages = new ArrayList<>();
|
||||
private String lastRequestJson = "";
|
||||
|
||||
public String generateReply(String userMessage, List<Message> history) {
|
||||
if (!aiConfig.isEnabled()) {
|
||||
return "AI服务暂未开启,请联系人工客服。";
|
||||
}
|
||||
|
||||
try {
|
||||
String provider = aiConfig.getProvider();
|
||||
String apiUrl;
|
||||
String apiKey;
|
||||
String model;
|
||||
|
||||
if ("deepseek".equalsIgnoreCase(provider)) {
|
||||
apiUrl = aiConfig.getDeepseek().getBaseUrl() + "/chat/completions";
|
||||
apiKey = aiConfig.getDeepseek().getApiKey();
|
||||
model = aiConfig.getDeepseek().getModel();
|
||||
} else {
|
||||
apiUrl = aiConfig.getOpenai().getBaseUrl() + "/chat/completions";
|
||||
apiKey = aiConfig.getOpenai().getApiKey();
|
||||
model = aiConfig.getOpenai().getModel();
|
||||
}
|
||||
|
||||
List<ChatCompletionRequest.Message> messages = buildMessages(history, userMessage);
|
||||
ChatCompletionRequest request = ChatCompletionRequest.create(model, messages);
|
||||
|
||||
lastRequestMessages = messages;
|
||||
lastRequestJson = JSON.toJSONString(request, true);
|
||||
|
||||
log.info("===== AI请求上下文 =====");
|
||||
log.info("Provider: {}, Model: {}", provider, model);
|
||||
log.info("API URL: {}", apiUrl);
|
||||
log.info("消息数量: {}", messages.size());
|
||||
for (int i = 0; i < messages.size(); i++) {
|
||||
ChatCompletionRequest.Message msg = messages.get(i);
|
||||
log.info("[{}] {}: {}", i, msg.getRole(), msg.getContent());
|
||||
}
|
||||
log.info("===== 完整请求JSON =====");
|
||||
log.info("\n{}", lastRequestJson);
|
||||
log.info("========================");
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
headers.setBearerAuth(apiKey);
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(request), headers);
|
||||
ResponseEntity<String> response = restTemplate.postForEntity(apiUrl, entity, String.class);
|
||||
|
||||
log.info("===== AI响应 =====");
|
||||
log.info("Status: {}", response.getStatusCode());
|
||||
log.info("Body: {}", response.getBody());
|
||||
log.info("==================");
|
||||
|
||||
ChatCompletionResponse completionResponse = JSON.parseObject(response.getBody(), ChatCompletionResponse.class);
|
||||
String reply = completionResponse.getContent();
|
||||
|
||||
lastConfidence = calculateConfidence(reply);
|
||||
|
||||
log.info("AI回复生成成功: confidence={}, reply={}", lastConfidence, reply);
|
||||
return reply;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("AI回复生成失败", e);
|
||||
lastConfidence = 0.0;
|
||||
return "抱歉,我暂时无法回答您的问题,正在为您转接人工客服...";
|
||||
}
|
||||
}
|
||||
|
||||
public double getLastConfidence() {
|
||||
return lastConfidence;
|
||||
}
|
||||
|
||||
public List<ChatCompletionRequest.Message> getLastRequestMessages() {
|
||||
return lastRequestMessages;
|
||||
}
|
||||
|
||||
public String getLastRequestJson() {
|
||||
return lastRequestJson;
|
||||
}
|
||||
|
||||
public String getSystemPrompt() {
|
||||
return SYSTEM_PROMPT;
|
||||
}
|
||||
|
||||
public List<ChatCompletionRequest.Message> buildMessagesForTest(List<Message> history, String currentMessage) {
|
||||
return buildMessages(history, currentMessage);
|
||||
}
|
||||
|
||||
private List<ChatCompletionRequest.Message> buildMessages(List<Message> history, String currentMessage) {
|
||||
List<ChatCompletionRequest.Message> messages = new ArrayList<>();
|
||||
|
||||
messages.add(new ChatCompletionRequest.Message("system", SYSTEM_PROMPT));
|
||||
|
||||
int startIndex = Math.max(0, history.size() - 10);
|
||||
for (int i = startIndex; i < history.size(); i++) {
|
||||
Message msg = history.get(i);
|
||||
String role = Message.SENDER_TYPE_CUSTOMER.equals(msg.getSenderType()) ? "user" : "assistant";
|
||||
messages.add(new ChatCompletionRequest.Message(role, msg.getContent()));
|
||||
}
|
||||
|
||||
messages.add(new ChatCompletionRequest.Message("user", currentMessage));
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
private double calculateConfidence(String reply) {
|
||||
if (reply == null || reply.isEmpty()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if (reply.contains("不确定") || reply.contains("不清楚") || reply.contains("无法回答")) {
|
||||
return 0.4;
|
||||
}
|
||||
|
||||
if (reply.contains("转接人工") || reply.contains("人工客服")) {
|
||||
return 0.5;
|
||||
}
|
||||
|
||||
if (reply.length() < 10) {
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
return 0.85;
|
||||
}
|
||||
}
|
||||
|
|
@ -31,7 +31,6 @@ public class MessageProcessService {
|
|||
private static final String CHANNEL_TYPE = "wechat";
|
||||
|
||||
private final SessionManagerService sessionManagerService;
|
||||
private final AiService aiService;
|
||||
private final TransferService transferService;
|
||||
private final WecomApiService wecomApiService;
|
||||
private final WebSocketService webSocketService;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import com.wecom.robot.adapter.ChannelAdapter;
|
|||
import com.wecom.robot.adapter.TransferCapable;
|
||||
import com.wecom.robot.dto.InboundMessage;
|
||||
import com.wecom.robot.dto.OutboundMessage;
|
||||
import com.wecom.robot.dto.ai.ChatRequest;
|
||||
import com.wecom.robot.dto.ai.ChatResponse;
|
||||
import com.wecom.robot.entity.Message;
|
||||
import com.wecom.robot.entity.Session;
|
||||
import com.wecom.robot.service.*;
|
||||
|
|
@ -17,14 +19,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 消息路由服务实现 - 渠道无关的消息路由核心逻辑
|
||||
*
|
||||
* <p>关联 AC: [AC-MCA-08] 统一消息路由, [AC-MCA-09] 状态路由, [AC-MCA-10] 人工客服分发
|
||||
*
|
||||
* @see MessageRouterService
|
||||
* @see InboundMessage
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
|
|
@ -34,7 +28,7 @@ public class MessageRouterServiceImpl implements MessageRouterService {
|
|||
private static final long IDEMPOTENT_TTL_HOURS = 1;
|
||||
|
||||
private final SessionManagerService sessionManagerService;
|
||||
private final AiService aiService;
|
||||
private final AiServiceClient aiServiceClient;
|
||||
private final TransferService transferService;
|
||||
private final WebSocketService webSocketService;
|
||||
private final Map<String, ChannelAdapter> channelAdapters;
|
||||
|
|
@ -95,20 +89,36 @@ public class MessageRouterServiceImpl implements MessageRouterService {
|
|||
session.getSessionId(), truncateContent(message.getContent()));
|
||||
|
||||
List<Message> history = sessionManagerService.getSessionMessages(session.getSessionId());
|
||||
String reply = aiService.generateReply(message.getContent(), history);
|
||||
|
||||
double confidence = aiService.getLastConfidence();
|
||||
ChatRequest chatRequest = ChatRequest.fromInboundMessage(message);
|
||||
ChatResponse chatResponse;
|
||||
try {
|
||||
chatResponse = aiServiceClient.generateReply(chatRequest).get();
|
||||
} catch (Exception e) {
|
||||
log.error("[AC-MCA-06] AI服务调用失败: {}", e.getMessage());
|
||||
chatResponse = ChatResponse.fallbackWithTransfer(
|
||||
"抱歉,我暂时无法回答您的问题,正在为您转接人工客服...",
|
||||
e.getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
String reply = chatResponse.getReply();
|
||||
double confidence = chatResponse.getConfidence() != null ? chatResponse.getConfidence() : 0.0;
|
||||
int messageCount = sessionManagerService.getMessageCount(session.getSessionId());
|
||||
|
||||
boolean shouldTransfer = transferService.shouldTransferToManual(
|
||||
message.getContent(),
|
||||
confidence,
|
||||
messageCount,
|
||||
session.getCreatedAt()
|
||||
);
|
||||
boolean shouldTransfer = chatResponse.getShouldTransfer() != null && chatResponse.getShouldTransfer();
|
||||
|
||||
if (!shouldTransfer) {
|
||||
shouldTransfer = transferService.shouldTransferToManual(
|
||||
message.getContent(),
|
||||
confidence,
|
||||
messageCount,
|
||||
session.getCreatedAt()
|
||||
);
|
||||
}
|
||||
|
||||
if (shouldTransfer) {
|
||||
handleTransferToManual(session, message, reply);
|
||||
handleTransferToManual(session, message, reply, chatResponse.getTransferReason());
|
||||
} else {
|
||||
sendReplyToUser(session, message, reply);
|
||||
}
|
||||
|
|
@ -177,10 +187,10 @@ public class MessageRouterServiceImpl implements MessageRouterService {
|
|||
);
|
||||
}
|
||||
|
||||
private void handleTransferToManual(Session session, InboundMessage message, String reply) {
|
||||
String reason = transferService.getTransferReason(
|
||||
private void handleTransferToManual(Session session, InboundMessage message, String reply, String transferReason) {
|
||||
String reason = transferReason != null ? transferReason : transferService.getTransferReason(
|
||||
message.getContent(),
|
||||
aiService.getLastConfidence(),
|
||||
0.0,
|
||||
sessionManagerService.getMessageCount(session.getSessionId())
|
||||
);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue