提示词和提示词模板
- [一、 核心概念详解](#一、 核心概念详解)
-
- [1. 提示词 (Prompt)](#1. 提示词 (Prompt))
- [2. 提示词中的四大角色 (Message Roles)](#2. 提示词中的四大角色 (Message Roles))
- [3. 提示词模板 (Prompt Template)](#3. 提示词模板 (Prompt Template))
- [二、 代码实战示例](#二、 代码实战示例)
-
- [1. 基础 Prompt 构建(手动组装消息)](#1. 基础 Prompt 构建(手动组装消息))
- [2. 使用 PromptTemplate 动态生成提示词](#2. 使用 PromptTemplate 动态生成提示词)
- [3. 在 ChatClient 中使用系统提示词模板](#3. 在 ChatClient 中使用系统提示词模板)
- [三、 高级特性:提示词动态管理 (Nacos 集成)](#三、 高级特性:提示词动态管理 (Nacos 集成))
-
- [1. 引入依赖](#1. 引入依赖)
- [2. 配置 Nacos](#2. 配置 Nacos)
- [3. 动态调用](#3. 动态调用)
- [四、 最佳实践建议](#四、 最佳实践建议)
在 Spring AI Alibaba 中,提示词(Prompt)是与大模型(交互的核心载体,而提示词模板(Prompt Template)则是实现动态化、结构化提示词工程的关键工具。以下是对这两者的详细解析及代码实现。
一、 核心概念详解
1. 提示词 (Prompt)
Prompt 是发送给大模型的完整指令集合。在 Spring AI 中,它不仅仅是一段文本,而是一个包含消息列表(Messages)和配置选项(ChatOptions)的结构化对象。
- 构成要素:
- Messages:由不同角色的消息组成,包括
System(系统指令)、User(用户输入)、Assistant(历史回复)和Tool(工具调用结果)。 - ChatOptions:控制模型行为的参数,如温度(temperature)、最大令牌数(max_tokens)、模型名称(model)等。
- Messages:由不同角色的消息组成,包括
2. 提示词中的四大角色 (Message Roles)
Spring AI 通过 Message 接口及其子类来区分对话中的不同角色,模型会根据角色理解上下文逻辑:
| 角色类型 | 类名 | 作用与优先级 | 示例场景 |
|---|---|---|---|
| 系统消息 | SystemMessage |
优先级最高。设定 AI 的全局行为准则、人设、语气约束。通常放在对话最前面。 | "你是一个专业的 Java 专家,回答要简洁严谨。" |
| 用户消息 | UserMessage代表当前用户的真实提问或指令。 |
"请解释一下 Spring Boot 的自动装配原理。" | |
| 助手消息 | AssistantMessage |
代表模型的历史回复。用于多轮对话中让模型"记住"之前的上下文。 | "Spring Boot 通过 @EnableAutoConfiguration..." |
| 工具消息 | ToolMessage |
代表外部工具或函数调用的返回结果。用于增强模型获取实时信息的能力。 | "查询到的北京天气是:晴,25℃。" |
3. 提示词模板 (Prompt Template)
硬编码字符串作为提示词难以维护且缺乏灵活性。Prompt Template 允许开发者定义带有占位符的模板,并在运行时动态替换变量。
- 核心机制:
- 占位符语法:默认使用
{variableName}格式。 - 渲染引擎:底层默认使用
StTemplateRenderer(基于 StringTemplate 引擎),支持复杂的逻辑处理;也可配置为NoOpTemplateRenderer(仅做简单替换)。 - 动态性:通过
Map<String, Object>传入变量值,生成最终的Prompt或String。
- 占位符语法:默认使用
二、 代码实战示例
以下代码展示了如何构建基础 Prompt、使用模板动态生成 Prompt,以及在 ChatClient 中应用模板。
1. 基础 Prompt 构建(手动组装消息)
java
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class BasicPromptController {
@Autowired
private ChatModel chatModel;
@GetMapping("/chat/basic")
public String basicChat() {
// 1. 构建系统消息:设定人设
SystemMessage systemMessage = new SystemMessage("你是一个幽默的编程导师,擅长用比喻解释复杂概念。");
// 2. 构建用户消息:具体提问
UserMessage userMessage = new UserMessage("什么是递归?");
// 3. 组装 Prompt
Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
// 4. 调用模型并获取响应
return chatModel.call(prompt).getResult().getOutput().getContent();
}
}
2. 使用 PromptTemplate 动态生成提示词
这是企业级开发中最常用的方式,实现了提示词与业务逻辑的解偶。
java
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.chat.model.ChatModel;
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.Map;
@RestController
public class TemplatePromptController {
@Autowired
private ChatModel chatModel;
@GetMapping("/chat/template")
public String templateChat(@RequestParam String topic, @RequestParam String language) {
// 1. 定义提示词模板,使用 {topic} 和 {language} 作为占位符
String templateText = """
你是一个精通 {language} 的技术专家。
请用通俗易懂的语言解释以下概念:{topic}。
要求:
1. 给出一个生活中的类比。
2. 提供一段简单的代码示例。
""";
// 2. 创建 PromptTemplate 实例
PromptTemplate promptTemplate = new PromptTemplate(templateText);
// 3. 准备动态变量
Map<String, Object> variables = Map.of(
"topic", topic,
"language", language
);
// 4. 渲染并创建 Prompt 对象
// create(variables) 方法会自动替换占位符并封装成 Prompt
Prompt prompt = promptTemplate.create(variables);
// 5. 调用模型
return chatModel.call(prompt).getResult().getOutput().getContent();
}
}
3. 在 ChatClient 中使用系统提示词模板
ChatClient 提供了更流畅的 API 来集成系统提示词。
java
import org.springframework.ai.chat.client.ChatClient;
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;
@RestController
public class ChatClientTemplateController {
private final ChatClient chatClient;
@Autowired
public ChatClientTemplateController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping("/chat/client-template")
public String clientTemplateChat(@RequestParam String userName) {
// 使用链式调用,动态设置 System Message
return chatClient
.prompt()
// 动态设置系统指令,这里可以直接传入字符串,也可以结合 PromptTemplate 预处理后传入
.system("你好,{name}!我是你的专属AI助手。", Map.of("name", userName))
.user("今天有什么新闻?")
.call()
.content();
}
}
三、 高级特性:提示词动态管理 (Nacos 集成)
在生产环境中,频繁修改提示词并重新打包部署效率极低。Spring AI Alibaba 提供了 Nacos Prompt 管理 功能,支持从 Nacos 配置中心动态加载和更新提示词模板。
1. 引入依赖
xml
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-nacos-prompt</artifactId>
</dependency>
2. 配置 Nacos
在 application.yml 中启用 Nacos Prompt 模板支持:
yaml
spring:
ai:
nacos:
prompt:
template:
enabled: true
cloud:
nacos:
config:
server-addr: your-nacos-address:8848
3. 动态调用
java
import org.springframework.ai.chat.prompt.ConfigurablePromptTemplate;
import org.springframework.ai.chat.prompt.ConfigurablePromptTemplateFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class NacosPromptController {
@Autowired
private ConfigurablePromptTemplateFactory promptTemplateFactory;
@GetMapping("/chat/nacos")
public String nacosChat() {
// 从 Nacos 获取名为 "greeting_template" 的提示词模板
// 如果 Nacos 中未配置,则使用默认的 fallback 逻辑(需自行处理或配置默认值)
ConfigurablePromptTemplate template = promptTemplateFactory.create("greeting_template");
// 渲染模板
String renderedPrompt = template.render(Map.of("user", "张三"));
// 此时 renderedPrompt 即为从云端动态获取并替换变量后的最终提示词
return renderedPrompt;
}
}
四、 最佳实践建议
- 分离关注点:不要将提示词硬编码在 Java 字符串中。对于简单的静态提示词,可以使用常量;对于复杂或经常变化的提示词,务必使用
PromptTemplate或外部配置(如 Nacos/数据库)。 - 善用 System Message:将角色设定、输出格式约束(如"只返回 JSON")、安全限制等放在
SystemMessage中,这比放在UserMessage中更有效且稳定。 - 变量校验:在使用
PromptTemplate时,确保传入的Map中包含所有占位符对应的键,否则可能会抛出异常或保留原始占位符(取决于渲染器配置)。 - 结构化输出配合:当需要模型返回特定格式(如 JSON)时,应在 Prompt 模板中明确说明格式要求,并结合 Spring AI 的
.entity()方法进行自动反序列化。