FileAgent实战Spring-AI-Alibaba和Langchain4J深度对比
本文通过FileAgent项目实战对比了Spring AI Alibaba和Langchain4J两个Java AI开发框架。Spring AI Alibaba深度集成Spring Boot,代码简洁但依赖外部SkillManager;Langchain4J社区活跃,支持多模型但代码量较大。两者在工具定义方式、模型支持等方面各有优劣,为Java开发者选择AI框架提供了实用参考。
FileAgent 实战:Spring AI Alibaba vs Langchain4J 深度对比
摘要:本文通过实际开发 FileAgent(文件操作 AI Agent)项目,深入对比 Spring AI Alibaba 和 Langchain4J 两个 Java AI 开发框架的差异、优缺点及适用场景。包含完整代码对比、架构分析和实践经验总结。
一、项目背景
在 AI Agent 开发领域,Java 开发者面临两个主流选择:Spring AI Alibaba 和 Langchain4J。为了客观对比两者,我使用这两个框架分别实现了相同的 FileAgent 项目——一个能够通过自然语言对话进行文件操作(查看磁盘、列出目录、读写文件等)的 AI Agent。
项目功能
- 自然语言对话交互
- 查看磁盘驱动器信息
- 列出目录内容
- 📏 获取文件/目录大小
- 📄 读取文件内容
- ✏️ 创建和编辑文件
- 🗑️ 删除文件/目录
- 💾 会话管理和历史记录
二、技术栈对比
2.1 核心依赖
Spring AI Alibaba 版本
<!-- Spring Alibaba AI -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.0.0-M6.1</version>
</dependency>
- 版本: 1.0.0-M6.1(里程碑版本)
- 生态: Spring AI 官方扩展,深度集成 Spring Boot
- 模型支持: 阿里云通义千问系列(qwen-plus, qwen-max, qwen-turbo)
Langchain4J 版本
<!-- Langchain4J Core -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>0.36.2</version>
</dependency>
<!-- Langchain4J OpenAI -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>0.36.2</version>
</dependency>
<!-- Langchain4J Spring Boot Starter -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>0.36.2</version>
</dependency>
- 版本: 0.36.2
- 生态: 社区活跃,兼容 OpenAI API
- 模型支持: 通过 OpenAI 兼容 API 可连接多种模型(通义千问、智谱、文心一言等)
2.2 依赖对比总结
| 维度 | Spring AI Alibaba | Langchain4J |
|---|---|---|
| 成熟度 | 里程碑版本(M6.1) | 稳定版本(0.36.2) |
| 官方支持 | 阿里云官方 | 社区驱动 |
| 模型生态 | 专注阿里云模型 | 支持多模型(OpenAI、Anthropic、HuggingFace等) |
| Spring 集成 | 原生深度集成 | 通过 Starter 集成 |
| 文档完善度 | 相对较少 | 文档丰富 |
三、核心代码对比
3.1 工具定义方式
这是两个框架最显著的差异点。
Spring AI Alibaba 版本(85 行)
@Component
public class FileTools {
private final SkillManager skillManager;
public FileTools(SkillManager skillManager) {
this.skillManager = skillManager;
}
/**
* 查看磁盘信息
*/
public String listDisk(String params) {
return skillManager.executeSkill("list_disk");
}
/**
* 列出目录内容
* @param path 目录路径
*/
public String listFiles(String path) {
return skillManager.executeSkill("list_files", path);
}
/**
* 读取文件内容
* @param path 文件路径
* @param maxLines 最大行数(可选)
*/
public String readFile(String path, Integer maxLines) {
if (maxLines != null) {
return skillManager.executeSkill("read_file", path, String.valueOf(maxLines));
}
return skillManager.executeSkill("read_file", path);
}
// ... 其他方法类似
}
特点:
- ✅ 代码简洁,职责清晰
- ✅ 通过
SkillManager统一管理技能 - ✅ 易于扩展和维护
- ❌ 依赖外部
SkillManager实现 - ❌ 需要额外编写 Skill 脚本
Langchain4J 版本(236 行)
@Component
public class FileTools {
private static final Logger log = LoggerFactory.getLogger(FileTools.class);
@Tool("列出所有磁盘驱动器及容量信息")
public String listDisk() {
try {
File[] roots = File.listRoots();
StringBuilder sb = new StringBuilder("磁盘驱动器列表:\n");
for (File root : roots) {
long totalSpace = root.getTotalSpace();
long freeSpace = root.getFreeSpace();
long usedSpace = totalSpace - freeSpace;
double totalGB = totalSpace / (1024.0 * 1024 * 1024);
double freeGB = freeSpace / (1024.0 * 1024 * 1024);
double usedGB = usedSpace / (1024.0 * 1024 * 1024);
sb.append(String.format(" %s - 总容量: %.2f GB, 已用: %.2f GB, 可用: %.2f GB\n",
root.getPath(), totalGB, usedGB, freeGB));
}
return sb.toString();
} catch (Exception e) {
log.error("获取磁盘信息失败", e);
return "获取磁盘信息失败: " + e.getMessage();
}
}
@Tool("读取文件内容。参数: filePath - 文件路径(可选参数: maxLength - 最大读取长度)")
public String readFile(String args) {
try {
// 智能解析参数:支持单个参数或多个参数(用|分隔)
String filePath;
Integer maxLength = null;
if (args.contains("|")) {
// 多参数格式: filePath|maxLength
String[] parts = args.split("\\|", 2);
filePath = parts[0].trim();
if (parts.length > 1 && !parts[1].trim().isEmpty()) {
maxLength = Integer.parseInt(parts[1].trim());
}
} else {
// 单参数格式: 仅文件路径
filePath = args.trim();
}
log.info("读取文件请求 - 路径: {}, 最大长度: {}", filePath, maxLength);
Path path = Paths.get(filePath);
if (!Files.exists(path)) {
return "文件不存在: " + filePath;
}
if (!Files.isRegularFile(path)) {
return "路径不是文件: " + filePath;
}
String content = Files.readString(path);
log.info("成功读取文件: {}, 内容长度: {} 字符", filePath, content.length());
if (maxLength != null && content.length() > maxLength) {
content = content.substring(0, maxLength) + "\n... (内容被截断,总长度: " + content.length() + " 字符)";
}
return "文件内容 (" + filePath + "):\n" + content;
} catch (NumberFormatException e) {
log.error("参数格式错误: {}", args, e);
return "参数格式错误,请使用: 文件路径 或 文件路径|最大长度";
} catch (Exception e) {
log.error("读取文件失败: {}", args, e);
return "读取文件失败: " + e.getMessage();
}
}
// ... 其他方法类似
}
特点:
- ✅ 使用
@Tool注解,语义清晰 - ✅ 工具实现完整,自包含
- ✅ 智能参数解析,支持灵活调用
- ✅ 完善的日志和错误处理
- ❌ 代码较长,每个工具需单独实现
- 参数解析需要手动处理
3.2 AI Agent 构建方式
Spring AI Alibaba 版本
@Service
public class ChatService {
private final ChatClient chatClient;
private final FileTools fileTools;
public ChatService(ChatClient.Builder chatClientBuilder, FileTools fileTools) {
this.fileTools = fileTools;
this.chatClient = chatClientBuilder.build();
}
public String chat(String message, String sessionId) {
// 使用 ChatMemory 管理会话
ChatMemory chatMemory = getOrCreateSession(sessionId);
// 构建消息并添加 Function Callback
Prompt prompt = new Prompt(
message,
ChatMemory.builder()
.messages(chatMemory.getMessages())
.build(),
FunctionCallingOptions.builder()
.functionCallbacks(List.of(
FunctionCallback.builder()
.function("listDisk", fileTools::listDisk)
.description("列出所有磁盘驱动器及容量信息")
.build(),
FunctionCallback.builder()
.function("readFile", fileTools::readFile)
.description("读取文件内容")
.build()
// ... 其他函数
))
.build()
);
ChatResponse response = chatClient.call(prompt);
return response.getResult().getOutput().getText();
}
}
Langchain4J 版本
@Service
public class ChatService {
private final FileTools fileTools;
private final Map<String, ChatMemory> sessions = new ConcurrentHashMap<>();
public ChatService(FileTools fileTools) {
this.fileTools = fileTools;
}
private ChatLanguageModel createChatModel() {
return OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName(model)
.baseUrl(baseUrl)
.temperature(0.7)
.build();
}
public String chat(String message, String sessionId) {
ChatMemory memory = getOrCreateSession(sessionId);
memory.add(UserMessage.from(message));
// 使用 AiServices 构建 Agent,自动识别 @Tool 注解
FileAgent agent = AiServices.builder(FileAgent.class)
.chatLanguageModel(createChatModel())
.chatMemory(memory)
.tools(fileTools)
.build();
String response = agent.chat(message);
memory.add(AssistantMessage.from(response));
saveSession(sessionId);
return response;
}
// 定义 Agent 接口
public interface FileAgent {
String chat(String message);
}
}
对比分析:
| 维度 | Spring AI Alibaba | Langchain4J |
|---|---|---|
| Agent 构建 | 手动注册 FunctionCallback | 自动识别 @Tool 注解 |
| 代码复杂度 | 较高(需手动配置) | 较低(声明式) |
| 扩展性 | 灵活但繁琐 | 简洁但需遵循约定 |
| 类型安全 | 弱类型(字符串) | 强类型(接口定义) |
3.3 会话管理
Spring AI Alibaba 版本
private ChatMemory getOrCreateSession(String sessionId) {
return sessions.computeIfAbsent(sessionId, id ->
MessageWindowChatMemory.withMaxMessages(20)
);
}
Langchain4J 版本
private ChatMemory getOrCreateSession(String sessionId) {
return sessions.computeIfAbsent(sessionId, id -> {
Path sessionFile = getHistoryFilePath(id);
if (Files.exists(sessionFile)) {
try {
String json = Files.readString(sessionFile);
return ChatMemorySerializer.fromJson(json);
} catch (Exception e) {
log.warn("加载会话历史失败: {}", id, e);
}
}
return MessageWindowChatMemory.withMaxMessages(20);
});
}
对比:
- Langchain4J 版本支持持久化,会话历史可保存到文件
- Spring AI Alibaba 版本默认在内存中,需自行实现持久化
四、功能特性对比
4.1 流式响应支持
两者都支持 SSE(Server-Sent Events)流式输出:
Spring AI Alibaba
@PostMapping(value = "/stream", produces = "text/event-stream;charset=UTF-8")
public Flux<String> streamChat(@RequestBody ChatRequest request) {
return chatService.streamChat(request.getMessage(), request.getSessionId());
}
public Flux<String> streamChat(String message, String sessionId) {
return Flux.create(sink -> {
chatClient.stream(new Prompt(message))
.doOnNext(response -> {
String text = response.getResult().getOutput().getText();
if (text != null) {
sink.next("data: " + text + "\n\n");
}
})
.doOnComplete(() -> sink.complete())
.doOnError(sink::error)
.subscribe();
});
}
Langchain4J
@PostMapping(value = "/stream", produces = "text/event-stream;charset=UTF-8")
public Flux<String> streamChat(@RequestBody ChatRequest request) {
return chatService.streamChat(request.getMessage(), request.getSessionId());
}
public Flux<String> streamChat(String message, String sessionId) {
return Flux.create(sink -> {
StreamingChatLanguageModel streamingModel = OpenAiStreamingChatModel.builder()
.apiKey(apiKey)
.modelName(model)
.baseUrl(baseUrl)
.build();
streamingModel.generate(
getOrCreateSession(sessionId).messages(),
new StreamingResponseHandler() {
@Override
public void onPartialResponse(String partialResponse) {
sink.next("data: " + partialResponse + "\n\n");
}
@Override
public void onCompleteResponse(ChatResponse completeResponse) {
sink.complete();
}
@Override
public void onError(Throwable error) {
sink.error(error);
}
}
);
});
}
4.2 REST API 接口
两个版本的 API 接口完全对齐:
POST /api/chat - 非流式对话
POST /api/chat/stream - 流式对话(SSE)
GET /api/chat/sessions - 获取会话列表
GET /api/chat/session/{id} - 获取会话历史
DELETE /api/chat/session/{id} - 删除会话
DELETE /api/chat/sessions - 清空所有会话
4.3 前端界面
两个版本复用相同的前端页面设计:
- ✅ 现代化聊天界面
- ✅ 实时流式响应显示
- ✅ 会话管理(新建/切换/删除)
- ✅ 快速操作按钮
- ✅ Markdown 渲染(可选)
五、优缺点总结
5.1 Spring AI Alibaba
✅ 优点
- 官方支持:阿里云官方出品,持续迭代
- 深度集成:与 Spring Boot 3.x 完美融合
- 模型优化:针对通义千问系列模型深度优化
- 企业级特性:支持流式输出、Function Calling 等企业级功能
- 生态系统:可与其他阿里云服务无缝集成
缺点
- 版本不成熟:仍为里程碑版本(M6.1),API 可能变动
- 文档不足:官方文档相对较少,社区资源有限
- 模型限制:主要支持阿里云模型,灵活性较低
- 学习曲线:Function Callback 机制较复杂
- 技能管理:依赖外部 SkillManager,需额外配置
5.2 Langchain4J
✅ 优点
- 功能丰富:支持多种 AI 模型和提供商
- API 简洁:@Tool 注解声明式编程,代码清晰
- 类型安全:通过接口定义 Agent,编译期检查
- 生态活跃:社区活跃,文档完善
- 灵活性强:可通过 OpenAI 兼容 API 连接多种模型
- 内置功能:自带会话持久化、向量存储等
❌ 缺点
- 非官方:社区驱动,缺乏大厂背书
- 代码冗余:每个工具需完整实现,代码量较大
- 参数解析:需手动处理参数格式(如
|分隔) - Spring 集成:通过 Starter 间接集成,深度不如 Spring AI
- 模型适配:连接阿里云模型需通过兼容模式,可能有功能差异
六、选择建议
6.1 选择 Spring AI Alibaba 的场景
- ✅ 企业项目:已使用阿里云生态,需要深度集成
- ✅ 通义千问专用:主要使用通义千问系列模型
- ✅ 团队要求:团队熟悉 Spring 生态,偏好官方方案
- ✅ 长期维护:需要大厂持续支持和版本保障
6.2 选择 Langchain4J 的场景
- ✅ 多模型需求:需要灵活切换不同 AI 模型
- ✅ 快速开发:希望用最少代码实现功能
- ✅ 社区活跃:依赖社区文档和示例
- ✅ 灵活性优先:不受限于单一模型提供商
- ✅ 学术研究:需要尝试各种 AI 技术和框架
6.3 综合对比
| 维度 | Spring AI Alibaba | Langchain4J | 推荐 |
|---|---|---|---|
| 易用性 | ⭐⭐ | ⭐⭐⭐⭐⭐ | Langchain4J |
| 灵活性 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Langchain4J |
| 企业支持 | ⭐⭐⭐⭐ | ⭐⭐⭐ | Spring AI Alibaba |
| 文档完善 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Langchain4J |
| 模型生态 | ⭐⭐ | ⭐⭐⭐⭐⭐ | Langchain4J |
| Spring 集成 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | Spring AI Alibaba |
| 类型安全 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | Langchain4J |
| 成熟度 | ⭐⭐⭐ | ⭐⭐⭐⭐ | Langchain4J |
七、项目源码
两个版本的 FileAgent 项目均已开源,欢迎 Star 和 Fork:
Spring AI Alibaba 版本
- Gitee 地址: https://gitee.com/mobuhan/fileagent
- 📦 技术栈: Spring Boot 3.2.5 + Spring AI Alibaba 1.0.0-M6.1
- 模型: 阿里云通义千问 qwen-turbo
- 📝 代码行数: 约 500 行(核心功能)
Langchain4J 版本
- 🌐 Gitee 地址: https://gitee.com/mobuhan/langchain4j-fileagent
- 📦 技术栈: Spring Boot 3.2.5 + Langchain4J 0.36.2
- 模型: 阿里云通义千问 qwen-turbo(通过 OpenAI 兼容 API)
- 📝 代码行数: 约 800 行(核心功能)
八、快速开始
8.1 环境要求
- Java 17+
- Maven 3.8+
- 阿里云 API Key(获取地址)
8.2 启动步骤
# 1. 克隆项目
git clone https://gitee.com/mobuhan/langchain4j-fileagent.git
# 或
git clone https://gitee.com/mobuhan/fileagent.git
# 2. 配置 API Key
cd langchain4j-fileagent
cp src/main/resources/application-example.yml src/main/resources/application.yml
# 编辑 application.yml,填入 API Key
# 3. 启动项目
mvn spring-boot:run
# 4. 访问应用
# 打开浏览器访问: http://localhost:8081
8.3 示例对话
用户: 帮我查看一下 D 盘有哪些文件
AI: 正在查看 D 盘目录内容...
目录内容 (D:\):
[DIR] Program Files
[DIR] Program Files (x86)
[DIR] Users
[FILE] aa.txt 1234 bytes
[FILE] test.txt 5678 bytes
用户: 帮我读取 D:\aa.txt 这个文件里的内容
AI: 正在读取文件内容...
文件内容 (D:\aa.txt):
这是一个测试文件,用于验证 FileAgent 的文件读取功能。
第二行内容...
九、总结
通过实际开发对比,两个框架各有优劣:
-
Spring AI Alibaba 更适合企业级项目,特别是已深度使用阿里云生态的团队。它的优势在于官方支持和深度集成,但目前在灵活性和文档完善度上有所欠缺。
-
Langchain4J 更适合快速开发和原型验证,其声明式编程风格和丰富的功能让开发者能够更快地上手。如果你需要灵活切换不同 AI 模型,或者希望有更完善的社区支持,Langchain4J 是更好的选择。
我的建议:
- 如果是生产环境且主要使用阿里云服务,选择 Spring AI Alibaba
- 如果是快速开发或需要多模型支持,选择 Langchain4J
- 如果不确定,可以先使用 Langchain4J 验证功能,后期再根据需求迁移
两个项目我都已开源,欢迎大家尝试、对比,并在评论区分享你的使用体验!
十、参考资料
标签: AI Agent Spring AI Langchain4J 通义千问 Function Calling Java 人工智能
版权声明: 本文为原创文章,转载请注明出处。项目源码已开源,欢迎 Star 和 Fork!
更多推荐



所有评论(0)