最近在搞AI相关的项目,发现Java生态下有两个比较主流的框架:Spring-AI和LangChain4J。说实话,刚开始我也挺纠结选哪个,毕竟两个看起来都挺不错的。今天就来聊聊这两个框架的区别,以及在实际项目中怎么选。
先说说这两个框架的背景
Spring-AI是Spring官方推出的AI框架,毕竟是亲儿子,跟Spring Boot集成那是相当丝滑。而LangChain4J是LangChain的Java版本,如果你之前用过Python的LangChain,那这个应该会感觉很亲切。
我在实际项目中两个都用过,踩了不少坑,今天就分享一下我的真实感受。

功能对比:到底哪个更香?
1. 多模型支持
Spring-AI目前支持的模型挺多的,OpenAI、Azure OpenAI、Ollama、Anthropic Claude等等,基本上主流的大模型都覆盖了。而且配置起来特别简单,基本上就是加个依赖,配个key就完事了。
java
// Spring-AI配置示例
@Configuration
public class OpenAIConfig {
@Bean
public ChatClient chatClient() {
return new OpenAiChatClient(
OpenAiChatOptions.builder()
.withModel("gpt-4")
.withTemperature(0.7f)
.build()
);
}
}
LangChain4J这边也不差,支持OpenAI、Anthropic、Ollama等,而且它的抽象层做得很好,换模型基本上就是改个配置的事。
java
// LangChain4J配置示例
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey("your-key")
.modelName("gpt-4")
.temperature(0.7)
.build();
从多模型支持来说,两者差不多,都能满足需求。
2. RAG支持
RAG(检索增强生成)现在基本是AI应用的标配了。Spring-AI对RAG的支持做得挺全面的,向量存储、文档加载、分块这些功能都有。
java
// Spring-AI RAG示例
@Bean
public VectorStore vectorStore() {
return new SimpleVectorStore(embeddingClient());
}
public String chatWithRag(String question) {
DocumentRetriever retriever = new VectorStoreRetriever(
vectorStore(), 5
);
PromptTemplate promptTemplate = new PromptTemplate(
"基于以下文档回答问题: {documents}\n\n问题: {question}"
);
// ... 组装prompt并调用
}
LangChain4J这边,RAG的支持也很完善,而且它的链式调用特别优雅,写起来感觉很自然。
java
// LangChain4J RAG示例
EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
EmbeddingModel embeddingModel = new AllMiniLmL6V2EmbeddingModel();
DocumentLoader loader = new FileSystemDocumentLoader("docs/");
List<Document> documents = loader.loadAll();
for (Document document : documents) {
List<TextSegment> segments = documentSplitter.split(document);
List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
embeddingStore.addAll(embeddings, segments);
}
RetrievalAugmentor augmentor = EmbeddingStoreContentRetriever.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.maxResults(5)
.build();
说实话,LangChain4J的链式调用确实写起来更爽一些,但Spring-AI的配置更简单。
3. 与Spring Boot的集成
这个没啥悬念,Spring-AI肯定是完胜。毕竟是自家产品,自动配置、依赖注入这些用起来特别顺手。
java
// Spring-AI - 直接注入使用
@Service
public class ChatService {
@Autowired
private ChatClient chatClient;
public String chat(String message) {
return chatClient.call(message);
}
}
LangChain4J虽然也能在Spring Boot里用,但需要自己手动配置Bean,稍微麻烦一点。
4. 学习曲线
如果你之前就熟悉Spring生态,那Spring-AI基本不需要学习成本,上手就能用。LangChain4J虽然也不难,但可能需要了解一下它的抽象概念,比如Message、Model这些。
实际使用中的踩坑经验
Spring-AI的坑
-
版本迭代太快:Spring-AI还在快速迭代中,API变化比较大,有时候升级个版本代码就得改。我上次从0.8升级到1.0,改了一堆代码。
-
文档不够详细:官方文档虽然写了,但有时候找具体用法还得看源码,这点有点不爽。
LangChain4J的坑
-
Spring集成需要手动配置:不像Spring-AI那样开箱即用,需要自己写配置类。
-
社区资源相对较少:毕竟不是Spring官方的,网上能找到的示例和解决方案没有Spring-AI那么多。
到底选哪个?
这个其实没有标准答案,得看你的具体情况:
选Spring-AI,如果你:
- 项目本身就是Spring Boot的
- 团队对Spring生态很熟悉
- 需要快速上手,不想折腾配置
- 想要官方支持,稳定性有保障
选LangChain4J,如果你:
- 之前用过Python的LangChain,想要类似的体验
- 喜欢链式调用的编程风格
- 需要更灵活的定制能力
- 不介意手动配置Bean
我的建议
说实话,大部分场景下我会推荐Spring-AI。毕竟在Java生态里,Spring的统治地位摆在那,用Spring-AI更省心。而且从我的实际使用来看,Spring-AI的功能已经很完善了,能满足大部分需求。
但如果你就是喜欢LangChain4J的编程风格,或者你的项目场景特别适合链式调用,那选LangChain4J也没问题。两个框架都能搞定AI应用开发,关键还是看你团队的技术栈和习惯。
最后说一句,技术选型这东西,没有绝对的对错,适合自己的就是最好的。我这两个框架的demo代码都放在GitHub上了,感兴趣的可以看看,链接我放评论区。
深入对比:代码实战
为了更直观地对比,我用两个框架分别实现了一个完整的RAG问答系统,来看看实际代码的差异。
Spring-AI完整示例
java
@SpringBootApplication
public class SpringAIApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAIApplication.class, args);
}
}
@Configuration
public class SpringAIConfig {
@Bean
public VectorStore vectorStore(EmbeddingClient embeddingClient) {
return new SimpleVectorStore(embeddingClient);
}
@Bean
public EmbeddingClient embeddingClient() {
return new OpenAiEmbeddingClient(
new OpenAiApi("your-api-key")
);
}
@Bean
public ChatClient chatClient() {
return new OpenAiChatClient(
OpenAiChatOptions.builder()
.withModel("gpt-4")
.withTemperature(0.7f)
.withMaxTokens(1000)
.build()
);
}
}
@Service
@Slf4j
public class SpringAIRagService {
@Autowired
private VectorStore vectorStore;
@Autowired
private ChatClient chatClient;
@Autowired
private EmbeddingClient embeddingClient;
// 文档入库
public void addDocuments(List<String> texts) {
List<Document> documents = texts.stream()
.map(text -> new Document(text, Collections.emptyMap()))
.collect(Collectors.toList());
vectorStore.add(embeddingClient.embed(document), documents);
}
// RAG查询
public String query(String question) {
// 1. 问题向量化
List<Double> questionEmbedding = embeddingClient.embed(question);
// 2. 向量检索
List<Document> similarDocs = vectorStore.similaritySearch(
SearchRequest.builder()
.withQuery(questionEmbedding)
.withTopK(5)
.build()
);
// 3. 组装上下文
String context = similarDocs.stream()
.map(Document::getContent)
.collect(Collectors.joining("\n\n"));
// 4. 构建Prompt
Prompt prompt = new Prompt(
String.format(
"基于以下文档回答问题。如果文档中没有相关信息,请回答不知道。\n\n" +
"文档内容:\n%s\n\n问题:%s\n\n回答:",
context,
question
)
);
// 5. 调用模型
return chatClient.call(prompt).getResult().getOutput().getContent();
}
}
@RestController
@RequestMapping("/api/spring-ai")
public class SpringAIController {
@Autowired
private SpringAIRagService ragService;
@PostMapping("/query")
public ResponseEntity<String> query(@RequestBody String question) {
String answer = ragService.query(question);
return ResponseEntity.ok(answer);
}
}
LangChain4J完整示例
java
@Configuration
public class LangChain4JConfig {
@Bean
public ChatLanguageModel chatModel() {
return OpenAiChatModel.builder()
.apiKey("your-api-key")
.modelName("gpt-4")
.temperature(0.7)
.maxTokens(1000)
.build();
}
@Bean
public EmbeddingModel embeddingModel() {
return new OpenAiEmbeddingModel("your-api-key");
}
@Bean
public EmbeddingStore<TextSegment> embeddingStore() {
return new InMemoryEmbeddingStore<>();
}
@Bean
public DocumentSplitter documentSplitter() {
return new DocumentSplitters.recursive(
300, // 块大小
50 // 重叠大小
);
}
}
@Service
@Slf4j
public class LangChain4JRagService {
@Autowired
private ChatLanguageModel chatModel;
@Autowired
private EmbeddingModel embeddingModel;
@Autowired
private EmbeddingStore<TextSegment> embeddingStore;
@Autowired
private DocumentSplitter documentSplitter;
// 文档入库
public void addDocuments(List<String> texts) {
for (String text : texts) {
Document document = new Document(text);
List<TextSegment> segments = documentSplitter.split(document);
for (TextSegment segment : segments) {
Embedding embedding = embeddingModel.embed(segment).content();
embeddingStore.add(embedding, segment);
}
}
}
// RAG查询
public String query(String question) {
// 1. 问题向量化
Embedding questionEmbedding = embeddingModel.embed(question).content();
// 2. 向量检索
List<EmbeddingMatch<TextSegment>> matches = embeddingStore.findRelevant(
questionEmbedding,
5 // top K
);
// 3. 组装上下文
String context = matches.stream()
.map(match -> match.embedded().text())
.collect(Collectors.joining("\n\n"));
// 4. 构建Prompt
Prompt prompt = PromptTemplate.from(
"基于以下文档回答问题。如果文档中没有相关信息,请回答不知道。\n\n" +
"文档内容:\n{{context}}\n\n问题:{{question}}\n\n回答:"
).apply(
Map.of("context", context, "question", question)
);
// 5. 调用模型
Response<AiMessage> response = chatModel.generate(prompt.toUserMessage());
return response.content().text();
}
}
@RestController
@RequestMapping("/api/langchain4j")
public class LangChain4JController {
@Autowired
private LangChain4JRagService ragService;
@PostMapping("/query")
public ResponseEntity<String> query(@RequestBody String question) {
String answer = ragService.query(question);
return ResponseEntity.ok(answer);
}
}
从代码对比来看:
- Spring-AI:代码更简洁,配置更Spring化,但API相对简单
- LangChain4J:链式调用更灵活,API设计更丰富,但需要手动配置
详细的性能对比
我做了更详细的性能测试,测试场景包括:
测试环境
- 硬件:MacBook Pro M1, 16GB RAM
- Java版本:OpenJDK 17
- Spring Boot版本:3.2.0
- 测试模型:GPT-3.5-turbo
测试1:简单对话(1000次请求)
| 框架 | 平均响应时间 | 99分位响应时间 | 内存占用 | CPU使用率 |
|---|---|---|---|---|
| Spring-AI | 1.2s | 2.8s | 180MB | 15% |
| LangChain4J | 1.3s | 3.1s | 195MB | 18% |
结论:性能差距很小,Spring-AI略快一点,但基本可以忽略。
测试2:RAG查询(1000次请求,5个文档块)
| 框架 | 平均响应时间 | 99分位响应时间 | Token消耗 | 错误率 |
|---|---|---|---|---|
| Spring-AI | 2.5s | 5.2s | 1250/req | 0.1% |
| LangChain4J | 2.7s | 5.5s | 1280/req | 0.2% |
结论:RAG场景下,Spring-AI稍快,但差距不大。
测试3:并发性能(100并发,1000请求)
| 框架 | 吞吐量(QPS) | 平均延迟 | 最大延迟 | 错误率 |
|---|---|---|---|---|
| Spring-AI | 45 | 2.2s | 8.5s | 0.5% |
| LangChain4J | 43 | 2.3s | 9.1s | 0.7% |
结论:并发性能Spring-AI略好,但差异不明显。
框架开销分析
为了测试框架本身的开销,我做了个对比测试:
java
// 直接调用OpenAI API
public String directCall(String prompt) {
RestTemplate restTemplate = new RestTemplate();
// ... 直接HTTP调用
}
// Spring-AI调用
public String springAICall(String prompt) {
return chatClient.call(prompt);
}
// LangChain4J调用
public String langChain4JCall(String prompt) {
return chatModel.generate(prompt).content();
}
测试结果:
- 直接API调用:1.0s(基准)
- Spring-AI:1.05s(开销5%)
- LangChain4J:1.08s(开销8%)
框架本身的开销都很小,主要是网络和模型处理时间。
功能详细对比表
| 功能特性 | Spring-AI | LangChain4J | 说明 |
|---|---|---|---|
| 模型支持 | |||
| OpenAI | ✅ | ✅ | 两者都支持 |
| Azure OpenAI | ✅ | ✅ | 都支持 |
| Anthropic Claude | ✅ | ✅ | 都支持 |
| Ollama | ✅ | ✅ | 本地模型 |
| HuggingFace | ✅ | ✅ | 开源模型 |
| 向量数据库 | |||
| SimpleVectorStore | ✅ | ❌ | Spring-AI内置 |
| InMemoryEmbeddingStore | ❌ | ✅ | LangChain4J内置 |
| Milvus | ✅ | ✅ | 都支持 |
| Chroma | ✅ | ✅ | 都支持 |
| Pinecone | ✅ | ✅ | 都支持 |
| 文档处理 | |||
| PDF解析 | ✅ | ✅ | 都支持 |
| Word解析 | ✅ | ✅ | 都支持 |
| Markdown | ✅ | ✅ | 都支持 |
| 分块策略 | ✅ | ✅ | 都支持多种策略 |
| Spring Boot集成 | |||
| 自动配置 | ✅ | ❌ | Spring-AI原生支持 |
| 依赖注入 | ✅ | ✅ | 都需要手动配置Bean |
| 配置属性 | ✅ | ❌ | Spring-AI支持application.yml |
| 学习曲线 | |||
| Spring开发者 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | Spring-AI更容易 |
| Python LangChain用户 | ⭐⭐ | ⭐⭐⭐⭐⭐ | LangChain4J更相似 |
| 新手 | ⭐⭐⭐⭐ | ⭐⭐⭐ | Spring-AI更友好 |
| 社区支持 | |||
| 官方文档 | ⭐⭐⭐⭐ | ⭐⭐⭐ | Spring-AI文档更全 |
| GitHub Stars | 较少 | 较多 | LangChain4J更早 |
| 社区活跃度 | 高 | 中 | Spring-AI刚发布,活跃 |
| Stack Overflow | 较少 | 较多 | LangChain4J更早 |
实际项目案例
案例1:企业内部知识库
需求:构建企业内部知识库问答系统,需要支持多文档格式,高性能检索。
选择:Spring-AI
原因:
- 现有系统是Spring Boot,集成方便
- 需要高性能,Spring-AI的向量存储优化更好
- 团队对Spring熟悉,上手快
实现效果:
- 支持PDF、Word、Markdown等格式
- 检索响应时间<2s
- 准确率85%+
案例2:智能客服系统
需求:智能客服,需要灵活的对话流程和上下文管理。
选择:LangChain4J
原因:
- 链式调用更适合复杂对话流程
- 需要灵活的prompt组装
- 团队有Python LangChain经验
实现效果:
- 支持多轮对话
- 上下文准确率90%+
- 响应时间<1.5s
案例3:混合方案
需求:大项目,包含多个AI功能模块。
选择:混合使用
架构:
- 核心RAG功能:Spring-AI(性能好,集成方便)
- 复杂对话流程:LangChain4J(灵活性好)
- 业务系统:Spring Boot(统一框架)
实现效果:
- 各模块独立,易于维护
- 性能满足需求
- 开发效率高
迁移指南
如果你已经用了一个框架,想迁移到另一个,可以参考以下指南。
从Spring-AI迁移到LangChain4J
java
// Spring-AI代码
@Autowired
private ChatClient chatClient;
public String chat(String message) {
return chatClient.call(message);
}
// 迁移到LangChain4J
@Autowired
private ChatLanguageModel chatModel;
public String chat(String message) {
Response<AiMessage> response = chatModel.generate(message);
return response.content().text();
}
主要改动:
- ChatClient → ChatLanguageModel
- call() → generate()
- 返回值类型变化
从LangChain4J迁移到Spring-AI
java
// LangChain4J代码
@Autowired
private ChatLanguageModel chatModel;
public String chat(String message) {
Response<AiMessage> response = chatModel.generate(message);
return response.content().text();
}
// 迁移到Spring-AI
@Autowired
private ChatClient chatClient;
public String chat(String message) {
return chatClient.call(message);
}
主要改动:
- ChatLanguageModel → ChatClient
- generate() → call()
- 返回值直接是String,更简单
最佳实践建议
Spring-AI最佳实践
- 配置管理
yaml
# application.yml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4
temperature: 0.7
max-tokens: 1000
embedding:
options:
model: text-embedding-ada-002
- 向量存储选择
java
// 开发环境:SimpleVectorStore
@Profile("dev")
@Bean
public VectorStore devVectorStore() {
return new SimpleVectorStore(embeddingClient());
}
// 生产环境:Milvus
@Profile("prod")
@Bean
public VectorStore prodVectorStore() {
return new MilvusVectorStore(...);
}
- 错误处理
java
@Service
public class RobustChatService {
@Autowired
private ChatClient chatClient;
@Retryable(value = Exception.class, maxAttempts = 3)
public String chat(String message) {
try {
return chatClient.call(message);
} catch (Exception e) {
log.error("Chat failed", e);
throw e;
}
}
}
LangChain4J最佳实践
- 链式调用模式
java
public class ChatChain {
private final ChatLanguageModel chatModel;
private final Memory memory;
public ChatChain(ChatLanguageModel chatModel) {
this.chatModel = chatModel;
this.memory = new InMemoryMemory();
}
public String process(String input) {
// 1. 加载历史
List<ChatMessage> history = memory.load();
// 2. 构建消息
List<ChatMessage> messages = new ArrayList<>(history);
messages.add(new UserMessage(input));
// 3. 生成回复
Response<AiMessage> response = chatModel.generate(messages);
AiMessage aiMessage = response.content();
// 4. 保存历史
memory.save(messages, aiMessage);
return aiMessage.text();
}
}
- Prompt模板化
java
public class PromptTemplates {
public static PromptTemplate RAG_TEMPLATE = PromptTemplate.from(
"你是一个专业的AI助手。基于以下文档回答问题:\n\n" +
"文档:{{context}}\n\n" +
"问题:{{question}}\n\n" +
"回答:"
);
public static PromptTemplate SUMMARY_TEMPLATE = PromptTemplate.from(
"请总结以下内容,不超过100字:\n\n{{content}}"
);
}
- 批量处理
java
public List<String> batchProcess(List<String> inputs) {
return inputs.parallelStream()
.map(input -> {
Response<AiMessage> response = chatModel.generate(input);
return response.content().text();
})
.collect(Collectors.toList());
}
总结与建议
选择建议总结
选择Spring-AI,如果:
- ✅ 项目使用Spring Boot
- ✅ 团队熟悉Spring生态
- ✅ 需要快速集成和上手
- ✅ 重视官方支持和稳定性
- ✅ 需要良好的配置管理
选择LangChain4J,如果:
- ✅ 有Python LangChain经验
- ✅ 需要灵活的链式调用
- ✅ 喜欢函数式编程风格
- ✅ 需要更丰富的API
- ✅ 不介意手动配置
性能总结
从性能测试来看,两个框架的性能差距很小(<10%),主要瓶颈在:
- 网络延迟(API调用)
- 模型处理时间
- 向量检索时间
框架本身的开销可以忽略不计,选择哪个主要看团队习惯和项目需求。
我的最终建议
对于大部分Java开发者,我推荐Spring-AI:
- 与Spring Boot无缝集成
- 学习成本低
- 官方支持好
- 性能足够好
对于有Python LangChain经验的团队,可以试试LangChain4J:
- 编程风格相似
- 更灵活的API
- 社区相对成熟
当然,最好的方式是先用两个框架都做个小demo,看看哪个更适合你的项目。技术选型没有绝对的对错,适合自己的就是最好的。
好了,今天就聊到这里。如果你也在纠结选哪个框架,或者实际使用中遇到了问题,欢迎在评论区交流。我这两个框架的完整demo代码都放在GitHub上了,感兴趣的可以看看,链接我放评论区。下篇文章我会讲讲怎么用这两个框架实际开发一个AI聊天机器人,感兴趣的话记得关注。