基于SpringBoot的DeepSeek-demo 深度求索-demo 支持流式输出、历史记录
文章目录文件下载效果展示IdeaPythonPostman使用说明核心代码controllerService文件下载百度网盘 提取码: jsfc蓝奏云 密码:5kxz效果展示IdeaPythonPostman注postman中只有websocket才有流式效果使用说明修改配置文件请求路径为/chat在请求体中传入对话列表可以携带对话的历史记录[ { content: 你是一个乐于助人的助手。, role: system }, { content: 记住a1,b2, role: user }, { content: 好的我已经记住了**a 1****b 2**。如果有其他问题或需要进一步帮助请告诉我 ??, role: assistant }, { content: a b等于什么, role: user } ] 响应结果如下 根据我记住的 **a 1** 和 **b 2****a b 1 2 3**。 结果是 **3**还有其他问题吗 ??核心代码controllerimport com.deepseek.deepseekdemo.service.AiChatService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import reactor.core.scheduler.Schedulers; import java.util.List; import java.util.Map; RestController public class AiChatController { Autowired private AiChatService aiChatService; GetMapping(value /chat, produces application/streamjson) public FluxString chat(RequestBody ListMapString, String messages) { FluxString responseFlux aiChatService.chat(messages); return Flux.create(sink - { responseFlux.subscribeOn(Schedulers.boundedElastic()) .subscribe( sink::next, // 返回流式字符串 sink::error, // 返回错误请在调用端完成错误处理 sink::complete // 返回完成事件 ); }); } }Serviceimport com.deepseek.deepseekdemo.config.DeepSeekConfig; import com.deepseek.deepseekdemo.dto.AiMessageDto; import com.deepseek.deepseekdemo.dto.DefaultAiMessageDto; import com.deepseek.deepseekdemo.dto.StreamingAiMessageDto; import com.deepseek.deepseekdemo.service.AiChatService; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import reactor.core.publisher.Flux; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; Slf4j Service public class AiChatServiceA implements AiChatService { MapString, Object body new HashMap(); Headers headers; AiMessageDto aiMessageDto; Autowired private DeepSeekConfig deepSeekConfig; Autowired private OkHttpClient httpClient; // 初始化 PostConstruct public void init() { body.put(model, deepSeekConfig.getModel()); body.put(frequency_penalty, deepSeekConfig.getFrequencyPenalty()); body.put(max_tokens, deepSeekConfig.getMaxTokens()); body.put(presence_penalty, deepSeekConfig.getPresencePenalty()); body.put(response_format, deepSeekConfig.getResponseFormat()); body.put(stop, deepSeekConfig.getStop()); body.put(stream, deepSeekConfig.getStream()); if (deepSeekConfig.getStream()) { body.put(stream_options, deepSeekConfig.getStreamOptions()); } body.put(temperature, deepSeekConfig.getTemperature()); body.put(top_p, deepSeekConfig.getTopP()); body.put(tools, deepSeekConfig.getTools()); body.put(tool_choice, deepSeekConfig.getToolChoice()); if (deepSeekConfig.getLogprobs()) { body.put(logprobs, deepSeekConfig.getLogprobs()); body.put(top_logprobs, deepSeekConfig.getTopLogprobs()); } // 构建请求头 headers new Headers.Builder().add(Authorization, Bearer deepSeekConfig.getApiKey()).add(Content-Type, application/json).build(); if (deepSeekConfig.getStream()) { aiMessageDto new StreamingAiMessageDto(); } else { aiMessageDto new DefaultAiMessageDto(); } } Override public FluxString chat(ListMapString, String question) { body.put(messages, question); // 将请求体转换为 JSON 字符串 ObjectMapper objectMapper new ObjectMapper(); String payload; try { payload objectMapper.writeValueAsString(body); } catch (JsonProcessingException e) { throw new RuntimeException(无法将负载转换为JSON, e); } // 构建请求 Request request new Request.Builder().url(deepSeekConfig.getUrl()).post(RequestBody.create(payload, MediaType.parse(application/json))).headers(headers).build(); // 返回 FluxString 以流式返回数据 return Flux.create(emitter - { try (Response response httpClient.newCall(request).execute()) { if (!response.isSuccessful()) { emitter.error(new IOException(请求失败响应码: response.code())); return; } // 处理流式响应 ResponseBody responseBody response.body(); if (responseBody ! null) { while (!responseBody.source().exhausted()) { String line responseBody.source().readUtf8Line(); if (line ! null !line.isEmpty()) { try { emitter.next(aiMessageDto.getMessage(line)); // 逐步发送数据 } catch (Exception e) { log.error(处理数据时发生错误: , e); } } } emitter.complete(); // 完成流 } } catch (IOException e) { emitter.error(e); } }); } }

相关新闻

【Linux网络】Socket编程预备

【Linux网络】Socket编程预备

1. 理解源IP地址和目的IP地址 IP 在网络中,用来标识主机的唯一性 注意:后面我们会讲 IP 的分类,会详细阐述 IP 的特点 但是这里要思考一个更深层次的问题:数据传输到主机真的是最终目的吗? 其实并不是。因为数据最终都…

2026/5/17 11:11:16 阅读更多 →
Java SpringBoot+Vue3+MyBatis 大学生创新创业项目管理系统系统源码|前后端分离+MySQL数据库

Java SpringBoot+Vue3+MyBatis 大学生创新创业项目管理系统系统源码|前后端分离+MySQL数据库

摘要 随着高等教育改革的深入推进,大学生创新创业项目的数量逐年增加,传统的项目管理方式已难以满足高效、便捷的管理需求。项目信息分散、审批流程繁琐、团队协作效率低下等问题日益突出,亟需一套科学化、信息化的管理系统来优化项目全生命周…

2026/5/17 11:11:15 阅读更多 →
二十层线路板设计制造,信号完整性与成本控制是关键

二十层线路板设计制造,信号完整性与成本控制是关键

去进行二十层 PCB 板的设计,这就如同于在微观的世界范围之内去构建一座具备精密立体特质的“电子城市”一般。那信号它会在那些层层叠叠的介质当中进行高速的穿行,对于工程师而言,所面临的早就已经不再是那种“能不能连通”的属于初级阶段的问…

2026/5/17 11:11:16 阅读更多 →

最新新闻

VisTR完全指南:从安装到推理,30分钟快速掌握视频实例分割神器

VisTR完全指南:从安装到推理,30分钟快速掌握视频实例分割神器

VisTR完全指南:从安装到推理,30分钟快速掌握视频实例分割神器 【免费下载链接】VisTR [CVPR2021 Oral] End-to-End Video Instance Segmentation with Transformers 项目地址: https://gitcode.com/gh_mirrors/vi/VisTR VisTR(End-to-…

2026/7/4 21:11:55 阅读更多 →
CANN/ge LLM-DataDist C++接口列表

CANN/ge LLM-DataDist C++接口列表

# LLM-DataDist-interface-list 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE…

2026/7/4 21:09:54 阅读更多 →
电流频率转换模块选型要考虑哪些参数?量程匹配、精度等级与封装形式的综合决策

电流频率转换模块选型要考虑哪些参数?量程匹配、精度等级与封装形式的综合决策

I/F(电流-频率)转换模块的选型直接影响测控系统的整体性能。面对不同的应用场景和技术要求,如何从量程、精度、温度范围、封装形式、输出频率等多个维度做出合理选择,是系统设计师需要解决的问题。本文结合智腾微电子JLHIF160的技…

2026/7/4 21:09:54 阅读更多 →
ThinkPHP 6.0.8反序列化漏洞深度剖析:从POP链原理到实战利用

ThinkPHP 6.0.8反序列化漏洞深度剖析:从POP链原理到实战利用

1. 项目概述:一次对ThinkPHP6.0.8反序列化漏洞的深度剖析最近在复盘一些经典的PHP框架漏洞案例,ThinkPHP6.0.8的反序列化漏洞(CVE-2021-36542)绝对是一个绕不开的经典。这个漏洞的利用链(POP Chain)设计得非…

2026/7/4 21:05:52 阅读更多 →
LiveViewJS生命周期完全解析:从Mount到HandleEvent的完整流程

LiveViewJS生命周期完全解析:从Mount到HandleEvent的完整流程

LiveViewJS生命周期完全解析:从Mount到HandleEvent的完整流程 【免费下载链接】liveviewjs LiveView-based library for reactive app development in NodeJS and Deno 项目地址: https://gitcode.com/gh_mirrors/li/liveviewjs 想要构建实时、响应式的Web应…

2026/7/4 21:05:52 阅读更多 →
天龙八部GM工具:3分钟掌握游戏数据自由编辑的终极方法

天龙八部GM工具:3分钟掌握游戏数据自由编辑的终极方法

天龙八部GM工具:3分钟掌握游戏数据自由编辑的终极方法 【免费下载链接】TlbbGmTool 某网络游戏的单机版本GM工具 项目地址: https://gitcode.com/gh_mirrors/tl/TlbbGmTool 还在为游戏中重复刷怪升级而烦恼?想要快速体验天龙八部单机版的全部内容…

2026/7/4 21:03:51 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻