LangChain4j 开发Java Agent智能体- 对话与提示词工程(Prompt)

大家好,我是Java1234_小锋老师,最近更新《2027版本 LangChain4j 开发Java Agent 智能体 视频教程》专辑,感谢大家支持。

本课程主要介绍和讲解 LangChain4j 简介,阿里云百炼大模型平台接入,Ollama简介以及安装和使用,HelloWorld 实现,日志配置,集成SpringBoot,Ai Service 使用,对话与提示词工程(Prompt),结构化输出,会话记忆,工具调用(Function Calling),嵌入模型 与向量数据库,RAG(检索增强生成),MCP(模型上下文协议),多模态支持

视频教程+课件+源码打包下载:

链接:https://pan.baidu.com/s/1o-zRfndo1HHrS_uFroOiCw?pwd=1234

提取码:0000

LangChain4j 开发Java Agent智能体- 对话与提示词工程(Prompt)

LangChain4j为复杂的提示词工程和对话管理,提供了一套简洁、声明式的解决方案。其核心是通过AI服务(AiServices) 与消息注解,让开发者只需定义Java接口,即可轻松编排与大模型的交互。

💡 核心概念:对话消息与提示词工程

在LangChain4j中,每一次与大模型的交互,都围绕两类核心消息展开:

  • SystemMessage (系统消息):为AI设定"角色"和"规则",定义其在整个对话中的身份、行为准则、回复风格,它由开发者预先设定,不随用户输入而改变。
  • UserMessage (用户消息):代表用户在当前轮次中提出的具体问题或指令,是对话中的动态输入部分。

🚀 声明式开发:AI服务与消息注解

通过声明一个普通的Java接口,并使用 @SystemMessage@UserMessage 注解,LangChain4j 的 AiServices 会自动生成其实现,并将方法调用转换为与大模型的交互。

1. @SystemMessage:为 AI 设定"人设"

@SystemMessage 注解于接口或方法之上,为后续所有对话奠定行为基础。

  • 支持通过 fromResource 属性从外部文件加载模板,便于管理和更新提示词。
  • @SystemMessage 内容修改后,原有的聊天记忆(ChatMemory)会失效,以确保新"身份"不受旧历史影响。
2. @UserMessage:定义用户输入模板

@UserMessage 注解于方法参数上,用于指示哪个参数是用户输入。

  • 若方法只有一个参数,则它默认作为用户消息,可省略 @UserMessage 注解。
  • 当方法有多个参数时,必须用 @UserMessage 明确指定哪一个是用户输入。
3. 占位符与变量注入:{``{it}}@V

为了构建动态提示词,可以在消息模板中使用占位符,然后在运行时将方法参数注入其中。

  • 当方法只有一个参数时,可以用 {``{it}} 作为默认占位符来引用它。
  • 对于多个参数,需使用 @V("变量名") 注解参数,并在提示词模板中使用 {``{变量名}} 来进行注入。

此外,LangChain4j 还内置了如 {``{current_date}} 的实用占位符,可直接在消息模板中获取当前日期。

💻 实战演练:构建一个智能客服助手

新建一个新的TravelAssistantService.我们使用openAI方式,流式响应输出

java 复制代码
package com.java1234.service;

import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.spring.AiService;
import dev.langchain4j.service.spring.AiServiceWiringMode;
import reactor.core.publisher.Flux;

/**
 * 旅游助手
 */
@AiService(
        wiringMode = AiServiceWiringMode.EXPLICIT, // 手动指定接入模型 手动装配
        streamingChatModel = "openAiStreamingChatModel"
)
public interface TravelAssistantService {

    @SystemMessage("你是一位专业的旅游顾问,请用专业、热情的语气回答问题。")
    Flux<String> chat(String userMessage);
}

再新建一个MyTravelChatController

java 复制代码
package com.java1234.controller;

import com.java1234.service.TravelAssistantService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/travel")
public class MyTravelChatController {

    @Autowired
    private TravelAssistantService travelAssistantService;

    @RequestMapping(value = "/chat",produces = "text/html;charset=utf-8")
    public Flux<String> chat(String question) {
        return travelAssistantService.chat(question);
    }

}

浏览器请求测试:http://localhost:8080/travel/chat?question=南通有哪些好玩的地方?

我们看下请求日志,role:system 就是系统设定,role:user就是用户问题

大模型进行了专业友好的响应:

我们在看一个 @UserMessage 作为用户提示词模板的实例。

java 复制代码
package com.java1234.service;

import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.spring.AiService;
import dev.langchain4j.service.spring.AiServiceWiringMode;
import reactor.core.publisher.Flux;

/**
 * 旅游助手
 */
@AiService(
        wiringMode = AiServiceWiringMode.EXPLICIT, // 手动指定接入模型 手动装配
        streamingChatModel = "openAiStreamingChatModel"
)
public interface TravelAssistantService {

    /**
     *  --- 场景1: 简单问答 ---
     * 注意:由于只有一个参数,@UserMessage 注解可以省略,框架会自动将参数视为用户消息
     * @param userMessage
     * @return
     */
    @SystemMessage("你是一位专业的旅游顾问,请用专业、热情的语气回答问题。")
    Flux<String> chat(String userMessage);

    /**
     *  --- 场景2: 结构化评价分析 (使用 {{it}} 占位符) ---
     *  注解 @UserMessage,并通过 {{it}} 指定用户输入的位置
     * @param review
     * @return
     */
    @UserMessage("分析以下旅游评价的正面或负面情感:\n\n评价:{{it}}")
    Flux<String> analyzeSentiment(String review);
}

MyTravelChatController 里在加下analyze方法:

java 复制代码
package com.java1234.controller;

import com.java1234.service.TravelAssistantService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/travel")
public class MyTravelChatController {

    @Autowired
    private TravelAssistantService travelAssistantService;

    @RequestMapping(value = "/chat",produces = "text/html;charset=utf-8")
    public Flux<String> chat(String question) {
        return travelAssistantService.chat(question);
    }

    @RequestMapping(value = "/analyze",produces = "text/html;charset=utf-8")
    public Flux<String> analyze(String review) {
        return travelAssistantService.analyzeSentiment(review);
    }

}

浏览器输入测试:http://localhost:8080/travel/analyze?review=黄山真是太美了

浏览器返回:

最后我们在看一个@SystemMessage和@UserMessage,以及@V注解参数使用的示例:

java 复制代码
package com.java1234.service;

import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import dev.langchain4j.service.spring.AiService;
import dev.langchain4j.service.spring.AiServiceWiringMode;
import reactor.core.publisher.Flux;

/**
 * 旅游助手
 */
@AiService(
        wiringMode = AiServiceWiringMode.EXPLICIT, // 手动指定接入模型 手动装配
        streamingChatModel = "openAiStreamingChatModel"
)
public interface TravelAssistantService {

    /**
     *  --- 场景1: 简单问答 ---
     * 注意:由于只有一个参数,@UserMessage 注解可以省略,框架会自动将参数视为用户消息
     * @param userMessage
     * @return
     */
    @SystemMessage("你是一位专业的旅游顾问,请用专业、热情的语气回答问题。")
    Flux<String> chat(String userMessage);

    /**
     *  --- 场景2: 结构化评价分析 (使用 {{it}} 占位符) ---
     *  注解 @UserMessage,并通过 {{it}} 指定用户输入的位置
     * @param review
     * @return
     */
    @UserMessage("分析以下旅游评价的正面或负面情感:\n\n评价:{{it}}")
    Flux<String> analyzeSentiment(String review);

    /**
     *  --- 场景3: 动态定制行程单 (使用 @V 注入多参数) ---
     *  使用 @UserMessage 明确指定用户输入是问题部分,并用 @V 注入其他变量
     * @param destination
     * @param days
     * @param preference
     * @return
     */
    @SystemMessage("你是一个旅行社的智能行程规划系统。")
    @UserMessage("根据以下目的地:{{destination}},天数:{{days}},偏好:{{preference}},生成一份详细的旅行计划。")
    Flux<String> planTrip(@V("destination") String destination, @V("days") int days, @V("preference") String preference);
}

MyTravelChatControllerf类加下plan方法:

java 复制代码
package com.java1234.controller;

import com.java1234.service.TravelAssistantService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/travel")
public class MyTravelChatController {

    @Autowired
    private TravelAssistantService travelAssistantService;

    @RequestMapping(value = "/chat",produces = "text/html;charset=utf-8")
    public Flux<String> chat(String question) {
        return travelAssistantService.chat(question);
    }

    @RequestMapping(value = "/analyze",produces = "text/html;charset=utf-8")
    public Flux<String> analyze(String review) {
        return travelAssistantService.analyzeSentiment(review);
    }

    @RequestMapping(value = "/plan",produces = "text/html;charset=utf-8")
    public Flux<String> plan() {
        return travelAssistantService.planTrip("成都", 2, "美食和熊猫");
    }


}

最后我们测试下:http://localhost:8080/travel/plan

结构化输出

LangChain4j 的结构化输出功能,能将大语言模型(LLM)生成的 JSON 文本自动转换为 Java 对象,让 Java 开发者能像调用普通方法一样获取结果,无需手动处理 JSON 或使用特定 Prompt。

结构化输出的三种方式

LangChain4j 主要提供三种实现结构化输出的方式,它们在可靠性和使用场景上有所区别。

方式 可靠性 原理与机制 适用场景
JSON Schema ⭐ 最可靠 将 JSON Schema 作为API专用属性传递给支持的模型,约束力最强。 追求高精度、高可靠性,并使用了支持的模型(如 OpenAI、Azure OpenAI 等)。
JSON Mode + Prompting ⭐⭐ 中等 强制 LLM 输出 JSON,但仍需在 Prompt 中包含 Schema 说明。 模型部分支持 JSON 模式,可靠性要求不是首要时。
Prompting Only ⭐ 最弱 仅通过 Prompt 要求 LLM 输出特定格式,无底层机制保障。 兼容性要求高,或作为不支持 JSON Schema 的模型的备选方案。

具体示例

第一步:第一数据模型

java 复制代码
package com.java1234.model;

import dev.langchain4j.model.output.structured.Description;

import java.util.List;

// 使用 Java 16+ 的 Record 特性,编译器会自动生成构造器、equals/hashCode等方法
@Description("按主题推荐的书籍列表")
public record TopicBooks(
        @Description("用户指定的书籍主题,例如:Java 并发、Spring Boot") String topic,
        @Description("推荐书目列表,每项格式:书名 - 作者,推荐 3~5 本") List<String> books
) {}

第二步:定义AI Service接口

java 复制代码
package com.java1234.service;

import com.java1234.model.TopicBooks;
import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;
import dev.langchain4j.service.spring.AiService;
import dev.langchain4j.service.spring.AiServiceWiringMode;


/**
 * 图书助手
 */
@AiService(
        wiringMode = AiServiceWiringMode.EXPLICIT, // 手动指定接入模型 手动装配
        chatModel = "openAiChatModel" // 指定模型
)
public interface BookAssistantService {

    @SystemMessage("你是一位资深图书推荐专家,只推荐真实存在的经典书籍。")
    @UserMessage("请根据主题「{{topic}}」推荐相关书籍。")
    TopicBooks recommendBooks(@V("topic") String topic);

}

第三步:定义MyBookChatController

java 复制代码
package com.java1234.controller;

import com.java1234.model.TopicBooks;
import com.java1234.service.BookAssistantService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/book")
public class MyBookChatController {

    @Autowired
    private BookAssistantService bookAssistantService;


    @RequestMapping("/recommend")
    public String recommend() {
        String topic="Java";
        TopicBooks topicBooks = bookAssistantService.recommendBooks(topic);
        System.out.println(topicBooks);
        return "ok";
    }


}

我们来测试下,浏览器输入:http://localhost:8080/book/recommend

运行输出:可以看到请求的时候,就约定大模型返回的json格式

复制代码
2026-06-02T19:34:30.765+08:00  INFO 19464 --- [nio-8080-exec-1] d.l.http.client.log.LoggingHttpClient    : HTTP request:
- method: POST
- url: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
- headers: [Authorization: Beare...bd], [User-Agent: langchain4j-openai], [Content-Type: application/json]
- body: {
  "model" : "qwen3.6-plus",
  "messages" : [ {
    "role" : "system",
    "content" : "你是一位资深图书推荐专家,只推荐真实存在的经典书籍。"
  }, {
    "role" : "user",
    "content" : "请根据主题「Java」推荐相关书籍。\nYou must answer strictly in the following JSON format: {\n\"topic\": (用户指定的书籍主题,例如:Java 并发、Spring Boot; type: string),\n\"books\": (推荐书目列表,每项格式:书名 - 作者,推荐 3~5 本; type: array of string)\n}"
  } ],
  "temperature" : 0.7,
  "stream" : false
}

2026-06-02T19:34:42.624+08:00  INFO 19464 --- [nio-8080-exec-1] d.l.http.client.log.LoggingHttpClient    : HTTP response:
- status code: 200
- headers: [x-request-id: 03172ed5-4967-9959-9927-34f9f3295e55], [date: Tue, 02 Jun 2026 11:34:42 GMT], [x-dashscope-call-gateway: true], [server: istio-envoy], [x-envoy-upstream-service-time: 11146], [transfer-encoding: chunked], [vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding], [content-type: application/json], [req-arrive-time: 1780400071309], [req-cost-time: 11153], [resp-start-time: 1780400082463]
- body: {"choices":[{"message":{"content":"```json\n{\n  \"topic\": \"Java\",\n  \"books\": [\n    \"Java核心技术 卷I - Cay S. Horstmann\",\n    \"Effective Java(第3版) - Joshua Bloch\",\n    \"Java并发编程实战 - Brian Goetz\",\n    \"Spring实战(第5版) - Craig Walls\"\n  ]\n}\n```","reasoning_content":"嗯,用户让我根据"Java"主题推荐相关书籍。首先,我需要确定用户的具体需求。他们可能刚开始学Java,或者想深入某个领域,比如并发编程、框架应用等。不过用户只提到了"Java"这个主题,没有更具体的细分,所以我得考虑推荐一些经典且覆盖面广的书籍。\n\n首先想到的是《Java核心技术》,这本书分为卷I和卷II,是学习Java基础的核心教材,适合初学者和有一定基础的读者。作者Cay S. Horstmann很有名,内容全面,应该不错。\n\n接下来,关于设计模式和最佳实践,《Effective Java》是必读的。Joshua Bloch写的这本书,第三版更新到Java 9,涵盖了现代Java的最佳实践,对提升代码质量很有帮助。\n\n然后,并发编程是Java的重要部分,用户可能需要这方面的资料。《Java并发编程实战》由Brian Goetz等人合著,是并发领域的权威书籍,详细讲解了并发原理和实用技巧,虽然有点老,但内容依然适用。\n\n另外,Spring框架在Java开发中非常流行,所以推荐《Spring in Action》。Craig Walls的这本书从基础到高级,适合想学习Spring生态的开发者,尤其是Spring Boot和微服务部分。\n\n最后,考虑是否要加入更深入的书籍,比如JVM相关的,但用户可能更需要实用和广泛认可的。不过四本可能够了,用户要求3-5本。检查一下这些书是否都是经典且真实存在,作者是否正确。确认无误后,按格式整理成JSON。确保书名和作者正确,顺序合理,覆盖基础、最佳实践、并发和框架应用,这样应该能满足大多数Java学习者的需求。","role":"assistant"},"finish_reason":"stop","index":0,"logprobs":null}],"object":"chat.completion","usage":{"prompt_tokens":107,"completion_tokens":433,"total_tokens":540,"completion_tokens_details":{"reasoning_tokens":346,"text_tokens":433},"prompt_tokens_details":{"text_tokens":107}},"created":1780400082,"system_fingerprint":null,"model":"qwen3.6-plus","id":"chatcmpl-03172ed5-4967-9959-9927-34f9f3295e55"}

TopicBooks[topic=Java, books=[Java核心技术 卷I - Cay S. Horstmann, Effective Java(第3版) - Joshua Bloch, Java并发编程实战 - Brian Goetz, Spring实战(第5版) - Craig Walls]]
相关推荐
SoftLipaRZC1 小时前
C语言动态内存:内存管理完全指南
c语言·开发语言
v***59831 小时前
SpringCloud实战十三:Gateway之 Spring Cloud Gateway 动态路由
java·spring cloud·gateway
星恒随风1 小时前
C++入门(二):函数重载、引用、const引用和 inline 内联函数
开发语言·c++·笔记·学习
MrMonkeyHou1 小时前
Java微服务架构中的双剑合璧:Nacos与Gateway深度解析
java·微服务·架构·gateway
普通网友1 小时前
【python】pyspark.errors.exceptions.base.PySparkRuntimeError [JAVA_GATEWAY_EXITED] Java gateway proce
java·python·gateway
zavoryn1 小时前
Python 面试高频:装饰器、迭代器、生成器和上下文管理器一次讲清
开发语言·python·面试
basketball6161 小时前
C++ 高级编程:1. 多线程基本操作
开发语言·c++
rqtz2 小时前
【机器人】ROS结合Qt开发上位机软件工作空间配置
开发语言·qt·ros
许彰午10 小时前
14_Java泛型完全指南
java·windows·python