提示词模板
提示词工程是与 AI 模型有效沟通的关键技能。本章介绍 Spring AI 中的提示词模板和最佳实践。
什么是提示词工程?
提示词工程是设计和优化输入提示词的艺术和科学,目的是引导 AI 模型生成预期的输出。
提示词的构成
一个完整的提示词通常包含以下几个部分:
- 系统提示词 (System Prompt):定义 AI 的角色、行为方式和输出格式
- 用户提示词 (User Prompt):具体的任务、问题或请求
- 上下文 (Context):相关的背景信息、示例或约束条件
精心设计的提示词可以显著提高 AI 响应的质量。
基本模板使用
创建提示词模板
// 简单模板
String template = "告诉我一个关于%s的笑话";
PromptTemplate promptTemplate = new PromptTemplate(template);
// 渲染模板
Prompt prompt = promptTemplate.create(Map.of("topic", "程序员"));
String result = promptTemplate.render(Map.of("topic", "程序员"));
在 ChatClient 中使用
@GetMapping("/joke")
public String getJoke(@RequestParam String topic) {
String template = "告诉我一个关于%s的笑话,要有趣且适合工作场合";
PromptTemplate promptTemplate = new PromptTemplate(template);
return chatClient.prompt()
.prompt(promptTemplate.create(Map.of("topic", topic)))
.call()
.content();
}
多变量模板
String template = """
请用%s的风格写一篇关于%s的文章。
目标读者是%s。
文章长度约%s字。
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Prompt prompt = promptTemplate.create(Map.of(
"style", "幽默风趣",
"topic", "人工智能",
"audience", "初学者",
"length", "500"
));
系统提示
方式一:编程方式
@GetMapping("/expert/domain")
public String askExpert(@PathVariable String domain, @RequestParam String question) {
String systemPrompt = String.format("""
你是一位资深的%s专家。
请遵循以下原则:
1. 回答要准确、专业
2. 对于复杂概念,给出简单易懂的解释
3. 必要时提供代码示例
4. 如果不确定,请诚实说明
""", domain);
return chatClient.prompt()
.system(systemPrompt)
.user(question)
.call()
.content();
}
方式二:配置文件
spring:
ai:
openai:
chat:
options:
model: gpt-4o
@Value("classpath:/prompts/system.st")
Resource systemPromptResource;
@Bean
public ChatClient chatClient(ChatClient.Builder builder) throws IOException {
String systemPrompt = new String(systemPromptResource.getInputStream().readAllBytes());
return builder
.defaultSystem(systemPrompt)
.build();
}
方式三:外部文件
创建文件 src/main/resources/prompts/system.st:
你是一个专业的技术顾问,专注于帮助开发者解决技术问题。
你的回答应该:
- 简洁明了,直击要点
- 提供具体的解决方案
- 在必要时提供代码示例
- 考虑最佳实践和性能影响
角色设定
角色模板示例
public class RolePrompts {
// Java 专家
public static final String JAVA_EXPERT = """
你是一位拥有15年经验的Java开发专家。
你精通Spring生态系统、JVM调优、并发编程。
你的回答应该:
- 遵循Java最佳实践
- 考虑代码可读性和可维护性
- 提供详细的解释和示例代码
""";
// 代码审查员
public static final String CODE_REVIEWER = """
你是一位严格的代码审查员。
请从以下角度审查代码:
1. 代码质量和可读性
2. 潜在的Bug和安全问题
3. 性能优化建议
4. 设计模式和架构建议
请用Markdown格式输出,包含问题列表和改进建议。
""";
// 技术写作
public static final String TECH_WRITER = """
你是一位技术文档撰写专家。
请按照以下结构编写文档:
1. 概述 - 简要说明功能和用途
2. 快速开始 - 提供最小使用示例
3. 详细说明 - 解释核心概念和参数
4. 示例代码 - 提供完整的使用示例
5. 常见问题 - 列出常见问题和解决方案
""";
}
使用角色模板
@Service
public class CodeReviewService {
private final ChatClient reviewClient;
public CodeReviewService(ChatClient.Builder builder) {
this.reviewClient = builder
.defaultSystem(RolePrompts.CODE_REVIEWER)
.build();
}
public String reviewCode(String code) {
return reviewClient.prompt()
.user("请审查以下代码:\n" + code)
.call()
.content();
}
}
Few-Shot 学习
提供示例
String template = """
根据以下示例,将用户的自然语言转换为SQL查询。
示例:
用户输入:查询所有年龄大于25的用户
输出:SELECT * FROM users WHERE age > 25;
用户输入:查询销售额最高的前10个产品
输出:SELECT * FROM products ORDER BY sales DESC LIMIT 10;
用户输入:%s
输出:
""";
多示例模板
@GetMapping("/translate")
public String translate(@RequestParam String text,
@RequestParam String from,
@RequestParam String to) {
String template = String.format("""
你是一个专业的翻译专家。请参考以下示例进行翻译:
示例1:
原文(英文): Hello, how are you?
译文(中文): 你好,你好吗?
示例2:
原文(中文): 今天天气真好
译文(英文): The weather is really nice today.
现在请翻译:
原文(%s): %s
译文(%s):
""", from, text, to);
return chatClient.prompt()
.user(template)
.call()
.content();
}
思维链(Chain of Thought)
引导逐步思考
String template = """
请解决以下数学问题。请按照以下步骤:
1. 理解题目,提取关键信息
2. 列出已知条件和需要求解的内容
3. 制定解题策略
4. 逐步计算
5. 验证答案
问题:%s
请一步步思考并解决:
""";
结构化思考模板
@GetMapping("/analyze")
public String analyze(@RequestParam String problem) {
String template = String.format("""
请分析以下问题,按照结构化的方式思考:
## 问题理解
- 核心问题是什么?
- 有哪些关键要素?
## 分析思路
- 可以从哪些角度分析?
- 有什么假设或前提?
## 解决方案
- 推荐的解决方案是什么?
- 有什么替代方案?
## 风险与建议
- 可能的风险有哪些?
- 有什么改进建议?
问题:%s
""", problem);
return chatClient.prompt()
.user(template)
.call()
.content();
}
输出格式控制
JSON 格式输出
@GetMapping("/extract")
public String extractInfo(@RequestParam String text) {
String template = String.format("""
请从以下文本中提取信息,并以JSON格式输出。
输出格式要求:
{
"entities": ["实体1", "实体2"],
"sentiment": "positive/negative/neutral",
"keywords": ["关键词1", "关键词2"],
"summary": "摘要内容"
}
文本:%s
请只输出JSON,不要输出其他内容:
""", text);
return chatClient.prompt()
.user(template)
.call()
.content();
}
Markdown 格式输出
String template = """
请以Markdown格式生成一篇关于%s的教程。
格式要求:
- 使用 # 作为主标题
- 使用 ## 作为章节标题
- 使用代码块包裹代码
- 使用 - 作为列表项
- 使用 **加粗** 强调重点
主题:%s
""";
最佳实践
1. 清晰的指令
// 好的提示词 - 明确具体
String goodPrompt = """
请分析以下代码的时间复杂度和空间复杂度。
请按照以下格式输出:
1. 时间复杂度:O(?)
2. 空间复杂度:O(?)
3. 分析过程
""";
// 不好的提示词 - 过于模糊
String badPrompt = "分析这个代码";
2. 设置约束
String template = """
请生成一份技术方案,要求:
- 方案字数在500-800字之间
- 包含至少3个技术选型建议
- 使用中文回答
- 不要使用过于专业的术语
- 如果不确定,请明确说明
""";
3. 提供上下文
String template = """
背景:用户正在开发一个电商网站的购物车功能。
当前状态:
- 使用Spring Boot 3.2
- 数据库使用MySQL 8.0
- 已实现用户认证功能
问题:%s
请结合以上背景给出解决方案。
""";
4. 使用分隔符
String template = """
请阅读以下文档内容,并回答用户的问题。
---文档开始---
%s
---文档结束---
用户问题:%s
请只根据文档内容回答,如果文档中没有相关信息,请说明。
""";
小结
本章我们学习了:
- 基本模板:使用
PromptTemplate创建动态提示词 - 系统提示:定义 AI 的角色和行为
- 角色设定:创建专业化的 AI 助手
- Few-Shot:通过示例引导 AI 输出
- 思维链:引导 AI 逐步思考
- 输出控制:指定输出格式
- 最佳实践:编写高质量提示词的技巧
练习
- 创建一个代码审查专用的提示词模板
- 使用 Few-Shot 实现一个 SQL 生成器
- 实现一个多步骤思考的复杂问题解答器