DeepSeek API 调用 - Spring Boot 实现

DeepSeek API 调用 - Spring Boot 实现

1. 项目依赖

pom.xml 中添加以下依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency>
</dependencies>

2. 项目结构

deepseek-project/
├── src/main/java/com/example/deepseek/
│   ├── DeepSeekApplication.java
│   ├── config/
│   │   └── DeepSeekConfig.java
│   ├── model/
│   │   ├── ChatRequest.java
│   │   ├── ChatResponse.java
│   │   └── Message.java
│   └── service/
│       └── DeepSeekService.java
└── conversation.txt

3. 完整代码实现

3.1 配置类 DeepSeekConfig.java
package com.example.deepseek.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;@Configuration
@Getter
public class DeepSeekConfig {@Value("${deepseek.api.url}")private String apiUrl;@Value("${deepseek.api.key}")private String apiKey;
}
3.2 请求/响应模型

Message.java:

package com.example.deepseek.model;import lombok.Data;@Data
public class Message {private String role;private String content;
}

ChatRequest.java:

package com.example.deepseek.model;import lombok.Data;
import java.util.List;@Data
public class ChatRequest {private String model = "deepseek-ai/DeepSeek-V3";private List<Message> messages;private boolean stream = true;private int max_tokens = 2048;private double temperature = 0.7;private double top_p = 0.7;private int top_k = 50;private double frequency_penalty = 0.5;private int n = 1;private ResponseFormat response_format = new ResponseFormat("text");@Datapublic static class ResponseFormat {private String type;public ResponseFormat(String type) {this.type = type;}}
}

ChatResponse.java:

package com.example.deepseek.model;import lombok.Data;
import java.util.List;@Data
public class ChatResponse {private List<Choice> choices;@Datapublic static class Choice {private Delta delta;}@Datapublic static class Delta {private String content;}
}
3.3 服务类 DeepSeekService.java
package com.example.deepseek.service;import com.example.deepseek.config.DeepSeekConfig;
import com.example.deepseek.model.ChatRequest;
import com.example.deepseek.model.ChatResponse;
import com.example.deepseek.model.Message;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Scanner;@Service
@RequiredArgsConstructor
public class DeepSeekService {private final DeepSeekConfig config;private final WebClient.Builder webClientBuilder;private final ObjectMapper objectMapper = new ObjectMapper();public void startInteractiveChat() {try (Scanner scanner = new Scanner(System.in);PrintWriter fileWriter = new PrintWriter(new FileWriter("conversation.txt", true))) {while (true) {System.out.print("\n请输入您的问题 (输入 q 退出): ");String question = scanner.nextLine().trim();if ("q".equalsIgnoreCase(question)) {System.out.println("程序已退出");break;}// 保存问题saveToFile(fileWriter, question, true);// 发起对话请求Flux<String> responseFlux = sendChatRequest(question);StringBuilder fullResponse = new StringBuilder();responseFlux.doOnNext(chunk -> {System.out.print(chunk);fullResponse.append(chunk);}).doOnComplete(() -> {// 保存完整回复saveToFile(fileWriter, fullResponse.toString(), false);System.out.println("\n----------------------------------------");fileWriter.println("\n----------------------------------------");fileWriter.flush();}).blockLast();}} catch (IOException e) {e.printStackTrace();}}private Flux<String> sendChatRequest(String question) {ChatRequest request = new ChatRequest();Message userMessage = new Message();userMessage.setRole("user");userMessage.setContent(question);request.setMessages(Collections.singletonList(userMessage));return webClientBuilder.build().post().uri(config.getApiUrl()).header("Authorization", "Bearer " + config.getApiKey()).header("Content-Type", "application/json").bodyValue(request).retrieve().bodyToFlux(String.class).filter(line -> line.startsWith("data: ") && !line.equals("data: [DONE]")).map(line -> {try {String jsonStr = line.substring(6);ChatResponse response = objectMapper.readValue(jsonStr, ChatResponse.class);return response.getChoices().get(0).getDelta().getContent();} catch (Exception e) {return "";}}).filter(content -> !content.isEmpty());}private void saveToFile(PrintWriter fileWriter, String content, boolean isQuestion) {String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));if (isQuestion) {fileWriter.printf("\n[%s] Question:\n%s\n\n[%s] Answer:\n", timestamp, content, timestamp);} else {fileWriter.print(content);}fileWriter.flush();}
}
3.4 主应用类 DeepSeekApplication.java
package com.example.deepseek;import com.example.deepseek.service.DeepSeekService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class DeepSeekApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(DeepSeekApplication.class, args);DeepSeekService deepSeekService = context.getBean(DeepSeekService.class);deepSeekService.startInteractiveChat();}
}
3.5 配置文件 application.properties
deepseek.api.url=https://api.siliconflow.cn/v1/chat/completions
deepseek.api.key=YOUR_API_KEY

4. 代码详解

4.1 关键特性
  1. 使用 Spring WebFlux 的响应式编程模型
  2. 流式处理 API 响应
  3. 文件记录对话
  4. 错误处理和异常管理
4.2 主要组件
  • DeepSeekConfig: 管理 API 配置
  • DeepSeekService: 处理对话逻辑和 API 交互
  • 模型类: 定义请求和响应结构

5. 使用方法

  1. 替换 application.properties 中的 YOUR_API_KEY
  2. 运行 DeepSeekApplication
  3. 在控制台输入问题
  4. 输入 ‘q’ 退出程序
  5. 查看 conversation.txt 获取对话记录

6. 性能和可扩展性

  • 使用响应式编程提高并发性能
  • 灵活的配置管理
  • 易于扩展和定制

7. 注意事项

  • 确保正确配置 API Key
  • 处理网络异常
  • 注意内存使用

总结

Spring Boot 实现提供了一个健壮、可扩展的 DeepSeek API 调用方案,利用响应式编程提供高效的流式对话体验。

立即体验

快来体验 DeepSeek:https://cloud.siliconflow.cn/i/vnCCfVaQ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/895111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

认识Electron 开启新的探索世界一

一、Electron轻松入门 1.搭建开发环境&#xff1a; 一般情况下开发者会使用node.js来创建electron项目&#xff0c;node.js是一个基于Chrome V8引擎的javascript运行环境&#xff0c;所以首先需要到官网去下载安装node.js 下载链接&#xff1a;https://nodejs.org/enhttps://no…

MySQL下载过程

MySQL Enterprise Edition Downloads | Oracle mysql官方下载网址&#xff08;9.2版本&#xff09; 下面的示例是5.7的包&#xff0c;过程是一样的 port&#xff1a;3308&#xff08;默认的是3306&#xff0c;笔者下了一个占用了该端口&#xff09; root&#xff1a;123456 问题…

【学术投稿】第五届计算机网络安全与软件工程(CNSSE 2025)

重要信息 官网&#xff1a;www.cnsse.org 时间&#xff1a;2025年2月21-23日 地点&#xff1a;中国-青岛 简介 第五届计算机网络安全与软件工程&#xff08;CNSSE 2025&#xff09;将于2025年2月21-23日在中国-青岛举行。CNSSE 2025专注于计算机网络安全、软件工程、信号处…

Qt:QWidget核心属性

目录 QWidget核心属性 enab geometry WindowFrame的影响 windowTitle windowIcon qrc文件管理资源 windowOpacity cursor font toolTip focusPolicy styleSheet QWidget核心属性 在Qt中使用QWidget类表示"控件"&#xff0c;如按钮、视图、输入框、滚动…

Linux TCP 编程详解与实例

一、引言 在网络编程的领域中&#xff0c;TCP&#xff08;Transmission Control Protocol&#xff09;协议因其可靠的数据传输特性而被广泛应用。在 Linux 环境下&#xff0c;使用 C 或 C 进行 TCP 编程可以实现各种强大的网络应用。本文将深入探讨 Linux TCP 编程的各个方面&…

论文笔记:Rethinking Graph Neural Networks for Anomaly Detection

目录 摘要 “右移”现象 beta分布及其小波 实验 《Rethinking Graph Neural Networks for Anomaly Detection》&#xff0c;这是一篇关于图&#xff08;graph&#xff09;上异常节点诊断的论文。 论文出处&#xff1a;ICML 2022 论文地址&#xff1a;Rethinking Graph Ne…

神经网络常见激活函数 6-RReLU函数

文章目录 RReLU函数导函数函数和导函数图像优缺点pytorch中的RReLU函数tensorflow 中的RReLU函数 RReLU 随机修正线性单元&#xff1a;Randomized Leaky ReLU 函数导函数 RReLU函数 R R e L U { x x ≥ 0 a x x < 0 \rm RReLU \left\{ \begin{array}{} x \quad x \ge 0…

Vue(6)

一.路由板块封装 &#xff08;1&#xff09;路由的封装抽离 目标&#xff1a;将路由板块抽离出来 好处&#xff1a;拆分板块&#xff0c;利于维护 // 路由的使用步骤 5 2 // 5个基础步骤 // 1. 下载 v3.6.5 // 2. 引入 // 3. 安装注册 Vue.use(Vue插件) // 4. 创建路由对象…

【python】matplotlib(animation)

文章目录 1、matplotlib.animation1.1、FuncAnimation1.2、修改 matplotlib 背景 2、matplotlib imageio2.1、折线图2.2、条形图2.3、散点图 3、参考 1、matplotlib.animation 1.1、FuncAnimation matplotlib.animation.FuncAnimation 是 Matplotlib 库中用于创建动画的一个…

【东莞常平】戴尔R710服务器不开机维修分享

1&#xff1a;2025-02-06一位老客户的朋友刚开工公司ERP服务器一台戴尔老服务器故障无法开机&#xff0c;于是经老客户介绍找到我们。 2&#xff1a;服务器型号是DELL PowerEdge R710 这个服务器至少也有15年以上的使用年限了。 3&#xff1a;客户反馈的故障问题为&#xff1a;…

Spring AI -使用Spring快速开发ChatGPT应用

前言 Spring在Java生态中一直占据大半江山。最近我发现Spring社区推出了一个Spring AI项目&#xff0c;目前该项目还属于Spring实验性项目&#xff0c;但是我们可以通过该项目&#xff0c;可以非常快速的开发出GPT对话应用。 本篇文章将会对SpringAI进行简单的介绍和使用&#…

经典排序算法复习----C语言

经典排序算法复习 分类 交换类 冒泡快排 分配类 计数排序基数排序 选择类 选择排序 堆排序 归并类 归并排序 插入类 直接插入排序 希尔排序 折半插入排序 冒泡排序 基于交换。每一轮找最大值放到数组尾部 //冒泡排序 void bubSort(int* arr,int size){bool sorte…

BFS解决拓扑排序(3题)

目录 拓扑排序 1.如何排序&#xff1f; 2.如何形成拓扑排序 3.如何建图 1.看数据稠密度 2. 根据算法流程灵活建图 1.课程表 2.课程表2 3.火星词典 拓扑排序 找到做事情的先后顺序&#xff0c;拓扑排序的结果可能不是唯一的 1.如何排序&#xff1f; 1.找出图中入度为…

kafka 3.5.0 raft协议安装

前言 最近做项目&#xff0c;需要使用kafka进行通信&#xff0c;且只能使用kafka&#xff0c;笔者没有测试集群&#xff0c;就自己搭建了kafka集群&#xff0c;实际上笔者在很早之前就搭建了&#xff0c;因为当时还是zookeeper&#xff08;简称ZK&#xff09;注册元数据&#…

Unity项目接入xLua的一种流程

1. 导入xlua 首先导入xlua&#xff0c;这个不用多说 2. 编写C#和Lua交互脚本 基础版本&#xff0c;即xlua自带的版本 using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; using System; using System.IO;[Serializable] public…

四次挥手详解

文章目录 一、四次挥手各状态FIN_WAIT_1CLOSE_WAITFIN_WAIT_2LAST_ACKTIME_WAITCLOSE 二、双方同时调用close()&#xff0c;FIN_WAIT_1状态后进入CLOSING状态CLOSING状态 三、TIME_WAIT状态详解(1) TIME_WAIT状态下的2MSL是什么MSL &#xff08;报文最大生存时间&#xff09;为…

【嵌入式 Linux 音视频+ AI 实战项目】瑞芯微 Rockchip 系列 RK3588-基于深度学习的人脸门禁+ IPC 智能安防监控系统

前言 本文主要介绍我最近开发的一个个人实战项目&#xff0c;“基于深度学习的人脸门禁 IPC 智能安防监控系统”&#xff0c;全程满帧流畅运行。这个项目我目前全网搜了一圈&#xff0c;还没发现有相关类型的开源项目。这个项目只要稍微改进下&#xff0c;就可以变成市面上目前…

java: framework from BLL、DAL、IDAL、MODEL、Factory using oracle

oracel 21c sql: -- 创建 School 表 CREATE TABLE School (SchoolId CHAR(5) NOT NULL,SchoolName NVARCHAR2(500) NOT NULL,SchoolTelNo VARCHAR2(8) NULL,PRIMARY KEY (SchoolId) );CREATE OR REPLACE PROCEDURE addschool(p_school_id IN CHAR,p_school_name IN NVARCHAR2,p…

1.攻防世界 baby_web

题目描述这里有提示&#xff0c;初始页面 进入题目页面如下 很简洁的页面只有一行HELLO WORLD ctrlu查看了源码也没有信息 用burp suite抓包&#xff0c;并发送到重放器 根据提示&#xff08;初始页面&#xff09;修改访问index.php文件 index.php index.php 是一种常见的…

什么是三层交换技术?与二层有什么区别?

什么是三层交换技术&#xff1f;让你的网络飞起来&#xff01; 一. 什么是三层交换技术&#xff1f;二. 工作原理三. 优点四. 应用场景五. 总结 前言 点个免费的赞和关注&#xff0c;有错误的地方请指出&#xff0c;看个人主页有惊喜。 作者&#xff1a;神的孩子都在歌唱 大家好…