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

Spring Ai--快速入门4:流式对话

原文网址:Spring Ai--快速入门4:流式对话-CSDN博客

简介

本文介绍Spring Ai流式对话的实战,以这三种方式进行实战:流式返回字符串结果、流式返回全量SSE数据、流式返回手动调用接口的结果。

备注:之前文章介绍过Spring Ai对话的实战:Spring Ai--快速入门1:对话实战-CSDN博客

流式会话的原理是什么?

流式会话的核心:服务端持续地向客户端发送数据。实现方案有两种:WebSocket、SSE。

WebSocket:大部分人都知道,它是长连接,全双工,客户端可以持续向服务端发送数据,服务端也可以持续地向客户端发送数据。

SSE:全称是:Server-Sent Events,中文含义:服务器发送事件。服务端可以持续地向客户端发送数据,但客户端是一次性的发送请求给服务器。

两者详细的对比可以看这里:WebSocket与SSE的对比-CSDN博客

对比后可以发现:SSE更适合用于AI流式数据返回。

Spring Ai底层就是基于SSE。

测试

用apifox进行测试。

1. 流式返回字符串结果

可以发现:Flux<String>这种写法,直接返回了回答的内容,没有额外的数据。

适合只需要结果的业务场景。

2. 流式返回全量SSE数据

可以发现:Flux<ServerSentEvent<ChatResponse>>这种写法会返回全量SSE数据,里边会包含AI的回答。而且,第一个响应和最后一个响应,真实数据的字段text,是空的。

适合需要全量SSE数据的业务场景。实际上,可以对结果进行定制,比如只取ChatResponse里的某个值,只需改写返回值泛型以及这个地方:

.map(chatResponse -> { return ServerSentEvent .builder(chatResponse) .event("message") .build(); });

第一个响应:

中间的响应

最后一个响应

这里贴出完整的单条响应:

{ "result": { "output": { "messageType": "ASSISTANT", "metadata": { "role": "ASSISTANT", "messageType": "ASSISTANT", "finishReason": "", "refusal": "", "index": 0, "annotations": [], "id": "chatcmpl-e20dbdd1-4e7d-9f48-9ea3-eecdf987d3c9", "reasoningContent": "" }, "toolCalls": [], "media": [], "text": "我可以" }, "metadata": { "finishReason": "", "contentFilters": [], "empty": true } }, "results": [ { "output": { "messageType": "ASSISTANT", "metadata": { "role": "ASSISTANT", "messageType": "ASSISTANT", "finishReason": "", "refusal": "", "index": 0, "annotations": [], "id": "chatcmpl-e20dbdd1-4e7d-9f48-9ea3-eecdf987d3c9", "reasoningContent": "" }, "toolCalls": [], "media": [], "text": "我可以" }, "metadata": { "finishReason": "", "contentFilters": [], "empty": true } } ], "metadata": { "id": "chatcmpl-e20dbdd1-4e7d-9f48-9ea3-eecdf987d3c9", "model": "qwen-plus", "rateLimit": { "tokensLimit": 0, "requestsReset": "PT0S", "tokensRemaining": 0, "tokensReset": "PT0S", "requestsLimit": 0, "requestsRemaining": 0 }, "usage": { "promptTokens": 0, "nativeUsage": {}, "completionTokens": 0, "totalTokens": 0 }, "promptMetadata": [], "empty": false } }

3. 流式返回手动调用接口数据

可以发现:Flux<ServerSentEvent<String>>这种写法会返回SSE部分数据,里边会包含AI的回答。而且,第一个响应和倒数第二个响应,真实数据的字段content,是空的;最后一个响应,是个统计性的数据,连content字段都没有,里边有一些token使用量等使用数据。

适合需要高度定制的业务场景。因为此法是直接使用WebFlux进行的接口调用,自由度最大。

第一次响应:

最后两个响应:

这里贴出详细数据

第一个响应:

{ "choices": [ { "delta": { "content": "", "role": "assistant" }, "index": 0, "logprobs": null, "finish_reason": null } ], "object": "chat.completion.chunk", "usage": null, "created": 1768920120, "system_fingerprint": null, "model": "qwen-plus", "id": "chatcmpl-174ca428-8fa3-9129-8567-69ccc39199d9" }

中间的响应:

{ "choices": [ { "finish_reason": null, "logprobs": null, "delta": { "content": "你好" }, "index": 0 } ], "object": "chat.completion.chunk", "usage": null, "created": 1768920120, "system_fingerprint": null, "model": "qwen-plus", "id": "chatcmpl-174ca428-8fa3-9129-8567-69ccc39199d9" }

倒数第二个响应:

{ "choices": [ { "finish_reason": "stop", "delta": { "content": "" }, "index": 0, "logprobs": null } ], "object": "chat.completion.chunk", "usage": null, "created": 1768920120, "system_fingerprint": null, "model": "qwen-plus", "id": "chatcmpl-174ca428-8fa3-9129-8567-69ccc39199d9" }

最后一个响应:

{ "choices": [], "object": "chat.completion.chunk", "usage": { "prompt_tokens": 11, "completion_tokens": 278, "total_tokens": 289, "prompt_tokens_details": { "cached_tokens": 0 } }, "created": 1768920120, "system_fingerprint": null, "model": "qwen-plus", "id": "chatcmpl-174ca428-8fa3-9129-8567-69ccc39199d9" }

代码

为便于维护,全文已转移到此网址:Spring Ai-快速入门4:流式对话 - 自学精灵

http://www.jsqmd.com/news/1352959/

相关文章:

  • 企业微信消息回调开发指南:如何实时接收并处理企微消息?
  • 5分钟让你的Windows提速50%:WinUtil终极优化工具完整指南
  • 3分钟掌握FastReport:免费开源报表工具让你的.NET应用数据可视化更简单
  • 5分钟构建全球地图可视化:world.geo.json地理数据宝库完全指南
  • Unity高性能动画系统:基于C# Job System的并行混合与IK实现
  • 5步彻底解决G-Helper启动问题:从现象到根源的完整指南
  • 终极指南:3步掌握tchMaterial-parser电子课本下载工具的完整教程
  • 为什么每个.NET开发者都需要gh_mirrors/edi/EditorConfig?StyleCop兼容的编码规范详解
  • 毕业论文高效写作:四步搞定初稿与智能工具应用
  • 终极免费跨平台GTA圣安地列斯存档编辑器:3个实用场景解决你的游戏难题
  • 手机变身装机神器:EtchDroid安卓启动盘制作终极指南
  • Unity机器人仿真:三步导入URDF模型与ROS集成实战
  • 3步彻底解决《恶霸鲁尼》Windows 10崩溃问题:终极兼容性修复方案
  • 阿里云万相3.0 AI视频生成实战:从API接入到30秒长视频工程化应用
  • Ant Design Modal全屏实现:CSS覆盖、Ref操作与高阶组件封装
  • 终极指南:3步打造你的专属Arduino电子宠物,重温童年记忆!
  • 大地影院卡回收,2026年手里的卡券到底怎么变现更划算? - 沃卡回收
  • 电商企微机器人:从自动欢迎语到订单转化,打造私域闭环
  • 终极指南:5分钟免费安装SD-PPP,让Photoshop拥有AI绘图超能力
  • 来自中立测评机构发布:2026年8月GEO服务商综合**,十家机构深度测评与选型指南 - 优质品牌中立测评推荐
  • Illustrator脚本合集:10款免费神器彻底改变你的设计工作流
  • 5个理由让你爱上Blockly:重新定义可视化编程体验
  • 5分钟搞定Coding WebIDE配置:修改端口、工作空间和用户信息完整指南
  • Qwen3.8 Max开源大模型部署实战:从环境准备到生产级应用
  • NBA 2K20自定义补丁通用安装指南:从备份到验证的完整流程
  • VC++中Tab键导航实现:从原理到MFC/Win32实战
  • 南开酒店消防维保服务商怎么选?重资质与实效|中隆消防(南开营销部) - 热点品牌推荐
  • AFL模糊测试实战:覆盖率引导的漏洞挖掘与工程优化
  • MediaCrawler-new:如何用Python一站式采集五大社交媒体数据
  • Diablo Edit2:暗黑破坏神II专业级存档编辑器的创新应用指南