今日除夕夜,deepseek可是出尽了风头,但是我看网上还没有这方面的内容对接,官网也并没有,故而本次对接是为了完成这个空缺
我看很多的博客内容是流式请求虽然返回时正常的,但是他并不是实时返回,而是全部响应结束之后返回,是有问题的,我这里的这个方法弥补了这个缺陷
下一次我应该会开源一个Starter,让大家使用起来更加方便,下一次直接开源出来,供大家参考,应该就在这一两天,可以期待一下
这里需要仔细看一下了
因为我使用的是JDK21,不过你也可以使用JDK8去做这件事情,但是前提fastjson和okHttp的版本,因为有些方法可能不是很兼容,如果想要完成可能有一些方法需要替换一下,但是肯定是可以用的
文章目录
- 前言
-
目录
文章目录
一、DeepSeek是什么?
二、使用步骤
1.引入库
2.配置环境变量
3.配置
三、 请求
1.流式请求
2.非流失请求
1.定义类
2.非流式请求
四、返回结果
1.流式结果
2.非流式请求
总结
一、DeepSeek是什么?
我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-V3。
-
开发者:深度求索(DeepSeek),一家专注于实现AGI(通用人工智能)的中国科技公司。
-
技术架构:基于大规模语言模型(LLM),通过深度学习技术训练,具备自然语言理解、生成和推理能力。
-
数据来源:训练数据涵盖多领域公开文本(如书籍、网页、学术论文等),经过严格清洗和过滤,符合伦理与安全规范。
二、使用步骤
1.引入库
代码如下(示例):
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.66</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
2.配置环境变量
spring:
ai:
deepseek:
api-key: 这里填写自己的APIKey
api-host: https://api.deepseek.com/chat/completions
3.配置
package com.hhh.springai_test.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ChatConfig {
@Value("${spring.ai.deepseek.api-key}")
private String DeepSeekConfigUrl;
@Value("${spring.ai.deepseek.api-host}")
private String DeepSeekConfigHost;
public String getDeepSeekConfigUrl() {
return DeepSeekConfigUrl;
}
public String getDeepSeekConfigHost() {
return DeepSeekConfigHost;
}
}
三、 请求
1.流式请求
@Resource
private ChatConfig config;
@GetMapping(value = "/ai/generateStreamAsString2", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> generateStreamAsString2(@RequestParam(value = "message") String message) throws Exception {
// 初始化 OkHttpClient
OkHttpClient client = new OkHttpClient().newBuilder().build();
// 创建动态请求体,使用流式传输
RequestBody body = new RequestBody() {
@Override
public okhttp3.MediaType contentType() {
return okhttp3.MediaType.parse("application/json");
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
// 构建请求体 JSON 数据
String requestBodyJson = "{\n" +
" \"messages\": [\n" +
" {\n" +
" \"content\": \"" + message + "\",\n" + // 动态插入用户消息
" \"role\": \"user\"\n" +
" }\n" +
" ],\n" +
" \"model\": \"deepseek-chat\",\n" +
" \"frequency_penalty\": 0,\n" +
" \"max_tokens\": 1024,\n" +
" \"presence_penalty\": 0,\n" +
" \"response_format\": {\n" +
" \"type\": \"text\"\n" +
" },\n" +
" \"stop\": null,\n" +
" \"stream\": true,\n" +
" \"stream_options\": null,\n" +
" \"temperature\": 1,\n" +
" \"top_p\": 1,\n" +
" \"tools\": null,\n" +
" \"tool_choice\": \"none\",\n" +
" \"logprobs\": false,\n" +
" \"top_logprobs\": null\n" +
"}";
// 写入请求体数据
sink.writeUtf8(requestBodyJson);
}
};
// 创建 Headers
Headers headers = new Headers.Builder()
.add("Content-Type", "application/json")
.add("Accept", "application/json")
.add("Authorization", "Bearer " + config.getDeepSeekConfigUrl()) // 使用您的 API 密钥
.build();
// 创建 HttpUrl
HttpUrl url = HttpUrl.parse(config.getDeepSeekConfigHost()); // 使用您的 API URL
if (url == null) {
throw new IllegalArgumentException("您此时未携带URL参数");
}
// 构造 Request
okhttp3.Request request = new okhttp3.Request.Builder()
.url(url)
.post(body) // 使用流式请求体
.headers(headers)
.build();
// 执行请求并返回 Flux 流
return Flux.create(sink -> {
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
// 异常发生时调用 sink.error()
sink.error(e);
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
ResponseBody responseBody = response.body();
BufferedSource source = responseBody.source();
while (true) {
// 逐行读取响应数据
String line = source.readUtf8Line();
if (line == null) {
break;
} else if (line.startsWith("data:")) {
String data = line.substring(5).trim();
// 检查数据是否为结束信号"[DONE]"
if (!"[DONE]".equals(data)) {
// 解析接收到的数据为JSON对象
JSONObject jsonResponse = new JSONObject(data);
String finishReason = jsonResponse.getJSONArray("choices").getJSONObject(0).optString("finish_reason");
if ("stop".equals(finishReason)) {
// 结束时推送数据并完成
sink.next(data);
sink.complete();
break;
} else {
// 否则继续推送数据
sink.next(data);
}
// 打印调试信息
System.out.println(jsonResponse.getJSONArray("choices"));
}
}
}
}
});
});
}
2.非流失请求
1.定义类
package com.hhh.springai_test.model.dto.DeepSeekChat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatCompletionResponse {
private String id;
private String object;
private long created;
private String model;
private List<Choice> choices;
private Usage usage;
private String system_fingerprint;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Choice {
private int index;
private Message message;
private Object logprobs;
private String finish_reason;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Message {
private String role;
private String content;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Usage {
private int prompt_tokens;
private int completion_tokens;
private int total_tokens;
private PromptTokensDetails prompt_tokens_details;
private int prompt_cache_hit_tokens;
private int prompt_cache_miss_tokens;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class PromptTokensDetails {
private int cached_tokens;
}
}
2.非流式请求
//引入这个bean
@Resource
private ChatConfig config;
@GetMapping(value = "/ai/generateAsString3")
public ChatCompletionResponse generateStreamAsString3(@RequestParam(value = "message") String message) {
// 初始化 OkHttpClient
OkHttpClient client = new OkHttpClient().newBuilder().build();
okhttp3.MediaType mediaType = okhttp3.MediaType.parse("application/json");
RequestBody requestBody = RequestBody.create(mediaType, "{\n" +
" \"messages\": [\n" +
" {\n" +
" \"content\": \"" + "请介绍一下你自己" + "\",\n" + // 动态插入用户消息
" \"role\": \"user\"\n" +
" },\n" +
" {\n" +
" \"content\": \"" + message + "\",\n" + // 动态插入用户消息
" \"role\": \"user\"\n" +
" }\n" +
" ],\n" +
" \"model\": \"deepseek-chat\",\n" +
" \"frequency_penalty\": 0,\n" +
" \"max_tokens\": 1024,\n" +
" \"presence_penalty\": 0,\n" +
" \"response_format\": {\n" +
" \"type\": \"text\"\n" +
" },\n" +
" \"stop\": null,\n" +
" \"stream\": false,\n" +
" \"stream_options\": null,\n" +
" \"temperature\": 1,\n" +
" \"top_p\": 1,\n" +
" \"tools\": null,\n" +
" \"tool_choice\": \"none\",\n" +
" \"logprobs\": false,\n" +
" \"top_logprobs\": null\n" +
"}");
Buffer buffer = new Buffer();
try {
requestBody.writeTo(buffer);
System.out.println("Request Body Content: " + buffer.readUtf8());
} catch (IOException e) {
e.printStackTrace();
}
// 创建 Headers
Headers headers = new Headers.Builder()
.add("Content-Type", "application/json")
.add("Accept", "application/json")
.add("Authorization", "Bearer " + config.getDeepSeekConfigUrl()) // 使用您的 API 密钥
.build();
// 创建 HttpUrl
HttpUrl url = HttpUrl.parse(config.getDeepSeekConfigHost());
if (url == null) {
throw new IllegalArgumentException("您此时未携带URL参数");
}
// 构造 Request
okhttp3.Request request = new okhttp3.Request.Builder()
.url(url)
.post(requestBody)
.headers(headers)
.build();
// 执行请求并打印响应
try (Response response = client.newCall(request).execute()) {
String responseBody = response.body().string();
System.out.println(responseBody);
ChatCompletionResponse responseVo = JSON.parseObject(responseBody, ChatCompletionResponse.class);
return responseVo;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
四、返回结果
1.流式结果
2.非流式请求
总结
因为我使用的是JDK21,不过你也可以使用JDK8去做这件事情,但是前提fastjson和okHttp的版本,因为有些方法可能不是很兼容,如果想要完成可能有一些方法需要替换一下,但是肯定是可以用的