* init project * init project * init project * init project * init project * init project * update action * update action * update action * update action * java format * java format * update code and format * update code and format * update code and format * update code and format * update code and format * update code and format * update version * fix publish * fix publish * fix publish * fix publish * fix publish * fix publish * fix publish * fix publish * fix publish * fix publish * fix publish * fix publish
23 KiB
Z.ai SDK Java - Architecture Documentation
Overview
The Z.ai SDK Java provides a service-oriented architecture that offers clean separation of concerns, comprehensive configuration management, and support for both synchronous and streaming operations. The SDK is built around a client-service pattern with reactive programming support.
Architecture Components
1. Core Client Architecture
ZaiClient
The main client class that serves as the entry point for all AI services:
public class ZaiClient extends AbstractClientBaseService {
// Service instances
private ChatService chatService;
private AgentService agentService;
private EmbeddingService embeddingService;
// ... other services
// Constructor
public ZaiClient(ZaiConfig config) {
// Initialize HTTP client and Retrofit
}
// Service accessors
public synchronized ChatService chat() { /* ... */ }
public synchronized AgentService agents() { /* ... */ }
// ... other service accessors
}
Base Request and Response Models
ClientRequest Interface: Base interface for all service requests
public interface ClientRequest<T> {
// Marker interface for type safety
}
ClientResponse Interface: Base interface for all service responses
public interface ClientResponse<T> {
T getData();
void setData(T data);
void setCode(int code);
void setMsg(String msg);
void setSuccess(boolean success);
void setError(ChatError error);
}
FlowableClientResponse Interface: Extended interface for streaming responses
public interface FlowableClientResponse<T> extends ClientResponse<T> {
void setFlowable(Flowable<T> stream);
}
2. Configuration Management
ZaiConfig
Main configuration class that contains all SDK settings:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ZaiConfig {
private String baseUrl;
private String apiSecretKey;
private String apiKey;
private String apiSecret;
private int expireMillis = 30 * 60 * 1000; // 30 minutes
private String alg = "HS256";
private boolean disableTokenCache;
// Connection pool settings
private int connectionPoolMaxIdleConnections = 5;
private long connectionPoolKeepAliveDuration = 1;
private TimeUnit connectionPoolTimeUnit = TimeUnit.SECONDS;
// Timeout settings
private int requestTimeOut;
private int connectTimeout;
private int readTimeout;
private int writeTimeout;
private TimeUnit timeOutTimeUnit;
private String source_channel;
}
Configuration Features
-
Authentication Settings
- API secret key in format
{apiKey}.{apiSecret} - JWT token expiration and algorithm configuration
- Token caching control
- API secret key in format
-
Network Configuration
- Base URL for API endpoints
- Connection pool settings (max idle connections, keep-alive duration)
- Timeout configurations (request, connect, read, write)
-
Token Management
- JWT token generation and caching
- Configurable expiration times
- Option to disable token caching for direct API key usage
3. Service Implementations
ChatService
Provides chat completion functionality with support for synchronous, asynchronous, and streaming operations:
public interface ChatService {
/**
* Creates a chat completion, either streaming or non-streaming based on the request configuration.
*/
ChatCompletionResponse createChatCompletion(ChatCompletionCreateParams request);
/**
* Creates an asynchronous chat completion.
*/
ChatCompletionResponse asyncChatCompletion(ChatCompletionCreateParams request);
/**
* Retrieves the result of an asynchronous model operation.
*/
QueryModelResultResponse retrieveAsyncResult(AsyncResultRetrieveParams request);
}
Service Implementation Pattern
All services follow a consistent implementation pattern:
public class ChatServiceImpl implements ChatService {
private final ZaiClient zAiClient;
private final ChatApi chatApi;
public ChatServiceImpl(ZaiClient zAiClient) {
this.zAiClient = zAiClient;
this.chatApi = this.zAiClient.retrofit().create(ChatApi.class);
}
@Override
public ChatCompletionResponse createChatCompletion(ChatCompletionCreateParams request) {
// Parameter validation
String paramMsg = validateParams(request);
if (StringUtils.isNotEmpty(paramMsg)) {
return new ChatCompletionResponse(-100, String.format("invalid param: %s", paramMsg));
}
// Route to streaming or synchronous execution
if (request.getStream()) {
return streamChatCompletion(request);
} else {
return syncChatCompletion(request);
}
}
}
Usage Examples
Basic Configuration
// Simple configuration with API secret key
ZaiConfig config = new ZaiConfig("your.api.key.your.api.secret");
ZaiClient client = new ZaiClient(config);
// Or using separate API key and secret
ZaiConfig config = new ZaiConfig("your.api.key", "your.api.secret");
ZaiClient client = new ZaiClient(config);
Builder Pattern Configuration
// Using the Builder pattern for advanced configuration
ZaiClient client = new ZaiClient.Builder("your.api.key.your.api.secret")
.enableTokenCache()
.networkConfig(
300, // request timeout
100, // connect timeout
100, // read timeout
100, // write timeout
TimeUnit.SECONDS
)
.connectionPool(
10, // max idle connections
5, // keep alive duration
TimeUnit.MINUTES
)
.tokenExpire(3600000) // 1 hour in milliseconds
.build();
Custom Configuration with ZaiConfig
ZaiConfig config = ZaiConfig.builder()
.apiSecretKey("your.api.key.your.api.secret")
.baseUrl("https://custom.api.endpoint")
.requestTimeOut(60)
.connectTimeout(30)
.readTimeout(30)
.writeTimeout(30)
.timeOutTimeUnit(TimeUnit.SECONDS)
.disableTokenCache(false)
.expireMillis(7200000) // 2 hours
.connectionPoolMaxIdleConnections(10)
.connectionPoolKeepAliveDuration(5)
.connectionPoolTimeUnit(TimeUnit.MINUTES)
.build();
ZaiClient client = new ZaiClient(config);
Service Usage
// Get service instance
ChatService chatService = client.chat();
// Create chat request
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model("glm-4")
.messages(Arrays.asList(
ChatMessage.builder()
.role(ChatMessage.Role.USER)
.content("Hello, world!")
.build()
))
.stream(false) // Set to true for streaming
.temperature(0.7f)
.maxTokens(1024)
.build();
// Execute request
try {
ChatCompletionResponse response = chatService.createChatCompletion(request);
if (response.isSuccess()) {
ModelData data = response.getData();
if (data != null && data.getChoices() != null && !data.getChoices().isEmpty()) {
String content = data.getChoices().get(0).getMessage().getContent();
System.out.println("Response: " + content);
}
} else {
System.err.println("Error: " + response.getMsg());
if (response.getError() != null) {
System.err.println("Error details: " + response.getError().getMessage());
}
}
} catch (Exception e) {
System.err.println("Request failed: " + e.getMessage());
}
Streaming Usage
// Create streaming request
ChatCompletionCreateParams streamRequest = ChatCompletionCreateParams.builder()
.model("glm-4")
.messages(Arrays.asList(
ChatMessage.builder()
.role(ChatMessage.Role.USER)
.content("Tell me a story")
.build()
))
.stream(true) // Enable streaming
.temperature(0.7f)
.maxTokens(1024)
.build();
// Execute streaming request
ChatCompletionResponse response = chatService.createChatCompletion(streamRequest);
if (response.isSuccess() && response.getFlowable() != null) {
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("Failed to start streaming: " + response.getMsg());
}
Asynchronous Usage
// Create async request
ChatCompletionCreateParams asyncRequest = ChatCompletionCreateParams.builder()
.model("glm-4")
.messages(Arrays.asList(
ChatMessage.builder()
.role(ChatMessage.Role.USER)
.content("Generate a long document")
.build()
))
.build();
// Execute async request
ChatCompletionResponse asyncResponse = chatService.asyncChatCompletion(asyncRequest);
if (asyncResponse.isSuccess()) {
String taskId = asyncResponse.getData().getTaskId();
System.out.println("Async task started with ID: " + taskId);
// Poll for results
AsyncResultRetrieveParams retrieveParams = new AsyncResultRetrieveParams();
retrieveParams.setId(taskId);
QueryModelResultResponse result = chatService.retrieveAsyncResult(retrieveParams);
// Handle result...
}
Available Services
The ZaiClient provides access to multiple AI services:
ZaiClient client = new ZaiClient(config);
// Chat completion service
ChatService chatService = client.chat();
// Agent service for agent-based completions
AgentService agentService = client.agents();
// Embedding service for text embeddings
EmbeddingService embeddingService = client.embeddings();
// File management service
FileService fileService = client.files();
// Audio processing service
AudioService audioService = client.audio();
// Image generation service
ImageService imageService = client.images();
// Batch processing service
BatchService batchService = client.batches();
// Fine-tuning service
FineTuningService fineTuningService = client.fineTuning();
// Web search service
WebSearchService webSearchService = client.webSearch();
// Video processing service
VideosService videosService = client.videos();
// Knowledge base service
KnowledgeService knowledgeService = client.knowledge();
// Document management service
DocumentService documentService = client.documents();
// Assistant service
AssistantService assistantService = client.assistants();
Request and Response Models
Common Request Structure
All requests extend CommonRequest which provides common fields:
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class CommonRequest {
@JsonProperty("request_id")
private String requestId;
@JsonProperty("user_id")
private String userId;
// Additional common fields...
}
Chat Request Example
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class ChatCompletionCreateParams extends CommonRequest implements ClientRequest<ChatCompletionCreateParams> {
private String model;
private List<ChatMessage> messages;
private Boolean stream;
private Float temperature;
@JsonProperty("max_tokens")
private Integer maxTokens;
private List<String> stop;
private List<ChatTool> tools;
// ... other fields
}
Response Structure
All responses implement ClientResponse or FlowableClientResponse:
@Data
public class ChatCompletionResponse implements FlowableClientResponse<ModelData> {
private int code;
private String msg;
private boolean success;
private ModelData data;
private Flowable<ModelData> flowable; // For streaming responses
private ChatError error;
}
Error Handling
Response Error Handling
ChatCompletionResponse response = chatService.createChatCompletion(request);
// Check if the request was successful
if (!response.isSuccess()) {
int errorCode = response.getCode();
String errorMessage = response.getMsg();
System.err.println("Request failed with code: " + errorCode);
System.err.println("Error message: " + errorMessage);
// Check for detailed error information
if (response.getError() != null) {
ChatError error = response.getError();
System.err.println("Error code: " + error.getCode());
System.err.println("Error details: " + error.getMessage());
// Handle specific error types
switch (errorCode) {
case 400:
System.err.println("Bad request - check your parameters");
break;
case 401:
System.err.println("Authentication failed - check your API key");
break;
case 429:
System.err.println("Rate limit exceeded - please retry later");
break;
case 500:
System.err.println("Server error - please try again");
break;
default:
System.err.println("Unexpected error occurred");
}
}
return;
}
// Process successful response
ModelData data = response.getData();
if (data != null) {
// Handle successful response data
System.out.println("Request completed successfully");
}
Exception Handling
try {
ChatCompletionResponse response = chatService.createChatCompletion(request);
// Process response...
} catch (ZAiHttpException e) {
// Handle HTTP-specific errors
System.err.println("HTTP Error: " + e.getMessage());
System.err.println("Status Code: " + e.statusCode);
System.err.println("Error Code: " + e.code);
} catch (Exception e) {
// Handle other exceptions
System.err.println("Unexpected error: " + e.getMessage());
e.printStackTrace();
}
Extension Points
Custom Service Implementation
public class CustomService implements AIService<CustomRequest, CustomResponse> {
@Override
public CustomResponse execute(CustomRequest request) throws Exception {
// Implementation
}
@Override
public CompletableFuture<CustomResponse> executeAsync(CustomRequest request) {
// Implementation
}
@Override
public Flowable<CustomResponse> executeStream(CustomRequest request) throws Exception {
// Implementation
}
@Override
public void validateRequest(CustomRequest request) throws IllegalArgumentException {
// Validation logic
}
@Override
public String getServiceType() {
return "CUSTOM_SERVICE";
}
}
// Register custom service
client.registerService("CUSTOM_SERVICE", new CustomService());
Custom Configuration
// Extend configuration for custom needs
ZaiConfiguration customConfig = ZaiConfigurationBuilder.newBuilder()
.apiSecretKey("your.api.key")
.baseUrl("https://custom.endpoint")
// Add custom settings
.build();
// Add custom metadata to configuration
customConfig.getAuth().addMetadata("customAuth", "value");
customConfig.getNetwork().addMetadata("customNetwork", "value");
Best Practices
Configuration Management
// Use builder pattern for configuration
ZaiConfig config = ZaiConfig.builder()
.apiSecretKey("your.api.key.your.api.secret")
.baseUrl("https://open.bigmodel.cn/")
.requestTimeOut(60)
.connectTimeout(30)
.readTimeout(30)
.writeTimeout(30)
.timeOutTimeUnit(TimeUnit.SECONDS)
.disableTokenCache(false)
.expireMillis(3600000) // 1 hour
.connectionPoolMaxIdleConnections(10)
.connectionPoolKeepAliveDuration(5)
.connectionPoolTimeUnit(TimeUnit.MINUTES)
.build();
ZaiClient client = new ZaiClient(config);
Request Building
// Use builder pattern for creating requests
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model("glm-4")
.messages(Arrays.asList(
ChatMessage.builder()
.role(ChatMessage.Role.USER)
.content("Hello, world!")
.build()
))
.temperature(0.7f)
.maxTokens(1000)
.stream(false)
.build();
Error Handling
// Comprehensive error handling
ChatCompletionResponse response = chatService.createChatCompletion(request);
if (!response.isSuccess()) {
System.err.println("Request failed: " + response.getMsg());
if (response.getError() != null) {
System.err.println("Error details: " + response.getError().getMessage());
}
return;
}
// Process successful response
ModelData data = response.getData();
if (data != null && data.getChoices() != null && !data.getChoices().isEmpty()) {
String content = data.getChoices().get(0).getMessage().getContent();
System.out.println("Response: " + content);
}
Streaming Best Practices
// Handle streaming responses properly
ChatCompletionCreateParams streamRequest = request.toBuilder()
.stream(true)
.build();
ChatCompletionResponse response = chatService.createChatCompletion(streamRequest);
if (response.isSuccess() && response.getFlowable() != null) {
response.getFlowable()
.observeOn(Schedulers.io())
.subscribe(
data -> {
// Process each 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("Streaming error: " + error.getMessage());
},
() -> {
System.out.println("\nStreaming completed");
}
);
}
Resource Management
// Properly manage client lifecycle
try {
ZaiClient client = new ZaiClient(config);
ChatService chatService = client.chat();
// Use the service...
ChatCompletionResponse response = chatService.createChatCompletion(request);
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
} finally {
// Clean up resources if needed
}
Asynchronous Processing
// Use async operations for long-running tasks
ChatCompletionResponse asyncResponse = chatService.asyncChatCompletion(request);
if (asyncResponse.isSuccess()) {
String taskId = asyncResponse.getData().getTaskId();
// Poll for results
AsyncResultRetrieveParams retrieveParams = new AsyncResultRetrieveParams();
retrieveParams.setId(taskId);
// Implement polling logic with backoff
CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000); // Wait before polling
return chatService.retrieveAsyncResult(retrieveParams);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}).thenAccept(result -> {
// Handle result
if (result.isSuccess()) {
System.out.println("Async task completed");
}
});
}
Security Best Practices
- API Key Management: Store API keys securely, never hardcode them
- Token Caching: Enable token caching to reduce authentication overhead
- Request Validation: Always validate input parameters
- Error Logging: Log errors but never log sensitive information
- Timeout Configuration: Set appropriate timeouts to prevent hanging requests
- Connection Pooling: Configure connection pools for optimal performance
- Rate Limiting: Implement client-side rate limiting to respect API limits
Migration Guide
Upgrading to Latest Version
This guide helps you migrate from older versions of the Z-AI SDK to the current architecture.
Key Changes in Current Version
- Unified Client Architecture: All services are now accessed through
ZaiClient - Improved Configuration:
ZaiConfigwith builder pattern for better flexibility - Standardized Request/Response: All requests implement
ClientRequest, responses implementClientResponse - Enhanced Streaming: Better support for streaming responses with
FlowableClientResponse - Comprehensive Service Coverage: Support for Chat, Agents, Embeddings, Files, Audio, Images, and more
Configuration Migration
// If you were using basic configuration
// Old approach (if applicable)
String apiKey = "your-api-key";
String apiSecret = "your-api-secret";
// New approach
ZaiConfig config = ZaiConfig.builder()
.apiKey(apiKey)
.apiSecret(apiSecret)
.baseUrl("https://open.bigmodel.cn/")
.enableTokenCache(true)
.tokenExpiredSeconds(3600)
.build();
ZaiClient client = new ZaiClient(config);
Service Usage Migration
// Modern service usage
ChatService chatService = client.chat();
EmbeddingService embeddingService = client.embeddings();
FileService fileService = client.files();
AudioService audioService = client.audio();
ImageService imageService = client.images();
// ... and more services
Request Building Migration
// Use builder pattern for all requests
ChatCompletionCreateParams chatRequest = ChatCompletionCreateParams.builder()
.model("glm-4")
.messages(Arrays.asList(
ChatMessage.builder()
.role(ChatMessage.Role.USER)
.content("Hello, world!")
.build()
))
.temperature(0.7f)
.maxTokens(1000)
.build();
Response Handling Migration
// Standardized response handling
ChatCompletionResponse response = chatService.createChatCompletion(chatRequest);
if (response.isSuccess()) {
ModelData data = response.getData();
// Process successful response
} else {
System.err.println("Error: " + response.getMsg());
if (response.getError() != null) {
System.err.println("Details: " + response.getError().getMessage());
}
}
Streaming Migration
// Enhanced streaming support
ChatCompletionCreateParams streamRequest = chatRequest.toBuilder()
.stream(true)
.build();
ChatCompletionResponse streamResponse = chatService.createChatCompletion(streamRequest);
if (streamResponse.isSuccess() && streamResponse.getFlowable() != null) {
streamResponse.getFlowable()
.subscribe(
data -> {
// Process streaming data
},
error -> {
// Handle streaming errors
},
() -> {
// Streaming completed
}
);
}
Best Practices for Migration
- Update Dependencies: Ensure you're using the latest version of the SDK
- Review Configuration: Update your configuration to use
ZaiConfig.builder() - Update Service Access: Use
ZaiClientto access all services - Standardize Error Handling: Use the new response structure for error handling
- Test Thoroughly: Test all functionality after migration
- Update Documentation: Update your internal documentation to reflect the new patterns
This architecture provides a solid foundation for future enhancements while maintaining backward compatibility where possible.