乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • Spring AI 学习路径
  • 第1章 Spring AI 概述与核心理念

    • 章节导读
    • Spring AI 概述与可移植 API
    • 核心模块与依赖关系
  • 第2章 快速入门与第一个AI应用

    • 章节导读
    • 环境准备与配置
    • 第一个 AI 对话应用
  • 第3章 聊天模型与ChatClient

    • 章节导读
    • ChatClient 详解
    • ChatModel 底层抽象
    • 多轮对话与 ChatMemory
  • 第4章 提示词管理与模板

    • 章节导读
    • Prompt 与 Message 体系
    • 提示词模板与动态构建
  • 第5章 输出解析与结构化响应

    • 章节导读
    • 输出解析器与 BeanOutputConverter
  • 第6章 嵌入模型与向量存储

    • 章节导读
    • EmbeddingModel 与文本向量化
    • ETL 数据注入流水线
    • 向量存储抽象与配置
  • 第7章 检索增强生成(RAG)

    • 章节导读
    • RAG 核心机制与流程
    • QuestionAnswerAdvisor 详解
    • RAG 实战案例
  • 第8章 函数调用(Function Calling)

    • 章节导读
    • Tool 注解与函数声明
    • 函数调用实战
  • 第9章 多模态

    • 章节导读
    • 图像输入与视觉模型
    • 图像生成
  • 第10章 Advisor拦截器链

    • 章节导读
    • Advisor 链与内置拦截器
  • 第11章 MCP 协议与跨语言工具集成

    • 章节导读
    • MCP 协议深入
  • 第12章 可观测性测试与最佳实践

    • 章节导读
    • 可观测性与指标监控
    • 测试策略与 Mock 实践
    • 最佳实践与面试考点汇总

白歌画了一个类图给小崔看:"SystemMessage 定规则,UserMessage 带问题,AssistantMessage 存历史,ToolResponseMessage 传结果。四种消息各司其职,Prompt 就是一个装消息的容器。"

Prompt 与 Message 体系

定义与作用

在 Spring AI 中,每次与 AI 模型的交互都通过 Prompt 对象表示。Prompt 是一个容器,装载:

  • 消息列表(List<Message>):对话的完整上下文
  • ChatOptions(可选):模型调用参数(temperature、model 等)

Message 是 Prompt 的基本构建单元。Spring AI 定义了四种消息类型,对应 LLM 的四种标准角色。

Message 四种类型详解

类型角色接口/类典型用途在对话中的位置
SystemMessagesystemSystemMessage设定 AI 全局行为和角色对话第一条,贯穿全程
UserMessageuserUserMessage用户输入,可附加图片/音频每轮对话的用户侧
AssistantMessageassistantAssistantMessageAI 的历史回复,维持上下文每轮对话的 AI 侧
ToolResponseMessagetoolToolResponseMessage工具函数执行结果Tool Calling 循环中

类继承体系

图释:四种 Message 共享 AbstractMessage 的 content + messageType 基础结构,各自扩展特有构造器。UserMessage 额外支持 Media 多模态参数。

Prompt 的三种构造方式

// 方式一:简单字符串(最简,适合单轮问答)
Prompt prompt1 = new Prompt("今天天气怎么样?");

// 方式二:消息列表(多角色,适合有角色设定场景)
Prompt prompt2 = new Prompt(List.of(
    new SystemMessage("你是学生的课程顾问。"),
    new UserMessage("离散数学的前置课程是什么?")
));

// 方式三:消息列表 + ChatOptions(精确控制参数)
Prompt prompt3 = new Prompt(
    List.of(
        new SystemMessage("你是飞翔科技大学的课程顾问。"),
        new UserMessage("推荐一门选修课")
    ),
    ChatOptions.builder()
        .temperature(0.3)   // 低温度 → 更准确的课程信息
        .model("gpt-4o")
        .build()
);

完整示例一:构建带角色设定的课程问答

场景说明

孔蓝要求课程咨询的 AI 回复风格专业且结构化。

关键代码

@RestController
public class CourseQAController {

    private final ChatClient chatClient;

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

    @GetMapping("/course-qa")
    public String ask(@RequestParam String question) {
        return chatClient.prompt()
                .system("""
                    你是飞翔科技大学的课程顾问。回答时遵循以下规则:
                    1. 先给出直接答案
                    2. 然后列出相关的课程编号和学分
                    3. 最后补充选课建议
                    即使不确定,也要给出参考信息而非泛泛而谈。
                    """)
                .user(question)
                .options(ChatOptions.builder()
                        .temperature(0.3)     // 课程信息需要准确
                        .build())
                .call()
                .content();
    }
}

对比效果

普通版本(无 SystemMessage):
Q: 离散数学的前置课程
A: 离散数学的常见前置课程包括高等数学、线性代数等基础数学课。
    具体以学校培养方案为准。

专业版本(有 SystemMessage):
Q: 离散数学的前置课程  
A: 根据培养方案,离散数学(CS201)需先修:
   1. MATH101 高等数学A — 5学分(侧重逻辑推理基础)
   2. MATH102 线性代数 — 4学分(侧重矩阵与组合基础)
   选课建议:建议大二上学期修读,与数据结构 CS301 搭配学习效果最佳。

完整示例二:UserMessage 的多模态能力

场景说明

孙鹤提出"学生拍照上传课程表图片,AI 自动识别课程安排"。

关键代码

@PostMapping("/read-schedule")
public String readSchedule(@RequestParam("image") MultipartFile image) 
        throws IOException {
    
    Media media = new Media(
        MimeTypeUtils.IMAGE_PNG,
        new InputStreamResource(image.getInputStream())
    );

    return chatClient.prompt()
            .system("你是 OCR 专家。从图片中提取所有课程信息,用表格格式输出。")
            .user(userSpec -> userSpec
                    .text("请提取这张课程表中的课程名称、时间和教室")
                    .media(media))
            .call()
            .content();
}

易错场景与面试考点

易错场景一:SystemMessage 和 UserMessage 混用

// ❌ 错误:把角色设定放在 UserMessage 中
Prompt prompt = new Prompt(List.of(
    new UserMessage("你是一个课程顾问。" +
                    "离散数学的前置课程是什么?")
));
// AI 可能把前半句当成普通聊天内容

问题分析

LLM 对 SystemMessage 和 UserMessage 的处理优先级不同。SystemMessage 被视为不可反驳的指令,UserMessage 视为可讨论的内容。

// ✅ 正确:角色设定放在 SystemMessage
Prompt prompt = new Prompt(List.of(
    new SystemMessage("你是飞翔科技大学的课程顾问。"),
    new UserMessage("离散数学的前置课程是什么?")
));

易错场景二:多模态请求忘记设置 MIME Type

// ❌ 错误:未指定 MIME type
Media media = new Media(resource);  // 编译错误或默认值不明确

问题分析

Media 的构造器需要明确的 MimeType,AI 模型据此判断如何处理附件。

// ✅ 正确:明确指定 MIME type
Media media = new Media(MimeTypeUtils.IMAGE_JPEG, resource);

面试高频题

Q1:SystemMessage 和 UserMessage 的 Token 分配优先级是什么?

大部分 LLM 给 SystemMessage 更高的"指令优先级"——AI 更倾向于遵守 System 的约束,即使与 User 消息冲突。建议在 SystemMessage 中放恒定的角色约束("你是课程顾问"),在 UserMessage 中放可变的具体问题。

Q2:Prompt 中四种消息的典型排列顺序是怎样的?

通常顺序:SystemMessage(角色)→ 历史 User/Assistant 交替 → 最新 UserMessage → 可能有 ToolResponseMessage。SystemMessage 必须放在最前面以确立全局约束。

Q3:什么时候需要手动构造 Prompt 而不是用 ChatClient 的 Fluent API?

当需要精确控制消息列表中每条消息的类型、顺序和参数时(如手动注入 ToolResponseMessage 做 Tool Calling 循环、动态裁剪历史消息),直接构造 Prompt 对象更灵活。

本章小结

  • Prompt 是消息列表 + ChatOptions 的容器
  • Message 有四种类型:System(规则)、User(问题)、Assistant(回复历史)、Tool(工具结果)
  • SystemMessage 在最前面设定角色,优先级高于 UserMessage
  • Prompt 有三种构造方式:简单字符串、消息列表、消息列表 + 选项
  • UserMessage 支持多模态(Media),可附加图片/音频
上一页
章节导读
下一页
提示词模板与动态构建