Java开发者AI应用入门:Spring AI与LangChain4j实战RAG知识库

发布时间:2026/11/4 4:49:43
Java开发者AI应用入门:Spring AI与LangChain4j实战RAG知识库

1. Java 开发者切入 AI 的真实路径长什么样

这两年身边不少写 Java 的朋友都在问同一个问题:后端业务写了五六年,CRUD 闭着眼睛都能敲,现在想往 AI 方向靠,到底从哪下手?网上教程一搜,清一色 Python、PyTorch、Jupyter Notebook,看完更焦虑了——难道要把 Java 全扔了重学一遍?

先给结论:不用。Java 开发者的 AI 入门路径,和算法工程师那条路完全是两码事。算法工程师关心的是模型结构、训练策略、损失函数怎么调;而 Java 开发者真正该切入的是AI 应用层——把大模型当成一个能力组件,嵌进你熟悉的 Spring Boot 体系里,做 RAG 知识库、做 Agent 工具调用、做企业级 AI 中台。这条路上,你的 Spring 生态经验、工程化能力、并发和事务处理功底,全是加分项,不是包袱。

我自己是从一个内部知识问答需求开始动手的,当时团队有几千份产品文档、历史工单、FAQ,客服每天重复回答同样的问题。用传统关键词检索效果很差,用户问"订单超时了钱扣了没发货怎么办",关键词匹配根本命中不了。后来用Spring AI加LangChain4j搭了一套 RAG 检索增强生成的知识库,两周上线,命中率从原来的四成多提到八成以上。整个过程没写一行 Python。

这篇就把我踩过的路完整梳理一遍:路线图怎么排、工具链怎么选、RAG 到底怎么落地、哪些坑必须提前知道。适合有 Java 基础、想往 AI 应用方向转的开发者,也适合正在评估技术选型的团队负责人。不吹概念,只讲能跑起来的东西。

2. 路线图拆解:Java 开发者该补什么、不该补什么

2.1 先划清边界:你要做的是应用,不是训练

很多人一上来就去啃 Transformer 论文、看反向传播推导,结果两周劝退。这是方向错了。AI 领域粗略分三层:

层级典型工作主要语言Java 开发者是否需要
模型训练层预训练、微调、对齐Python基本不需要
模型服务层推理部署、量化、加速Python/C++了解即可
应用编排层RAG、Agent、工作流、业务集成Java 完全够用核心战场

你要抢的是第三层。这一层的核心能力是:提示词工程、检索增强、工具调用编排、上下文管理、工程化落地。这些全是软件工程问题,Java 的强项。

提示:不要因为"AI"两个字就自我怀疑。应用层 80% 的工作量是数据清洗、接口编排、异常处理、性能优化,这些恰恰是 Java 后端最擅长的。

2.2 三阶段路线图,每阶段都有可交付物

我把入门拆成三个阶段,每个阶段都要求有能跑的东西,避免"学了一堆概念但啥也做不出来"。

第一阶段:打通调用链路(1-2 周)

目标是让 Java 程序能稳定调用大模型接口。核心知识点:

  • HTTP 客户端调用大模型 API,理解请求体结构(messages 数组、role 角色、temperature 等参数)
  • 流式响应处理(SSE),这是打字机效果的底层
  • Token 概念与计费逻辑,知道钱花在哪
  • 引入Spring AI或LangChain4j,用框架替代手写 HTTP

这个阶段的交付物:一个能对话的 Spring Boot 接口,支持流式输出。

第二阶段:RAG 检索增强(3-4 周)

目标是让模型能回答"它本来不知道"的私有知识。核心知识点:

  • 文档解析(PDF、Word、Markdown、HTML)
  • 文本分块策略(chunk size、overlap 怎么定)
  • 向量化 Embedding 与向量数据库(Milvus、PgVector、Redis 等)
  • 相似度检索与重排序
  • 提示词模板拼接上下文

交付物:一个能基于本地文档回答问题的知识库服务。

第三阶段:Agent 与工程化(持续)

目标是让 AI 能"动手做事",而不只是"动嘴回答"。核心知识点:

  • 工具调用(Function Calling),让模型决定调哪个接口
  • 多轮对话状态管理
  • 可观测性(日志、链路追踪、Token 统计)
  • 缓存、限流、降级

交付物:一个能查订单、能建工单、能调内部系统的 AI 助手。

2.3 不该补的坑:这些时间可以省下来

  • 不要系统学 Python 数据科学栈。除非你要转算法岗,否则 NumPy、Pandas 学到够看懂示例就行。
  • 不要死磕数学推导。知道注意力机制大概在干嘛即可,推导过程交给专业的人。
  • 不要一上来就搞微调。90% 的企业场景,RAG 加好的提示词就能解决,微调是最后手段。
  • 不要迷信某个框架。Spring AI 和 LangChain4j 都在快速迭代,学的是思路不是 API。

3. 工具链选型:Spring AI 与 LangChain4j 到底怎么选

3.1 两个框架的定位差异

这是被问最多的问题。我的判断是:它们不是二选一,而是各有主场。

Spring AI的定位是"Spring 生态原生的 AI 抽象层"。它的设计哲学和 Spring Data、Spring Cache 一脉相承——用统一的抽象屏蔽底层差异。你换模型厂商,改配置就行;你用不同的向量库,换 starter 就行。对已经在 Spring Boot 体系里的团队,接入成本极低。

LangChain4j的定位更接近"Java 版的 LangChain",功能覆盖面更广,尤其在 Agent、工具调用、RAG 高级特性(如查询转换、多路召回)上更激进。它的 API 设计更贴近 AI 应用的思维方式,声明式注解用起来很顺手。

我实际项目的做法是:基础对话和模型抽象用 Spring AI,复杂的 RAG 编排和 Agent 用 LangChain4j。两者可以在同一个 Spring Boot 工程里共存,不冲突。

3.2 关键能力对照表

能力维度Spring AILangChain4j我的建议
模型接入官方 starter 丰富支持广泛平手
流式输出支持,与 WebFlux 集成好支持Spring AI 略优
RAG 基础有,够用更完整LangChain4j
向量库支持主流都支持主流都支持平手
Agent/工具调用支持更成熟LangChain4j
与 Spring 集成原生需手动配置Spring AI
学习曲线低(Spring 开发者)中看背景

3.3 Maven 依赖怎么引

以 LangChain4j 为例,核心依赖长这样:

<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j</artifactId> <version>0.35.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> <version>0.35.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-pgvector</artifactId> <version>0.35.0</version> </dependency>

Spring AI 则是走 starter 路线:

<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> </dependency>

注意:版本号一定要对齐。LangChain4j 的各个模块版本必须一致,否则会出现 NoSuchMethodError 这种运行时才暴露的问题,排查起来很痛苦。建议用 BOM 统一管理。

3.4 选型决策的实操建议

如果你所在团队是标准的 Spring Boot 技术栈,且需求以"对话 + 基础 RAG"为主,直接上 Spring AI,接入快、维护省心。

如果需求里有复杂的 Agent 编排、多工具协同、高级检索策略,LangChain4j 更合适,它的抽象层次更贴合这类场景。

如果两个都想要,就共存。我现在的项目就是这么干的,Spring AI 管模型调用和配置,LangChain4j 管 RAG 链路,各司其职。

4. RAG 落地实战:从文档到可用的知识库

4.1 RAG 到底解决了什么问题

先讲清楚原理,不然后面全是黑盒。大模型的知识来自训练数据,有两个硬伤:一是时效性,训练截止之后的事它不知道;二是私有性,你公司的内部文档它没见过。

RAG(Retrieval-Augmented Generation,检索增强生成)的思路很朴素:既然模型不知道,那我在提问的时候把相关资料一起塞给它。流程是:

  1. 用户提问
  2. 把问题向量化,去向量库检索最相关的几段资料
  3. 把资料和问题拼成一个提示词,发给模型
  4. 模型基于资料回答

打个比方:模型是个博学但不了解你公司的专家,RAG 就是每次提问前先给他递一份相关资料,让他看着资料回答。这样既不用重新训练模型,又能保证答案基于事实。

4.2 文档处理:最脏最累但最关键的一步

我踩过最大的坑就在这。很多人以为 RAG 效果差是模型问题,其实八成是文档处理没做好。

第一步是解析。不同格式要用不同工具:

  • PDF:推荐 Apache PDFBox,但要注意扫描件需要 OCR
  • Word:Apache POI,注意表格和图片的处理
  • Markdown/HTML:Jsoup 或直接文本处理
  • 数据库/API:直接查询后拼接

第二步是清洗。原始文档里全是页眉页脚、页码、乱码、多余空行。这些噪声会严重干扰检索。我一般会做:

  • 去掉连续空行和特殊字符
  • 合并被换行切断的句子
  • 过滤掉过短的段落(比如少于 10 个字的)

第三步是分块(Chunking)。这是最讲究的地方。块太大,检索出来的内容冗余,浪费 Token;块太小,语义不完整,检索不准。

我的经验参数:

文档类型chunk sizeoverlap说明
技术文档500-800 字100 字段落语义完整
FAQ按问答对切0一问一答天然分块
长篇文章800-1000 字150 字保留上下文
代码文档按函数/类切50 字保持代码完整

overlap 的作用是防止关键信息正好被切在边界上。比如一句话被切成两半,两半都不完整,加了重叠就能保证至少有一块是完整的。

4.3 向量化与向量库选择

分块之后,每块文本要通过 Embedding 模型转成向量(一串浮点数)。这个向量就代表了文本的语义,语义相近的文本,向量距离也近。

Embedding 模型的选择:

  • 通用场景:OpenAI 的 text-embedding-3-small,性价比高
  • 中文场景:BGE 系列(如 bge-large-zh)效果不错,可本地部署
  • 预算敏感:本地部署开源模型,省 API 费用

向量库的选择,我列个实际对比:

向量库部署难度性能适用场景
PgVector低(复用 PG)中已有 PG,数据量中等
Milvus中高大规模、专业向量检索
Redis低中已有 Redis,追求简单
Elasticsearch中中高已有 ES,需混合检索

我的建议:如果团队已经有 PostgreSQL,直接用 PgVector,省一套中间件,运维成本最低。数据量上千万级别再考虑 Milvus。

4.4 检索质量优化:从能用到好用

基础 RAG 跑通后,你会发现效果时好时坏。这时候要做优化,几个关键手段:

混合检索。纯向量检索对精确匹配不敏感,比如用户问"错误码 E1024",向量检索可能召回一堆语义相近但错误码不对的内容。解决办法是向量检索 + 关键词检索(BM25)结合,各取所长。

重排序(Rerank)。初次检索召回 Top 20,再用重排序模型精排出 Top 5。重排序模型更慢但更准,用它来提纯。这一步对效果提升很明显,我实测命中率能再涨 10 个点。

查询改写。用户的问题往往口语化、有指代。比如"它怎么用","它"指什么?可以用模型先把问题改写成完整清晰的查询,再检索。

元数据过滤。给每个块打上标签(来源、部门、时间),检索时先按标签过滤,再算相似度。这样能大幅缩小范围,提升准确率。

4.5 一个最小可用的 RAG 代码骨架

用 LangChain4j 搭一个最简 RAG,核心代码大概这样:

// 1. 加载并切分文档 DocumentSplitter splitter = DocumentSplitters.recursive(500, 100); List<Document> documents = FileSystemDocumentLoader.loadDocuments("/docs"); List<TextSegment> segments = splitter.splitAll(documents); // 2. 向量化并存入向量库 EmbeddingModel embeddingModel = new OpenAiEmbeddingModel("your-api-key"); EmbeddingStore<TextSegment> store = new PgVectorEmbeddingStore( dataSource, "embeddings", 1536 ); EmbeddingStoreIngestor.builder() .embeddingModel(embeddingModel) .embeddingStore(store) .build() .ingest(segments); // 3. 构建检索增强的对话链 ChatLanguageModel chatModel = OpenAiChatModel.builder() .apiKey("your-api-key") .modelName("gpt-4o-mini") .build(); RetrievalAugmentor augmentor = DefaultRetrievalAugmentor.builder() .contentRetriever(EmbeddingStoreContentRetriever.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .maxResults(5) .minScore(0.7) .build()) .build(); Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(chatModel) .retrievalAugmentor(augmentor) .build(); // 4. 提问 String answer = assistant.chat("订单超时未发货怎么处理?");

这段代码里,maxResults是召回数量,minScore是相似度阈值。这两个参数要反复调,没有万能值。

提示:minScore设太高会漏召回,设太低会引入噪声。建议先用 0.6-0.7 起步,根据实际效果微调。不同 Embedding 模型的分数分布不一样,换模型后要重新校准。

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

5.1 效果类问题速查表

现象可能原因排查方向
答非所问检索没召回相关内容检查分块、Embedding、相似度阈值
答案不完整召回块太少或太小增大 maxResults 或 chunk size
胡编乱造模型没基于资料回答强化提示词约束,要求"仅根据资料回答"
检索到无关内容噪声数据太多清洗文档,加元数据过滤
相同问题答案不稳定temperature 太高降到 0.1-0.3
响应太慢召回太多或模型太大减少召回数,换小模型

5.2 几个我踩过的具体坑

坑一:分块把表格切碎了。产品文档里有很多参数表格,按固定字数切会把表格拦腰截断,检索出来全是残缺信息。解决办法是按结构切分,识别到表格就整块保留,或者用 Markdown 的标题层级来切。

坑二:Embedding 模型和检索模型不匹配。有次我入库用的是 A 模型,检索时配置写成了 B 模型,结果检索出来的东西驴唇不对马嘴。入库和检索必须用同一个 Embedding 模型,这是铁律。

坑三:提示词没约束,模型自由发挥。早期提示词写得太宽松,模型经常"我觉得..."然后开始编。后来改成明确指令:"你是知识库助手,只能根据以下资料回答,资料中没有的信息请回答'暂无相关信息'。"效果立刻稳定。

坑四:忽略 Token 成本。召回 10 个块,每块 500 字,加上系统提示词,一次请求轻松上万 Token。高频调用下成本很吓人。后来我做了两件事:一是召回数降到 5,二是加了缓存,相同问题直接返回缓存结果。

5.3 性能与成本优化技巧

缓存策略。问题级别的缓存最有效,相同问题直接命中。可以用 Redis 存"问题哈希 -> 答案",设置合理过期时间。注意要归一化问题(去空格、转小写)再算哈希。

异步与流式。用户对首字延迟很敏感,但对完整回答的等待容忍度高。用流式输出,首字 1 秒内出来,体验就好很多。Spring AI 和 LangChain4j 都支持流式。

批量 Embedding。入库时不要一条一条调 Embedding 接口,要批量提交,能省大量网络往返时间。

模型分级。简单问题用小模型(便宜快),复杂问题用大模型(贵但准)。可以先用小模型判断问题复杂度,再路由。

5.4 上线前必须检查的清单

  • 提示词是否明确约束了"仅基于资料回答"
  • 检索阈值是否经过实际数据校准
  • 是否有兜底回答(检索不到时怎么回)
  • 是否有敏感内容过滤
  • Token 消耗是否有监控和告警
  • 是否有降级方案(模型服务挂了怎么办)
  • 日志是否记录了完整的请求链路,方便排查

6. 从 RAG 到 Agent:下一步怎么走

RAG 解决的是"知道"的问题,Agent 解决的是"做到"的问题。当你的知识库跑顺了,下一步自然是让 AI 能调用工具、执行动作。

工具调用(Function Calling)是核心机制。你定义好工具(比如"查询订单状态"、"创建工单"),模型根据用户意图决定调哪个、传什么参数。Java 里用 LangChain4j 的@Tool注解就能声明:

public class OrderTools { @Tool("根据订单号查询订单状态") public String queryOrder(@P("订单号") String orderId) { // 调用内部订单服务 return orderService.getStatus(orderId); } }

然后在构建 Assistant 时注册这些工具,模型就能自动调用了。

Agentic RAG是更进一步的形态:让 Agent 自己决定要不要检索、检索几次、用什么查询。比如用户问一个复杂问题,Agent 可以先拆解成子问题,分别检索,再综合回答。这比固定流程的 RAG 灵活得多,但也更难控制,容易陷入循环或跑偏。

我的建议是循序渐进:先把基础 RAG 做扎实,再上工具调用,最后考虑 Agentic 编排。每一步都要有明确的业务价值,不要为了技术而技术。

可观测性这块千万别省。AI 应用的调试比传统应用难得多,因为输出是不确定的。我一般会记录:完整的提示词、召回的文档块及分数、模型的原始输出、Token 消耗、耗时。出问题时能快速定位是哪一环的问题。

最后分享一个我自己的体会:Java 开发者做 AI,最大的优势不是算法,而是工程化能力。模型能力大家都能用,但谁能把 RAG 的召回率调上去、把响应延迟压下来、把成本控制住、把系统做得稳定可维护,这才是真正的壁垒。我见过太多 demo 很惊艳但一上生产就崩的项目,问题全出在工程细节上。所以别焦虑自己不懂算法,把你后端那套本事用足,AI 应用这条路你走得比想象中顺。