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");

    @Data
    public 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;

    @Data
    public static class Choice {
        private Delta delta;
    }

    @Data
    public 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("
请输入您的问题 (输入 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("
----------------------------------------");
                        fileWriter.println("
----------------------------------------");
                        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("
[%s] Question:
%s

[%s] Answer:
", 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

相关推荐
love530love5 小时前
LiveTalking 数字人项目 Windows 部署完全指南(EPGF 架构)
人工智能·windows·python·架构·livetalking·epgf
星辰徐哥5 小时前
Spring Boot 微服务架构设计与实现
spring boot·后端·微服务
星辰徐哥5 小时前
Spring Boot 数据导入导出与报表生成
spring boot·后端·ui
明夜之约5 小时前
Spring Boot 自动装配源码
java·spring boot·后端
Leaton Lee5 小时前
Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程
java·spring boot·后端·架构
Micro麦可乐5 小时前
Spring Boot 实战:从零设计一个短链系统(含完整代码与数据库设计)
数据库·spring boot·后端·哈希算法·雪花算法·短链系统
Jinkxs5 小时前
Resilience4j- 与 Spring Boot 快速集成:自动配置与基础注解使用
java·spring boot·后端
毕设源码_郑学姐5 小时前
计算机毕业设计springboot网络相册设计与实现 基于Spring Boot框架的在线相册管理系统开发与应用 Spring Boot驱动的网络影集设计与实践
spring boot·后端·课程设计
辣机小司5 小时前
【踩坑记录:Spring Boot 配置文件读取值不一致?警惕 YAML 的“八进制陷阱”与 SnakeYAML 版本之谜】
java·spring boot·后端·yaml·踩坑记录
一条小锦吕*5 小时前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化