行业资讯 2025年08月6日
0 收藏 0 点赞 341 浏览 5076 个字
摘要 :

文章目录 一、函数调用的工作原理 二、基于Spring Boot和Spring AI实现函数调用 (一)定义函数 (二)在聊天选项中传递函数契约 (三)创建控制器 三、演示 四、总结……




  • 一、函数调用的工作原理
  • 二、基于Spring Boot和Spring AI实现函数调用
    • (一)定义函数
    • (二)在聊天选项中传递函数契约
    • (三)创建控制器
  • 三、演示
  • 四、总结

本文将详细介绍如何在Spring AI框架下,借助Spring Boot实现函数调用功能,让LLM能够调用外部API获取实时数据,进而准确回答用户的问题。通过实际示例,帮助读者深入理解并掌握这一技术。

一、函数调用的工作原理

从本质上讲,大语言模型类似于强化版的自动补全程序,它们凭借预先训练的历史知识,在生成文本方面表现出色。然而,大语言模型自身无法从远程API获取实时信息,也不能替我们进行科学计算。

因此,我们需要编写特定的函数来获取回答用户问题所需的实时信息。当向大语言模型传递用户提示时,除了其他元数据,还必须提供有关这个函数的信息。

当大语言模型需要相关信息来回答用户问题时,会返回一个函数执行请求。聊天机器人应用接收到请求后,会调用相应的服务方法或函数,获取所需的实时信息。然后,聊天机器人应用将JSON格式的响应发送回大语言模型。大语言模型接收到JSON响应后,会对其中的信息进行解读,最终结合实时信息,以文本形式回复用户。Spring AI 如何调用外部API实战

二、基于Spring Boot和Spring AI实现函数调用

在Spring AI中实现函数调用功能,主要需要完成两个关键步骤:定义函数并将其配置为Spring bean,以及在与大语言模型交互时,在聊天选项中指定函数。

(一)定义函数

在Spring AI里,我们把函数定义为Function类型的bean。当大语言模型需要实时信息时,就会调用这个bean。在下面的示例中,当函数被调用时,它会执行StockPriceService::getStockPrice方法。

import com.howtodoinjava.ai.demo.StockPriceService.Stock;
import java.util.function.Function;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;

// 配置类,用于定义Spring bean,proxyBeanMethods = false表示不使用CGLIB代理创建bean,提升性能
@Configuration(proxyBeanMethods = false) 
public class Functions {
    // 定义一个名为priceByStockNameFunction的bean
    @Bean
    // 为bean添加描述,帮助大语言模型理解其功能
    @Description(\"Get price by stock name\") 
    public Function<Stock, Double> priceByStockNameFunction(StockPriceService stockPriceService) {
        // 返回一个方法引用,当函数被调用时,会执行StockPriceService的getStockPrice方法
        return stockPriceService::getStockPrice; 
    }
}

StockPriceService类中,getStockPrice()方法用于执行API调用或进行计算。通过这种方式,将API调用逻辑与大语言模型的函数调用逻辑分离开来。

import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

@Service
public class StockPriceService {
    // 使用ConcurrentHashMap存储股票名称和价格的映射关系,保证线程安全
    private static final Map<Stock, Double> data = new ConcurrentHashMap<>(); 

    // 静态代码块,初始化一些股票价格数据,仅用于演示
    static { 
        data.put(new Stock(\"Google\"), 101.00);
        data.put(new Stock(\"Microsoft\"), 100.00);
        // 可继续添加其他股票数据
    }

    // 根据股票名称获取股票价格的方法
    Double getStockPrice(Stock stock) {
        // 实际应用中,这里应是调用外部服务获取数据的逻辑
        // 此处为演示,从预定义的Map中查找股票价格
        return data.keySet().stream() 
               .filter(s -> s.name().equalsIgnoreCase(stock.name()))
               .map(s -> data.get(s))
               .findFirst()
               .orElse(-1.0); 
    }

    // 定义一个记录类,用于表示股票,包含股票名称属性
    public record Stock(String name) { 
    }
}

需要注意的是,bean的描述非常重要,它能帮助大语言模型理解函数的功能,从而判断在当前对话场景下是否需要调用该函数。在实际应用中,股票价格数据通常是通过HTTP调用外部服务获取的,这里为了演示方便,使用了预定义的Map数据。

(二)在聊天选项中传递函数契约

函数定义完成后,需要将函数契约信息发送给大语言模型。ChatClient.ChatClientRequestSpec类提供了functions()方法,通过这个方法可以在向大语言模型发送用户提示时,同时传递函数bean的名称。

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

@Service
public class ChatService {
    // 注入ChatClient实例,用于与大语言模型进行交互
    private final ChatClient chatClient; 

    // 构造函数,通过ChatClient.Builder构建ChatClient实例
    ChatService(ChatClient.Builder chatClientBuilder) { 
        this.chatClient = chatClientBuilder.build();
    }

    // 根据股票名称获取股票价格的方法
    String getPriceByStockName(String stockName) {
        // 定义用户提示模板,其中{stockName}是占位符
        var userPromptTemplate = \"Get the latest price for {stockName}.\"; 
        // 使用ChatClient发送提示并获取响应
        return chatClient.prompt() 
               .user(userSpec -> userSpec
                        // 设置用户提示文本,并填充stockName参数
                       .text(userPromptTemplate) 
                       .param(\"stockName\", stockName)
                )
               // 传递函数契约,指定要调用的函数bean名称
               .functions(\"priceByStockNameFunction\") 
               .call()
               .content(); 
    }
}

如果使用ChatModel类,也可以通过OpenAiChatOptions构建器来传递函数信息。

// 定义用户提示模板
var userPromptTemplate = \"Get the latest price for {stockName}.\"; 
// 创建提示模板对象
PromptTemplate promptTemplate = new PromptTemplate(userPromptTemplate); 
// 根据提示模板和参数创建消息对象
Message message = promptTemplate.createMessage(Map.of(\"stockName\", stockName)); 
// 使用ChatModel发送提示并获取响应
ChatResponse response = chatModel.call(
        new Prompt(List.of(message), OpenAiChatOptions.builder()
               // 添加要调用的函数信息
               .withFunction(\"priceByStockNameFunction\").build())); 
// 返回响应中的内容
return response.getResult().getOutput().getContent(); 

(三)创建控制器

最后,为了让终端用户能够与大语言模型进行交互,我们在聊天机器人应用中通过REST端点来暴露ChatService

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ChatController {
    // 注入ChatService实例
    private final ChatService chatService; 

    // 构造函数,用于初始化ChatService实例
    ChatController(ChatService chatService) { 
        this.chatService = chatService;
    }

    // 处理GET请求,根据用户传入的股票名称获取股票价格并返回
    @GetMapping(\"/chat/function\") 
    String chat(@RequestParam String stockName) {
        return chatService.getPriceByStockName(stockName);
    }
}

三、演示

在本演示中,我们使用OpenAI GPT模型来响应用户提示。首先,需要在项目中添加相关依赖。如果是新建项目,可以参考《Spring AI入门指南》进行项目搭建。

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

别忘了在环境变量或属性文件中指定OpenAI API密钥,配置如下:

spring.ai.openai.api-key=${OPENAI_API_KEY}

完成上述配置后,将Spring Boot应用作为Web应用启动。然后,通过如下命令调用股票价格API:

curl --location \'http://localhost:8080/chat/function?stockName=Microsoft\'

执行上述命令后,会得到如下响应:

The latest price for Microsoft is $100.00.

Spring AI 如何调用外部API实战

四、总结

通过本文的学习,我们掌握了如何在Spring AI和Spring Boot的框架下,利用函数调用实现大语言模型对外部API的调用。需要明确的是,大语言模型本身不具备调用外部API的能力,这就需要我们编写相应的函数,并在与大语言模型交互时提供准确的函数信息和描述,以便大语言模型判断是否调用该函数。Spring AI将整个函数调用流程进行了框架化封装,大大简化了开发过程,我们只需专注于函数的定义和描述即可。

归属教程 Spring AI 快速入门教程汇总

文章目录 Spring AI是什么?有啥优势? 如何在项目中使用Spring AI? Spring AI详细功 […]

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/10305.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号