跳到主要内容
版本:1.1.4

Message

Message 是 Spring AI 中所有对话消息的抽象基元,定义了 UserMessageSystemMessageAssistantMessageToolResponseMessage 四种消息类型,构成多轮对话的基础数据结构。


1. 概述

Message 是所有对话消息的基础抽象,定义了四种消息类型:UserMessage、SystemMessage、AssistantMessage、ToolResponseMessage。


2. MessageType 枚举

MessageType 定义了四种消息类型,每种对应一个具体的 Message 子类。

枚举值字符串值对应类说明
USER"user"UserMessage来自终端用户或开发者
ASSISTANT"assistant"AssistantMessageAI 模型生成的响应
SYSTEM"system"SystemMessage高层指令,定义 AI 角色和行为边界
TOOL"tool"ToolResponseMessage工具执行结果,回传给模型

3. UserMessage

用户消息,承载用户输入。支持纯文本、Resource 资源文件、Media 多媒体内容。

3.1 字符串构造

完整示例:UserMessageTextDemo.java
UserMessageTextDemo.java
@Component
public class UserMessageTextDemo implements CommandLineRunner {

private final ChatClient chatClient;

public UserMessageTextDemo(ChatClient.Builder builder) {
this.chatClient = builder.build();
}

@Override
public void run(String... args) {
UserMessage message = new UserMessage("什么是 Spring AI 的 Message 体系?");

String response = chatClient.prompt()
.messages(List.of(message))
.call()
.content();

System.out.println(response);
}
}

3.2 从 Resource 构造

完整示例:UserMessageResourceDemo.java
UserMessageResourceDemo.java
@Component
public class UserMessageResourceDemo implements CommandLineRunner {

private final ChatClient chatClient;

public UserMessageResourceDemo(ChatClient.Builder builder) {
this.chatClient = builder.build();
}

@Override
public void run(String... args) {
UserMessage message = new UserMessage(
new ClassPathResource("prompts/review-prompt.txt"));

String response = chatClient.prompt()
.messages(List.of(message))
.call()
.content();

System.out.println(response);
}
}

3.3 Builder 方式

完整示例:UserMessageBuilderDemo.java
UserMessageBuilderDemo.java
@Component
public class UserMessageBuilderDemo implements CommandLineRunner {

private final ChatClient chatClient;

public UserMessageBuilderDemo(ChatClient.Builder builder) {
this.chatClient = builder.build();
}

@Override
public void run(String... args) {
UserMessage message = UserMessage.builder()
.text("请分析这张图片的内容")
.media(Media.builder()
.mimeType(Media.Format.IMAGE_PNG)
.data(new ClassPathResource("images/screenshot.png"))
.build())
.build();

String response = chatClient.prompt()
.messages(List.of(message))
.call()
.content();

System.out.println(response);
}
}

4. SystemMessage

系统消息,定义 AI 的角色、行为边界和回答规范。在多轮对话中通常作为第一条消息。

4.1 字符串构造

完整示例:SystemMessageDemo.java
SystemMessageDemo.java
@Component
public class SystemMessageDemo implements CommandLineRunner {

private final ChatClient chatClient;

public SystemMessageDemo(ChatClient.Builder builder) {
this.chatClient = builder.build();
}

@Override
public void run(String... args) {
SystemMessage system = new SystemMessage("""
你是一个 Spring Boot 资深架构师。
回答要求:
1. 专业、准确,引用官方文档依据
2. 代码示例必须可运行
3. 不超过 300 字
""");

String response = chatClient.prompt()
.messages(List.of(
system,
new UserMessage("Spring Boot 3.x 自动配置机制有什么变化?")
))
.call()
.content();

System.out.println(response);
}
}

4.2 Builder 方式

完整示例:SystemMessageBuilderDemo.java
SystemMessageBuilderDemo.java
@Component
public class SystemMessageBuilderDemo implements CommandLineRunner {

private final ChatClient chatClient;

public SystemMessageBuilderDemo(ChatClient.Builder builder) {
this.chatClient = builder.build();
}

@Override
public void run(String... args) {
SystemMessage system = SystemMessage.builder()
.text("你是一个代码审查专家,专注于 Java 后端代码的安全性审查")
.metadata(Map.of("priority", "high", "domain", "security"))
.build();

String response = chatClient.prompt()
.messages(List.of(
system,
new UserMessage("审查这段 SQL 查询是否安全")
))
.call()
.content();

System.out.println(response);
}
}

5. AssistantMessage

助手消息,封装 AI 模型的响应。与普通文本消息的区别在于——它可以携带 ToolCall,表示模型请求调用的工具。

5.1 纯文本响应

完整示例:AssistantMessageTextDemo.java
AssistantMessageTextDemo.java
@Component
public class AssistantMessageTextDemo implements CommandLineRunner {

private final ChatModel chatModel;

public AssistantMessageTextDemo(ChatModel chatModel) {
this.chatModel = chatModel;
}

@Override
public void run(String... args) {
Prompt prompt = new Prompt(new UserMessage("用一句话介绍 Java"));
ChatResponse response = chatModel.call(prompt);

AssistantMessage assistantMsg = response.getResult().getOutput();
System.out.println("消息类型: " + assistantMsg.getMessageType());
System.out.println("消息内容: " + assistantMsg.getText());
System.out.println("是否包含工具调用: " + assistantMsg.hasToolCalls());
}
}

5.2 工具调用响应

当模型返回工具调用请求时,AssistantMessagegetToolCalls() 会包含对应的 ToolCall 列表。

完整示例:AssistantMessageToolCallDemo.java
AssistantMessageToolCallDemo.java
@Component
public class AssistantMessageToolCallDemo implements CommandLineRunner {

private final ChatClient chatClient;

public AssistantMessageToolCallDemo(ChatClient.Builder builder) {
this.chatClient = builder.build();
}

@Override
public void run(String... args) {
ChatResponse response = chatClient.prompt()
.user("今天上海的天气怎么样?")
.call()
.chatResponse();

AssistantMessage assistantMsg = response.getResult().getOutput();

if (assistantMsg.hasToolCalls()) {
for (AssistantMessage.ToolCall toolCall : assistantMsg.getToolCalls()) {
System.out.println("工具 ID: " + toolCall.id());
System.out.println("工具名称: " + toolCall.name());
System.out.println("工具参数: " + toolCall.arguments());
}
}
}
}

6. ToolResponseMessage

工具响应消息,携带 ToolResponse 列表。DefaultToolCallingManager 执行完工具后,将结果封装为此类型,追加到对话历史中发送给模型。

6.1 手动构造

完整示例:ToolResponseMessageDemo.java
ToolResponseMessageDemo.java
@Component
public class ToolResponseMessageDemo implements CommandLineRunner {

private final ChatModel chatModel;

public ToolResponseMessageDemo(ChatModel chatModel) {
this.chatModel = chatModel;
}

@Override
public void run(String... args) {
ToolResponseMessage.ToolResponse toolResp = new ToolResponseMessage.ToolResponse(
"call_001",
"getWeather",
"{\"city\": \"上海\", \"temperature\": \"22°C\", \"condition\": \"晴\"}"
);

ToolResponseMessage toolMsg = new ToolResponseMessage(List.of(toolResp));

List<Message> conversation = List.of(
new UserMessage("今天上海的天气怎么样?"),
toolMsg
);

Prompt prompt = new Prompt(conversation);
ChatResponse response = chatModel.call(prompt);

System.out.println(response.getResult().getOutput().getText());
}
}

6.2 ToolCall 与 ToolResponse 的关联

ToolResponse.idToolCall.id 一一对应,模型通过 id 匹配哪个工具的调用结果已经返回。


7. 消息列表构建模式

7.1 ChatClient 隐式构建

大多数场景无需手动构造 Message,ChatClient 的 prompt().user().system() 会自动组装消息列表。

完整示例:ImplicitMessagesDemo.java
ImplicitMessagesDemo.java
@Component
public class ImplicitMessagesDemo implements CommandLineRunner {

private final ChatClient chatClient;

public ImplicitMessagesDemo(ChatClient.Builder builder) {
this.chatClient = builder.build();
}

@Override
public void run(String... args) {
String response = chatClient.prompt()
.system("你是一个精通 Java 的编程助手")
.user("什么是面向接口编程?")
.call()
.content();

System.out.println(response);
}
}

7.2 显式构造消息列表

当需要精确控制消息顺序或类型时,直接传入 List<Message>

完整示例:ExplicitMessagesDemo.java
ExplicitMessagesDemo.java
@Component
public class ExplicitMessagesDemo implements CommandLineRunner {

private final ChatClient chatClient;

public ExplicitMessagesDemo(ChatClient.Builder builder) {
this.chatClient = builder.build();
}

@Override
public void run(String... args) {
List<Message> conversation = List.of(
new SystemMessage("你是一个代码审查专家,只审查安全性问题"),
new UserMessage("请分析以下代码"),
new AssistantMessage("""
代码中出现了一些问题:
1. SQL 拼接存在注入风险
String query = "SELECT * FROM users WHERE name = '" + userName + "'";
"""),
new UserMessage("请给出修复方案")
);

String response = chatClient.prompt()
.messages(conversation)
.call()
.content();

System.out.println(response);
}
}

8. 完整综合示例

以下示例展示多轮对话中四种消息类型的协同使用。

完整示例:MessageCompleteExample.java
MessageCompleteExample.java
@Component
public class MessageCompleteExample implements CommandLineRunner {

private final ChatClient chatClient;

public MessageCompleteExample(ChatClient.Builder builder) {
this.chatClient = builder
.defaultOptions(options -> options.temperature(0.7))
.build();
}

@Override
public void run(String... args) {
record ReviewResult(String file, String issue, String severity) {}

SystemMessage system = new SystemMessage("""
你是一个代码审查专家。分析用户提供的代码,
输出发现的每个问题。格式:
{"file": "文件名", "issue": "问题描述", "severity": "HIGH/MEDIUM/LOW"}
""");

UserMessage user = UserMessage.builder()
.text("请审查以下代码片段")
.metadata(Map.of("language", "java", "framework", "spring"))
.build();

AssistantMessage assistant = new AssistantMessage("""
以下是待审查的代码:
@RestController
public class UserController {
@GetMapping("/user/{id}")
public String getUser(@PathVariable String id) {
return jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = " + id,
String.class
);
}
}
""");

UserMessage followUp = new UserMessage("请用 JSON 格式输出审查结果");

List<Message> conversation = List.of(system, user, assistant, followUp);

ReviewResult result = chatClient.prompt()
.messages(conversation)
.call()
.entity(ReviewResult.class);

System.out.println("文件: " + result.file());
System.out.println("问题: " + result.issue());
System.out.println("严重程度: " + result.severity());
}
}