Spring AI 提示词(Prompt)

在 Spring AI 框架中,提示词(Prompt)是连接应用程序与 AI 模型的核心媒介,它作为引导 AI 模型生成特定输出的指令,其设计质量直接影响模型响应的准确性、相关性和有效性。

提示词本质上是一段结构化或非结构化的文本(可能包含动态占位符),用于向 AI 模型传递任务目标、上下文信息或约束条件。在 Spring AI 中,它不仅是简单的输入字符串,更是应用程序与 AI 模型交互的 “桥梁”—— 通过精心设计的提示词,开发者可以引导模型完成问答、文本生成、逻辑推理等多样化任务

例如,在对话场景中,提示词可能包含用户的历史提问、系统的回复规则(如“保持回答简洁”)。在数据增强(RAG)场景中,提示词可能嵌入待分析的文档片段,以让模型基于特定上下文生成结论。

下图是一个 Spring AI 发起大模型请求的输出日志,其中包含了 SystemMessage(系统提示词)和 UserMssage(用户提示词)。

Spring AI 提示词(Prompt)

在 Spring AI 与 AI 模型的基础交互层中,提示词的处理逻辑类似于 Spring MVC 中的 “View” 管理机制,先创建带有动态内容占位符的扩展文本,再根据用户请求或应用代码替换这些占位符。

随着 Spring AI 的不断发展,其将引入更高级别的 AI 模型交互抽象。本节介绍的基础类在角色和功能上可与 JDBC 类似 —— 例如,ChatModel 类类似于 JDK 中的核心 JDBC 库,而构建于 ChatModel 之上的 ChatClient 类则堪比 JdbcClient,它能通过 Advisor 实现更复杂的功能构造,比如考虑与模型的历史交互记录、用附加上下文文档增强提示词,以及引入代理行为等。

提示词的结构在 AI 领域处于持续演进中:从最初的简单字符串,逐步发展出包含 “USER:” 等模型可识别的特定输入占位符;OpenAI 则进一步推动了结构化设计,在 AI 模型处理前将多条消息按不同角色进行分类。

  

提示词相关 API

Prompt 类

通常使用 ChatModel 的 call() 方法,该方法接收 Prompt 实例并返回 ChatResponse。call() 方法定义如下:

ChatResponse call(Prompt prompt);

Prompt 类作为有序 Message 对象和请求 ChatOptions 的容器。每个 Message 在提示词中扮演独特角色(如用户提示词、系统提示词等),其内容和意图各异 —— 从用户询问到 AI 生成响应,再到相关背景信息。这种结构支持与 AI 模型的复杂交互,因为提示词由多条消息(Message)构建而成,每条消息(Message)在对话中承担特定角色。如下图:

image.png

以下是 Prompt 类的部分源码:

public class Prompt implements ModelRequest<List<Message>> {
    // 提示词列表
    private final List<Message> messages;
    // AI 模型的对话请求提供配置选项,充当应用程序与 AI 模型之间的 “参数桥梁”
    @Nullable
    private ChatOptions chatOptions;

    // 构造方法
    public Prompt(String contents) {
        this((Message)(new UserMessage(contents)));
    }

    public Prompt(Message message) {
        this(Collections.singletonList(message));
    }

    public Prompt(List<Message> messages) {
        this((List)messages, (ChatOptions)null);
    }

    public Prompt(Message... messages) {
        this((List)Arrays.asList(messages), (ChatOptions)null);
    }

    public Prompt(String contents, @Nullable ChatOptions chatOptions) {
        this((Message)(new UserMessage(contents)), chatOptions);
    }

    public Prompt(Message message, @Nullable ChatOptions chatOptions) {
        this(Collections.singletonList(message), chatOptions);
    }

    public Prompt(List<Message> messages, @Nullable ChatOptions chatOptions) {
        Assert.notNull(messages, "messages cannot be null");
        Assert.noNullElements(messages, "messages cannot contain null elements");
        this.messages = messages;
        this.chatOptions = chatOptions;
    }
    
    //....
}

  

Message 接口

Message 接口封装了一个 Prompt 的文本内容、一组元数据属性,以及一个称为 MessageType 的分类枚举。Message 类继承关系如下图:

image.png

它继承了 Content 接口,而且拥有很多实现,每个实现对应了同步的消息类型:

  • AssistantMessage  AI回复消息

  • UserMessage  用户提示词

  • SystemMessage  系统提示词

  • ToolResponseMessage  工具/函数调用消息

后续将介绍上面这些具体的消息类,先看看这些接口定义:

Content 接口

Content 接口表示可被AI模型处理的内容载体,定义了内容文本及其元数据的标准访问接口。定义如下:

public interface Content {

    // 通常作为提示词的一部分传递给AI模型
    String getContent();

    // 获取与内容关联的元数据
    Map<String, Object> getMetadata();
}

Message 接口

Message 接口继承了 Content 接口,表示具有特定角色类型的消息(通过 MessageType 区分)。通常用于多轮对话场景,标识不同参与者的交互内容。定义如下:

public interface Message extends Content {
    /**
     * 获取消息的类型,对应不同参与者角色
     * @return 消息类型枚举值,常见类型包括:
     *         - SYSTEM: 系统指令,设置AI模型行为、角色定义等
     *         - USER: 用户输入的问题或指令
     *         - ASSISTANT: AI模型生成的回复
     */
    MessageType getMessageType();
}

MessageType 枚举

MessageType 是一个枚举类,定义了在与 AI 大模型交互过程中的消息类型,共四种类型。定义如下:

public enum MessageType {
    USER("user"), // 用户消息
    ASSISTANT("assistant"), // AI回复消息
    SYSTEM("system"), // 系统消息
    FUNCTION("function"); // 工具调用
    //....
}

MessageType 接口

如果消息是多模态消息类型,那么它还实现了 MediaContent 接口,用于提供 Media(媒体资源,如图片,音频等) 内容对象列表。接口定义如下:

/**
 * 扩展 Content 接口,用于表示包含多媒体资源的内容载体
 * 适用于需要在文本基础上关联图片、音频、视频等媒体资源的场景
 * 例如:图文混合的提示词、包含附件的对话消息等
 */
public interface MediaContent extends Content {

    /**
     * 获取关联的多媒体资源集合
     * @return 不可为空的 Media 对象集合,每个 Media 对象封装了具体资源的元数据和访问方式
     *         集合顺序通常表示资源在内容中的呈现顺序
     */
    Collection<Media> getMedia();
}

在 Spring AI 中,AssistantMessage UserMessage 类型均实现了 MediaContent 接口,如下图:

Spring AI 提示词(Prompt)

下面是 UserMessage 类的定义:

public class UserMessage extends AbstractMessage implements MediaContent {
    protected final List<Media> media;
    //...
}

注意,其中的 Media 类表示一个独立的多媒体资源,封装了资源的核心元数据和访问方式,支持存储图片、音频、视频等二进制资源,或指向外部资源的引用。定义如下:

public class Media {
    private static final String NAME_PREFIX = "media-";

    /**
     * 媒体资源的唯一标识符(可选)
     * 若为空则表示该资源未被持久化,或由系统在运行时自动生成
     */
    @Nullable
    private final String id;

    /**
     * 媒体资源的 MIME 类型
     * 例如:image/png、audio/mpeg、video/mp4 等
     * 用于指示资源的格式和处理方式
     */
    private final MimeType mimeType;

    /**
     * 媒体资源的数据内容
     */
    private final Object data;

    /**
     * 媒体资源名称
     */
    private final String name;
    //...
}

到这里,介绍了 Spring AI 提示词相关的接口和类。这些接口和类的关系,可以通过下面图进行表示:

Spring AI 提示词(Prompt)

注意,上图中这些消息的具体角色是由 MessageType 枚举进行有效映射,每个具体的消息内部都持有一个名为 messageType 的成员变量,该变量决定了消息的类型。

角色(Role)

每条消息都被分配了特定的角色,这些角色对消息进行分类,向 AI 模型阐明提示词每个片段的上下文和目的。这种结构化方法通过让提示词的每个部分在交互中扮演明确角色,增强了与 AI 沟通的精细度和有效性。见 MessageType 枚举类:

public enum MessageType {
    USER("user"), // 用户消息
    ASSISTANT("assistant"), // AI回复消息
    SYSTEM("system"), // 系统消息
    FUNCTION("function"); // 工具调用
    //....
}

主要角色包含以下几类:

  • System 角色:用于指导 AI 的行为模式与响应风格,在对话开始时,就向 AI 预先设定解释和回复输入的参数、规则,相当于给 AI 下达初始指令 。

  • User 角色:代表用户发出的各类输入,像提出的问题、下达的命令,或是对 AI 进行的陈述等。它是 AI 做出响应的基础,有着根本性的重要地位 。

  • Assistant 角色:是 AI 针对用户输入给出的回应,不只是简单的答案或响应,对保持对话的流畅推进起着关键作用。系统会通过追踪 AI 此前的响应(即其 “Assistant Role” 消息),保障交互连贯且贴合上下文。而且助手消息里还可能包含函数工具调用请求信息,这属于 AI 的特殊功能,在有需要时,可执行计算、获取数据等这类超出常规对话范畴的特定任务 。

  • Tool/Function 角色:专门针对工具调用类的助手消息进行响应,返回额外的补充信息 。

  

PromptTemplate 类

在 Spring AI 中,提示词模板化机制的核心组件是 PromptTemplate 类。该类被精心设计以解决结构化提示词创建过程中的复杂性,其核心目标是通过标准化的模板定义,让开发者能够更高效、更规范地生成符合 AI 模型输入要求的提示内容。

具体来说,PromptTemplate 类的作用体现在两个关键层面:

  • 简化构建流程:它允许开发者预先定义包含固定文本和动态变量的模板(例如,通过占位符 {variable} 标记需要动态替换的内容),无需每次手动拼接字符串,大幅减少了重复编码和格式错误的风险。

  • 适配 AI 模型需求:生成的结构化提示词会严格遵循目标 AI 模型(如大语言模型、生成式模型等)对输入格式的要求,确保提示信息能够被模型准确解析和处理,从而提升交互效率与响应质量。

PromptTemplate 类的定义如下:

public class PromptTemplate implements PromptTemplateActions, PromptTemplateMessageActions {
    // 其他方法将在后面讨论
}

该类使用 TemplateRenderer 接口渲染模板。默认情况下,Spring AI 采用基于 Terence Parr 开发的开源 StringTemplate 引擎的 StTemplateRenderer 实现。模板变量通过 {} 语法标识,但也可配置为其他分隔符语法。

TemplateRenderer 接口定义如下:

public interface TemplateRenderer extends BiFunction<String, Map<String, Object>, String> {

	@Override
	String apply(String template, Map<String, Object> variables);

}

在 Spring AI 中,TemplateRenderer 提供了两个默认实现,如下图:

Spring AI 提示词(Prompt)

Spring AI 通过 TemplateRenderer 接口处理模板字符串中的变量替换,默认实现使用 StringTemplate。若需自定义逻辑,可提供自己的 TemplateRenderer 实现。对于无需模板渲染的场景(如模板字符串已完整),可使用提供的 NoOpTemplateRenderer。

自定义 StringTemplate 渲染器

默认情况下,StringTemplate 渲染器使用 '{' 和 '}' 为分隔符。我们可以通过它的 startDelimiterToken()endDelimiterToken() 方法自定义分隔符。例如,采用 '<' 和 '>' 为分隔符:

PromptTemplate promptTemplate = PromptTemplate.builder()
    .renderer(StTemplateRenderer.builder().startDelimiterToken('<').endDelimiterToken('>').build())
    .template("""
            Tell me the names of 5 movies whose soundtrack was composed by <composer>.
            """)
    .build();

String prompt = promptTemplate.render(Map.of("composer", "John Williams"));

  

从上面 PromptTemplate 类的定义可知,PromptTemplate 类实现了 PromptTemplateActions、PromptTemplateStringActions 和 PromptTemplateMessageActions 接口,使得它支持不同的方式去创建提示词。

PromptTemplateStringActions 接口

专注于创建和渲染提示词字符串,代表最基础的提示生成形式。定义如下:

public interface PromptTemplateStringActions {

	String render();

	String render(Map<String, Object> model);

}

方法说明:

  • String render():将提示词模板渲染为最终字符串格式(无需外部输入),适用于不含占位符或动态内容的模板。

  • String render(Map<String, Object> model):增强渲染功能以包含动态内容,使用 Map<String, Object> 参数(Key 为提示模板中的占位符名称, Value 为待插入的动态内容)。


PromptTemplateMessageActions 接口

专为通过生成和操作 Message 对象来创建提示词而设计。定义如下:

public interface PromptTemplateMessageActions {

	Message createMessage();

    Message createMessage(List<Media> mediaList);

	Message createMessage(Map<String, Object> model);

}

方法说明:

  • Message createMessage():创建不带附加数据的 Message 对象,适用于静态或预定义的消息内容。

  • Message createMessage(List<Media> mediaList):创建包含静态文本和媒体内容的 Message 对象。

  • Message createMessage(Map<String, Object> model):扩展消息创建以整合动态内容,接收 Map<String, Object> 参数(每条记录代表消息模板中的占位符及其对应的动态值)。


PromptTemplateActions 接口

设计用于返回 Prompt 对象,该对象可传递给 ChatModel 生成响应。定义如下:

public interface PromptTemplateActions extends PromptTemplateStringActions {

	Prompt create();

	Prompt create(ChatOptions modelOptions);

	Prompt create(Map<String, Object> model);

	Prompt create(Map<String, Object> model, ChatOptions modelOptions);

}

方法说明:

  • Prompt create():生成不带外部数据输入的 Prompt 对象,适用于静态或预定义的提示。

  • Prompt create(ChatOptions modelOptions):生成不带外部数据输入但含聊天请求特定选项的 Prompt 对象。

  • Prompt create(Map<String, Object> model):扩展提示创建能力以包含动态内容,接收 Map<String, Object> 参数(每个 Map 条目代表提示模板中的占位符及其关联的动态值)。

  • Prompt create(Map<String, Object> model, ChatOptions modelOptions):扩展提示创建能力以包含动态内容和聊天请求特定选项,接收 Map<String, Object> 参数(每个 Map 条目代表提示模板中的占位符及其关联的动态值)及 ChatOptions 参数。

  

示例用法

PromptTemplate 占位符应用

下面通过一个简单的示例介绍如何使用占位符,如下:

package com.hxstrive.springai.springai_openai.prompt1.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
class MyController {

    @Autowired
    private ChatModel chatModel;


    // http://localhost:8080/ai?topic=海盗&adjective=幽默
    @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8")
    public String ai(@RequestParam("adjective") String adjective, @RequestParam("topic") String topic) {
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultSystem("你是AI助手小粒,所有回复均使用中文。")
                .defaultAdvisors(
                        new SimpleLoggerAdvisor() // 输出聊天日志
                )
                .build();

        // 创建提示词
        PromptTemplate promptTemplate = new PromptTemplate("给我讲一个关于 {topic} 的 {adjective} 笑话");

        // 设置替换占位符的数据
        Map<String,Object> modelMap = new HashMap<>();
        modelMap.put("adjective", adjective);
        modelMap.put("topic", topic);
        Prompt prompt = promptTemplate.create(modelMap);

        return chatClient.prompt(prompt).call().content();
    }

}

上面代码中,{topic} 和 {adjective} 表示名为 topic 和 adjective 的占位符。运行代码,输出日志如下:

image.png

image.png

  

SystemPromptTemplate 占位符应用

下面给出 SystemPromptTemplate 占位符的简单应用:

package com.hxstrive.springai.springai_openai.prompt2.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
class MyController {

    @Autowired
    private ChatModel chatModel;


    // http://localhost:8080/ai?name=小粒&voice=幽默
    @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8")
    public String ai(@RequestParam("name") String name, @RequestParam("voice") String voice) {
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(
                        new SimpleLoggerAdvisor() // 输出聊天日志
                )
                .build();

        // 用户提示词
        Message userMessage = new UserMessage("给我讲讲海盗黄金时代的三个著名海盗以及他们的事迹,针对每个海盗至少写一句话。");

        // 系统提示词
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate("""
                你是AI助手{name},是一个乐于助人的人工智能助手,帮助人们查找信息。
                你必须以你的名字并按照{voice}的风格回复用户的请求。所有回复均使用中文。
                """);
        Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice));
        Prompt prompt = new Prompt(List.of(systemMessage, userMessage));

        return chatClient.prompt(prompt).call().content();
    }

}

上面示例展示如何通过 SystemPromptTemplate 构建 Prompt 实例,使用 system 角色创建含占位值的 Message,再与 user 角色的 Message 组合成提示,最终传递给 ChatModel 获取生成式响应。运行应用,输出日志如下:

image.png

image.png

  

使用自定义模板渲染器

你还可通过实现 TemplateRenderer 接口并将其传入 PromptTemplate 构造函数来使用自定义模板渲染器,也可继续使用默认的 StTemplateRenderer 但采用自定义配置。

默认情况下,模板变量通过 {} 语法标识。若提示中包含 JSON,建议改用 < 和 > 等分隔符以避免与JSON语法冲突。例如:

package com.hxstrive.springai.springai_openai.prompt3.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.ai.template.st.StTemplateRenderer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@RestController
class MyController {

    @Autowired
    private ChatModel chatModel;


    // http://localhost:8080/ai
    @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8")
    public String ai() {
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(
                        new SimpleLoggerAdvisor() // 输出聊天日志
                )
                .build();

        PromptTemplate promptTemplate = PromptTemplate.builder()
                .renderer(StTemplateRenderer.builder().startDelimiterToken('<').endDelimiterToken('>').build())
                .template("告诉我5部配乐由<composer>创作的电影的名字。")
                .build();
        String prompt = promptTemplate.render(Map.of("composer", "John Williams"));

        return chatClient.prompt(prompt).call().content();
    }

}

运行应用,输出日志如下:

image.png

image.png

  

使用 Resource 替代原始字符串

Spring AI 支持 org.springframework.core.io.Resource 抽象,因此可将提示数据存入文件并直接用于 PromptTemplate。例如:

(1)在项目的 resources 目录下面创建 /prompts/system-message.txt 文件:

image.png

内容如下:

你是AI助手{name},是一个乐于助人的人工智能助手,帮助人们查找信息。你必须以你的名字并按照{voice}的风格回复用户的请求。所有回复均使用中文。

(2)编写代码,使用 @Value 导入提示词,并且作为 SystemPromptTemplate 的构造参数:

package com.hxstrive.springai.springai_openai.prompt4.controller;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.SystemPromptTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@RestController
class MyController {

    @Autowired
    private ChatModel chatModel;

    @Value("classpath:/prompts/system-message.txt")
    private Resource systemResource;

    // http://localhost:8080/ai?name=小粒&voice=幽默
    @GetMapping(value = "/ai",produces = "text/html; charset=UTF-8")
    public String ai(@RequestParam("name") String name, @RequestParam("voice") String voice) {
        ChatClient chatClient = ChatClient.builder(chatModel)
                .defaultAdvisors(
                        new SimpleLoggerAdvisor() // 输出聊天日志
                )
                .build();

        // 用户提示词
        Message userMessage = new UserMessage("给我讲讲海盗黄金时代的三个著名海盗以及他们的事迹,针对每个海盗至少写一句话。");

        // 系统提示词
        SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemResource);
        Message systemMessage = systemPromptTemplate.createMessage(Map.of("name", name, "voice", voice));
        Prompt prompt = new Prompt(List.of(systemMessage, userMessage));

        return chatClient.prompt(prompt).call().content();
    }

}

运行应用,输出日志如下:

image.png

image.png

关于 Spring AI 中提示词 Prompt 的用法,读者可以自行尝试。

  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号