模拟一个最经典的场景:查询实时天气。

因为大模型(如 GPT)的数据是预训练的,它不知道此时此刻“北京”的天气如何,所以它必须“回调”我们的 Java 代码来获取真实数据。


示例场景:智能天气助手

我们需要做三件事:

  1. 定义输入/输出数据结构(Class/Record)。
  2. 编写具体的 Java 逻辑并注册为 Bean。
  3. ChatClient 中启用这个函数。
1. 定义输入和输出 (Request & Response)

Spring AI 会利用 Java 的类型系统(Reflection)来读取这些字段,自动生成 JSON Schema 告诉大模型:“这个函数需要一个叫 location 的字符串参数”。

Java

// 1. 请求参数(大模型会尝试提取这个参数)
public record WeatherRequest(String location) {}

// 2. 响应数据(我们将把这个数据返回给大模型)
public record WeatherResponse(String location, String temp, String description) {}
2. 注册函数 Bean (The Magic Part)

这是最关键的一步。我们需要定义一个标准的 java.util.function.Function,并加上 @Description 注解。

  • @Description 的作用: 这段文字会被发送给大模型。大模型通过读这句话来决定 “在什么情况下” 应该调用这个函数。

Java

@Configuration
public class ToolsConfig {

    @Bean
    @Description("Get the weather in location. 用于查询特定地点的天气状况") 
    public Function<WeatherRequest, WeatherResponse> weatherFunction() {
        return request -> {
            // 这里通常会调用第三方API (如高德/OpenWeatherMap)
            // 为了演示简单,我们直接模拟数据
            System.out.println(">>> 正在调用 Java 方法查询天气: " + request.location());
            
            if (request.location().contains("北京")) {
                return new WeatherResponse(request.location(), "25°C", "晴朗");
            } else {
                return new WeatherResponse(request.location(), "20°C", "多云");
            }
        };
    }
}
3. 实际调用 (ChatClient)

在 Controller 或 Service 中,我们告诉 AI:“你可以使用 weatherFunction 这个工具”。

Java

@RestController
public class ChatController {

    private final ChatClient chatClient;

    // 构造器注入,Spring AI 自动配置好了 Builder
    public ChatController(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }

    @GetMapping("/ask")
    public String askAi(@RequestParam String prompt) {
        return chatClient.prompt()
                .user(prompt)
                // 关键点:启用刚才注册的 Bean 名称
                .functions("weatherFunction") 
                .call()
                .content();
    }
}

底层原理拆解:刚才发生了什么?

当你访问 /ask?prompt=北京天气怎么样? 时,Spring AI 在底层通过以下步骤完成了“魔法”:

第一步:意图识别与参数提取 (Java -> LLM)

Spring AI 扫描到了 weatherFunction,它将其转换为类似下面的 JSON Schema,附带在发送给 LLM 的请求中:

JSON

// Spring AI 发给 LLM 的 system 提示片段(伪代码)
{
  "tools": [
    {
      "name": "weatherFunction",
      "description": "用于查询特定地点的天气状况",
      "parameters": {
        "type": "object",
        "properties": {
          "location": { "type": "string", "description": "城市名称" }
        },
        "required": ["location"]
      }
    }
  ],
  "messages": [{ "role": "user", "content": "北京天气怎么样?" }]
}
第二步:大模型决策 (LLM -> Java)

LLM 收到请求,分析发现用户问的是天气,且自己手头有一个 weatherFunction 可以用。

它不会直接回答“天气很好”,而是返回一个特殊的指令(Function Call Request):

  • LLM 回复: “请帮我调用 weatherFunction,参数是 {"location": "北京"}”。
第三步:本地执行与递归 (Java Execution)
  1. Spring AI 的拦截器捕获到这个“调用请求”。
  2. 它利用 Java 反射机制,找到 weatherFunction Bean。
  3. 它将 JSON {"location": "北京"} 反序列化为 WeatherRequest 对象。
  4. 执行 weatherFunction.apply() 方法(控制台打印 >>> 正在调用...)。
  5. 拿到返回值 WeatherResponse(25°C, 晴朗)。
第四步:最终生成 (Java -> LLM)

Spring AI 拿着 Java 方法的运行结果,再次发起请求给 LLM:

  • 发送内容: “函数调用结果是:北京,25°C,晴朗。请根据这个信息回复用户。”
  • LLM 最终回复: “目前北京的天气是晴朗的,气温大约 25°C。”

总结

这个过程完全体现了 Spring AI 的核心价值:它把复杂的“提示词工程”和“JSON 序列化/反序列化”封装成了标准的 Java 方法调用。 开发者只需要写业务逻辑(Function),剩下的底层代码由框架自动处理。


Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐