当前位置: 首页 > article >正文

SpringBoot或SpringAI对接DeekSeek大模型

今日除夕夜,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: 这里填写自己的APIKeyapi-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 {// 初始化 OkHttpClientOkHttpClient client = new OkHttpClient().newBuilder().build();// 创建动态请求体,使用流式传输RequestBody body = new RequestBody() {@Overridepublic okhttp3.MediaType contentType() {return okhttp3.MediaType.parse("application/json");}@Overridepublic 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);}};// 创建 HeadersHeaders headers = new Headers.Builder().add("Content-Type", "application/json").add("Accept", "application/json").add("Authorization", "Bearer " + config.getDeepSeekConfigUrl())  // 使用您的 API 密钥.build();// 创建 HttpUrlHttpUrl url = HttpUrl.parse(config.getDeepSeekConfigHost()); // 使用您的 API URLif (url == null) {throw new IllegalArgumentException("您此时未携带URL参数");}// 构造 Requestokhttp3.Request request = new okhttp3.Request.Builder().url(url).post(body)  // 使用流式请求体.headers(headers).build();// 执行请求并返回 Flux 流return Flux.create(sink -> {client.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(@NotNull Call call, @NotNull IOException e) {// 异常发生时调用 sink.error()sink.error(e);}@Overridepublic 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@NoArgsConstructorpublic static class Choice {private int index;private Message message;private Object logprobs;private String finish_reason;}@Data@AllArgsConstructor@NoArgsConstructorpublic static class Message {private String role;private String content;}@Data@AllArgsConstructor@NoArgsConstructorpublic 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@NoArgsConstructorpublic 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) {// 初始化 OkHttpClientOkHttpClient 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();}// 创建 HeadersHeaders headers = new Headers.Builder().add("Content-Type", "application/json").add("Accept", "application/json").add("Authorization", "Bearer " + config.getDeepSeekConfigUrl())  // 使用您的 API 密钥.build();// 创建 HttpUrlHttpUrl url = HttpUrl.parse(config.getDeepSeekConfigHost());if (url == null) {throw new IllegalArgumentException("您此时未携带URL参数");}// 构造 Requestokhttp3.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的版本,因为有些方法可能不是很兼容,如果想要完成可能有一些方法需要替换一下,但是肯定是可以用的

相关文章:

SpringBoot或SpringAI对接DeekSeek大模型

今日除夕夜&#xff0c;deepseek可是出尽了风头&#xff0c;但是我看网上还没有这方面的内容对接&#xff0c;官网也并没有&#xff0c;故而本次对接是为了完成这个空缺 我看很多的博客内容是流式请求虽然返回时正常的&#xff0c;但是他并不是实时返回&#xff0c;而是全部响应…...

Funnel-Transformer:通过过滤序列冗余实现高效语言处理

摘要 随着语言预训练的成功&#xff0c;开发更具扩展性且能高效利用大量未标注数据的架构变得尤为重要。为了提高效率&#xff0c;我们研究了在维持完整token级别表示时的冗余问题&#xff0c;尤其是对于仅需要序列单向量表示的任务。基于这一直觉&#xff0c;我们提出了Funne…...

【搜索回溯算法】:BFS的魔力--如何使用广度优先搜索找到最短路径

✨感谢您阅读本篇文章&#xff0c;文章内容是个人学习笔记的整理&#xff0c;如果哪里有误的话还请您指正噢✨ ✨ 个人主页&#xff1a;余辉zmh–CSDN博客 ✨ 文章所属专栏&#xff1a;搜索回溯算法篇–CSDN博客 文章目录 一.广度优先搜索&#xff08;BFS&#xff09;解决最短路…...

【算法】经典博弈论问题——威佐夫博弈 python

目录 威佐夫博弈(Wythoff Game)【模板】 威佐夫博弈(Wythoff Game) 有两堆石子&#xff0c;数量任意&#xff0c;可以不同&#xff0c;游戏开始由两个人轮流取石子 游戏规定&#xff0c;每次有两种不同的取法 1)在任意的一堆中取走任意多的石子 2)可以在两堆中同时取走相同数量…...

CUDA学习-内存访问

一 访存合并 1.1 说明 本部分内容主要参考: 搞懂 CUDA Shared Memory 上的 bank conflicts 和向量化指令(LDS.128 / float4)的访存特点 - 知乎 1.2 share memory结构 图1.1 share memory结构 放在 shared memory 中的数据是以 4 bytes(即 32 bits)作为 1 个 word,依…...

力扣动态规划-13【算法学习day.107】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;建议灵神的题单和代码随想录&#xff09;和记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关…...

《剪映5.9官方安装包》免费自动生成字幕

&#xff08;避免失效建议存自己网盘后下载&#xff09;剪映5.9官方Win.Mac 链接&#xff1a;https://pan.xunlei.com/s/VOHc-Fg2XRlD50MueEaOOeW1A1?pwdawtt# 官方唯一的免费版&#xff0c;Win和Mac都有&#xff0c;此版本官方已下架&#xff0c;觉得有用可转存收藏&#xf…...

ESP32-S3模组上跑通esp32-camera(32)

接前一篇文章:ESP32-S3模组上跑通esp32-camera(31) 一、OV5640初始化 2. 相机初始化及图像传感器配置 上一回开始解析camera_probe函数的第8段即最后一段代码,本回继续解析该段代码。为了便于理解和回顾,再次贴出camera_probe函数源码,在components/esp32-camera/drive…...

Brave132 编译指南 Windows 篇:安装 Visual Studio 2022(二)

1. 引言 在着手编译 Brave 浏览器的 132 版本之前&#xff0c;构建一个完备的开发环境至关重要。Visual Studio 2022 作为一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;为 Brave 浏览器的编译提供了坚实的工具链和技术支持。它不仅提供了高效的代码编辑…...

DBO-高斯回归预测matlab

蜣螂优化算法(Dung Beetle Optimizer, DBO)是一种新型的群智能优化算法&#xff0c;在2022年底提出&#xff0c;主要是受蜣螂的的滚球、跳舞、觅食、偷窃和繁殖行为的启发。 本次研究使用的是 Excel 格式的股票预测数据。数据集按照 8&#xff1a;1&#xff1a;1 的比例&#x…...

2025美国大学生数学建模竞赛美赛E题成品参考论文(48页)(含模型,可运行代码,求解结果)

2025美国大学生数学建模竞赛E题成品参考论文 目录 一、问题重述 二、问题分析 三、模型假设 四、模型建立与求解 4.1问题1 4.1.1问题1思路分析 4.1.2问题1模型建立 4.1.3问题1代码&#xff08;仅供参考&#xff09; 4.1.4问题1求解结果&#xff08;仅供参考&…...

VMware 中Ubuntu无网络连接/无网络标识解决方法【已解决】

参考文档 Ubuntu无网络连接/无网络标识解决方法_ubuntu没网-CSDN博客 再我们正常使用VMware时&#xff0c;就以Ubuntu举例可能有时候出现无网络连接&#xff0c;甚至出现无网络标识的情况&#xff0c;那么废话不多说直接上教程 环境&#xff1a;无网络 解决方案&#…...

Vuex中的getter和mutation有什么区别

在现代前端开发中&#xff0c;状态管理是一个不可忽视的话题&#xff0c;而Vuex作为Vue.js的官方状态管理库&#xff0c;在大型应用中扮演着至关重要的角色。当我们使用Vuex进行状态管理时&#xff0c;getter和mutation是两个重要的概念。虽然它们都是用来处理状态的&#xff0…...

笔试-二维数组2

应用 现有M(1<M<10)个端口组&#xff0c;每个端口组是长度为N(1<N<100)&#xff0c;元素均为整数。如果这些端口组间存在2个及以上的元素相同&#xff0c;则认为端口组可以关联合并&#xff1b;若可以关联合并&#xff0c;请用二位数组表示输出结果。其中&#xf…...

基于RIP的MGRE VPN综合实验

实验拓扑 实验需求 1、R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有IP地址&#xff1b; 2、R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方&#xff1b; R2与R5之间使用ppp的CHAP认证&#xff0c;R5为主认证方&#xff1b; R3与R5之间使用HDLC封…...

十三先天记

没有一刻&#xff0c;只有当下在我心里。我像星星之间的空间一样空虚。他们是我看到的第一件事&#xff0c;我知道的第一件事。 在接下来的时间里&#xff0c;我意识到我是谁&#xff0c;我是谁。我知道星星在我上方&#xff0c;星球的固体金属体在我脚下。这个支持我的世界是泰…...

Autosar-Os是怎么运行的?(Os基础模块)

写在前面&#xff1a; 入行一段时间了&#xff0c;基于个人理解整理一些东西&#xff0c;如有错误&#xff0c;欢迎各位大佬评论区指正&#xff01;&#xff01;&#xff01; 书接上文 Autosar-Os是怎么运行的&#xff1f;&#xff08;一&#xff09;-CSDN博客 目录 1.Resourc…...

OPencv3.4.1安装及配置教程

来到GitHub上opencv的项目地址 https://github.com/opencv/opencv/releases/tag/3.4.1 以上资源包都是 OpenCV 3.4.1 版本相关资源&#xff0c;它们的区别如下&#xff1a; (1). opencv-3.4.1-android-sdk.zip&#xff1a;适用于 Android 平台的软件开发工具包&#xff08;SDK…...

选择困难?直接生成pynput快捷键字符串

from pynput import keyboard# 文档&#xff1a;https://pynput.readthedocs.io/en/latest/keyboard.html#monitoring-the-keyboard # 博客(pynput相关源码)&#xff1a;https://blog.csdn.net/qq_39124701/article/details/145230331 # 虚拟键码(十六进制)&#xff1a;https:/…...

Vue.js组件开发-如何实现带有搜索功能的下拉框

创建 Vue 项目&#xff1a; 如果还没有创建一个 Vue 项目&#xff0c;可以使用 Vue CLI 来创建一个新的项目。 vue create my-project cd my-project安装依赖&#xff1a; 如果需要使用第三方组件库&#xff0c;比如 Element UI 或 Ant Design Vue&#xff0c;可以安装相应的…...

java 字符串日期字段格式化前端显示

在 Java 应用程序中&#xff0c;如果你有一个字符串类型的日期字段&#xff0c;并希望将其格式化后显示在前端&#xff0c;可以通过多种方式实现。这通常涉及到在后端将字符串转换为 Date 或 LocalDateTime 等对象&#xff0c;然后使用适当的注解或配置来确保它们以正确的格式序…...

LeetCode题练习与总结:安装栅栏--587

一、题目描述 给定一个数组 trees&#xff0c;其中 trees[i] [xi, yi] 表示树在花园中的位置。 你被要求用最短长度的绳子把整个花园围起来&#xff0c;因为绳子很贵。只有把 所有的树都围起来&#xff0c;花园才围得很好。 返回恰好位于围栏周边的树木的坐标。 示例 1: 输…...

< OS 有关 > 阿里云 几个小时前 使用密钥替换 SSH 密码认证后, 发现主机正在被“攻击” 分析与应对

信息来源&#xff1a; 文件&#xff1a;/var/log/auth.log 因为在 sshd_config 配置文件中&#xff0c;已经定义 LogLevel INFO 部分内容&#xff1a; 2025-01-27T18:18:55.68272708:00 jpn sshd[15891]: Received disconnect from 45.194.37.171 port 58954:11: Bye Bye […...

使用八爪鱼爬虫和Web Scraper抓取数据实战案例,附详细教程

最近有不少小伙伴咨询怎么抓取抖音视频或者评论的数据&#xff0c;他们多是自媒体或者商家&#xff0c;想要模仿爆火视频或者分析视频评论区的舆情信息&#xff0c;确实呀&#xff0c;现在抖音是流量高地&#xff0c;淘金的地方&#xff0c;真的是一个值得挖掘的宝藏。当然我一…...

海外问卷调查渠道查如何设置:最佳实践+示例

随着经济全球化和一体化进程的加速&#xff0c;企业间的竞争日益加剧&#xff0c;为了获得更大的市场份额&#xff0c;对企业和品牌而言&#xff0c;了解受众群体的的需求、偏好和痛点才是走向成功的关键。而海外问卷调查才是获得受众群体痛点的关键&#xff0c;制作海外问卷调…...

【C++数论】880. 索引处的解码字符串|2010

本文涉及知识点 数论&#xff1a;质数、最大公约数、菲蜀定理 LeetCode880. 索引处的解码字符串 给定一个编码字符串 s 。请你找出 解码字符串 并将其写入磁带。解码时&#xff0c;从编码字符串中 每次读取一个字符 &#xff0c;并采取以下步骤&#xff1a; 如果所读的字符是…...

从ai产品推荐到利用cursor快速掌握一个开源项目再到langchain手搓一个Text2Sql agent

目录 0. 经验分享&#xff1a;产品推荐 1. 经验分享&#xff1a;提示词优化 2. 经验分享&#xff1a;使用cursor 阅读一篇文章 3. 经验分享&#xff1a;使用cursor 阅读一个完全陌生的开源项目 4. 经验分享&#xff1a;手搓一个text2sql agent &#xff08;使用langchain l…...

freeswitch在centos上编译过程

操作系统&#xff1a;centos9-last usr/local/freeswitch/bin/freeswitch -version FreeSWITCH version: 1.10.13-devgit~20250125T131725Z~3f1e4bf90a~64bit (git 3f1e4bf 2025-01-25 13:17:25Z 64bit)vi /etc/ssh/sshd_config ip a nmtui reboot ip a curl -o /etc/pki/rpm-…...

项目测试之MockMvc

文章目录 基础基础概念Mockxxx一般实现文件位置 实战MockMvc与Test注解不兼容RequestParams参数RequestBody参数 基础 基础概念 定义&#xff1a;是Spring框架提供的一种用于测试Spring MVC控制器的工具&#xff0c;它允许开发者在不启动完整的web服务器的情况下&#xff0c;…...

Blazor-选择循环语句

今天我们来说说Blazor选择语句和循环语句。 下面我们以一个简单的例子来讲解相关的语法&#xff0c;我已经创建好了一个Student类&#xff0c;以此类来进行语法的运用 因为我们需要交互性所以我们将类创建在*.client目录下 if 我们做一个学生信息的显示&#xff0c;Gender为…...