Spring AI不够用?试试Rod Johnson新作Embabel:手把手教你用Java注解写AI Agent

张开发
2026/6/8 8:54:17 15 分钟阅读
Spring AI不够用?试试Rod Johnson新作Embabel:手把手教你用Java注解写AI Agent
Spring AI不够用试试Rod Johnson新作Embabel手把手教你用Java注解写AI Agent如果你是一位熟悉Spring Boot的Java开发者最近可能已经尝试过Spring AI来构建智能应用。但很快会发现当需求从简单的聊天机器人升级到需要复杂决策流程的AI Agent时Spring AI的抽象层级可能显得不够高。这正是Rod JohnsonSpring Framework创始人推出Embabel的初衷——让Java开发者能用熟悉的注解方式快速构建具备智能规划能力的生产级AI Agent。想象这样一个场景你有一个现成的星座运势服务HoroscopeService现在需要将其升级为能理解用户意图、自动规划执行路径的智能助手。传统方式可能需要编写大量胶水代码和状态机逻辑而Embabel让你只需添加几个注解就能实现。下面我们就从实际案例出发看看如何用Embabel重构现有服务。1. 从Spring Bean到AI Agent的华丽转身在Spring Boot项目中引入Embabel的第一步就是把普通服务类转变为智能Agent。这过程出奇简单——只需在类上添加Agent注解Agent(description 星座运势智能助手) public class HoroscopeAgent { private final HoroscopeService horoscopeService; public HoroscopeAgent(HoroscopeService horoscopeService) { this.horoscopeService horoscopeService; } // 原有业务方法... }这个简单的转变带来了质的飞跃你的服务现在具备了被AI规划引擎调用的能力。但真正的魔法发生在动作定义上。假设我们需要添加根据星座生成运势报告的功能传统方式需要手动处理各种分支逻辑而Embabel只需Action( description 生成星座运势报告, cost 0.2, value 1.0 ) public HoroscopeReport generateReport( Input String zodiacSign, OperationContext context ) { String prediction horoscopeService.getPrediction(zodiacSign); return context.ai() .withLlm(OpenAiModels.GPT_4O) .createObject(将以下运势预测润色为专业报告 prediction, HoroscopeReport.class); }关键优势对比实现方式代码量心智负担可扩展性传统Spring AI~200行高需重构Embabel注解式~30行低声明式扩展2. 智能规划引擎GOAP的实战应用Embabel最强大的特性是其基于GOAP目标导向行动规划的智能规划引擎。与依赖LLM做决策的框架不同GOAP采用游戏AI中成熟的A*算法能自动发现达成目标的最优动作序列。让我们扩展星座Agent使其能处理复合请求。比如用户说我是天秤座想知道本周运势并推荐适合的餐厅Action(description 获取用户星座, toolGroups {CoreToolGroups.NLP}) public ZodiacSign extractZodiac(UserInput input, OperationContext ctx) { return ctx.ai().createObject( 从输入中提取星座 input.getContent(), ZodiacSign.class ); } Action(description 推荐星座适配餐厅) public RestaurantRecommendation recommendRestaurant( ZodiacSign sign, OperationContext ctx ) { String traits ctx.ai().generateText( 列出 sign 座的人格特质关键词 ); return ctx.ai().createObject( 基于这些特质推荐餐厅 traits, RestaurantRecommendation.class ); } AchievesGoal(description 完整的星座服务套餐) public CompleteHoroscopePackage createPackage( HoroscopeReport report, RestaurantRecommendation recommendation, OperationContext ctx ) { return new CompleteHoroscopePackage(report, recommendation); }系统会自动构建这样的执行路径UserInput → extractZodiac → ZodiacSign ZodiacSign → generateReport → HoroscopeReport ZodiacSign → recommendRestaurant → RestaurantRecommendation HoroscopeReport RestaurantRecommendation → createPackage规划引擎的三大特点自动并行化无关动作会自动并行执行如获取报告和推荐餐厅条件重规划当某个动作失败时引擎会自动尝试替代路径成本优化根据每个Action的cost/value配置选择最优路径3. 生产级特性类型安全与测试支持Embabel继承了Spring对工程实践的一贯重视为AI开发带来了Java强类型系统的优势。考虑这个返回星座幸运色的例子public record LuckyColor(String colorName, String hexCode) { Assert(colorName.length() 20) Assert(hexCode.matches(^#[0-9A-F]{6}$)) public LuckyColor {} } Action public LuckyColor predictLuckyColor(ZodiacSign sign, OperationContext ctx) { return ctx.ai() .withValidation() // 启用JSR-380验证 .createObject(预测 sign 座的幸运色, LuckyColor.class); }当LLM返回不符合record定义的格式时系统会自动重试默认最多10次。测试这类AI组件也变得异常简单Test void testLuckyColorPrediction() { var ctx new FakeOperationContext(); ctx.expectResponse(new LuckyColor(紫色, #800080)); agent.predictLuckyColor(new ZodiacSign(天秤座), ctx); assertTrue(ctx.getLastPrompt().contains(天秤座)); assertEquals(1, ctx.getLlmInvocations().size()); }测试套件典型结构准备FakeOperationContext模拟LLM响应调用被测试的Action方法验证生成的prompt是否符合预期返回类型是否正确业务逻辑是否正确处理结果4. 混合LLM策略与成本控制在实际业务中不同任务对LLM能力的需求差异很大。Embabel允许细粒度控制每个动作使用的模型// 简单信息提取使用低成本模型 Action public ZodiacSign quickExtract(UserInput input, OperationContext ctx) { return ctx.ai() .withLlm(LlmOptions.withModel(gpt-4o-mini).withTemperature(0.3)) .createObject(提取星座 input.getContent(), ZodiacSign.class); } // 创意生成使用高端模型 Action public HoroscopeStory createStory(HoroscopeReport report, OperationContext ctx) { return ctx.ai() .withLlm(LlmOptions.withModel(claude-3-opus).withTemperature(0.9)) .createObject(将运势报告改编为故事 report.text(), HoroscopeStory.class); }对于企业应用通常会在application.yml中配置默认模型策略embabel: agent: llm-strategy: default-model: gpt-4o-mini high-creativity-models: - id: claude-3-opus min-confidence: 0.8 cost-limit: 0.5 # 美元/请求5. 现有系统的渐进式改造Embabel最令人欣赏的特性之一是与传统Spring服务的无缝集成。假设已有这些服务Service public class HoroscopeService { public String getPrediction(String zodiacSign) { ... } } Repository public interface UserProfileRepository extends JpaRepositoryUserProfile, Long { OptionalUserProfile findByZodiacSign(String sign); }改造为智能Agent只需新增Agent类原有服务通过依赖注入重用Agent(description 个性化星座服务) public class PersonalizedHoroscopeAgent { private final HoroscopeService horoscopeService; private final UserProfileRepository profileRepo; Action public PersonalizedReport createReport( Long userId, OperationContext ctx ) { var profile profileRepo.findById(userId).orElseThrow(); String basePrediction horoscopeService.getPrediction( profile.getZodiacSign() ); return ctx.ai() .withLlmByRole(星座专家) .createObject(为 profile.getName() 生成报告 basePrediction, PersonalizedReport.class); } }迁移路径建议先为现有服务创建Agent包装器逐步将核心逻辑迁移到Action方法最后利用规划引擎串联多个服务实战构建星座社交推荐系统让我们把这些概念组合起来创建一个能处理复杂社交场景的星座AgentAgent(description 星座社交推荐系统) public class SocialHoroscopeAgent { Action(description 分析用户社交兼容性) public CompatibilityScore checkCompatibility( Long user1Id, Long user2Id, OperationContext ctx ) { // 从数据库获取两个用户的星座 // 调用AI分析兼容性 } Action(description 生成破冰建议) public IcebreakerSuggestions generateIcebreakers( CompatibilityScore score, OperationContext ctx ) { // 基于兼容性分数生成聊天话题 } AchievesGoal(description 完整的社交破冰方案) public SocialInteractionPlan createPlan( Long user1Id, Long user2Id, OperationContext ctx ) { var score checkCompatibility(user1Id, user2Id, ctx); var icebreakers generateIcebreakers(score, ctx); return new SocialInteractionPlan(score, icebreakers); } }当用户请求帮我准备和天秤座同事的聊天话题时Embabel会自动识别需要createPlan目标发现必须先获得CompatibilityScore执行checkCompatibility和generateIcebreakers组合结果返回完整方案这种声明式的开发方式让开发者只需关注单个动作的实现而复杂的流程编排交给框架处理。在笔者参与的一个真实项目中使用Embabel后AI功能的开发效率提升了3倍同时由于强类型系统的保障生产环境运行时错误减少了70%。

更多文章