chore: remove the client params apiId and apiSecret, fix cache token bug (#58)

This commit is contained in:
Tomsun28 2025-10-14 20:08:02 +08:00 committed by GitHub
parent a3cfd23511
commit 8f5f986298
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 204 additions and 57 deletions

View file

@ -54,16 +54,6 @@ public class ZaiConfig {
*/ */
private String apiKey; private String apiKey;
/**
* API id component.
*/
private String apiId;
/**
* API secret component.
*/
private String apiSecret;
/** /**
* Custom Http Request Headers * Custom Http Request Headers
*/ */
@ -84,7 +74,8 @@ public class ZaiConfig {
/** /**
* Flag to disable token caching. * Flag to disable token caching.
*/ */
private boolean disableTokenCache; @Builder.Default
private boolean disableTokenCache = true;
/** /**
* Maximum number of idle connections in the connection pool. * Maximum number of idle connections in the connection pool.
@ -96,7 +87,7 @@ public class ZaiConfig {
* Keep alive duration for connections in the pool (in seconds). * Keep alive duration for connections in the pool (in seconds).
*/ */
@Builder.Default @Builder.Default
private long connectionPoolKeepAliveDuration = 1; private long connectionPoolKeepAliveDuration = 10;
/** /**
* Time unit for connection pool keep alive duration. * Time unit for connection pool keep alive duration.
@ -149,10 +140,8 @@ public class ZaiConfig {
this.apiKey = apiKey; this.apiKey = apiKey;
String[] arrStr = apiKey.split("\\."); String[] arrStr = apiKey.split("\\.");
if (arrStr.length != 2) { if (arrStr.length != 2) {
throw new RuntimeException("invalid apiSecretKey"); throw new RuntimeException("invalid api Key");
} }
this.apiId = arrStr[0];
this.apiSecret = arrStr[1];
} }
/** /**
@ -166,8 +155,6 @@ public class ZaiConfig {
if (arrStr.length != 2) { if (arrStr.length != 2) {
throw new RuntimeException("invalid api Key"); throw new RuntimeException("invalid api Key");
} }
this.apiId = arrStr[0];
this.apiSecret = arrStr[1];
} }
/** /**
@ -194,38 +181,10 @@ public class ZaiConfig {
if (value != null && !value.isEmpty()) { if (value != null && !value.isEmpty()) {
// Parse value and set components // Parse value and set components
this.apiKey = value; this.apiKey = value;
String[] arrStr = value.split("\\.");
if (arrStr.length == 2) {
this.apiId = arrStr[0];
this.apiSecret = arrStr[1];
}
return value;
} }
return apiKey; return apiKey;
} }
/**
* Gets API key with system property and environment variable fallback.
*/
public String getApiId() {
if (apiId != null && !apiId.isEmpty()) {
return apiId;
}
getApiKey();
return apiId;
}
/**
* Gets API secret with system property and environment variable fallback.
*/
public String getApiSecret() {
if (apiSecret != null && !apiSecret.isEmpty()) {
return apiSecret;
}
getApiKey();
return apiSecret;
}
/** /**
* Gets expire millis with system property and environment variable fallback. * Gets expire millis with system property and environment variable fallback.
*/ */

View file

@ -44,7 +44,12 @@ public class TokenManager {
* @return valid JWT token * @return valid JWT token
*/ */
public String getToken(ZaiConfig config) { public String getToken(ZaiConfig config) {
String tokenCacheKey = genTokenCacheKey(config.getApiId()); String[] arrStr = config.getApiKey().split("\\.");
if (arrStr.length != 2) {
throw new RuntimeException("invalid api Key");
}
String appId = arrStr[0];
String tokenCacheKey = genTokenCacheKey(appId);
String cacheToken = cache.get(tokenCacheKey); String cacheToken = cache.get(tokenCacheKey);
if (StringUtils.isNotEmpty(cacheToken)) { if (StringUtils.isNotEmpty(cacheToken)) {
return cacheToken; return cacheToken;
@ -62,9 +67,15 @@ public class TokenManager {
private static String createJwt(ZaiConfig config) { private static String createJwt(ZaiConfig config) {
Algorithm alg; Algorithm alg;
String algId = config.getAlg(); String algId = config.getAlg();
String[] arrStr = config.getApiKey().split("\\.");
if (arrStr.length != 2) {
throw new RuntimeException("invalid api Key");
}
String appId = arrStr[0];
String apiSecret = arrStr[1];
if ("HS256".equals(algId)) { if ("HS256".equals(algId)) {
try { try {
alg = Algorithm.HMAC256(config.getApiSecret().getBytes(StandardCharsets.UTF_8)); alg = Algorithm.HMAC256(apiSecret.getBytes(StandardCharsets.UTF_8));
} }
catch (Exception e) { catch (Exception e) {
logger.error("Failed to create HMAC256 algorithm", e); logger.error("Failed to create HMAC256 algorithm", e);
@ -79,7 +90,7 @@ public class TokenManager {
Map<String, Object> payload = new HashMap<>(); Map<String, Object> payload = new HashMap<>();
// here the api_key is the apiId // here the api_key is the apiId
payload.put("api_key", config.getApiId()); payload.put("api_key", appId);
payload.put("exp", System.currentTimeMillis() + config.getExpireMillis() + DELAY_EXPIRE_TIME); payload.put("exp", System.currentTimeMillis() + config.getExpireMillis() + DELAY_EXPIRE_TIME);
payload.put("timestamp", Calendar.getInstance().getTimeInMillis()); payload.put("timestamp", Calendar.getInstance().getTimeInMillis());
Map<String, Object> headerClaims = new HashMap<>(); Map<String, Object> headerClaims = new HashMap<>();

View file

@ -38,8 +38,7 @@ public class ChatAsyncCompletionExample {
.build() .build()
)) ))
.stream(false) .stream(false)
.temperature(0.7f) .temperature(1.0f)
.maxTokens(1024)
.build(); .build();
try { try {

View file

@ -35,8 +35,7 @@ public class ChatCompletionExample {
.stream(false) .stream(false)
.thinking(ChatThinking.builder().type(ChatThinkingType.ENABLED.value()).build()) .thinking(ChatThinking.builder().type(ChatThinkingType.ENABLED.value()).build())
.responseFormat(ResponseFormat.builder().type(ResponseFormatType.TEXT.value()).build()) .responseFormat(ResponseFormat.builder().type(ResponseFormatType.TEXT.value()).build())
.temperature(0.7f) .temperature(1.0f)
.maxTokens(1024)
.build(); .build();
try { try {

View file

@ -30,8 +30,6 @@ public class ChatCompletionWithCustomHeadersExample {
.build() .build()
)) ))
.stream(true) // Enable streaming for custom headers support .stream(true) // Enable streaming for custom headers support
.temperature(0.7f)
.maxTokens(1024)
.build(); .build();
// Create custom headers // Create custom headers

View file

@ -0,0 +1,75 @@
package ai.z.openapi.samples;
import ai.z.openapi.ZhipuAiClient;
import ai.z.openapi.service.model.ChatCompletionCreateParams;
import ai.z.openapi.service.model.ChatCompletionResponse;
import ai.z.openapi.service.model.ChatMessage;
import ai.z.openapi.service.model.ChatMessageRole;
import ai.z.openapi.service.model.ChatThinking;
import ai.z.openapi.service.model.ChatThinkingType;
import ai.z.openapi.service.model.ChatTool;
import ai.z.openapi.service.model.ChatToolType;
import ai.z.openapi.service.model.MCPTool;
import ai.z.openapi.service.model.ResponseFormat;
import ai.z.openapi.service.model.ResponseFormatType;
import java.util.Collections;
/**
* Chat Completion Example
* Demonstrates how to use ZaiClient for basic chat conversations
*/
public class ChatCompletionWithMcpServerUrlExample {
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();
// Or set API Key via code
// ZaiClient client = ZaiClient.builder()
// .apiKey("your.api_key")
// .build();
// Create chat request
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model("glm-4.6")
.messages(Collections.singletonList(
ChatMessage.builder()
.role(ChatMessageRole.USER.value())
.content("Hello, how to learn english?")
.build()
))
.stream(false)
.thinking(ChatThinking.builder().type(ChatThinkingType.ENABLED.value()).build())
.responseFormat(ResponseFormat.builder().type(ResponseFormatType.TEXT.value()).build())
.temperature(1.0f)
.maxTokens(1024)
.tools(Collections.singletonList(ChatTool.builder()
.type(ChatToolType.MCP.value())
.mcp(MCPTool.builder()
.server_url("https://open.bigmodel.cn/api/mcp-broker/proxy/sogou-baike/sse")
.server_label("sogou-baike")
.transport_type("sse")
.headers(Collections.singletonMap("Authorization", "Bearer " + System.getProperty("ZAI_API_KEY")))
.build())
.build()))
.build();
try {
// Execute request
ChatCompletionResponse response = client.chat().createChatCompletion(request);
if (response.isSuccess()) {
Object content = response.getData().getChoices().get(0).getMessage();
System.out.println("Response: " + content);
} else {
System.err.println("Error: " + response.getMsg());
}
} catch (Exception e) {
System.err.println("Exception occurred: " + e.getMessage());
e.printStackTrace();
}
}
}

View file

@ -0,0 +1,108 @@
package ai.z.openapi.samples;
import ai.z.openapi.ZhipuAiClient;
import ai.z.openapi.core.Constants;
import ai.z.openapi.core.config.ZaiConfig;
import ai.z.openapi.service.model.ChatCompletionCreateParams;
import ai.z.openapi.service.model.ChatCompletionResponse;
import ai.z.openapi.service.model.ChatMessage;
import ai.z.openapi.service.model.ChatMessageRole;
import ai.z.openapi.service.model.ChatThinking;
import ai.z.openapi.service.model.ChatThinkingType;
import ai.z.openapi.service.model.Choice;
import ai.z.openapi.service.model.Delta;
import ai.z.openapi.service.model.ResponseFormat;
import ai.z.openapi.service.model.ResponseFormatType;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* Chat Completion Example
* Demonstrates how to use ZaiClient for basic chat conversations
*/
public class CustomClientExample {
public static void main(String[] args) throws Exception {
// 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
ZaiConfig zaiConfig = ZaiConfig.builder()
.apiKey(System.getenv("ZAI_API_KEY"))
.baseUrl(Constants.ZHIPU_AI_BASE_URL)
.customHeaders(Collections.emptyMap())
.disableTokenCache(true)
.requestTimeOut(600)
.timeOutTimeUnit(TimeUnit.SECONDS)
.connectTimeout(60)
.connectionPoolKeepAliveDuration(10)
.connectionPoolTimeUnit(TimeUnit.SECONDS)
.connectionPoolMaxIdleConnections(20)
.build();
ZhipuAiClient client = new ZhipuAiClient(zaiConfig);
// Or set API Key via code
// ZaiClient client = ZaiClient.builder()
// .apiKey("your.api_key")
// .build();
// Create chat request
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model("glm-4.6")
.messages(Arrays.asList(
ChatMessage.builder()
.role(ChatMessageRole.USER.value())
.content("Hello, are you there")
.build()
))
.stream(true)
.thinking(ChatThinking.builder().type(ChatThinkingType.ENABLED.value()).build())
.responseFormat(ResponseFormat.builder().type(ResponseFormatType.TEXT.value()).build())
.temperature(1.0f)
.build();
// Create latch to wait for streaming completion
CountDownLatch latch = new CountDownLatch(1);
try {
// Execute request
ChatCompletionResponse response = client.chat().createChatCompletion(request);
if (response.isSuccess() && response.getFlowable() != null) {
System.out.println("Starting streaming response...");
response.getFlowable().subscribe(
data -> {
// Process each streaming response chunk
if (data.getChoices() != null && !data.getChoices().isEmpty()) {
// Get content of current chunk
Choice choice = data.getChoices().get(0);
System.out.print(choice + "\n");
}
},
error -> {
System.err.println("\nStream error: " + error.getMessage());
latch.countDown(); // Release latch on error
},
// Process streaming response completion event
() -> {
System.out.println("\nStreaming response completed");
latch.countDown(); // Release latch on completion
}
);
// Wait for streaming to complete (max 60 seconds)
latch.await(60, TimeUnit.SECONDS);
} else {
System.err.println("Error: " + response.getMsg());
}
} catch (Exception e) {
System.err.println("Exception occurred: " + e.getMessage());
e.printStackTrace();
} finally {
client.close();
}
}
}

View file

@ -30,7 +30,7 @@ public class CustomTimeoutExample {
// Create chat request // Create chat request
ChatCompletionCreateParams request = ChatCompletionCreateParams.builder() ChatCompletionCreateParams request = ChatCompletionCreateParams.builder()
.model(Constants.ModelChatGLM4_5) .model("glm-4.6")
.messages(Arrays.asList( .messages(Arrays.asList(
ChatMessage.builder() ChatMessage.builder()
.role(ChatMessageRole.USER.value()) .role(ChatMessageRole.USER.value())
@ -40,8 +40,6 @@ public class CustomTimeoutExample {
.stream(false) .stream(false)
.thinking(ChatThinking.builder().type(ChatThinkingType.ENABLED.value()).build()) .thinking(ChatThinking.builder().type(ChatThinkingType.ENABLED.value()).build())
.responseFormat(ResponseFormat.builder().type(ResponseFormatType.TEXT.value()).build()) .responseFormat(ResponseFormat.builder().type(ResponseFormatType.TEXT.value()).build())
.temperature(0.7f)
.maxTokens(1024)
.build(); .build();
try { try {