Langchain4j 简介 生态定位 在 Java 庞大的企业级生态中,LangChain4j 是 “Java 领域大模型应用开发的第一基础设施”,它就是 Java 版的 LangChain(Python)。在 Java 开发中,如果作一个类比,它就类似于 JDBC 或 Spring Data。大模型厂商(OpenAI、智谱、阿里、DeepSeek、以及本地 Ollama 下的各类大模型)就像各种不同的关系型数据库(MySQL、Oracle、PostgreSQL),其原生 API 各不相同。LangChain4j 抹平了这些差异,提供了一套统一的 Java 抽象接口。它不自己做模型,它只做大模型与企业级 Java 架构之间的 “粘合剂” 与 “立交桥”。
简而言之,LangChain4j 的出现,让 Java 工程师不需要再去卷底层的 Python 算法,而是用最熟悉的面向接口编程、依赖注入、POJO 映射这套标准组合拳,快速把 AI 能力组装进现有的微服务体系中。
开发套路
Low-Level API:类似于 JDBC,适用于动态网关与路由。直接操控原始报文、Token 计数,适合做企业级 LLM 统一网关、多模型动态降级熔断。
High-Level API:类似于 Mybatis 或 Spring Data,日常业务主要用它开发。通过编写 Java 接口加注解,把 Prompt 隐藏在方法之上,像调用普通 RPC 服务一样调用大模型。
Streaming API:利用 WebFlux 或 WebSocket 配合流式接口,实现前端类似 ChatGPT 那样逐字蹦出(SSE)的打字机流式体验。
常见落地应用 在实际生产中,目前阶段围绕 LangChain4j 的玩法主要集中在以下三个方向:
智能客服与知识库(RAG 架构) :这是目前企业落地最多的套路。利用 LangChain4j 的 Embedding 模块,把企业的本地 PDF/Word 文档切片、向量化,存入向量数据库(如 Milvus, Pgvector)。用户提问时,LangChain4j 先去向量库捞出相关片段,再把片段和问题一起喂给大模型,让大模型 “看书答题”。
结构化数据提取与数据看板(Structured Outputs) :利用 LangChain4j 的 AiServices 强类型绑定能力。你可以定义一个 Java POJO(如 Invoice),让大模型去阅读一封杂乱的求职邮件或发票扫描文本,大模型会自动精准抽取出 JSON 并直接映射为 Java 对象。
自动化代理工具箱(Agent + Tool Calling) :将 Java 本地的 Service 方法通过 @Tool 注解暴露给 LangChain4j。大模型在理解用户意图后,会主动决定去调用你的 Java 方法(例如 checkInventory(String itemId)),拿到结果后,再组织语言回复给用户。让大模型拥有了执行具体业务代码的能力。
父项目 POM 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 <properties > <java.version > 17</java.version > <maven.compiler.source > ${java.version}</maven.compiler.source > <maven.compiler.target > ${java.version}</maven.compiler.target > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <project.reporting.outputEncoding > UTF-8</project.reporting.outputEncoding > <spring-boot.version > 3.5.16</spring-boot.version > <spring-ai.version > 1.1.8</spring-ai.version > <langchain4j.version > 1.17.2</langchain4j.version > <langchain4j-community.version > 1.17.2-beta27</langchain4j-community.version > <langgraph4j.version > 1.8.20</langgraph4j.version > <lombok.version > 1.18.32</lombok.version > <spring-boot-maven-plugin.version > 3.4.5</spring-boot-maven-plugin.version > <spring-ai-alibaba.version > 1.1.2.0</spring-ai-alibaba.version > <spring-ai-alibaba-extensions.version > 1.1.2.1</spring-ai-alibaba-extensions.version > <maven-compiler-plugin.version > 3.15.0</maven-compiler-plugin.version > <maven-surefire-plugin.version > 3.2.5</maven-surefire-plugin.version > <maven-source-plugin.version > 3.3.1</maven-source-plugin.version > </properties > <dependencyManagement > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-dependencies</artifactId > <version > ${spring-boot.version}</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > org.springframework.ai</groupId > <artifactId > spring-ai-bom</artifactId > <version > ${spring-ai.version}</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > com.alibaba.cloud.ai</groupId > <artifactId > spring-ai-alibaba-bom</artifactId > <version > ${spring-ai-alibaba.version}</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > com.alibaba.cloud.ai</groupId > <artifactId > spring-ai-alibaba-extensions-bom</artifactId > <version > ${spring-ai-alibaba-extensions.version}</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > dev.langchain4j</groupId > <artifactId > langchain4j-bom</artifactId > <version > ${langchain4j.version}</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > dev.langchain4j</groupId > <artifactId > langchain4j-community-bom</artifactId > <version > ${langchain4j-community.version}</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > org.bsc.langgraph4j</groupId > <artifactId > langgraph4j-bom</artifactId > <version > ${langgraph4j.version}</version > <type > pom</type > <scope > import</scope > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > ${lombok.version}</version > <scope > provided</scope > </dependency > </dependencies > </dependencyManagement > <dependencies > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-api</artifactId > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <scope > provided</scope > </dependency > <dependency > <groupId > org.junit.jupiter</groupId > <artifactId > junit-jupiter-engine</artifactId > <scope > test</scope > </dependency > <dependency > <groupId > org.assertj</groupId > <artifactId > assertj-core</artifactId > <scope > test</scope > </dependency > </dependencies > <build > <pluginManagement > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > <version > ${spring-boot-maven-plugin.version}</version > <executions > <execution > <goals > <goal > repackage</goal > </goals > </execution > </executions > <configuration > <excludeDevtools > true</excludeDevtools > </configuration > </plugin > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-compiler-plugin</artifactId > <version > ${maven-compiler-plugin.version}</version > <configuration > <source > ${java.version}</source > <target > ${java.version}</target > <annotationProcessorPaths > <path > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > ${lombok.version}</version > </path > </annotationProcessorPaths > <compilerArgs > <arg > -parameters</arg > </compilerArgs > </configuration > </plugin > </plugins > </pluginManagement > </build > <repositories > <repository > <id > aliyun-maven</id > <name > aliyun</name > <url > https://maven.aliyun.com/repository/public</url > </repository > <repository > <id > spring-milestones</id > <name > Spring Milestones</name > <url > https://repo.spring.io/milestone</url > <snapshots > <enabled > false</enabled > </snapshots > </repository > <repository > <id > spring-snapshots</id > <name > Spring Snapshots</name > <url > https://repo.spring.io/snapshot</url > <releases > <enabled > false</enabled > </releases > </repository > </repositories > <pluginRepositories > <pluginRepository > <id > aliyun-plugin</id > <name > aliyun plugin</name > <url > https://maven.aliyun.com/repository/public</url > <releases > <enabled > true</enabled > </releases > <snapshots > <enabled > false</enabled > </snapshots > </pluginRepository > </pluginRepositories >
原始低阶和高阶API的使用 依赖配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <dependencies > <dependency > <groupId > dev.langchain4j</groupId > <artifactId > langchain4j-open-ai</artifactId > </dependency > <dependency > <groupId > dev.langchain4j</groupId > <artifactId > langchain4j</artifactId > </dependency > <dependency > <groupId > ch.qos.logback</groupId > <artifactId > logback-classic</artifactId > </dependency > </dependencies >
原始低阶API示例 测试调用本地 ollama 安装的模型
1 2 3 4 5 6 7 8 9 10 11 12 13 public static void test01 () { OpenAiChatModel model = OpenAiChatModel.builder() .baseUrl("http://localhost:11434/v1" ) .apiKey("xxx" ) .modelName("qwen3:4b" ) .timeout(Duration.ofSeconds(300 )) .logRequests(true ) .logResponses(true ) .build(); String response = model.chat("介绍你自己,100字以内" ); log.info("LLM response: {}" , response); }
测试调用本地 ollama 安装的模型(流式响应)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public static void test02 () throws IOException { OpenAiStreamingChatModel model = OpenAiStreamingChatModel.builder() .baseUrl("http://localhost:11434/v1" ) .apiKey("xxx" ) .modelName("qwen3:4b" ) .timeout(Duration.ofSeconds(300 )) .logRequests(true ) .logResponses(true ) .build(); model.chat("介绍你自己,100字以内" , new StreamingChatResponseHandler () { @Override public void onPartialResponse (String token) { System.out.print(token); } @Override public void onCompleteResponse (ChatResponse chatResponse) { System.out.println(chatResponse.aiMessage().text()); } @Override public void onError (Throwable ex) { System.err.println(ex.getMessage()); } }); System.in.read(); }
测试调用远程千问模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public static void test03 () { String apiUrl = "https://dashscope.aliyuncs.com/compatible-mode/v1" ; String apiKey = System.getenv("QWEN_API_KEY" ); String modelName = "qwen3.7-plus" ; OpenAiChatModel model = OpenAiChatModel.builder() .baseUrl(apiUrl) .apiKey(apiKey) .modelName(modelName) .logRequests(true ) .logResponses(true ) .build(); ChatRequest request = ChatRequest.builder() .messages(List.of( SystemMessage.from("你是一个资深 Java 架构师,回答要简洁" ), UserMessage.from("什么是 LangChain4j?" ), AiMessage.from("LangChain4j 是 Java 生态的 LLM 应用框架" ), UserMessage.from("它和 Spring AI 有什么区别?" ) )) .build(); ChatResponse response = model.chat(request); log.info("QWEN response: {}" , response); }
原始高阶API示例 定义接口:
1 2 3 public interface MyChatService { String chat (String question) ; }
测试调用大模型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void test01 () { OpenAiChatModel chatModel = OpenAiChatModel.builder() .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1" ) .apiKey(System.getenv("QWEN_API_KEY" )) .modelName("qwen-plus" ) .logRequests(true ) .logResponses(true ) .build(); MyChatService chatService = AiServices.builder(MyChatService.class) .chatModel(chatModel) .build(); String answer = chatService.chat("介绍 LangChain4j,回答请在100字之内" ); log.info("AI: {}" , answer); }
低阶方式整合spring 依赖配置 1 2 3 4 5 6 7 8 9 10 11 12 13 <dependencies > <dependency > <groupId > dev.langchain4j</groupId > <artifactId > langchain4j-open-ai-spring-boot-starter</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies >
启动项 1 2 3 4 5 6 @SpringBootApplication public class App { public static void main (String[] args) { SpringApplication.run(App.class, args); } }
配置类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 import dev.langchain4j.model.chat.ChatModel;import dev.langchain4j.model.chat.listener.ChatModelErrorContext;import dev.langchain4j.model.chat.listener.ChatModelListener;import dev.langchain4j.model.chat.listener.ChatModelRequestContext;import dev.langchain4j.model.chat.listener.ChatModelResponseContext;import dev.langchain4j.model.openai.OpenAiChatModel;import lombok.extern.slf4j.Slf4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import java.time.Duration;import java.util.UUID;@Slf4j @Configuration public class LLMConfig { @Bean("local") @Primary public ChatModel chatModelLocalQwen () { return OpenAiChatModel.builder() .baseUrl("http://localhost:11434/v1" ) .apiKey("api_key_xxx" ) .modelName("qwen3:4b" ) .timeout(Duration.ofSeconds(300 )) .maxRetries(3 ) .logRequests(true ) .logResponses(true ) .build(); } @Bean("qwen") public ChatModel chatModelQwen () { return OpenAiChatModel.builder() .apiKey(System.getenv("QWEN_API_KEY" )) .modelName("qwen3.7-plus" ) .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1" ) .logRequests(true ) .logResponses(true ) .listeners(new ChatModelListener () { @Override public void onRequest (ChatModelRequestContext requestContext) { String traceId = UUID.randomUUID().toString(); requestContext.attributes().put("traceId" , traceId); log.info("[{}] 请求参数 requestContext:{}" , traceId, requestContext); } @Override public void onResponse (ChatModelResponseContext responseContext) { Object traceId = responseContext.attributes().get("traceId" ); log.info("[{}] 响应结果 response text:{}" , traceId, responseContext.chatResponse().aiMessage().text()); } @Override public void onError (ChatModelErrorContext errorContext) { Object traceId = errorContext.attributes().get("traceId" ); log.info("[{}] 出现异常 error content:{}" , traceId, errorContext.error().getMessage()); } }) .build(); } @Bean("deepseek") public ChatModel chatModelDeepseek () { return OpenAiChatModel.builder() .apiKey(System.getenv("DEEPSEEK_API_KEY" )) .modelName("deepseek-v4-flash" ) .baseUrl("https://api.deepseek.com" ) .logRequests(true ) .logResponses(true ) .build(); } }
业务测试类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @RestController @RequestMapping("/chat") public class HelloController { @Resource @Qualifier("local") private ChatModel localChatModel; @Resource @Qualifier("qwen") private ChatModel qwenChatModel; @Resource @Qualifier("deepseek") private ChatModel deepseekChatModel; @RequestMapping("faq01") public String faq01 (@RequestParam(defaultValue = "10个字以内介绍你自己") String userContent) { return localChatModel.chat(userContent); } @RequestMapping("faq02") public String faq02 (@RequestParam(defaultValue = "10个字以内介绍你自己") String userContent) { ChatResponse response = qwenChatModel.chat(UserMessage.from(userContent)); return "响应结果:" + response.aiMessage().text() + "\n\ntoken 的用量:" + response.tokenUsage(); } @RequestMapping("faq03") public String faq03 (@RequestParam(defaultValue = "10个字以内介绍你自己") String userContent) { return deepseekChatModel.chat(userContent); } }
高阶方式整合 spring 依赖配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <dependencies > <dependency > <groupId > dev.langchain4j</groupId > <artifactId > langchain4j-open-ai-spring-boot-starter</artifactId > </dependency > <dependency > <groupId > dev.langchain4j</groupId > <artifactId > langchain4j-spring-boot-starter</artifactId > </dependency > <dependency > <groupId > dev.langchain4j</groupId > <artifactId > langchain4j-reactor</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-webflux</artifactId > </dependency > </dependencies >
启动项 1 2 3 4 5 6 @SpringBootApplication public class App { public static void main (String[] args) { SpringApplication.run(App.class, args); } }
配置文件 application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 server: port: 8080 langchain4j: open-ai: chat-model: base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 api-key: ${QWEN_API_KEY} model-name: qwen3.7-plus log-requests: true log-responses: true streaming-chat-model: base-url: http://localhost:11434/v1 api-key: api-key-xxx model-name: "qwen3:4b"
使用原始 ChatModel 1 2 3 4 5 6 7 8 9 10 11 12 13 @RestController public class ChatController { private ChatModel chatModel; public ChatController (ChatModel chatModel) { this .chatModel = chatModel; } @GetMapping("/chat") public String model (@RequestParam(value = "message", defaultValue = "Hello") String message) { return chatModel.chat(message); } }
原始 StreamingChatModel 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @RestController public class StreamingChatController { @Resource private StreamingChatModel streamingChatModel; @GetMapping(value = "/chat5", produces = MediaType.TEXT_PLAIN_VALUE) public Flux<String> model (@RequestParam(value = "message", defaultValue = "Hello") String message) { return Flux.<String>create(fluxSink -> { streamingChatModel.chat(message, new StreamingChatResponseHandler () { @Override public void onPartialResponse (String token) { if (!fluxSink.isCancelled()) { fluxSink.next(token); } } @Override public void onCompleteResponse (ChatResponse chatResponse) { fluxSink.complete(); } @Override public void onError (Throwable throwable) { fluxSink.error(throwable); } }); }); } }
使用 @AiService 声明一个 AiService 代理类
1 2 3 4 5 6 7 8 9 10 11 12 import dev.langchain4j.service.spring.AiService;import reactor.core.publisher.Flux;@AiService public interface MyChatService2 { String handleMyChat (String prompt) ; Flux<String> handleMyStreamingChat (String prompt) ; }
业务测试类 ChatController2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @RestController public class ChatController2 { @Resource private MyChatService2 myChatService2; @GetMapping("/chat21") public String model (@RequestParam(value = "message", defaultValue = "Hello") String message) { return myChatService2.handleMyChat(message); } @GetMapping(value = "/chat22", produces = MediaType.TEXT_PLAIN_VALUE) public Flux<String> model22 (@RequestParam(value = "message", defaultValue = "Hello") String message) { return myChatService2.handleMyStreamingChat(message); } }
以上 MyChatService2 代理类除了使用高阶的 @AiService 创建,也可以使用如下方式进行创建,效果是一样的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Configuration public class LLMConfig { @Bean public MyChatService2 myChatService3 (StreamingChatModel localStreamingChatModel) { return AiServices.create(MyChatService2.class, localStreamingChatModel); } }
标题:
Langchain4j - 基础工程的构建以及两套API测试案例