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

删除 基于Spring AI的课程查询与卡片展示实现

一、背景与需求在天机AI助手中学生可以通过自然语言查询课程信息。例如学生提供课程ID后系统需要调用课程微服务的接口获取课程详细信息并在前端以卡片形式展示包含课程名称、价格、适用人群、详情等并支持点击跳转。原有的课程微服务已经提供了通过课程ID查询课程基础的Feign接口。我们需要在AI助手中集成该能力同时解决一个关键难题大模型返回的是文本内容而前端需要结构化的JSON数据来渲染卡片。二、整体实现流程定义课程信息结果类CourseInfo编写工具类CourseTools通过Tool注解暴露给Spring AI在ChatClient中注册工具解决卡片渲染问题通过ToolContext传递requestId使用ToolResultHolder暂存工具结果最后在响应流中追加结构化数据下面我们逐步展开。三、代码实现3.1 定义课程信息结果类javaData Builder NoArgsConstructor AllArgsConstructor public class CourseInfo { JsonPropertyDescription(课程id) private Long id; JsonPropertyDescription(课程名称) private String name; JsonPropertyDescription(课程价格单位为元货币为人民币) private double price; JsonPropertyDescription(课程学习有效期单位月) private Integer validDuration; JsonPropertyDescription(适用人群例如初学者) private String usePeople; JsonPropertyDescription(课程详细介绍) private String detail; public static CourseInfo of(CourseBaseInfoDTO dto) { if (dto null) return null; CourseInfo info BeanUtil.toBeanIgnoreError(dto, CourseInfo.class); info.setPrice(Optional.ofNullable(dto.getPrice()) .map(p - NumberUtil.round(p / 100.0, 2).doubleValue()) .orElse(0.0)); return info; } }CourseBaseInfoDTO来自课程微服务的Feign接口其中价格字段单位为分。我们在of方法中将其转换为元并保留两位小数。3.2 定义常量javapublic interface Constant { String REQUEST_ID requestId; interface Tools { String QUERY_COURSE_BY_ID 根据课程id查询课程详细信息; } interface ToolParams { String COURSE_ID 课程id; } }良好的常量管理有助于代码维护。3.3 编写工具类CourseToolsjavaComponent RequiredArgsConstructor public class CourseTools { private final CourseClient courseClient; private static final String FIELD_NAME_FORMAT {}_{}; Tool(description Constant.Tools.QUERY_COURSE_BY_ID) public CourseInfo queryCourseById(ToolParam(description Constant.ToolParams.COURSE_ID) Long courseId, ToolContext toolContext) { return Optional.ofNullable(courseId) .map(id - CourseInfo.of(courseClient.baseInfo(id, true))) .map(courseInfo - { String field StrUtil.format(FIELD_NAME_FORMAT, StrUtil.lowerFirst(CourseInfo.class.getSimpleName()), courseInfo.getId()); String requestId Convert.toStr(toolContext.getContext().get(Constant.REQUEST_ID)); ToolResultHolder.put(requestId, field, courseInfo); return courseInfo; }) .orElse(null); } }关键点方法参数中增加了ToolContext用于接收从调用链传递的requestId。查询结果后将CourseInfo存入ToolResultHolderkey为requestIdvalue中再使用field区分具体的课程数据。3.4 注册工具到ChatClientjavaBean public ChatClient chatClient(ChatClient.Builder builder, Advisor loggerAdvisor, Advisor messageChatMemoryAdvisor, CourseTools courseTools) { return builder .defaultAdvisors(loggerAdvisor, messageChatMemoryAdvisor) .defaultTools(courseTools) .build(); }3.5 实现ToolResultHolder工具结果暂存器javapublic class ToolResultHolder { private static final MapString, MapString, Object HANDLER_MAP new ConcurrentHashMap(); public static void put(String key, String field, Object result) { HANDLER_MAP.computeIfAbsent(key, k - new HashMap()).put(field, result); } public static MapString, Object get(String key) { return key null ? null : HANDLER_MAP.get(key); } public static void remove(String key) { HANDLER_MAP.remove(key); } }这个线程安全的容器用于在一次请求中保存多个工具执行结果。3.6 在聊天服务中生成requestId并处理输出流javaOverride public FluxChatEventVO chat(String question, String sessionId) { var conversationId ChatService.getConversationId(sessionId); StringBuilder outputBuilder new StringBuilder(); var requestId IdUtil.fastSimpleUUID(); // 每次请求生成唯一ID return chatClient.prompt() .system(promptSystem - promptSystem .text(systemPromptConfig.getChatSystemMessage().get()) .param(now, DateUtil.now())) .advisors(advisor - advisor.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_CONVERSATION_ID_KEY, conversationId)) .toolContext(Map.of(Constant.REQUEST_ID, requestId)) // 传递requestId .user(question) .stream() .chatResponse() .doFirst(() - GENERATE_STATUS.put(sessionId, true)) .doOnComplete(() - GENERATE_STATUS.remove(sessionId)) .doOnError(e - GENERATE_STATUS.remove(sessionId)) .doOnCancel(() - saveStopHistoryRecord(conversationId, outputBuilder.toString())) .takeWhile(s - Optional.ofNullable(GENERATE_STATUS.get(sessionId)).orElse(false)) .map(chatResponse - { String text chatResponse.getResult().getOutput().getText(); outputBuilder.append(text); return ChatEventVO.builder() .eventData(text) .eventType(ChatEventTypeEnum.DATA.getValue()) .build(); }) .concatWith(Flux.defer(() - { MapString, Object map ToolResultHolder.get(requestId); if (CollUtil.isNotEmpty(map)) { ToolResultHolder.remove(requestId); ChatEventVO paramEvent ChatEventVO.builder() .eventData(map) .eventType(ChatEventTypeEnum.PARAM.getValue()) .build(); return Flux.just(paramEvent, STOP_EVENT); } return Flux.just(STOP_EVENT); })); }注意toolContext(Map.of(Constant.REQUEST_ID, requestId))将请求ID传递给Tool。在流结束时通过ToolResultHolder.get(requestId)获取本次请求产生的所有工具结果将其封装为PARAM类型的事件发送给前端。前端约定的事件类型1003对应卡片渲染eventData中存放课程信息。四、测试效果用户输入查询课程课程id为1589905661084430337后端接收到请求生成requestId调用AI模型。模型识别到需要查询课程触发CourseTools.queryCourseById传入课程ID和ToolContext。工具从课程微服务获取数据转成CourseInfo并存入ToolResultHolderkey为requestId。模型生成文本回复如“已为您查询到课程信息如下”。流式传输文本内容最后追加一个PARAM事件携带课程JSON数据。前端根据PARAM事件渲染课程卡片用户可点击跳转详情页。五、小结本文介绍了在天机AI助手中集成课程查询卡片功能的完整实现核心要点包括工具的定义与注册使用Spring AI的Tool注解并通过defaultTools注册到ChatClient。数据的跨层传递通过ToolContext传递请求级唯一ID保证并发场景下数据不会错乱。结构化数据输出借助ToolResultHolder暂存工具结果在响应流末尾追加JSON数据满足前端卡片渲染需求。代码规范常量化、工具类设计、线程安全容器等最佳实践。这一模式可推广到其他需要结构化展示如商品卡片、用户卡片、图表数据的AI助手场景。希望本文能为您提供有益的参考。

相关文章:

删除 基于Spring AI的课程查询与卡片展示实现

一、背景与需求在天机AI助手中,学生可以通过自然语言查询课程信息。例如,学生提供课程ID后,系统需要调用课程微服务的接口,获取课程详细信息,并在前端以卡片形式展示(包含课程名称、价格、适用人群、详情等…...

Docker存储性能翻倍实操:3步精准配置overlay2,90%工程师都忽略的inode泄漏预警

更多请点击: https://intelliparadigm.com 第一章:Docker存储配置概览与核心挑战 Docker 的存储机制直接影响容器的性能、数据持久性与跨环境一致性。其底层依赖存储驱动(Storage Driver)管理镜像层与容器层的读写,不…...

YoloMouse终极指南:如何用开源工具彻底解决游戏光标太小看不清的问题

YoloMouse终极指南:如何用开源工具彻底解决游戏光标太小看不清的问题 【免费下载链接】YoloMouse Game Cursor Changer 项目地址: https://gitcode.com/gh_mirrors/yo/YoloMouse 你是否曾在激烈的游戏对战中,因为鼠标光标太小、颜色单调而迷失方向…...

论述情况盀导致全转栈系统通信通讯无法进入感应联系,致使握手网络正常值哈希被恶意倉取仺⺋以钩子成鐌檵盀的导致䗃进行恶意压仓的方式元

### 问题解构提出的问题涉及多个技术概念的复杂组合,部分表述(如“正值”、“压仓注入”、“利率占比”)在常规计算机科学语境下较为晦涩或可能存在隐喻。为了准确回答,首先对问题进行技术层面的解构与重构:1. **攻击…...

AISMM模型中的隐性治理协议(联盟章程里从未写明却决定成败的3类动态契约)

更多请点击: https://intelliparadigm.com 第一章:AISMM模型中的隐性治理协议(联盟章程里从未写明却决定成败的3类动态契约) 在AISMM(Autonomous Inter-System Mediation Model)架构中,显性治…...

告别臃肿模拟器!APK-Installer让你在Windows上3分钟搞定安卓应用安装

告别臃肿模拟器!APK-Installer让你在Windows上3分钟搞定安卓应用安装 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 还在为安装笨重的安卓模拟器而烦恼吗&…...

AISMM评估价值被严重低估!SITS2026现场实测:同一组织经AISMM牵引后,安全预算效能提升2.8倍

更多请点击: https://intelliparadigm.com 第一章:AISMM评估的价值被严重低估!SITS2026现场实测洞察 在 SITS2026(Software Intelligence & Trustworthiness Summit)技术展会上,我们对 AISMM&#xf…...

3分钟快速掌握VideoDownloadHelper:高效视频下载终极指南

3分钟快速掌握VideoDownloadHelper:高效视频下载终极指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 想要轻松下载在线视频却…...

金融核心系统灰度发布中的测试兜底方案

一、在金融科技飞速发展的当下,金融核心系统作为金融机构业务运营的“心脏”,其稳定性、安全性和连续性直接关系到金融机构的生存与发展,更关乎广大客户的资金安全和金融市场的稳定。灰度发布作为一种降低系统上线风险的有效手段,…...

2025届学术党必备的六大降重复率平台横评

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 撰写文本之际,为把AI生成痕迹予以降低,得从词汇、句法以及结构这三个…...

查看 Taotoken 账单明细理解按 token 计费的透明性

查看 Taotoken 账单明细理解按 token 计费的透明性 对于使用大模型 API 的开发者而言,成本控制是项目可持续性的关键。按 token 计费是当前主流且精确的计费模式,但如何清晰地追踪每一笔花费,理解费用构成,是许多用户关心的问题。…...

AISMM模型与政策建议深度对标(2024最新国标/行标合规对照表首次公开)

更多请点击: https://intelliparadigm.com 第一章:AISMM模型与政策建议深度对标(2024最新国标/行标合规对照表首次公开) AISMM(AI Security Maturity Model)是我国2024年正式发布的首个人工智能安全成熟度…...

AD8232开源心电监测终极指南:30分钟构建专业级生物信号采集系统

AD8232开源心电监测终极指南:30分钟构建专业级生物信号采集系统 【免费下载链接】AD8232_Heart_Rate_Monitor AD8232 Heart Rate Monitor 项目地址: https://gitcode.com/gh_mirrors/ad/AD8232_Heart_Rate_Monitor 在医疗健康监测和可穿戴设备开发领域&#…...

支付账单拉取和标准化怎么做才稳?渠道获取、格式解析、统一账单模型全讲清

支付账单拉取和标准化怎么做才稳?渠道获取、格式解析、统一账单模型全讲清 这篇直接按支付账单拉取和标准化来拆,不只讲“把文件拉下来”,而是把渠道差异、格式解析、统一模型和补拉讲具体。 目标是你看完后,能把账单拉取从一个下…...

暗黑破坏神2重制版自动化运行:D2R Pixel Bot完整指南

暗黑破坏神2重制版自动化运行:D2R Pixel Bot完整指南 【免费下载链接】botty D2R Pixel Bot 项目地址: https://gitcode.com/gh_mirrors/bo/botty D2R Pixel Bot是一款专门为《暗黑破坏神2重制版》设计的像素级自动化工具,通过先进的图像识别技术…...

终极macOS窗口透明化方案:开源工具深度解析与应用实战

终极macOS窗口透明化方案:开源工具深度解析与应用实战 【免费下载链接】open-source-mac-os-apps 🚀 Awesome list of open source applications for macOS. https://t.me/s/opensourcemacosapps 项目地址: https://gitcode.com/gh_mirrors/op/open-so…...

终极Kindle漫画转换指南:用KCC打造完美电子漫画体验

终极Kindle漫画转换指南:用KCC打造完美电子漫画体验 【免费下载链接】kcc KCC (a.k.a. Kindle Comic Converter) is a comic and manga converter for ebook readers. 项目地址: https://gitcode.com/gh_mirrors/kc/kcc 你是否曾在Kindle上打开漫画时遇到页面…...

在ubuntu系统上使用curl快速测试taotoken大模型api连通性

在Ubuntu系统上使用curl快速测试Taotoken大模型API连通性 对于在Ubuntu服务器或开发环境中工作的开发者而言,快速验证一个API服务的连通性是集成前的关键一步。Taotoken平台提供了OpenAI兼容的HTTP API,这意味着您无需安装任何特定的SDK,仅使…...

Windows系统优化神器Winhance中文版:小白也能轻松掌握的终极优化指南

Windows系统优化神器Winhance中文版:小白也能轻松掌握的终极优化指南 【免费下载链接】Winhance-zh_CN A Chinese version of Winhance. C# application designed to optimize and customize your Windows experience. 项目地址: https://gitcode.com/gh_mirrors/…...

语音助手DNS查询技能开发:从API集成到智能家居运维实践

1. 项目概述:一个DNS查询技能的诞生最近在折腾智能音箱和家庭自动化,发现一个挺有意思的需求:能不能直接问家里的智能设备,某个网站的DNS解析情况?比如,想知道“我的博客域名解析生效了吗?”或者…...

如何深度定制UndertaleModTool:从游戏修改到二次开发的完整指南

如何深度定制UndertaleModTool:从游戏修改到二次开发的完整指南 【免费下载链接】UndertaleModTool The most complete tool for modding, decompiling and unpacking Undertale (and other GameMaker games!) 项目地址: https://gitcode.com/gh_mirrors/un/Under…...

Windows微信批量消息发送终极指南:3步轻松搞定群发任务

Windows微信批量消息发送终极指南:3步轻松搞定群发任务 【免费下载链接】WeChat-mass-msg 微信自动发送信息,微信群发消息,Windows系统微信客户端(PC端 项目地址: https://gitcode.com/gh_mirrors/we/WeChat-mass-msg 还在…...

解锁Unity资源宝库:用AssetRipper在3个场景中高效提取游戏资产

解锁Unity资源宝库:用AssetRipper在3个场景中高效提取游戏资产 【免费下载链接】AssetRipper GUI Application to work with engine assets, asset bundles, and serialized files 项目地址: https://gitcode.com/GitHub_Trending/as/AssetRipper 你是否曾面…...

开源像素智能体监控平台:可视化调试AI决策,提升自动化任务效率

1. 项目概述:一个面向像素级智能体的开源监控平台最近在折腾一些AI智能体项目,特别是那些需要处理图像、进行像素级交互的自动化任务时,我遇到了一个很实际的问题:我怎么知道我的智能体“看”到了什么,又在“想”什么&…...

VoWLAN技术挑战与802.11e QoS解决方案解析

1. VoWLAN技术挑战与802.11e QoS解决方案深度解析作为一名在无线通信领域工作多年的工程师,我见证了VoWLAN技术从实验室走向商用的全过程。在这个过程中,最核心的挑战始终是如何在共享的无线介质上保障语音业务的质量。本文将基于IEEE 802.11标准族的技术…...

手机耳机麦克风(ECM)电路设计避坑指南:从差分走线到射频干扰的实战经验

手机耳机麦克风(ECM)电路设计避坑指南:从差分走线到射频干扰的实战经验 在移动设备音频系统中,耳机麦克风电路的设计质量直接影响通话清晰度和语音交互体验。驻极体电容麦克风(ECM)因其成本优势和良好的频响…...

安卓USB调试不显示问题

问题:原本安卓可以开启USB调试正常的,被修改设定后不再弹出USB连接的提示问题解决:发现的OTG连接被打开了,关闭了之后就恢复正常...

基于lumerical fdtd的六边形狭缝生成斯格明子

关键词:斯格明子;SPP波;光学斯格明子;相位调控本工作基于表面等离激元(SPP)场,设计六边形金属狭缝结构实现光学斯格明子的动态调控,通过时域有限差分法(FDTD)…...

【已解决】Microsoft Edge无法打开 错误代码0x80070002/0x80004005 并行配置不正确

# 【已解决】Microsoft Edge无法打开 错误代码0x80070002/0x80004005 并行配置不正确## 问题描述Edge浏览器突然无法打开,尝试各种方法都失败: - **错误1**:应用程序的并行配置不正确。请参阅应用程序事件日志,或使用命令行 sxstr…...

【C++】 vector(代码实现+坑点讲解)

作为C标准模板库(STL)中最基础、最常用的容器之一,vector提供了动态数组的功能。今天我们将深入探讨如何从零实现一个完整的vector容器,理解其内部工作原理和设计思想。 代码解释:C Vector模板类实现 代码整体功能和…...