java调用deepseek案例
最近在关注大模型在测开方向的应用,许多博主都是基于python去开发项目,由于公司里面只使用java,所以学习了下如何使用java调用大模型(以deepseek为例)。本文通过两种方式调用deepseek1. 普通调用:大模型收到用户的请求后,会等待答案生成完毕才返回给用户2. 流式调用:需要在请求体中设置==stream=true==,然后大模型就会以流失传输的方式,一旦生成了部分答案就会马上返
·
文章目录
- 1、背景
- 2、搭建步骤
-
- 2.1 项目结构
- 2.2 相关代码
-
- 2.2.1 ApiConfig
- 2.2.2 ChatRequest
- 2.2.3 ChatResponse
- 2.2.4 Delta
- 2.2.5 DeepSeekService
- 2.2.6 config.properties
- 2.2.7 Main
- 2.2.8 pom.xml
- 3、效果展示
1、背景
最近在关注大模型在测开方向的应用,许多博主都是基于python去开发项目,由于公司里面只使用java,所以学习了下如何使用java调用大模型(以deepseek为例)。
本文通过两种方式调用deepseek
- 普通调用:大模型收到用户的请求后,会等待答案生成完毕才返回给用户
- 流式调用:需要在请求体中设置stream=true,然后大模型就会以流失传输的方式,一旦生成了部分答案就会马上返回给用户,跟大家在网页使用效果一样。
这里分享一下搭建代码的步骤以及过程中遇到的一些问题,所写代码比较粗糙,大家根据需求自行修改。
2、搭建步骤
2.1 项目结构
首先创建一个Maven项目,我的文件结构如下
- ApiConfig:用于读取配置文件中调用大模型的Key
- ChatRequest:调用大模型的请求体
- ChatResponse:大模型回答问题的响应体
- Delta:大模型以流式方式回答问题需要的类
- DeepSeekService:调用大模型方法
- config.properties:存储调用大模型的Key和Url
2.2 相关代码
2.2.1 ApiConfig
package org.example.config;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import java.io.File;
public class ApiConfig {
private static final String CONFIG_FILE = "config.properties";
public static String getApiKey() {
return getConfig().getString("deepseek.api.key");
}
public static String getApiEndpoint() {
return getConfig().getString("deepseek.api.endpoint");
}
private static PropertiesConfiguration getConfig() {
try {
return new Configurations().properties(new File(
Thread.currentThread()
.getContextClassLoader()
.getResource(CONFIG_FILE).getPath()));
} catch (Exception e) {
throw new RuntimeException("加载配置文件失败", e);
}
}
}
2.2.2 ChatRequest
根据官方API定义,文档里面有每个字段的解释,根据想实现的功能自行定义
package org.example.model;
import java.util.List;
public class ChatRequest {
private String model;
private List<Message> messages;
private double temperature;
private Boolean stream;
public void setModel(String s) {
model = s;
}
public void setTemperature(double t) {
temperature = t;
}
public void setMessages(List<Message> m) {
messages = m;
}
public void setStream(Boolean stream) {
this.stream = stream;
}
public Boolean getStream() {
return stream;
}
// 构造方法、Getter/Setter
public static class Message {
private String role;
private String content;
public void setRole(String user) {
role = user;
}
public void setContent(String s) {
content = s;
}
// 构造方法、Getter/Setter
}
}
2.2.3 ChatResponse
同理官网有全部字段的解释,需要啥拿啥
package org.example.model;
import java.util.List;
public class ChatResponse {
private List<Choice> choices;
public List<Choice> getChoices() {
return choices;
}
// Getter/Setter
public static class Choice {
private Message message;
private Delta delta;
public Delta getDelta() {
return delta;
}
public Message getMessage() {
return message;
}
// Getter/Setter
public static class Message {
private String content;
// Getter/Setter
public String getContent() {
return content;
}
}
}
}
2.2.4 Delta
当我们定义了使用流失传输,deepseek响应体结构将会改变,所以需要定义一个新的类去接收
可以看看两种不同方式调用的返回结果:
-
stream=false:
-
stream=true:
package org.example.model;
public class Delta {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
2.2.5 DeepSeekService
两种调用方法:
- 普通调用:chatCompletion
- 流式调用:streamChatCompletion
package org.example.service;
import com.google.gson.*;
import org.example.config.ApiConfig;
import org.example.model.ChatRequest;
import org.example.model.ChatResponse;
import okhttp3.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit;
public class DeepSeekService {
private static final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(300000, TimeUnit.SECONDS) // 连接超时 xx 秒
.readTimeout(300000, TimeUnit.SECONDS) // 读取超时 xx 秒
.writeTimeout(300000, TimeUnit.SECONDS) // 写入超时 xx 秒
.build();
private static final Gson gson = new Gson();
public String chatCompletion(ChatRequest request) throws Exception {
String jsonRequest = gson.toJson(request);
RequestBody body = RequestBody.create(
jsonRequest,
MediaType.parse("application/json")
);
Request httpRequest = new Request.Builder()
.url(ApiConfig.getApiEndpoint())
.addHeader("Authorization", "Bearer " + ApiConfig.getApiKey())
.post(body)
.build();
try (Response response = client.newCall(httpRequest).execute()) {
if (!response.isSuccessful()) {
throw new RuntimeException("API请求失败: " + response.code());
}
ChatResponse resp = gson.fromJson(
response.body().string(),
ChatResponse.class
);
return resp.getChoices().get(0).getMessage().getContent();
}
}
// 流式回调
public void streamChatCompletion(ChatRequest request, StreamCallback callback) throws IOException {
String jsonRequest = gson.toJson(request);
RequestBody body = RequestBody.create(jsonRequest, MediaType.get("application/json"));
Request httpRequest = new Request.Builder()
.url(ApiConfig.getApiEndpoint())
.addHeader("Authorization", "Bearer " + ApiConfig.getApiKey())
.post(body)
.build();
try (Response response = client.newCall(httpRequest).execute()) {
if (!response.isSuccessful()) {
throw new RuntimeException("API请求失败: " + response.code());
}
// 使用try-with-resources确保流关闭
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(response.body().byteStream()))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("data: ")) {
String jsonData = line.substring(6).trim();
if ("[DONE]".equals(jsonData)) {
break;
}
// 流式处理
try {
// 解析流式数据块
ChatResponse chunk = gson.fromJson(jsonData, ChatResponse.class);
// 流式模式下应该检查delta而不是message
if (chunk != null &&
chunk.getChoices() != null &&
!chunk.getChoices().isEmpty() &&
chunk.getChoices().get(0).getDelta() != null) {
String content = chunk.getChoices().get(0).getDelta().getContent();
if (content != null) {
callback.onContentReceived(content);
}
}
} catch (Exception e) {
System.err.println("解析数据块出错: " + e.getMessage());
}
}
}
}
}
}
// 流式回调接口
public interface StreamCallback {
void onContentReceived(String content);
}
}
2.2.6 config.properties
deepseek.api.key=sk-xx
deepseek.api.endpoint=https://api.deepseek.com/chat/completions
2.2.7 Main
package org.example;
import org.example.model.ChatRequest;
import org.example.service.DeepSeekService;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
DeepSeekService service = new DeepSeekService();
System.out.println("DeepSeek 对话系统 (输入 'bye' 退出)");
System.out.println("=================================");
while (true) {
System.out.print("\n用户: ");
String userInput = scanner.nextLine().trim();
// 检查退出条件
if ("bye".equalsIgnoreCase(userInput)) {
System.out.println("对话结束,再见!");
break;
}
// 跳过空输入
if (userInput.isEmpty()) {
System.out.println("请输入有效内容");
continue;
}
try {
// 构建请求
ChatRequest request = new ChatRequest();
request.setModel("deepseek-chat");
request.setTemperature(0.7);
request.setStream(true);
ChatRequest.Message message = new ChatRequest.Message();
message.setRole("user");
message.setContent(userInput);
request.setMessages(List.of(message));
// 获取并显示响应
// 记录开始时间
long startTime = System.currentTimeMillis();
System.out.println("\nDeepSeek 思考中...");
if(request.getStream()) {
service.streamChatCompletion(request, newContent -> { // 执行流式调用
printWithTypingEffect(newContent, 20);
});
} else {
String response = service.chatCompletion(request); // 普通调用
// System.out.println("\nDeepSeek: " + response); // 直接返回全部答案
printWithTypingEffect(response, 20); //打字机效果
}
// 记录结束时间
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.printf("\n[本次响应耗时: %ds]\n", duration / 1000);
} catch (Exception e) {
System.err.println("\n请求出错: " + e.getMessage());
e.printStackTrace();
}
}
scanner.close();
}
private static void printWithTypingEffect(String text, int delay) {
try {
for (char c : text.toCharArray()) {
System.out.print(c);
System.out.flush(); // 确保立即输出
// 处理换行符和制表符
if (c == '\n') {
Thread.sleep(delay * 3); // 换行时多停顿一会
} else if (c == '\t') {
Thread.sleep(delay * 2);
} else {
Thread.sleep(delay);
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
2.2.8 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>Test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- HTTP客户端 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- JSON处理 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<!-- 配置管理 -->
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.virtlink.commons/commons-configuration2-jackson -->
<dependency>
<groupId>com.virtlink.commons</groupId>
<artifactId>commons-configuration2-jackson</artifactId>
<version>1.3.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
</project>
3、效果展示
这里只展示流式调用,输入问题后程序可以及时把deepseek返回的部分内容展现给用户。整个问题耗时大约58S,如果没有启动流式传输,程序只有等待58S后才打印答案,所以考虑到用户体验还是流式调用更加方便
更多推荐
所有评论(0)