chore: update jackson version, add custom headers (#30)

This commit is contained in:
tomsun28 2025-08-07 14:09:26 +08:00 committed by GitHub
parent 192ea35963
commit 72f21989bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 670 additions and 143 deletions

1
.gitignore vendored
View file

@ -3,6 +3,7 @@ target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
.DS_Store
### STS ###
.apt_generated

View file

@ -49,7 +49,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<slf4j.version>2.0.11</slf4j.version>
<okhttp.version>3.14.9</okhttp.version>
<jackson.version>2.11.3</jackson.version>
<jackson.version>2.18.3</jackson.version>
<retrofit2.version>2.9.0</retrofit2.version>
<rxjava.version>3.1.8</rxjava.version>
<jwt.version>4.2.2</jwt.version>

View file

@ -42,6 +42,7 @@ import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.jackson.JacksonConverterFactory;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
@ -477,6 +478,19 @@ public abstract class AbstractAiClient extends AbstractClientBaseService {
return self();
}
/**
* Config the custom headers
* @param customHeaders custom headers
* @return this Builder instance for method chaining
*/
public B customHeaders(Map<String, String> customHeaders) {
if (customHeaders == null || customHeaders.isEmpty()) {
throw new IllegalArgumentException("Custom headers cannot be null or empty");
}
config.setCustomHeaders(customHeaders);
return self();
}
/**
* Disables token caching, forcing the client to use API keys for direct requests.
* This is the default behavior.

View file

@ -7,10 +7,13 @@ import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.HeaderMap;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Streaming;
import java.util.Map;
/**
* Chat Completions API for advanced GLM-4 series models Provides synchronous,
* asynchronous, and streaming chat completion capabilities Supports complex reasoning,
@ -36,6 +39,23 @@ public interface ChatApi {
@POST("chat/completions")
Call<ResponseBody> createChatCompletionStream(@Body ChatCompletionCreateParams request);
/**
* Create a streaming chat completion with custom headers support Returns response
* content incrementally through Server-Sent Events (SSE) for immediate user feedback
* Optimized for interactive applications requiring low latency and progressive
* content delivery Supports all GLM-4 models with configurable streaming parameters
* and custom HTTP headers
* @param request Chat completion parameters including model selection, messages, and
* streaming settings
* @param headers Custom HTTP headers to be added to the request
* @return Streaming response body with incremental content, usage statistics, and
* completion indicators
*/
@Streaming
@POST("chat/completions")
Call<ResponseBody> createChatCompletionStream(@Body ChatCompletionCreateParams request,
@HeaderMap Map<String, String> headers);
/**
* Create an asynchronous chat completion for long-running tasks Submits the request
* and returns immediately with a task ID for later result retrieval Ideal for complex
@ -64,6 +84,22 @@ public interface ChatApi {
@POST("chat/completions")
Single<ModelData> createChatCompletion(@Body ChatCompletionCreateParams request);
/**
* Create a synchronous chat completion with custom headers support Waits for the
* GLM-4 model to complete execution and returns the final result with custom HTTP
* headers Supports complex reasoning, tool calling, function execution, and
* multi-modal understanding Features advanced capabilities like web search
* integration, code interpretation, and image analysis
* @param request Chat completion parameters including model selection, conversation
* messages, generation settings, tools configuration, and response format
* @param headers Custom HTTP headers to be added to the request
* @return Complete chat completion response with generated content, usage statistics,
* tool call results, and reasoning traces
*/
@POST("chat/completions")
Single<ModelData> createChatCompletion(@Body ChatCompletionCreateParams request,
@HeaderMap Map<String, String> headers);
/**
* Query the result of an asynchronous chat completion task Retrieves the completion
* result or current status using the task ID from async request Provides detailed

View file

@ -260,6 +260,11 @@ public final class Constants {
*/
public static final String ModelCogVideoX2 = "cogvideox-2";
/**
* CogVideoX-3 model
*/
public static final String ModelCogVideoX3 = "cogvideox-3";
/**
* Vidu Q1 Text model - High-performance video generation from text input. Supports
* general and anime styles.

View file

@ -5,6 +5,7 @@ import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static ai.z.openapi.core.Constants.Z_AI_BASE_URL;
@ -63,6 +64,11 @@ public class ZaiConfig {
*/
private String apiSecret;
/**
* Custom Http Request Headers
*/
private Map<String, String> customHeaders;
/**
* JWT token expiration time in milliseconds (default: 30 minutes).
*/
@ -408,4 +414,12 @@ public class ZaiConfig {
return source_channel;
}
/**
* Get custom headers
* @return
*/
public Map<String, String> getCustomHeaders() {
return customHeaders;
}
}

View file

@ -7,16 +7,17 @@ import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
/**
* OkHttp Interceptor that adds an authorization token header
*/
public class AuthenticationInterceptor implements Interceptor {
public class HttpRequestInterceptor implements Interceptor {
private final ZaiConfig config;
public AuthenticationInterceptor(ZaiConfig config) {
public HttpRequestInterceptor(ZaiConfig config) {
Objects.requireNonNull(config.getApiKey(), "Z.ai token required");
this.config = config;
}
@ -31,17 +32,22 @@ public class AuthenticationInterceptor implements Interceptor {
TokenManager tokenManager = GlobalTokenManager.getTokenManagerV4();
accessToken = tokenManager.getToken(this.config);
}
String source_channel = "java-sdk";
String source_channel = "z-ai-sdk-java";
if (StringUtils.isNotEmpty(config.getSource_channel())) {
source_channel = config.getSource_channel();
}
Request request = chain.request()
Request.Builder request = chain.request()
.newBuilder()
.header("Authorization", "Bearer " + accessToken)
.header("x-source-channel", source_channel)
.header("Accept-Language", "en-US,en")
.build();
return chain.proceed(request);
.header("Zai-SDK-Ver", "0.0.2")
.header("Accept-Language", "en-US,en");
if (Objects.nonNull(config.getCustomHeaders())) {
for (Map.Entry<String, String> entry : config.getCustomHeaders().entrySet()) {
request.addHeader(entry.getKey(), entry.getValue());
}
}
return chain.proceed(request.build());
}
}

View file

@ -5,6 +5,8 @@ import ai.z.openapi.service.model.ChatCompletionResponse;
import ai.z.openapi.service.model.AsyncResultRetrieveParams;
import ai.z.openapi.service.model.QueryModelResultResponse;
import java.util.Map;
/**
* Chat completion service interface
*/
@ -32,4 +34,13 @@ public interface ChatService {
*/
QueryModelResultResponse retrieveAsyncResult(AsyncResultRetrieveParams request);
/**
* Creates a chat completion with custom headers support. This method allows passing
* custom HTTP headers along with the chat completion request.
* @param request the chat completion request parameters
* @param customHeaders custom HTTP headers to be added to the request
* @return ChatCompletionResponse containing the completion result
*/
ChatCompletionResponse createChatCompletion(ChatCompletionCreateParams request, Map<String, String> customHeaders);
}

View file

@ -7,11 +7,12 @@ import ai.z.openapi.service.model.ChatCompletionResponse;
import ai.z.openapi.service.model.AsyncResultRetrieveParams;
import ai.z.openapi.service.model.QueryModelResultResponse;
import ai.z.openapi.service.model.ModelData;
import ai.z.openapi.service.model.ChatRequestWithHeaders;
import ai.z.openapi.utils.FlowableRequestSupplier;
import ai.z.openapi.utils.RequestSupplier;
import ai.z.openapi.utils.StringUtils;
import okhttp3.ResponseBody;
import java.util.Map;
import java.util.Objects;
/**
@ -64,6 +65,38 @@ public class ChatServiceImpl implements ChatService {
return this.zAiClient.executeRequest(request, supplier, ChatCompletionResponse.class);
}
@Override
public ChatCompletionResponse createChatCompletion(ChatCompletionCreateParams request,
Map<String, String> customHeaders) {
if (Objects.isNull(customHeaders)) {
throw new IllegalArgumentException("customHeaders can not be null");
}
validateParams(request);
if (Objects.nonNull(request.getStream()) && request.getStream()) {
return streamChatCompletionWithHeaders(request, customHeaders);
}
else {
return syncChatCompletionWithHeaders(request, customHeaders);
}
}
private ChatCompletionResponse streamChatCompletionWithHeaders(ChatCompletionCreateParams request,
Map<String, String> customHeaders) {
ChatRequestWithHeaders requestWithHeaders = new ChatRequestWithHeaders(request, customHeaders);
FlowableRequestSupplier<ChatRequestWithHeaders, retrofit2.Call<ResponseBody>> supplier = (wrapper) -> chatApi
.createChatCompletionStream(wrapper.getRequest(), wrapper.getCustomHeaders());
return this.zAiClient.streamRequest(requestWithHeaders, supplier, ChatCompletionResponse.class,
ModelData.class);
}
private ChatCompletionResponse syncChatCompletionWithHeaders(ChatCompletionCreateParams request,
Map<String, String> customHeaders) {
ChatRequestWithHeaders requestWithHeaders = new ChatRequestWithHeaders(request, customHeaders);
RequestSupplier<ChatRequestWithHeaders, ModelData> supplier = (wrapper) -> chatApi
.createChatCompletion(wrapper.getRequest(), wrapper.getCustomHeaders());
return this.zAiClient.executeRequest(requestWithHeaders, supplier, ChatCompletionResponse.class);
}
private void validateParams(ChatCompletionCreateParams request) {
if (request == null) {
throw new IllegalArgumentException("request cannot be null");

View file

@ -0,0 +1,17 @@
package ai.z.openapi.service.file;
public enum UploadFilePurpose {
BATCH("batch"), FILE_EXTRACT("file-extract"), CODE_INTERPRETER("code-interpreter"), AGENT("agent");
private final String value;
UploadFilePurpose(final String value) {
this.value = value;
}
public String value() {
return value;
}
}

View file

@ -0,0 +1,32 @@
package ai.z.openapi.service.model;
import ai.z.openapi.core.model.ClientRequest;
import ai.z.openapi.service.CommonRequest;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.Map;
/**
* Chat request wrapper that includes custom headers support. This class wraps the
* original ChatCompletionCreateParams and adds custom headers functionality.
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatRequestWithHeaders extends CommonRequest implements ClientRequest<ChatRequestWithHeaders> {
/**
* The original chat completion request parameters
*/
private ChatCompletionCreateParams request;
/**
* Custom headers to be added to the HTTP request
*/
private Map<String, String> customHeaders;
}

View file

@ -1,7 +1,7 @@
package ai.z.openapi.utils;
import ai.z.openapi.core.config.ZaiConfig;
import ai.z.openapi.core.token.AuthenticationInterceptor;
import ai.z.openapi.core.token.HttpRequestInterceptor;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
@ -42,7 +42,7 @@ public final class OkHttps {
throw new IllegalArgumentException("Configuration cannot be null");
}
OkHttpClient.Builder builder = new OkHttpClient.Builder().addInterceptor(new AuthenticationInterceptor(config));
OkHttpClient.Builder builder = new OkHttpClient.Builder().addInterceptor(new HttpRequestInterceptor(config));
// Configure timeouts
configureTimeouts(builder, config);

View file

@ -61,44 +61,6 @@ public class AssistantServiceTest {
"AssistantService should be an instance of AssistantServiceImpl");
}
// As of 2025-07-23, no models support synchronous completion
// @Test
// @DisplayName("Test Synchronous Assistant Completion - Basic Functionality")
// @EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
// void testSyncAssistantCompletion() throws JsonProcessingException {
// // Prepare test data
// MessageTextContent textContent = MessageTextContent.builder()
// .text("Hello, please introduce yourself")
// .type("text")
// .build();
// ConversationMessage message = ConversationMessage.builder()
// .role("user")
// .content(Collections.singletonList(textContent))
// .build();
// String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
// AssistantParameters request = AssistantParameters.builder()
// .model(Constants.ModelChatGLM4Assistant)
// .assistantId(TEST_ASSISTANT_ID)
// .stream(false)
// .messages(Collections.singletonList(message))
// .requestId(requestId)
// .build();
// // Execute test
// AssistantApiResponse response = assistantService.assistantCompletion(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");
// assertNull(response.getError(), "Response error should be null");
// logger.info("Synchronous assistant completion response: {}",
// mapper.writeValueAsString(response));
// }
@Test
@DisplayName("Test Stream Assistant Completion")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
@ -188,13 +150,17 @@ public class AssistantServiceTest {
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void testQueryConversationUsage() {
// Prepare test data
ConversationParameters request = ConversationParameters.builder().assistantId(TEST_ASSISTANT_ID).build();
ConversationParameters request = ConversationParameters.builder()
.assistantId(TEST_ASSISTANT_ID)
.page(1)
.pageSize(5)
.build();
// Execute test
ConversationUsageListResponse response = assistantService.queryConversationUsage(request);
// Verify results
assertNotNull(response, "Response should not be null");
assertNotNull(response.getData(), "Response should not be null");
logger.info("Query conversation usage response: {}", response);
}
@ -216,7 +182,7 @@ public class AssistantServiceTest {
.messages(Collections.singletonList(message))
.build();
AssistantApiResponse response = assistantService.assistantCompletion(request);
AssistantApiResponse response = assistantService.assistantCompletionStream(request);
// Should handle error gracefully
assertNotNull(response, "Response should not be null even for invalid assistant ID");
@ -258,45 +224,29 @@ public class AssistantServiceTest {
AssistantParameters request = AssistantParameters.builder()
.assistantId(TEST_ASSISTANT_ID)
.stream(false)
.stream(true)
.messages(messages)
.requestId(requestId)
.build();
AssistantApiResponse response = assistantService.assistantCompletion(request);
AssistantApiResponse response = assistantService.assistantCompletionStream(request);
response.getFlowable().doOnNext(accumulator -> {
if (accumulator.getChoices() != null && !accumulator.getChoices().isEmpty()) {
MessageContent delta = accumulator.getChoices().get(0).getDelta();
if (delta != null) {
try {
logger.info("MessageContent: {}", mapper.writeValueAsString(delta));
}
catch (JsonProcessingException e) {
logger.error("Error processing message content", e);
}
}
}
})
.doOnComplete(() -> logger.info("Stream response completed, received messages"))
.doOnError(throwable -> logger.error("Stream error: {}", throwable.getMessage()))
.blockingSubscribe();
assertNotNull(response, "Multi-turn conversation response should not be null");
logger.info("Multi-turn conversation response: {}", mapper.writeValueAsString(response));
}
@Test
@DisplayName("Test Assistant with Translation Parameters")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void testAssistantWithTranslation() throws JsonProcessingException {
// This test is based on the existing
// TestAssistantClientApiService.testTranslateAssistantCompletion
MessageTextContent textContent = MessageTextContent.builder().text("Hello there").type("text").build();
ConversationMessage message = ConversationMessage.builder()
.role("user")
.content(Collections.singletonList(textContent))
.build();
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
AssistantParameters request = AssistantParameters.builder()
.assistantId("9996ijk789lmn012o345p999") // Translation assistant ID
.stream(false)
.messages(Collections.singletonList(message))
.requestId(requestId)
.build();
// Execute test
AssistantApiResponse response = assistantService.assistantCompletion(request);
// Verify results
assertNotNull(response, "Translation response should not be null");
logger.info("Translation assistant response: {}", mapper.writeValueAsString(response));
}
}

View file

@ -303,7 +303,7 @@ public class AudioServiceTest {
@DisplayName("Should transcribe different audio formats successfully")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void shouldTranscribeDifferentAudioFormatsSuccessfully() throws JsonProcessingException {
String[] audioFiles = { "asr.wav", "asr.webm" };
String[] audioFiles = { "asr.wav", "asr.mp3" };
for (String audioFile : audioFiles) {
String requestId = String.format(REQUEST_ID_TEMPLATE + "-%s", System.currentTimeMillis(), audioFile);

View file

@ -508,4 +508,187 @@ public class ChatServiceTest {
logger.info("CodeGeex code completion test completed");
}
@Test
@DisplayName("Test Synchronous Chat Completion with Custom Headers")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void testSyncChatCompletionWithCustomHeaders() throws JsonProcessingException {
// Prepare test data
List<ChatMessage> messages = new ArrayList<>();
ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "Hello, please introduce yourself");
messages.add(userMessage);
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model(Constants.ModelChatGLM4)
.stream(Boolean.FALSE)
.messages(messages)
.requestId(requestId)
.build();
// Prepare custom headers
Map<String, String> customHeaders = new HashMap<>();
customHeaders.put("X-Custom-User-ID", "test-user-123");
customHeaders.put("X-Request-Source", "junit-test");
customHeaders.put("Session-Id", "session-" + System.currentTimeMillis());
// Execute test
ChatCompletionResponse response = chatService.createChatCompletion(request, customHeaders);
// 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 with custom headers response: {}",
mapper.writeValueAsString(response));
}
@Test
@DisplayName("Test Stream Chat Completion with Custom Headers")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void testStreamChatCompletionWithCustomHeaders() throws JsonProcessingException {
// Prepare test data
List<ChatMessage> messages = new ArrayList<>();
ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(),
"Please write a short poem about spring");
messages.add(userMessage);
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model(Constants.ModelChatGLM4)
.stream(Boolean.TRUE)
.messages(messages)
.requestId(requestId)
.temperature(0.7F)
.maxTokens(100)
.build();
// Prepare custom headers
Map<String, String> customHeaders = new HashMap<>();
customHeaders.put("X-Custom-User-ID", "stream-test-user-456");
customHeaders.put("X-Request-Source", "junit-stream-test");
customHeaders.put("X-Stream-Mode", "enabled");
customHeaders.put("Content-Type", "application/json");
// Execute test
ChatCompletionResponse response = chatService.createChatCompletion(request, customHeaders);
// Verify results
assertNotNull(response, "Response should not be null");
assertTrue(response.isSuccess(), "Response should be successful");
// Test stream data processing
AtomicInteger messageCount = new AtomicInteger(0);
AtomicBoolean isFirst = new AtomicBoolean(true);
response.getFlowable().doOnNext(modelData -> {
if (isFirst.getAndSet(false)) {
logger.info("Starting to receive stream response with custom headers:");
}
if (modelData.getChoices() != null && !modelData.getChoices().isEmpty()) {
Choice choice = modelData.getChoices().get(0);
if (choice.getDelta() != null && choice.getDelta().getContent() != null) {
logger.info("Received content: {}", choice.getDelta().getContent());
messageCount.incrementAndGet();
}
}
})
.doOnComplete(() -> logger.info(
"Stream response with custom headers completed, received {} messages in total", messageCount.get()))
.blockingSubscribe();
assertTrue(messageCount.get() > 0, "Should receive at least one message");
logger.info("Stream chat completion with custom headers test completed");
}
@Test
@DisplayName("Test Custom Headers Validation - Null Headers")
void testCustomHeadersValidation_NullHeaders() {
// Prepare test data
List<ChatMessage> messages = new ArrayList<>();
ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "Hello");
messages.add(userMessage);
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model(Constants.ModelChatGLM4)
.stream(Boolean.FALSE)
.messages(messages)
.build();
// Test with null custom headers
assertThrows(IllegalArgumentException.class, () -> {
chatService.createChatCompletion(request, null);
}, "Null custom headers should throw IllegalArgumentException");
}
@Test
@DisplayName("Test Custom Headers with Empty Map")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void testCustomHeadersWithEmptyMap() throws JsonProcessingException {
// Prepare test data
List<ChatMessage> messages = new ArrayList<>();
ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "Hello");
messages.add(userMessage);
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model(Constants.ModelChatGLM4)
.stream(Boolean.FALSE)
.messages(messages)
.requestId(requestId)
.build();
// Test with empty custom headers map
Map<String, String> emptyHeaders = new HashMap<>();
ChatCompletionResponse response = chatService.createChatCompletion(request, emptyHeaders);
// 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");
logger.info("Chat completion with empty custom headers response: {}", mapper.writeValueAsString(response));
}
@Test
@DisplayName("Test Custom Headers with Special Characters")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void testCustomHeadersWithSpecialCharacters() throws JsonProcessingException {
// Prepare test data
List<ChatMessage> messages = new ArrayList<>();
ChatMessage userMessage = new ChatMessage(ChatMessageRole.USER.value(), "Hello");
messages.add(userMessage);
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model(Constants.ModelChatGLM4)
.stream(Boolean.FALSE)
.messages(messages)
.requestId(requestId)
.build();
// Prepare custom headers with special characters
Map<String, String> customHeaders = new HashMap<>();
customHeaders.put("X-User-Agent", "ZAI-SDK/1.0 (Java; Test)");
customHeaders.put("X-Client-Version", "v1.2.3-beta");
customHeaders.put("X-Request-Timestamp", String.valueOf(System.currentTimeMillis()));
customHeaders.put("X-Trace-ID", "trace-" + UUID.randomUUID());
// Execute test
ChatCompletionResponse response = chatService.createChatCompletion(request, customHeaders);
// 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");
logger.info("Chat completion with special character headers response: {}", mapper.writeValueAsString(response));
}
}

View file

@ -0,0 +1,120 @@
package ai.z.openapi.service.chat;
import ai.z.openapi.service.model.ChatCompletionCreateParams;
import ai.z.openapi.service.model.ChatMessage;
import ai.z.openapi.service.model.ChatMessageRole;
import ai.z.openapi.service.model.ChatRequestWithHeaders;
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.*;
/**
* Unit test for ChatRequestWithHeaders wrapper functionality. Tests the wrapper class
* used for custom headers in chat requests.
*/
class ChatServiceWithHeadersIntegrationTest {
@Test
void testChatRequestWithHeaders_StreamingRequest() {
// Arrange
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model("glm-4-flash")
.messages(Arrays
.asList(ChatMessage.builder().role(ChatMessageRole.USER.value()).content("Hello, world!").build()))
.stream(true)
.build();
Map<String, String> customHeaders = new HashMap<>();
customHeaders.put("X-Custom-User-ID", "user123");
customHeaders.put("X-Request-Source", "test");
// Act
ChatRequestWithHeaders wrapper = new ChatRequestWithHeaders(request, customHeaders);
// Assert
assertNotNull(wrapper);
assertNotNull(wrapper.getRequest());
assertNotNull(wrapper.getCustomHeaders());
assertEquals(request, wrapper.getRequest());
assertEquals(customHeaders, wrapper.getCustomHeaders());
assertEquals(2, wrapper.getCustomHeaders().size());
assertEquals("user123", wrapper.getCustomHeaders().get("X-Custom-User-ID"));
assertEquals("test", wrapper.getCustomHeaders().get("X-Request-Source"));
}
@Test
void testChatRequestWithHeaders_NonStreamingRequest() {
// Arrange
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model("glm-4-flash")
.messages(Arrays
.asList(ChatMessage.builder().role(ChatMessageRole.USER.value()).content("What is AI?").build()))
.stream(false) // Non-streaming request
.build();
Map<String, String> customHeaders = new HashMap<>();
customHeaders.put("X-Custom-User-ID", "user456");
customHeaders.put("X-Request-Source", "test-sync");
// Act
ChatRequestWithHeaders wrapper = new ChatRequestWithHeaders(request, customHeaders);
// Assert
assertNotNull(wrapper);
assertNotNull(wrapper.getRequest());
assertNotNull(wrapper.getCustomHeaders());
assertEquals(request, wrapper.getRequest());
assertEquals(customHeaders, wrapper.getCustomHeaders());
assertFalse(wrapper.getRequest().getStream()); // Verify non-streaming
assertEquals("user456", wrapper.getCustomHeaders().get("X-Custom-User-ID"));
assertEquals("test-sync", wrapper.getCustomHeaders().get("X-Request-Source"));
}
@Test
void testChatRequestWithHeaders_NullHeaders() {
// Arrange
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model("glm-4-flash")
.messages(Arrays
.asList(ChatMessage.builder().role(ChatMessageRole.USER.value()).content("Test message").build()))
.stream(false)
.build();
// Act
ChatRequestWithHeaders wrapper = new ChatRequestWithHeaders(request, null);
// Assert
assertNotNull(wrapper);
assertNotNull(wrapper.getRequest());
assertEquals(request, wrapper.getRequest());
// Custom headers are converted to empty map when null
assertNull(wrapper.getCustomHeaders());
}
@Test
void testChatRequestWithHeaders_ToString() {
// Arrange
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model("glm-4-flash")
.messages(Arrays
.asList(ChatMessage.builder().role(ChatMessageRole.USER.value()).content("Test message").build()))
.stream(false)
.build();
Map<String, String> headers = new HashMap<>();
headers.put("X-Test", "value");
// Act
ChatRequestWithHeaders wrapper = new ChatRequestWithHeaders(request, headers);
String toStringResult = wrapper.toString();
// Assert
assertNotNull(toStringResult);
assertTrue(toStringResult.contains("ChatRequestWithHeaders"));
}
}

View file

@ -37,13 +37,6 @@ public class FileServiceTest {
// Request ID template
private static final String REQUEST_ID_TEMPLATE = "file-test-%d";
// Test file purposes
private static final String PURPOSE_FINE_TUNE = "fine-tune";
private static final String PURPOSE_ASSISTANTS = "assistants";
private static final String PURPOSE_BATCH = "batch";
@BeforeEach
void setUp() {
ZaiConfig zaiConfig = new ZaiConfig();
@ -74,7 +67,7 @@ public class FileServiceTest {
FileUploadParams request = FileUploadParams.builder()
.filePath(tempFile.toString())
.purpose(PURPOSE_ASSISTANTS)
.purpose(UploadFilePurpose.AGENT.value())
.requestId(requestId)
.build();
@ -87,7 +80,7 @@ public class FileServiceTest {
assertNotNull(response.getData(), "Response data should not be null");
assertNotNull(response.getData().getId(), "File ID should not be null");
assertEquals("file", response.getData().getObject(), "Object type should be 'file'");
assertEquals(PURPOSE_ASSISTANTS, response.getData().getPurpose(), "Purpose should match");
assertEquals(UploadFilePurpose.AGENT.value(), response.getData().getPurpose(), "Purpose should match");
assertNotNull(response.getData().getFilename(), "Filename should not be null");
assertNotNull(response.getData().getBytes(), "File size should not be null");
assertTrue(response.getData().getBytes() > 0, "File size should be greater than 0");
@ -119,7 +112,7 @@ public class FileServiceTest {
FileUploadParams request = FileUploadParams.builder()
.filePath(tempFile.toString())
.purpose(PURPOSE_FINE_TUNE)
.purpose(UploadFilePurpose.FILE_EXTRACT.value())
.requestId(requestId)
.extraJson(extraJson)
.build();
@ -131,7 +124,8 @@ public class FileServiceTest {
assertNotNull(response, "Response should not be null");
assertTrue(response.isSuccess(), "Response should be successful");
assertNotNull(response.getData(), "Response data should not be null");
assertEquals(PURPOSE_FINE_TUNE, response.getData().getPurpose(), "Purpose should match");
assertEquals(UploadFilePurpose.FILE_EXTRACT.value(), response.getData().getPurpose(),
"Purpose should match");
assertNull(response.getError(), "Response error should be null");
logger.info("File upload with extra JSON response: {}", mapper.writeValueAsString(response));
@ -149,7 +143,7 @@ public class FileServiceTest {
FileUploadParams request = FileUploadParams.builder()
.filePath("/non/existent/file.txt")
.purpose(PURPOSE_ASSISTANTS)
.purpose(UploadFilePurpose.AGENT.value())
.requestId(requestId)
.build();
@ -187,7 +181,7 @@ public class FileServiceTest {
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
FileListParams request = FileListParams.builder()
.purpose(PURPOSE_ASSISTANTS)
.purpose(UploadFilePurpose.AGENT.value())
.limit(5)
.order("asc")
.requestId(requestId)
@ -205,7 +199,8 @@ public class FileServiceTest {
// Verify purpose filter if files exist
if (response.getData().getData() != null && !response.getData().getData().isEmpty()) {
response.getData().getData().forEach(file -> {
assertEquals(PURPOSE_ASSISTANTS, file.getPurpose(), "All files should have the specified purpose");
assertEquals(UploadFilePurpose.AGENT.value(), file.getPurpose(),
"All files should have the specified purpose");
});
}
@ -269,7 +264,7 @@ public class FileServiceTest {
FileUploadParams uploadRequest = FileUploadParams.builder()
.filePath(tempFile.toString())
.purpose(PURPOSE_ASSISTANTS)
.purpose(UploadFilePurpose.FILE_EXTRACT.value())
.requestId(requestId)
.build();

View file

@ -110,13 +110,13 @@ public class ImageServiceTest {
@DisplayName("Test Different Image Sizes")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void testDifferentImageSizes() throws JsonProcessingException {
String[] sizes = { "256x256", "512x512", "1024x1024" };
String[] sizes = { "512x512", "1024x1024" };
for (String size : sizes) {
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
CreateImageRequest request = CreateImageRequest.builder()
.model(Constants.ModelCogView3Plus)
.model(Constants.ModelCogView4)
.prompt("A simple geometric pattern")
.size(size)
.requestId(requestId)
@ -124,7 +124,8 @@ public class ImageServiceTest {
ImageResponse response = imageService.createImage(request);
assertNotNull(response, "Response should not be null for size: " + size);
assertNotNull(response.getData(), "Response should not be null for size: " + size);
assertEquals(200, response.getCode());
logger.info("Size {} response: {}", size, mapper.writeValueAsString(response));
}
}

View file

@ -1,6 +1,7 @@
package ai.z.openapi.service.videos;
import ai.z.openapi.ZaiClient;
import ai.z.openapi.core.Constants;
import ai.z.openapi.core.config.ZaiConfig;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@ -35,11 +36,6 @@ public class VideosServiceTest {
// Request ID template
private static final String REQUEST_ID_TEMPLATE = "video-test-%d";
// Video model constants
private static final String MODEL_COGVIDEOX = "cogvideox";
private static final String MODEL_COGVIDEO3 = "cogvideo-3";
@BeforeEach
void setUp() {
ZaiConfig zaiConfig = new ZaiConfig();
@ -67,7 +63,7 @@ public class VideosServiceTest {
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
VideoCreateParams request = VideoCreateParams.builder()
.model(MODEL_COGVIDEOX)
.model(Constants.ModelCogVideoX3)
.prompt("A beautiful sunset over the ocean with waves gently crashing on the shore")
.requestId(requestId)
.withAudio(Boolean.TRUE)
@ -80,6 +76,7 @@ public class VideosServiceTest {
// Verify results
assertNotNull(response, "Response should not be null");
assertEquals(200, response.getCode());
assertTrue(response.isSuccess(), "Response should be successful");
assertNotNull(response.getData(), "Response data should not be null");
assertNotNull(response.getData().getId(), "Response data ID should not be null");
@ -95,7 +92,7 @@ public class VideosServiceTest {
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
VideoCreateParams request = VideoCreateParams.builder()
.model(MODEL_COGVIDEOX)
.model(Constants.ModelCogVideoX3)
.prompt("A person walking in a beautiful garden")
.requestId(requestId)
.build();
@ -114,6 +111,7 @@ public class VideosServiceTest {
// Verify result response
assertNotNull(resultResponse, "Result response should not be null");
assertEquals(200, resultResponse.getCode());
assertNotNull(resultResponse.getData(), "Result response data should not be null");
assertNotNull(resultResponse.getData().getId(), "Result response task ID should not be null");
logger.info("Video generation result: taskId={}, response={}", taskId,
@ -138,7 +136,7 @@ public class VideosServiceTest {
}
@ParameterizedTest
@ValueSource(strings = { MODEL_COGVIDEOX, MODEL_COGVIDEO3 })
@ValueSource(strings = { Constants.ModelCogVideoX2, Constants.ModelCogVideoX3 })
@DisplayName("Test Different Video Models")
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
void testDifferentModels(String model) throws JsonProcessingException {
@ -153,6 +151,7 @@ public class VideosServiceTest {
VideosResponse response = videosService.videoGenerations(request);
assertNotNull(response, "Response should not be null");
assertEquals(200, response.getCode());
logger.info("Model {} response: {}", model, mapper.writeValueAsString(response));
}
@ -177,7 +176,7 @@ public class VideosServiceTest {
@Test
@DisplayName("Test Parameter Validation - Empty Prompt")
void testValidation_EmptyPrompt() {
VideoCreateParams request = VideoCreateParams.builder().model(MODEL_COGVIDEOX).prompt("").build();
VideoCreateParams request = VideoCreateParams.builder().model(Constants.ModelCogVideoX3).prompt("").build();
assertThrows(IllegalArgumentException.class, () -> {
videosService.videoGenerations(request);
@ -202,17 +201,18 @@ public class VideosServiceTest {
Base64.Encoder encoder = Base64.getEncoder();
String imageUrl = encoder.encodeToString(bytes);
VideoCreateParams request = VideoCreateParams.builder()
.model(MODEL_COGVIDEOX)
.model(Constants.ModelCogVideoX3)
.prompt("Transform this image into a dynamic video scene")
.imageUrl(imageUrl)
.requestId(requestId)
.withAudio(Boolean.FALSE)
.duration(3)
.duration(5)
.build();
VideosResponse response = videosService.videoGenerations(request);
assertNotNull(response, "Response should not be null");
assertEquals(200, response.getCode());
logger.info("Video generation with image response: {}", mapper.writeValueAsString(response));
}
@ -223,19 +223,20 @@ public class VideosServiceTest {
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
VideoCreateParams request = VideoCreateParams.builder()
.model(MODEL_COGVIDEOX)
.model(Constants.ModelCogVideoX3)
.prompt("A futuristic city with flying cars and neon lights")
.requestId(requestId)
.quality("high")
.quality("speed")
.withAudio(Boolean.TRUE)
.size("1280x720")
.duration(10)
.duration(5)
.fps(30)
.build();
VideosResponse response = videosService.videoGenerations(request);
assertNotNull(response, "Response should not be null");
assertEquals(200, response.getCode());
logger.info("Video generation with custom settings response: {}", mapper.writeValueAsString(response));
}

Binary file not shown.

View file

@ -21,7 +21,7 @@ public class AgentExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().build();

View file

@ -21,7 +21,7 @@ public class AgentVideoExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().build();

View file

@ -19,13 +19,13 @@ public class ChatAsyncCompletionExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZhipuAiClient client = ZhipuAiClient.builder().build();
// Or set API Key via code
// ZaiClient client = ZaiClient.builder()
// .apiKey("your.api.key")
// .apiKey("your.api_key")
// .build();
// Create chat request

View file

@ -14,13 +14,13 @@ public class ChatCompletionExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZhipuAiClient client = ZhipuAiClient.builder().build();
// Or set API Key via code
// ZaiClient client = ZaiClient.builder()
// .apiKey("your.api.key")
// .apiKey("your.api_key")
// .build();
// Create chat request

View file

@ -0,0 +1,90 @@
package ai.z.openapi.samples;
import ai.z.openapi.ZhipuAiClient;
import ai.z.openapi.service.model.*;
import ai.z.openapi.core.Constants;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Chat Completion with Custom Headers Example
* Demonstrates how to use ZaiClient for chat conversations with custom HTTP headers
*/
public class ChatCompletionWithCustomHeadersExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZhipuAiClient client = ZhipuAiClient.builder().build();
// Create chat request
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model(Constants.ModelChatGLM4_5)
.messages(Arrays.asList(
ChatMessage.builder()
.role(ChatMessageRole.USER.value())
.content("Hello, how are you?")
.build()
))
.stream(true) // Enable streaming for custom headers support
.temperature(0.7f)
.maxTokens(1024)
.build();
// Create custom headers
Map<String, String> customHeaders = new HashMap<>();
customHeaders.put("X-Custom-User-ID", "user123");
customHeaders.put("X-Request-Source", "mobile-app");
customHeaders.put("Session-Id", "session-abc-123");
try {
// Execute request with custom headers
// This works for both streaming and non-streaming requests
ChatCompletionResponse response = client.chat().createChatCompletion(request, customHeaders);
// Example for non-streaming request with custom headers
ChatCompletionCreateParams nonStreamingRequest = ChatCompletionCreateParams.builder()
.model(Constants.ModelChatGLM4_5)
.messages(Arrays.asList(
ChatMessage.builder()
.role(ChatMessageRole.USER.value())
.content("What is artificial intelligence?")
.build()
))
.stream(false) // Explicitly set to false for non-streaming
.temperature(0.7f)
.maxTokens(1024)
.build();
ChatCompletionResponse nonStreamingResponse = client.chat()
.createChatCompletion(nonStreamingRequest, customHeaders);
System.out.println("Non-streaming response: " + nonStreamingResponse.getData());
if (response.isSuccess() && response.getFlowable() != null) {
System.out.println("Streaming response with custom headers:");
response.getFlowable().subscribe(
data -> {
// Handle streaming chunk
if (data.getChoices() != null && !data.getChoices().isEmpty()) {
String content = data.getChoices().get(0).getDelta().getContent();
if (content != null) {
System.out.print(content);
}
}
},
error -> System.err.println("\nStream error: " + error.getMessage()),
() -> System.out.println("\nStream completed")
);
} else {
System.err.println("Error: " + response.getMsg());
}
} catch (Exception e) {
System.err.println("Exception occurred: " + e.getMessage());
e.printStackTrace();
}
}
}

View file

@ -1,6 +1,10 @@
package ai.z.openapi.samples;
import ai.z.openapi.ZaiClient;
import ai.z.openapi.ZhipuAiClient;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
@ -12,14 +16,17 @@ public class ClientConfigurationExample {
public static void main(String[] args) {
System.out.println("=== Basic Configuration Example ===");
ZaiClient basicClient = ZaiClient.builder().build();
ZaiClient basicClient = ZaiClient.builder().apiKey("xxx.xxx").build();
System.out.println("✓ Basic client created successfully");
// Complete configuration example
System.out.println("\n=== Complete Configuration Example ===");
Map<String, String> customHeaders = new HashMap<>();
customHeaders.put("Session-Id", "custom-session-id-xx");
ZaiClient advancedClient = ZaiClient.builder()
.apiKey("your.api.key")
.apiKey("your.api_key")
.baseUrl("https://api.z.ai/api/paas/v4/")
.customHeaders(customHeaders)
.enableTokenCache()
.tokenExpire(3600000) // 1 hour
.connectionPool(10, 5, TimeUnit.MINUTES)
@ -28,14 +35,25 @@ public class ClientConfigurationExample {
// ZHIPU platform specific client
System.out.println("\n=== ZHIPU Platform Specific Configuration ===");
ZaiClient zhipuClient = ZaiClient.ofZHIPU("your.api.key").build();
ZaiClient zhipuClient = ZaiClient.ofZHIPU("your.api_key").build();
System.out.println("✓ ZHIPU platform client created successfully");
ZhipuAiClient zhipuAiClient = ZhipuAiClient.builder()
.apiKey("your.api_key")
.baseUrl("https://api.z.ai/api/paas/v4/")
.customHeaders(customHeaders)
.enableTokenCache()
.tokenExpire(3600000) // 1 hour
.connectionPool(10, 5, TimeUnit.MINUTES)
.build();
System.out.println("✓ ZHIPU platform client created successfully");
// Custom configuration example
System.out.println("\n=== Custom Configuration Example ===");
ZaiClient customClient = ZaiClient.builder()
.apiKey("your.api.key")
.apiKey("your.api_key")
.baseUrl("https://custom.api.endpoint/")
.customHeaders(customHeaders)
.enableTokenCache()
.tokenExpire(7200000)
.connectionPool(20, 10, TimeUnit.MINUTES)

View file

@ -16,13 +16,13 @@ public class CogVideoX3Example {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().build();
// Or set API Key via code
// ZaiClient client = ZaiClient.builder()
// .apiKey("your.api.key")
// .apiKey("your.api_key")
// .build();
// Video generation examples

View file

@ -13,13 +13,13 @@ public class CogVideoXExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().build();
// Or set API Key via code
// ZaiClient client = ZaiClient.builder()
// .apiKey("your.api.key")
// .apiKey("your.api_key")
// .build();
// Basic Video Generation

View file

@ -16,7 +16,7 @@ public class GLM41VThinkingExample {
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder()
.apiKey("your.api.key")
.apiKey("your.api_key")
.build();
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()

View file

@ -15,7 +15,7 @@ public class GLM4VPlusExample {
public static void main(String[] args) {
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().apiKey("your.api.key").build();
ZaiClient client = ZaiClient.builder().apiKey("your.api_key").build();
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model("glm-4v-plus-0111")

View file

@ -15,7 +15,7 @@ public class ViduAspectVideoExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().build();

View file

@ -13,7 +13,7 @@ public class ViduImageToVideoExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().build();

View file

@ -15,7 +15,7 @@ public class ViduStartEndVideoExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().build();

View file

@ -13,13 +13,13 @@ public class ViduTextToVideoExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().build();
// Or set API Key via code
// ZaiClient client = ZaiClient.builder()
// .apiKey("your.api.key")
// .apiKey("your.api_key")
// .build();
// Example: Generate video from text using Vidu

View file

@ -23,13 +23,13 @@ public class WebSearchExample {
public static void main(String[] args) {
// Create client, recommended to set API Key via environment variable
// export ZAI_API_KEY=your.api.key
// export ZAI_API_KEY=your.api_key
// for Z.ai use the `ZaiClient`, for Zhipu AI use the ZhipuAiClient
ZaiClient client = ZaiClient.builder().build();
// Or set API Key via code
// ZaiClient client = ZaiClient.builder()
// .apiKey("your.api.key")
// .apiKey("your.api_key")
// .build();
// Example 1: Basic Web Search