diff --git a/core/src/main/java/ai/z/openapi/service/model/ChatMessage.java b/core/src/main/java/ai/z/openapi/service/model/ChatMessage.java index ebdc86d..b263236 100644 --- a/core/src/main/java/ai/z/openapi/service/model/ChatMessage.java +++ b/core/src/main/java/ai/z/openapi/service/model/ChatMessage.java @@ -16,6 +16,9 @@ public class ChatMessage { private String role; + /** + * Message content: String | MessageContent + */ private Object content; @JsonProperty("reasoning_content") diff --git a/core/src/main/java/ai/z/openapi/service/model/FileUrl.java b/core/src/main/java/ai/z/openapi/service/model/FileUrl.java new file mode 100644 index 0000000..4569adf --- /dev/null +++ b/core/src/main/java/ai/z/openapi/service/model/FileUrl.java @@ -0,0 +1,16 @@ +package ai.z.openapi.service.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class FileUrl { + + private String url; + +} diff --git a/core/src/main/java/ai/z/openapi/service/model/MessageContent.java b/core/src/main/java/ai/z/openapi/service/model/MessageContent.java index 5c15655..321cfd7 100644 --- a/core/src/main/java/ai/z/openapi/service/model/MessageContent.java +++ b/core/src/main/java/ai/z/openapi/service/model/MessageContent.java @@ -14,18 +14,30 @@ import lombok.NoArgsConstructor; @Builder public class MessageContent { - /** 消息类型 text image_url video_url */ + /** Message Type: text image_url input_audio video_url file_url */ private String type; - /** 消息内容 when type is text */ + /** Message Content: when type is text */ private String text; - /** 消息图片URL when type is image_url */ + /** Message Content: when type is image_url */ @JsonProperty("image_url") private ImageUrl imageUrl; - /** 消息视频URL when type is video_url */ + /** Message Content: when type is input_audio */ @JsonProperty("input_audio") private InputAudio inputAudio; + /** + * Message Content: when type is video_url + */ + @JsonProperty("video_url") + private VideoUrl videoUrl; + + /** + * Message Content: when type is file_url Only support by GLM4.5V + */ + @JsonProperty("file_url") + private FileUrl fileUrl; + } diff --git a/core/src/main/java/ai/z/openapi/service/model/VideoUrl.java b/core/src/main/java/ai/z/openapi/service/model/VideoUrl.java new file mode 100644 index 0000000..faf0378 --- /dev/null +++ b/core/src/main/java/ai/z/openapi/service/model/VideoUrl.java @@ -0,0 +1,16 @@ +package ai.z.openapi.service.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class VideoUrl { + + private String url; + +} diff --git a/core/src/test/java/ai/z/openapi/service/chat/ChatServiceTest.java b/core/src/test/java/ai/z/openapi/service/chat/ChatServiceTest.java index 3cb32a6..a48396e 100644 --- a/core/src/test/java/ai/z/openapi/service/chat/ChatServiceTest.java +++ b/core/src/test/java/ai/z/openapi/service/chat/ChatServiceTest.java @@ -14,12 +14,17 @@ import ai.z.openapi.service.model.ChatMessageRole; import ai.z.openapi.service.model.ChatTool; import ai.z.openapi.service.model.ChatToolType; import ai.z.openapi.service.model.Choice; +import ai.z.openapi.service.model.InputAudio; +import ai.z.openapi.service.model.MessageContent; import ai.z.openapi.service.model.QueryModelResultResponse; import ai.z.openapi.service.model.WebSearch; import ai.z.openapi.service.model.params.CodeGeexExtra; import ai.z.openapi.service.model.params.CodeGeexTarget; +import ai.z.openapi.service.videos.VideoCreateParams; +import ai.z.openapi.service.videos.VideosResponse; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.io.FileUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.DisplayName; @@ -29,6 +34,8 @@ import org.junit.jupiter.params.provider.ValueSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; +import java.io.IOException; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -284,6 +291,44 @@ public class ChatServiceTest { logger.info("Function calling response: {}", mapper.writeValueAsString(response)); } + @Test + @DisplayName("Test Audio with audio Input") + @EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$") + void testAudioWithAudio() throws IOException { + String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis()); + String file = ClassLoader.getSystemResource("asr.wav").getFile(); + byte[] bytes = FileUtils.readFileToByteArray(new File(file)); + Base64.Encoder encoder = Base64.getEncoder(); + String audioBytes = encoder.encodeToString(bytes); + + MessageContent messageContent = new MessageContent(); + messageContent.setType("input_audio"); + messageContent.setInputAudio(InputAudio.builder().format("wav").data(audioBytes).build()); + List messages = new ArrayList<>(); + ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), Arrays.asList(messageContent)); + messages.add(userMessage); + + ChatCompletionCreateParams request = ChatCompletionCreateParams.builder() + .model(Constants.ModelChatGLM4Voice) + .stream(Boolean.FALSE) + .messages(messages) + .requestId(requestId) + .build(); + + // Execute test + ChatCompletionResponse response = chatService.createChatCompletion(request); + + // Verify results + assertNotNull(response, "Response should not be null"); + assertTrue(response.isSuccess(), "Response should be successful"); + assertNotNull(response.getData(), "Response data should not be null"); + assertEquals(requestId, response.getData().getRequestId(), "Request ID should match"); + assertNotNull(response.getData().getChoices(), "Response data should not be null"); + assertFalse(response.getData().getChoices().isEmpty(), "Response data should not be empty"); + assertNull(response.getError(), "Response error should be null"); + logger.info("Synchronous chat completion response: {}", mapper.writeValueAsString(response)); + } + @ParameterizedTest @ValueSource(strings = { Constants.ModelChatGLM4, Constants.ModelCharGLM3 }) @DisplayName("Test Different Models")