在实际 Java 后端开发中,集成 AI 大模型能力正从一个前沿探索变为工程标配。无论是构建智能客服、文档分析助手,还是实现复杂的多步骤推理 Agent,开发者都需要一套稳定、高效且符合 Java 生态的解决方案。面对 Spring AI、Spring AI Alibaba、LangChain4j 等多个框架,如何选择、如何整合、如何从零搭建一个可运行、可调试、可扩展的 AI 应用,是许多团队正在面临的实际问题。本文将以一个工程实践者的视角,带你梳理 Java 生态下的 AI 集成方案,通过对比核心框架、手把手搭建一个融合多种能力的 Agent 案例,并深入探讨生产环境中必须考虑的配置、排错与优化策略。无论你是希望将 AI 能力引入现有 Spring Boot 项目,还是计划从零开始构建一个 AI 驱动的服务,本文提供的思路和代码都将为你提供一个坚实的起点。

1. 核心框架对比与选型:Spring AI、Spring AI Alibaba 与 LangChain4j

在 Java 中集成 AI,目前主要有三个活跃的框架选项:Spring AI、Spring AI Alibaba 和 LangChain4j。它们的设计理念、抽象层次和适用场景各有不同,选型错误可能导致后期开发成本陡增。

1.1 Spring AI:Spring 生态的官方尝试

Spring AI 是 Spring 官方团队推出的项目,旨在为 Spring 应用提供一套统一的 AI 抽象。它的核心思想是“Portable Service API”,即定义一套标准的接口(如 ChatClient EmbeddingClient ),让开发者可以像切换数据库驱动一样,在不同的大模型提供商(OpenAI、Azure OpenAI、Ollama 等)之间切换,而无需重写业务代码。

核心优势:

  • 无缝 Spring 集成 :与 Spring Boot 的自动配置、属性绑定、依赖注入完美融合,学习成本低。
  • 声明式配置 :通过 application.yml 即可完成模型连接、参数设置。
  • 功能模块化 :提供了 Chat、Embedding、Image Generation、Vector Store 等模块,结构清晰。

潜在考量:

  • 发展早期 :相比 Python 的 LangChain,其生态和社区成熟度仍在快速发展中。
  • 抽象程度 :高级功能(如复杂的 Agent、工作流)的抽象和支持还在完善中。

对于已经深度使用 Spring 技术栈,且需求集中在模型调用、向量检索等基础能力的团队,Spring AI 是首选的集成路径。

1.2 Spring AI Alibaba:阿里云模型的深度集成

Spring AI Alibaba 可以看作是 Spring AI 的一个扩展实现,专门为阿里云的通义千问(Qwen)系列大模型以及灵积平台(DashScope)进行了深度适配和优化。它实现了 Spring AI 定义的标准接口,因此可以几乎无感地替换掉 Spring AI 中默认的 OpenAI 客户端。

核心价值:

  • 专有模型优化 :针对通义千问模型的参数、调用方式、流式响应等做了专门处理,性能更优。
  • 阿里云生态集成 :天然支持阿里云的 AK/SK 认证、服务网格等云原生能力。
  • 符合国内合规要求 :对于数据不出境、使用国产化模型有硬性要求的场景,这是关键选择。

如果你的项目明确要求使用通义千问、千问 VL 等阿里系模型,或者部署在阿里云上,Spring AI Alibaba 是最直接的方案。

1.3 LangChain4j:Java 版的 LangChain

LangChain4j 是著名 AI 应用框架 LangChain 的 Java 移植版本。它不完全遵循 Spring 那套“约定大于配置”的哲学,而是提供了一套更灵活、功能更丰富的 API 来构建复杂的 AI 应用,特别是在智能体(Agent)、工具(Tool)调用、链(Chain)式编排方面非常强大。

核心优势:

  • 功能强大且成熟 :直接继承了 LangChain 的设计理念,在 Agent、RAG、复杂工作流方面有深厚的积累和丰富的模式。
  • 模型无关性 :支持数十种模型和嵌入服务,包括本地模型(Ollama)。
  • 丰富的工具集成 :可以轻松地将搜索引擎、计算器、数据库查询等封装成工具供 AI 调用。

潜在考量:

  • 与 Spring 集成需要额外配置 :虽然提供了 Spring Boot Starter,但其核心 API 并非完全 Spring 风格,需要一定的适配。
  • 学习曲线 :概念更多(Agent, Chain, Memory, Tool),需要理解其设计模式。

当你需要构建超越简单问答的复杂 AI 应用,例如一个能自动调用 API、查询知识库、进行多轮规划决策的智能体时,LangChain4j 是目前 Java 生态中最有力的工具。

选型决策速查表:

场景需求 推荐框架 关键理由
现有 Spring Boot 项目快速接入 GPT/Claude Spring AI 配置简单,与 Spring 生态无缝融合。
必须使用通义千问等阿里云模型 Spring AI Alibaba 官方深度适配,功能与性能有保障。
构建复杂的、多步骤的智能体(Agent)应用 LangChain4j 在 Agent、Tool、Chain 方面功能最完善。
项目技术栈自由,追求 AI 功能的最大灵活性 LangChain4j 模型和工具支持最广泛,社区活跃。
团队熟悉 Spring,需求以基础模型调用和 RAG 为主 Spring AI Spring AI Alibaba 开发模式最符合团队习惯。

在实际项目中,它们并非互斥。一个常见的混合架构是: 使用 Spring AI Alibaba 作为底层模型调用客户端(实现 ChatClient ),同时利用 LangChain4j 来构建上层的复杂 Agent 逻辑 。这样既能享受 Spring 生态的便利,又能使用 LangChain4j 强大的编排能力。

2. 环境准备与项目初始化

在开始编码前,我们需要一个干净的 Spring Boot 工程环境。这里我们选择 Spring Boot 3.x 和 Java 17 作为基础,因为它们是当前主流且被这些 AI 框架良好支持的版本。

2.1 基础环境检查

首先,确保你的开发环境满足以下要求:

  • JDK : 17 或更高版本(推荐 17 或 21 LTS)。
  • 构建工具 : Maven 3.6+ 或 Gradle 7.x+。
  • IDE : IntelliJ IDEA(推荐)或 VS Code with Spring Boot 插件。

可以通过命令行验证:

java -version
# 应输出类似:openjdk version "17.0.10" ...
mvn -v
# 应输出 Maven 版本信息

2.2 创建 Spring Boot 项目

使用 Spring Initializr 生成项目骨架,选择以下依赖:

  • Project : Maven
  • Language : Java
  • Spring Boot : 3.2.x (最新稳定版)
  • Packaging : Jar
  • Java : 17
  • Dependencies :
    • Spring Web (用于构建 REST API)
    • Lombok (简化代码,可选但推荐)
    • Spring Boot DevTools (开发热加载,可选)

生成并下载项目,解压后用 IDE 打开。你的 pom.xml 初始部分应该类似这样:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.5</version> <!-- 版本可能更新 -->
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>java-ai-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>java-ai-demo</name>
    <description>Demo project for Java AI Integration</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <!-- ... 构建插件等 ... -->
</project>

2.3 引入 AI 框架依赖

接下来,我们将 Spring AI Alibaba 和 LangChain4j 的依赖加入项目。 注意 :由于 Spring AI 和 Spring AI Alibaba 在 ChatClient 等接口上可能存在冲突,我们这里选择以 Spring AI Alibaba 作为模型客户端,并引入 LangChain4j 的 Spring Boot Starter 来使用其高级功能。

pom.xml <dependencies> 部分添加:

<!-- Spring AI Alibaba: 用于连接通义千问等模型 -->
<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-ai-spring-boot-starter</artifactId>
    <version>2023.0.1.0</version> <!-- 请检查最新版本 -->
</dependency>

<!-- LangChain4j Spring Boot Starter -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-spring-boot-starter</artifactId>
    <version>0.31.0</version> <!-- 请检查最新版本 -->
</dependency>

<!-- LangChain4j 对阿里云模型的支持 -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-alibaba-qianfan</artifactId> <!-- 注意:此模块名可能随版本变化 -->
    <version>0.31.0</version>
</dependency>

注意 :AI 框架版本迭代较快,上述版本号在编写时是稳定的,但在你实际实践时,务必去 Maven Central 或项目的 GitHub Release 页面查看最新稳定版本。版本不匹配是后续各种 ClassNotFoundException NoSuchMethodError 的常见根源。

添加依赖后,执行 mvn clean compile 确保依赖下载成功且无冲突。

3. 基础配置与第一个 AI 对话接口

配置是连接模型服务的第一步,也是最容易出错的一步。我们将分别配置 Spring AI Alibaba 和 LangChain4j,并创建两个简单的 REST 端点来验证连通性。

3.1 配置 Spring AI Alibaba 连接通义千问

首先,你需要获取阿里云 DashScope 平台的 API Key。访问阿里云官网,开通灵积(DashScope)服务并创建 API Key。

在项目的 src/main/resources/application.yml 文件中进行配置:

# 应用基础配置
server:
  port: 8080

spring:
  application:
    name: java-ai-demo

  # Spring AI Alibaba 配置
  ai:
    alibaba:
      # 通义千问 Turbo 模型
      chat:
        options:
          # 从阿里云控制台获取
          api-key: ${ALIBABA_API_KEY:your-api-key-here}
          # 模型名称,如 qwen-turbo, qwen-max, qwen-plus 等
          model: qwen-turbo
          # 温度参数,控制随机性 (0.0 ~ 1.0)
          temperature: 0.7
          # 最大生成长度
          max-tokens: 2000
      # 基础连接配置
      base:
        # DashScope API 端点,通常无需修改
        base-url: https://dashscope.aliyuncs.com/compatible-mode/v1

关键参数解释:

  • api-key 切勿硬编码在代码或配置文件中提交到版本库 。推荐使用环境变量 ALIBABA_API_KEY 传入。
  • model :指定要使用的模型。 qwen-turbo 响应快成本低,适合对话; qwen-max 能力更强但更贵。
  • temperature :影响输出的创造性。值越高(接近1.0),回答越多样、随机;值越低(接近0.0),回答越确定、保守。对于事实性问答,建议设低(如0.1);对于创意写作,可以设高。
  • base-url :Spring AI Alibaba 已经适配了 DashScope 的接口,通常使用这个兼容模式端点即可。

3.2 创建 Spring AI Alibaba 的对话服务

创建一个简单的 Service 来使用配置好的 ChatClient

package com.example.javaaidemo.service;

import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class SimpleChatService {

    // Spring AI Alibaba 会自动配置一个 ChatClient Bean
    private final ChatClient chatClient;

    public String chat(String message) {
        // 调用 ChatClient 进行同步对话
        return chatClient.prompt()
                .user(message)
                .call()
                .content();
    }

    public String chatWithSystem(String userMessage, String systemInstruction) {
        // 可以指定系统指令,塑造 AI 的角色
        return chatClient.prompt()
                .system(systemInstruction) // 例如:“你是一个专业的Java工程师助手”
                .user(userMessage)
                .call()
                .content();
    }
}

创建一个 REST 控制器来暴露接口:

package com.example.javaaidemo.controller;

import com.example.javaaidemo.service.SimpleChatService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/ai")
@RequiredArgsConstructor
public class ChatController {

    private final SimpleChatService chatService;

    @PostMapping("/chat")
    public String chat(@RequestBody ChatRequest request) {
        return chatService.chat(request.getMessage());
    }

    @PostMapping("/chat-with-role")
    public String chatWithRole(@RequestBody RoleChatRequest request) {
        return chatService.chatWithSystem(request.getUserMessage(), request.getSystemInstruction());
    }

    // 简单的请求体
    public static class ChatRequest {
        private String message;
        // getter and setter ...
    }
    public static class RoleChatRequest {
        private String userMessage;
        private String systemInstruction;
        // getter and setter ...
    }
}

启动应用,使用 curl 或 Postman 测试:

curl -X POST http://localhost:8080/api/ai/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "用Java写一个Hello World程序"}'

如果配置正确,你将收到通义千问模型生成的 Java 代码。这一步验证了 Spring AI Alibaba 的基础集成是成功的。

3.3 配置与使用 LangChain4j 进行对话

LangChain4j 的配置相对独立。我们需要在 application.yml 中补充它的配置,并创建一个使用其 ChatLanguageModel 的服务。

application.yml 中追加:

# LangChain4j 配置
langchain4j:
  alibaba:
    qianfan:
      # 使用同一个 API Key
      api-key: ${ALIBABA_API_KEY:your-api-key-here}
      # 模型名称,与上面保持一致
      model-name: ${spring.ai.alibaba.chat.options.model:qwen-turbo}
      # 温度、最大token等参数
      temperature: ${spring.ai.alibaba.chat.options.temperature:0.7}
      max-tokens: ${spring.ai.alibaba.chat.options.max-tokens:2000}
      top-p: 0.9 # 另一个采样参数,与 temperature 配合使用
      # 请求超时时间
      timeout: 60s

创建 LangChain4j 的对话服务:

package com.example.javaaidemo.service;

import dev.langchain4j.model.chat.ChatLanguageModel;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class LangChain4jChatService {

    // LangChain4j 会自动注入配置好的模型 Bean
    private final ChatLanguageModel chatLanguageModel;

    public String chat(String message) {
        return chatLanguageModel.generate(message);
    }

    public String chatWithMemory(String message) {
        // LangChain4j 的一个优势是内置了简单的对话记忆管理
        // 这里演示一个最简单的单次调用
        return chatLanguageModel.generate(message);
        // 更复杂的多轮记忆需要用到 ChatMemory 和 AiServices,下文会介绍
    }
}

在控制器中增加一个端点:

@RestController
@RequestMapping("/api/ai")
@RequiredArgsConstructor
public class ChatController {
    // ... 之前的 SimpleChatService 注入 ...
    private final LangChain4jChatService langChain4jChatService;

    @PostMapping("/langchain-chat")
    public String langchainChat(@RequestBody ChatRequest request) {
        return langChain4jChatService.chat(request.getMessage());
    }
}

测试这个端点,功能上与第一个端点类似,但底层使用的是 LangChain4j 的抽象。至此,我们完成了两个框架的基础接入。接下来,我们将利用 LangChain4j 更强大的能力,构建一个真正的智能体(Agent)。

4. 构建智能体(Agent)案例实战

智能体的核心是让大模型能够“使用工具”。我们将创建一个“业务数据分析助手”Agent,它可以根据用户描述,调用我们预定义的工具(例如,查询本周销售额、查询热门商品)来回答问题,而不是仅仅基于训练数据生成文本。

4.1 定义工具(Tools)

工具是 Agent 可以调用的函数。在 LangChain4j 中,工具就是一个普通的 Java 方法,加上 @Tool 注解。

首先,创建一个工具类 BusinessDataTools

package com.example.javaaidemo.agent.tools;

import dev.langchain4j.agent.tool.Tool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class BusinessDataTools {

    /**
     * 查询指定日期范围的销售额。
     * @param startDate 开始日期 (YYYY-MM-DD)
     * @param endDate 结束日期 (YYYY-MM-DD)
     * @return 销售额描述
     */
    @Tool("根据开始日期和结束日期查询销售额。日期格式必须是 YYYY-MM-DD。")
    public String querySales(String startDate, String endDate) {
        log.info("工具被调用: querySales, 参数: startDate={}, endDate={}", startDate, endDate);
        // 这里应该是真实的数据库或API调用,此处模拟返回
        // 实际项目中,这里可以注入 Repository 或 Service
        double simulatedSales = 150000.0 + Math.random() * 50000;
        return String.format("从 %s 到 %s 的销售额约为 %.2f 元。", startDate, endDate, simulatedSales);
    }

    /**
     * 查询本周的销售额(从周一到今天)。
     */
    @Tool("查询本周(周一到今天)的销售额。")
    public String queryThisWeekSales() {
        log.info("工具被调用: queryThisWeekSales");
        LocalDate today = LocalDate.now();
        LocalDate monday = today.with(DayOfWeek.MONDAY);
        return querySales(monday.toString(), today.toString());
    }

    /**
     * 查询热门商品列表。
     * @param topN 返回前N名,默认是5
     * @return 热门商品列表描述
     */
    @Tool("查询最畅销的前N个商品。")
    public String queryTopProducts(@Tool("返回的商品数量") int topN) {
        log.info("工具被调用: queryTopProducts, 参数: topN={}", topN);
        // 模拟数据
        List<Map.Entry<String, Integer>> products = List.of(
                Map.entry("智能手机", 1200),
                Map.entry("无线耳机", 850),
                Map.entry("笔记本电脑", 600),
                Map.entry("智能手表", 450),
                Map.entry("平板电脑", 300)
        );
        StringBuilder sb = new StringBuilder("热门商品排名:\n");
        products.stream().limit(topN).forEach(entry ->
                sb.append(String.format("- %s: 销量 %d 件\n", entry.getKey(), entry.getValue()))
        );
        return sb.toString();
    }

    /**
     * 一个简单的计算器工具,展示 Agent 可以处理逻辑。
     */
    @Tool("执行简单的数学计算,支持加(+)、减(-)、乘(*)、除(/)。")
    public String calculate(String expression) {
        log.info("工具被调用: calculate, 参数: expression={}", expression);
        try {
            // 警告:这是一个极其简化的示例,生产环境必须使用安全的表达式求值库!
            String[] parts = expression.split("\\s+");
            if (parts.length != 3) {
                return "表达式格式错误,请使用 'a + b' 这样的格式。";
            }
            double a = Double.parseDouble(parts[0]);
            double b = Double.parseDouble(parts[2]);
            double result;
            switch (parts[1]) {
                case "+": result = a + b; break;
                case "-": result = a - b; break;
                case "*": result = a * b; break;
                case "/":
                    if (b == 0) return "错误:除数不能为零。";
                    result = a / b;
                    break;
                default: return "不支持的操作符: " + parts[1];
            }
            return String.format("%s = %.2f", expression, result);
        } catch (Exception e) {
            return "计算失败: " + e.getMessage();
        }
    }
}

关键点说明:

  1. @Tool 注解 :标记一个方法可以作为工具被 Agent 调用。注解中的字符串描述非常重要,AI 模型会阅读这个描述来决定何时以及如何调用该工具。
  2. 方法参数 :工具方法的参数名和类型也会被模型感知。可以使用 @Tool 注解在参数上提供更详细的描述。
  3. 模拟实现 :示例中返回了模拟数据。在实际项目中,这里应该注入你的 Service 或 Repository,执行真实的业务逻辑。
  4. 日志 :在工具方法开始处打日志,对于调试 Agent 的决策过程至关重要。

4.2 创建 AI 服务(AiServices)与 Agent

LangChain4j 的 AiServices 是一个强大的抽象,它能够自动将工具、记忆(Memory)和模型绑定在一起,创建一个可以对话的 AI 服务接口。

首先,定义这个 AI 服务接口:

package com.example.javaaidemo.agent;

import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import dev.langchain4j.service.V;

public interface BusinessAnalystAgent {

    /**
     * 与业务分析师对话。
     * @param userMessage 用户消息
     * @return Agent 的回复,可能包含工具调用结果。
     */
    @SystemMessage("""
            你是一个专业的业务数据分析助手。你的职责是帮助用户分析业务数据。
            你可以调用工具来查询销售额、热门商品等信息,也可以进行简单的计算。
            如果用户的问题需要查询数据,请主动调用合适的工具。
            你的回答应该专业、清晰,并基于工具返回的数据。
            如果工具返回了数据,请在回答中总结并解释这些数据。
            """)
    String chat(@UserMessage String userMessage);

    /**
     * 一个更复杂的例子,使用动态变量。
     * @param question 用户问题
     * @param userName 用户名
     * @return 个性化的回复
     */
    @SystemMessage("你是{{userName}}的专属业务顾问。")
    String personalizedChat(@V("userName") String userName, @UserMessage String question);
}

接口设计解析:

  • @SystemMessage :定义了 AI 的“系统提示词”(System Prompt),即它的角色和行事规则。这是塑造 Agent 行为的关键。
  • @UserMessage :标记哪个参数是用户的输入。
  • @V :用于在 @SystemMessage @UserMessage 中引用方法参数,实现动态提示词。

接下来,在配置类或主应用类中,创建这个 AiService 的 Bean:

package com.example.javaaidemo.config;

import com.example.javaaidemo.agent.BusinessAnalystAgent;
import com.example.javaaidemo.agent.tools.BusinessDataTools;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.service.AiServices;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AgentConfig {

    @Bean
    public BusinessAnalystAgent businessAnalystAgent(
            ChatLanguageModel chatLanguageModel, // 注入之前配置的模型
            BusinessDataTools businessDataTools // 注入工具类
    ) {
        // 创建聊天记忆,保留最近10轮对话
        ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);

        return AiServices.builder(BusinessAnalystAgent.class)
                .chatLanguageModel(chatLanguageModel)
                .chatMemory(chatMemory) // 为Agent绑定记忆,实现多轮对话
                .tools(businessDataTools) // 注册工具类,其内部所有@Tool方法都会被自动发现
                .build();
    }
}

4.3 创建 Agent 控制器并测试

现在,我们可以通过 REST API 来与这个智能体交互了。

package com.example.javaaidemo.controller;

import com.example.javaaidemo.agent.BusinessAnalystAgent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/agent")
@RequiredArgsConstructor
@Slf4j
public class AgentController {

    private final BusinessAnalystAgent businessAnalystAgent;

    @PostMapping("/analyze")
    public String analyze(@RequestBody AgentRequest request) {
        log.info("收到Agent分析请求: {}", request.getQuestion());
        String response = businessAnalystAgent.chat(request.getQuestion());
        log.info("Agent回复: {}", response);
        return response;
    }

    public static class AgentRequest {
        private String question;
        // getter and setter ...
    }
}

启动应用,进行测试。以下是几个测试用例和预期的 Agent 行为:

测试 1:查询本周销售额

curl -X POST http://localhost:8080/api/agent/analyze \
  -H "Content-Type: application/json" \
  -d '{"question": "本周的销售情况怎么样?"}'
  • 预期 :Agent 会识别出需要查询本周销售额,调用 queryThisWeekSales 工具。你会在应用日志中看到 工具被调用: queryThisWeekSales 。然后 Agent 会将工具返回的模拟销售额数据整合到它的自然语言回复中,例如:“根据查询,从2024-05-20到2024-05-26的销售额约为 178,345.12 元。本周销售表现稳健。”

测试 2:混合查询与计算

curl -X POST http://localhost:8080/api/agent/analyze \
  -H "Content-Type: application/json" \
  -d '{"question": "帮我查一下最热门的3个商品,然后计算一下如果它们的单价都上涨10%,总销售额会增加多少?假设当前平均单价分别是2000、800、5000。"}'
  • 预期 :这是一个多步骤任务。Agent 可能会:
    1. 先调用 queryTopProducts(3) 获取商品列表。
    2. 然后,它需要“计算”。它可能会尝试调用 calculate 工具,但需要先组织好计算表达式。高级的模型能够进行规划,它可能会分别计算每个商品的增长额再求和,或者直接计算总增长额。观察日志,你会看到多个工具被依次调用。

测试 3:多轮对话(依赖记忆) 连续发送两条消息:

# 第一轮
curl -X POST ... -d '{"question": "我是张三,我想了解业务。"}'
# 第二轮
curl -X POST ... -d '{"question": "那我本周的销售额呢?"}'
  • 预期 :由于我们为 Agent 配置了 ChatMemory ,在第二轮对话中,Agent 能记住上下文(用户是“张三”),并在回答中体现出来。这展示了 Agent 的对话连贯性。

通过这个案例,你已经构建了一个能够理解用户意图、自主选择并调用工具、整合信息后回复的真正智能体。这远比简单的模型调用强大。

5. 生产环境关键配置、排错与最佳实践

将 AI 应用部署到生产环境,会面临与开发环境不同的问题。以下是必须关注的要点。

5.1 配置管理:安全与灵活性

1. API Key 管理:

  • 绝对禁止硬编码 :如前所述,使用环境变量或配置中心(如 Spring Cloud Config, Apollo, Nacos)。
  • 使用配置 Profile :在 application-prod.yml 中配置生产环境的 Key 和端点,与开发环境隔离。
  • 密钥轮换 :制定流程,定期轮换 API Key。

2. 连接与超时配置: application-prod.yml 中调整超时和重试策略,防止网络抖动导致服务雪崩。

spring:
  ai:
    alibaba:
      base:
        connect-timeout: 5s
        read-timeout: 30s # 大模型响应可能较慢
        max-retries: 2 # 谨慎设置重试,某些错误重试无效且浪费token

langchain4j:
  alibaba:
    qianfan:
      timeout: 30s
      log-requests: true # 生产环境建议开启,用于审计和调试
      log-responses: false # 响应可能包含敏感数据,生产环境谨慎开启

5.2 常见问题排查清单

当你的 AI 接口出现问题时,请按以下顺序排查:

问题现象 可能原因 检查点与解决方案
启动报错 NoSuchBeanDefinitionException (ChatClient/ChatLanguageModel) 1. 依赖未正确引入。
2. 配置项缺失或错误。
3. 版本冲突。
1. 检查 pom.xml 依赖,运行 mvn dependency:tree 查看是否拉取成功。
2. 检查 application.yml spring.ai.alibaba langchain4j.alibaba 配置项,特别是 api-key
3. 确认 Spring Boot、Spring AI Alibaba、LangChain4j 版本兼容性。
调用接口返回 401/403 错误 API Key 无效、过期或没有对应模型的权限。 1. 去阿里云控制台确认 API Key 状态和额度。
2. 确认配置的 model 名称是否正确,且该 Key 有权访问此模型。
3. 检查环境变量是否生效。
调用超时 (Timeout) 1. 网络问题。
2. 模型响应慢。
3. 请求的 max-tokens 设置过大。
1. 检查服务器网络连通性。
2. 适当调大 read-timeout
3. 降低 max-tokens temperature ,简化用户问题。
Agent 不调用工具,直接回答“我不知道” 1. 工具描述 ( @Tool 注解) 不清晰。
2. 系统提示词 ( @SystemMessage ) 未明确指示使用工具。
3. 模型能力不足。
1. 优化工具描述,确保清晰说明功能、输入格式和用途。
2. 强化系统提示词,例如:“你必须优先考虑使用工具来获取数据回答用户问题。”
3. 尝试更换更强的基础模型(如 qwen-max )。
工具被调用,但参数解析错误 模型未能正确理解用户问题并提取参数。 1. 在工具方法内增加更严格的参数校验和日志。
2. 优化系统提示词,指导模型如何提取参数。
3. 考虑在工具层做参数的后处理和兜底逻辑。
多轮对话中,Agent 忘记上下文 ChatMemory 配置不当或未生效。 1. 确认 AiServices.builder() 时绑定了 ChatMemory Bean。
2. 检查 MessageWindowChatMemory.withMaxMessages(10) 中的消息数量是否足够。
3. 对于 Web 应用,需要为每个用户/会话创建独立的 ChatMemory 实例,通常需要自定义实现或使用 TokenWindowChatMemory

5.3 性能、成本与监控最佳实践

1. 优化 Token 使用以控制成本:

  • 精简提示词 :系统提示词和工具描述要精炼准确,减少不必要的 Token 消耗。
  • 缓存结果 :对于重复性高、结果变化不频繁的查询(如“公司介绍”),可以将 AI 的回复缓存起来(使用 Redis 或 Caffeine),避免重复调用模型。
  • 设置最大 Token 限制 :在配置中明确设置 max-tokens ,防止生成过长内容。

2. 引入熔断与降级: 使用 Resilience4j 或 Sentinel 为 AI 服务调用配置熔断器。当模型服务连续超时或失败时,快速失败并返回预设的降级内容(如“系统繁忙,请稍后再试”),保护自身服务不被拖垮。

// 伪代码示例
@CircuitBreaker(name = "aiChatService", fallbackMethod = "fallbackResponse")
public String chatWithCircuitBreaker(String message) {
    return businessAnalystAgent.chat(message);
}
private String fallbackResponse(String message, Throwable t) {
    log.warn("AI服务降级,原问题: {}", message, t);
    return "当前AI服务暂时不可用,请稍后重试。";
}

3. 完善的日志与监控:

  • 记录请求与响应摘要 :记录用户问题、调用的工具、消耗的 Token 数(如果 API 返回)、响应时间。 注意脱敏 ,不要记录完整的 API Key 和可能包含用户隐私的响应内容。
  • 监控关键指标 :使用 Micrometer 暴露指标,如 ai.request.count , ai.request.duration , ai.token.usage ,并接入 Prometheus 和 Grafana。
  • 工具调用审计 :所有工具调用(特别是涉及数据修改或敏感查询的)必须有清晰的审计日志,记录操作人、时间、参数和结果。

4. 处理速率限制(Rate Limiting): 模型服务商都有调用频率限制。在客户端(你的应用)实现简单的限流,避免突发流量触发服务商限流导致整体失败。可以使用 Guava 的 RateLimiter 或 Resilience4j 的 RateLimiter

从简单的模型调用到复杂的智能体构建,Java 生态通过 Spring AI Alibaba 和 LangChain4j 提供了坚实的支撑。成功的集成关键在于理解框架的抽象层次,做出正确的选型,并像对待任何外部服务一样,为 AI 调用配置好超时、重试、熔断、监控和审计。本文的案例提供了一个从零到一的完整路径,但每个生产系统都需要在此基础上,根据自身的业务逻辑、数据安全和性能要求进行深度定制。下一步,你可以探索更复杂的 Agent 模式(如 ReAct、Plan-and-Execute),集成向量数据库实现 RAG,或者将 AI 能力与你现有的业务工作流引擎相结合,创造出真正智能化的业务应用。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐