开头:别让工具拉开你的差距
很多 Java 程序员看到 AI 开发就本能地觉得 “那是 Python 的事”。但随着Spring AI、LangChain4j的成熟,让 Java 程序员在不离开自己技术栈的情况下,就能构建生产级的 AI 应用。
今天带你从零走完这条路:接入大模型、构建知识库、实现 Agent 自动化,每一步都有完整的 SpringBoot 代码,能直接跑通。
一、Spring AI 接入 vLLM
1.1 为什么是 vLLM?
很多教程直接对接 OpenAI,但国内生产环境大多数团队的选择是:私有化部署开源模型 + vLLM 作为推理服务。原因很简单:数据不出内网、成本可控、模型可定制。
vLLM 默认暴露的是OpenAI 兼容接口(/v1/chat/completions),这意味着所有支持 OpenAI 协议的客户端都可以无缝对接,Spring AI 就是其中之一。
1.2 环境准备
依赖版本:
SpringBoot 3.3.x
JDK 17+
Spring AI 1.0.0
pom.xml核心依赖:
<dependencyManagement><dependencies><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-bom</artifactId><version>1.0.0</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-openai-spring-boot-starter</artifactId></dependency></dependencies>
1.3 配置文件
application.yml:
spring:ai:openai:base-url: http://IP:8000api-key: "not-needed"chat:options:model: /home/models/Qwen/Qwen3-14B-AWQtemperature: 0.7max-tokens: 2048
注意:model字段填的是 vLLM 启动时--model参数指定的路径,可通过curl http://IP:8000/v1/models确认。
1.4 最简对话:Hello AI
先跑通最基础的调用,建立信心:
@RestController@RequestMapping("/ai")public class ChatController {private final ChatClient chatClient;public ChatController(ChatClient.Builder builder) {this.chatClient = builder.build();}@GetMapping("/chat")public String chat(@RequestParam String message) {return chatClient.prompt().user(message).call().content();}}
启动项目,访问:
curl "http://localhost:8080/ai/chat?message=你好,用一句话介绍Spring AI"1.5 流式输出(生产必备)
大模型响应慢是常识,流式输出(Streaming)是生产环境的标配:
@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<String> chatStream(@RequestParamString message) {return chatClient.prompt().user(message).stream().content();}
1.6 带系统提示词的对话(业务场景核心)
实际业务中,你需要给模型设定角色和约束:
@RestController@RequestMapping("/ai")public class CustomerServiceController {private final ChatClient chatClient;private static final String SYSTEM_PROMPT = """你是一名专业的电商客服助手,名字叫"小智"。你的职责是:解答用户关于订单、物流、退换货的问题回答简洁友好,每次回复不超过150字""";public CustomerServiceController(ChatClient.Builder builder) {this.chatClient = builder.defaultSystem(SYSTEM_PROMPT).build();}@PostMapping("/customer-service")public String customerService(@RequestBody ChatRequest request) {return chatClient.prompt().user(request.message()).call().content();}public record ChatRequest(String message) {}}
1.7 多轮对话(带记忆)
要实现连续对话,需要引入会话记忆:
@RestController@RequestMapping("/ai")public class MultiTurnChatController {private final ChatClient chatClient;private final Map<String, MessageWindowChatMemory> sessionMemory = new ConcurrentHashMap<>();public MultiTurnChatController(ChatClient.Builder builder) {this.chatClient = builder.build();}@PostMapping("/chat/multi-turn")public String multiTurnChat(@RequestBodyMultiTurnRequest request) {MessageWindowChatMemory memory = sessionMemory.computeIfAbsent(request.sessionId(),id -> MessageWindowChatMemory.withMaxMessages(10));return chatClient.prompt().user(request.message()).advisors(new MessageChatMemoryAdvisor(memory)).call().content();}public record MultiTurnRequest(String sessionId, String message) {}}
1.8 结构化输出(告别解析 JSON 的痛苦)
Spring AI 支持直接将模型输出映射成 Java 对象:
@RestController@RequestMapping("/ai")public class OrderExtractController {private final ChatClient chatClient;public OrderExtractController(ChatClient.Builder builder) {this.chatClient = builder.build();}@PostMapping("/extract-order")public OrderInfo extractOrder(@RequestBody String userDescription) {return chatClient.prompt().system("从用户的描述中提取订单相关信息...").user(userDescription).call().entity(OrderInfo.class);}}
二、LangChain4j 接入 vLLM
2.1 LangChain4j 是什么?
如果说 Spring AI 是 “Spring 官方钦定的 AI 集成方案”,那 LangChain4j 就是 “Java 生态里最接近 LangChain 设计哲学的框架”。它的核心理念是:把 AI 应用开发中所有可复用的模式都抽象成组件,像搭积木一样组合。
2.2 环境准备
pom.xml:
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-spring-boot-starter</artifactId><version>0.36.2</version></dependency><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-open-ai-spring-boot-starter</artifactId><version>0.36.2</version></dependency></dependencies>
2.3 配置文件
application.yml:
langchain4j:open-ai:chat-model:base-url: http://10.8.5.186:8000/v1api-key: "not-needed"model-name: /home/models/Qwen/Qwen3-14B-AWQtemperature: 0.7max-tokens: 2048timeout: 120slog-requests: truelog-responses: true
2.4 LangChain4j 的核心概念:AI Service
核心思想:用一个 Java 接口描述你的 AI 能力,框架自动实现它,就像 MyBatis 的 Mapper 接口一样:
@AiServicepublic interface AssistantService {@SystemMessage("你是一名专业的Java技术顾问,回答简洁专业,不超过200字。")String chat(String userMessage);}@RestController@RequestMapping("/ai")public class AssistantController {@Autowiredprivate AssistantService assistantService;@GetMapping("/chat")public String chat(@RequestParamString message) {return assistantService.chat(message);}}
2.5 流式输出
通过返回类型TokenStream实现:
@AiServicepublic interface StreamingAssistantService {@SystemMessage("你是一名helpful的AI助手。")TokenStream chatStream(String userMessage);}@RestController@RequestMapping("/ai")public class StreamingController {@Autowiredprivate StreamingAssistantService streamingAssistantService;@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public SseEmitter chatStream(@RequestParam String message) {SseEmitter emitter = new SseEmitter(120_000L);streamingAssistantService.chatStream(message).onNext(token -> {try {emitter.send(SseEmitter.event().data(token));} catch (IOException e) {emitter.completeWithError(e);}}).onComplete(response -> {try {emitter.send(SseEmitter.event().name("done").data("[DONE]"));emitter.complete();} catch (IOException e) {emitter.completeWithError(e);}}).onError(emitter::completeWithError).start();return emitter;}}
2.6 多轮对话(带记忆)
直接在 AI Service 接口上声明即可:
@AiServicepublic interface MemoryChatService {@SystemMessage("你是一名友好的AI助手,能记住用户在对话中提到的信息。")String chat(@MemoryId String sessionId, @UserMessage String userMessage);}@Configurationpublic class LangChain4jConfig {@BeanChatMemoryProvider chatMemoryProvider() {return memoryId -> MessageWindowChatMemory.builder().id(memoryId).maxMessages(10).build();}}@RestController@RequestMapping("/ai")public class MemoryChatController {@Autowiredprivate MemoryChatService memoryChatService;@PostMapping("/chat/memory")public String memoryChat(@RequestBodyMemoryChatRequest request) {return memoryChatService.chat(request.sessionId(), request.message());}public record MemoryChatRequest(String sessionId, String message) {}}
2.7 结构化输出
直接把返回类型改成 POJO,框架自动处理:
public record ProductReview(String productName,Integer rating,String sentiment,List<String> highlights,List<String> complaints) {}@AiServicepublic interface ReviewAnalysisService {@SystemMessage("你是一名电商评论分析专家...")ProductReview analyzeReview(String reviewText);}@RestController@RequestMapping("/ai")public class ReviewController {@Autowiredprivate ReviewAnalysisService reviewAnalysisService;@PostMapping("/analyze-review")public ProductReview analyzeReview(@RequestBodyString reviewText) {return reviewAnalysisService.analyzeReview(reviewText);}}
2.8 动态系统提示词(模板变量)
系统提示词可根据业务参数动态生成:
@AiServicepublic interface DynamicAssistantService {@SystemMessage("""你是{{companyName}}的专属客服助手"{{botName}}"。你只负责处理{{category}}类目的商品咨询。当前促销活动:{{promotion}}""")String chat(@V("companyName") String companyName,@V("botName") String botName,@V("category") String category,@V("promotion") String promotion,@UserMessage String userMessage);}
三、选型对比:Spring AI vs LangChain4j,别纠结看场景
3.1 全景对比表
| 对比维度 | Spring AI | LangChain4j |
|---|---|---|
| 主导方 | Spring 官方 | 社区主导 |
| 上手成本 | 极低,配置即用 | 低,接口即契约 |
| 与 Spring 生态融合 | 原生融合 | 良好,有 Starter |
| 工具调用成熟度 | 支持,仍在完善 | 强,核心设计之一 |
| 可测试性 | 一般,需 Mock ChatClient | 强,直接 Mock 接口 |
| 适合场景 | 快速集成、Spring 项目改造 | 复杂 AI 应用、Agent 系统 |
3.2 核心差异深度解析
编程哲学:Spring AI 是配置驱动(命令式),LangChain4j 是声明式(接口即契约)。
工具调用:LangChain4j 的@Tool注解让模型自主决策调用,更接近 Agent 理念。
可测试性:LangChain4j 的 AI Service 是接口,直接 Mock 即可,测试成本更低。
3.3 选型决策树
你的项目是否已经是Spring项目?├─ 否 → 选LangChain4j└─ 是 ├─ 需求简单(对话、问答)→ 选Spring AI ├─ 需要工具调用、Agent → 选LangChain4j └─ 不确定 → 直接用LangChain4j
3.4 可以共存吗?
可以,而且是务实的选择。两个框架可在同一项目中分工:Spring AI 负责简单对话、内容生成;LangChain4j 负责工具调用、Agent。
夜雨聆风