ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Java开发者AI应用实战:Spring AI与LangChain4j从RAG到Agent

Java开发者AI应用实战:Spring AI与LangChain4j从RAG到Agent 1. Java 开发者切入 AI 的真实路径与选型逻辑1.1 为什么 Java 开发者不必从 Python 重头学起我身边不少写了五六年 Java 的朋友一提到 AI 第一反应就是是不是得先把 Python 学一遍。这个念头本身就把门槛抬高了。实际情况是AI 应用开发早就分成了两层一层是模型训练和微调那确实是 Python 的主场另一层是AI 应用工程化落地也就是把大模型能力接进业务系统这一层恰恰是 Java 的主战场。你想想企业里的真实场景订单系统、风控系统、CRM、ERP绝大多数跑在 JVM 上。要让这些系统具备理解自然语言检索知识库自动生成报告的能力最省事的做法不是把整个系统用 Python 重写而是在现有 Java 服务里调用模型接口、编排检索流程。这就是Spring AI和LangChain4j这两个框架存在的意义——它们把调用大模型、管理对话上下文、接入向量库这些脏活累活封装成了 Java 开发者熟悉的 API 风格。所以路线图的第一条原则是别把 AI 当成一门新语言来学把它当成一类新的外部依赖来集成。你会用 Spring 整合 Redis、整合 MyBatis那你就能用 Spring AI 整合大模型。心态摆正了后面的事情就顺了。1.2 三条主流技术路线的取舍Java 侧做 AI 应用目前能落地的路线大致三条我按上手难度和适用场景列个表你可以对号入座。路线代表工具适合场景上手成本我的评价官方 SDK 直连各家模型厂商的 Java SDK单一模型、简单问答低适合验证想法不适合复杂业务Spring AISpring AI、Spring AI AlibabaSpring Boot 项目集成中生态好和现有工程无缝LangChain4jLangChain4j复杂编排、RAG、Agent中高抽象层次高功能全如果你手上是标准的 Spring Boot 项目团队又习惯了 starter 那一套Spring AI 是首选。它的设计哲学就是约定优于配置加个依赖、写个application.yml、注入一个ChatClient就能跑起来。而如果你要做的是知识库问答、多步骤推理、工具调用这类偏编排的活LangChain4j 的表达能力更强它借鉴了 Python 版 LangChain 的思路但 API 做了 Java 化改造用起来不别扭。至于直接调 SDK我的建议是只用来做技术预研别用来做生产。原因很简单模型厂商的接口格式、鉴权方式、返回结构各不相同你一旦写死在业务代码里将来换模型就是一场灾难。中间加一层抽象框架是给自己留后路。1.3 一个务实的四阶段学习路线我把这条路线总结成四个阶段每个阶段都有明确的毕业标准避免你学了半天不知道学到哪了。第一阶段打通调用链路。目标很简单用 Java 代码成功调用一次大模型拿到返回文本。这个阶段你要搞清楚三件事API Key 怎么配、请求参数有哪些temperature、maxTokens 这些、返回结构长什么样。别小看这一步很多人卡在环境变量和依赖冲突上。第二阶段掌握对话与上下文管理。单轮问答没意思真实业务都是多轮对话。你要理解ChatMemory的概念知道怎么把历史消息带进去怎么控制上下文长度避免 token 爆炸。第三阶段接入 RAG。这是 Java 开发者最能体现价值的地方。企业里的知识库、文档、工单记录都是私有数据模型本身不知道。RAG检索增强生成就是把这些数据向量化存起来提问时先检索再让模型基于检索结果回答。LangChain4j 的 RAG 支持和Spring AI 的 VectorStore 抽象是这个阶段的核心工具。第四阶段编排 Agent。让模型能调用你的 Java 方法查数据库、发邮件、调接口形成思考—行动—观察的循环。这一步开始涉及AI Agent和Agentic RAG的概念是当前最热的方向。2. 环境搭建与工具链的实操细节2.1 JDK 与构建工具的版本选择先说个容易被忽略的坑Spring AI 对 JDK 版本有硬性要求。目前主流版本要求 JDK 17 起步部分新特性甚至需要 JDK 21。如果你还在用 JDK 8第一步就得升级。我见过太多人兴冲冲加了依赖结果编译报错折腾半天才发现是 JDK 版本问题。升级 JDK 这件事Windows 上就是下载安装包、配JAVA_HOME和PathLinux 上用包管理器或者手动解压都行。配完记得java -version验证一下别配了个寂寞。构建工具方面Maven 和 Gradle 都支持但 Spring AI 的官方文档和社区示例以 Maven 居多新手建议先用 Maven遇到问题好搜。依赖引入的时候有个细节Spring AI 的版本管理推荐用 BOMBill of Materials也就是在dependencyManagement里统一声明版本这样各个 starter 之间不会打架。我实测下来手动指定每个依赖版本的做法十有八九会遇到传递依赖冲突。dependencyManagement dependencies dependency groupIdorg.springframework.ai/groupId artifactIdspring-ai-bom/artifactId version1.0.0/version typepom/type scopeimport/scope /dependency /dependencies /dependencyManagement2.2 模型接入的配置要点配置这块核心就是三样东西接口地址、API Key、模型名称。以接入国内某主流模型平台为例application.yml大致长这样spring: ai: openai: base-url: https://api.example.com api-key: ${AI_API_KEY} chat: options: model: glm-4 temperature: 0.7这里有几个经验点值得说。第一API Key 千万别硬编码在配置文件里提交到仓库用环境变量或者配置中心这是安全底线。第二temperature这个参数控制输出的随机性做知识问答建议调到 0.1~0.3让回答更稳定做创意生成可以调到 0.8 以上。第三base-url很多平台是兼容 OpenAI 协议的所以 Spring AI 的 openai starter 往往能直接复用不用为每个厂商单独找 starter。注意不同厂商对 OpenAI 协议的兼容程度不一样有的在流式返回、函数调用上有差异。接入前先用 curl 或者 Postman 把接口调通再写 Java 代码能省掉大量排查时间。2.3 向量库与嵌入模型的选择做 RAG 绕不开向量库。Java 生态里可选的有Redis带向量检索、Milvus、PgVector、Elasticsearch等。怎么选我的建议是按你现有技术栈来。如果项目里已经有 Redis直接用 Redis 的向量能力最省事少维护一个中间件。如果数据量大、对检索性能要求高Milvus 更专业。如果本来就用 PostgreSQLPgVector 插件几乎零成本。别为了用新技术而引入一个团队没人会维护的组件这是我在实际项目里踩过的坑。嵌入模型Embedding Model负责把文本转成向量。它和对话模型可以是同一个平台也可以分开。选嵌入模型主要看两点向量维度和中文效果。维度越高表达能力越强但存储和计算成本也越高常见的有 768 维、1024 维、1536 维。中文场景一定要选对中文优化过的模型否则检索准确率会明显下降。3. RAG 落地从文档到可问答知识库3.1 RAG 的核心流程拆解RAG 这个词听着玄乎拆开看就四步加载、切分、向量化、检索生成。加载就是把你的 PDF、Word、Markdown、数据库记录读进来。切分是把长文档切成一段段合适大小的文本块chunk因为模型有上下文长度限制整本书塞不进去。向量化是把每个文本块通过嵌入模型转成向量存进向量库。检索生成是用户提问时把问题也向量化去库里找最相似的几个块拼进提示词让模型基于这些内容回答。这四步里切分策略是最影响效果的。切太大检索出来的块包含太多无关信息干扰模型切太小语义不完整检索不准。我的经验是中文文档按 300~500 字切块之间留 10%~20% 的重叠overlap避免把一句话从中间切断。3.2 LangChain4j 实现 RAG 的关键代码LangChain4j 把 RAG 的流程封装得相当顺手。一个最小可用的例子大概是这样// 1. 加载文档 Document document FileSystemDocumentLoader.loadDocument( Paths.get(/data/manual.pdf), new ApachePdfBoxDocumentParser() ); // 2. 切分 DocumentSplitter splitter DocumentSplitters.recursive(500, 50); ListTextSegment segments splitter.split(document); // 3. 向量化并存储 EmbeddingModel embeddingModel new AllMiniLmL6V2EmbeddingModel(); EmbeddingStoreTextSegment store new InMemoryEmbeddingStore(); EmbeddingStoreIngestor.ingestor(embeddingModel, store).ingest(segments); // 4. 构建检索增强的对话 ContentRetriever retriever EmbeddingStoreContentRetriever.builder() .embeddingStore(store) .embeddingModel(embeddingModel) .maxResults(5) .minScore(0.7) .build(); Assistant assistant AiServices.builder(Assistant.class) .chatLanguageModel(chatModel) .contentRetriever(retriever) .build();这段代码里maxResults(5)表示每次检索返回最相似的 5 个块minScore(0.7)是相似度阈值低于这个分数的直接丢弃。阈值这个参数很关键设太低会引入噪音设太高可能什么都检索不到。建议先用 0.6~0.7 起步根据实际效果微调。3.3 提升 RAG 效果的几个实战技巧光跑通流程只是及格线真正让 RAG 好用还得做优化。我总结了几个投入产出比高的做法。第一查询改写。用户的问题往往口语化、有指代直接拿去检索效果差。可以先让模型把问题改写成更适合检索的形式再去做向量匹配。LangChain4j 里有QueryTransformer接口实现一个改写逻辑不难。第二混合检索。纯向量检索对关键词不敏感比如用户搜一个具体的产品型号向量可能匹配不准。这时候把关键词检索BM25和向量检索结合用 RRF倒数排名融合算法合并结果效果会明显提升。有意思的是LangChain 和 LangChain4j 默认的 RRF 实现在去重逻辑上存在一些缺陷如果你对结果精度要求高可能需要自己重写融合逻辑。第三重排序Rerank。检索回来的块用一个专门的重排序模型再过一遍把最相关的排到前面。这一步能显著提升最终答案质量代价是多一次模型调用。第四元数据过滤。给每个文本块打上来源、时间、部门等标签检索时先按元数据过滤再向量匹配。比如用户问今年的政策你就只检索今年的文档避免翻出过期信息。4. 常见问题排查与避坑经验4.1 依赖冲突与版本问题速查Java 生态的依赖冲突是老生常谈AI 框架因为依赖链长问题更突出。我整理了一张常见问题对照表。现象大概率原因解决方向启动报 NoSuchMethodError依赖版本不一致用 BOM 统一版本mvn dependency:tree排查编译提示找不到类JDK 版本过低升级到 JDK 17调用超时网络或模型响应慢设置合理超时加重试机制返回乱码编码问题统一 UTF-8检查响应解析流式输出中断SSE 配置问题检查响应头、缓冲区设置排查依赖冲突mvn dependency:tree是神器把冲突的依赖用exclusions排除掉或者显式声明版本覆盖。我一般会在项目初期就把依赖树打印出来看一遍心里有数。4.2 上下文与 Token 管理的坑多轮对话最容易出的问题是上下文越滚越长最后超出模型限制报错。解决办法是给ChatMemory设置窗口大小只保留最近 N 轮对话。但这里有个权衡窗口太小模型记不住前面的信息窗口太大token 消耗高还容易超限。我的做法是滑动窗口加摘要保留最近几轮原文更早的对话让模型压缩成一段摘要。这样既控制了长度又不丢关键信息。LangChain4j 提供了MessageWindowChatMemory和摘要相关的组件组合使用即可。另一个坑是中文的 token 计算。同样一段话中文占的 token 通常比英文多估算时别按字符数除以 4 来算中文大概一个字对应 1~2 个 token具体看模型的分词器。做成本预估的时候这个差异会被放大。4.3 生产环境的稳定性考量从 demo 到生产中间隔着好几道坎。限流和降级是必须的模型接口不稳定是常态要有重试、熔断、兜底回复。日志和可观测性也不能少每次调用的输入输出、耗时、token 消耗都要记录下来出问题才好定位。还有一点容易被忽视成本控制。大模型调用是按 token 计费的一个不小心账单就上去了。建议在网关层做统一的 token 统计和配额管理给不同业务线分配额度。我见过有团队因为没做限制测试环境疯狂调用月底账单吓一跳。提示做 RAG 时嵌入模型和对话模型可以分开选。嵌入模型调用频繁但便宜对话模型贵但调用少。合理搭配能省不少钱。5. 从 RAG 到 Agent 的能力延伸5.1 Agent 与 RAG 的区别和联系很多人搞不清 RAG 和 Agent 的关系。简单说RAG 是查了再答Agent 是想了再做。RAG 的流程是固定的检索、拼接、生成。Agent 则多了决策环节模型会自己判断这个问题我需不需要查资料要不要调用某个工具结果够不够要不要再查一次。所以 Agentic RAG 就是让 Agent 来驱动 RAG 流程模型自主决定检索策略、检索次数、是否需要多轮检索。这比固定流程灵活得多但也更难控制容易陷入死循环或者调用过多工具。5.2 工具调用的实现思路让模型调用 Java 方法核心是把方法签名和说明告诉模型模型返回要调用的方法名和参数你的代码去执行再把结果喂回模型。LangChain4j 里用Tool注解标记方法即可public class OrderTools { Tool(根据订单号查询订单状态) public String queryOrderStatus(String orderId) { // 实际查询逻辑 return orderService.getStatus(orderId); } }然后在构建 Assistant 时把工具注册进去。模型会根据用户问题自动决定是否调用。这里的关键是工具描述要写清楚模型靠描述来判断什么时候用哪个工具。描述含糊模型就会乱调或者不调。5.3 当前值得关注的方向Java AI 生态这两年变化很快。Spring AI Alibaba这类针对国内模型平台优化的项目在快速成熟接入国内模型更方便。MCP模型上下文协议这类标准化协议也在推进未来工具接入可能会更规范。RAG 方面Ontology RAG基于本体的检索和Agentic RAG是研究热点前者用知识图谱增强检索的语义理解后者用 Agent 动态编排检索流程。我的建议是先把基础 RAG 做扎实再考虑这些进阶方向。基础没打好上来就搞 Agent很容易做成一个演示很炫、实际没法用的东西。技术选型永远服务于业务需求别为了追新而追新。我在实际项目里最大的体会是Java 开发者做 AI优势不在算法而在工程。把调用链路做稳、把成本控住、把效果调好这些才是企业真正需要的能力。模型会一代代更新但工程能力是能沉淀下来的。
返回列表