LangChain4j 提示词与模板

概述
提示词(Prompt)是与 LLM 交互的核心。本教程将介绍如何使用 LangChain4j 的提示词模板功能,实现灵活、可复用的提示词管理。
基础提示词
简单文本提示
代码示例 (参考:tutorials/src/main/java/_03_PromptTemplate.java)
java
package dev.langchain4j.example;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;
public class SimplePromptExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.build();
// 直接使用字符串作为提示词
String response = model.generate("请用一句话解释什么是机器学习");
System.out.println(response);
}
}
提示词模板(PromptTemplate)
使用占位符的模板
提示词模板允许你创建可复用的提示词,通过占位符动态注入内容。
java
package dev.langchain4j.example;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.input.Prompt;
import dev.langchain4j.model.input.PromptTemplate;
import dev.langchain4j.model.openai.OpenAiChatModel;
import java.util.HashMap;
import java.util.Map;
import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;
public class PromptTemplateExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.build();
// 1. 创建提示词模板(使用 {{变量名}} 语法)
PromptTemplate promptTemplate = PromptTemplate.from(
"你是一位专业的{{profession}}。请用{{style}}的语气回答以下问题:\n\n{{question}}"
);
// 2. 准备变量值
Map<String, Object> variables = new HashMap<>();
variables.put("profession", "历史老师");
variables.put("style", "通俗易懂");
variables.put("question", "秦始皇统一六国是哪一年?");
// 3. 应用变量,生成最终提示词
Prompt prompt = promptTemplate.apply(variables);
// 4. 发送到模型
String response = model.generate(prompt.text());
System.out.println("提示词: \n" + prompt.text());
System.out.println("\n响应: \n" + response);
}
}
输出示例:
提示词:
你是一位专业的历史老师。请用通俗易懂的语气回答以下问题:
秦始皇统一六国是哪一年?
响应:
秦始皇统一六国是在公元前221年。经过多年的征战,秦国最终消灭了其他六个诸侯国(齐、楚、燕、韩、赵、魏),建立了中国历史上第一个统一的中央集权制国家。
简化语法(单个变量)
对于只有一个变量的情况,可以使用 {``{it}} 作为占位符:
java
// 单变量模板
PromptTemplate template = PromptTemplate.from("将以下文本翻译成英文:{{it}}");
// 直接传入字符串
Prompt prompt = template.apply("你好,世界");
String response = model.generate(prompt.text());
AI Service 中的提示词注解
@SystemMessage 和 @UserMessage
在 AI Service 中,可以使用注解优雅地定义提示词。
代码示例 (参考:tutorials/src/main/java/_08_AIServiceExamples.java)
java
package dev.langchain4j.example;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;
public class AnnotationPromptExample {
// 1. 系统消息:定义 AI 的角色和行为
interface Translator {
@SystemMessage("你是一位专业的翻译,精通多种语言。")
@UserMessage("将以下文本翻译成{{language}}:{{text}}")
String translate(@V("text") String text, @V("language") String language);
}
// 2. 多行提示词
interface Poet {
@SystemMessage({
"你是一位才华横溢的诗人。",
"你擅长创作各种风格的诗歌。",
"你的作品意境深远、文字优美。"
})
@UserMessage("请写一首关于{{topic}}的{{style}}诗")
String writePoem(@V("topic") String topic, @V("style") String style);
}
// 3. 动态系统消息
interface Assistant {
@SystemMessage("你是一位{{role}}。你的专长是{{expertise}}。")
String chat(@V("role") String role,
@V("expertise") String expertise,
String question);
}
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.build();
// 使用翻译器
Translator translator = AiServices.create(Translator.class, model);
String translation = translator.translate("春天来了", "English");
System.out.println("翻译: " + translation);
// 使用诗人
Poet poet = AiServices.create(Poet.class, model);
String poem = poet.writePoem("月亮", "古体");
System.out.println("\n诗歌:\n" + poem);
// 使用动态助手
Assistant assistant = AiServices.create(Assistant.class, model);
String answer = assistant.chat(
"数学老师",
"代数和几何",
"什么是勾股定理?"
);
System.out.println("\n回答:\n" + answer);
}
}
@V 注解详解
@V 注解用于将方法参数映射到提示词模板中的变量:
java
interface Calculator {
@UserMessage("计算 {{a}} + {{b}} 的结果")
String add(@V("a") int firstNumber, @V("b") int secondNumber);
}
// 调用
Calculator calc = AiServices.create(Calculator.class, model);
String result = calc.add(5, 3); // "计算 5 + 3 的结果"
使用 {{it}} 简化单参数
当只有一个参数时,可以省略 @V,使用 {``{it}}:
java
interface Summarizer {
@UserMessage("请用一句话总结:{{it}}")
String summarize(String text);
}
// 调用
Summarizer summarizer = AiServices.create(Summarizer.class, model);
String summary = summarizer.summarize("这是一篇很长的文章内容...");
结构化提示词(Structured Prompts)
使用类定义复杂提示词
对于复杂的提示词,可以使用类来组织结构:
java
package dev.langchain4j.example;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.input.structured.StructuredPrompt;
import dev.langchain4j.model.input.structured.StructuredPromptProcessor;
import dev.langchain4j.model.openai.OpenAiChatModel;
import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;
public class StructuredPromptExample {
// 1. 定义结构化提示词类
@StructuredPrompt("创作一首{{style}}诗,主题是{{topic}},要求:{{requirements}}")
static class CreatePoemPrompt {
private String style;
private String topic;
private String requirements;
public CreatePoemPrompt(String style, String topic, String requirements) {
this.style = style;
this.topic = topic;
this.requirements = requirements;
}
// Getters
public String getStyle() { return style; }
public String getTopic() { return topic; }
public String getRequirements() { return requirements; }
}
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.build();
// 2. 创建提示词实例
CreatePoemPrompt promptData = new CreatePoemPrompt(
"现代诗",
"科技与人性",
"不少于4行,富有哲理"
);
// 3. 处理结构化提示词
String promptText = StructuredPromptProcessor.toPrompt(promptData).text();
// 4. 发送到模型
String poem = model.generate(promptText);
System.out.println("提示词: " + promptText);
System.out.println("\n生成的诗:\n" + poem);
}
}
Few-Shot 学习(示例学习)
通过提供示例,引导模型生成期望的输出格式。
代码示例 (参考:tutorials/src/main/java/_06_FewShot.java)
java
package dev.langchain4j.example;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import java.util.ArrayList;
import java.util.List;
import static dev.langchain4j.model.openai.OpenAiChatModelName.GPT_4_O_MINI;
public class FewShotExample {
public static void main(String[] args) {
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.build();
// 1. 构建消息列表
List<ChatMessage> messages = new ArrayList<>();
// 系统消息:定义任务
messages.add(SystemMessage.from("你是一个情感分析助手。请将文本分类为:积极、消极或中性。"));
// Few-shot 示例
messages.add(UserMessage.from("今天天气真好!"));
messages.add(AiMessage.from("积极"));
messages.add(UserMessage.from("这个产品质量太差了。"));
messages.add(AiMessage.from("消极"));
messages.add(UserMessage.from("会议将在下午三点开始。"));
messages.add(AiMessage.from("中性"));
// 实际要分类的文本
messages.add(UserMessage.from("我对这次旅行非常满意!"));
// 2. 发送所有消息
String response = model.generate(messages).content().text();
System.out.println("情感分类结果: " + response); // 输出: 积极
}
}
AI Service 中使用 Few-Shot
java
interface SentimentAnalyzer {
@SystemMessage("你是情感分析助手,分类为:积极、消极或中性")
@UserMessage({
"示例1:",
"输入: 今天天气真好!",
"输出: 积极",
"",
"示例2:",
"输入: 这个产品质量太差了",
"输出: 消极",
"",
"示例3:",
"输入: 会议将在下午三点开始",
"输出: 中性",
"",
"现在请分析:{{it}}"
})
String analyze(String text);
}
提示词最佳实践
1. 清晰的角色定义
java
@SystemMessage({
"你是一位经验丰富的 Java 架构师。",
"你有 15 年的大型系统设计经验。",
"你擅长性能优化和高并发架构。",
"请用专业但易懂的语言回答问题。"
})
interface JavaArchitect {
String advise(String question);
}
2. 明确的输出格式
java
@UserMessage({
"请分析以下代码的时间复杂度。",
"",
"代码:",
"{{code}}",
"",
"请按以下格式回答:",
"1. 时间复杂度:O(...)",
"2. 空间复杂度:O(...)",
"3. 解释:...",
"4. 优化建议:..."
})
String analyzeComplexity(@V("code") String code);
3. 提供上下文信息
java
@UserMessage({
"项目背景:{{background}}",
"当前问题:{{problem}}",
"约束条件:{{constraints}}",
"",
"请提供解决方案,并说明:",
"1. 方案描述",
"2. 优缺点分析",
"3. 实施步骤"
})
String proposeSolution(
@V("background") String background,
@V("problem") String problem,
@V("constraints") String constraints
);
4. 使用分隔符避免注入
java
@UserMessage({
"请翻译以下内容(内容在 ### 标记之间):",
"",
"###",
"{{userInput}}",
"###",
"",
"目标语言:{{targetLanguage}}"
})
String translate(@V("userInput") String input, @V("targetLanguage") String lang);
提示词工程技巧
技巧 1: 链式思考(Chain of Thought)
引导模型逐步推理:
java
@UserMessage({
"请一步一步分析以下数学问题:",
"",
"问题:{{problem}}",
"",
"请按以下步骤回答:",
"步骤1:理解问题,提取关键信息",
"步骤2:选择合适的方法",
"步骤3:逐步计算",
"步骤4:验证答案",
"最终答案:..."
})
String solveMathProblem(@V("problem") String problem);
技巧 2: 自我检查
让模型检查自己的输出:
java
@UserMessage({
"请完成以下任务:{{task}}",
"",
"完成后,请自我检查:",
"1. 是否完全满足要求?",
"2. 是否有遗漏或错误?",
"3. 是否可以改进?",
"",
"如果发现问题,请修正并重新输出。"
})
String completeTask(@V("task") String task);
技巧 3: 角色扮演
通过具体的角色设定提高回答质量:
java
@SystemMessage({
"你现在是一位苏格拉底式的导师。",
"你不会直接给出答案,而是通过提问引导学生思考。",
"你的问题应该层层深入,帮助学生自己找到答案。"
})
interface SocraticTutor {
String guide(String studentQuestion);
}
技巧 4: 限制输出长度
java
@UserMessage("用不超过 50 字总结:{{text}}")
String summarizeBriefly(@V("text") String longText);
@UserMessage("用 3-5 个要点列出:{{topic}}")
String listKeyPoints(@V("topic") String topic);
多语言提示词
java
interface MultilingualAssistant {
@SystemMessage("You are a multilingual assistant proficient in Chinese and English.")
@UserMessage("Translate to {{targetLang}}: {{text}}")
String translate(@V("text") String text, @V("targetLang") String targetLang);
@SystemMessage("你是一个中英双语助手")
@UserMessage("用{{language}}回答:{{question}}")
String answerInLanguage(
@V("language") String language,
@V("question") String question
);
}
提示词调试技巧
1. 打印最终提示词
java
PromptTemplate template = PromptTemplate.from("角色:{{role}}\n问题:{{question}}");
Map<String, Object> vars = Map.of("role", "医生", "question", "什么是感冒?");
Prompt prompt = template.apply(vars);
System.out.println("=== 最终提示词 ===");
System.out.println(prompt.text());
System.out.println("==================");
String response = model.generate(prompt.text());
2. 使用日志记录
java
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.logRequests(true) // 查看实际发送的提示词
.logResponses(true)
.build();
3. A/B 测试不同提示词
java
String prompt1 = "简单总结:" + text;
String prompt2 = "用一句话概括核心观点:" + text;
String response1 = model.generate(prompt1);
String response2 = model.generate(prompt2);
System.out.println("提示词 A: " + response1);
System.out.println("提示词 B: " + response2);
常见错误与解决方案
错误 1: 变量名不匹配
java
// ❌ 错误
@UserMessage("翻译:{{text}}")
String translate(@V("content") String text); // 变量名不一致
// ✅ 正确
@UserMessage("翻译:{{text}}")
String translate(@V("text") String text);
错误 2: 忘记转义特殊字符
java
// ❌ 如果用户输入包含 {{}},会被当作变量
String userInput = "我想问 {{这个}}"; // 可能导致解析错误
// ✅ 使用分隔符隔离用户输入
@UserMessage({
"用户问题(在分隔符内):",
"---",
"{{userInput}}",
"---"
})
String answer(@V("userInput") String input);
错误 3: 提示词过长导致超出 Token 限制
java
// ✅ 检查 Token 数量
import dev.langchain4j.model.openai.OpenAiTokenizer;
Tokenizer tokenizer = new OpenAiTokenizer(GPT_4_O_MINI);
int tokens = tokenizer.estimateTokenCountInText(promptText);
if (tokens > 4000) {
System.err.println("警告:提示词过长,可能被截断");
}
下一步学习
- 04-AI服务核心模式 - 深入学习 AI Services
- 05-对话记忆管理 - 实现上下文记忆
- 06-工具与函数调用 - 扩展 AI 能力
参考资料
- 示例代码:
tutorials/src/main/java/_03_PromptTemplate.java - AI Service 示例:
tutorials/src/main/java/_08_AIServiceExamples.java - Few-Shot 示例:
tutorials/src/main/java/_06_FewShot.java