下面我帮你写一个Java完整示范项目骨架,实现了:
- DeepSeek API调用(包含带上下文的多轮问答)
- 知识库参数传入
- 流式响应的异步处理示例(基于OkHttp)
- JSON解析(用Jackson)
- 简单的上下文管理示范
Java调用DeepSeek示范代码
1. 依赖(Maven示例)
<dependencies>
<!-- OkHttp: HTTP客户端,支持异步流式 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.11.0</version>
</dependency>
<!-- Jackson: JSON解析 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.15.2</version>
</dependency>
</dependencies>
2. DeepSeekClient.java
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CountDownLatch;
public class DeepSeekClient {
private static final String API_KEY = "YOUR_DEEPSEEK_API_KEY";
private static final String BASE_URL = "https://api.deepseek.ai/v1/chat/completions";
private final OkHttpClient client;
private final ObjectMapper mapper;
public DeepSeekClient() {
this.client = new OkHttpClient.Builder().build();
this.mapper = new ObjectMapper();
}
/**
* 多轮对话消息格式
*/
public static class Message {
public String role;
public String content;
public Message(String role, String content) {
this.role = role;
this.content = content;
}
}
/**
* 发送非流式请求,获取完整回答
*/
public String askSync(List<Message> messages, List<Map<String, String>> knowledgeBase) throws IOException {
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", "deepseek-gpt");
requestBody.put("messages", messages);
if (knowledgeBase != null && !knowledgeBase.isEmpty()) {
requestBody.put("knowledge_base", knowledgeBase);
}
requestBody.put("enable_retrieval", true);
requestBody.put("stream", false);
Request request = new Request.Builder()
.url(BASE_URL)
.header("Authorization", "Bearer " + API_KEY)
.header("Content-Type", "application/json")
.post(RequestBody.create(
mapper.writeValueAsString(requestBody),
MediaType.parse("application/json")))
.build();
try (Response response = client.newCall(request).execute()) {
String body = response.body().string();
JsonNode root = mapper.readTree(body);
// 解析回答文本:choices[0].message.content
return root.path("choices").get(0).path("message").path("content").asText();
}
}
/**
* 流式响应,异步接收并实时处理
*/
public void askStream(List<Message> messages, List<Map<String, String>> knowledgeBase, StreamListener listener) throws IOException, InterruptedException {
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("model", "deepseek-gpt");
requestBody.put("messages", messages);
if (knowledgeBase != null && !knowledgeBase.isEmpty()) {
requestBody.put("knowledge_base", knowledgeBase);
}
requestBody.put("enable_retrieval", true);
requestBody.put("stream", true);
Request request = new Request.Builder()
.url(BASE_URL)
.header("Authorization", "Bearer " + API_KEY)
.header("Content-Type", "application/json")
.post(RequestBody.create(
mapper.writeValueAsString(requestBody),
MediaType.parse("application/json")))
.build();
CountDownLatch latch = new CountDownLatch(1);
client.newCall(request).enqueue(new Callback() {
StringBuilder partialAnswer = new StringBuilder();
@Override
public void onFailure(Call call, IOException e) {
listener.onError(e);
latch.countDown();
}
@Override
public void onResponse(Call call, Response response) {
try (ResponseBody body = response.body()) {
if (body == null) {
listener.onError(new IOException("响应体为空"));
latch.countDown();
return;
}
// 读取流式数据
var source = body.source();
while (!source.exhausted()) {
String line = source.readUtf8LineStrict();
// DeepSeek流式返回通常是 SSE 格式,包含data:字段
if (line.startsWith("data: ")) {
String jsonPart = line.substring(6).trim();
if ("[DONE]".equals(jsonPart)) {
break;
}
JsonNode node = mapper.readTree(jsonPart);
JsonNode contentNode = node.path("choices").get(0).path("delta").path("content");
if (!contentNode.isMissingNode()) {
String content = contentNode.asText();
partialAnswer.append(content);
listener.onPartialResponse(content);
}
}
}
listener.onComplete(partialAnswer.toString());
} catch (Exception e) {
listener.onError(e);
} finally {
latch.countDown();
}
}
});
latch.await(); // 等待响应结束
}
/**
* 流式监听器接口
*/
public interface StreamListener {
void onPartialResponse(String partial);
void onComplete(String fullResponse);
void onError(Exception e);
}
}
3. 使用示例
import java.io.IOException;
import java.util.*;
public class DeepSeekDemo {
public static void main(String[] args) throws IOException, InterruptedException {
DeepSeekClient client = new DeepSeekClient();
// 维护多轮对话上下文
List<DeepSeekClient.Message> messages = new ArrayList<>();
messages.add(new DeepSeekClient.Message("system", "你是一个专业Java助手。"));
messages.add(new DeepSeekClient.Message("user", "什么是Java内存模型?"));
// 简单知识库示例
List<Map<String, String>> knowledgeBase = new ArrayList<>();
knowledgeBase.add(Map.of(
"title", "Java内存模型简介",
"content", "Java内存模型描述了线程之间如何通过主内存和工作内存交互..."
));
// 同步调用示范
String answer = client.askSync(messages, knowledgeBase);
System.out.println("同步回答:\n" + answer);
// 添加用户第二轮提问
messages.add(new DeepSeekClient.Message("assistant", answer));
messages.add(new DeepSeekClient.Message("user", "它对多线程有什么影响?"));
// 流式调用示范
client.askStream(messages, knowledgeBase, new DeepSeekClient.StreamListener() {
@Override
public void onPartialResponse(String partial) {
System.out.print(partial); // 实时打印流式回答
}
@Override
public void onComplete(String fullResponse) {
System.out.println("\n=== 回答结束 ===");
}
@Override
public void onError(Exception e) {
System.err.println("请求出错:" + e.getMessage());
}
});
}
}
四、项目运行说明
- 替换代码中
YOUR_DEEPSEEK_API_KEY
为你真实的DeepSeek API密钥。 - 使用
mvn clean compile exec:java
或你喜欢的IDE运行。 - 程序演示先同步请求,再用流式输出实时显示多轮对话结果。
五、总结
- 使用OkHttp和Jackson实现HTTP请求和JSON解析,代码简洁且高效。
- 通过维护
messages
列表,实现多轮上下文传递。 knowledge_base
参数可以灵活传入,支持自定义知识库补充回答内容。- 流式接口支持实时数据处理,用户体验更好。
- 可以根据需要扩展缓存、异常重试、并发控制等功能。
如果你需要,我还可以帮你扩展:
- 基于Spring Boot的DeepSeek服务封装
- 集成数据库的知识库动态管理
- 多线程并发调用示例
- 流式结果UI实时展示方案
随时告诉我!
发表回复