摘要
Spring AI 通过消息(Message)抽象统一了与大模型的对话载体,将系统指令、用户输入、助手回复和工具调用结果分别封装为四个独立的消息类。本文深入解析 SystemMessage、UserMessage、AssistantMessage 和 ToolResponseMessage 的底层设计、作用边界与配合方式,并结合 Spring AI Alibaba DashScope 给出从环境配置到多轮对话、Function Calling 完整闭环的代码实践,助你彻底吃透 Spring AI 的提示词工程核心。
1. 四大角色整体设计
Spring AI 将与模型的一次完整交互抽象为 Message 接口,并针对对话中不同来源和用途的内容设计了四个具体的实现类。每条消息都携带一个专属的 Role 标识,大模型通过这一角色区分语义边界,从而彻底告别混乱的字符串拼接。
| SystemMessage | SYSTEM | 全局系统指令,定义 AI 身份、输出规范、行为约束 | 消息列表首位,全局永久生效,不被用户覆盖 |
| UserMessage | USER | 用户原始提问、业务输入、多模态内容 | 对话输入源,动态可变业务数据存放处 |
| AssistantMessage | ASSISTANT | 大模型历史回答、工具调用请求载体 | 多轮上下文核心,可携带 ToolCall 指令 |
| ToolResponseMessage | TOOL | 外部工具执行结果 | Function Calling 闭环必备,补齐数据后回传 |
这四个角色的有序组合构成了 Prompt(提示词),最终交给模型推理。下面逐一拆解每个角色的设计意图和正确使用方式。
2. 角色详解与使用规范
2.1 SystemMessage —— 全局指挥官
SystemMessage 是对话中最高优先级的指令,用于固定 AI 的人设、输出格式、领域约束和安全边界。在一轮完整对话的消息列表中,通常只在最前面放置一条。
⚠️ 使用禁忌不要把动态变化的业务数据(如用户 ID、订单详情)放入 SystemMessage,因为每次变更都会导致提示词整体发生变化,白白消耗 token。系统消息应该保持稳定。
SystemMessage systemMsg = new SystemMessage(""" 你是资深Java后端技术专家,基于Spring AI Alibaba框架解答问题; 1. 回答必须附带可运行完整代码; 2. 代码使用Java17规范,适配DashScope通义千问; 3. 不编造不存在的框架API,解释简洁易懂。 """);
2.2 UserMessage —— 人类输入载体
所有来自用户侧的内容都通过 UserMessage 封装。它支持纯文本、图片(多模态)等输入,是触发每一次对话的源头。在多轮对话中,每一个新的用户提问都会创建一个新的 UserMessage 追加到消息列表末尾。
// 普通文本提问UserMessage userMsg = new UserMessage("讲解Spring AI Alibaba四大Prompt角色用法");// 多模态示例(图片+文本)// UserMessage multiModalMsg = new UserMessage("分析这张图片", // List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageResource)));
2.3 AssistantMessage —— 模型双向载体
AssistantMessage 身兼两职:
多轮上下文拼接示例:
[SystemMessage, UserMessage1, AssistantMessage1, UserMessage2, AssistantMessage2, …]
// 普通回答AssistantMessage assistant = new AssistantMessage("ChatModel是底层标准接口,ChatClient是上层便捷封装。");// 工具调用(框架自动生成)// AssistantMessage 内含 toolCalls 字段
2.4 ToolResponseMessage —— 外部数据桥梁
仅在 Function Calling 场景出现。一条完整的工具调用链路为:
UserMessage → AssistantMessage(含 ToolCall) → 本地执行工具 → ToolResponseMessage → 二次请求模型
ToolResponseMessage 将工具执行的结果封装,并将其与之前所有的消息(系统、用户、助手工具调用)合并,再次发送给大模型,由模型结合工具数据生成最终的自然语言回复。缺少该角色,就无法实现联网查询、数据库检索等 Agent 能力。
3. 项目环境配置
3.1 Maven 依赖
<dependency> <groupId>com.alibaba.cloud.ai</groupId> <artifactId>spring-ai-alibaba-starter-dashscope</artifactId> <version>1.0.0-M6.1</version></dependency>
3.2 application.yml 通用配置
spring: ai: dashscope: api-key: sk-你的灵积API密钥 chat: options: model: qwen-turbo temperature: 0.7
3.3 两套接入方案
Spring AI Alibaba 提供自动装配和手动配置两种方式,推荐优先使用自动装配。
方案一:Starter 自动装配(90% 场景首选)
只需引入 starter 并配置 yml,DashScopeAutoConfiguration 会自动创建:
- DashScopeApi(API 客户端)
- DashScopeChatModel(ChatModel 接口实现)
- 业务代码直接注入 ChatModel 或 ChatClient 即可。
无需任何配置类。
方案二:手动自定义配置类(需要定制网络参数时)
当需要自定义连接超时、HTTP 代理或私有化地址时,可以手动创建 Bean(此时自动装配会失效),并复用 DashScopeProperties 避免硬编码。
@Configurationpublic class DashScopeLLMConfig { @Bean public DashScopeApi dashScopeApi(DashScopeProperties properties) { return DashScopeApi.builder() .apiKey(properties.getApiKey()) .connectTimeout(Duration.ofSeconds(30)) .readTimeout(Duration.ofSeconds(60)) // .baseUrl("私有化地址") // .proxy(自定义代理) .build(); } @Bean public ChatModel chatModel(DashScopeApi api, DashScopeProperties properties) { return new DashScopeChatModel(api, properties.getChat().getOptions()); } // 注册全局 ChatClient,统一管理系统提示词 @Bean public ChatClient chatClient(ChatModel chatModel) { return ChatClient.builder(chatModel) .defaultSystem("你是Spring AI Alibaba技术专家,代码示例完整规范") .defaultTemperature(0.7) .build(); }}
4. 实战一:基础多轮对话(System + User + Assistant)
本案例演示如何手动组装三种角色消息,并对比 ChatModel 底层 API 和 ChatClient 高层封装两种调用方式。
@RestControllerpublic class PromptRoleController { private final ChatModel chatModel; private final ChatClient chatClient; public PromptRoleController(ChatModel chatModel, ChatClient chatClient) { this.chatModel = chatModel; this.chatClient = chatClient; } // 方式一:原生 ChatModel 手动构建多轮对话 @GetMapping("/chat/multi/sync") public String multiRoundSync() { SystemMessage systemMsg = new SystemMessage("你是Java AI开发博主,回答简短精炼"); UserMessage user1 = new UserMessage("什么是ChatModel与ChatClient区别?"); AssistantMessage assistant1 = new AssistantMessage( "ChatModel是底层标准接口,ChatClient是上层便捷封装。"); UserMessage user2 = new UserMessage("开发中该优先使用哪一个?"); Prompt prompt = new Prompt(List.of(systemMsg, user1, assistant1, user2)); return chatModel.call(prompt).getResult().getOutput().getText(); } // 方式二:ChatClient 流式调用(推荐) @GetMapping("/chat/client/stream") public Flux<String> clientStreamChat(@RequestParam String query) { return chatClient.prompt() .system("讲解代码附带完整示例") .user(query) .stream() .content(); }}
- ChatModel 需要手动维护消息列表顺序,适合底层精细控制。
- ChatClient 内部自动管理上下文并支持链式 API,更贴近业务开发。
5. 实战二:四大角色全闭环 Function Calling
下面代码完整展示了 System、User、Assistant(带 ToolCall)和 ToolResponse 四个角色的协作过程,实现“查询天气”的 Agent 功能。
@GetMapping("/chat/tool/allRole")public String toolCallAllRole() throws Exception { // 1. 系统消息:约束必须使用工具 SystemMessage systemMsg = new SystemMessage(""" 你拥有天气查询工具getCityWeather,需要查询天气时必须调用该工具, 禁止编造数据。调用时传入参数city(城市名称)。 """); // 2. 用户消息 UserMessage userMsg = new UserMessage("查询北京今日气温"); Prompt prompt = new Prompt(List.of(systemMsg, userMsg)); ChatResponse response = chatModel.call(prompt); // 3. 获取助手消息(可能包含工具调用) AssistantMessage assistantMsg = response.getResult().getOutput(); if (!assistantMsg.getToolCalls().isEmpty()) { ToolCall toolCall = assistantMsg.getToolCalls().get(0); // 解析参数 JsonNode args = new ObjectMapper().readTree(toolCall.arguments()); String city = args.get("city").asText(); // 执行本地工具(模拟) String weatherData = getCityWeather(city); // 4. 构造 ToolResponseMessage ToolResponseMessage toolMsg = new ToolResponseMessage( List.of(new ToolResponse(toolCall.id(), weatherData)) ); // 5. 拼接完整消息二次请求 List<Message> fullMessages = List.of(systemMsg, userMsg, assistantMsg, toolMsg); ChatResponse finalResp = chatModel.call(new Prompt(fullMessages)); return finalResp.getResult().getOutput().getText(); } return assistantMsg.getText();}private String getCityWeather(String city) { return String.format("%s今日:晴,气温18~28℃,微风", city);}
关键步骤解析:
- 模型返回的 AssistantMessage 中 getToolCalls() 非空,说明需要调用外部工具;
- 程序根据 ToolCall 中的函数名和参数执行本地逻辑,并将结果封装为 ToolResponseMessage;
- 第二次请求时消息列表必须为 [System, User, Assistant(含ToolCall), ToolResponse] 的顺序;
- 模型结合工具数据生成最终的自然语言回答。
6. 总结与最佳实践
Spring AI 的四大角色设计不仅使得提示词构建更加模块化和类型安全,也为后续的 Agent 编排、记忆管理打下了坚实的基础。理解并善用这些角色,你将能够构建出更加稳定、智能的 AI 应用。





