【Langchain4j-Java AI开发】03-提示词与模板

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("警告:提示词过长,可能被截断");
}

下一步学习

参考资料

  • 示例代码: 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
相关推荐
海南java第二人2 小时前
Spring Bean作用域深度解析:从单例到自定义作用域的全面指南
java·后端·spring
cike_y2 小时前
Spring5入门&IOC容器
java·开发语言·spring·jdk·ioc·jdk1.8
你疯了抱抱我2 小时前
【QQ】空间说说批量删除脚本(不用任何额外插件,打开F12控制台即可使用)
开发语言·前端·javascript
彼岸花开了吗2 小时前
构建AI智能体:六十六、智能的边界:通过偏差-方差理论理解大模型的能力与局限
人工智能·python
AlanHou2 小时前
Dify、n8n 还是 Coze?万字长文解析三大主流 AI Agent 平台
人工智能·agent
悟空码字2 小时前
SpringBoot 整合 Nacos,让微服务像外卖点单一样简单
java·spring boot·后端
未知原色2 小时前
前端工程师转型AI的优势与挑战
前端·人工智能
白日做梦Q2 小时前
生成式AI的底层逻辑:GAN、VAE与扩散模型的对比及研究切入点
人工智能·深度学习·机器学习
白日做梦Q2 小时前
深度学习可解释性研究综述:从特征可视化到因果推理
人工智能·深度学习