02. 提示词工程与 Java 模板
你是否发现,AI 有时候很聪明,有时候又答非所问?
问题的关键不在于 AI 笨,而在于你的 Prompt (提示词) 写得不够好。
| 作为后端开发,我们不能像普通用户那样每次手敲问题。我们需要:
1. **结构化**:区分“人设”和“指令”。
2. **模板化**:用 Java 代码动态组装 Prompt。
3. **示例化**:教会 AI 举一反三 (Few-Shot)。
|
🎭 第一部分:Prompt 的三明治结构
在 OpenAI/ModelScope 的协议中,一条完整的 Prompt 并不是一个简单的字符串,而是由不同角色的消息组成的列表。
最经典的是 System (系统/人设) 和 User (用户/指令) 的配合。
| 角色 (Role) |
作用 |
比喻 |
| System |
设定 AI 的行为模式、语气、身份。 |
导演:“你现在是一个资深的 Java 面试官,语气要严厉。” |
| User |
用户具体的提问或指令。 |
演员:“请问 HashMap 的底层原理是什么?” |
| Assistant |
AI 的回复历史 (用于多轮对话)。 |
搭档:“(AI 之前的回答...)” |
❌ 错误示范 (只有 User)
User: "把这句话翻译成英文:你好"
✅ 正确示范 (System + User)
System: "你是一个精通中英互译的翻译官,只能输出翻译结果,不要多说话。"
User: "你好"
🧱 第二部分:Java 新特性——文本块 (Text Blocks)
在 JDK 13 以前,要在 Java 里拼接一个多行的 Prompt 或者 JSON,简直是噩梦:
| // ❌ JDK 8 的写法:丑陋、易错、难以阅读
String json = "{\n" +
" \"role\": \"system\",\n" +
" \"content\": \"你是个助手\"\n" +
"}";
|
从 JDK 15 开始,Java 正式引入了 Text Blocks (文本块),使用 """ 包裹。这简直是为 AI 开发量身定做的功能!
| // ✅ JDK 15+ 的写法:清爽、所见即所得
String json = """
{
"role": "system",
"content": "你是个助手"
}
""";
|
配合 .formatted() 方法(相当于 String.format 的简化版),我们可以轻松创建 Prompt 模板。
🧠 第三部分:技巧——Few-Shot (少样本提示)
这是 Prompt Engineering 中性价比最高的技巧。
不要只告诉 AI “做什么”,而是给它看几个“成功的例子”。
场景:情感分析
我们希望 AI 判断用户评论是“正面”还是“负面”,并只返回 POSITIVE 或 NEGATIVE。
Zero-Shot (零样本 - 直接问)
User: "这家店很难吃。是正面还是负面?"
AI: "这句话表达了对食物的不满,所以是负面评价。" (废话太多,不好解析)
Few-Shot (少样本 - 给例子)
User:
这是一个情感分析任务。
例子 1:
输入:"味道不错" -> 输出:POSITIVE
例子 2:
输入:"服务员态度很差" -> 输出:NEGATIVE
请分析以下输入:"这家店很难吃" -> 输出:
AI: "NEGATIVE" (非常听话)
💻 第四部分:代码实战
我们将结合 System 人设、文本块 和 Few-Shot,写一个“智能情感分析器”。
在 src/test/java 下新建 PromptTest.java。
| PromptTest.java |
|---|
| package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.web.client.RestClient;
@SpringBootTest
public class PromptTest {
private static final String API_KEY = "sk-你的Token";
private static final String API_URL = "https://api-inference.modelscope.cn/v1/chat/completions";
@Test
void testSentimentAnalysis() {
// ==========================================
// 1. 定义 Prompt 模板 (Java 文本块)
// ==========================================
// System Prompt: 确立人设
String systemPrompt = "你是一个情感分析专家。请根据用户的输入,只返回 'POSITIVE' 或 'NEGATIVE',不要包含任何其他文字。";
// User Prompt: 包含 Few-Shot 示例 + 动态变量 (%s)
String userPromptTemplate = """
这里有一些示例:
输入:"快递很快,包装完好" -> 输出:POSITIVE
输入:"虽然便宜,但是质量太差了" -> 输出:NEGATIVE
输入:"老板人很好,下次还来" -> 输出:POSITIVE
现在请分析这个输入:
输入:"%s" -> 输出:
""";
// 模拟用户输入
String userInput = "衣服很漂亮,但是物流太慢了,等了一周!";
// 组装最终的 User Prompt
String finalUserPrompt = userPromptTemplate.formatted(userInput);
// ==========================================
// 2. 构建 JSON 请求体
// ==========================================
// 注意:这里为了演示方便直接拼 JSON。
// 真实项目中,如果 input 包含换行或引号,直接拼会报错。下一节我们会用 JSON 库来解决这个问题。
String jsonBody = """
{
"model": "deepseek-ai/DeepSeek-R1-0528",
"messages": [
{
"role": "system",
"content": "%s"
},
{
"role": "user",
"content": "%s"
}
]
}
""".formatted(systemPrompt, finalUserPrompt.replace("\n", "\\n").replace("\"", "\\\""));
// 👆 简单的转义处理,防止 JSON 格式破损
// ==========================================
// 3. 发送请求
// ==========================================
RestClient client = RestClient.builder()
.baseUrl(API_URL)
.defaultHeader("Authorization", "Bearer " + API_KEY)
.build();
System.out.println("🤖 正在分析情感...");
String response = client.post()
.contentType(MediaType.APPLICATION_JSON)
.body(jsonBody)
.retrieve()
.body(String.class);
System.out.println("✅ AI 原始回复: " + response);
}
}
|
运行结果预期
由于我们使用了 System 限定 和 Few-Shot 引导,AI 应该会非常克制,只输出我们想要的结果(可能 DeepSeek-R1 会先输出 <think>,但最终结论会很标准)。
| {
...
"content": "<think>...</think>NEGATIVE"
}
|
⚠️ 痛点预告:JSON 拼接的风险
仔细看上面的代码,为了把 prompt 塞进 JSON,我不得不写了这样一行代码:
| finalUserPrompt.replace("\n", "\\n").replace("\"", "\\\"")
|
这是非常危险且不优雅的!
- 如果用户输入里有复杂的字符(比如 Emoji、Tab),手写替换很容易漏掉,导致 JSON 格式错误(400 Bad Request)。
- 代码里充斥着大量的转义符,难以维护。
如何优雅地把 Java 对象转换成 JSON,并让 AI 稳定地返回 JSON 格式的数据?
下一节,我们将引入 Jackson 和 JSON Schema,让程序交互变得真正“专业化”。
📝 总结
- 结构化:Prompt 不是一句话,而是
System (人设) + User (指令) 的组合。
- 工具:使用 Java 15+ 的 Text Blocks (
""") 和 .formatted(),让 Prompt 代码清晰可读。
- 心法:Few-Shot (少样本) 是提高 AI 准确率的神器,给它几个例子,它就能懂你的规矩。
下一节:让 AI 说“机器话”:JSON Schema 与解析