模块1(上):Prompt Engineering——4个技巧让大模型听你的话
上一篇文章预告了模块1:Prompt Engineering实战,手把手教你写出能让模型稳定返回JSON的prompt。今天来交作业。
我被模型气笑了的那些时刻
先说个真事。
上个月我写了个代码审查助手,让AI帮我review Java代码。Prompt是这么写的:
"请审查以下代码,指出潜在问题"
结果模型洋洋洒洒给我写了一篇800字的散文,从"这段代码体现了程序员的逻辑思维能力"讲到"变量命名反映了程序员的职业素养"。
我当时的表情就是 😤。
后来我才搞明白:不是模型蠢,是我写prompt的方式蠢。
我以为prompt是"许愿",写几个关键词让模型猜我的意思。实际上prompt是"下单",你得把规格写清楚,模型才能给你准确的结果。
所以prompt工程不是玄学,是规格说明书。
Prompt到底由什么构成
别急,先搞清楚prompt的"配料表"。
一个完整prompt通常包含四个部分:
plaintext
System Prompt(系统指令):你是谁,你的角色是什么
User Prompt(用户输入):具体的问题或任务
Few-shot Examples(示例):给模型看标准答案
Context(上下文):额外的信息补充
举个子:
plaintext
System: 你是一个Java代码审查专家,擅长发现性能问题和安全隐患。
User: 请审查这段代码,找出所有可能引发NPE的地方。
Context: 这段代码运行在JDK17环境,使用Spring Boot 3.x
这四部分不是都要写,根据场景灵活组合。但新手最常犯的错是:只写User Prompt,其他全靠模型脑补。
实战技巧一:先定角色
这是最简单、效果最明显的技巧。
你告诉模型"你是谁",它就会按照那个角色的方式回答。
❌ 之前我写的:
text
请审查以下代码
✅ 改成:
text
你是一个资深Java开发工程师,10年经验,擅长代码重构和性能优化。请审查以下代码,找出:
- 空指针风险
- 资源泄漏
- 线程安全问题
为什么有效?因为大模型训练时,不同角色的回答风格差异很大。你让它扮演"资深工程师",它输出的严谨程度和专业术语完全不一样。
所以:角色约束不是玄学,是锚定模型的回答质量。
实战技巧二:控制输出格式
想让模型返回JSON做后端处理,结果它给你来一段自然语言?
我踩过这个坑。
早期我用GPT-4处理用户评价,想让模型返回结构化的情感分类结果。Prompt写的是"请以JSON格式返回",结果模型返回的是:
plaintext
根据我的分析,这段文本的情感是积极的...
后来我找到解法:用模型原生的结构化输出能力。
Java代码(Spring AI)
java
@RestController
@RequestMapping("/api/ai")
public class PromptEngineeringController {
private final ChatModel chatModel;
public PromptEngineeringController(ChatModel chatModel) {
this.chatModel = chatModel;
}
// 技巧2:使用responseFormat控制输出格式
@GetMapping("/sentiment")
public Map<String, Object> analyzeSentiment(@RequestParam String text) {
String prompt = """
分析以下用户评价的情感,返回JSON格式:
{"sentiment": "positive|negative|neutral", "score": 0-100, "keywords": ["关键词1", "关键词2"]}
用户评价:%s
""".formatted(text);
// 使用结构化输出,强制返回JSON
var request = OpenAiChatOptions.builder()
.withModel("gpt-4o")
.withResponseFormat(new ResponseFormat("json_object"))
.build();
ChatResponse response = chatModel.call(
new Prompt(prompt, request)
);
String content = response.getResult().getOutput().getText();
return Map.of(
"raw", content,
"status", "success"
);
}
}
关键就在这行:
java
.withResponseFormat(new ResponseFormat("json_object"))
这是告诉模型:"你必须给我一个合法的JSON对象,不许解释,不许废话。"
所以:想让模型听话,得用它的原生能力,而不是"请"它。
实战技巧三:Few-shot,给模型看标准答案
有时候说一百遍不如给个例子。
Few-shot就是你在prompt里放1-3个示例,让模型"照着这个格式来"。
❌ 之前我写的:
text
请提取文本中的人名和职位
✅ 改成:
text
请从文本中提取人名和职位,格式如下:
示例:
输入:张三在华为担任技术总监
输出:{"name": "张三", "title": "技术总监"}
输入:李四是阿里巴巴的高级算法工程师
输出:
模型看到示例后,会自动模仿格式输出。这就是Few-shot的威力。
Java代码
java
public String extractWithFewShot(String text) {
String prompt = """
从以下文本中提取人名和职位,返回JSON格式:
示例1:
输入:马云是阿里巴巴的创始人
输出:{"name": "马云", "title": "创始人"}
示例2:
输入:王坚在微软担任首席工程师多年
输出:{"name": "王坚", "title": "首席工程师"}
现在提取:
输入:%s
输出:
""".formatted(text);
// 使用低温获得确定性输出
var request = OpenAiChatOptions.builder()
.withModel("gpt-4o")
.withTemperature(0.1) // 低温保证格式稳定
.withResponseFormat(new ResponseFormat("json_object"))
.build();
return chatModel.call(new Prompt(prompt, request))
.getResult().getOutput().getText();
}
所以:Few-shot就是"手把手教",比抽象指令有效十倍。
实战技巧四:思维链,让模型"想清楚再说"
你有没有遇到过这种情况:模型回答得很流畅,但逻辑是错的?
这是因为模型跳过了推理过程,直接给了答案。
CoT(Chain of Thought,思维链)就是逼模型把思考过程说出来。
❌ 直接要答案:
text
问:一个商店有20个苹果,卖出12个,又进货8个,现在有多少苹果?
答:
✅ 加上"Think step by step":
text
问:一个商店有20个苹果,卖出12个,又进货8个,现在有多少苹果?
答:让我们一步步思考...
加上"think step by step"之后,模型的准确率能提升30%以上。
Java代码:带思维链的代码审查
java
public String reviewCodeWithCoT(String code) {
String prompt = """
你是一个Java代码审查专家。请审查以下代码,先用思维链分析问题,再给出结论。
思维链格式:
1. 首先分析...(这步做了什么)
2. 然后检查...(有没有风险)
3. 最后总结...(整体评价)
代码:
%s
请按以下JSON格式输出:
{"analysis": ["步骤1", "步骤2", "步骤3"], "issues": ["问题1", "问题2"], "score": 0-100}
""".formatted(code);
var request = OpenAiChatOptions.builder()
.withModel("gpt-4o")
.withTemperature(0.3) // 稍高温度,因为推理过程可以有变化
.withResponseFormat(new ResponseFormat("json_object"))
.build();
return chatModel.call(new Prompt(prompt, request))
.getResult().getOutput().getText();
}
所以:逼模型说出推理过程,不是浪费时间,是提高准确率。
这四个技巧——角色约束、格式控制、Few-shot、思维链——每一个都能单独提显著提升效果。
下一篇我们用一个完整实战把四个技巧串起来,再聊聊温度参数怎么选、以及我踩过的4个坑。
往期文章:
Java转AI,我整理了8个模块的学习路线图
如果对你有帮助,点个赞再走~