From 56ffb522acf14fe486bd52783a550f20278bd1ba Mon Sep 17 00:00:00 2001 From: MerCry Date: Tue, 24 Feb 2026 10:20:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(MCA):=20TASK-030=20=E5=AE=9A=E4=B9=89=20AI?= =?UTF-8?q?=20=E6=9C=8D=E5=8A=A1=20DTO=20[AC-MCA-04-REQ,=20AC-MCA-05]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建 ChatRequest DTO - 创建 ChatResponse DTO - 创建 ChatMessage DTO - 包含 InboundMessage 到 ChatRequest 的映射方法 - 单元测试覆盖 --- .../com/wecom/robot/dto/ai/ChatMessage.java | 34 +++++++++ .../com/wecom/robot/dto/ai/ChatRequest.java | 48 ++++++++++++ .../com/wecom/robot/dto/ai/ChatResponse.java | 44 +++++++++++ .../wecom/robot/dto/ai/ChatRequestTest.java | 74 +++++++++++++++++++ .../wecom/robot/dto/ai/ChatResponseTest.java | 45 +++++++++++ 5 files changed, 245 insertions(+) create mode 100644 src/main/java/com/wecom/robot/dto/ai/ChatMessage.java create mode 100644 src/main/java/com/wecom/robot/dto/ai/ChatRequest.java create mode 100644 src/main/java/com/wecom/robot/dto/ai/ChatResponse.java create mode 100644 src/test/java/com/wecom/robot/dto/ai/ChatRequestTest.java create mode 100644 src/test/java/com/wecom/robot/dto/ai/ChatResponseTest.java diff --git a/src/main/java/com/wecom/robot/dto/ai/ChatMessage.java b/src/main/java/com/wecom/robot/dto/ai/ChatMessage.java new file mode 100644 index 0000000..6f6cfdd --- /dev/null +++ b/src/main/java/com/wecom/robot/dto/ai/ChatMessage.java @@ -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(); + } +} diff --git a/src/main/java/com/wecom/robot/dto/ai/ChatRequest.java b/src/main/java/com/wecom/robot/dto/ai/ChatRequest.java new file mode 100644 index 0000000..1b7a6ef --- /dev/null +++ b/src/main/java/com/wecom/robot/dto/ai/ChatRequest.java @@ -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 history = new ArrayList<>(); + + @Builder.Default + private Map 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 history) { + return ChatRequest.builder() + .sessionId(msg.getSessionKey()) + .currentMessage(msg.getContent()) + .channelType(msg.getChannelType()) + .history(history) + .build(); + } +} diff --git a/src/main/java/com/wecom/robot/dto/ai/ChatResponse.java b/src/main/java/com/wecom/robot/dto/ai/ChatResponse.java new file mode 100644 index 0000000..5a62c66 --- /dev/null +++ b/src/main/java/com/wecom/robot/dto/ai/ChatResponse.java @@ -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 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(); + } +} diff --git a/src/test/java/com/wecom/robot/dto/ai/ChatRequestTest.java b/src/test/java/com/wecom/robot/dto/ai/ChatRequestTest.java new file mode 100644 index 0000000..479a202 --- /dev/null +++ b/src/test/java/com/wecom/robot/dto/ai/ChatRequestTest.java @@ -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 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()); + } +} diff --git a/src/test/java/com/wecom/robot/dto/ai/ChatResponseTest.java b/src/test/java/com/wecom/robot/dto/ai/ChatResponseTest.java new file mode 100644 index 0000000..d81ff6b --- /dev/null +++ b/src/test/java/com/wecom/robot/dto/ai/ChatResponseTest.java @@ -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()); + } +}