使用JavaSDK调用智谱AI模型
大冶湖学校
2024年07月28日 11:56
收录于文集
共36篇
智谱清言ChatGLM

一、  为什么使用Java SDK

因为目前AI深度学习的框架大多都是由Python训练得来的,比如PyTorch、TensorFlow,Python是深度学习训练的原始语言。 而Java程序员在中国的群体是最多的,为了让大模型能够被Java使用,开发了Java SDK来调用大模型文件,方便Java程序员应用。 二、  Java接入 2.1构建SpringBoot工程 使用SpringBoot 3版本,JDK版本要求为jdk17。 如果大家使用的是Spring Boot 2.7及以下的版本,首先要安装jdk 17,然后升级为Spring Boot 3版本。 (1)采用IntelliJ IDEA新建Maven工程

(2)Maven工程接入SpringBoot 3版本坐标 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.1</version> <relativePath/>

</parent>

(3)指定Maven项目groupId、artifactId <groupId>org.example</groupId> <artifactId>springboot-zhipu</artifactId> <version>1.0-SNAPSHOT</version> <name>springboot-zhipu</name> <description>zhipu AI大模型工具</description> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>

(4)Maven依赖引入Spring Web: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 引入lombok: <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> 引入Spring Boot Test: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency>

如图:

(5)在src/main/resources资源目录下新建application.yml,配置项目端口:

application.yml: server: port: 8080

(6)  新建org.example.controller包

(7)在org.example.controller包新建HelloController.java类:

HelloController.java代码为: @RequestMapping("/hello") @RestController public class HelloController { @GetMapping("/world") public String world() { return "Hello World"; } }

(8)  改造主启动类Main.java:

增加@SpringBootApplication注解:

增加@ComponentScan扫描包: @ComponentScan(basePackages = {"org.example.controller"}) 使用SpringApplication.run启动主启动类: SpringApplication.run(Main.class, args); 完整代码如下: import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @ComponentScan(basePackages = {"org.example.controller"}) public class Main { public static void main(String[] args) { SpringApplication.run(Main.class, args); }

}

(9)  执行IntelliJ IDEA右侧的Maven Install:

Maven Install安装好后,Reload一下项目,加载Maven坐标:

(10)右键启动Main.java

启动完成控制台打印:

(11)打开浏览器输入地址:

http://localhost:8080/hello/world

SpringBoot工程就搭建完毕,先关闭Main.java运行,准备接入ChatGLM大模型组件

2.2接入大模型SDK (1)引入官网ChatGLM坐标: <dependency> <groupId>cn.bigmodel.openapi</groupId> <artifactId>oapi-java-sdk</artifactId> <version>release-V4-2.0.0</version> </dependency> 如果有兴趣查看官网源码,可访问:https://github.com/MetaGLM/zhipuai-sdk-java-v4

目前还处于测试阶段,不太成熟,可能有Bug缺陷:

(2)引入JunitTest相关坐标: <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.10.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.10.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.10.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers</artifactId> <version>1.19.8</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>junit-jupiter</artifactId> <version>1.19.8</version> <scope>test</scope>

</dependency>

2.3使用单元测试测试大模型功能

在src/test/java下新建:org.example.utils包:

报下新建AiClients类,类里面替换api_key为自己的api_key,申请api_key地址: https://open.bigmodel.cn/usercenter/apikeys (1)AiClients.java代码如下,注意替换api_key: package org.example.utils; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.zhipu.oapi.ClientV4; import com.zhipu.oapi.Constants; import com.zhipu.oapi.service.v4.model.*; import io.reactivex.Flowable; import org.junit.jupiter.api.Test; import org.testcontainers.junit.jupiter.Testcontainers; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; @Testcontainers public class AiClients { static ClientV4 client = new ClientV4.Builder("自己的api_key密钥").build(); private static final ObjectMapper mapper = defaultObjectMapper(); // 请自定义自己的业务id private static final String requestIdTemplate = "mycompany-%d"; public static ObjectMapper defaultObjectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); mapper.addMixIn(ChatFunction.class, ChatFunctionMixIn.class); mapper.addMixIn(ChatCompletionRequest.class, ChatCompletionRequestMixIn.class); mapper.addMixIn(ChatFunctionCall.class, ChatFunctionCallMixIn.class); return mapper; } /** * sse调用 */ @Test public void testFunctionSSE() throws JsonProcessingException { List<ChatMessage> messages = new ArrayList<>(); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "成都到北京要多久,天气如何"); messages.add(chatMessage); String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); // 函数调用参数构建部分 List<ChatTool> chatToolList = new ArrayList<>(); ChatTool chatTool = new ChatTool(); chatTool.setType(ChatToolType.FUNCTION.value()); ChatFunctionParameters chatFunctionParameters = new ChatFunctionParameters(); chatFunctionParameters.setType("object"); Map<String, Object> properties = new HashMap<>(); properties.put("location", new HashMap<String, Object>() {{ put("type", "string"); put("description", "城市,如:北京"); }}); properties.put("unit", new HashMap<String, Object>() {{ put("type", "string"); put("enum", new ArrayList<String>() {{ add("celsius"); add("fahrenheit"); }}); }}); chatFunctionParameters.setProperties(properties); ChatFunction chatFunction = ChatFunction.builder() .name("get_weather") .description("Get the current weather of a location") .parameters(chatFunctionParameters) .build(); chatTool.setFunction(chatFunction); chatToolList.add(chatTool); HashMap<String, Object> extraJson = new HashMap<>(); extraJson.put("temperature", 0.5); extraJson.put("max_tokens", 50); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() .model(Constants.ModelChatGLM4) .stream(Boolean.TRUE) .messages(messages) .requestId(requestId) .tools(chatToolList) .toolChoice("auto") //.extraJson(extraJson) .build() ; ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest); if (sseModelApiResp.isSuccess()) { AtomicBoolean isFirst = new AtomicBoolean(true); List<Choice> choices = new ArrayList<>(); ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable()) .doOnNext(accumulator -> { { if (isFirst.getAndSet(false)) { System.out.println("Response: "); } if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) { String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls()); System.out.println("tool_calls: "+ jsonString); } if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) { System.out.println(accumulator.getDelta().getContent()); } choices.add(accumulator.getChoice()); } }) .doOnComplete(System.out::println) .lastElement() .blockingGet(); ModelData data = new ModelData(); data.setChoices(choices); data.setUsage(chatMessageAccumulator.getUsage()); data.setId(chatMessageAccumulator.getId()); data.setCreated(chatMessageAccumulator.getCreated()); data.setRequestId(chatCompletionRequest.getRequestId()); sseModelApiResp.setFlowable(null);// 打印前置空 sseModelApiResp.setData(data); } System.out.println("model output: "+mapper.writeValueAsString(sseModelApiResp)); } /** * sse-V4:非function调用 */ @Test public void testNonFunctionSSE() throws JsonProcessingException { List<ChatMessage> messages = new ArrayList<>(); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "ChatGLM和你哪个更强大"); messages.add(chatMessage); HashMap<String, Object> extraJson = new HashMap<>(); extraJson.put("temperature", 0.5); extraJson.put("max_tokens", 3); String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() .model(Constants.ModelChatGLM4) .stream(Boolean.TRUE) .messages(messages) .requestId(requestId) //.extraJson(extraJson) .build(); ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest); // stream 处理方法 if (sseModelApiResp.isSuccess()) { AtomicBoolean isFirst = new AtomicBoolean(true); List<Choice> choices = new ArrayList<>(); ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable()) .doOnNext(accumulator -> { { if (isFirst.getAndSet(false)) { System.out.println("Response: "); } if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) { String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls()); System.out.println("tool_calls: "+jsonString); } if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) { System.out.println("accumulator.getDelta().getContent(): "+accumulator.getDelta().getContent()); } choices.add(accumulator.getChoice()); } }) .doOnComplete(System.out::println) .lastElement() .blockingGet(); ModelData data = new ModelData(); data.setChoices(choices); data.setUsage(chatMessageAccumulator.getUsage()); data.setId(chatMessageAccumulator.getId()); data.setCreated(chatMessageAccumulator.getCreated()); data.setRequestId(chatCompletionRequest.getRequestId()); sseModelApiResp.setFlowable(null);// 打印前置空 sseModelApiResp.setData(data); } System.out.println("model output: "+mapper.writeValueAsString(sseModelApiResp)); } /** * V4-同步非function调用 */ @Test public void testNonFunctionInvoke() throws JsonProcessingException { List<ChatMessage> messages = new ArrayList<>(); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "ChatGLM和你哪个更强大"); messages.add(chatMessage); String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); HashMap<String, Object> extraJson = new HashMap<>(); extraJson.put("temperature", 0.5); extraJson.put("max_tokens", 3); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() .model(Constants.ModelChatGLM4) .stream(Boolean.FALSE) .invokeMethod(Constants.invokeMethod) .messages(messages) .requestId(requestId) //.extraJson(extraJson) .build(); ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest); System.out.println("model output: "+mapper.writeValueAsString(invokeModelApiResp)); } public static Flowable<ChatMessageAccumulator> mapStreamToAccumulator(Flowable<ModelData> flowable) { return flowable.map(chunk -> { return new ChatMessageAccumulator(chunk.getChoices().get(0).getDelta(), null, chunk.getChoices().get(0), chunk.getUsage(), chunk.getCreated(), chunk.getId()); }); } } (2)调用结果如下

SSE调用:

输出结果:

sse-V4:非function调用

输出结果:

V4-同步非function调用

输出结果:

2.4使用Controller运行大模型

在src/main/java下新建:org.example.utils包

(1)建立ChatGLMUtils工具类 在org.example.utils包新建ChatGLMUtils工具类,注意将工具类的api_key替换为自己的api_key: package org.example.utils; import cn.hutool.json.JSONUtil; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.zhipu.oapi.ClientV4; import com.zhipu.oapi.Constants; import com.zhipu.oapi.service.v4.model.*; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import static com.zhipu.oapi.demo.V4OkHttpClientTest.mapStreamToAccumulator; public class ChatGLMUtils { static ClientV4 client = new ClientV4.Builder("自己的api_key").build(); private static final ObjectMapper mapper = defaultObjectMapper(); // 请自定义自己的业务id private static final String requestIdTemplate = "mycompany-%d"; public static ObjectMapper defaultObjectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE); mapper.addMixIn(ChatFunction.class, ChatFunctionMixIn.class); mapper.addMixIn(ChatCompletionRequest.class, ChatCompletionRequestMixIn.class); mapper.addMixIn(ChatFunctionCall.class, ChatFunctionCallMixIn.class); return mapper; } /** * 同步调用 */ public static void testInvoke() { List<ChatMessage> messages = new ArrayList<>(); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "作为一名营销专家,请为智谱开放平台创作一个吸引人的slogan"); messages.add(chatMessage); String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() .model(Constants.ModelChatGLM4) .stream(Boolean.FALSE) .invokeMethod(Constants.invokeMethod) .messages(messages) .requestId(requestId) .build(); ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest); try { System.out.println("model output:" + mapper.writeValueAsString(invokeModelApiResp)); } catch (JsonProcessingException e) { e.printStackTrace(); } } /** * 异步调用 */ public static String testAsyncInvoke() { List<ChatMessage> messages = new ArrayList<>(); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "作为一名营销专家,请为智谱开放平台创作一个吸引人的slogan"); messages.add(chatMessage); String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() .model(Constants.ModelChatGLM4) .stream(Boolean.FALSE) .invokeMethod(Constants.invokeMethodAsync) .messages(messages) .requestId(requestId) .build(); ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest); System.out.println("model output:" + JSONUtil.toJsonPrettyStr(invokeModelApiResp)); return invokeModelApiResp.getData().getTaskId(); } /** * sse调用 */ public static void testSseInvoke() { List<ChatMessage> messages = new ArrayList<>(); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), "作为一名营销专家,请为智谱开放平台创作一个吸引人的slogan"); messages.add(chatMessage); String requestId = String.format(requestIdTemplate, System.currentTimeMillis()); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() .model(Constants.ModelChatGLM4) .stream(Boolean.TRUE) .messages(messages) .requestId(requestId) .build(); ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest); if (sseModelApiResp.isSuccess()) { AtomicBoolean isFirst = new AtomicBoolean(true); ChatMessageAccumulator chatMessageAccumulator = mapStreamToAccumulator(sseModelApiResp.getFlowable()) .doOnNext(accumulator -> { { if (isFirst.getAndSet(false)) { System.out.print("Response: "); } if (accumulator.getDelta() != null && accumulator.getDelta().getTool_calls() != null) { String jsonString = mapper.writeValueAsString(accumulator.getDelta().getTool_calls()); System.out.println("tool_calls: " + jsonString); } if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) { System.out.print(accumulator.getDelta().getContent()); } } }) .doOnComplete(System.out::println) .lastElement() .blockingGet(); Choice choice = new Choice(chatMessageAccumulator.getChoice().getFinishReason(), 0L, chatMessageAccumulator.getDelta()); List<Choice> choices = new ArrayList<>(); choices.add(choice); ModelData data = new ModelData(); data.setChoices(choices); data.setUsage(chatMessageAccumulator.getUsage()); data.setId(chatMessageAccumulator.getId()); data.setCreated(chatMessageAccumulator.getCreated()); data.setRequestId(chatCompletionRequest.getRequestId()); sseModelApiResp.setFlowable(null); sseModelApiResp.setData(data); } System.out.println("model output:" + JSONUtil.toJsonPrettyStr(sseModelApiResp)); } } 工具类分别实现了ChatGLM的同步调用、异步调用和SSE调用,也是参考了官网的示例来的。

同步调用:

异步调用:

SSE调用:

(2)在org.example.controller包下面的HelloController控制器类增加调用示例: /** * 同步调用 */ @GetMapping("/testInvoke") public String testInvoke(){ ChatGLMUtils.testInvoke(); return "testInvoke"; } /** * 异步调用 * @return */ @GetMapping("/testAsyncInvoke") public String testAsyncInvoke(){ ChatGLMUtils.testAsyncInvoke(); return "testAsyncInvoke"; } /** * sse调用 */ @GetMapping("/testSseInvoke") public String testSseInvoke() { ChatGLMUtils.testSseInvoke(); return "testSseInvoke"; } 而HelloController.java完整代码: package org.example.controller; import org.example.utils.ChatGLMUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RequestMapping("/hello") @RestController public class HelloController { @GetMapping("/world") public String world() { return "Hello World"; } /** * 同步调用 */ @GetMapping("/testInvoke") public String testInvoke(){ ChatGLMUtils.testInvoke(); return "testInvoke"; } /** * 异步调用 * @return */ @GetMapping("/testAsyncInvoke") public String testAsyncInvoke(){ ChatGLMUtils.testAsyncInvoke(); return "testAsyncInvoke"; } /** * sse调用 */ @GetMapping("/testSseInvoke") public String testSseInvoke() { ChatGLMUtils.testSseInvoke(); return "testSseInvoke"; } } (3)浏览器测试 启动Main.java主启动类:

启动成功:

浏览器运行:http://localhost:8080/hello/testInvoke

IntelliJ IDEA控制台输出ChatGLM结果:

浏览器出现testInvoke,表示调用完毕:

浏览器运行:http://localhost:8080/hello/testAsyncInvoke IntelliJ IDEA控制台输出ChatGLM结果:

浏览器出现testAsyncInvoke,表示调用完毕:

浏览器运行:http://localhost:8080/hello/testSseInvoke

IntelliJ IDEA控制台输出ChatGLM结果:

浏览器出现testSseInvoke,表示调用完毕:

以上主要分享Java SDK中使用智谱AI的方法,花费了博主半天时间。 如果您也觉得本文不错,欢迎推荐转发关注博主。