Spring AI、LangChain4j 和 LangChain 应该怎么选?
简化版
三个框架做的是同一件事:把不同服务商的模型接口、Prompt、工具调用、向量检索统一成一套编程接口。先按语言栈分:Python 服务选 LangChain,需要有条件分支和循环的流程再加 LangGraph;Java 服务在 Spring AI 和 LangChain4j 之间选。Spring AI 是 Spring 官方项目,和 Spring Boot 的自动配置、Bean 体系结合最紧,调用风格是 ChatClient 链式调用;LangChain4j 不依赖 Spring 也能用,特色是用接口加注解声明 AI 服务。模型配置要在后台动态修改时,三者都要绕开「从配置文件读模型参数」,改成按数据库里的配置手动构建模型对象。
详细版
| 维度 | Spring AI | LangChain4j | LangChain(Python) |
|---|---|---|---|
| 出身 | Spring 官方项目 | 独立开源项目 | LangChain 官方 |
| 与框架的关系 | 围绕 Spring Boot 自动配置设计 | 可以独立使用,也提供 Spring Boot starter | 独立使用,常配 FastAPI |
| 典型调用 | ChatClient.prompt().user(..).call() | AiServices 生成接口实现,@SystemMessage、@UserMessage 绑定提示词 | ChatOpenAI().invoke()、LCEL 组合 |
| 工具调用 | @Tool + ChatClient.tools() | @Tool 方法转成工具规格与执行器 | @tool 或绑定工具 |
| 复杂流程 | 业务代码自己控制 | 业务代码自己控制 | LangGraph 状态图 |
选型看三件事:
- 语言栈跟着团队和已有系统走。 业务系统是 Spring Boot,就在 Java 里选;数据、评测、Agent 实验为主,Python 生态更全。
- Java 里看和 Spring 的绑定程度。 项目深度依赖 Spring 的自动配置和 Bean 注入,Spring AI 更顺手;想要声明式的 AI 接口,或者不想让模型接入跟着 Spring 的配置体系走,LangChain4j 更轻。
- Python 里看流程形态。 线性链路用 LangChain 的组件就够;有条件边、有回环、要控制最大轮数的 Agent 流程,用 LangGraph 表达。
无论选哪个,框架覆盖不到的专用接口直接发 HTTP,所有模型调用收敛到一个统一出口,日志、报错翻译、Token 统计只写一份。
完整版教学
一、三个框架封装的是同一层
先弄清楚框架帮你做了什么,才能比较。调用一次大模型,裸写 HTTP 要处理的事情大致是:
拼请求体(model、messages、tools、temperature……)
-> 带 Authorization 请求头 POST 到 /chat/completions
-> 解析 choices[0].message(正文或 tool_calls)
-> 读 usage、finish_reason
-> 有 tool_calls 时执行工具、把结果以 tool 消息回填、再请求一轮
三个框架都把这一层封装掉,只是叫法不同:
| 能力 | Spring AI | LangChain4j | LangChain |
|---|---|---|---|
| 对话模型 | ChatModel、ChatClient | ChatModel(旧版 ChatLanguageModel) | ChatOpenAI 等 |
| 向量模型 | EmbeddingModel | EmbeddingModel | OpenAIEmbeddings 等 |
| 提示词模板 | PromptTemplate | PromptTemplate、注解模板 | ChatPromptTemplate |
| 工具 | @Tool | @Tool | @tool |
| 向量存储 | VectorStore | EmbeddingStore | VectorStore |
所以选型不是比「谁能调模型」,而是比「谁和你的工程体系、编程习惯、流程形态更贴合」。
二、第一刀:按语言栈分
语言栈通常不是框架决定的,而是团队和已有系统决定的。业务系统、权限、订单、数据库访问都在 Spring Boot 里,把 AI 能力做成同一个服务里的一层,调用业务数据最直接,这时在 Java 的两个框架里选。反过来,以数据处理、评测脚本、多 Agent 实验为主,Python 的生态更全:模型 SDK、评测工具、文档解析库大多先有 Python 版本。
还有一个容易忽略的点是运行模型。Python 服务配合 FastAPI 走 async/await,一次请求里串几次模型调用和数据库查询时,等待期间不占线程;Java 服务一般是线程模型,长耗时的模型调用要靠超时、异步任务或流式输出来管住线程。两种都能做好,但写法不同,选型时要算进团队熟悉度。
记忆钩子:先问「AI 能力要放进哪个服务」,语言定了,框架选择就只剩一半。
三、Java 里:Spring AI 和 LangChain4j 差在哪
两者的能力清单越来越接近,差异主要在设计取向:
| 维度 | Spring AI | LangChain4j |
|---|---|---|
| 与 Spring 的关系 | 为 Spring Boot 而生,starter 自动配置出模型 Bean | 核心不依赖 Spring,另有 Spring Boot 集成 |
| 调用风格 | ChatClient 链式调用,Advisor 挂增强逻辑 | AiServices 按接口生成实现,注解声明提示词 |
| 配置来源 | 默认从 application.yml 的 spring.ai.* 读 | 默认用 builder 在代码里构建 |
| 学习迁移 | 熟悉 Spring 的团队几乎零门槛 | 熟悉 LangChain 概念的团队容易上手 |
声明式的 AiServices 写起来是这样:
// 只写接口,LangChain4j 在运行时生成实现:把两段文本分别作为系统消息和用户消息发给模型
public interface PromptAgent {
@SystemMessage("{{systemPrompt}}")
@UserMessage("{{userPrompt}}")
String generate(@V("systemPrompt") String systemPrompt, @V("userPrompt") String userPrompt);
}
Spring AI 的等价写法是 chatClient.prompt().system(systemPrompt).user(userPrompt).call().content()。两种都没有对错,团队更习惯哪种,维护成本就更低。
四、Python 里:LangChain 管组件,LangGraph 管流程
LangChain 提供模型、提示词、解析器、检索器这些组件,线性链路用它拼起来就够。流程一旦出现「根据结果决定下一步」和「不满意就回到前面重做」,比如检索后判断相关性、不相关就改写再检索、最多三次,用普通函数写会变成一堆 while 和 if,状态散落在局部变量里。
LangGraph 把这类流程画成状态图:节点是一步操作,边决定下一步去哪,条件边读取状态里的字段做分支,环表示回到前面重做,最大步数防止死循环。流程写在边上,看图就是看流程,节点函数也能脱离模型单独测试。所以 Python 这边常见的组合是「LangChain 组件 + LangGraph 编排」,而不是二选一。
五、模型配置在数据库里时,三者都要绕开配置文件
框架的默认用法都假设模型参数写在配置里:Spring AI 的 starter 读 spring.ai.openai.api-key,LangChain 的示例从环境变量读 Key。可企业应用常见的需求是「管理员在后台改完 Key、换完模型,下一次调用就生效,不重启服务」,这时要反过来:
ai_model_config 表(地址、Key、模型名、温度……)
-> 模型工厂按这一行配置用 builder 构建模型对象
-> 以配置内容拼缓存 key,内容变了自动重建
-> 业务代码只从工厂取模型,不注入框架自动配置出来的 Bean
Spring AI 这里有个坑:starter 里的自动配置读不到 API Key 会让应用启动失败,连用不到的语音、图像模型也一起报错,所以要在启动类上把相关自动配置排除掉。LangChain4j 引普通依赖而不是 starter,就没有这一步。
六、框架覆盖不到的地方
框架跟进的是主流协议。服务商的专用接口,比如异步的录音文件识别(上传、提交任务、轮询结果)、不在 OpenAI 兼容模式下的重排接口,框架往往没有封装。处理原则是:
| 情况 | 做法 |
|---|---|
| 专用接口,只在一个服务里用 | 直接按服务商文档发 HTTP 请求 |
| 专用接口,需要接进框架的链路 | 自己实现框架的标准组件接口,内部发 HTTP |
| 框架某个库和主线版本不兼容 | 换掉这个库或自己实现,不为它降级主线 |
不管走框架还是直连,调用都收敛到一个统一出口,调用日志、报错翻译、Token 统计只维护一份。
七、一次加权选型推演
假设一个团队要给 Spring Boot 的业务系统加 AI 功能,列出四个维度和权重,给候选打 1~5 分:
| 维度 | 权重 | Spring AI | LangChain4j | LangChain(另起 Python 服务) |
|---|---|---|---|---|
| 和现有 Spring Boot 系统的集成 | 0.4 | 5 | 4 | 2 |
| 团队熟悉度 | 0.3 | 5 | 3 | 2 |
| 复杂 Agent 流程的表达 | 0.2 | 3 | 3 | 5 |
| 模型配置动态化的改造量 | 0.1 | 3 | 4 | 4 |
Spring AI = 0.4×5 + 0.3×5 + 0.2×3 + 0.1×3 = 2.0 + 1.5 + 0.6 + 0.3 = 4.4
LangChain4j = 0.4×4 + 0.3×3 + 0.2×3 + 0.1×4 = 1.6 + 0.9 + 0.6 + 0.4 = 3.5
LangChain = 0.4×2 + 0.3×2 + 0.2×5 + 0.1×4 = 0.8 + 0.6 + 1.0 + 0.4 = 2.8
如果这个团队的核心需求变成「多轮反思、条件分支很多的 Agent」,把第三项权重提到 0.5、第一项降到 0.2,结果就可能反过来。打分本身不重要,重要的是把「为什么选它」拆成能讨论的维度。
八、常见误区与追问
- 误区:LangChain4j 就是 LangChain 的 Java 版,功能一一对应。 它借鉴了 LangChain 的概念,但 API 设计独立演进,Python 生态里的很多组件(包括 LangGraph)不能照搬。
- 误区:用了 Spring AI 就必须把 Key 写进 application.yml。 自动配置只是默认用法,可以排除自动配置,按数据库里的配置自己构建模型对象。
- 误区:框架能覆盖所有服务商接口。 专用接口经常没有封装,要直接发 HTTP,必要时包装成框架组件。
- 误区:选了框架就不用自己管日志和报错。 调用日志、报错翻译、Token 统计仍要在统一出口里自己做。
- 追问:LangGraph 解决了 LangChain 的什么问题? 线性链路之外的条件分支、回环和轮数上限,用状态图表达比手写循环清楚,也更容易测试。
- 追问:一个项目能不能混用框架? 可以,常见的是主线用一个框架,覆盖不到的接口直连,关键是调用出口统一。
九、加强记忆
框架选型按三刀切:第一刀按语言栈,AI 能力放进哪个服务就用哪门语言;第二刀在 Java 里看和 Spring 的绑定程度,Spring AI 贴合 Spring Boot 的自动配置和链式 ChatClient,LangChain4j 独立、擅长声明式 AiServices;第三刀在 Python 里看流程形态,线性链路用 LangChain 组件,有条件边和回环用 LangGraph。三者封装的是同一层模型协议,动态模型配置都要绕开配置文件、按库中配置构建并缓存;覆盖不到的接口直连 HTTP,所有调用收进统一出口。
项目实战落地
项目里怎么做的
《AI Agent旅游行程智能规划平台》用的是 LangChain4j 1.20.0,pom.xml 只引两个普通依赖:langchain4j 核心模块和 langchain4j-open-ai。DeepSeek 对话模型和阿里云百炼向量模型都提供 OpenAI 兼容接口,这一个依赖就同时接住对话和向量两类模型,不需要各家的 SDK。因为不是 starter,application.yml 里不填任何模型参数,后端启动时也不会去找 API Key;模型对象由 LangChain4jModelFactory 按 ai_model_config 表里的配置用 builder 构建。
另外两个项目是另外两种选择:
- 《AI Agent智能教务排课与教学质量分析系统》用 Spring AI 的 OpenAI 兼容 starter。starter 带的六个 OpenAI 自动配置(聊天、向量、图像、语音合成、语音转写、内容审核)都要从
spring.ai.openai.api-key读密钥,读不到就启动失败,而项目的密钥在数据库里,所以启动类上把六个全部排除,模型客户端由SpringAiModelFactory按库中配置构建。 - 《AI Agent智能会议纪要辅助系统》是 Python 路线:FastAPI + Tortoise ORM 全链路异步,因为转写要轮询几分钟、自检要串好几次模型调用,同步框架会把工作线程占满;纪要自检是「审查 → 条件分支 → 重写 → 回环 + 上限」的形态,用 LangGraph 表达,条件写在边上,状态图不碰数据库,能单独测试。
为什么这样取舍
- 旅游项目选普通依赖。 模型参数全部存库、由工厂构建,用不到 starter 的自动配置,普通依赖省掉了排除自动配置这一步。
- 教务项目排除全部六个。 项目只用聊天补全,但其余五项同样要读密钥,不一起排掉,没填 Key 时连登录页都打不开。
- 纪要项目用 Python 和 LangGraph。 耗时的异步任务多,反思环又是有条件边和回环的流程,这两点正好是 FastAPI 和 LangGraph 的长处。
面试官还会追问
- 旅游项目内层的工具调用往返交给 LangChain4j 托管,外层的反思循环为什么由业务代码自己控制?
- 教务项目的普通问答和排课 Agent 共用同一个
ChatClient实例,两条链路是在哪一步分开的?
学完《AI Agent旅游行程智能规划平台》,上面这些追问你都会迎刃而解。