SpringBoot或SpringAI對(duì)接DeepSeek大模型的詳細(xì)步驟
我看很多的博客內(nèi)容是流式請(qǐng)求雖然返回時(shí)正常的,但是他并不是實(shí)時(shí)返回,而是全部響應(yīng)結(jié)束之后返回,是有問(wèn)題的,我這里的這個(gè)方法彌補(bǔ)了這個(gè)缺陷
這里需要仔細(xì)看一下了
因?yàn)槲沂褂玫氖荍DK21,不過(guò)你也可以使用JDK8去做這件事情,但是前提fastjson和okHttp的版本,因?yàn)橛行┓椒赡懿皇呛芗嫒荩绻胍瓿煽赡苡幸恍┓椒ㄐ枰鎿Q一下,但是肯定是可以用的
一、DeepSeek是什么?
我是由中國(guó)的深度求索(DeepSeek)公司開發(fā)的智能助手DeepSeek-V3。
開發(fā)者:深度求索(DeepSeek),一家專注于實(shí)現(xiàn)AGI(通用人工智能)的中國(guó)科技公司。
技術(shù)架構(gòu):基于大規(guī)模語(yǔ)言模型(LLM),通過(guò)深度學(xué)習(xí)技術(shù)訓(xùn)練,具備自然語(yǔ)言理解、生成和推理能力。
數(shù)據(jù)來(lái)源:訓(xùn)練數(shù)據(jù)涵蓋多領(lǐng)域公開文本(如書籍、網(wǎng)頁(yè)、學(xué)術(shù)論文等),經(jīng)過(guò)嚴(yán)格清洗和過(guò)濾,符合倫理與安全規(guī)范。
二、使用步驟
1.引入庫(kù)
代碼如下(示例):
<!--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.配置環(huán)境變量
spring:
ai:
deepseek:
api-key: 這里填寫自己的APIKey
api-host: https://api.deepseek.com/chat/completions3.配置
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;
}
}三、 請(qǐng)求
1.流式請(qǐng)求
@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();
// 創(chuàng)建動(dòng)態(tài)請(qǐng)求體,使用流式傳輸
RequestBody body = new RequestBody() {
@Override
public okhttp3.MediaType contentType() {
return okhttp3.MediaType.parse("application/json");
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
// 構(gòu)建請(qǐng)求體 JSON 數(shù)據(jù)
String requestBodyJson = "{\n" +
" \"messages\": [\n" +
" {\n" +
" \"content\": \"" + message + "\",\n" + // 動(dòng)態(tài)插入用戶消息
" \"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" +
"}";
// 寫入請(qǐng)求體數(shù)據(jù)
sink.writeUtf8(requestBodyJson);
}
};
// 創(chuàng)建 Headers
Headers headers = new Headers.Builder()
.add("Content-Type", "application/json")
.add("Accept", "application/json")
.add("Authorization", "Bearer " + config.getDeepSeekConfigUrl()) // 使用您的 API 密鑰
.build();
// 創(chuàng)建 HttpUrl
HttpUrl url = HttpUrl.parse(config.getDeepSeekConfigHost()); // 使用您的 API URL
if (url == null) {
throw new IllegalArgumentException("您此時(shí)未攜帶URL參數(shù)");
}
// 構(gòu)造 Request
okhttp3.Request request = new okhttp3.Request.Builder()
.url(url)
.post(body) // 使用流式請(qǐng)求體
.headers(headers)
.build();
// 執(zhí)行請(qǐng)求并返回 Flux 流
return Flux.create(sink -> {
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
// 異常發(fā)生時(shí)調(diào)用 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) {
// 逐行讀取響應(yīng)數(shù)據(jù)
String line = source.readUtf8Line();
if (line == null) {
break;
} else if (line.startsWith("data:")) {
String data = line.substring(5).trim();
// 檢查數(shù)據(jù)是否為結(jié)束信號(hào)"[DONE]"
if (!"[DONE]".equals(data)) {
// 解析接收到的數(shù)據(jù)為JSON對(duì)象
JSONObject jsonResponse = new JSONObject(data);
String finishReason = jsonResponse.getJSONArray("choices").getJSONObject(0).optString("finish_reason");
if ("stop".equals(finishReason)) {
// 結(jié)束時(shí)推送數(shù)據(jù)并完成
sink.next(data);
sink.complete();
break;
} else {
// 否則繼續(xù)推送數(shù)據(jù)
sink.next(data);
}
// 打印調(diào)試信息
System.out.println(jsonResponse.getJSONArray("choices"));
}
}
}
}
});
});
}2.非流失請(qǐng)求
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.非流式請(qǐng)求
//引入這個(gè)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\": \"" + "請(qǐng)介紹一下你自己" + "\",\n" + // 動(dòng)態(tài)插入用戶消息
" \"role\": \"user\"\n" +
" },\n" +
" {\n" +
" \"content\": \"" + message + "\",\n" + // 動(dòng)態(tài)插入用戶消息
" \"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();
}
// 創(chuàng)建 Headers
Headers headers = new Headers.Builder()
.add("Content-Type", "application/json")
.add("Accept", "application/json")
.add("Authorization", "Bearer " + config.getDeepSeekConfigUrl()) // 使用您的 API 密鑰
.build();
// 創(chuàng)建 HttpUrl
HttpUrl url = HttpUrl.parse(config.getDeepSeekConfigHost());
if (url == null) {
throw new IllegalArgumentException("您此時(shí)未攜帶URL參數(shù)");
}
// 構(gòu)造 Request
okhttp3.Request request = new okhttp3.Request.Builder()
.url(url)
.post(requestBody)
.headers(headers)
.build();
// 執(zhí)行請(qǐng)求并打印響應(yīng)
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);
}
}四、返回結(jié)果
1.流式結(jié)果

2.非流式請(qǐng)求

總結(jié)
因?yàn)槲沂褂玫氖荍DK21,不過(guò)你也可以使用JDK8去做這件事情,但是前提fastjson和okHttp的版本,因?yàn)橛行┓椒赡懿皇呛芗嫒?,如果想要完成可能有一些方法需要替換一下,但是肯定是可以用的
到此這篇關(guān)于SpringBoot或SpringAI對(duì)接DeekSeek大模型的文章就介紹到這了,更多相關(guān)SpringBoot或SpringAI對(duì)接DeekSeek內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot兩種方式接入DeepSeek的實(shí)現(xiàn)
- SpringBoot快速接入DeepSeek?api(帶頁(yè)面)保姆級(jí)教程
- SpringBoot調(diào)用DeepSeek接口的實(shí)現(xiàn)
- SpringBoot接入deepseek深度求索示例代碼(jdk1.8)
- SpringBoot整合DeepSeek實(shí)現(xiàn)AI對(duì)話功能
- SpringBoot調(diào)用DeepSeek?API的完整操作指南
- springboot接入deepseek深度求索代碼示例(java版)
- springboot集成Deepseek4j的項(xiàng)目實(shí)踐
相關(guān)文章
Nebula?Graph介紹和SpringBoot環(huán)境連接和查詢操作
Nebula?Graph?是一款開源的、分布式的、易擴(kuò)展的原生圖數(shù)據(jù)庫(kù),能夠承載包含數(shù)千億個(gè)點(diǎn)和數(shù)萬(wàn)億條邊的超大規(guī)模數(shù)據(jù)集,并且提供毫秒級(jí)查詢,這篇文章主要介紹了Nebula?Graph介紹和SpringBoot環(huán)境連接和查詢,需要的朋友可以參考下2022-10-10
解決Java中基于GeoTools的Shapefile讀取亂碼的問(wèn)題
本文主要討論了在使用Java編程語(yǔ)言進(jìn)行地理信息數(shù)據(jù)解析時(shí)遇到的Shapefile屬性信息亂碼問(wèn)題,以及根據(jù)不同的編碼設(shè)置進(jìn)行屬性信息解析的方法,感興趣的朋友跟隨小編一起看看吧2025-03-03
Sentinel結(jié)合Nacos實(shí)現(xiàn)數(shù)據(jù)持久化過(guò)程詳解
這篇文章主要介紹了Sentinel結(jié)合Nacos實(shí)現(xiàn)數(shù)據(jù)持久化過(guò)程,要持久化的原因是因?yàn)槊看螁?dòng)Sentinel都會(huì)使之前配置的規(guī)則就清空了,這樣每次都要再去設(shè)定規(guī)則顯得非常的麻煩,感興趣想要詳細(xì)了解可以參考下文2023-05-05
前端和后端時(shí)間不一致問(wèn)題解決的實(shí)踐指南
這篇文章主要給大家介紹了關(guān)于前端和后端時(shí)間不一致問(wèn)題解決的實(shí)踐指南,在SpringBoot項(xiàng)目中,可以通過(guò)設(shè)置application.yml文件中的屬性來(lái)統(tǒng)一時(shí)間格式和時(shí)區(qū),從而確保序列化和反序列化過(guò)程中的時(shí)間和時(shí)區(qū)一致性,需要的朋友可以參考下2025-01-01
Java線程啟動(dòng)為什么要用start()而不是run()?
這篇文章主要介紹了線程啟動(dòng)為什么要用start()而不是run()?下面文章圍繞start()與run()的相關(guān)資料展開詳細(xì)內(nèi)容,具有一定的參考價(jià)值,西藥的小火熬版可以參考一下,希望對(duì)你有所幫助2021-12-12
Java程序初始化啟動(dòng)自動(dòng)執(zhí)行的三種方式
這篇文章主要介紹了Java程序初始化啟動(dòng)自動(dòng)執(zhí)行的三種方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Spring框架+jdbcTemplate實(shí)現(xiàn)增刪改查功能
這篇文章主要介紹了Spring框架+jdbcTemplate實(shí)現(xiàn)增刪改查功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09

