如果你已经熟悉 Python 版的 LangChain,那 LangChain4j 的核心概念你基本都能对上号。但 Java 生态有它自己的玩法,尤其在 Spring Boot 整合、声明式 API 和工具调用方面,LangChain4j 的设计更贴合 Java 开发者的习惯。
一、为什么是 LangChain4j?
Java 调用大模型的主流框架有两个:LangChain4j和Spring AI。如果你是 Spring 生态的重度用户,两者都可以选。LangChain4j 的优势在于:
- 与 LangChain(Python)概念高度对应,迁移成本低
- Spring Boot 起步依赖,配置即用
- 声明式
@AiService注解,代码极简 - 内置 RAG、Tools、会话记忆等高阶能力
官网:https://docs.langchain4j.dev
二、快速入门:5 分钟跑通第一个对话
2.1 引入依赖
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-open-ai</artifactId><version>1.0.1</version></dependency>LangChain4j 使用 OpenAI 兼容协议,所以阿里云百炼、DeepSeek 等平台只需换
baseUrl即可。
2.2 构建模型 & 发起对话
OpenAiChatModel model = OpenAiChatModel.builder() .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1") .apiKey(System.getenv("API-KEY"))// 推荐:从环境变量读取.modelName("qwen-plus") .logRequests(true)// 开发阶段开启日志.logResponses(true) .build(); String result = model.chat("你好,介绍一下自己"); System.out.println(result);对比 LangChain(Python):
| 操作 | LangChain (Python) | LangChain4j (Java) |
|---|---|---|
| 构建模型 | ChatOpenAI(model=..., api_key=...) | OpenAiChatModel.builder()...build() |
| 发起对话 | model.invoke("...") | model.chat("...") |
| 日志调试 | 需手动配置 logging | .logRequests(true).logResponses(true) |
核心差异:LangChain4j 用Builder 模式替代 Python 的关键字参数,日志开关是内建的。
三、Spring Boot 整合:配置驱动
纯 Java 方式能用,但实际项目必然要和 Spring 结合。LangChain4j 提供了起步依赖,做到配置即注入。
3.1 引入起步依赖
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-open-ai-spring-boot-starter</artifactId><version>1.0.1-beta6</version></dependency>3.2 application.yml 配置
langchain4j:open-ai:chat-model:base-url: https://dashscope.aliyuncs.com/compatible-mode/v1api-key: ${API-KEY}model-name: qwen-pluslog-requests: truelog-responses: truelogging:level:dev.langchain4j: debug配置完成后,IOC 容器自动注入OpenAiChatModel对象,直接@Autowired使用。
3.3 接口开发
@RestControllerpublicclassChatController{ @AutowiredprivateOpenAiChatModel model; @RequestMapping("/chat")publicString chat(String message) {returnmodel.chat(message); } }到这里,一个可用的 AI 对话接口就完成了。但直接用model.chat()做高阶功能(会话记忆、RAG、Tools)会很麻烦——所以 LangChain4j 提供了AiServices。
四、AiServices:LangChain4j 的灵魂(原理:动态代理)
LangChain4j 中,AiServices是对 LangChain(Python)中Chain的替代方案。它把模型、记忆、检索、工具等能力封装到一个接口的动态代理中,用起来像调用普通方法一样简单。
4.1 编程式使用
// 1. 声明接口publicinterfaceConsultantService{ String chat(String message); }// 2. 用 AiServices 创建代理对象@ConfigurationpublicclassCommonConfig{ @AutowiredprivateOpenAiChatModel model; @BeanpublicConsultantService consultantService() {returnAiServices.builder(ConsultantService.class) .chatModel(model) .build(); } }4.2 声明式使用(推荐)
更简洁的方式——直接在接口上加@AiService注解,LangChain4j 自动扫描创建代理:
@AiService( wiringMode = AiServiceWiringMode.EXPLICIT,// 手动装配chatModel = "openAiChatModel" )publicinterfaceConsultantService{ String chat(String message); }不需要写@Configuration,不需要手动构建 Bean,一个注解搞定。
对比 LangChain(Python):
| 概念 | LangChain (Python) | LangChain4j (Java) |
|---|---|---|
| 链式调用 | chain = LLMChain | prompt | memory | @AiService注解 + 属性配置 |
| 装配方式 | 代码串联 | 声明式注解,Spring 自动注入 |
| 扩展能力 | 传参给 Chain 构造函数 | @AiService的属性指定 Bean 名 |
LangChain4j 的声明式风格对 Java 开发者更友好——不需要记住 Chain 的嵌套顺序,在注解里指明用哪个组件就行。
五、流式调用:从阻塞到实时
阻塞式调用一次性返回完整结果,用户体验差。流式调用逐 Token 推送,类似打字机效果。
5.1 配置流式模型
langchain4j:open-ai:streaming-chat-model:# 流式模型配置base-url: https://dashscope.aliyuncs.com/compatible-mode/v1api-key: ${API-KEY}model-name: qwen-plus5.2 引入 WebFlux 依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-reactor</artifactId><version>1.0.1-beta6</version></dependency>5.3 接口返回 Flux
@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", streamingChatModel = "openAiStreamingChatModel" )publicinterfaceConsultantService{ Flux<String> chat(@MemoryId String memoryId, @UserMessage String message); }Controller 返回Flux<String>,前端通过 SSE 接收实时推送。
六、消息注解:SystemMessage 与 UserMessage
大模型的行为由消息类型决定。SystemMessage设定 AI 角色和规则,UserMessage携带用户输入。
6.1 SystemMessage:设定 AI 人设
// 方式一:直接写在注解里@SystemMessage("你是志愿填报顾问,只回答高考志愿相关问题") Flux<String> chat(@MemoryId String memoryId, @UserMessage String message);// 方式二:从外部文件加载(推荐,方便管理长提示词)@SystemMessage(fromResource = "system.txt") Flux<String> chat(@MemoryId String memoryId, @UserMessage String message);6.2 UserMessage:模板化用户消息
可以在用户消息前后拼接预设内容,通过{{it}}或@V注解引用参数:
// 使用默认占位符 {{it}}@UserMessage("你是AI助手。{{it}}") Flux<String> chat(String message);// 自定义占位符名称@UserMessage("你是AI助手。{{msg}}") Flux<String> chat(@V("msg") String message);七、会话记忆:从无状态到有上下文
大模型本身没有记忆,每次对话都是独立的。会话记忆的原理是把历史消息一起发给模型,让它"看到"之前的对话。
7.1 基本实现
@BeanpublicChatMemory chatMemory() {returnMessageWindowChatMemory.builder() .maxMessages(20)// 最多保留 20 条,超出淘汰最早的.build(); }@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", chatMemory = "chatMemory"// 注入会话记忆)为什么要限制条数?两个原因:大模型上下文有上限(约 10 万 Token);消息越多,Token 消耗越大,费用越高。
7.2 会话隔离
不同用户不能共享同一个记忆对象。通过ChatMemoryProvider+@MemoryId实现:
@BeanpublicChatMemoryProvider chatMemoryProvider() {returnmemoryId -> MessageWindowChatMemory.builder() .id(memoryId) .maxMessages(20) .build(); }@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", chatMemoryProvider = "chatMemoryProvider" )publicinterfaceConsultantService{ @SystemMessage(fromResource = "system.txt") Flux<String> chat(@MemoryId String memoryId, @UserMessage String message); }LangChain4j 根据memoryId查找或创建对应的ChatMemory对象,实现用户间记忆隔离。
对比 LangChain(Python):
| 操作 | LangChain (Python) | LangChain4j (Java) |
|---|---|---|
| 记忆管理 | ConversationBufferMemory | MessageWindowChatMemory |
| 消息窗口 | ConversationBufferWindowMemory(k=20) | .maxMessages(20) |
| 会话隔离 | 手动管理 session_id | ChatMemoryProvider+@MemoryId |
7.3 持久化:记忆存到 Redis
默认的MessageWindowChatMemory使用内存存储,重启即丢失。实现ChatMemoryStore接口即可持久化:
@RepositorypublicclassRedisChatMemoryStoreimplementsChatMemoryStore { @AutowiredprivateStringRedisTemplate redisTemplate; @OverridepublicList<ChatMessage> getMessages(Object memoryId) { String json = redisTemplate.opsForValue().get(memoryId);returnChatMessageDeserializer.messagesFromJson(json); } @Overridepublicvoid updateMessages(Object memoryId, List<ChatMessage> list) { String json = ChatMessageSerializer.messagesToJson(list); redisTemplate.opsForValue().set(memoryId.toString(), json, Duration.ofDays(1)); } @Overridepublicvoid deleteMessages(Object memoryId) { redisTemplate.delete(memoryId.toString()); } }然后在ChatMemoryProvider中指定使用:
@BeanpublicChatMemoryProvider chatMemoryProvider() {returnmemoryId -> MessageWindowChatMemory.builder() .id(memoryId) .maxMessages(20) .chatMemoryStore(redisChatMemoryStore)// 使用 Redis 存储.build(); }八、RAG 知识库:让 AI 拥有专属知识
RAG(Retrieval Augmented Generation)的本质:先检索相关知识,再让模型结合知识生成答案。
8.1 RAG 工作原理
用户提问 → 向量化 → 在向量数据库中检索相似片段 → 把「问题 + 检索到的片段」一起发给大模型 → 生成答案核心概念:
-向量:文本的数学表示,多维坐标中的一个点
-余弦相似度:衡量两个向量的方向接近程度,值越大越相似(0~1)
-向量数据库:专门存储和检索向量的数据库(Milvus、Chroma、RedisSearch 等)
8.2 快速入门:内存版 RAG
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-easy-rag</artifactId><version>1.0.1-beta6</version></dependency>@BeanpublicEmbeddingStore store() {// 1. 加载文档List<Document> documents = ClassPathDocumentLoader.loadDocuments("content");// 2. 构建内存向量数据库InMemoryEmbeddingStore store =newInMemoryEmbeddingStore();// 3. 分割 + 向量化 + 存储(一步搞定)EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() .embeddingStore(store) .build(); ingestor.ingest(documents);returnstore; } @BeanpublicContentRetriever contentRetriever(EmbeddingStore store) {returnEmbeddingStoreContentRetriever.builder() .embeddingStore(store) .minScore(0.5)// 最低相似度阈值.maxResults(3)// 最多返回 3 个片段.build(); }@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", chatMemoryProvider = "chatMemoryProvider", contentRetriever = "contentRetriever"// 配置检索器)三步搞定:存文档 → 建检索器 → 配到@AiService。
8.3 核心组件详解
RAG 涉及五个核心 API,LangChain4j 把大部分细节封装到了EmbeddingStoreIngestor中:
① 文档加载器
| 加载器 | 用途 |
|---|---|
ClassPathDocumentLoader | 从 classpath 加载 |
FileSystemDocumentLoader | 从本地磁盘加载 |
UrlDocumentLoader | 从 URL 加载 |
② 文档解析器
| 解析器 | 支持格式 |
|---|---|
ApacheTikaDocumentParser(默认) | 几乎所有格式 |
ApachePdfBoxDocumentParser | |
ApachePoiDocumentParser | Office 文件 |
TextDocumentParser | 纯文本 |
③ 文档分割器
| 分割器 | 策略 |
|---|---|
DocumentByParagraphSplitter | 按段落 |
DocumentByLineSplitter | 按行 |
DocumentBySentenceSplitter | 按句子 |
DocumentSplitters.recursive()(默认) | 段落 → 行 → 句子 → 词,逐级递归 |
递归分割器最实用,还支持配置片段重叠保持语义连贯:
DocumentSplitter ds = DocumentSplitters.recursive(500, 100);// 500 = 每个片段最大字符数// 100 = 相邻片段重叠字符数(防止语义断裂)④ 向量模型
内存版向量模型功能有限,生产环境建议替换为百炼的text-embedding-v3:
langchain4j:open-ai:embedding-model:base-url: https://dashscope.aliyuncs.com/compatible-mode/v1api-key: ${API-KEY}model-name: text-embedding-v3注入后交给EmbeddingStoreIngestor和EmbeddingStoreContentRetriever:
@AutowiredprivateEmbeddingModel embeddingModel;// 存储时用EmbeddingStoreIngestor.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .build();// 检索时也用EmbeddingStoreContentRetriever.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .build();⑤ 向量数据库
内存版InMemoryEmbeddingStore重启即丢,生产环境用 RedisSearch:
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-community-redis-spring-boot-starter</artifactId><version>1.0.1-beta6</version></dependency>langchain4j:community:redis:host: localhostport: 6379配置后自动注入RedisEmbeddingStore,替换InMemoryEmbeddingStore即可。
8.4 LangChain vs LangChain4j RAG 对比
| 环节 | LangChain (Python) | LangChain4j (Java) |
|---|---|---|
| 文档加载 | PyPDFLoader/DirectoryLoader | ClassPathDocumentLoader/FileSystemDocumentLoader |
| 文本分割 | RecursiveCharacterTextSplitter | DocumentSplitters.recursive() |
| 向量模型 | OpenAIEmbeddings() | EmbeddingModel(yml 配置注入) |
| 向量数据库 | FAISS/Chroma/Pinecone | InMemoryEmbeddingStore/RedisEmbeddingStore |
| 检索器 | retriever = vectorstore.as_retriever() | EmbeddingStoreContentRetriever |
| 整合方式 | RetrievalQA.from_chain_type() | @AiService(contentRetriever=...) |
关键差异:LangChain4j 用@AiService注解的contentRetriever属性挂载检索器,比 Python 的 Chain 组装更简洁。
九、Tools 工具:让 AI 调用你的代码
Tools(原 Function Calling)让大模型能调用你定义的 Java 方法。典型场景:AI 在对话中识别用户意图,自动调用预约接口写入数据库。
9.1 工作原理
用户提问 → 大模型判断是否需要调用工具 → 返回工具名称 + 参数 → AI 应用执行工具方法 → 把执行结果发回大模型 → 大模型生成最终回答大模型不直接执行你的代码,它只是告诉你"该调用哪个方法、传什么参数",由你的程序执行后把结果回传。
9.2 定义工具方法
用@Tool描述方法作用,用@P描述参数含义:
@ComponentpublicclassReservationTool{ @AutowiredprivateReservationService reservationService; @Tool("预约志愿填报服务")publicvoid addReservation( @P("考生姓名") String name, @P("考生性别") String gender, @P("考生手机号") String phone, @P("预约沟通时间,格式:yyyy-MM-dd'T'HH:mm") String communicationTime, @P("考生所在省份") String province, @P("考生预估分数") Integer estimatedScore ) { Reservation reservation =newReservation(null, name, gender, phone, LocalDateTime.parse(communicationTime), province, estimatedScore); reservationService.insert(reservation); } @Tool("根据考生手机号查询预约单")publicReservation findReservation(@P("考生手机号") String phone) {returnreservationService.findByPhone(phone); } }9.3 配置工具
@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", streamingChatModel = "openAiStreamingChatModel", chatMemoryProvider = "chatMemoryProvider", contentRetriever = "contentRetriever", tools = "reservationTool"// 挂载工具)用户说"我想预约,我叫张三,电话13800000001",大模型会自动解析出参数并调用addReservation方法。
对比 LangChain(Python):
| 操作 | LangChain (Python) | LangChain4j (Java) |
|---|---|---|
| 工具定义 | @tool装饰器 或StructuredTool | @Tool+@P注解 |
| 工具挂载 | agent = Agent(tools=[...]) | @AiService(tools="beanName") |
| 参数描述 | Pydantic BaseModel 的 Field | @P("描述") |
| 自动执行 | Agent 自动调用 | LangChain4j 自动调用 |
十、全能力配置:最终形态
把所有能力整合到一个@AiService接口上:
@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel",// 对话模型streamingChatModel = "openAiStreamingChatModel",// 流式模型chatMemoryProvider = "chatMemoryProvider",// 会话记忆(Redis 持久化)contentRetriever = "contentRetriever",// RAG 知识库检索tools = "reservationTool"// Tools 工具)publicinterfaceConsultantService{ @SystemMessage(fromResource = "system.txt")// 系统人设Flux<String> chat(@MemoryId String memoryId, @UserMessage String message); }一个接口,五个注解属性,覆盖了 AI 应用开发的核心能力。
十一、总结:LangChain vs LangChain4j 核心映射
| 能力 | LangChain (Python) | LangChain4j (Java) |
|---|---|---|
| 模型调用 | ChatOpenAI() | OpenAiChatModel.builder()或 yml 配置 |
| 链式编排 | LLMChain \| SequentialChain | @AiService声明式注解 |
| 会话记忆 | ConversationBufferMemory | MessageWindowChatMemory+ChatMemoryProvider |
| 消息模板 | ChatPromptTemplate | @SystemMessage/@UserMessage注解 |
| RAG | RetrievalQA+ 各种 Loader | EmbeddingStoreIngestor+ContentRetriever |
| 工具调用 | @tool+Agent | @Tool+@P+tools="beanName" |
| 流式输出 | astream() | Flux<String>+ WebFlux |
| Spring 整合 | 不适用 | 起步依赖 + yml 配置即注入 |
LangChain4j 的核心设计哲学:用声明式注解替代编程式组装,用 Spring 生态替代手动管理。如果你已经理解了 LangChain 的概念,迁移到 LangChain4j 只需要换一套 API 风格——底层原理完全一致。