三、Spring AI Alibaba · Messages
Spring AI Alibaba · Messages 消息整理时间2026-10-09适用版本Spring AI 1.1.0 / Spring AI Alibaba 1.1.2.x一、什么是 MessageMessage 是模型交互的基本单元代表模型的输入与输出承载对话状态所需的内容和元数据。Spring AI Alibaba 提供跨厂商一致的标准消息类型系统。一个 Message 由三部分组成组成说明Role角色标识消息类型system / user / assistant / toolContent内容实际内容文本、图像、音频、文档等Metadata元数据可选响应信息、消息 ID、token 使用情况注意并非所有厂商都对三者一视同仁尤其 metadata 的行为因提供商而异有的用于用户识别有的直接忽略使用前需查对应厂商文档。二、两种调用方式文本提示 vs 消息提示文本提示StringStringresponsechatModel.call(写一首关于春天的俳句);适用场景单个独立请求不需要对话历史追求最小代码复杂度本质是单个 UserMessage 的快捷方式拿不到 metadata / token 用量。消息提示ListMessageListMessagemessagesList.of(newSystemMessage(你是一个诗歌专家),newUserMessage(写一首关于春天的俳句),newAssistantMessage(樱花盛开时...));PromptpromptnewPrompt(messages);ChatResponseresponsechatModel.call(prompt);适用场景管理多轮对话处理多模态内容图像 / 音频 / 文件需要携带系统指令三、四种消息类型3.1 SystemMessage —— 定规则、设人设用于设定语气、定义角色、建立响应指南。// 基础指令SystemMessagesystemMsgnewSystemMessage(你是一个有帮助的编程助手。);// 详细角色设定推荐用文本块SystemMessagesystemMsgnewSystemMessage( 你是一位资深的 Java 开发者擅长 Web 框架。 始终提供代码示例并解释你的推理。 在解释中要简洁但透彻。 );本项目MockInterviewService就是这一模式的典型SystemMessage(prompt资源)UserMessage(简历/问答)。3.2 UserMessage —— 用户输入与多模态载体纯文本ChatResponseresponsechatModel.call(newPrompt(List.of(newUserMessage(什么是机器学习))));StringshortcutchatModel.call(什么是机器学习);// 等价快捷方式带元数据UserMessageuserMsgUserMessage.builder().text(你好).metadata(Map.of(user_id,alice,// 用户标识session_id,sess_123// 会话标识)).build();多模态MediaUserMessageuserMsgUserMessage.builder().text(描述这张图片的内容。).media(Media.builder().mimeType(MimeTypeUtils.IMAGE_JPEG).data(newURL(https://example.com/image.jpg))// 也支持 ClassPathResource.build()).build();3.3 AssistantMessage —— 模型输出模型调用返回的结果包含文本内容、工具调用、媒体内容与厂商元数据。ChatResponseresponsechatModel.call(newPrompt(解释 AI));AssistantMessageaiMessageresponse.getResult().getOutput();System.out.println(aiMessage.getText());四要素属性说明text消息文本内容metadata元数据映射含厂商特有信息如 reasoningContenttoolCalls模型发起的工具调用列表media媒体内容列表若有手动构造回填历史对话编排/纠偏常用AssistantMessageaiMsgnewAssistantMessage(我很乐意帮助你回答这个问题);ListMessagemessagesList.of(newSystemMessage(你是一个有帮助的助手),newUserMessage(你能帮我吗),aiMsg,// 插入就像它来自模型一样newUserMessage(太好了22 等于多少));ChatResponseresponsechatModel.call(newPrompt(messages));不同厂商对消息权重的处理方式不同手动插入 AssistantMessage 是控制对话走向的实用技巧。工具调用读取AssistantMessageaiMessageresponse.getResult().getOutput();if(aiMessage.hasToolCalls()){for(AssistantMessage.ToolCalltoolCall:aiMessage.getToolCalls()){System.out.println(Tool: toolCall.name());System.out.println(Args: toolCall.arguments());System.out.println(ID: toolCall.id());}}3.4 ToolResponseMessage —— 工具执行结果回传用于把单个工具执行的结果回传给模型让 LLM 接着推理。// 1) 模型发出工具调用AssistantMessageaiMessageAssistantMessage.builder().content().toolCalls(List.of(newAssistantMessage.ToolCall(call_123,tool,get_weather,{\location\: \San Francisco\}))).build();// 2) 执行工具构造结果消息ToolResponseMessagetoolMessageToolResponseMessage.builder().responses(List.of(newToolResponse(call_123,get_weather,晴朗22°C))).build();// 3) 继续对话ListMessagemessagesList.of(newUserMessage(旧金山的天气怎么样),aiMessage,// 模型的工具调用toolMessage// 工具执行结果);ChatResponseresponsechatModel.call(newPrompt(messages));ToolResponse 三要素字段说明id工具调用 ID必须与 AssistantMessage 中的 toolCall.id 匹配name调用的工具名称responseData工具输出的字符串化结果这就是 ReactAgent「推理 → 行动 → 观察」中Observation环节的底层形式。四、Token 使用统计ChatResponse的 metadata 中保存 token 计数与使用信息ChatResponseresponsechatModel.call(newPrompt(你好));ChatResponseMetadatametadataresponse.getMetadata();if(metadata!nullmetadata.getUsage()!null){System.out.println(Input tokens: metadata.getUsage().getPromptTokens());System.out.println(Output tokens: metadata.getUsage().getCompletionTokens());System.out.println(Total tokens: metadata.getUsage().getTotalTokens());}成本治理的第一步别把ChatResponse丢掉。写getResult().getOutput().getText()的链式调用会让中间的 metadata 无从获取。五、流式与块Chunk流式期间收到的每个ChatResponse是消息的片段需要自己拼接FluxChatResponseresponseStreamchatModel.stream(newPrompt(你好));StringBuilderfullResponsenewStringBuilder();responseStream.subscribe(chunk-{Stringcontentchunk.getResult().getOutput().getText();fullResponse.append(content);System.out.print(content);});流式下的消息类型场景怎么取内容模型普通响应AssistantMessage.getText()且metadata.reasoningContent为空模型 Thinkingmetadata.reasoningContent非空如 DeepSeek / qwen 深度思考工具调用请求AssistantMessage.hasToolCalls() true工具执行结果ToolResponseMessage.getResponses()→responseData()六、多模态输入统一通过Mediaorg.springframework.ai.content.Media MIME 类型承载。// 图片 - URL.media(Media.builder().mimeType(MimeTypeUtils.IMAGE_JPEG).data(newURL(https://example.com/image.jpg)).build())// 图片 - 本地/类路径资源.media(newMedia(MimeTypeUtils.IMAGE_JPEG,newClassPathResource(images/photo.jpg)))// 音频.media(newMedia(MimeTypeUtils.parseMimeType(audio/wav),newClassPathResource(audio/recording.wav)))// 视频.media(Media.builder().mimeType(MimeTypeUtils.parseMimeType(video/mp4)).data(newURL(https://example.com/path/to/video.mp4)).build())警告并非所有模型支持所有文件类型需查厂商文档确认格式与大小限制。对照前表通义千问 DashScope 在官方能力矩阵中未标注多模态支持OpenAI / Gemini / Ollama 支持。七、实用 APIBuilder / copy / mutate// UserMessage builderUserMessageuserMsgUserMessage.builder().text(你好我想学习 Spring AI Alibaba).metadata(Map.of(user_id,user_123)).build();// SystemMessage builderSystemMessagesystemMsgSystemMessage.builder().text(你是一个 Spring 框架专家).metadata(Map.of(version,1.0)).build();// AssistantMessage builderAssistantMessageassistantMsgAssistantMessage.builder().content(我很乐意帮助你学习 Spring AI Alibaba).build();// 复制UserMessagecopyoriginal.copy();// 基于副本修改原对象不变UserMessagemodifiedoriginal.mutate().text(修改后的消息).metadata(Map.of(modified,true)).build();mutate()是不可变风格的改造入口适合在拦截器/钩子中改写消息而不污染原列表。八、多轮对话ChatModel 是无状态的ChatModel 交互天然无状态简单对话循环 不断变长的消息列表ListMessageconversationHistorynewArrayList();conversationHistory.add(newUserMessage(你好));ChatResponseresponse1chatModel.call(newPrompt(conversationHistory));conversationHistory.add(response1.getResult().getOutput());// 把 AI 回复回填conversationHistory.add(newUserMessage(你能帮我学习 Java 吗));ChatResponseresponse2chatModel.call(newPrompt(conversationHistory));conversationHistory.add(response2.getResult().getOutput());conversationHistory.add(newUserMessage(从哪里开始));ChatResponseresponse3chatModel.call(newPrompt(conversationHistory));三个必须注意的点每轮都要把AssistantMessage回填否则模型失忆。列表会不断膨胀 → 需要窗口裁剪/摘要ReactAgent 里对应MessagesModelHook。生产环境请交给ChatMemory或 Agent 的SaverMemorySaver / RedisSaver托管。九、在 ReactAgent 中使用 MessageReactAgent自动管理消息历史但也接受直接传消息ReactAgentagentReactAgent.builder().name(my_agent).model(chatModel).systemPrompt(你是一个有帮助的助手).build();AssistantMessager1agent.call(你好);// 字符串AssistantMessager2agent.call(newUserMessage(帮我写一首诗));// 单条 UserMessageListMessagemessagesList.of(newUserMessage(我喜欢春天),newUserMessage(写一首关于春天的诗));AssistantMessager3agent.call(messages);// 消息列表十、速查表类型谁产生关键 APISystemMessage开发者.text()多写角色规则输出格式UserMessage用户/系统.text().media().metadata()AssistantMessage模型.getText().hasToolCalls().getToolCalls().getMetadata()ToolResponseMessage工具执行侧.builder().responses(List.of(new ToolResponse(id, name, data)))// 取值链路ChatResponse→getMetadata()// token 用量→getResult()// Generation→getOutput()// AssistantMessage→getText()/hasToolCalls()/getMetadata()四条铁律chatModel.call(String)≡ 单个 UserMessage别指望拿到元数据。多轮上下文靠自己拼ListMessageChatModel 无状态。ToolResponse.id必须和ToolCall.id对齐否则模型无法关联结果。多模态/元数据能力因厂商而异换模型前务必查适配文档。十一、对照本项目MockInterviewService的三次调用都是标准的「System User → Assistant」结构messages.add(newSystemMessage(resumeAnalysisSystemPromptResource));// 资源注入的系统提示messages.add(newUserMessage(promptTemplate.render(Map.of(resumeText,resumeText))));PromptpromptnewPrompt(messages,DashScopeChatOptions.builder().temperature(0.7).build());StringresponsechatModel.call(prompt).getResult().getOutput().getText();可优化点接住 metadata 做成本核算简历全文 长 JSON 输出 token 不低应记录getUsage().getTotalTokens()并做预算告警。回填历史实现追问result.html若要做针对评估报告追问正好用第八节的conversationHistory累加模式以resumeId为 key 存起来。多模态扩展面试官上传项目截图让 AI 点评用UserMessage.media(ClassPathResource/MultipartFile 转 Resource)即可无需改模型层。mutate 改写 SystemMessage想做Java / 前端 / 算法多套面试模式时用systemMsg.mutate().text(...)生成变体避免重复写模板。

相关新闻

OpenClaw接入飞书/钉钉/QQ/企微:四平台IM机器人配置指南与排坑实战

OpenClaw接入飞书/钉钉/QQ/企微:四平台IM机器人配置指南与排坑实战

Openclaw记录写到第二篇。上一篇把基础服务部署完,Openclaw跑起来之后,我干的第一件事就是把手机里的几个IM全接了上去——飞书、钉钉、QQ、企业微信,一个都没落下。这个开源网关服务说白了就是把大模型能力接入各种聊天软件,让你…

2026/10/11 7:49:01 阅读更多 →
nanoMuse: An Open-Source Personal Agent for Every Device You Own——一个属于你所有设备的开源个人智能体

nanoMuse: An Open-Source Personal Agent for Every Device You Own——一个属于你所有设备的开源个人智能体

文章的核心是提出并实现一个开源、个人拥有、可本地运行的“个人智能体”,作为Meta闭源产品Muse的开放对等物。以下是对其主要研究内容的全面总结: 一、研究背景与问题 2026年9月,Meta发布Muse,标志着“个人智能体”产品形态的成…

2026/10/11 7:49:01 阅读更多 →
主流网络、安全、存储、负载均衡产品厂商设备一键收集诊断设备的命令方式

主流网络、安全、存储、负载均衡产品厂商设备一键收集诊断设备的命令方式

主流网络、安全、存储、负载均衡产品厂商设备一键收集诊断设备的命令方式:厂商一键收集诊断信息命令解释Cisco(思科)show tech-support该命令将生成包括所有路由器和交换机配置、接口和协议状态等在内的详细技术支持信息。Juniper Networks&a…

2026/10/11 7:49:01 阅读更多 →

最新新闻

从模糊标题到可运行系统:需求不明确项目的拆解与落地方法

从模糊标题到可运行系统:需求不明确项目的拆解与落地方法

1. 当标题只有一个“rea”时,我们到底在聊什么第一次看到“rea”这个标题,我盯着屏幕愣了好几秒。没有正文,没有关键词,没有摘要,连一个标点符号都没有。这种极简到近乎空白的输入,反而让我觉得有意思——因…

2026/10/11 8:39:35 阅读更多 →
高校机房 / 企业办公全适配:vDisk 融合云桌面,IDV+VDI 双架构 + 算力共享,降本又提效

高校机房 / 企业办公全适配:vDisk 融合云桌面,IDV+VDI 双架构 + 算力共享,降本又提效

不管是高校的公共机房、专业实训室、标准化考点,还是企业的办公终端、研发工位、分支机构,云桌面的核心需求早已从 “能用” 变成 “好用、划算、好管”。微碟云 vDisk 融合云管理平台 5.0全面升级 IDVVDI 双架构能力,打通终端本地算力与集中…

2026/10/11 8:39:35 阅读更多 →
原材料与成品装箱优化:提升仓储空间利用率与出货效率的实操方法

原材料与成品装箱优化:提升仓储空间利用率与出货效率的实操方法

一、装箱优化的核心价值在制造业与外贸物流场景中,集装箱和厢式货车的装载率直接影响单件货物的运输成本。原材料与成品的规格差异大、形状不规则、重量分布不均,导致人工排柜容易出现空间浪费、重心偏移甚至货损。通过数字化装箱模拟,可以在…

2026/10/11 8:39:35 阅读更多 →
LLVM ADT与内存管理:从SmallVector到BumpPtrAllocator的工程实践

LLVM ADT与内存管理:从SmallVector到BumpPtrAllocator的工程实践

1. 从一次编译期崩溃说起:为什么要啃LLVM的ADT和内存管理前阵子帮一个做静态分析工具的朋友排查问题,他的工具基于LLVM做了一套自定义的IR遍历逻辑,跑小文件没问题,一上大工程就随机崩溃,堆栈指向的却总是标准库容器相…

2026/10/11 8:39:35 阅读更多 →
财联社电报实时提示工具:接口轮询与桌面通知实战解析

财联社电报实时提示工具:接口轮询与桌面通知实战解析

简介:面向股民的财联社电报实时提示工具,包含完整源码和编译好的程序。运行后在右下角自动弹窗显示最新消息,并与同花顺、通达信联动;消息中提及的股票支持单击跳转,适合盘中需要即时掌握资讯、快速关注个股的投资者。…

2026/10/11 8:39:35 阅读更多 →
工厂设备如何实现远程监控,支持485传感器、变频器数据采集

工厂设备如何实现远程监控,支持485传感器、变频器数据采集

实现工厂设备远程监控的核心思路:现场采集设备数据 → 边缘网关转发 → 云端/本地平台 → 远程查看、告警、控制,整套架构分为四层:现场感知层、边缘采集层、网络传输层、监控平台层。一、现场感知层(采集设备信号) 负责把设备状态、参数变成…

2026/10/11 8:38:35 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →