Spring AI

Administrator 2 阅读 java

🛠️ 准备:环境与依赖

你需要 JDK 17+ 和 Spring Boot 3.x。

Spring AI 的设计哲学是“像添加一个普通 Starter 一样简单”。在 pom.xml​ 中,通常需要两步:

1. 通过 BOM 统一管理版本,避免依赖冲突:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>1.0.0</version> <!-- 请使用最新稳定版 -->
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

2. 添加具体模型的 Starter。一个巨大的便利是,DeepSeek 等许多模型都兼容 OpenAI 的 API 规范,所以即使你用 DeepSeek,也直接引入 OpenAI 的 Starter 即可,只需修改配置中的端点地址。

<dependencies>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

在 application.yml​ 中配置凭证(以 DeepSeek 为例):

spring:
  ai:
    openai:
      api-key: ${DEEPSEEK_API_KEY} # 推荐用环境变量
      base-url: https://api.deepseek.com
      chat:
        options:
          model: deepseek-chat

🌱 第一级:让 AI 开口说话(ChatClient)

这是所有能力的起点。ChatClient​ 是 Spring AI 提供的流式 API,用起来感觉很像 RestTemplate​。

@Service
public class SimpleChatService {

    private final ChatClient chatClient;

    // ChatClient.Builder 由 Spring Boot 自动注入
    public SimpleChatService(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    public String chat(String message) {
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }
}

调用 chat("你好")​,你会收到模型的回复。这一步验证了你的依赖、API Key 和模型连接全部通畅。

⚡ 第二级:让 AI 调用你的 Java 函数(Tool Calling)

这是 Spring AI 的灵魂,也是实现“AI 帮你下单、查合同”的核心。它的安全性在于:模型只能“提议”调用你的方法,真正的执行权永远在你的 Java 代码手里,模型无法直接触碰你的数据库或 API。

📝 定义工具:@Tool​ 注解

在任何 Spring Bean 的方法上使用 @Tool​ 注解即可。Spring AI 会自动将该方法的方法签名和描述转换成模型能理解的 JSON Schema。

@Component
public class RentalTools {

    @Tool(description = "查询租赁合同状态。当用户询问合同是否有效、租期、租金时调用。需要提供合同编号。")
    public String queryContract(
            @ToolParam(description = "合同编号,格式如 HT20260809001") String contractId) {
        // 这里是你原有的业务逻辑
        return "合同 " + contractId + " 状态:履行中,租期至 2027-08-09,月租金 5000 元。";
    }
}

注意:@Tool​ 的 description​ 极其重要,必须写清楚“什么时候该用”,而不仅仅是“这个方法是干嘛的”,这直接决定了模型调用的准确率。

🔗 将工具注入 ChatClient

@Service
public class ToolChatService {

    private final ChatClient chatClient;
    private final RentalTools rentalTools;

    public ToolChatService(ChatClient.Builder builder, RentalTools rentalTools) {
        this.chatClient = builder.build();
        this.rentalTools = rentalTools;
    }

    public String chat(String message) {
        return chatClient.prompt()
                .user(message)
                .tools(rentalTools) // 关键:把工具实例注册进来
                .call()
                .content();
    }
}

当你问“查一下合同 HT20260809001 的状态”,背后发生的事:

  1. ​ChatClient​ 将你的问题、以及 RentalTools​ 中 @Tool​ 的描述一起发给模型。

  2. 模型判断需要调用 queryContract​,并提议参数 contractId = "HT20260809001"​。

  3. Spring AI 的 ToolCallingAdvisor​ 在你的本地执行 queryContract​ 方法。

  4. 方法返回的结果被回传给模型,模型用它组织成最终的自然语言回复。

安全边界不变:你只注册了“查合同”工具,模型就不可能做出“删合同”的操作。

🧠 第三级:构建一个“会思考”的 Agent(ReAct 模式)

Tool Calling 解决的是“单次调用”。如果你想要一个能多步推理、反复调用工具直到解决问题的智能体,就需要实现 ReAct(推理+行动) 循环。

需要澄清的是:原生的 Spring AI 核心库主要聚焦于 Tool Calling 的底层机制。而开箱即用的 ReactAgent​ 抽象是由 Spring AI Alibaba 提供的,它构建在 Spring AI 和 Graph 运行时之上,让你不必手动编写循环逻辑。如果你选择纯 Spring AI,你也可以基于 ChatClient​ 和 ToolCallingAdvisor​ 自己实现这个循环,或者直接引入 Spring AI Alibaba 的 Agent 框架来获得生产级的 ReactAgent​。

下面是一个使用 Spring AI Alibaba ReactAgent​ 的最小示例(假设你已添加相应依赖):

// 1. 准备 ChatModel(或使用自动配置的 ChatModel)
ChatModel chatModel = ...;

// 2. 定义工具(可以是 @Tool Bean,也可以是 FunctionToolCallback)
ToolCallback weatherTool = FunctionToolCallback.builder("get_weather", (String city) -> city + "今天晴,25°C")
        .description("获取指定城市的天气")
        .inputType(String.class)
        .build();

// 3. 构建 ReactAgent
ReactAgent agent = ReactAgent.builder()
        .name("weather_agent")
        .model(chatModel)
        .tools(weatherTool)
        .systemPrompt("你是一个天气助手。需要天气信息时调用工具。")
        .build();

// 4. 调用
AssistantMessage response = agent.call("上海今天天气怎么样?");

​ReactAgent​ 会自己维护“推理-行动”循环。如果一次工具调用不够,它会自主决定继续调用,直到能给出最终答案。

🕸️ 第四级:用 Graph 编排确定性工作流

对于有固定步骤和分支的业务流程(比如“先分类合同类型 → 再走不同的续租计算逻辑”),用 Graph​ 工作流比让 Agent 自由发挥更可控。

​Graph​ 把流程拆成节点,用边连接,并支持条件路由。一个概念性的最小流程如下:

StateGraph graph = new StateGraph();
graph.addNode("classify", classifyNode);      // 节点1:分类合同类型
graph.addNode("calcRenewal", calcRenewalNode); // 节点2:计算续租方案
graph.addEdge("classify", "calcRenewal");      // 无条件串联
graph.setEntryPoint("classify");
graph.setFinishPoint("calcRenewal");

CompiledGraph compiled = graph.compile();
compiled.invoke(初始状态);

Spring AI Alibaba 的 Graph 支持条件边来实现分支,以及并行分支等复杂编排。当你的业务流程本身就有明确步骤时,Graph 能提供确定性的控制。

🤝 第五级:多智能体协作(Supervisor 模式)

当任务复杂到单个 Agent 难以胜任时,可以引入多个专业 Agent 分工协作。Supervisor 模式是其中一种经典架构:

  • 主管 Agent:负责理解用户意图,并路由给最合适的子 Agent。

  • 子 Agent:每个只专注于自己的领域(如“合同 Agent”只负责查合同,“账单 Agent”只负责算账单)。

主管汇总子 Agent 的结果后返回给用户。Spring AI Alibaba 的 Graph 框架支持包括 Supervisor、顺序、并行在内的多种多智能体协作模式。