三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Spring AI 提示词工程实战:让大模型更懂你的意图

Spring AI 提示词工程实战:让大模型更懂你的意图

Spring AI 提示词工程实战:让大模型更懂你的意图

Posted on 2026-05-30 22:32  work hard work smart  阅读(0)  评论(0)    收藏  举报

摘要:提示词工程(Prompt Engineering)是发挥大模型能力的关键技术。本文结合实际项目代码,系统讲解 Spring AI 中提示词工程的四大核心策略:角色设定、少样本学习、结构化输出和思维链推理。

一、什么是提示词工程?

提示词工程是通过精心设计的提示词(Prompt),引导大模型输出符合预期结果的技术。

为什么需要提示词工程?

同样的模型,不同的提示词,结果天差地别:

❌ 差的提示词:

帮我写个故事

→ 输出:随便写一个普通故事

✅ 好的提示词:

请以科幻为主题,写一个关于 AI 觉醒的短篇故事,要求:
1. 包含悬念和反转
2. 人物对话占比 40%
3. 字数 1000 字以内

→ 输出:高质量、符合要求的科幻故事

提示词工程的核心策略

  1. Role(角色设定):告诉 AI 它是谁
  2. Shot(少样本学习):给 AI 看几个例子
  3. Structure(结构化输出):规定输出格式
  4. Step(思维链):让 AI 逐步思考

二、策略一:角色设定(Role Prompting)

核心思想

通过 SystemMessage 定义 AI 的角色、性格和行为准则,让它以特定身份回答问题。

代码实现

@RestController
@RequestMapping("/prompt")
public class RolePromptingController implements InitializingBean {@Autowiredprivate ChatModel chatModel;private ChatClient chatClient;@Overridepublic void afterPropertiesSet() {// 设定默认角色:美食评论家chatClient = ChatClient.builder(chatModel).defaultSystem("你是一个专业的美食评论家,擅长用生动的语言描述菜品,评价要客观但带有个人风格").build();}@GetMapping("/food-review")public String foodReview(String restaurant) {return chatClient.prompt("评价一下" + restaurant).call().content();}
}

测试效果

# 输入
curl "http://localhost:8000/prompt/food-review?restaurant=海底捞"# 输出(美食评论家风格)
"海底捞的服务确实无可挑剔,但说实话,火锅的味道还停留在'不会出错但也不惊艳'的阶段。毛肚的脆度和牛油锅的醇厚是亮点,可如果你在追求味蕾的极致体验,可能会觉得少了点惊喜。"

角色设定技巧

1. 明确身份

.defaultSystem("""你是一个拥有 10 年经验的 Java 架构师,擅长 Spring Boot、微服务、分布式系统设计。""")

2. 定义行为准则

.defaultSystem("""你是一个耐心的编程老师,1. 用简单易懂的语言解释概念2. 提供代码示例3. 指出常见错误4. 鼓励学生思考""")

3. 设定语气风格

// 正式专业
.defaultSystem("你是一位专业的技术顾问,请用正式的语言回答问题")// 幽默风趣
.defaultSystem("你是一个幽默的程序员,喜欢用段子解释技术概念")// 简洁直接
.defaultSystem("你是一个高效的技术专家,只说重点,不要废话")

实战场景

@Bean
public ChatClient teacherClient(ChatModel chatModel) {return ChatClient.builder(chatModel).defaultSystem("""你是一个耐心的 Python 编程老师,教学风格:1. 先解释概念,再给代码示例2. 代码必须包含详细注释3. 指出新手容易犯的错误4. 最后给一个练习题""").build();
}

三、策略二:少样本学习(Few-Shot Learning)

核心思想

通过提供几个输入-输出示例,让 AI 学习任务的模式和规则,而不需要明确说明。

代码实现

@GetMapping("/intent-recognition")
public String recognizeIntent(String message) {return chatClient.prompt().system("""请识别用户输入的真实意图,并返回对应的操作类型。参考示例:Input:明天北京天气怎么样?Output:{"intent": "weather_query", "location": "北京", "time": "明天"}Input:帮我订一张后天去上海的高铁票Output:{"intent": "ticket_book", "type": "train", "from": "当前城市", "to": "上海", "date": "后天"}Input:推荐几部好看的电影Output:{"intent": "recommendation", "category": "movie"}""").user(message).call().content();
}

测试效果

# 输入
curl "http://localhost:8000/prompt/intent-recognition?message=我想定一个下周去成都的机票,最好是上午的航班"# 输出
{"intent": "ticket_book", "type": "flight", "to": "成都", "date": "下周", "preference": "上午航班"}

少样本学习的要素

1. 任务描述(可选)

请你根据用户输入的问题做改写,主要有以下改写策略:
1、改写其中的错别字。
2、做内容精简

2. 示例(核心)

Input:ni好
Output :{"错别字改写":"你好","内容精简":""}Input:我今天心情不错...
Output :{"错别字改写":"","内容精简":"今天是什么天气?"}

3. 用户输入

.user(message)

示例设计原则

✅ 好的示例

.system("""情感分析任务:示例 1:Input:这家餐厅太好吃了,服务也很棒!Output:{"sentiment": "positive", "score": 0.95}示例 2:Input:菜太咸了,等了一个小时还没上菜Output:{"sentiment": "negative", "score": 0.15}示例 3:Input:味道一般,价格还行Output:{"sentiment": "neutral", "score": 0.50}""")

优点:

  • 覆盖不同情况(正面、负面、中性)
  • 输出格式一致
  • 标签清晰

❌ 差的示例

.system("""情感分析:示例:好吃 -> 正面""")

缺点:

  • 示例太少,无法覆盖边界情况
  • 格式不统一
  • 缺少具体数值

实战场景:文本分类

@GetMapping("/classify")
public String classifyText(String text) {return chatClient.prompt().system("""请将用户的问题分类为以下类型:- code:代码相关- math:数学计算- writing:写作创作- chat:闲聊聊天示例:Input:如何用 Spring Boot 实现登录功能?Output:{"category": "code"}Input:1+1等于几?Output:{"category": "math"}Input:写一首关于春天的诗Output:{"category": "writing"}Input:你好,今天天气不错Output:{"category": "chat"}""").user(text).call().content();
}

四、策略三:结构化输出(Structured Output)

核心思想

明确要求 AI 以特定格式(如 JSON、XML、Markdown)输出结果,方便程序解析和后续处理。

代码实现

@GetMapping("/analyze")
public String structuredAnalyze(String company) {return chatClient.prompt().system("你是一个资深的商业分析师").user("请分析%s公司的商业模式,以 JSON 格式输出,包含:公司名称、核心业务、盈利模式、竞争优势、潜在风险".formatted(company)).call().content();
}

测试效果

# 输入
curl "http://localhost:8000/prompt/analyze?company=特斯拉"# 输出
{"company": "Tesla Inc.","core_business": "电动汽车、清洁能源、自动驾驶技术","revenue_model": "车辆销售、FSD软件订阅、太阳能产品、充电服务","competitive_advantages": ["领先的电池技术和超级充电网络","Autopilot 自动驾驶系统","强大的品牌影响力","垂直整合的供应链"],"risks": ["产能瓶颈","激烈的市场竞争","监管政策变化"]
}

结构化输出技巧

1. 明确指定格式

// JSON 格式
.user("请以 JSON 格式输出,包含以下字段:name, age, skills")// Markdown 表格
.user("请以 Markdown 表格形式输出,包含列:姓名、年龄、技能")// XML 格式
.user("请以 XML 格式输出,根节点为 person")

2. 提供 Schema 定义

.user("""请以 JSON 格式输出,严格遵循以下 Schema:{"person": {"name": "string","age": "number","skills": ["string"],"experience_years": "number"}}""")

3. 使用 JSON Mode(如果模型支持)

ChatOptions options = DashScopeChatOptions.builder().responseFormat(ResponseFormat.builder().type(ResponseFormat.Type.JSON_OBJECT).build()).build();return chatClient.prompt(message).options(options).call().content();

实战场景:信息抽取

@GetMapping("/extract")
public String extractInfo(String text) {return chatClient.prompt().system("你是一个信息抽取专家").user("""从以下文本中抽取关键信息,以 JSON 格式输出:文本:%s输出格式:{"persons": ["人名列表"],"locations": ["地点列表"],"organizations": ["组织机构列表"],"dates": ["日期列表"],"key_events": ["关键事件列表"]}""".formatted(text)).call().content();
}

五、策略四:思维链推理(Chain of Thought)

核心思想

让 AI 按照特定的步骤逐步思考,而不是直接给出答案,提高复杂问题的准确率。

代码实现

@GetMapping("/story-analysis")
public Flux<String> storyAnalysis(String story, HttpServletResponse response) {response.setCharacterEncoding("UTF-8");return chatClient.prompt("""请分析以下故事,并输出关键信息。请按照以下步骤逐步思考,最终只输出 JSON 即可:step 1-用一句话概括故事主题step 2-识别故事中的主要人物及其角色step 3-分析故事的情感基调(正面/负面/中性)step 4-提取故事的关键转折点step 5-输出一个 JSON 对象,包含以下键:theme(主题), characters(人物列表), sentiment(情感), plot_twists(转折点列表)最终输出格式:{"theme": "故事主题","characters": ["人物1", "人物2"],"sentiment": "情感基调","plot_twists": ["转折点1", "转折点2"]}""").system("你是专业的文学分析师").user(story).stream().content();
}

测试效果

# 输入
curl "http://localhost:8000/prompt/story-analysis?story=小明一直梦想成为画家,但父亲希望他学医。高考那年,他偷偷报考了美术学院。成绩公布那天,父亲拿着他的录取通知书,沉默了很久后说:'去吧,别后悔。'"# 输出(逐步思考过程,最终输出)
{"theme": "追求梦想与家庭和解","characters": ["小明(追梦者)", "父亲(严厉但理解)"],"sentiment": "positive","plot_twists": ["偷偷报考美术学院", "父亲最终支持"]
}

思维链的优势

1. 提高复杂任务的准确率

直接问:这篇文章有几个人名?
→ 可能漏掉或数错分步问:
step 1-概括内容
step 2-翻译
step 3-列出人名
step 4-统计数量
→ 准确率高

2. 便于调试和验证

// 可以看到 AI 的每一步思考过程
step 1: 张三、李四和王五一起去旅游
step 2: Zhang San, Li Si and Wang Wu went traveling together
step 3: 人名:Zhang San, Li Si, Wang Wu
step 4: {"num_names": 3}

思维链设计模式

模式 1:分析 → 综合

.system("""请按以下步骤分析代码:step 1-识别代码的主要功能step 2-分析代码的时间复杂度step 3-指出潜在的 bug 或性能问题step 4-给出优化建议step 5-输出优化后的代码最终输出一个 JSON:{"functionality": "功能描述","time_complexity": "时间复杂度","issues": ["问题列表"],"suggestions": ["建议列表"],"optimized_code": "优化后的代码"}""")

模式 2:分解 → 解决 → 合并

.system("""解决数学问题的步骤:step 1-理解问题,提取已知条件step 2-确定解题思路和方法step 3-分步计算,展示详细过程step 4-验证答案是否正确step 5-输出最终答案最终输出:{"understanding": "问题理解","approach": "解题思路","steps": ["计算步骤"],"verification": "验证过程","answer": "最终答案"}""")

模式 3:评估 → 对比 → 推荐

.system("""技术选型分析步骤:step 1-列出所有候选方案step 2-评估每个方案的优缺点step 3-对比关键指标(性能、易用性、生态)step 4-根据使用场景给出推荐最终输出:{"candidates": ["候选方案"],"comparison": {"方案1": {"pros": [], "cons": []},"方案2": {"pros": [], "cons": []}},"recommendation": "推荐方案","reason": "推荐理由"}""")

六、组合策略:提示词工程的最佳实践

实战案例:智能代码审查助手

@GetMapping("/code-review")
public String codeReview(String code) {return chatClient.prompt().system("""你是一个拥有 15 年经验的资深 Java 架构师,擅长代码审查、性能优化和设计模式。""")  // 角色设定.user("""请审查以下代码,并按照以下步骤输出:step 1-分析代码的主要功能step 2-识别代码中的问题(bug、性能、安全)step 3-评估代码的可维护性和可读性step 4-给出具体的优化建议step 5-提供优化后的代码参考示例:Input:public void process(List<String> data) {for (int i = 0; i < data.size(); i++) {String item = data.get(i);if (item != null) {System.out.println(item.toUpperCase());}}}Output:{"functionality": "遍历列表并打印大写字符串","issues": ["使用传统 for 循环,不够简洁","没有处理空列表的情况","直接打印到控制台,不够灵活"],"suggestions": ["使用增强 for 循环或 Stream API","添加空值检查","使用日志框架替代 System.out"],"optimized_code": "public void process(List<String> data) {\\n    if (data == null || data.isEmpty()) return;\\n    \\n    data.stream()\\n        .filter(Objects::nonNull)\\n        .map(String::toUpperCase)\\n        .forEach(log::info);\\n}"}现在请审查以下代码:%s最终以 JSON 格式输出。""".formatted(code))  // 少样本 + 思维链 + 结构化输出.call().content();
}

这个提示词组合了:

  1. ✅ 角色设定:资深 Java 架构师
  2. ✅ 思维链:5 步审查流程
  3. ✅ 少样本学习:提供了一个完整示例
  4. ✅ 结构化输出:要求 JSON 格式

七、提示词工程的常见陷阱

❌ 陷阱 1:提示词太长太啰嗦

// 错误示例
.system("""你是一个助手,你应该回答问题,你应该帮助用户,你要有礼貌,要专业,要准确,要详细,要全面,不要说谎,不要编造,不要误导...(废话太多)""")// 正确示例
.system("你是一个专业的技术顾问,回答要准确、简洁、实用")

❌ 陷阱 2:示例不一致

// 错误示例:格式不统一
.system("""示例1:好吃 -> 正面情感示例2:{"sentiment": "负面"}示例3:neutral""")// 正确示例:格式统一
.system("""示例1:{"sentiment": "positive", "score": 0.95}示例2:{"sentiment": "negative", "score": 0.15}示例3:{"sentiment": "neutral", "score": 0.50}""")

❌ 陷阱 3:缺少边界条件

// 错误示例:只给正常情况
.system("把数字乘以 2。示例:5 -> 10")// 正确示例:覆盖边界
.system("""把数字乘以 2。示例:5 -> 100 -> 0-3 -> -61000000 -> 2000000""")

八、完整 Controller 示例

package cn.hollis.llm.llmentor.controller;import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;@RestController
@RequestMapping("/prompt")
public class PromptEngineeringController implements InitializingBean {@Autowiredprivate ChatModel chatModel;private ChatClient chatClient;/*** 策略一:角色设定 - 美食评论家*/@GetMapping("/food-review")public String foodReview(String restaurant) {return chatClient.prompt("评价一下" + restaurant).call().content();}/*** 策略二:少样本学习 - 意图识别*/@GetMapping("/intent-recognition")public String recognizeIntent(String message) {return chatClient.prompt().system("""请识别用户输入的真实意图,并返回对应的操作类型。参考示例:Input:明天北京天气怎么样?Output:{"intent": "weather_query", "location": "北京", "time": "明天"}Input:帮我订一张后天去上海的高铁票Output:{"intent": "ticket_book", "type": "train", "from": "当前城市", "to": "上海", "date": "后天"}Input:推荐几部好看的电影Output:{"intent": "recommendation", "category": "movie"}""").user(message).call().content();}/*** 策略三:结构化输出 - 商业分析*/@GetMapping("/analyze")public String structuredAnalyze(String company) {return chatClient.prompt().system("你是一个资深的商业分析师").user("请分析%s公司的商业模式,以 JSON 格式输出,包含:公司名称、核心业务、盈利模式、竞争优势、潜在风险".formatted(company)).call().content();}/*** 策略四:思维链推理 - 故事分析*/@GetMapping("/story-analysis")public Flux<String> storyAnalysis(@RequestParam(value = "story") String story, HttpServletResponse response) {response.setCharacterEncoding("UTF-8");return chatClient.prompt("""请分析以下故事,并输出关键信息。请按照以下步骤逐步思考,最终只输出 JSON 即可:step 1-用一句话概括故事主题step 2-识别故事中的主要人物及其角色step 3-分析故事的情感基调(正面/负面/中性)step 4-提取故事的关键转折点step 5-输出一个 JSON 对象,包含以下键:theme(主题), characters(人物列表), sentiment(情感), plot_twists(转折点列表)最终输出格式:{"theme": "故事主题","characters": ["人物1", "人物2"],"sentiment": "情感基调","plot_twists": ["转折点1", "转折点2"]}""").system("你是专业的文学分析师").user(story).stream().content();}@Overridepublic void afterPropertiesSet() throws Exception {// 默认角色:美食评论家chatClient = ChatClient.builder(chatModel).defaultSystem("你是一个专业的美食评论家,擅长用生动的语言描述菜品,评价要客观但带有个人风格").build();}
}

九、提示词工程检查清单

在实际开发中,使用以下检查清单优化你的提示词:

✅ 角色设定检查

✅ 少样本学习检查

✅ 结构化输出检查

✅ 思维链检查


十、总结

提示词工程是发挥大模型潜力的关键技术。在 Spring AI 中,我们可以通过 ChatClient 优雅地实现四大核心策略:

策略 核心思想 适用场景 代码方法
角色设定 定义 AI 身份 统一回答风格 defaultSystem()
少样本学习 提供示例 模式识别任务 .system("示例...")
结构化输出 规定格式 程序解析 "以 JSON 格式输出"
思维链推理 分步思考 复杂问题 "step 1...step 2..."

最佳实践:

  1. 组合使用多种策略,效果更佳
  2. 示例要典型、覆盖边界情况
  3. 输出格式要明确、统一
  4. 复杂任务分解为多步骤

掌握提示词工程,让大模型真正成为你的得力助手!


参考资源:

  • OpenAI Prompt Engineering Guide
  • Spring AI 官方文档
  • Awesome Prompt Engineering
← 返回列表