Agent 迎来重量级框架:Embabel 开源,Spring 之父的下一场“革命”

23 阅读6分钟

在 Java 统治企业级开发的 20 年里,我们习惯了确定性的逻辑。然而,AI 浪潮让 Python 凭借灵活性抢占了先机。

Spring 创始人 Rod Johnson 在介绍 Embabel 时曾明确表示:这是他自 Spring 之后,最希望投入精力推动的一个方向性项目——目标不是简单追赶 Python,而是为 JVM 生态构建真正可落地的 Agent 能力。

Embabel 并非简单的 LLM 封装,它是类似于 Spring MVC 级别的高级 Agent 框架,旨在为 JVM 生态带来真正的 AI 生产力。

一、 核心设计:为什么它是“JVM 原生”的 Agent 革命?

1. 放弃死板的 DAG,引入“动态规划”

大多数 Agent 框架依赖预定义的有限状态机(FSM)或硬编码的顺序执行。Embabel 引入了游戏 AI 领域著名的 GOAP(目标导向行动计划)算法

  • 动态寻路:开发者只需定义 Action(行动)Goal(目标),系统会自动规划执行路径,甚至能完成未被硬编码的复杂任务。

  • OODA 闭环:系统在每一步 Action 完成后都会进行 Replanning(重新规划)。它能观察上一步的效果并自适应调整。

2. 强类型约束:告别“魔术贴”字典

Python 框架中常见的 Dict 传递在大型工程中是灾难性的。Embabel 充分利用 Java/Kotlin 的强类型特性,将 Prompt 交互、代码逻辑和领域模型(Domain Model)深度融合,支持完整的重构(Refactoring)。

3. Spring 原生基因

作为 Rod Johnson 的力作,Embabel 支持熟悉的注解驱动(@Agent@Action)、依赖注入以及完善的测试体系,让 AI 开发拥有与传统 Java 开发一致的工程化体验。

二、 实战:Spring 项目集成与自定义 AI 厂商

由于 Embabel 社区文档尚处于早期,对于如何接入国内主流模型(如通义千问)缺乏指引。本文基于 Spring + Spring AI + Embabel 这一黄金组合,手把手构建一个生产级的“退货处理智能 Agent”。

1. 自定义 AI 厂商配置

通过自定义 Llm Bean,我们可以利用 Spring AI 的 ChatModel 无缝桥接国内大模型。

/**
 * 直接创建 Spring AI ChatModel,指向百炼 OpenAI 协议接口
 */
@Bean
public OpenAiChatModel bailianChatModel() {

    OpenAiApi api = OpenAiApi.builder()
            .apiKey("sk-xxxx")
            .baseUrl("https://dashscope.aliyuncs.com/compatible-mode")
            .build();

    return OpenAiChatModel.builder()
            .openAiApi(api)
            .defaultOptions(OpenAiChatOptions.builder()
                    .model("qwen3-max")
                    .temperature(0.7)
                    .build())
            .build();
}

/**
 * Embabel Llm Bean,包装上面的 ChatModel
 */
@Bean
public Llm bailianLlm(OpenAiChatModel bailianChatModel) {
    return new Llm(
            "qwen3-max", // Embabel default LLM 名称
            "bailian", // provider 名称,随便写
            bailianChatModel);
}

在application.yml中加入:

embabel:
  models:
    default-llm: qwen3-max

2. 构建“退货处理 Agent”

在 Embabel 中,开发不再是写死 if-else,而是定义领域模型和动作。

@Agent(description = "处理客户退货请求的专业助手")
@Component
public class ReturnAgent {

    @Action(description = "从用户输入中提取订单号和退货原因")
    public OrderInfo extractOrderInfo(UserInput userInput, Ai ai) {
        return ai.withDefaultLlm().createObject(
                "从用户输入中提取退货信息。用户输入: %s".formatted(userInput.getContent()),
                OrderInfo.class);
    }

    @Action(description = "查询订单信息数据库")
    public DbRecord lookupOrder(OrderInfo orderInfo) {
        // 模拟数据库返回,实际开发中此处为 DB 调用
        return new DbRecord("ORDER123", "DELIVERED", "2024-06-15", true, 299.99);
    }

    @AchievesGoal(description = "为用户生成最终的退货决策和解释")
    public RefundDecision finalizeDecision(OrderInfo orderInfo, DbRecord dbRecord, Ai ai) {
        var prompt = "用户想退货: %s, 数据库状态: %s. 请根据7天内可退政策给出决策。".formatted(orderInfo, dbRecord);
        return ai.withDefaultLlm().createObject(prompt, RefundDecision.class);
    }
}

三、 深度拆解:日志里的“黑科技”

调用接口测试:GET /api/ai/refund-decision?userInput=用户想退货订单号:ORDER123

核心日志追踪:

14:18:57.398 [task-1] INFO Embabel - [epic_tu] ready to plan from:
  {it:OrderInfo=FALSE, it:DbRecord=FALSE, it:UserInput=TRUE, it:RefundDecision=FALSE}

14:18:57.437 [task-1] INFO Embabel - [epic_tu] formulated plan:
  extractOrderInfo -> lookupOrder -> finalizeDecision

14:18:57.486 [task-1] INFO Embabel - [epic_tu] executing action extractOrderInfo... using LLM qwen3-max
14:18:59.322 [task-1] INFO Embabel - [epic_tu] object bound it:OrderInfo

14:18:59.361 [task-1] INFO Embabel - [epic_tu] formulated plan:
  lookupOrder -> finalizeDecision

14:19:03.251 [task-1] INFO Embabel - [epic_tu] completed in PT5.899S

为什么说这是“自适应规划”?

  1. 意图感知:初始状态只有 UserInput。系统检测到目标是 RefundDecision,通过类型依赖分析,自动算出了执行路径

  2. 混合执行流

    • AI 语义提取:耗时 1.8s,将模糊的文字转化为强类型的 OrderInfo 对象。

    • 原生 Java 逻辑:拿到订单号后,系统自动触发 lookupOrder注意:这一步是纯 Java 代码,无需 LLM 介入,保证了核心业务的确定性。

    • 终极决策:所有拼图凑齐,LLM 结合数据库信息生成最终 JSON。

最终结果:

JSON

{
  "approved": false,
  "actionCode": "REJECT_OUTSIDE_RETURN_WINDOW",
  "message": "您好,感谢您联系我们。根据我们的退货政策,商品需在签收后7天内申请退货。您的订单于2024年6月15日签收,目前已超过退货期限,因此无法为您办理退货。不过,该商品仍在保修期内,如遇质量问题,欢迎随时联系客服获取支持。",
  "nextStep": "建议用户检查商品是否存在问题,如有质量问题可申请保修服务"
}

四、与LangChain的比较

在 Agent 领域,Embabel 与 LangChain 并不是“谁取代谁”的关系,而是服务于完全不同的问题空间。

维度LangChain(含 LangGraph)Embabel
核心思想Prompt + Chain + Tool 编排Goal + Action + 动态规划
流程模型静态 DAG / FSMGOAP + Replanning(自适应)
数据结构Dict / JSON 为主强类型 Domain Model
执行控制主要交给 LLMJVM 算法主导,LLM 只做认知补全
工程特性生态广,适合快速构建原型生产友好:支持 AOP、严谨测试、易于长期维护
出错方式语义漂移、隐性失败显性失败、日志可追踪

五、推荐使用 Embabel 的场景

  1. 多步骤动态决策:如电商退货处理、保险理赔审批。这类场景的逻辑分支极多,用传统的 if-else 或固定图(Graph)会陷入“状态爆炸”,而 Embabel 的 GOAP 算法 能自动处理海量分支。

  2. 高安全性/确定性需求:如果你担心 AI “幻觉”导致调用了不该调用的接口,Embabel 的类型沙箱和行动约束能强制 AI 在预设的 Java 业务逻辑轨道内运行。

  3. 大型企业级项目:当你需要利用 Spring 的 DI、AOP 以及成熟的单元测试体系来管理 Agent 时,Embabel 是唯一的“二楼”框架(在 Spring 之上构建)。

六、 结语

Embabel 的出现,标志着 Java 开发者正式进入了 “意图驱动开发(Intent-Driven Development)” 的时代。

  1. **从“写逻辑”到“定目标”:**开发者不再是 AI 的“保姆”,而是规则的“制定者”。

  2. **让 AI 真正落地:**它通过 JVM 的严谨性驯服了 LLM 的随机性,解决了企业级应用中最核心的“信任”问题。

GitHub 传送门https://github.com/embabel/embabel-agent