SpringBoot 调用deepseek的API进行对话
这里只讲发一次消息和多轮对话,其余的拓展欢迎去官方文档参考进行实验首次调用 API | DeepSeek API DocsDeepSeek API 使用与 OpenAI 兼容的 API 格式,通过修改配置,您可以使用 OpenAI SDK 来访问 DeepSeek API,或使用与 OpenAI API 兼容的软件。
这里只讲发一次消息和多轮对话,其余的拓展欢迎去官方文档参考进行实验
一、去官网申请API key

然后进行充值,不然是使用不了key的
二、准备Java项目
1、完整代码
https://gitcode.com/bluefoxyu/deepseek-chat-demo
2、项目讲解
代码结构

接口
这里主要实现了单次对话和多轮对话:

import com.bluefoxyu.domain.Result;
import com.bluefoxyu.service.DeepSeekService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
@RestController
@RequestMapping("/api/chat")
public class ChatController {
@Resource
private DeepSeekService deepSeekService;
@PostMapping("/one")
public String chat(@RequestBody String message) {
try {
return Result.success(deepSeekService.sendMessage(message)).toJson();
} catch (IOException e) {
throw new RuntimeException("调用DeepSeek API失败: " + e.getMessage(), e);
}
}
// 多轮对话
// 目前还没做用户区分,不过数据表里面做了这个字段,到时候查询再加一层即可
@PostMapping("/completion")
public String chatCompletion(@RequestBody String param) {
try {
return Result.success(deepSeekService.chatCompletion(param)).toJson();
} catch (IOException e) {
throw new RuntimeException("调用DeepSeek API失败: " + e.getMessage(), e);
}
}
}
接口的实现
其实逻辑就那么几点:处理用户请求的数据,构建发送deepseek的http请求,解析deepseek返回的结构进行解析取出deepseek的回答(有用的数据),封装结构返回

这个是单次问答的大致逻辑,如果是多次的话还会多一些和数据库的操作,和一些保证。
多轮对话,这里我主要设计的是:
使用一个conversation_id进行隔离不同对话,使用数据库进行对话的记忆,参考官方的流程:

主要的报文格式是:

其实这样子也很容易理解
下面是我的代码的大致实现:

可能还有很多完善的点,还有完善的功能,比如多用户隔离,这样子需要数据库新增字段
完整代码示例如下:
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bluefoxyu.domain.ChatCompletionResponse;
import com.bluefoxyu.domain.CompletionChatParam;
import com.bluefoxyu.domain.DeepSeekRequest;
import com.bluefoxyu.domain.Message;
import com.bluefoxyu.mapper.MessageMapper;
import jakarta.annotation.Resource;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@Service
public class DeepSeekService {
@Resource
private OkHttpClient client;
@Value("${bluefox.deepseek.base_url}")
private String baseUrl;
@Value("${bluefox.deepseek.api_key}")
private String apiKey;
@Resource
private MessageMapper messageMapper;
/**
* <p>
* description: 发送用户消息到DeepSeek API。
* </p>
*
* @param userMessage 用户输入的消息字符串
* @return: java.lang.String API响应的字符串表示形式
* @author: bluefoxyu
* @date: 2025-06-25 17:15:21
*/
public String sendMessage(String userMessage) throws IOException {
return sendChatCompletion(createDefaultRequest(userMessage));
}
/**
* <p>
* description: 创建默认的聊天请求对象,包含系统提示和用户消息。
* </p>
*
* @param userMessage 用户输入的消息字符串
* @return: com.bluefoxyu.domain.DeepSeekRequest 默认的DeepSeek请求对象
* @author: bluefoxyu
* @date: 2025-06-25 17:18:54
*/
private DeepSeekRequest createDefaultRequest(String userMessage) {
DeepSeekRequest request = new DeepSeekRequest();
request.setMessages(List.of(
new DeepSeekRequest.Message("assistant", "You are a helpful assistant"),
new DeepSeekRequest.Message("user", userMessage)
));
return request;
}
/**
* <p>
* description: 发送聊天完成请求到DeepSeek API
* </p>
*
* @param request 包含请求数据的对象
* @return: java.lang.String API响应的字符串表示形式
* @author: bluefoxyu
* @date: 2025-06-25 17:18:26
*/
public String sendChatCompletion(DeepSeekRequest request) throws IOException {
String jsonBody = JSONUtil.toJsonStr(request);
Request httpRequest = buildRequest(jsonBody);
try (Response response = client.newCall(httpRequest).execute()) {
if (!response.isSuccessful()) {
throw new IOException(buildErrorMessage(response));
}
// 解析响应体
String responseBody = Objects.requireNonNull(response.body()).string();
ChatCompletionResponse chatCompletionResponse = JSONUtil.toBean(responseBody, ChatCompletionResponse.class);
// 提取第一个choice的消息内容
if (chatCompletionResponse.getChoices() != null && !chatCompletionResponse.getChoices().isEmpty()) {
return chatCompletionResponse.getChoices().get(0).getMessage().getContent();
} else {
throw new RuntimeException("No valid response from DeepSeek API.");
}
}
}
/**
* <p>
* description: 根据提供的JSON请求体构建HTTP
* </p>
*
* @param jsonBody JSON格式的请求体字符串
* @return: okhttp3.Request 构建好的HTTP请求对象
* @author: bluefoxyu
* @date: 2025-06-25 17:19:33
*/
private Request buildRequest(String jsonBody) {
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, jsonBody);
return new Request.Builder()
.url(baseUrl)
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("Authorization", "Bearer " + apiKey)
.build();
}
/**
* <p>
* description: 构建错误信息字符串,包含HTTP状态码和响应体内容。
* </p>
*
* @param response HTTP响应对象
* @return: java.lang.String 错误信息字符串
* @author: bluefoxyu
* @date: 2025-06-25 17:17:40
*/
private String buildErrorMessage(Response response) throws IOException {
return String.format("API请求失败: %d - %s",
response.code(),
response.body() != null ? response.body().string() : "无响应内容");
}
public String chatCompletion(String param) throws IOException {
// 将传入的参数字符串转换为CompletionChatParam对象
CompletionChatParam bean = JSONUtil.toBean(param, CompletionChatParam.class);
String conversationId = bean.getConversation_id();
String userMessage = bean.getMessage();
// 查询数据库中的历史消息
List<Message> historyMessages = messageMapper.selectList(
Wrappers.<Message>lambdaQuery()
.eq(Message::getConversationId, conversationId)
.orderByAsc(Message::getId) // 确保按时间顺序排列
);
// 构建请求消息列表
List<DeepSeekRequest.Message> messages = new ArrayList<>();
for (Message msg : historyMessages) {
messages.add(new DeepSeekRequest.Message(msg.getUserRole(), msg.getUserContent()));
messages.add(new DeepSeekRequest.Message(msg.getAssistantRole(), msg.getAssistantContent()));
}
// 添加当前用户的提问
messages.add(new DeepSeekRequest.Message("user", userMessage));
// 创建请求并发送
DeepSeekRequest request = new DeepSeekRequest();
request.setMessages(messages);
// 发送聊天完成请求到DeepSeek API
String responseMessage = sendChatCompletion(request);
// 保存助手的回复到数据库
Message assistantReply = new Message();
assistantReply.setUserRole("user");
assistantReply.setAssistantRole("assistant");
assistantReply.setUserContent(userMessage); // 用户输入的内容
assistantReply.setAssistantContent(responseMessage); // 助手的回复内容
assistantReply.setConversationId(Integer.valueOf(conversationId));
messageMapper.insert(assistantReply);
return responseMessage;
}
}
数据库
create table message
(
id bigint auto_increment comment '主键ID,唯一标识每条对话记录'
primary key,
user_role varchar(255) not null comment '用户角色(例如:user)',
assistant_role varchar(255) not null comment '助手角色(例如:assistant)',
user_content text not null comment '用户输入的内容',
assistant_content text not null comment '助手回复的内容',
conversation_id int null comment '对话会话ID,用于关联同一轮对话的多条消息'
)
comment '存储多轮对话记录的表,包含用户与助手之间的交互内容';

配置

详细的信息通过bean来获取


3、接口测试

http://localhost:8081/api/chat/one
"Hello, how are you?,用中文回答"


http://localhost:8081/api/chat/completion
{
"message": "我刚刚问了你啥问题",
"conversation_id": "3"
}

其实这里的解析式有些问题的,有很多的换行的符号,可能大家觉得有问题,不过由于是json数据才会这样子,这些换行符方便后续使用的时候,解析json,内容就是正常的了。

完美实现!
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)