Prompt
思维导图

为什么需要有这个?
这是用户发给大模型的完整对话输入,设计一个好的prompt,能够更好的让大模型懂用户的意图,因此设计了prompt让大模型更好的理解用户的意图。
Prompt组成
- 角色(Role)
给模型设定身份和视角,如"你是一名医疗AI领域专家"。 - 指令(Instruction)
明确告诉模型要做什么任务,这是最核心部分。 - 上下文(Context)
提供任务背景、受众、应用场景等信息,帮助模型理解语境。 - 输入(Input)
模型需要处理的具体数据或内容。 - 输出(Output Indicator)
明确输出的格式、结构、风格,如 Markdown、JSON、列表等,但是模型输出不一定按照给出的格式进行百分百的输出 - 约束(Constraints)
对结果进行限制,如字数、语气、必须包含的内容、不允许的内容等。
| 要素 | 语义作用 | Spring AI 对应 |
|---|---|---|
| Role | 角色定位 | SystemMessage |
| Instruction | 任务定义 | PromptTemplate 主体 |
| Context | 场景说明 | SystemMessage/模板变量 |
| Input | 输入数据 | UserMessage/{input} |
| Output Indicator | 输出格式 | 模板中"输出要求" |
| Constraints | 行为边界 | 模板中"约束说明" |
Prompt = 角色 + 指令 + 上下文 + 输入 + 输出指示 + 约束
在工程中应当把它们"接口化、模板化、结构化",而不是随意拼接一句话,这个大模型能够更加准确的理解用户的意图。
Spring AI相关的接口
| 组件 | 包路径(示意) | 作用 |
|---|---|---|
Prompt |
org.springframework.ai.chat.prompt.Prompt |
Prompt 的核心接口/类,封装所有消息 |
PromptTemplate |
org.springframework.ai.chat.prompt.PromptTemplate |
模板化 Prompt,支持变量替换 |
Message |
org.springframework.ai.chat.messages.Message |
所有消息的父接口 |
SystemMessage |
org.springframework.ai.chat.messages.SystemMessage |
角色 + 上下文 |
UserMessage |
org.springframework.ai.chat.messages.UserMessage |
用户输入 |
AssistantMessage |
org.springframework.ai.chat.messages.AssistantMessage |
few-shot 示例 |
ChatClient |
org.springframework.ai.chat.client.ChatClient |
调用模型的客户端 |
ChatResponse |
org.springframework.ai.chat.ChatResponse |
模型返回结果 |
prompt 接口核心组成
java
public class Prompt implements ModelRequest<List<Message>>{
private final List<Message> messages;
// 封装了大模型的可选参数,后续说明
private final ChatOptions options;
}
//ModelRequest = 发给大模型的一次"完整请求"抽象
public interface ModelRequest<T> {
// 真正要交给模型的输入内容"
T getInstructions();
//这次请求调用模型时的参数配置
ModelOptions getOptions();
}
| 接口方法 | Prompt 内部字段 |
|---|---|
| getInstructions() | messages |
| getOptions() | options |
Message
每一条 Message 都包含:
- 文本内容(Content): 人类能读懂、模型直接处理的文本本体
- 元数据(Metadata):大模型的附加消息,存放模型的行管的附加消息,便于后续的处理。后续接口模块详细说明
这些不是写给模型看的,而是给服务端程序用来分辨、分类、管理消息流的辅助信息。
- 消息类型(MessageType / Role)
Message / Content / MediaContent 接口层级
java
public interface Content {
//文本的内容
String getContent();
//元数据
Map<String, Object> getMetadata();
}
public interface Message extends Content {
//消息角色,是下述的枚举类型
MessageType getMessageType();
}
public enum MessageType {
USER("user"),
ASSISTANT("assistant"),
SYSTEM("system"),
TOOL("tool");
}
//带附件的消息接口,普通的Content 只有文本+元数据 而 MediaContent 在此基础上还能带一组 Media(多媒体附件)
public interface MediaContent extends Content {
Collection<Media> getMedia();
}
Metadata 会放什么内容?举几个常见且实际会用到的例子:
| 元数据 Key | 意义 | 用途 |
|---|---|---|
**userId** |
用户身份 | 系统识别用户、区分对话 |
**sessionId** |
会话 ID | 统计、上下文区分 |
**messageId** |
当前消息编号 | 唯一标识一条消息 |
**timestamp** |
时间戳 | 排序、日志分析 |
**priority** |
优先级 | 决策调度(比如高优先级消息) |
java
Message (interface)
├── SystemMessage → Role(系统角色) + Context
├── UserMessage → Input + Instruction
├── AssistantMessage → 示例(Few-shot)
└── ToolMessage → 工具调用结果(高级用法)
**SystemMessage:**系统限制信息,权重最大,AI会有优先根据这个进行内容进行回复
**UserMessage:**用户发送的消息
**AssistantMessage:**AI回复的消息
ToolMessage: 工具返回的消息
ChatOptions
ChatOptions封装了大模型的可选参数
- 模型选择(model)
- 温度(temperature,控制随机性)
- topP/topK(采样方式)
- 最大输出长度(maxTokens)
- 惩罚项(presencePenalty/FrequencyPenalty):控制模型生成时的重复问题,数值越大,模型越倾向于往"新话题"拓展。
Prompt = 内容 + 参数
java
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.messages.*;
import org.springframework.ai.chat.options.ChatOptions;
import java.util.List;
import java.util.Map;
// 1️⃣ 构建消息内容(Prompt 的"内容部分")
List<Message> messages = List.of(
// SYSTEM:最高优先级规则
new SystemMessage(
"你是一个订单查询助手,只能根据工具返回的数据回答问题。",
//系统元数据
Map.of("sessionId", "session-001", "policy", "NO_HALLUCINATION")
),
// USER:用户输入
new UserMessage(
"帮我查一下订单 10002 的状态",
// 用户身份元数据
Map.of("userId", "u-888", "channel", "web")
),
// TOOL:工具真实返回
new ToolMessage(
"{ \"orderId\": \"10002\", \"status\": \"已签收\" }",
//工具元数据
Map.of("toolName", "OrderQueryService", "latencyMs", 42)
)
);
// 2️⃣ 构建 ChatOptions(Prompt 的"参数部分")
ChatOptions options = ChatOptions.builder()
.withModel("gpt-4.1-mini") // 模型选择
.withTemperature(0.2) // 随机性低,偏确定性
.withTopP(0.9) // nucleus sampling
.withMaxTokens(100) // 最大输出长度
.withPresencePenalty(0.6) // 鼓励引入新内容
.withFrequencyPenalty(0.2) // 减少重复
.build();
// 3️⃣ Prompt = 内容 + 参数
Prompt prompt = new Prompt(messages, options);
** 内容部分(Messages)**
- SystemMessage → 定规则
- UserMessage → 提问题
- ToolMessage → 给事实
参数部分(ChatOptions)
| 参数 | 作用 |
|---|---|
| model | 用哪个大模型 |
| temperature | 回答随机性 |
| topP | 采样策略 |
| maxTokens | 最大输出长度 |
| presencePenalty | 鼓励"新话题" |
| frequencyPenalty | 降低重复 |
说白了这个prompt,简单点说就是不同的角色+元数据(不同角色的附加信息)。

PromptTemplate
上述的接口,足以创建提示词,为啥还需要这个PromptTemplate,从这个名字就可以看出来,这个作用,提示词模版。官方解释:使用该类<font style="color:rgb(25, 30, 30);">PromptTemplate</font>来处理用户和系统文本,并根据给定的实现,在运行时将变量替换为提供的值<font style="color:rgb(25, 30, 30);">TemplateRenderer</font>这还是比较拗口,难以理解,我们换种说法,PromptTemplate 是"用来生成 Prompt 的模板工具"。Prompt每次创建都需要说明,系统身份,还需要表明背景,上下文信息,以及指令的需求,而PromptTemplate 解决的问题是:不想在代码里到处拼字符串,不想每次都 new Prompt 手写内容。想用"模板 + 变量"的方式批量生产 Prompt。直接举个例子进行说明这个。
不使用模版创建Prompt提示词
java
String systemText = "你是一名耐心的中文少儿科普老师。";
SystemMessage systemMessage = new SystemMessage(systemText);
//用户的中获取
String topic = "火山爆发";
int age = 10;
String userText = "请用适合 " + age + " 岁孩子理解的方式,讲解一下 "
+ topic + ",并举一个生活中的例子。";
UserMessage userMessage = new UserMessage(userText);
Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
使用模版创建Prompt提示词
java
// System 模板
String systemText = "你是一名耐心的中文少儿科普老师。";
SystemMessage systemMessage = new SystemMessage(systemText);
// User 模板
String userTemplate = """
请用适合 {age} 岁孩子理解的方式,
讲解一下 {topic},并举一个生活中的例子。
""";
PromptTemplate userPromptTemplate = new PromptTemplate(userTemplate);
// 用户输入
Map<String, Object> vars = Map.of(
"topic", "火山爆发",
"age", 10
);
// 用模板生成 UserMessage
Message userMessage = userPromptTemplate.createMessage(vars);
// 构建 Prompt
Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
可以看出来,使用模版可以进行复用,减少了相关的拼接过程。
可以用一句话概括:
PromptTemplate = 提示词模板引擎 + 变量渲染器 + Message / Prompt 生产器
它做三件事:
| 能力 | 对应方法 |
|---|---|
| 存模板 | template字符串 / Resource |
| 填变量 | render() / render(Map) |
| 造对象 | createMessage()/ create() |
类层级结构
java
PromptTemplate (核心模板引擎)
├── SystemPromptTemplate → 产 SystemMessage
├── AssistantPromptTemplate → 产 AssistantMessage
└── FunctionPromptTemplate → 产 FunctionMessage(工具/函数)
也就是说:PromptTemplate 负责"怎么把模板变成文字",子类负责"这段文字属于哪个角色"
PromptTemplate核心组成
java
private String template; // 模板文本,例如 "告诉我 {city} 的天气"
private final Map<String, Object> variables;// 模板变量,如 {city -> 北京}
private final TemplateRenderer renderer; // 渲染器(负责把 {city} 替换成 北京)
| 方法 | 作用 |
|---|---|
render() |
把模板 + 变量 → 生成最终字符串 |
createMessage() |
用 render 结果 → 生成 UserMessage |
create() |
用 render 结果 → 生成 Prompt |
create(vars, options) |
生成带 ChatOptions 的 Prompt |
java
String text = "请给我推荐 {city} 的 3 个旅游景点";
PromptTemplate pt = new PromptTemplate(text);
Map<String, Object> vars = Map.of("city", "杭州");
// 👉 生成 UserMessage
Message userMsg = pt.createMessage(vars);
// 👉 生成 Prompt
Prompt prompt = pt.create(vars);
//生成的效果是这样的
UserMessage: "请给我推荐 杭州 的 3 个旅游景点"
SystemPromptTemplate
java
public class SystemPromptTemplate extends PromptTemplate {
public Message createMessage() {
return new SystemMessage(this.render());
}
}
和 PromptTemplate 唯一的区别:它不是产 UserMessage,而是产 SystemMessage
String systemText = "你是一个旅游专家,只能用中文回答,不要超过 100 字";
SystemPromptTemplate sysPt = new SystemPromptTemplate(systemText);
Message systemMsg = sysPt.createMessage();
得到:
plain
SystemMessage: "你是一个旅游专家,只能用中文回答,不要超过 100 字"
AssistantPromptTemplate
java
public class AssistantPromptTemplate extends PromptTemplate {
public Message createMessage() {
return new AssistantMessage(this.render());
}
}
java
String assistantText = "当然可以,我来为你介绍一下杭州。";
AssistantPromptTemplate ap = new AssistantPromptTemplate(assistantText);
Message assistantMsg = ap.createMessage();
//得到结果
AssistantMessage: "当然可以,我来为你介绍一下杭州。"
FunctionPromptTemplate(函数工具角色)
java
public class FunctionPromptTemplate extends PromptTemplate {
private String name;
}
这个用于 Tool / Function Calling 场景,给模型一个"函数说明模板"
java
SystemPromptTemplate sysPt =
new SystemPromptTemplate("你是一个旅游专家,只用中文回答");
PromptTemplate userPt =
new PromptTemplate("请给我推荐 {city} 的 2 个景点");
AssistantPromptTemplate asPt =
new AssistantPromptTemplate("好的,我来帮你推荐。");
//创建message
Message systemMsg = sysPt.createMessage();
Message userMsg = userPt.createMessage(Map.of("city", "成都"));
Message assistantMsg = asPt.createMessage();
Prompt prompt = new Prompt(List.of(systemMsg, userMsg, assistantMsg));