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:
parent
d3b696d9bb
commit
56ffb522ac
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue