从 LangChain 到 LangChain4j:Java 开发者的 AI 应用实战指南
如果你已经熟悉 Python 版的 LangChain那 LangChain4j 的核心概念你基本都能对上号。但 Java 生态有它自己的玩法尤其在 Spring Boot 整合、声明式 API 和工具调用方面LangChain4j 的设计更贴合 Java 开发者的习惯。一、为什么是 LangChain4jJava 调用大模型的主流框架有两个LangChain4j和Spring AI。如果你是 Spring 生态的重度用户两者都可以选。LangChain4j 的优势在于与 LangChainPython概念高度对应迁移成本低Spring Boot 起步依赖配置即用声明式AiService注解代码极简内置 RAG、Tools、会话记忆等高阶能力官网https://docs.langchain4j.dev二、快速入门5 分钟跑通第一个对话2.1 引入依赖dependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-open-ai/artifactIdversion1.0.1/version/dependencyLangChain4j 使用 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);对比 LangChainPython操作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 引入起步依赖dependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-open-ai-spring-boot-starter/artifactIdversion1.0.1-beta6/version/dependency3.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。四、AiServicesLangChain4j 的灵魂原理动态代理LangChain4j 中AiServices是对 LangChainPython中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一个注解搞定。对比 LangChainPython概念LangChain (Python)LangChain4j (Java)链式调用chain LLMChain | prompt | memoryAiService注解 属性配置装配方式代码串联声明式注解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 依赖dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-webflux/artifactId/dependencydependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-reactor/artifactIdversion1.0.1-beta6/version/dependency5.3 接口返回 FluxAiService( wiringMode AiServiceWiringMode.EXPLICIT, chatModel openAiChatModel, streamingChatModel openAiStreamingChatModel )publicinterfaceConsultantService{ FluxString chat(MemoryId String memoryId, UserMessage String message); }Controller 返回FluxString前端通过 SSE 接收实时推送。六、消息注解SystemMessage 与 UserMessage大模型的行为由消息类型决定。SystemMessage设定 AI 角色和规则UserMessage携带用户输入。6.1 SystemMessage设定 AI 人设// 方式一直接写在注解里SystemMessage(你是志愿填报顾问只回答高考志愿相关问题) FluxString chat(MemoryId String memoryId, UserMessage String message);// 方式二从外部文件加载推荐方便管理长提示词SystemMessage(fromResource system.txt) FluxString chat(MemoryId String memoryId, UserMessage String message);6.2 UserMessage模板化用户消息可以在用户消息前后拼接预设内容通过{{it}}或V注解引用参数// 使用默认占位符 {{it}}UserMessage(你是AI助手。{{it}}) FluxString chat(String message);// 自定义占位符名称UserMessage(你是AI助手。{{msg}}) FluxString 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 会话隔离不同用户不能共享同一个记忆对象。通过ChatMemoryProviderMemoryId实现BeanpublicChatMemoryProvider chatMemoryProvider() {returnmemoryId - MessageWindowChatMemory.builder() .id(memoryId) .maxMessages(20) .build(); }AiService( wiringMode AiServiceWiringMode.EXPLICIT, chatModel openAiChatModel, chatMemoryProvider chatMemoryProvider )publicinterfaceConsultantService{ SystemMessage(fromResource system.txt) FluxString chat(MemoryId String memoryId, UserMessage String message); }LangChain4j 根据memoryId查找或创建对应的ChatMemory对象实现用户间记忆隔离。对比 LangChainPython操作LangChain (Python)LangChain4j (Java)记忆管理ConversationBufferMemoryMessageWindowChatMemory消息窗口ConversationBufferWindowMemory(k20).maxMessages(20)会话隔离手动管理 session_idChatMemoryProviderMemoryId7.3 持久化记忆存到 Redis默认的MessageWindowChatMemory使用内存存储重启即丢失。实现ChatMemoryStore接口即可持久化RepositorypublicclassRedisChatMemoryStoreimplementsChatMemoryStore { AutowiredprivateStringRedisTemplate redisTemplate; OverridepublicListChatMessage getMessages(Object memoryId) { String json redisTemplate.opsForValue().get(memoryId);returnChatMessageDeserializer.messagesFromJson(json); } Overridepublicvoid updateMessages(Object memoryId, ListChatMessage 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 拥有专属知识RAGRetrieval Augmented Generation的本质先检索相关知识再让模型结合知识生成答案。8.1 RAG 工作原理用户提问 → 向量化 → 在向量数据库中检索相似片段 → 把「问题 检索到的片段」一起发给大模型 → 生成答案核心概念-向量文本的数学表示多维坐标中的一个点-余弦相似度衡量两个向量的方向接近程度值越大越相似0~1-向量数据库专门存储和检索向量的数据库Milvus、Chroma、RedisSearch 等8.2 快速入门内存版 RAGdependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-easy-rag/artifactIdversion1.0.1-beta6/version/dependencyBeanpublicEmbeddingStore store() {// 1. 加载文档ListDocument 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 涉及五个核心 APILangChain4j 把大部分细节封装到了EmbeddingStoreIngestor中① 文档加载器加载器用途ClassPathDocumentLoader从 classpath 加载FileSystemDocumentLoader从本地磁盘加载UrlDocumentLoader从 URL 加载② 文档解析器解析器支持格式ApacheTikaDocumentParser默认几乎所有格式ApachePdfBoxDocumentParserPDFApachePoiDocumentParserOffice 文件TextDocumentParser纯文本③ 文档分割器分割器策略DocumentByParagraphSplitter按段落DocumentByLineSplitter按行DocumentBySentenceSplitter按句子DocumentSplitters.recursive()默认段落 → 行 → 句子 → 词逐级递归递归分割器最实用还支持配置片段重叠保持语义连贯DocumentSplitter ds DocumentSplitters.recursive(500, 100);// 500 每个片段最大字符数// 100 相邻片段重叠字符数防止语义断裂④ 向量模型内存版向量模型功能有限生产环境建议替换为百炼的text-embedding-v3langchain4j:open-ai:embedding-model:base-url: https://dashscope.aliyuncs.com/compatible-mode/v1api-key: ${API-KEY}model-name: text-embedding-v3注入后交给EmbeddingStoreIngestor和EmbeddingStoreContentRetrieverAutowiredprivateEmbeddingModel embeddingModel;// 存储时用EmbeddingStoreIngestor.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .build();// 检索时也用EmbeddingStoreContentRetriever.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .build();⑤ 向量数据库内存版InMemoryEmbeddingStore重启即丢生产环境用 RedisSearchdependencygroupIddev.langchain4j/groupIdartifactIdlangchain4j-community-redis-spring-boot-starter/artifactIdversion1.0.1-beta6/version/dependencylangchain4j:community:redis:host: localhostport: 6379配置后自动注入RedisEmbeddingStore替换InMemoryEmbeddingStore即可。8.4 LangChain vs LangChain4j RAG 对比环节LangChain (Python)LangChain4j (Java)文档加载PyPDFLoader/DirectoryLoaderClassPathDocumentLoader/FileSystemDocumentLoader文本分割RecursiveCharacterTextSplitterDocumentSplitters.recursive()向量模型OpenAIEmbeddings()EmbeddingModelyml 配置注入向量数据库FAISS/Chroma/PineconeInMemoryEmbeddingStore/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-ddTHH: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方法。对比 LangChainPython操作LangChain (Python)LangChain4j (Java)工具定义tool装饰器 或StructuredToolToolP注解工具挂载agent Agent(tools[...])AiService(toolsbeanName)参数描述Pydantic BaseModel 的 FieldP(描述)自动执行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)// 系统人设FluxString chat(MemoryId String memoryId, UserMessage String message); }一个接口五个注解属性覆盖了 AI 应用开发的核心能力。十一、总结LangChain vs LangChain4j 核心映射能力LangChain (Python)LangChain4j (Java)模型调用ChatOpenAI()OpenAiChatModel.builder()或 yml 配置链式编排LLMChain \| SequentialChainAiService声明式注解会话记忆ConversationBufferMemoryMessageWindowChatMemoryChatMemoryProvider消息模板ChatPromptTemplateSystemMessage/UserMessage注解RAGRetrievalQA 各种 LoaderEmbeddingStoreIngestorContentRetriever工具调用toolAgentToolPtoolsbeanName流式输出astream()FluxString WebFluxSpring 整合不适用起步依赖 yml 配置即注入LangChain4j 的核心设计哲学用声明式注解替代编程式组装用 Spring 生态替代手动管理。如果你已经理解了 LangChain 的概念迁移到 LangChain4j 只需要换一套 API 风格——底层原理完全一致。