diff --git a/java/README.md b/java/README.md
index fa6de481..a33e936b 100644
--- a/java/README.md
+++ b/java/README.md
@@ -12,7 +12,7 @@
com.baidubce
qianfan
- 0.0.9
+ 0.1.0
```
@@ -21,13 +21,13 @@
对于Kotlin DSL,在build.gradle.kts的dependencies中添加依赖。
```kotlin
-implementation("com.baidubce:qianfan:0.0.9")
+implementation("com.baidubce:qianfan:0.1.0")
```
对于Groovy DSL,在build.gradle的dependencies中添加依赖。
```groovy
-implementation 'com.baidubce:qianfan:0.0.9'
+implementation 'com.baidubce:qianfan:0.1.0'
```
> 我们提供了一些 [示例](./examples),可以帮助快速了解 SDK 的使用方法并完成常见功能。
diff --git a/java/example/pom.xml b/java/example/pom.xml
index 52509fba..1de49559 100644
--- a/java/example/pom.xml
+++ b/java/example/pom.xml
@@ -18,7 +18,7 @@
com.baidubce
qianfan
- 0.0.9
+ 0.1.0
diff --git a/java/example/src/main/java/com/baidubce/ConsoleExample.java b/java/example/src/main/java/com/baidubce/ConsoleExample.java
new file mode 100644
index 00000000..9b214b7b
--- /dev/null
+++ b/java/example/src/main/java/com/baidubce/ConsoleExample.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2024 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.baidubce;
+
+import com.baidubce.qianfan.Qianfan;
+import com.baidubce.qianfan.util.CollUtils;
+
+import java.util.Map;
+
+/**
+ * 本示例实现了Console管控API调用流程
+ * API文档可见 API列表
+ */
+public class ConsoleExample {
+ public static void main(String[] args) {
+ describePresetServices();
+ describeTPMResource();
+ }
+
+ private static void describePresetServices() {
+ // 获取预置服务列表 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Glygmrg7v
+ Map response = new Qianfan().console()
+ // 对应文档中请求地址的后缀
+ .route("/v2/service")
+ // 对应文档中Query参数的Action
+ .action("DescribePresetServices")
+ // 如果不传入任何Response类,则默认返回Map
+ .execute()
+ // 可以传入class或者TypeRef来指定反序列化后返回的Response类
+ // .execute(DescribePresetServicesResponse.class)
+ .getResult();
+ System.out.println(response);
+ }
+
+ private static void describeTPMResource() {
+ // 查询TPM配额信息详情 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/ultmls9l9
+ Map response = new Qianfan().console().route("/v2/charge").action("DescribeTPMResource")
+ // 需要传入参数的场景,可以自行封装请求类,或者使用Map.of()来构建请求Body
+ // Java 8可以使用SDK提供的CollUtils.mapOf()来替代Map.of()
+ .body(CollUtils.mapOf(
+ "model", "ernie-4.0-8k",
+ "paymentTiming", "Postpaid"
+ ))
+ .execute()
+ .getResult();
+ System.out.println(response);
+ }
+}
+
+
diff --git a/java/example/src/main/java/com/baidubce/SystemMemoryExample.java b/java/example/src/main/java/com/baidubce/SystemMemoryExample.java
new file mode 100644
index 00000000..33263aef
--- /dev/null
+++ b/java/example/src/main/java/com/baidubce/SystemMemoryExample.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2024 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.baidubce;
+
+import com.baidubce.qianfan.Qianfan;
+import com.baidubce.qianfan.core.auth.Auth;
+import com.baidubce.qianfan.core.builder.MessageBuilder;
+import com.baidubce.qianfan.model.chat.Message;
+import com.baidubce.qianfan.util.CollUtils;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 本示例实现了简易的系统记忆管理接口及推理接口的全流程调用
+ * 系统记忆Console接口文档可见 创建系统记忆
+ */
+public class SystemMemoryExample {
+ // 在模型服务-应用接入中创建应用,即可获得应用的AppID、API Key和Secret Key
+ private static final String APP_ID = "替换为实际的AppId";
+ private static final String APP_API_KEY = "替换为实际的ApiKey";
+ private static final String APP_SECRET_KEY = "替换为实际的SecretKey";
+
+ public static void main(String[] args) throws InterruptedException {
+ // 注意,在生产环境中,应当手动创建一个系统记忆并维护记忆内容,然后在推理中重复使用该系统记忆
+ String systemMemoryId = createSystemMemory(APP_ID, "度小茶饮品店智能客服系统记忆");
+ System.out.println("系统记忆ID:" + systemMemoryId);
+
+ Boolean result = modifySystemMemory(systemMemoryId, CollUtils.listOf(
+ new MessageBuilder()
+ .add("user", "你的幸运数字是什么?")
+ .add("system", "我的幸运数字是42。")
+ .build(),
+ new MessageBuilder()
+ .add("user", "能推荐一款适合夏天饮用的饮品吗?")
+ .add("system", "当然可以,我们推荐冰镇柠檬绿茶,清新爽口,非常适合夏日消暑。")
+ .build()
+ ));
+ System.out.println("修改系统记忆结果:" + result);
+
+ Thread.sleep(5000);
+
+ Map memories = describeSystemMemory(systemMemoryId);
+ System.out.println("记忆列表:" + memories);
+
+ String system = "你是度小茶饮品店的智能客服。";
+ String response = chat(systemMemoryId, system, "你的幸运数字是什么");
+ System.out.println("推理结果:" + response);
+ String response2 = chat(systemMemoryId, system, "推荐一个适合夏天的饮料");
+ System.out.println("推理结果2:" + response2);
+ }
+
+ private static String createSystemMemory(String appId, String description) {
+ return new Qianfan().console()
+ .route("/v2/memory")
+ .action("CreateSystemMemory")
+ .body(CollUtils.mapOf(
+ "appId", appId,
+ "description", description
+ ))
+ .execute(String.class)
+ .getResult();
+ }
+
+ private static Boolean modifySystemMemory(String systemMemoryId, List> memories) {
+ return new Qianfan().console()
+ .route("/v2/memory")
+ .action("ModifySystemMemory")
+ .body(CollUtils.mapOf(
+ "systemMemoryId", systemMemoryId,
+ "memories", memories
+ ))
+ .execute(Boolean.class)
+ .getResult();
+ }
+
+ private static Map describeSystemMemory(String systemMemoryId) {
+ return new Qianfan().console()
+ .route("/v2/memory")
+ .action("DescribeSystemMemory")
+ .body(CollUtils.mapOf(
+ "systemMemoryId", systemMemoryId
+ ))
+ .execute()
+ .getResult();
+ }
+
+ private static String chat(String systemMemoryId, String system, String query) {
+ // 使用系统记忆时,鉴权需要使用OAuth方式,同时需要传入与系统记忆相同应用的Api Key和Secret Key
+ return new Qianfan(Auth.TYPE_OAUTH, APP_API_KEY, APP_SECRET_KEY).chatCompletion()
+ .model("ERNIE-3.5-8K")
+ .system(system)
+ .enableSystemMemory(true)
+ .systemMemoryId(systemMemoryId)
+ .addUserMessage(query)
+ .execute()
+ .getResult();
+ }
+}
diff --git a/java/pom.xml b/java/pom.xml
index d1b6e285..265987d5 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -4,7 +4,7 @@
com.baidubce
qianfan
- 0.0.9
+ 0.1.0
jar
qianfan
diff --git a/java/src/main/java/com/baidubce/qianfan/Qianfan.java b/java/src/main/java/com/baidubce/qianfan/Qianfan.java
index 3f718124..04a33848 100644
--- a/java/src/main/java/com/baidubce/qianfan/Qianfan.java
+++ b/java/src/main/java/com/baidubce/qianfan/Qianfan.java
@@ -26,6 +26,8 @@
import com.baidubce.qianfan.model.chat.ChatResponse;
import com.baidubce.qianfan.model.completion.CompletionRequest;
import com.baidubce.qianfan.model.completion.CompletionResponse;
+import com.baidubce.qianfan.model.console.ConsoleRequest;
+import com.baidubce.qianfan.model.console.ConsoleResponse;
import com.baidubce.qianfan.model.embedding.EmbeddingRequest;
import com.baidubce.qianfan.model.embedding.EmbeddingResponse;
import com.baidubce.qianfan.model.image.Image2TextRequest;
@@ -37,6 +39,9 @@
import com.baidubce.qianfan.model.rerank.RerankRequest;
import com.baidubce.qianfan.model.rerank.RerankResponse;
+import java.lang.reflect.Type;
+
+
public class Qianfan {
private final QianfanClient client;
@@ -138,6 +143,14 @@ public StreamIterator pluginStream(PluginRequest request) {
return requestStream(request, PluginResponse.class);
}
+ public ConsoleBuilder console() {
+ return new ConsoleBuilder(this);
+ }
+
+ public ConsoleResponse console(ConsoleRequest request, Type type) {
+ return consoleRequest(request, type);
+ }
+
public , U extends BaseRequest> T request(BaseRequest request, Class responseClass) {
return client.request(request, responseClass);
}
@@ -145,4 +158,8 @@ public , U extends BaseRequest> T request(BaseReque
public , U extends BaseRequest> StreamIterator requestStream(BaseRequest request, Class responseClass) {
return client.requestStream(request, responseClass);
}
+
+ public ConsoleResponse consoleRequest(ConsoleRequest request, Type type) {
+ return client.consoleRequest(request, type);
+ }
}
\ No newline at end of file
diff --git a/java/src/main/java/com/baidubce/qianfan/QianfanClient.java b/java/src/main/java/com/baidubce/qianfan/QianfanClient.java
index c3d938a9..29c48581 100644
--- a/java/src/main/java/com/baidubce/qianfan/QianfanClient.java
+++ b/java/src/main/java/com/baidubce/qianfan/QianfanClient.java
@@ -21,18 +21,27 @@
import com.baidubce.qianfan.core.RateLimiter;
import com.baidubce.qianfan.core.StreamIterator;
import com.baidubce.qianfan.core.auth.Auth;
+import com.baidubce.qianfan.core.auth.IAMAuth;
import com.baidubce.qianfan.core.auth.IAuth;
import com.baidubce.qianfan.model.*;
+import com.baidubce.qianfan.model.console.ConsoleRequest;
+import com.baidubce.qianfan.model.console.ConsoleResponse;
import com.baidubce.qianfan.model.exception.ApiException;
+import com.baidubce.qianfan.model.exception.AuthException;
import com.baidubce.qianfan.model.exception.QianfanException;
import com.baidubce.qianfan.model.exception.RequestException;
import com.baidubce.qianfan.util.Json;
+import com.baidubce.qianfan.util.ParameterizedTypeImpl;
import com.baidubce.qianfan.util.StringUtils;
import com.baidubce.qianfan.util.function.ThrowingFunction;
import com.baidubce.qianfan.util.http.*;
+import java.lang.reflect.Type;
+
class QianfanClient {
- private static final String SDK_VERSION = "0.0.9";
+ private static final String SDK_VERSION = "0.1.0";
+ private static final String CONSOLE_URL_NO_ACTION_TEMPLATE = "%s%s";
+ private static final String CONSOLE_URL_ACTION_TEMPLATE = "%s%s?Action=%s";
private static final String QIANFAN_URL_TEMPLATE = "%s/rpc/2.0/ai_custom/v1/wenxinworkshop%s";
private static final String EXTRA_PARAM_REQUEST_SOURCE = "request_source";
private static final String REQUEST_SOURCE_PREFIX = "qianfan_java_sdk_v";
@@ -120,6 +129,36 @@ private , U, V, E extends Exception> V request(
throw new IllegalStateException("Request failed with unknown error");
}
+ public ConsoleResponse consoleRequest(ConsoleRequest request, Type type) {
+ try {
+ if (!(auth instanceof IAMAuth)) {
+ throw new AuthException("Console request requires IAM authentication");
+ }
+ String url = StringUtils.isNotEmpty(request.getAction())
+ ? String.format(CONSOLE_URL_ACTION_TEMPLATE, QianfanConfig.getConsoleApiBaseUrl(), request.getRoute(), request.getAction())
+ : String.format(CONSOLE_URL_NO_ACTION_TEMPLATE, QianfanConfig.getConsoleApiBaseUrl(), request.getRoute());
+ HttpRequest httpRequest = HttpClient.request()
+ .post(url)
+ .body(request.getBody() == null ? new Object() : request.getBody());
+
+ Type respType = new ParameterizedTypeImpl(ConsoleResponse.class, new Type[]{type});
+ HttpResponse> resp = auth.signRequest(httpRequest).executeJson(respType);
+
+ if (resp.getCode() != HttpStatus.SUCCESS) {
+ throw new RequestException(String.format("Request failed with status code %d: %s", resp.getCode(), resp.getStringBody()));
+ }
+ ApiErrorResponse errorResp = Json.deserialize(resp.getStringBody(), ApiErrorResponse.class);
+ if (StringUtils.isNotEmpty(errorResp.getErrorMsg())) {
+ throw new ApiException("Request failed with api error", errorResp);
+ }
+ return resp.getBody();
+ } catch (QianfanException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RequestException(String.format("Request failed: %s", e.getMessage()), e);
+ }
+ }
+
private , U, V, E extends Exception> V innerRequest(
BaseRequest request,
ThrowingFunction, E> reqProcessor,
diff --git a/java/src/main/java/com/baidubce/qianfan/core/StreamIterator.java b/java/src/main/java/com/baidubce/qianfan/core/StreamIterator.java
index 031302de..66647422 100644
--- a/java/src/main/java/com/baidubce/qianfan/core/StreamIterator.java
+++ b/java/src/main/java/com/baidubce/qianfan/core/StreamIterator.java
@@ -23,7 +23,6 @@
import com.baidubce.qianfan.util.http.SSEIterator;
import java.io.Closeable;
-import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
diff --git a/java/src/main/java/com/baidubce/qianfan/core/builder/ConsoleBuilder.java b/java/src/main/java/com/baidubce/qianfan/core/builder/ConsoleBuilder.java
new file mode 100644
index 00000000..c419d184
--- /dev/null
+++ b/java/src/main/java/com/baidubce/qianfan/core/builder/ConsoleBuilder.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2024 Baidu, Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.baidubce.qianfan.core.builder;
+
+import com.baidubce.qianfan.Qianfan;
+import com.baidubce.qianfan.model.console.ConsoleRequest;
+import com.baidubce.qianfan.model.console.ConsoleResponse;
+import com.baidubce.qianfan.model.exception.ValidationException;
+import com.baidubce.qianfan.util.TypeRef;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+public class ConsoleBuilder {
+ private Qianfan qianfan;
+
+ private String route;
+
+ private String action;
+
+ private Object body;
+
+ public ConsoleBuilder() {
+ super();
+ }
+
+ public ConsoleBuilder(Qianfan qianfan) {
+ this.qianfan = qianfan;
+ }
+
+ public ConsoleBuilder route(String route) {
+ this.route = route;
+ return this;
+ }
+
+ public ConsoleBuilder action(String action) {
+ this.action = action;
+ return this;
+ }
+
+ public ConsoleBuilder body(Object body) {
+ this.body = body;
+ return this;
+ }
+
+ public ConsoleRequest build() {
+ return new ConsoleRequest()
+ .setRoute(route)
+ .setAction(action)
+ .setBody(body);
+ }
+
+ public ConsoleResponse