ai-robot-channel/src/main/java/com/wecom/robot/service/impl/AiServiceClientImpl.java

79 lines
3.1 KiB
Java
Raw Normal View History

package com.wecom.robot.service.impl;
import com.wecom.robot.config.AiServiceConfig;
import com.wecom.robot.dto.ai.ChatRequest;
import com.wecom.robot.dto.ai.ChatResponse;
import com.wecom.robot.service.AiServiceClient;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.timelimiter.annotation.TimeLimiter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.CompletableFuture;
@Slf4j
@Service
@RequiredArgsConstructor
public class AiServiceClientImpl implements AiServiceClient {
private static final String CHAT_ENDPOINT = "/ai/chat";
private static final String HEALTH_ENDPOINT = "/ai/health";
private final AiServiceConfig aiServiceConfig;
private final RestTemplate restTemplate;
@Override
@CircuitBreaker(name = "aiService", fallbackMethod = "generateReplyFallback")
@TimeLimiter(name = "aiService")
public CompletableFuture<ChatResponse> generateReply(ChatRequest request) {
log.info("[AC-MCA-04] 调用 AI 服务: sessionId={}", request.getSessionId());
String url = aiServiceConfig.getUrl() + CHAT_ENDPOINT;
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("X-Tenant-Id", aiServiceConfig.getTenantId());
headers.set("X-API-Key", aiServiceConfig.getApiKey());
HttpEntity<ChatRequest> entity = new HttpEntity<>(request, headers);
ResponseEntity<ChatResponse> response = restTemplate.postForEntity(
url, entity, ChatResponse.class);
log.info("[AC-MCA-05] AI 服务响应: sessionId={}, shouldTransfer={}",
request.getSessionId(),
response.getBody() != null ? response.getBody().getShouldTransfer() : null);
return CompletableFuture.completedFuture(response.getBody());
}
public CompletableFuture<ChatResponse> generateReplyFallback(ChatRequest request, Throwable cause) {
log.warn("[AC-MCA-06][AC-MCA-07] AI 服务降级: sessionId={}, cause={}",
request.getSessionId(), cause.getMessage());
ChatResponse fallbackResponse = ChatResponse.fallbackWithTransfer(
"抱歉,我暂时无法回答您的问题,正在为您转接人工客服...",
cause.getMessage()
);
return CompletableFuture.completedFuture(fallbackResponse);
}
@Override
public boolean healthCheck() {
try {
String url = aiServiceConfig.getUrl() + HEALTH_ENDPOINT;
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
return response.getStatusCode().is2xxSuccessful();
} catch (Exception e) {
log.error("[AC-MCA-04] AI 服务健康检查失败: {}", e.getMessage());
return false;
}
}
}