在人工智能(AI)代理开发的浪潮中,Python似乎一直是默认的编程语言选择。然而,Java虚拟机(JVM)平台正在以其强大的类型安全、优雅的体系结构和企业级生态系统,挑战这一现状。Rod Johnson在2025年8月发表的文章《You Can Build Better AI Agents in Java Than Python》以及Embabel代理框架的GitHub文档,为我们展示了Java在AI代理开发中的独特优势。通过一个具体的书籍写作案例,我们将深入探索Java如何以更少的代码、更高的可扩展性和更强的类型安全性,超越Python的CrewAI框架,创造出更高效、更优雅的AI代理。
---
## 📚 从愿景到现实:书籍写作的AI代理场景
想象一下,你是一位作者,梦想创作一本关于“2025年7月人工智能现状”的书籍。你需要一个AI系统,能够自动研究主题、生成大纲、撰写章节,并最终整合成一本完整的Markdown格式书籍。这样的任务看似复杂,但通过AI代理的协作,可以分解为清晰的步骤,高效完成。Rod Johnson选择了CrewAI框架中的“Write a Book Flow”示例作为基准,将其用Java的Embabel框架重写,展示Java在AI代理开发中的优势。
> **什么是“Write a Book Flow”?**
> 这个流程通过多个AI代理协作完成书籍创作:首先,`OutlineCrew`研究主题并生成书籍大纲;然后,`WriteBookChapterCrew`为每个章节撰写内容;最后,将所有章节整合为一个Markdown文件。这是一个典型的多代理协作场景,适合展示框架的能力。
---
## 🧬 CrewAI的Python实现:直观但繁琐
### 🛠️ CrewAI的核心概念
CrewAI是一个流行的Python代理框架,通过“crew”(代理团队)组织任务。每个crew包含多个代理(agent),每个代理有特定的角色(role)、目标(goal)和背景故事(backstory)。任务通过YML文件定义,Python代码负责将代理和任务连接起来。Pydantic模型用于约束大语言模型(LLM)的输出,确保结构化数据。
在书籍写作示例中,CrewAI的实现分为两个crew:
1. **OutlineCrew**:包含两个代理:
- **Researcher**:负责研究书籍主题,收集关键信息。
- **Outliner**:根据研究结果生成书籍大纲,包含章节标题和描述。
2. **WriteBookChapterCrew**:为每个章节分配一个代理,撰写内容并进行进一步研究。
Python代码通过`@CrewBase`装饰器定义crew,通过`@agent`和`@task`装饰器配置代理和任务,最终在`main.py`中通过`BookFlow`类协调整个流程。异步编程(`asyncio`)用于并行撰写章节,Pydantic模型(如`ChapterOutline`和`BookOutline`)提供数据结构支持。
### 💪 CrewAI的优点
CrewAI的实现直观且模块化:
- **任务分解**:将复杂任务拆分为研究、大纲生成和章节撰写,清晰分工。
- **LLM灵活性**:每个代理可以使用不同的LLM和工具(如SerperDevTool进行网络搜索)。
- **结构化输出**:Pydantic模型确保LLM输出的数据格式一致。
- **并行处理**:通过`asyncio`实现章节的并发撰写,提高效率。
> **比喻:像一个交响乐团**
> CrewAI就像一个交响乐团,每个代理是乐手,演奏特定乐器(任务)。指挥(Python代码)协调乐手,确保音乐(书籍)和谐完成。然而,乐谱(YML配置)繁琐,乐手间的协作(数据流)不够明确。
### ⚠️ CrewAI的不足
尽管CrewAI功能强大,但也存在显著的短板:
- **配置繁琐**:需要多个YML文件和Python代码,设置复杂,涉及多个目录和文件。
- **类型安全性不足**:代理和任务的输入依赖“魔法字符串”(如`{topic}`),容易出错,且`@listen`装饰器的参数无类型约束。
- **代理与任务耦合**:代理知道输入键(如`topic`),限制了复用性,代理与任务的划分显得冗余。
- **并发控制不佳**:章节撰写的并发由LLM决定章节数量,可能导致速率限制问题。
- **生产环境适配性**:缺乏日志框架支持,难以满足企业级需求。
> **比喻:拼装玩具的挑战**
> CrewAI就像一套复杂的拼装玩具,说明书(YML)冗长,零件(代理和任务)需要手动拼接,且容易因为零件标记不清(魔法字符串)而出错。
---
## 🚀 Embabel的Java实现:优雅与力量的结合
Embabel是一个专为JVM设计的代理框架,基于Spring框架,利用Java或Kotlin的强类型特性和企业级生态,提供了更简洁、更安全的AI代理开发方式。Rod Johnson通过重写CrewAI的书籍写作示例,展示了Embabel的优越性。
### 🌟 Embabel的核心概念
Embabel通过以下概念组织代理流程:
- **动作(Actions)**:代理执行的具体步骤。
- **目标(Goals)**:代理希望实现的状态。
- **条件(Conditions)**:动作执行前的状态检查。
- **领域模型(Domain Model)**:支撑流程的对象,包含行为。
- **计划(Plan)**:由系统动态生成的动作序列,基于目标导向动作规划(GOAP)算法。
> **什么是GOAP?**
> GOAP(Goal-Oriented Action Planning)是一种在游戏AI中常用的规划算法,允许系统根据当前状态和目标动态选择动作序列。Embabel利用GOAP实现智能路径规划,无需开发者手动定义流程顺序。
Embabel的关键优势包括:
- **动态规划**:系统根据动作的输入输出类型自动推导执行顺序,减少手动配置。
- **强类型安全**:所有提示(prompt)和数据流基于领域对象,消除魔法字符串。
- **Spring集成**:利用Spring的依赖注入、配置管理和AOP,简化开发并增强生产能力。
- **可测试性**:支持单元测试和端到端测试,确保代码可靠性。
### 🖥️ Embabel的代码实现
在Embabel中,书籍写作流程被简化为一个Java类(`BookWriter`)和一个YML配置文件(`application.yml`)。以下是核心实现:
#### **YML配置**
```yaml
examples:
book-writer:
max-concurrency: 8
researcher-llm:
model: gpt-4.1-nano
temperature: 0.7
writer-llm:
model: gpt-4.1-mini
researcher:
role: Researcher
goal: >
Gather comprehensive information about a topic that will be used
to create an organized and well-structured book outline.
Consider the author's desired goal for the book.
backstory: >
You are an experienced researcher skilled in finding the most relevant and up-to-date information on any given topic.
outliner:
role: Outliner
goal: >
Based on research, generate a book outline about the given topic.
The generated outline should include all chapters in sequential order and provide a title and description for each chapter.
backstory: >
You are a skilled organizer, great at turning scattered information into a structured format.
writer:
role: Chapter Writer
goal: >
Write a well-structured chapter for a book based on the provided chapter title, goal, and outline.
backstory: >
You are an exceptional writer, known for producing engaging, well-researched, and informative content.
outputDirectory: ./books
```
> **注解:YML的优雅**
> 与CrewAI的多个YML文件相比,Embabel的单一`application.yml`集中配置了LLM模型、超参数、并发限制和代理角色,简洁且易于维护。Spring的`@ConfigurationProperties`注解自动将YML映射为Java对象。
#### **领域模型**
```java
record ChapterOutline(String title, String content) {}
record BookOutline(String title, List chapterOutlines) implements PromptContributor {
@NotNull
@Override
public String contribution() {
return "Book Outline:\nTitle: " + title + "\n" + chapterOutlines.stream()
.map(chapter -> chapter.title() + "\n" + chapter.content())
.collect(Collectors.joining("\n\n"));
}
}
record Chapter(String title, String content) {}
record Book(BookRequest request, String title, List chapters) {
public String text() {
return "# " + title() + "\n" + request.goal() + "\n\n" +
chapters().stream()
.map(chapter -> "## " + chapter.title() + "\n" + chapter.content())
.collect(Collectors.joining("\n\n"));
}
}
```
> **注解:行为丰富的领域模型**
> 与CrewAI的Pydantic模型(仅作为数据结构)不同,Embabel的领域对象(如`BookOutline`和`Book`)实现了`PromptContributor`接口,允许它们参与提示构建,并提供格式化输出方法(如`Book.text()`),增强了代码的内聚性。
#### **代理实现**
```java
@Agent(description = "Write a book, first creating an outline, then writing the chapters and combining them")
public record BookWriter(BookWriterConfig config) {
@Action
ResearchReport researchTopic(BookRequest bookRequest, OperationContext context) {
return context.ai()
.withLlm(config.researcherLlm())
.withPromptElements(config.researcher(), bookRequest)
.withToolGroup(CoreToolGroups.WEB)
.createObject(
"""
Research the topic to gather the most important information that will
be useful in creating a book outline. Ensure you focus on high-quality, reliable sources.
""",
ResearchReport.class);
}
@Action
BookOutline createOutline(BookRequest bookRequest, ResearchReport researchReport, OperationContext context) {
return context.ai()
.withLlm(config.writerLlm())
.withPromptElements(config.outliner(), bookRequest, researchReport)
.withToolGroup(CoreToolGroups.WEB)
.createObject(
"""
Create a book outline as requested with chapters in sequential order based on the given research findings.
Ensure that each chapter has a title and a brief description that highlights the topics and subtopics to be covered.
""",
BookOutline.class);
}
@Action
Book writeBook(BookRequest bookRequest, BookOutline bookOutline, ResearchReport researchReport, OperationContext context) {
var chapters = context.parallelMap(
bookOutline.chapterOutlines(),
config.maxConcurrency(),
chapterOutline -> writeChapter(bookRequest, bookOutline, chapterOutline, context)
);
return new Book(bookRequest, bookOutline.title(), chapters);
}
@AchievesGoal(description = "Book has been written and published about the requested topic")
@Action
Book publishBook(Book book) {
var path = config.saveContent(book);
logger.info("Book {} written and saved to {}", book.title(), path);
return book;
}
}
```
> **注解:类型安全与动态规划**
> 每个`@Action`方法使用强类型的领域对象(如`BookRequest`和`ResearchReport`)作为参数,避免魔法字符串。`OperationContext`提供对AI服务的统一访问,`parallelMap`方法通过`maxConcurrency`控制并发,防止速率限制问题。GOAP算法自动推导动作顺序,简化流程设计。
### 💡 Embabel的优势
与CrewAI相比,Embabel的实现展现了以下优势:
- **更少的代码**:单一Java类和YML文件取代了CrewAI的多个文件和目录,代码量减少。
- **类型安全**:所有提示和数据流基于领域对象,消除了魔法字符串,提高了开发工具支持(如重构和自动补全)。
- **可配置性**:通过Spring的YML配置,可轻松调整LLM模型、超参数和并发限制。
- **生产就绪**:内置日志框架(SLF4J),支持单元测试和端到端测试,适合企业级应用。
- **并发控制**:`parallelMap`方法通过配置限制并发,避免CrewAI中由LLM决定章节数量导致的潜在问题。
> **比喻:像一架精密的飞船**
> Embabel就像一架精密的飞船,Spring框架是其引擎,GOAP算法是导航系统,领域对象是模块化的组件。开发者只需设定目标(目标和动作),飞船便能自动规划路线,高效到达目的地。
---
## 🔍 深入比较:Java vs. Python
### 📊 代码量与简洁性
令人惊讶的是,Embabel的Java实现比CrewAI的Python实现代码量更少。CrewAI需要多个YML文件、Python类和装饰器,而Embabel通过Spring的依赖注入和单一Java类简化了配置和实现。YML配置也更为集中,减少了维护成本。
### 🛡️ 类型安全性
CrewAI的提示依赖字符串模板(如`{topic}`),容易出错,且`@listen`装饰器的参数无类型约束。Embabel通过强类型的领域对象和`PromptContributor`接口,确保提示构建和数据流的安全性。这种类型安全性不仅降低了错误风险,还提升了IDE支持(如代码补全和重构)。
### ⚙️ 可扩展性与复用性
Embabel的GOAP规划算法允许动态生成动作序列,开发者只需添加新的动作和目标即可扩展功能,无需修改现有代码。CrewAI的流程依赖手动定义的`@listen`装饰器,扩展需要修改多个文件,复用性较差。
### 🏭 生产环境适配性
Embabel利用Spring的生态系统,提供了日志、测试和配置管理的原生支持。CrewAI依赖`print`语句和`asyncio`,缺乏生产级的日志和并发控制,难以满足企业需求。
> **比喻:从手工坊到智能工厂**
> CrewAI像一个手工坊,工匠(开发者)需要手动拼接零件(YML和Python代码),流程繁琐且易出错。Embabel则像一座智能工厂,自动化流水线(GOAP和Spring)高效生产,开发者只需提供蓝图(领域模型和动作)。
---
## 🌍 更广阔的视野:Embabel的生态与未来
### 🧩 Spring与JVM的生态优势
Embabel基于Spring框架,充分利用了JVM的成熟生态:
- **依赖注入**:Spring自动管理代理和服务的生命周期。
- **持久化与事务**:轻松集成Spring Data和JPA,适合企业级应用。
- **测试支持**:内置单元测试和端到端测试框架,确保代码质量。
> **比喻:JVM的宝库**
> JVM就像一座宝库,Spring是钥匙,Embabel是探险者,带领开发者挖掘企业级功能(如数据库、事务和微服务)的无限可能。
### 🚀 Embabel的创新特性
Embabel不仅仅是一个代理框架,它引入了多项创新:
- **动态规划**:GOAP算法使流程无需硬编码,系统可根据目标和状态自动调整。
- **多LLM支持**:支持混合使用不同LLM(如OpenAI和Anthropic),优化成本和性能。
- **MCP集成**:通过Model Context Protocol(MCP)与外部工具无缝协作,提供标准化接口。
- **联邦支持**:未来支持与其他Embabel系统或第三方框架的协作,增强跨平台能力。
### 📅 未来路线图
Embabel的GitHub文档勾勒了宏大的愿景:
- **成为Java应用的AI标配**:尤其是在Spring生态中,成为Gen AI的首选框架。
- **跨平台扩展**:将Embabel的概念推广到TypeScript和Python。
- **预算感知代理**:开发支持预算限制的代理,如“花费不超过20美分进行研究”。
- **自然语言动作**:允许开发者用自然语言定义动作和目标,进一步降低开发门槛。
---
## 📖 参考文献
1. Johnson, R. (2025). *You Can Build Better AI Agents in Java Than Python*. Medium. [https://medium.com/@springrod/you-can-build-better-ai-agents-in-java-than-python-868eaf008493](https://medium.com/@springrod/you-can-build-better-ai-agents-in-java-than-python-868eaf008493)
2. Embabel. (2025). *Embabel Agent Framework*. GitHub. [https://github.com/embabel/embabel-agent](https://github.com/embabel/embabel-agent)
3. CrewAI. (2025). *Write a Book Flow*. CrewAI Official Examples. [https://github.com/crewAI/crewAI-examples](https://github.com/crewAI/crewAI-examples)
4. Spring AI. (2025). *Spring AI Documentation*. [https://docs.spring.io/spring-ai/reference/](https://docs.spring.io/spring-ai/reference/)
5. Model Context Protocol (MCP). (2025). *MCP Quickstart for Claude Desktop Users*. [https://modelcontextprotocol.org/docs/claude-desktop](https://modelcontextprotocol.org/docs/claude-desktop)
---
## 🎉 结语:JVM的AI新篇章
通过重写CrewAI的书籍写作示例,Embabel展示了Java在AI代理开发中的优雅与力量。它的类型安全、动态规划和Spring生态集成,使其在代码简洁性、可扩展性和生产就绪性上超越了Python的CrewAI框架。无论是初学者还是企业开发者,Embabel都提供了一个强大而灵活的平台,让AI代理开发变得如探险般引人入胜。
> **想象一下**
> 你站在一座未来城市的控制中心,JVM是坚实的地基,Spring是智能的管道系统,Embabel是指挥AI代理的超级计算机。只需几行代码,你就能指挥代理完成从研究到创作的壮举。Embabel不仅是一个框架,它是通向AI驱动未来的桥梁。
现在,加入Embabel社区,拿起你的Java代码,开启AI代理的创作之旅吧!🌟
登录后可参与表态
讨论回复
0 条回复还没有人回复,快来发表你的看法吧!