Agent入门开发(3):LangChain4j 应用

在过往的开发实践中,我们手动实现了 HTTP 请求封装、固定格式 JSON 请求体的拼接以及对话消息列表的维护工作,包括系统提示、用户提问和AI回复等内容的组装。这种实现方式导致代码结构臃肿,维护和更新成本较高。为此,我们决定引入新的框架技术,以支持后续功能扩展和性能优化。

1.LangChain4j 和 AiServices

LangChain4j 是适配 Java 生态的大模型应用开发框架,它统一适配市面上不同大模型接口,内置对话记忆管理,支持同步和流式请求处理,同时预留工具调用和RAG 等扩展能力。因为它封装了这些底层通用逻辑,所以我们不用关心这些底层细节,只需要专注AI 人设设定、业务对话逻辑即可。

AiServices 是 LangChain4j 提供的高阶快捷开发组件,也是我们简化编码的核心。它帮我们省去了手动编写请求封装、消息维护、流式回调这些模板代码的过程,只通过定义接口和少量注解,就能让框架自动生成可直接调用的 AI 服务实例。

我们可以具体了解一下定义的接口是什么样的。

java 复制代码
// 自定义对话格式
interface ChatAssistant {
    //注解:嵌入代码的编译 / 运行时配置信息
    @SystemMessage("你是AI助手,请简洁回答问题")
    //LangChain4j 框架定义的流式响应数据类型,用于封装大模型的流式输出结果
    TokenStream streamChat(@UserMessage String userMessage);
}

ChatAssistant 是我们自定义的 AI 服务接口,作用是声明 AI 具备的能力,不需要编写任何方法实现。 AiServices 会读取这个接口,自动生成可运行的 AI 服务实例。

其中例如 @SystemMessage 的注解 是一种嵌入代码的编译或运行时配置信息 ,它不直接执行逻辑 ,仅作为标记性数据 存在,其价值会由框架实现。

@SystemMessage 是语义配置注解 ,用于注入 AI 服务的系统提示词,例如我们写的"你是AI助手,请简洁回答问题"。其作用是规范大模型的响应风格、能力边界与交互规则。

@UserMessage 属于参数语义注解 ,标记参数为用户输入的对话消息,框架会自动将这个字符串封装为 UserMessage 对象,加入对话上下文。

除了对提示词和用户消息的管理,我们还加入了流式输出功能 。之前的自定义 agent 在对话时会一口气输出回答内容,这会带来用户体验问题:如果要输出的内容较多,AI 处理的时间较长,用户会长时间得不到反馈。而 TokenStream------LangChain4j 流式输出的标准类型,能够实现逐字打印的流式对话效果,优化用户体验。

2.对话交互实现

完成接口定义后,我们通过 chat() 方法完成模型初始化、服务组装、交互逻辑的全流程实现。

2.1AI 模型初始化与服务组装
java 复制代码
// 构建流式对话模型
StreamingChatModel model = OpenAiStreamingChatModel.builder()
        .baseUrl(URL)
        .apiKey(API_KEY)
        .temperature(0.7)
        .build();

// 聊天记忆:滑动窗口模式,保留最近10条对话消息
ChatMemory memory = MessageWindowChatMemory.withMaxMessages(10);

// 创建AiServices服务对象,整合模型、记忆、接口契约
ChatAssistant assistant = AiServices.builder(ChatAssistant.class)
        .streamingChatModel(model)
        .chatMemory(memory)
        .build();

我们使用框架提供的 OpenAiStreamingChatModel 适配 DeepSeek 大模型,通过构造器配置接口地址、身份密钥、生成温度这些核心参数,得到一个支持异步流式输出的模型调用对象。

为实现多轮连贯对话,我们配置滑动窗口对话记忆组件MessageWindowChatMemory 会自动保留最近十条对话记录。最后是核心装配环节,将自定义接口契约、流式模型、对话记忆三大组件注入 AiServices 构造器,框架可以通过动态代理自动生成接口实现对象,替代了原生开发中数十行的模板代码。

2.2构建交互流程
java 复制代码
// 初始化控制台输入工具,开启无限循环对话
Scanner scan = new Scanner(System.in);
while (true) {
    String input = scan.nextLine().trim();
    // 调用AI服务,获取流式响应对象
    TokenStream tokenStream = assistant.streamChat(input);

    // 定义流式输出的行为逻辑
    System.out.println("AI:");
    tokenStream.onPartialResponse(partial -> System.out.print(partial));
    tokenStream.onCompleteResponse(response -> System.out.println("\n"));
    tokenStream.onError(throwable -> throwable.printStackTrace());

    // 启动异步流式请求
    tokenStream.start();
}

我们用 while(true) 实现永久循环对话。输入内容后,调用 AI 服务对象发起流式对话请求,框架就会自动完成消息封装、上下文拼接等底层操作,返回流式响应对象。

随后我们配置流式响应回调规则 。由于onPartialResponse onCompleteResponse onError三个方法的参数全部是函数式接口(接口里有且只有 1 个抽象方法且可以加 @FunctionalInterface 标记), 所以可以用 Lambda ((参数) -> { 执行的代码 })简写而不用写繁琐的匿名内部类。

tokenStream.onPartialResponse(partial -> System.out.print(partial));此句注册 AI 实时返回文本片段 的处理规则。AI 流式输出过程中,每生成一小段内容 ,就会自动触发一次。partial是框架自动传递的参数,代表 AI 返回的文本片段

tokenStream.onCompleteResponse(response -> System.out.println("\n"));此句注册AI 完整回答结束 的处理规则。AI 把所有内容全部生成完毕,没有新内容返回时触发。

tokenStream.onError(throwable -> throwable.printStackTrace());此句注册程序执行出错 的处理规则。会在错误发生时触发,打印错误日志。

最后调用 start() 方法启动异步非阻塞的 API 调用,框架在后台接收响应数据并按规则输出,实现流式对话效果。

相关推荐
ch.ju1 小时前
Java程序设计(第3版)第四章——静态部分
java·开发语言
不负岁月无痕2 小时前
STL -- C++ string 类 模拟实现
java·开发语言·c++
身如柳絮随风扬2 小时前
除了 JWT,你还用过哪些认证方案?Spring Security 中如何集成 JWT?
java·后端·spring
吴声子夜歌2 小时前
Java——Apache Commons CSV
java·csv
Anastasiozzzz2 小时前
万字深度实战!AI Agent 接入万物的底层密码:MCP 协议传输机制与开发指南(下篇)
java·开发语言·数据库·人工智能·ai·架构
JAVA面经实录9172 小时前
完整版JVM 深度学习体系(一)
java·jvm
兰令水2 小时前
topcode【随机算法题】【2026.5.17打卡-java版本】
java·算法·leetcode
CoderJia程序员甲2 小时前
GitHub 热榜项目 - 周榜(2026-05-17)
ai·大模型·github·ai教程
Geometry Fu2 小时前
《设计模式》2026编程作业汇总
java·c++·设计模式