☰
Java开发者AI入门路线图:Spring AI与LangChain4j实战RAG与Agent
2026/10/1 5:32:50 网站建设 项目流程

1. Java 开发者切入 AI 的真实路径拆解

1.1 为什么 Java 开发者做 AI 总觉得“隔了一层”

我做了十多年 Java 后端,从 SSH 时代一路写到 Spring Boot 微服务,中间也带过不少团队。这两年最常被问的一个问题就是:Java 开发者到底怎么入门 AI?很多人一上来就去啃 Python 的 PyTorch 教程,结果环境配了三天,模型没跑起来,反而把自己搞崩溃了。问题不在于 AI 难,而在于路径选错了。

Java 开发者的核心优势是什么?是工程化能力。你熟悉依赖注入、熟悉分层架构、熟悉事务和并发、熟悉怎么把一个接口稳定地跑在生产环境里。而 AI 应用落地,尤其是大模型应用落地,恰恰最缺的就是工程化。模型本身有开源社区在推,但怎么把它接进现有系统、怎么做知识库检索、怎么保证响应稳定、怎么控制成本,这些全是工程问题。所以 Java 开发者入门 AI,不应该从训练模型开始,而应该从“调用模型 + 编排流程 + 接入业务”这条线切入。

这条路线图大致可以分成四层:第一层是基础认知,搞清楚大模型能做什么、不能做什么;第二层是工具链,选一个顺手的框架把模型调起来;第三层是核心能力,也就是 RAG 和 Agent 这两块;第四层是工程落地,把 AI 能力嵌进 Spring Boot 项目里。下面我按这个顺序,把每一层的关键点、工具选型和踩坑经验都摊开讲。

1.2 路线图全景:从“会调接口”到“能上生产”

先给一张我实际带人用的路线图,按阶段划分,每个阶段都有明确的产出物,避免学了一堆概念却做不出东西。

阶段核心目标关键工具产出物
第一阶段理解大模型交互方式HTTP 客户端、Postman能手动调通一次对话接口
第二阶段用框架封装调用Spring AI、LangChain4j一个可复用的对话服务类
第三阶段接入私有知识向量库、Embedding 模型一个能回答文档问题的 RAG 服务
第四阶段让 AI 自主决策Function Calling、Agent 框架一个能查数据库/调接口的 Agent
第五阶段工程化与优化缓存、限流、监控可上生产的 AI 模块

这个路线图的好处是每一步都有可运行的东西,不会出现“学了两周还在看理论”的情况。我见过太多人卡在第一步,就是因为想一次性把 Transformer 原理搞明白,结果还没写出第一行调用代码就放弃了。先跑起来,再回头补原理,这是 Java 开发者最舒服的节奏。

1.3 工具链选型:Spring AI 还是 LangChain4j

这是被问得最多的问题,没有之一。我的结论是:如果你已经在用 Spring Boot,优先 Spring AI;如果你需要更灵活的链式编排和更丰富的模型支持,选 LangChain4j;两者并不冲突,可以混用。

Spring AI 的优势在于和 Spring 生态无缝集成。它的ChatClient设计非常符合 Java 开发者的直觉,自动配置、依赖注入、条件装配这些你熟悉的东西全都在。你可以在application.yml里配好模型参数,然后直接注入使用,几乎零学习成本。而且 Spring AI 对 RAG 的支持也在快速完善,VectorStore抽象、Advisor机制都做得比较规整。

LangChain4j 的优势在于它的抽象层次更丰富。AiServices可以把一个接口直接变成 AI 实现,ChatMemory、Retriever、Tool这些组件组合起来非常灵活。它支持的模型提供商也更多,社区活跃度很高。如果你要做复杂的 Agent 编排,LangChain4j 的表达能力会更强一些。

我实际项目里的做法是:基础对话和 RAG 用 Spring AI,因为和业务代码融合得自然;复杂的多步推理和工具调用用 LangChain4j,因为它链式编排更顺手。两个框架都基于 Java 的 HTTP 客户端,底层并不冲突,放在同一个项目里完全可行。

注意:不要一上来就同时引入两个框架,先把一个用熟。我见过有人项目里两个都引,结果依赖冲突排查了半天,最后发现是版本不兼容。

2. 核心细节解析与实操要点

2.1 环境准备:Java 版本和依赖管理

Java 开发者做 AI,第一个坑往往不是 AI 本身,而是环境。Spring AI 和 LangChain4j 对 Java 版本都有要求,建议直接用 JDK 17 或 JDK 21,这两个是长期支持版本,而且新框架的很多特性都依赖较新的语言能力。JDK 8 虽然还能跑,但会遇到各种奇怪的兼容问题,不值得省这点升级成本。

依赖管理用 Maven 或 Gradle 都行,我习惯 Maven,因为团队里大家都熟。Spring AI 的 BOM 一定要引入,否则版本对不齐会出各种NoSuchMethodError。LangChain4j 也有自己的 BOM,同样建议引入。下面是一个典型的 Maven 依赖片段,注意版本号只是示例,实际用的时候去官方仓库查最新稳定版。

<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> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-bom</artifactId> <version>0.35.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>

这里有个细节:Spring AI 的版本迭代很快,不同小版本之间 API 可能有变化。我建议在pom.xml里锁定具体版本,不要用LATEST或范围版本,否则某天构建突然失败你会很懵。LangChain4j 相对稳定一些,但同样建议锁版本。

2.2 模型接入:本地模型和云端模型怎么选

模型接入这块,Java 开发者有两个选择:调云端 API,或者本地跑模型。两者各有场景,我的建议是开发阶段用云端 API 快速验证,生产环境根据数据敏感度和成本决定。

云端 API 的好处是省事,不用管显卡、不用管显存、不用管模型加载。你只需要一个 API Key,配好 base URL 和模型名就能用。Spring AI 和 LangChain4j 都支持通过配置切换不同的模型提供商,代码层面几乎不用改。缺点是数据要出你的服务器,如果业务涉及敏感信息,需要评估合规性。

本地模型的好处是数据不出内网,而且没有调用成本。现在用 Ollama 跑本地模型非常方便,一条命令就能拉起一个模型服务,然后 Java 端通过 HTTP 调用就行。缺点是本地模型的能力通常比云端顶级模型弱一些,而且需要一台有显卡的机器。如果只是做知识库问答这类任务,本地中小模型配合好的 RAG 策略,效果其实够用。

我实际的做法是:开发调试用云端 API,因为响应快、效果好,能快速验证流程;上线时如果数据敏感,就切到本地 Ollama,用同一套代码,只改配置。Spring AI 的ChatModel抽象让这种切换非常自然。

# application.yml 示例 spring: ai: openai: api-key: ${AI_API_KEY} base-url: https://api.example.com chat: options: model: gpt-4o-mini temperature: 0.7

提示:API Key 千万不要硬编码在代码里,用环境变量或配置中心。我见过有人把 Key 提交到 Git 仓库,结果被扫到后产生了一笔不小的账单。

2.3 RAG 的核心:检索质量决定回答质量

RAG 是 Java 开发者做 AI 应用最值得投入的方向,因为它是纯工程问题,不涉及模型训练。RAG 的全称是检索增强生成,说白了就是:用户问一个问题,你先从知识库里找出相关片段,把这些片段和问题一起塞给大模型,让模型基于这些片段回答。这样模型就不会胡编,而且能回答它训练数据里没有的私有知识。

RAG 的流程可以拆成三步:索引、检索、生成。索引阶段把文档切块、向量化、存进向量库;检索阶段把用户问题向量化,去向量库里找最相似的块;生成阶段把检索到的块和问题拼成提示词,交给大模型。每一步都有坑,我逐个说。

文档切块是最容易被忽视的一步。切太大,检索出来的块包含太多无关信息,模型容易被干扰;切太小,语义不完整,检索可能漏掉关键内容。我的经验是按语义切,不要按固定字数切。比如按段落切,或者用递归切分,先按标题切,再按段落切,最后按句子切。LangChain4j 提供了DocumentSplitter,Spring AI 也有TokenTextSplitter,都可以用。切块大小一般控制在 500 到 1000 个 token 之间,重叠 100 到 200 个 token,保证边界信息不丢。

向量库的选择也很多。开发阶段可以用内存向量库,比如 Spring AI 的SimpleVectorStore,重启就丢数据,但调试方便。生产环境建议用专门的向量数据库,比如 Milvus、Qdrant、PgVector。如果团队已经在用 PostgreSQL,PgVector 是最省事的选择,不用额外维护一个数据库。我实际项目里用 PgVector 比较多,因为运维成本低,而且 SQL 和向量查询能混用。

Embedding 模型的选择同样关键。Embedding 负责把文本转成向量,它的质量直接决定检索准确率。云端有 OpenAI 的 embedding 模型,本地可以用 Ollama 拉一个 embedding 模型。注意 embedding 模型和对话模型是两回事,可以分开选。我一般用云端 embedding 做索引,因为质量稳定,成本也不高。

2.4 Agent 与 Function Calling:让 AI 真正干活

RAG 解决的是“知道”的问题,Agent 解决的是“做到”的问题。Agent 的核心是让大模型能够调用外部工具,比如查数据库、调接口、发邮件。Java 开发者做 Agent 有天然优势,因为你的系统里本来就有一堆 Service 方法,只要把它们暴露成工具,模型就能调用。

Spring AI 和 LangChain4j 都支持 Function Calling。基本思路是:你定义一个方法,加上注解描述它的功能,框架会把这个描述发给模型,模型决定什么时候调用、传什么参数。模型返回调用意图后,框架执行你的方法,把结果再发给模型,模型基于结果生成最终回答。

@Tool(description = "根据订单号查询订单状态") public String queryOrderStatus(@P("订单号") String orderId) { return orderService.getStatus(orderId); }

上面是 LangChain4j 的写法,Spring AI 也有类似的注解。关键点是工具描述要写清楚,模型是根据描述来决定调不调的。描述太模糊,模型可能该调的时候不调,或者不该调的时候乱调。我一般会把工具描述写得像给新人看的接口文档,说明功能、参数含义、返回格式。

Agent 的坑在于循环控制。模型可能会反复调用同一个工具,或者陷入死循环。一定要设置最大迭代次数,并且对工具调用做超时和异常处理。我见过一个 Agent 因为工具返回了空结果,模型一直重试,最后把 API 额度耗光了。所以生产环境的 Agent 必须有熔断和兜底逻辑。

3. 实操过程与核心环节实现

3.1 从零搭一个 Spring AI 对话服务

先从一个最小的对话服务开始,把流程跑通。新建一个 Spring Boot 项目,引入 Spring AI 的 starter,然后在配置文件里配好模型信息。下面是最简配置。

spring: ai: openai: api-key: ${AI_API_KEY} base-url: ${AI_BASE_URL} chat: options: model: gpt-4o-mini temperature: 0.7

然后写一个 Controller,注入ChatClient,直接调用。

@RestController 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(); } }

启动项目,访问/chat?message=你好,如果能看到模型回复,说明基础链路通了。这一步看起来简单,但很多人卡在这里,原因通常是 API Key 没配好、base URL 写错、或者模型名不对。排查的时候先看日志,Spring AI 会把请求和响应都打出来,根据错误信息定位。

跑通之后,可以加一些实用功能。比如加系统提示词,让模型扮演特定角色;加对话记忆,让模型记住上下文;加流式输出,让用户看到逐字生成的效果。这些 Spring AI 都有现成的支持,ChatClient的链式 API 用起来很顺手。

this.chatClient = builder .defaultSystem("你是一个专业的客服助手,回答要简洁准确") .build();

对话记忆用MessageChatMemoryAdvisor,流式输出用.stream()替代.call()。这些改动都很小,但体验提升明显。

3.2 用 LangChain4j 实现一个 RAG 知识库

接下来做 RAG,这是最能体现 Java 工程能力的部分。我用 LangChain4j 演示,因为它的 RAG 组件比较完整。整体流程分四步:加载文档、切分、向量化存储、检索生成。

第一步,加载文档。LangChain4j 提供了DocumentLoader,支持从文件、URL、数据库加载。假设我们有一批 PDF 文档,可以用ApachePdfBoxDocumentLoader加载。

DocumentLoader loader = new ApachePdfBoxDocumentLoader(new File("docs/manual.pdf")); List<Document> documents = loader.load();

第二步,切分文档。用DocumentSplitters.recursive做递归切分,参数是最大块大小和重叠大小。

DocumentSplitter splitter = DocumentSplitters.recursive(800, 150); List<TextSegment> segments = splitter.splitAll(documents);

第三步,向量化存储。用EmbeddingModel把文本块转成向量,存进EmbeddingStore。开发阶段用内存存储,生产环境换成 PgVector 或 Milvus。

EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel(); EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>(); EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder() .embeddingModel(embeddingModel) .embeddingStore(embeddingStore) .build(); ingestor.ingest(segments);

第四步,检索生成。用EmbeddingStoreContentRetriever做检索,配合AiServices把检索和对话串起来。

ContentRetriever retriever = EmbeddingStoreContentRetriever.builder() .embeddingStore(embeddingStore) .embeddingModel(embeddingModel) .maxResults(5) .minScore(0.7) .build(); Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(chatModel) .contentRetriever(retriever) .build(); String answer = assistant.answer("文档里提到的安装步骤是什么?");

maxResults控制检索返回几个块,minScore控制相似度阈值。这两个参数需要根据实际数据调。maxResults太小可能漏信息,太大可能引入噪声。我一般从 5 开始调,minScore从 0.7 开始,根据回答质量微调。

3.3 参数调优:检索命中率的提升过程

RAG 最核心的指标是检索命中率,也就是用户问的问题,相关知识块有没有被检索出来。我实际调优过一个知识库项目,命中率从 60% 提到 90% 以上,主要做了三件事。

第一件是优化切块策略。原来按固定 500 字切,结果很多段落被从中间切断,语义不完整。改成按标题和段落递归切分后,命中率明显提升。因为检索的时候,语义完整的块更容易和问题匹配上。

第二件是加元数据过滤。给每个文档块打上来源、章节、类型等标签,检索的时候可以按标签过滤。比如用户问的是“安装问题”,就只在安装相关的块里检索,排除掉其他章节的干扰。LangChain4j 的MetadataFilter支持这种操作。

第三件是调整相似度算法。默认是余弦相似度,但有些场景下欧氏距离效果更好。这个需要实验,不同数据集表现不一样。我一般会准备一批测试问题,跑一遍看命中率,然后换算法再跑,对比结果。

调优项调整前调整后命中率变化
切块策略固定 500 字递归语义切分60% → 75%
元数据过滤无按章节过滤75% → 85%
相似度算法余弦欧氏距离85% → 90%

提示:调优一定要有测试集,不能凭感觉。我见过有人改完参数觉得“好像好点了”,实际上命中率降了都不知道。准备 50 到 100 个真实问题,每次改动都跑一遍,用数据说话。

3.4 把 AI 能力嵌进现有 Spring Boot 业务

AI 能力最终要落到业务里才有价值。我拿一个订单客服场景举例,说明怎么把 RAG 和 Agent 嵌进现有系统。

场景是这样的:用户问“我的订单什么时候到”,系统需要先查订单状态,再根据状态回答。这里既需要 RAG(查知识库里的配送政策),又需要 Agent(查订单数据库)。

我的做法是定义一个OrderAssistant接口,用 LangChain4j 的AiServices实现。接口里定义两个方法,一个查订单,一个回答政策问题。查订单的方法加上@Tool注解,让模型能调用。

interface OrderAssistant { @Tool("根据订单号查询订单状态和预计送达时间") String queryOrder(@P("订单号") String orderId); String chat(String message); }

然后在业务层注入这个接口,用户消息进来后直接调用。模型会自己判断:如果用户问的是订单状态,就调queryOrder;如果问的是配送政策,就从 RAG 知识库里检索。整个过程对业务代码是透明的,你不需要写 if-else 判断意图。

这种做法的好处是业务代码保持干净,AI 的决策逻辑交给模型。但要注意,模型不是百分百可靠,关键操作一定要有兜底。比如查订单这种涉及用户隐私的操作,要在工具方法里做权限校验,不能完全信任模型的判断。

4. 常见问题与排查技巧实录

4.1 依赖冲突和版本不兼容

Java 项目引入 AI 框架后,最常见的报错就是NoSuchMethodError和ClassNotFoundException。这通常是版本不兼容导致的。Spring AI 和 LangChain4j 都依赖一些 HTTP 客户端和 JSON 库,如果项目里已经有旧版本,就会冲突。

排查方法是先看报错类属于哪个包,然后用mvn dependency:tree查这个包的版本来源。如果是传递依赖引入的旧版本,用exclusion排除掉,显式引入新版本。我一般会在dependencyManagement里统一管理这些公共依赖的版本,避免各处版本不一致。

还有一个坑是 Spring Boot 版本和 Spring AI 版本的匹配。Spring AI 对 Spring Boot 版本有要求,用之前先看官方文档的兼容性说明。我见过有人用 Spring Boot 2.x 配 Spring AI 1.x,结果启动就报错,折腾半天才发现是版本不匹配。

4.2 模型响应慢和超时处理

大模型调用是网络请求,响应时间从几百毫秒到几十秒都有可能。如果不做超时处理,一个慢请求可能把线程池占满,拖垮整个服务。我的做法是给 AI 调用单独配一个线程池,设置合理的超时时间,并且做降级处理。

超时时间怎么定?看模型和任务。简单对话一般 10 到 30 秒够用,复杂推理可能要 60 秒以上。我一般设 30 秒超时,超过就返回“正在思考,请稍后重试”,同时记录日志。如果超时率很高,说明要么模型太慢,要么提示词太长,需要优化。

流式输出是缓解慢响应体验的好办法。用户看到字一个个出来,感知上会快很多。Spring AI 和 LangChain4j 都支持流式,用 SSE 推给前端就行。但流式也有坑,比如错误处理比较麻烦,因为响应已经开始推送了,出错只能中断连接。所以流式场景下要做好异常捕获和前端提示。

4.3 成本控制和 Token 优化

大模型调用是按 Token 计费的,用不好成本会失控。我实际项目里做过统计,一个不加优化的 RAG 问答,每次调用可能消耗几千个 Token,其中大部分是检索到的文档块。优化空间很大。

第一个优化是精简检索结果。maxResults不要设太大,5 个块通常够用。每个块的大小也要控制,切块时别切太大。第二个优化是压缩提示词。系统提示词能短则短,不要写一堆废话。第三个优化是加缓存。相同或相似的问题,直接返回缓存结果,不用再调模型。

优化项优化前 Token优化后 Token降幅
检索块数量10 块5 块40%
系统提示词500 字200 字30%
缓存命中无30% 命中25%

缓存这块要注意,不能简单按问题字符串缓存,因为语义相同但表述不同的问题应该命中同一个缓存。可以用 Embedding 做语义缓存,把问题向量化后查相似缓存。这个实现起来稍微复杂,但效果很好。

4.4 常见问题速查表

问题现象可能原因排查方向解决方法
启动报 NoSuchMethodError依赖版本冲突mvn dependency:tree排除旧版本,统一版本管理
调用返回 401API Key 无效检查配置和环境变量重新生成 Key,确认配置生效
响应超时模型慢或网络差看日志中的请求耗时加超时、降级、流式输出
检索结果不相关切块或 Embedding 问题检查切块质量和相似度分数优化切块,换 Embedding 模型
回答胡编提示词没约束检查系统提示词加“只基于检索内容回答”约束
成本过高Token 消耗大统计每次调用 Token 数精简检索、压缩提示词、加缓存

注意:排查 AI 问题时,日志是第一手资料。Spring AI 和 LangChain4j 都支持请求响应日志,开发阶段一定要打开,生产环境注意脱敏。

4.5 几个我踩过的坑和独家经验

第一个坑是向量库的维度不匹配。换 Embedding 模型后,向量维度变了,但向量库还是旧的维度,插入数据直接报错。解决方法是换模型时重建索引,或者用支持多维度的向量库。我现在的习惯是,Embedding 模型一旦确定就不轻易换,换的话一定走完整的重建流程。

第二个坑是对话记忆无限增长。LangChain4j 的MessageWindowChatMemory默认保留最近 N 条消息,但如果 N 设太大,Token 消耗会爆炸。我一般设 10 到 20 条,并且对历史消息做摘要压缩。摘要用一个小模型跑,成本低,效果好。

第三个坑是工具调用的参数类型。模型返回的参数是 JSON,如果方法参数是复杂对象,反序列化可能失败。我的做法是工具方法参数尽量用 String、int 这些简单类型,复杂参数在方法内部自己解析。这样容错性更好。

第四个经验是提示词要版本化管理。提示词是 AI 应用的核心资产,改一个字效果可能差很多。我建议把提示词放在配置文件或数据库里,不要硬编码,并且记录每次修改的效果对比。这样出问题能快速回滚,也能积累经验。

5. 后续扩展方向与个人建议

5.1 从 RAG 到 Agentic RAG 的演进

RAG 做熟了之后,可以往 Agentic RAG 方向走。传统 RAG 是“检索一次,生成一次”,Agentic RAG 是让模型自己决定检索什么、检索几次、要不要换关键词再检索。这需要模型有更强的推理能力,也需要框架支持多轮工具调用。

LangChain4j 和 Spring AI 都在往这个方向走。LangChain4j 的AiServices已经支持多轮工具调用,Spring AI 的Advisor机制也能实现类似效果。我的建议是先把基础 RAG 做扎实,命中率和回答质量稳定了,再考虑上 Agentic RAG。否则基础不牢,Agent 的决策会放大错误。

5.2 知识图谱与 RAG 的结合

另一个值得关注的方向是 GraphRAG,也就是把知识图谱和 RAG 结合。传统 RAG 基于向量相似度检索,对于需要多跳推理的问题效果不好。比如“A 的上级的部门负责什么项目”,这种问题向量检索很难找到完整答案。知识图谱可以把实体关系显式建模,配合 RAG 做多跳检索。

Java 生态里做知识图谱可以用 Neo4j,LangChain4j 有 Neo4j 的集成。这个方向门槛稍高,需要先建图谱,但效果在某些场景下确实好。我建议先把向量 RAG 跑通,有精力再研究图谱。

5.3 给 Java 开发者的几句实在话

最后说几句掏心窝的话。Java 开发者做 AI,不要被 Python 社区的声音吓到。AI 应用落地,工程能力比算法能力更重要。你多年积累的架构设计、性能优化、稳定性保障经验,在 AI 时代一样值钱,甚至更值钱。

入门阶段不要贪多,选一个框架,做一个能跑的小项目,比看十篇综述文章有用。我见过太多人收藏了一堆教程,结果一个都没跑起来。先跑通,再优化,再扩展,这是最实在的路径。

还有一点,AI 技术变化很快,今天的最佳实践明天可能就过时了。但底层的东西不会变:怎么设计好的提示词、怎么保证检索质量、怎么控制成本和延迟、怎么做降级和兜底。这些工程能力是通用的,值得花时间打磨。

我在实际项目里最大的体会是,AI 不是替代开发者,而是放大开发者的能力。你把 AI 接进系统,用户能更快拿到答案,客服能更高效处理问题,这就是价值。至于用哪个框架、哪个模型,都是手段,不是目的。

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

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

立即咨询