news 2026/4/3 5:47:45

深入浅出LangChain4J

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入浅出LangChain4J

1.走进LangChain

1.1.什么是LangChain4J?

The goal of LangChain4J is to simplify integrating LLMs into Java applications.

​ -- 《LangChain4J Doc》

LangChain4J就像Java的Spring框架一样,为LLM的接入提供了一套标准的接入能力。LangChain4J是LangChain在Java生态下的具体实现,用于构建基于LLM的应用和Agent系统。

LangChain4J为不同的LLM提供了一个统一的API,屏蔽了底层API供应商的实现和调用差异,开发者可以使用LangChain无缝切换不同的LLM。

2.Architecture of LangChain4J

LangChain4J的架构可以分为两层,分别为高层和底层。

高层AI服务屏蔽了底层实现的细节,开发者可以实现一些业务服务的API和LLM进行交互。

低层具有更高的自由度,你可以任意定义组件的具体实现,控制组件的组合方式等等。

下面,就LangChain4J的核心组件,一一详细介绍。

2.1.Chat and Language Model

一般地,LLMs的API可以分为两类,

  • LanguageModel:输入输出都为String类型,现在使用的越来越少了
  • ChatModel:应用广泛的一类API,接收多个ChatMessage作为输入,输出一个AiMessage,除了文本类型之外,还支持图片、音频、视频等其他模式。

ChatModel是LangChain4J的低层API,提供强大的灵活性和可扩展性。

根据消息来源进行分类,LangChain4J支持以下五种消息类型:

消息类型描述主要方法
UserMessage用户输入的消息数据content(), name(), attributes()
AiMessageAI根据输入数据生成的消息text(), thinking(), toolExceptionRequests(), attributes()
ToolExecutionResultMessage工具执行结果消息
SystemMessage系统发送的消息,可以由开发者自定义
CustomMessage自定义消息
2.2.Chat Memory

我们知道,大模型是无状态的,模型本身并不会记录对话上下文。因此,如果你想要在对话中使用上下文的内容,就必须主动维护管理ChatMessage。但是手动维护比较麻烦,而LangChain4J提供了ChatMemory用来维护管理chatMessage.

2.2.1.History VS Memory

历史记录和记忆听起来似乎是同一种东西,但是对于LLM Agent来说,history和memory具有两种截然不同的语义:

  • history保留了用户和AI的所有会话记录,用户可以在界面中看到
  • memory记录的是专门呈现给大模型使用的信息,使其表现得好像是“记住了”对话的内容,实际底层实现是截然不同的算法。

LangChain4J目前只提供Memroy,而不提供History

下面介绍关于Memory的几点高级特性。

2.2.2.Eviction Policy 淘汰策略

为什么要使用淘汰策略?

  • 存储空间受限:Memory组件可以理解为缓存,当存放的内容超过容量大小的时候,需要使用一定的策略淘汰一些记忆;
  • Token成本昂贵:更多的上下文记忆就代表使用更多的Token,而token的增加会增加每次调用LLM的成本;
  • 控制延迟:发送的LLM的token越多,处理他们所需要的时长越长,则用户等待输出的时间越长

LangChain4J目前支持两种开箱即用的记忆淘汰策略:

  1. 基于消息滑动窗口:使用MessageWindowChatMemory作为滑动窗口,仅保留最近的N条信息,淘汰窗口之外的旧消息;
  2. 基于token的滑动窗口:TokenWindowChatMemory只保留最近的N个token。但是消息是不可再分的,因此如果消息不合适的话,整条消息会直接被丢弃。
2.2.3.Persistence 持久化

默认情况下Memory是存放在内存中的,如果需要保留消息,可以自定义实现MessageStore,将chatMessage存储在数据库中。

class PersistentChatMemroyStore implements ChatMemoryStore { @Override public List<ChatMessage> getMessages(Object memoryId) { } @Override public void updateMessages(Object memoryId, List<ChatMessage> messages) { } @Override public void deleteMessages(Object memoryId) { // TODO: Implement deleting all messages in the persistent store by memory ID. } }
2.2.4.SystemMessage

SystemMessage是一种特殊的消息,具有如下的特性:

  • 一旦添加,就会一直被保留,不会被淘汰策略淘汰
  • 一次只能持有一个SystemMessage
  • SystemMessage具有唯一性,重复的SystemMessage会被忽略,如果不一致,则会覆盖掉之前的SystemMessage
2.2.5.Tool 消息配对

AIMessage 中的ToolExecutionRequestToolExecutionResponse总是成对出现的。如果ToolExecutionRequest被淘汰了,则其对应的ToolExecutionResponse消息也会被自动淘汰。

2.3.Tools(Function Calling)

工具(Tools)允许LLM在必要的时候调用开发者定义的一个或者多个可用工具,工具是一个泛称,可以表示任何东西,例如网页搜索、外部API、或者执行特定的代码等等。

实际上LLM并不会去主动调用工具,而是通过开发人员在业务层接收LLM的回复,根据LLM的意愿进行工具的调用并将执行结果反馈给LLM。

一个良好的工具应当具有以下几个属性:

  1. 清晰明确的工具名称
  2. 工具的具体描述,以及应该何时使用工具;
  3. 每个工具的具体参数;

如果这个工具对于人来说一眼就能理解应该如何使用,那么这个工具对于LLM也是易于使用的。

Tools的定义和使用可以参考文档:LangChain4J Documents

2.4.Agent

3.实战

3.1.ChatModel
3.1.1.基本聊天
public static void main(String[] args) { // 1.创建 chatModel OpenAiChatModel chatModel = OpenAiChatModel.builder() .apiKey(System.getenv("OPENAI_API_KEY")) .baseUrl(System.getenv("OPENAI_BASE_URL")) .modelName(System.getenv("OPENAI_MODEL")) .build(); // 2.使用 chat 方法发起对话 ChatResponse response = chatModel.chat(ChatRequest.builder() .messages(UserMessage.from("Hello, could you introduce yourself ?")) .build()); // 3.控制台打印 System.out.println(response.aiMessage().text()); }
3.1.2.多轮对话

多轮对话和基本对话的实现方式相同,只不过构建对话请求的时候,需要将前文传入到messages中,LLM会参考message得出合理的响应。

private static void chatWithMultipleMessages() { // 1.构建 User 和AI 的多轮对话 UserMessage firstUserMessage = UserMessage.from("Hello, My name is shepi, could you introduce yourself ?"); AiMessage firstAiMessage = CHAT_MODEL.chat( ChatRequest.builder() .messages(firstUserMessage) .build()) .aiMessage(); UserMessage secondUserMessage = UserMessage.from("Please tell me my name"); AiMessage secondAiMessage = CHAT_MODEL.chat( ChatRequest.builder() .messages(firstUserMessage, firstAiMessage, secondUserMessage) .build()).aiMessage(); // 2.控制台打印 System.out.println(secondAiMessage.text()); }
3.2.ChatMemory

ChatMemory可以帮助我们维护上下文,LangChain4J提供了两种开箱即用的窗口聊天记忆

  • MessageWindowChatMemory
  • TokenWindowChatMemory

下面是一个基于消息数量的窗口对话记忆:

public static void main(String[] args) { // 1.新建 messageWindow,滑动窗口最大长度设置为 3 MessageWindowChatMemory chatWindow = MessageWindowChatMemory.builder() .maxMessages(4) .build(); // tryChatWithCommonMessages(chatWindow); // 测试特殊的系统消息 systemMessage tryChatWithSystemMessage(chatWindow); } /** * 系统消息永远不会被驱逐 * @param chatWindow */ private static void tryChatWithSystemMessage(MessageWindowChatMemory chatWindow) { // 创建系统消息 SystemMessage systemMessage = SystemMessage.from("The user talking with you is shepi"); chatWindow.add(systemMessage); System.out.println(systemMessage.text()); for (int i = 0; i < 4; i++) { UserMessage userMessage = null; if (i == 3) { userMessage = UserMessage.from("Please tell me my name"); } else { userMessage = UserMessage.from("let's talk about something interesting"); } System.out.println(userMessage.contents()); chatWindow.add(userMessage); // 使用 chatMemory 对话 AiMessage aiMessage = CHAT_MODEL.chat(ChatRequest.builder().messages(chatWindow.messages()).build()).aiMessage(); System.out.println(aiMessage.text()); chatWindow.add(aiMessage); } } private static void tryChatWithCommonMessages(MessageWindowChatMemory chatWindow) { // 2.模拟进行多轮对话 // 第一轮给出自己的名字,第四轮询问AI我的名字,其他两轮随便聊点什么 for (int i = 0; i < 4; i++) { UserMessage userMessage = null; if (i == 0) { userMessage = UserMessage.from("Hello, My name is shepi, could you introduce yourself ?"); } else if (i == 3) { userMessage = UserMessage.from("Please tell me my name"); } else { userMessage = UserMessage.from("let's talk about something interesting"); } System.out.println(userMessage.contents()); chatWindow.add(userMessage); // 使用 chatMemory 对话 AiMessage aiMessage = CHAT_MODEL.chat(ChatRequest.builder().messages(chatWindow.messages()).build()).aiMessage(); System.out.println(aiMessage.text()); chatWindow.add(aiMessage); } }
3.3.Tools

LangChain中定义Tool非常简单,只需要在工具接口方法上使用注解@Tool("Tool description")即可,下面是一个简答的例子。

public class WeatherService { @Tool("获取指定城市的天气情况") public String getWeather(String city) { // 模拟天气数据 return MessageFormat. format("Today's weather in {0} is sunny with a temperature of 22 degrees.", city); } }
3.4.AiService (Agent 封装)

AiService 是什么?

AiService 是 LangChain4J 提供的高层 API,用于快速构建 Agent 应用。它屏蔽了工具调用的底层细节(如检测 LLM 返回的函数调用请求、执行工具、将结果反馈给 LLM),让开发者可以专注于业务逻辑。

AiService 与 Agent 的关系:

  • AiService 是 LangChain4J 对 Agent 概念的具体实现
  • 它自动完成了 Agent Loop 中的:接收输入 → 判断是否需要 Tool → 调用 Tool → 观察结果 → 生成响应
  • 开发者只需定义接口和 Tool,AiService 会自动完成工具调用的编排

如果想要使用上面创建的 Tool,我们需要在定义AiService时,传入 Tool 对象。

private static final OpenAiChatModel CHAT_MODEL = OpenAiChatModel.builder() .apiKey(System.getenv("OPENAI_API_KEY")) .baseUrl(System.getenv("OPENAI_BASE_URL")) .modelName(System.getenv("OPENAI_MODEL")) .build(); public static void main(String[] args) { // 根据CHAT_MODEL创建一个 chatService ChatAssistant chatService = AiServices.builder(ChatAssistant.class) .chatLanguageModel(CHAT_MODEL) .tools(new WeatherService()) .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) .build(); // 问题 String question = "今天北京什么天气?"; String answer = chatService.chat(question); System.out.println(answer); }

4.流式响应 (Streaming)

LangChain4J 支持流式响应,即 LLM 在生成内容时实时返回每个 token,而不是等待完整响应后再返回。

使用场景
  • 需要实时显示生成过程的场景(如 ChatGPT 的打字机效果)
  • 生成较长内容时提升用户体验
  • 需要提前终止不满意的输出
实现方式

使用StreamingAiServices代替AiServices

private static final OpenAiChatModel CHAT_MODEL = OpenAiChatModel.builder() .apiKey(System.getenv("OPENAI_API_KEY")) .baseUrl(System.getenv("OPENAI_BASE_URL")) .modelName(System.getenv("OPENAI_MODEL")) .build(); public static void main(String[] args) { // 根据CHAT_MODEL创建一个 chatService ChatAssistant chatService = AiServices.builder(ChatAssistant.class) .chatLanguageModel(CHAT_MODEL) .tools(new WeatherService()) .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) .build(); // 问题 String question = "今天北京什么天气?"; String answer = chatService.chat(question); System.out.println(answer); }
流式 vs 非流式
特性非流式 (AiServices)流式 (StreamingAiServices)
响应方式等待完整响应后返回实时返回每个 token
用户体验有等待感实时反馈,体验更好
实现复杂度简单稍复杂(需要处理回调)
适用场景短文本、后台任务长文本、交互式对话


学习资源推荐

如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!​

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示

​因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

四、AI大模型商业化落地方案

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/31 17:08:23

24、25年国自然资助情况详解,医学部最难已跌破9%、青C连创新低

2026年国自然申报进入倒计时&#xff0c;回望近两年资助数据&#xff0c;竞争加剧信号明显。而2026年叠加申请书改版、评审规范收紧等多项新政策&#xff0c;这场科研“突围战”&#xff0c;难度再创新高。从近两年数据看&#xff0c;面上项目2025年资助数量较2024年增长10.96%…

作者头像 李华
网站建设 2026/4/1 16:53:20

对比一圈后,一键生成论文工具,千笔·专业学术智能体 VS Checkjie

随着人工智能技术的迅猛发展&#xff0c;AI辅助写作工具已逐渐成为高校学生完成毕业论文的重要帮手。无论是开题报告、文献综述还是整篇论文的撰写&#xff0c;越来越多的学生开始借助AI工具提升效率、降低写作难度。然而&#xff0c;面对市场上琳琅满目的AI写作平台&#xff0…

作者头像 李华
网站建设 2026/4/1 6:41:52

EL缺陷检测仪

问&#xff1a;光伏EL检测仪的核心定位是什么&#xff1f;答&#xff1a;核心定位是光伏组件失效检测专属设备&#xff0c;主打“高清成像、精准定位、便捷高效”&#xff0c;核心作用是洞察肉眼不可见的组件能量损失&#xff0c;精准捕捉各类核心失效点。它专门解决光伏组件中…

作者头像 李华
网站建设 2026/3/20 0:33:09

绕过 Cloudflare 检测的 Headers 与 JS 挑战:原理、合规边界与实操思路

在现代 Web 爬虫、接口调用与自动化场景中&#xff0c;Cloudflare 已成为最常见的网站安全防护层&#xff0c;其核心拦截手段包括请求 Headers 校验、JS 指纹 / 浏览器环境验证、人机验证&#xff08;CAPTCHA&#xff09;、IP 风控等。很多开发者会遇到 “正常浏览器能访问&…

作者头像 李华
网站建设 2026/3/31 0:17:43

商业照明专业解析:核心指标与光品质的深度剖析

商业照明灯具&#xff0c;是现代商业空间里&#xff0c;不可缺少的重要构成部分&#xff0c;其性能展现&#xff0c;直接对空间氛围、商品展示效果&#xff0c;以及顾客的视觉感受与舒适程度产生影响。和普通家居照明相较&#xff0c;商业照明在光质量、可靠性、光学设计和环境…

作者头像 李华