☰
Java开发者AI入门:Spring AI与LangChain4j实战指南
2026/11/2 13:30:39 网站建设 项目流程

1. 从写业务代码到跑通第一个AI功能,中间隔着什么

如果你是一个写了三五年 Java 的开发者,最近大概率会有一种隐隐的焦虑:身边做算法的同事在聊 RAG、Agent、向量库,而你每天还在跟 MyBatis 的映射文件和 Spring 的事务传播行为打交道。想入门 AI,打开教程一看全是 Python,PyTorch、Transformers、LangChain,光是环境配置就能劝退一半人。于是很多人卡在第一步:我到底要不要转 Python?

我的结论很直接:绝大多数 Java 开发者入门 AI,不需要转 Python,也不需要从零训练模型。你要做的是把 AI 能力当成一个新的"外部依赖"接进现有的 Spring 体系里,就像当年你接 Redis、接 MQ 一样。真正需要你花时间理解的,是提示词怎么组织、上下文怎么管理、工具怎么调用、结果怎么校验这几件事,而不是反向传播怎么求导。

这篇内容就是给这类人写的:有 Java 基础、熟悉 Spring Boot、想在自己的项目里落地 AI 功能,但不知道从哪下手、用什么库、踩哪些坑。我会把整条路线拆成可执行的阶段,重点讲清楚Spring AI 和 LangChain4j 这两个主流框架怎么选、工具链怎么搭、第一个能跑的功能怎么写,以及那些文档里不会写、只有实际跑过才知道的经验。全程不涉及任何需要特殊网络环境的内容,所有依赖都走公开的 Maven 仓库。

先说清楚一个前提:AI 应用开发和传统后端开发最大的区别在于,你的"下游服务"是不确定的。数据库查询返回什么就是什么,但大模型的输出每次都可能不一样。这个不确定性会渗透到你整个架构设计里——重试策略、结果解析、降级方案、成本控制,全都跟传统 CRUD 不一样。想明白这一点,后面的很多设计选择就顺理成章了。

2. 先搞清楚 Java 在 AI 应用里的真实定位

2.1 你不是在训练模型,你是在编排模型

很多新手一上来就想搞明白 Transformer 架构、注意力机制,结果啃了两周论文,代码一行没写。这是典型的路线错误。Java 开发者在 AI 应用层的角色,本质上是编排者:把大模型、向量数据库、业务系统、外部工具串成一条能完成任务的链路。

打个比方,大模型就像一个知识渊博但记性不太好、还偶尔会胡说八道的顾问。你的工作不是把他脑子重新造一遍,而是:给他准备好参考资料(RAG)、告诉他这次任务的具体要求(提示词工程)、给他配几个能查数据能调接口的助手(Function Calling / Tool)、最后检查他给的答案靠不靠谱(输出校验)。这套活儿,用 Java 干完全没问题,而且因为 Java 的工程化能力强,做企业级落地反而更有优势。

2.2 哪些场景适合 Java 团队先切入

不是所有 AI 功能都值得做。根据我见过的落地案例,Java 团队最容易出成果的方向有这么几类:

场景类型典型例子技术要点落地难度
智能问答基于内部文档的知识库问答RAG、向量检索中
内容生成自动写周报、生成商品描述提示词模板、结构化输出低
信息抽取从合同/简历里抽字段结构化输出、JSON Schema低
智能助手能查订单能改状态的客服Tool Calling、多轮对话高
代码辅助内部代码规范检查、单测生成长上下文、代码理解中

建议从信息抽取或内容生成入手,因为这两个场景对准确性要求相对可控,出错了人工兜底成本低,能让你快速跑通全链路、建立信心。等这套流程熟了,再上 RAG 和 Agent。

2.3 一个容易被忽略的现实:成本和质量是要权衡的

新手最容易犯的错,是拿最强的模型去干最简单的活。我见过一个项目,用顶级模型给每条用户评论做情感分类(正面/负面/中性),一天几万条,账单直接爆炸。实际上这种任务用一个小模型甚至本地跑个小模型就够了。

所以从第一天起,你就要在架构里留出模型可切换的抽象层。这也是为什么我强烈建议用 Spring AI 或 LangChain4j 这类框架,而不是直接裸调 HTTP 接口——它们把模型抽象成了统一的接口,换模型基本只改配置。这个设计决策,会在你后期优化成本时救你的命。

3. Spring AI 和 LangChain4j 到底怎么选

这是被问得最多的问题,没有之一。网上很多对比文章列一堆特性表格,看完还是不知道选哪个。我换个角度,从你的项目现状来给判断依据。

3.1 Spring AI:如果你已经是 Spring 重度用户

Spring AI 最大的优势就是和 Spring 生态无缝。你的ChatClient可以像RestTemplate一样注入,配置写在application.yml里,和现有的@Service、@Configuration风格完全一致。团队里只要会 Spring Boot,上手几乎没有学习成本。

它的核心抽象是ChatClient和ChatModel,调用长这样:

@RestController public class ChatController { private final ChatClient chatClient; public ChatController(ChatClient.Builder builder) { this.chatClient = builder .defaultSystem("你是一个专业的客服助手,回答要简洁准确。") .build(); } @GetMapping("/chat") public String chat(@RequestParam String message) { return chatClient.prompt() .user(message) .call() .content(); } }

看到没,这就是标准的 Spring 风格。如果你团队里有人对 AI 完全没概念,让他看这段代码也能大概明白在干嘛。

Spring AI 的短板在于,它的高级特性(比如复杂的 Agent 编排、多步推理链)相对 LangChain4j 来说还在快速演进中,版本迭代比较快,API 偶尔会有变动。用的时候要留意版本兼容。

3.2 LangChain4j:如果你需要更细的编排控制

LangChain4j 是 LangChain 理念在 Java 上的实现,它的抽象层次更丰富:ChatLanguageModel、EmbeddingModel、EmbeddingStore、AiServices、RetrievalAugmentor等等。如果你要做 RAG、要做带记忆的多轮对话、要做工具调用链,LangChain4j 提供的现成组件更多。

它最有意思的是AiServices这个声明式接口,你可以定义一个 Java 接口,框架自动帮你实现:

interface Assistant { @SystemMessage("你是一个只回答技术问题的助手,其他问题礼貌拒绝。") String chat(@UserMessage String userMessage); } Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(model) .chatMemory(MessageWindowChatMemory.withMaxMessages(10)) .build(); String answer = assistant.chat("Spring 的事务传播行为有哪些?");

这种"接口即 Agent"的写法,对 Java 开发者来说非常自然,比手写一堆 prompt 拼接清爽得多。

3.3 我的实际选择建议

说个实在的判断标准:

  • 项目以 CRUD 为主,只想加个 AI 功能:选 Spring AI。集成成本最低,和现有代码风格统一。
  • 要做 RAG 知识库、多轮对话、工具调用:选 LangChain4j。组件更全,编排更灵活。
  • 两个都想用:其实可以共存,它们底层都是调 HTTP 接口,不冲突。但别在一个功能里混用,容易乱。

还有一个现实因素:看你团队的技术栈惯性。如果团队连 Spring Cloud 都用得很溜,Spring AI 的接受度会高很多;如果团队本来就喜欢用各种独立组件拼装,LangChain4j 更对味。

提示:无论选哪个,都建议先用一个独立的小项目跑通,别一上来就往核心业务里塞。AI 功能的调试成本和传统功能完全不是一个量级。

4. 工具链搭建:从零到跑通第一个调用

4.1 环境准备里最容易忽略的三件事

搭环境这一步,看着简单,但坑不少。我列几个实际踩过的:

第一,JDK 版本。Spring AI 目前主流版本要求 JDK 17 及以上,LangChain4j 也建议 17+。如果你还在用 JDK 8,先升级,别想着凑合。这不是框架挑剔,是因为它们大量用了 record、sealed class、虚拟线程这些新特性。

第二,构建工具的依赖管理。Spring AI 的版本管理建议用 BOM(Bill of Materials),避免各个子模块版本对不上:

<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>

LangChain4j 同理,它也有自己的 BOM。千万别手动一个个指定版本号,模块之间的版本依赖很微妙,用 BOM 能省掉大量排查时间。

第三,API Key 的管理。这是安全红线。绝对不要把 Key 硬编码在代码里,也不要在测试代码里明文写。用环境变量或者配置中心:

spring: ai: openai: api-key: ${AI_API_KEY} base-url: ${AI_BASE_URL}

然后在启动脚本或 IDE 的运行配置里注入环境变量。团队协作时,把.env文件加进.gitignore,提供一个.env.example模板给同事参考。

4.2 第一个能跑的功能:结构化信息抽取

我建议第一个练手项目做信息抽取,因为它最能体现 AI 应用的核心模式,又不需要复杂的编排。比如从一段用户反馈里抽出:产品名称、问题类型、紧急程度、联系方式。

用 Spring AI 的BeanOutputConverter可以直接把模型输出映射成 Java 对象:

public record FeedbackInfo( String productName, String issueType, String urgency, String contact ) {} @GetMapping("/extract") public FeedbackInfo extract(@RequestParam String text) { BeanOutputConverter<FeedbackInfo> converter = new BeanOutputConverter<>(FeedbackInfo.class); String prompt = """ 从下面的用户反馈中抽取信息,严格按照要求的 JSON 格式输出。 反馈内容:%s %s """.formatted(text, converter.getFormat()); String result = chatClient.prompt().user(prompt).call().content(); return converter.convert(result); }

这里有个关键点:converter.getFormat()会自动生成 JSON Schema 描述塞进提示词,告诉模型该输出什么结构。这比你自己手写"请输出 JSON,包含以下字段……"要可靠得多,因为 Schema 是机器生成的,格式更规范。

4.3 跑通之后立刻要做的三件事

很多人跑通第一个 Demo 就以为入门了,其实真正的工程化才刚开始。跑通后立刻做这三件事:

加超时和重试。大模型接口的响应时间波动很大,快的时候一两秒,慢的时候几十秒。必须设置合理的超时,并且对可重试的错误(比如限流、网络抖动)做退避重试。Spring AI 支持通过RetryTemplate配置,LangChain4j 也有类似机制。

加日志和可观测性。把每次调用的输入、输出、耗时、token 消耗都记下来。这不是为了调试,是为了成本核算和质量分析。你会需要知道哪个功能最费钱、哪类问题模型答得最差。

加降级方案。模型服务挂了怎么办?限流了怎么办?必须有兜底逻辑,比如返回缓存结果、走规则引擎、或者给用户一个友好的提示。AI 功能不能成为系统的单点故障。

5. RAG 落地:让模型回答你的私有知识

5.1 RAG 的本质是"开卷考试"

RAG(检索增强生成)这个词听着高大上,本质特别朴素:模型不知道你公司内部的事,那就在提问之前,先把相关资料找出来塞给它。就像开卷考试,允许你带小抄进场。

整个流程分两步:离线索引和在线检索。离线阶段把你的文档切块、向量化、存进向量库;在线阶段把用户问题也向量化,去库里找最相似的几块,拼进提示词一起发给模型。

用 LangChain4j 做一套最小可用的 RAG,核心代码大概是这样:

// 离线:文档入库 EmbeddingModel embeddingModel = OpenAiEmbeddingModel.builder() .apiKey(System.getenv("AI_API_KEY")) .build(); EmbeddingStore<TextSegment> store = new InMemoryEmbeddingStore<>(); DocumentSplitter splitter = DocumentSplitters.recursive(500, 50); List<TextSegment> segments = splitter.split(Document.from("你的文档内容")); List<Embedding> embeddings = embeddingModel.embedAll(segments).content(); store.addAll(embeddings, segments); // 在线:检索 + 生成 ContentRetriever retriever = EmbeddingStoreContentRetriever.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .maxResults(5) .minScore(0.7) .build(); RetrievalAugmentor augmentor = DefaultRetrievalAugmentor.builder() .contentRetriever(retriever) .build();

5.2 切块策略:RAG 效果好坏的第一决定因素

我见过太多 RAG 项目效果差,问题根本不在模型,而在切块。文档切得不好,检索出来的内容驴唇不对马嘴,模型再强也救不回来。

几个实战经验:

块大小别一刀切。500 字符是个常见起点,但不是万能。技术文档、法律条款这种信息密度高的,块可以小一点(300-400);叙述性的内容可以大一点(800-1000)。关键是保证一个块内的内容是语义完整的,别把一句话从中间劈开。

一定要有重叠。相邻块之间留 10%-20% 的重叠,防止关键信息正好卡在边界上被切断。上面代码里的50就是重叠字符数。

按结构切优于按长度切。如果文档有明确的标题层级、段落结构,优先按结构切。Markdown 文档按##切,代码按函数切,效果通常比纯按字符数切好很多。

5.3 检索质量调优:从"能查到"到"查得准"

基础 RAG 跑通后,你会发现检索质量不稳定。这时候有几个调优方向:

调整相似度阈值。minScore设太低会召回一堆无关内容干扰模型,设太高又可能什么都查不到。建议从 0.7 开始,根据实际效果微调。这个值跟你的 embedding 模型有关,换模型要重新调。

混合检索。纯向量检索对关键词不敏感,比如用户搜"错误码 5001",向量检索可能找不准。加上关键词检索(BM25)做混合,效果会明显提升。LangChain4j 支持组合多个 retriever。

重排序(Rerank)。先粗召回 20 条,再用一个重排序模型精排出最相关的 5 条。这一步能显著提升精度,代价是多一次模型调用。对质量要求高的场景值得加。

注意:RAG 不是银弹。如果检索出来的内容本身就是错的或者过时的,模型只会把错误信息包装得更像真的。所以知识库的维护和更新机制,比技术选型更重要。

6. 那些文档不会告诉你的坑

6.1 提示词不是越长越好

新手容易陷入一个误区:把提示词写得越长越详细,模型表现就越好。实际上,过长的提示词会稀释关键信息,模型可能抓不住重点。而且提示词越长,token 消耗越大,成本越高。

我的经验是:核心指令放开头和结尾,因为模型对这两个位置的注意力最强。中间放参考资料。指令要具体、可执行,避免"尽量""适当"这种模糊词。比如别说"回答要简洁",要说"回答控制在 100 字以内"。

6.2 结构化输出会失败,必须做容错

即使你用了 JSON Schema,模型偶尔还是会输出格式不对的内容——多一个逗号、少一个引号、或者干脆输出一段解释文字。所以解析的时候必须 try-catch,失败了要么重试,要么降级。

try { return converter.convert(result); } catch (Exception e) { log.warn("结构化输出解析失败,原始内容:{}", result); // 降级:返回默认值或触发重试 return FeedbackInfo.empty(); }

别指望模型 100% 听话,这是概率系统,不是确定性系统。

6.3 上下文窗口是硬约束,要主动管理

多轮对话场景下,历史消息会越积越多,最终超出模型的上下文窗口。你必须主动管理:要么只保留最近 N 轮,要么对历史做摘要压缩。

LangChain4j 的MessageWindowChatMemory就是干这个的,设置maxMessages后它会自动丢弃最老的消息。但要注意,简单丢弃可能导致上下文断裂,更好的做法是对早期对话做摘要,保留关键信息。

6.4 流式输出能极大改善体验

大模型生成完整回答可能要十几秒,用户干等着体验很差。用流式输出(SSE),让文字一个字一个字蹦出来,感知延迟会低很多。Spring AI 和 LangChain4j 都支持流式,Spring AI 配合Flux返回即可:

@GetMapping(value = "/chat/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> chatStream(@RequestParam String message) { return chatClient.prompt().user(message).stream().content(); }

这个改动很小,但对用户体验的提升是质变的。建议所有面向用户的对话功能都上流式。

7. 从能跑到能用:工程化的几个关键决策

7.1 模型抽象层要提前留好

前面提过,一定要在架构里留出模型可切换的抽象。Spring AI 的ChatModel接口、LangChain4j 的ChatLanguageModel接口都是干这个的。你的业务代码只依赖接口,具体用哪个模型通过配置决定。

这样做的好处,在你想换模型、想加多模型路由、想做 A/B 测试的时候会体现得淋漓尽致。我见过一个项目因为把模型调用写死在业务代码里,后来想换个更便宜的模型,改了几十个文件。

7.2 成本控制要从第一天做起

AI 功能的成本是持续的、随用量线性增长的,不像服务器是一次性投入。几个控制手段:

  • 按场景选模型:简单任务用小模型,复杂任务才用大模型。
  • 缓存高频请求:相同或相似的问题,直接返回缓存结果。
  • 限制输入长度:对用户输入做长度限制,避免有人恶意塞超长文本。
  • 监控 token 消耗:把每次调用的 token 数记下来,做用量看板。

7.3 测试策略要调整

传统单元测试那套"给定输入,断言输出"的方法,对 AI 功能基本失效,因为输出不确定。你需要换一套思路:

  • 断言结构而非内容:验证输出是合法 JSON、包含必需字段,而不是断言具体文字。
  • 用评分而非相等:对生成质量用另一个模型打分,或者用关键词覆盖率等指标。
  • 建立回归集:收集一批典型输入和期望输出特征,每次改动后跑一遍,看有没有明显退化。

这套测试体系搭起来费劲,但一旦有了,你改提示词、换模型的时候心里就有底了。

8. 我个人的学习路线建议

说了这么多技术细节,最后聊聊路线。如果你现在完全零基础,我建议按这个顺序走,每一步都动手写代码,别只看不练:

第一阶段(1-2 周):跑通最简单的对话调用,理解提示词、token、上下文窗口这几个概念。用 Spring AI 或 LangChain4j 都行,重点是建立"AI 调用就是个特殊的外部接口"这个认知。

第二阶段(2-3 周):做结构化输出和信息抽取。这一步会让你理解提示词工程的实际价值,以及为什么要做输出校验。

第三阶段(3-4 周):搭一套最小 RAG。重点体会切块策略和检索质量的关系,这是 RAG 的核心。

第四阶段(持续):做工具调用和多步编排。这是 Agent 的基础,也是最难的部分,建议等前三阶段都熟了再碰。

整个过程不需要你去看深度学习论文,也不需要学 Python。你需要的是工程思维 + 对不确定性的容忍度。Java 开发者在这两点上其实有天然优势,因为企业级开发本来就是在和各种不确定性打交道。

我自己的体会是,入门 AI 最大的障碍不是技术难度,而是心理上的陌生感。一旦你跑通第一个功能,发现它其实就是个 HTTP 调用加一堆字符串处理,那种神秘感就消失了。剩下的就是不断实践、踩坑、总结。这个领域变化很快,但底层的工程方法论是稳定的,把方法论吃透,工具怎么变都不慌。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询