第2集:AI说话像机器人?一个Prompt模板让它秒变老员工
上集回顾:老张用Spring AI搭了个客服助手原型,能对话但语气生硬,用户反馈"像跟Siri聊天"。总监老李皱眉:“这哪像我们公司的客服?”
一、故事继续:用户的吐槽
周四上午,老张打开客服系统后台,看到一条用户留言:
“你们这个AI怎么回事?我问的是退款流程,它给我背了一堆条款,跟念经似的。我要的是步骤!”
老张点开AI对话记录,果然:
用户:怎么退款?
AI:根据《售后服务管理条例》第三条规定,退货需满足以下条件:
一、商品完好无损;
二、原始包装齐全;
三、在七日内申请...
老张的内心独白:“这AI是不是没受过客服培训?光背法条不管用啊!”
他想起自己写代码时,如果给新员工发的"员工手册"写得太官方,新员工肯定也学不会。AI也一样——你得先告诉它"你是谁"“你该怎么做”。
二、技术引入:System Message是什么?
2.1 类比理解
System Message就像给AI的"岗位说明书":
| 岗位 | System Message内容 |
|---|---|
| 客服 | “你是XX公司的资深客服,语气亲切,回答简洁,不背法条” |
| 技术支持 | “你是高级Java工程师,能用代码示例解释概念” |
| 销售 | “你是金牌销售,擅长挖掘需求、促成成交” |
2.2 代码实现
// 之前:没有System Message
String answer = chatClient.prompt()
.user("怎么退款?")
.call()
.content();
// 之后:加上System Message
String answer = chatClient.prompt()
.system("你是XX公司的资深客服小王,有5年客服经验。")
.system("你的职责:1)快速回答用户问题 2)语气亲切友好 3)不用官方术语")
.system("当用户问流程时,用步骤列表回答,不要太长")
.user("怎么退款?")
.call()
.content();
效果对比:
【改前】AI:根据《售后服务管理条例》第三条规定...
【改后】AI:亲,退款很简单哦~
1️⃣ 登录APP → 订单详情
2️⃣ 点击「申请退款」
3️⃣ 选择退款原因
4️⃣ 提交后3天内原路退回
有问题随时问我哈!😊
三、Prompt模板:别让AI猜你的意思
3.1 问题:每次手写Prompt太累
老张发现,每个功能都要写一大段System Message,重复代码很多:
// 客服对话
.system("你是XX公司的客服小王...")
.system("语气要亲切...")
.system("回答要简洁...")
// 技术支持对话
.system("你是XX公司的技术支持工程师...")
.system("语气要专业...")
.system("回答要有代码示例...")
3.2 解决方案:PromptTemplate
Prompt模板就像"填空游戏":
@Service
public class AiService {
// 定义客服角色模板
private final PromptTemplate客服模板 = PromptTemplate.builder()
.template("""
你是{company}公司的资深客服{name}。
你的背景:{experience}年客服经验,熟悉{productLine}产品。
你的职责:
1. 快速回答用户问题
2. 语气亲切友好,多用emoji
3. 不用官方术语,用大白话
回答格式:
- 流程类问题:用步骤列表(1️⃣2️⃣3️⃣)
- 咨询类问题:简洁回答,不超过3句话
- 投诉类问题:先道歉,再给解决方案
当前对话:
{conversation}
用户问题:{question}
""")
.build();
public String chat(String question, String userId) {
// 获取用户历史对话
String conversation = getHistory(userId);
// 渲染模板
Map<String, Object> vars = new HashMap<>();
vars.put("company", "XX科技");
vars.put("name", "小王");
vars.put("experience", "5");
vars.put("productLine", "软件服务");
vars.put("conversation", conversation);
vars.put("question", question);
Prompt prompt = 客服模板.create(vars);
return chatClient.prompt(prompt).call().content();
}
}
老张的感悟:“Prompt模板就是『标准化作业流程』的AI版——同样的场景,同样的回答风格,不靠AI临场发挥。”
四、Few-shot示例:给AI看"标准答案"
4.1 问题:光说不够,要让AI看样例
老张发现,光写System Message,AI还是掌握不好"简洁"的度。有时候太长,有时候又太短。
解决方案:Few-shot Learning(少样本学习)
.system("""
你是资深客服小王。
回答示例:
用户:退款流程是什么?
AI:亲,退款3步走:
1️⃣ APP→我的订单→申请退款
2️⃣ 选原因→提交
3️⃣ 等审核(通常3天)
用户:发票怎么开?
AI:电子发票在订单详情页点「开具发票」,填邮箱就行~
现在请你回答:{question}
""")
4.2 Few-shot的核心逻辑
┌─────────────────────────────────────┐
│ System Message │
│ ├─ 角色定义 │
│ ├─ 回答规则 │
│ └─ 示例(关键!) │
│ ├─ 示例1:流程类问题 │
│ ├─ 示例2:咨询类问题 │
│ └─ 示例3:投诉类问题 │
└─────────────────────────────────────┘
↓
AI学习你的"风格"
老张的发现:“原来AI也是『看样例学做事』的——就像新员工培训,给几个优秀案例比说一堆规则管用。”
五、结构化输出:让AI返回「可解析的数据」
5.1 问题:AI的回答太自由
某天,老李要求"把AI回答存进数据库"。老张写了代码,结果AI一会儿返回纯文本,一会儿返回JSON,一会儿还带表情符号…
用户:这个订单什么时候发货?
AI:亲亲,您的订单已经在路上啦~预计明天送到哦!📦✨
老张的困惑:“这格式,我怎么存数据库?”
5.2 解决方案:结构化输出
Spring AI提供BeanOutputConverter,让AI返回标准Java对象:
// 定义输出结构
public record OrderStatus(
String orderId, // 订单号
String status, // 状态:已发货/运输中/已签收
String estimatedDelivery, // 预计送达
String trackingNumber // 快递单号
) {}
// 使用结构化输出
ChatResponse response = chatClient.prompt()
.system("你是客服小王。请严格按照JSON格式回答订单查询。")
.system("""
输出格式:
{
"orderId": "订单号",
"status": "状态",
"estimatedDelivery": "预计送达时间",
"trackingNumber": "快递单号"
}
""")
.user("查一下订单ORD20240820001的物流状态")
.call()
.entity(OrderStatus.class); // 关键:直接转Java对象
OrderStatus result = response.getResult().getOutput().getText();
效果:
{
"orderId": "ORD20240820001",
"status": "运输中",
"estimatedDelivery": "2024-08-21",
"trackingNumber": "SF1234567890"
}
5.3 结构化输出的应用场景
| 场景 | 输出结构 |
|---|---|
| 订单查询 | OrderStatus 对象 |
| 问题分类 | {"category": "咨询/投诉/建议"} |
| 情感分析 | {"sentiment": "positive/negative/neutral"} |
| 意图识别 | {"intent": "refund/query/complaint"} |
老张的总结:“以前AI是『自由发挥』,现在让它『按格式交作业』——后端开发最擅长的结构化数据,AI也能搞定。”
六、完整代码:老张的客服AI V2
@Service
public class CustomerServiceAgent {
@Autowired
private ChatClient chatClient;
// 客服角色模板
private final PromptTemplate 客服模板 = PromptTemplate.builder()
.template("""
你是XX科技的资深客服小王,5年经验。
你的风格:
- 亲切友好,像朋友聊天
- 简洁明了,不啰嗦
- 该道歉时真诚道歉
回答规则:
1. 流程类 → 步骤列表(1️⃣2️⃣3️⃣)
2. 咨询类 → 3句话内回答
3. 投诉类 → 先道歉再给方案
示例:
用户:怎么退款?
你:亲,退款3步走:
1️⃣ APP→我的订单→申请退款
2️⃣ 选原因→提交
3️⃣ 等审核(通常3天)
现在请回答:{question}
""")
.build();
public String chat(String userId, String question) {
// 1. 获取历史对话
List<Message> history = getHistory(userId);
// 2. 渲染Prompt模板
Map<String, Object> vars = Map.of("question", question);
Prompt prompt = 客服模板.create(vars);
// 3. 构建带历史的对话
ChatResponse response = chatClient.prompt(prompt)
.system(history) // 注入历史
.call()
.getResult();
// 4. 保存历史
saveHistory(userId, question, response.getOutput());
return response.getOutput().getText();
}
}
七、效果对比:从「机器人」到「老员工」
| 维度 | 改前 | 改后 |
|---|---|---|
| 语气 | 官方、生硬 | 亲切、自然 |
| 格式 | 大段文字 | 列表、emoji |
| 风格 | 千人一面 | 有个人特色 |
| 用户反馈 | 常被吐槽"太机械" | 张姐验收时说"像那么回事了" |
张姐(客服主管)的评价:“这个AI像那么回事了,比我们新培训的员工还行!”
八、下一集预告
AI学会了"说话",但总是「断片」——用户问第三句时,它忘了第一句。
“它怎么老忘事?” —— 第3集,给客服助手装上"海马体"。
📦 完整代码
GitHub分支:https://github.com/yinclei/SpringAITutorial/chapter02-prompt-engineering
💬 互动环节
老兵问答:
你在Prompt编写时遇到过什么问题?
A. AI不按我说的格式回答
B. 提示词太长记不住
C. 不知道怎么写才能控制AI
D. 其他(评论区说说)
下周三晚9点,我们继续!
作者:Java老兵搞AI | 关注我,看Java如何玩转AI
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)