找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

5312

积分

0

好友

703

主题
发表于 2 小时前 | 查看: 3| 回复: 0

上个月,我在公司里负责搭建一个企业内部知识库问答系统。需求听起来很简单——用户提问,AI 去查阅文档并给出答案。但实际操作起来,却踩了不少坑。

第一版采用了纯 API 调用的方式,为了实现问题路由和逻辑判断,写了一大堆 if-else,代码变得冗长且难以维护。第二版,我转向了 LangChain4j,虽然 Agent 能跑起来了,但在处理多智能体协同和流程编排时,简直是一场噩梦。工具调用、记忆管理、人机协作……每一个功能都几乎需要从零开始搭建。

一个看似简单的“查文档+执行操作”的智能体,我前后花了整整五天时间,代码量超过了 2000 行。

直到我发现了 Spring AI Alibaba

实现同样的功能,核心代码不到10行,一个功能完整的 Agent 就成功运行起来了。多智能体编排?框架内置支持。记忆管理?一行配置搞定。人工审批?一个 Hook 就能轻松接入。

今天这篇文章,我将结合自己的实践,从架构到实战,从单智能体到多智能体协同,为你彻底解析这个框架。

一、先看定位:Spring AI Alibaba 是什么?

一句话概括:这是阿里巴巴基于 Spring AI 打造的 Java Agent 开发框架,旨在帮助 Java 开发者快速构建企业级 AI 智能体应用。

它与 Spring AI 的层次关系可以这样理解:

┌──────────────────────────────────────────┐
│  Spring AI Alibaba(Agent 开发框架)       │
│  ├── ReactAgent 核心                       │
│  ├── Agent Skills 技能体系                 │
│  ├── Multi-Agent 多智能体编排              │
│  └── Context Engineering 上下文工程        │
├──────────────────────────────────────────┤
│  Spring AI(基础框架)                      │
│  ├── ChatModel 抽象                       │
│  ├── Tool Calling                         │
│  ├── MCP 协议支持                          │
│  └── RAG & Vector Store                   │
├──────────────────────────────────────────┤
│  Spring Boot 3.5.x(运行时基座)            │
└──────────────────────────────────────────┘

关键信息速览

维度 说明
最新版本 1.1.2.0(2026年2月发布,生产环境推荐)
核心能力 ReactAgent + Graph + Multi-Agent
模型支持 通义千问(DashScope)、OpenAI 等
代码量 不到10行启动一个Agent
企业特性 Human-in-the-Loop、记忆管理、成本控制

与 LangChain4j 对比,最核心的区别在于:Spring AI Alibaba 将 Agent 的编排逻辑深度集成到了框架层。开发者无需手动编写 ReAct 循环、管理状态机或拼接复杂的消息历史,框架已经为你封装好了这些复杂性。

二、实战开始:10行代码启动你的第一个 Agent

1. Maven 依赖配置

首先,在项目中引入必要的依赖。建议使用 BOM 进行版本统一管理。

<dependencyManagement>
    <dependencies>
        <!-- BOM 统一版本管理 -->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-bom</artifactId>
            <version>1.1.2.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!-- Agent 框架核心 -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-agent-framework</artifactId>
    </dependency>
    <!-- 通义千问模型支持 -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
    </dependency>
</dependencies>

2. 配置文件

application.yml 中配置模型连接信息,建议将 API Key 设置为环境变量。

spring:
  ai:
    dashscope:
      api-key: ${AI_DASHSCOPE_API_KEY}
      chat:
        options:
          model: qwen-plus

3. 创建 Agent(核心代码)

下面就是见证“10行代码”魔法的时刻。通过定义一个 Spring Bean,即可创建一个具备 ReAct 推理能力的智能体。

@Bean
public ReactAgent myFirstAgent(ChatModel chatModel) {
    return ReactAgent.builder()
            .name("my_agent")
            .model(chatModel)
            .instruction("你是一个有帮助的AI助手")
            .build();
}

是的,就这些。 一个功能完整的 Agent 已经就绪。

调用方式也非常简单直观:

@Autowired
private ReactAgent myFirstAgent;

public String chat(String userMessage) {
    return myFirstAgent.call(userMessage);
}
  • ✅ 无需手动编写 ReAct 循环
  • ✅ 无需手动拼接和管理消息历史
  • ✅ 无需自己维护工具调用链

框架已经为你处理了所有底层复杂性。

三、赋予 Agent “动手”能力:工具调用

一个只能聊天的 Agent 价值有限,真正的智能体需要能够“执行任务”。Spring AI Alibaba 提供了多种灵活的工具定义方式。

1. 函数式定义(推荐)

这是最直接的一种方式,通过实现 BiFunction 接口来定义工具。

// 定义搜索工具
public class SearchTool implements BiFunction<String, ToolContext, String> {
    @Override
    public String apply(@ToolParam(description = "搜索关键词") String query,
                         ToolContext ctx) {
        // 实际业务逻辑:调用搜索API
        return searchService.search(query);
    }
}

// 注册工具
@Bean
public ToolCallback searchTool() {
    return FunctionToolCallback.builder("search", new SearchTool())
            .description("搜索内部知识库,获取相关信息")
            .inputType(String.class)
            .build();
}

2. 将工具绑定到 Agent

创建 Agent 时,将定义好的工具传入即可。

@Bean
public ReactAgent smartAgent(ChatModel chatModel,
                             ToolCallback searchTool,
                             ToolCallback dbQueryTool) {
    return ReactAgent.builder()
            .name("smart_agent")
            .model(chatModel)
            .instruction("""
                你是一个企业知识库助手。
                当用户提问时,先用search工具搜索知识库,
                如果需要数据,再用db_query工具查询数据库。
                """)
            .tools(searchTool, dbQueryTool)
            .build();
}

此后,Agent 会根据用户的输入和自身指令,自主决策调用哪个工具、传递什么参数。这正是 ReAct(推理-行动)范式的核心体现。

3. 工具调用流程示例

用户提问:“上个月销售额是多少?”
    │
    ▼
Agent 思考:需要查询数据库
    │
    ▼
调用 db_query(“SELECT SUM(amount) FROM sales WHERE month=‘last’”)
    │
    ▼
获取结果:¥1,234,567
    │
    ▼
Agent 回复:“上个月的总销售额为123万4千567元。”

四、Agent 的记忆:实现连续对话

没有记忆的 Agent 就像金鱼,每次对话都从零开始。Spring AI Alibaba 提供了优雅且强大的记忆管理方案。

1. 开启会话记忆

仅需一行代码,即可为 Agent 添加记忆能力。

ReactAgent agent = ReactAgent.builder()
        .name("chat_agent")
        .model(chatModel)
        .saver(new MemorySaver())  // 一行代码,开启记忆
        .build();

// 使用 threadId 来维护独立的对话上下文
RunnableConfig config = RunnableConfig.builder()
        .threadId("user_123")
        .build();

agent.call(“我叫张三,我是Java开发”, config);
agent.call(“我叫什么名字?”, config);
// Agent 回答:“你叫张三,你是一名Java开发”

2. 生产环境使用 Redis 持久化

对于分布式生产环境,可以将内存存储替换为 Redis,实现记忆的持久化和跨实例共享。

// 内存版 → 生产替换为 Redis
ReactAgent agent = ReactAgent.builder()
        .saver(new RedisSaver(redisTemplate))  // 分布式持久化
        .build();

3. 消息自动压缩(控制成本与上下文长度)

随着对话轮次增加,上下文会越来越长,导致 Token 消耗剧增。框架提供了自动总结压缩的 Hook。

SummarizationHook summarizationHook = SummarizationHook.builder()
        .model(chatModel)                    // 可使用更经济的模型进行总结
        .maxTokensBeforeSummary(4000)        // 触发总结的Token阈值
        .messagesToKeep(20)                  // 总结后保留的最新消息数量
        .build();

ReactAgent agent = ReactAgent.builder()
        .hooks(summarizationHook)
        .saver(new MemorySaver())
        .build();
  • ✅ 消息长度超过阈值后自动触发总结
  • ✅ 只保留指定数量的最近消息,防止上下文窗口溢出
  • ✅ 总结过程可使用成本更低的模型,有效控制费用

五、生产级功能:人工审批与安全护栏

这是 Spring AI Alibaba 最具吸引力的部分之一——开箱即用的企业级特性,为智能体应用保驾护航。

1. Human-in-the-Loop(人工审批)

对于删除数据、执行敏感 SQL 等高危操作,可以配置必须经过人工确认后才能执行。

// 1. 配置审批Hook
HumanInTheLoopHook humanReviewHook = HumanInTheLoopHook.builder()
        .approvalOn(“execute_sql”,
            ToolConfig.builder()
                .description(“SQL执行需要人工审批”)
                .build())
        .build();

ReactAgent agent = ReactAgent.builder()
        .hooks(humanReviewHook)
        .saver(new MemorySaver())
        .tools(executeSqlTool)
        .build();

// 2. Agent 执行到该工具时会自动中断,等待人工确认
RunnableConfig config = RunnableConfig.builder()
        .threadId(“user_123”)
        .build();
Optional<NodeOutput> result = agent.invokeAndGetOutput(“删除过期数据”, config);
// 返回 InterruptionMetadata → 可通知前端弹出确认对话框

// 3. 人工确认后,携带元数据恢复执行
RunnableConfig resumeConfig = RunnableConfig.builder()
        .threadId(“user_123”)
        .addMetadata(RunnableConfig.HUMAN_FEEDBACK_METADATA_KEY, approvalMetadata)
        .build();
Optional<NodeOutput> finalResult = agent.invokeAndGetOutput(“”, resumeConfig);

2. 安全护栏(Guardrail)

通过自定义拦截器,实现对输入和输出的双向安全检查,过滤敏感内容。

public class GuardrailInterceptor extends ModelInterceptor {
    private static final List<String> BLOCKED = List.of(“密码”, “token”, “密钥”);

    @Override
    public ModelResponse interceptModel(ModelRequest request,
                                         ModelCallHandler handler) {
        // 前置检查:输入过滤
        if (containsSensitive(request.getMessages())) {
            return ModelResponse.of(new AssistantMessage(“检测到敏感内容,已拦截”));
        }
        // 正常调用模型
        ModelResponse response = handler.call(request);
        // 后置清洗:输出过滤
        return sanitizeIfNeeded(response);
    }
}

3. 模型调用限制

防止 Agent 陷入无限推理循环,限制其单次任务中调用大模型的最高次数。

// 限制 Agent 单次调用最多使用模型 10 次
ModelCallLimitHook limitHook = ModelCallLimitHook.builder()
        .maxCalls(10)
        .build();

ReactAgent agent = ReactAgent.builder()
        .hooks(limitHook)
        .build();

六、多 Agent 协同:从单兵作战到团队协作

1.1.2.0 版本 的一个重要更新是增强了多智能体协作能力,提供了6种主要模式,覆盖绝大多数企业应用场景。

1. Agent As A Tool(智能体即工具)

将一个智能体作为另一个智能体的工具来调用,实现能力的嵌套和复用。

// 子Agent:写作专家
ReactAgent writerAgent = ReactAgent.builder()
        .name(“writer_agent”)
        .model(chatModel)
        .description(“擅长写作,可以写文章”)
        .build();

// 主Agent:博客管理Agent,将写作Agent当作一个工具使用
ReactAgent blogAgent = ReactAgent.builder()
        .name(“blog_agent”)
        .model(chatModel)
        .instruction(“使用写作工具来完成用户的文章创作请求”)
        .tools(AgentTool.getFunctionToolCallback(writerAgent))
        .build();

blogAgent.invoke(“帮我写一篇关于西湖的散文”);

2. LLM 智能路由

根据用户问题的领域,自动将其路由到最合适的专家智能体进行处理。

// 创建两个专家Agent
ReactAgent writerAgent = ReactAgent.builder()
        .name(“writer_agent”)
        .description(“擅长创作各类文章,包括散文、诗歌等文学作品”)
        .outputKey(“writer_output”)
        .build();

ReactAgent codeAgent = ReactAgent.builder()
        .name(“code_agent”)
        .description(“专门处理编程相关问题”)
        .outputKey(“code_output”)
        .build();

// 路由Agent负责智能分发任务
LlmRoutingAgent routingAgent = LlmRoutingAgent.builder()
        .name(“content_routing_agent”)
        .model(chatModel)
        .subAgents(List.of(writerAgent, codeAgent))
        .build();

routingAgent.invoke(“帮我写一篇关于春天的散文”);  // → 自动路由到 writerAgent
routingAgent.invoke(“帮我写一个Java排序算法”);    // → 自动路由到 codeAgent

1.1.2.0 新增特性:路由 Agent 现在支持一次选择多个子 Agent 并行执行,极大提升了处理复杂任务的效率。

3. 六大多 Agent 协作模式速查

模式 核心特点 典型场景
Supervisor(主管) 主Agent协调子Agent,支持并行执行 同时查询邮件和数据库
Handoffs(交接) 多轮对话间状态持久化,动态切换Agent 客服流程:收集信息 → 执行退款操作
Skills(技能) 能力按需披露,由Prompt驱动 单Agent根据需求动态扩展多种能力
Routing(路由) 按问题领域拆解并分派给不同Agent 多领域知识库并行问答
Sequential/Parallel(管道) 前序节点输出作为后续节点输入 RAG 处理管道、固定业务流程
Custom Workflow 自定义图结构,混合编排以上模式 上述标准模式无法满足的复杂场景

对于希望深入探讨 Java 和 人工智能 结合的开发者,理解这些协作模式至关重要。

七、1.1.2.0 新特性:Agent Skills 技能体系

这个特性非常巧妙——Agent 的能力可以动态按需加载,而不是在初始化时就将所有工具描述塞进系统提示词(System Prompt)中。

核心机制:渐进式披露

初始状态:Agent 只知道技能列表(技能名 + 简要描述)
    │
    ▼ 用户提问了一个需要PDF提取的问题
Agent 判断:需要调用 ‘pdf_extract’ 技能
    │
    ▼ 自动调用 read_skill(“pdf_extract”)
动态加载完整的 SKILL.md 文件内容及关联的工具
    │
    ▼ 使用 pdf_extract 技能下的工具处理用户请求
    │
    ▼ 返回处理结果

带来的好处是显而易见的:

  • 传统方式:将所有工具的详细描述都写入 System Prompt → 导致 Token 消耗巨大,成本高且可能超出模型上下文限制。
  • Skills 方式:仅动态加载当前任务所需的技能描述 → 可节省 70% 以上的 Token 消耗,更加经济高效。

技能目录结构

技能以目录形式组织,每个技能是一个独立的文件夹。

skills/
├── pdf_extract/
│   ├── SKILL.md              # 技能描述文件(必需)
│   ├── references/           # 该技能相关的参考资料
│   └── scripts/              # 可执行脚本或工具类
├── data_query/
│   ├── SKILL.md
│   └── examples/
└── code_review/
    ├── SKILL.md
    └── references/

SKILL.md 文件规范

这是一个技能的核心描述文件,采用 Markdown 格式,包含元数据和详细说明。

---
name: pdf_extract
description: 从PDF文件中提取文本和表格数据
---

# PDF 提取技能

## 功能说明
支持从PDF文件中提取文本内容、表格数据和图片信息。

## 可用资源
- references/pdf_parser.py:PDF解析脚本
- scripts/batch_extract.sh:批量提取脚本

代码集成示例

// 1. 注册技能目录
SkillRegistry registry = new FileSystemSkillRegistry(“/path/to/skills”);

// 2. 构建技能钩子,将技能与具体工具关联
SkillsAgentHook skillsHook = SkillsAgentHook.builder()
        .skillRegistry(registry)
        .groupedTools(Map.of(
            “pdf_extract”, List.of(pdfTool),
            “data_query”, List.of(dbTool)
        ))
        .build();

// 3. 将技能钩子注入Agent
ReactAgent agent = ReactAgent.builder()
        .hooks(skillsHook)
        .build();

八、开发过程中的常见“坑”与解决方案

坑1:DashScope API Key 未正确配置

现象:应用启动时报错 ApiKey is null
解决方案:确保 API Key 已通过配置文件或环境变量设置。

# 方式1:在 application.yml 中配置(不推荐用于生产)
# spring.ai.dashscope.api-key=sk-xxxxx

# 方式2:使用环境变量(推荐,更安全)
export AI_DASHSCOPE_API_KEY=sk-xxxxx

坑2:工具定义时描述(description)过于简略或缺失

现象:Agent 几乎不调用工具,倾向于自己“编造”答案。
原因FunctionToolCallbackdescription 字段是大语言模型(LLM)判断是否以及何时调用该工具的主要依据。描述不清,模型就无法理解工具用途。

// ❌ 错误:描述过于模糊
FunctionToolCallback.builder(“search”, new SearchTool())
    .description(“搜索”)  // 模型困惑:搜索什么?什么时候用?
    .build();

// ✅ 正确:描述清晰明确
FunctionToolCallback.builder(“search”, new SearchTool())
    .description(“搜索企业内部知识库,当用户询问公司政策、流程、产品信息时使用此工具”)
    .build();

坑3:配置了 Hook 但未配置 Saver,导致功能失效

现象:配置了 HumanInTheLoopHookSummarizationHook,但在多轮对话中不生效。
原因:这些 Hook 依赖对话状态的持久化(Saver)来记录中断点或历史消息。必须同时配置 Saver

// ❌ 错误:只配置了 Hook,没有配置 Saver
ReactAgent agent = ReactAgent.builder()
        .hooks(summarizationHook)  // 不会生效!
        .build();

// ✅ 正确:Hook 和 Saver 需配对使用
ReactAgent agent = ReactAgent.builder()
        .hooks(summarizationHook)
        .saver(new MemorySaver())  // 必须配置!
        .build();

坑4:多 Agent 并行执行时,结果顺序混乱

现象:并行执行多个子 Agent 任务,最终聚合结果的顺序与预期不符。
解决方案:在 1.1.2.0 版本中,可以利用 AllOfAnyOf 聚合策略来控制流程。

// AllOf:等待所有并行分支都完成后,再聚合结果继续执行。
// AnyOf:任一分支完成后即可聚合结果继续执行。
StateGraph workflow = new StateGraph(“my_workflow”, keyStrategyFactory);
workflow.addParallelEdge(
    List.of(“research”, “analysis”, “writing”),  // 三个并行执行的节点
    AggregationStrategy.ALL_OF,                   // 等待全部完成
    “merge_node”                                  // 结果聚合节点
);

九、方案对比与总结

维度 纯API调用 LangChain4j Spring AI Alibaba
启动代码量 ~500行 ~200行 <10行
多Agent编排 需手动实现路由逻辑 需手动构建Chain 内置6种协作模式
记忆管理 需自行实现 需额外配置 一行配置即可
人工审批 不支持 不支持 内置Hook支持
上下文管理 需手动裁剪 需手动裁剪 支持自动压缩
Spring生态集成 需适配 原生深度集成
学习曲线 ⭐⭐ ⭐⭐⭐⭐ ⭐⭐
生产就绪度 ⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐

十、Java 开发者学习路径建议

如果你是一名 Java 开发者,希望快速掌握 AI Agent 开发,我建议遵循以下路径:

1️⃣ Spring AI 基础(1-2天)
   └── 掌握 ChatModel、Tool Calling、RAG 核心概念

2️⃣ Spring AI Alibaba 入门(1天)
   └── 学会创建 ReactAgent、绑定工具、配置记忆

3️⃣ 进阶:上下文与管控(2天)
   └── 掌握 Hook/Interceptor、Human-in-the-Loop、安全护栏

4️⃣ 高级:多智能体编排(2-3天)
   └── 实践 Supervisor、Routing、Graph 工作流等模式

5️⃣ 实战:Agent Skills(1-2天)
   └── 理解技能定义、渐进式披露、工具分组管理

写在最后

进入2026年,Java 生态下的 AI Agent 开发早已不再是“手搓轮子”的蛮荒时代。Spring AI Alibaba 做对了一件至关重要的事:将智能体编排、记忆管理、上下文工程等底层复杂性,全部封装到了框架层面

作为开发者,我们的核心工作得以聚焦于两件事:

  1. 定义清晰、可靠的业务工具(Tools)。
  2. 编写高质量的指引(Prompt)。

剩下的繁重工作,就交给框架来处理吧。如果你正在或计划进行 Java AI Agent 相关的开发,强烈建议尝试一下 Spring AI Alibaba,它或许能让你避开我走过的那些弯路,更高效地构建智能、可靠的企业级应用。

希望这篇从实践出发的总结对你有帮助。如果你想与更多开发者交流类似的技术实践,可以关注 云栈社区 的相关讨论。




上一篇:S200伺服电机选型指南:低中高惯量区别与应用场景详解
下一篇:个人量化交易的意义:在策略开发与正收益预期的路上,我们为何依然坚持
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-20 15:37 , Processed in 0.783459 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表