主题
42 · 从其它框架迁移(Migrating)
很多人的旅程是从 Python 框架开始的。
本节讲的是:当你需要迁移到一个更健壮、更安全、且能访问既有代码与服务的平台时,如何从流行框架迁移过来。
从 CrewAI 迁移
CrewAI 使用协作式多智能体方法,让多个 Agent 围绕任务协同工作。 Embabel 提供类似的能力,但具备更强的类型安全以及与既有 Java/Kotlin 代码库更好的集成。
核心概念映射
| CrewAI 概念 | Embabel 对应物 | 说明 |
|---|---|---|
| Agent Role/Goal/Backstory | RoleGoalBackstory PromptContributor | Agent 人格的便捷类 |
| Sequential Tasks | 动作之间的类型化数据流 | 类型驱动执行 + 自动规划 |
| Crew(多智能体协作) | 共享 PromptContributor 的动作 | Agent 可按需采用人格 |
| YAML 配置 | 标准的 Spring @ConfigurationProperties,由 application.yml 或 profile 专属配置文件支撑 | 带校验的类型安全配置 |
迁移示例
CrewAI 写法:
python
research_agent = Agent(
role='Research Specialist',
goal='Find comprehensive information',
backstory='Expert researcher with 10+ years experience'
)
writer_agent = Agent(
role='Content Writer',
goal='Create engaging content',
backstory='Professional writer specializing in technical content'
)
crew = Crew(
agents=[research_agent, writer_agent],
tasks=[research_task, write_task],
process=Process.sequential
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Embabel 等价写法:
java
@ConfigurationProperties("examples.book-writer")
record BookWriterConfig(
LlmOptions researcherLlm,
LlmOptions writerLlm,
RoleGoalBackstory researcher,
RoleGoalBackstory writer
) {}
@Agent(description = "Write a book by researching, outlining, and writing chapters")
public record BookWriter(BookWriterConfig config) {
@Action
ResearchReport researchTopic(BookRequest request, OperationContext context) {
return context.ai()
.withLlm(config.researcherLlm())
.withPromptElements(config.researcher(), request)
.withToolGroup(CoreToolGroups.WEB)
.createObject("Research the topic thoroughly...", ResearchReport.class);
}
@Action
BookOutline createOutline(BookRequest request, ResearchReport research, OperationContext context) {
return context.ai()
.withLlm(config.writerLlm())
.withPromptElements(config.writer(), request, research)
.createObject("Create a book outline...", BookOutline.class);
}
@AchievesGoal(export = @Export(remote = true))
@Action
Book writeBook(BookRequest request, BookOutline outline, OperationContext context) {
// 以类似 crew 的协作方式并行撰写各章节
var chapters = context.parallelMap(outline.chapterOutlines(),
config.maxConcurrency(),
chapterOutline -> writeChapter(request, outline, chapterOutline, context));
return new Book(request, outline.title(), chapters);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
关键优势:
- 类型安全:数据流在编译期就被校验;
- Spring 集成:复用既有的企业基础设施;
- 自动规划:GOAP 规划器负责任务排序,且能做到更复杂的规划;
- 与 JVM 的工具集成:原生访问既有的 Java/Kotlin 服务。
从 Pydantic AI 迁移
Pydantic AI 提供了一个用 Python 构建 AI Agent 的框架,强调类型安全与校验。 Embabel 在 JVM 生态中提供类似能力,并更强地集成到企业环境中。
核心概念映射
| Pydantic AI 概念 | Embabel 对应物 | 说明 |
|---|---|---|
@system_prompt 装饰器 | PromptContributor 类 | 更灵活、更可组合的提示词管理 |
@tool 装饰器 | 等价的 @Tool 注解方法,可放在 Agent 类与领域对象上 | Agent 类 |
@Agent 注解的 record/class | 带 Spring 集成的声明式 Agent 定义 | RunContext |
| SystemPrompt | 自定义 PromptContributor | Blackboard 状态,可通过 OperationContext 访问,但用户代码通常无需关心 |
| deps 参数 | Spring 依赖注入 | 结构化提示词贡献体系 |
迁移示例
Pydantic AI 写法:
python
# 基于 https://ai.pydantic.dev/examples/bank-support/
from pydantic_ai import Agent, RunContext
from pydantic_ai.tools import tool
@system_prompt
def support_prompt() -> str:
return "You are a support agent in our bank"
@tool
async def get_customer_balance(customer_id: int, include_pending: bool = False) -> float:
# 数据库查询
customer = find_customer(customer_id)
return customer.balance + (customer.pending if include_pending else 0)
agent = Agent(
'openai:gpt-4-mini',
system_prompt=support_prompt,
tools=[get_customer_balance],
)
result = agent.run("What's my balance?", deps={'customer_id': 123})1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Embabel 等价写法:
java
// 来自 embabel-agent-examples/examples-java/src/main/java/com/embabel/example/pydantic/banksupport/SupportAgent.java
record Customer(Long id, String name, float balance, float pendingAmount) {
@Tool(description = "Find the balance of a customer by id")
float balance(boolean includePending) {
return includePending ? balance + pendingAmount : balance;
}
}
record SupportInput(
@JsonPropertyDescription("Customer ID") Long customerId,
@JsonPropertyDescription("Query from the customer") String query) {
}
record SupportOutput(
@JsonPropertyDescription("Advice returned to the customer") String advice,
@JsonPropertyDescription("Whether to block their card or not") boolean blockCard,
@JsonPropertyDescription("Risk level of query") int risk) {
}
@Agent(description = "Customer support agent")
record SupportAgent(CustomerRepository customerRepository) {
@AchievesGoal(description = "Help bank customer with their query")
@Action
SupportOutput supportCustomer(SupportInput supportInput, OperationContext context) {
var customer = customerRepository.findById(supportInput.customerId());
if (customer == null) {
return new SupportOutput("Customer not found with this id", false, 0);
}
return context.ai()
.withLlm(OpenAiModels.GPT_41_MINI)
.withToolObject(customer)
.createObject(
"""
You are a support agent in our bank, give the
customer support and judge the risk level of their query.
In some cases, you may need to block their card. In this case, explain why.
Reply using the customer's name, "%s".
Currencies are in $.
Their query: [%s]
""".formatted(customer.name(), supportInput.query()),
SupportOutput.class);
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
关键优势:
- 企业集成:与既有服务的原生 Spring Boot 集成;
- 编译期安全:强类型在构建时就抓到错误;
- 自动规划:GOAP 规划器处理复杂的多步操作;
- JVM 生态:可使用成熟库与企业基础设施。
从 LangGraph 迁移
LangGraph 用状态机来构建 Agent 工作流。
关于 LangGraph 与 Embabel 常见模式的详细对比,见博客 Build Better Agents in Java vs Python: Embabel vs LangGraph。
从 Google ADK 迁移
待补充(tbd)。