feat(MCA): TASK-030 定义 AI 服务 DTO [AC-MCA-04-REQ, AC-MCA-05]

- 创建 ChatRequest DTO

- 创建 ChatResponse DTO

- 创建 ChatMessage DTO

- 包含 InboundMessage 到 ChatRequest 的映射方法

- 单元测试覆盖
This commit is contained in:
MerCry 2026-02-24 10:20:31 +08:00
parent d3b696d9bb
commit 56ffb522ac
5 changed files with 245 additions and 0 deletions

View File

@ -0,0 +1,34 @@
package com.wecom.robot.dto.ai;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ChatMessage {
private String role;
private String content;
public static final String ROLE_USER = "user";
public static final String ROLE_ASSISTANT = "assistant";
public static ChatMessage userMessage(String content) {
return ChatMessage.builder()
.role(ROLE_USER)
.content(content)
.build();
}
public static ChatMessage assistantMessage(String content) {
return ChatMessage.builder()
.role(ROLE_ASSISTANT)
.content(content)
.build();
}
}

View File

@ -0,0 +1,48 @@
package com.wecom.robot.dto.ai;
import com.wecom.robot.dto.InboundMessage;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ChatRequest {
private String sessionId;
private String currentMessage;
private String channelType;
@Builder.Default
private List<ChatMessage> history = new ArrayList<>();
@Builder.Default
private Map<String, Object> metadata = new HashMap<>();
public static ChatRequest fromInboundMessage(InboundMessage msg) {
return ChatRequest.builder()
.sessionId(msg.getSessionKey())
.currentMessage(msg.getContent())
.channelType(msg.getChannelType())
.build();
}
public static ChatRequest fromInboundMessage(InboundMessage msg, List<ChatMessage> history) {
return ChatRequest.builder()
.sessionId(msg.getSessionKey())
.currentMessage(msg.getContent())
.channelType(msg.getChannelType())
.history(history)
.build();
}
}

View File

@ -0,0 +1,44 @@
package com.wecom.robot.dto.ai;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.HashMap;
import java.util.Map;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ChatResponse {
private String reply;
private Double confidence;
private Boolean shouldTransfer;
private String transferReason;
@Builder.Default
private Map<String, Object> metadata = new HashMap<>();
public static ChatResponse fallback(String reply) {
return ChatResponse.builder()
.reply(reply)
.confidence(0.0)
.shouldTransfer(true)
.build();
}
public static ChatResponse fallbackWithTransfer(String reply, String reason) {
return ChatResponse.builder()
.reply(reply)
.confidence(0.0)
.shouldTransfer(true)
.transferReason(reason)
.build();
}
}

View File

@ -0,0 +1,74 @@
package com.wecom.robot.dto.ai;
import com.wecom.robot.dto.InboundMessage;
import com.wecom.robot.dto.SignatureInfo;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
class ChatRequestTest {
@Test
void testChatRequestBuilder() {
ChatMessage msg1 = ChatMessage.userMessage("Hello");
ChatMessage msg2 = ChatMessage.assistantMessage("Hi there!");
Map<String, Object> metadata = new HashMap<>();
metadata.put("key", "value");
ChatRequest request = ChatRequest.builder()
.sessionId("session-123")
.currentMessage("How are you?")
.channelType(InboundMessage.CHANNEL_WECHAT)
.history(Arrays.asList(msg1, msg2))
.metadata(metadata)
.build();
assertEquals("session-123", request.getSessionId());
assertEquals("How are you?", request.getCurrentMessage());
assertEquals(InboundMessage.CHANNEL_WECHAT, request.getChannelType());
assertEquals(2, request.getHistory().size());
assertEquals("value", request.getMetadata().get("key"));
}
@Test
void testFromInboundMessage() {
InboundMessage inbound = InboundMessage.builder()
.channelType(InboundMessage.CHANNEL_WECHAT)
.channelMessageId("msg-123")
.sessionKey("session-key-001")
.customerId("customer-001")
.kfId("kf-001")
.content("Hello AI")
.build();
ChatRequest request = ChatRequest.fromInboundMessage(inbound);
assertEquals("session-key-001", request.getSessionId());
assertEquals("Hello AI", request.getCurrentMessage());
assertEquals(InboundMessage.CHANNEL_WECHAT, request.getChannelType());
}
@Test
void testFromInboundMessageWithHistory() {
InboundMessage inbound = InboundMessage.builder()
.sessionKey("session-002")
.content("New message")
.channelType(InboundMessage.CHANNEL_DOUYIN)
.build();
ChatMessage history1 = ChatMessage.userMessage("Previous");
ChatMessage history2 = ChatMessage.assistantMessage("Response");
ChatRequest request = ChatRequest.fromInboundMessage(inbound, Arrays.asList(history1, history2));
assertEquals("session-002", request.getSessionId());
assertEquals("New message", request.getCurrentMessage());
assertEquals(InboundMessage.CHANNEL_DOUYIN, request.getChannelType());
assertEquals(2, request.getHistory().size());
}
}

View File

@ -0,0 +1,45 @@
package com.wecom.robot.dto.ai;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class ChatResponseTest {
@Test
void testChatResponseBuilder() {
ChatResponse response = ChatResponse.builder()
.reply("This is a reply")
.confidence(0.95)
.shouldTransfer(false)
.transferReason(null)
.build();
assertEquals("This is a reply", response.getReply());
assertEquals(0.95, response.getConfidence());
assertFalse(response.getShouldTransfer());
assertNull(response.getTransferReason());
}
@Test
void testFallback() {
ChatResponse response = ChatResponse.fallback("Service unavailable");
assertEquals("Service unavailable", response.getReply());
assertEquals(0.0, response.getConfidence());
assertTrue(response.getShouldTransfer());
}
@Test
void testFallbackWithTransfer() {
ChatResponse response = ChatResponse.fallbackWithTransfer(
"Transferring to human agent",
"AI service timeout"
);
assertEquals("Transferring to human agent", response.getReply());
assertEquals(0.0, response.getConfidence());
assertTrue(response.getShouldTransfer());
assertEquals("AI service timeout", response.getTransferReason());
}
}