什么是Function Calling

Function Calling = 大模型主动调用你写好的函数 / 接口,完成真实任务的能力。

不过,springAI在这个依然做了封装,它利用tool类把循环的部分封装到一块,所以我们只需要把我们的接口写到tool里即可实现传统编程和大模型的搭配使用

实现Function Calling

初始化客户端

这里的客户端是在之前的基础上增加了tool的功能

什么是tool

我们要实现AI+传统编程相结合的功能,就要使用AI的响应结果;把响应结果作为入参输入到传统的方法中。

那么tool就是把响应结果注入到传统编程的参数中的过程,或者可以理解为一个注入类。

  @Bean
    public ChatClient serviceChatClient(DashScopeChatModel model, ChatMemory chatMemory, CourseTools courseTools) {
        return ChatClient
                .builder(model)// 对接阿里云百炼的大模型
                .defaultSystem(SystemConstants.SERVICE_SYSTEM_PROMPT)//系统AI设定
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                        // 直接用 builder(chatMemory) 构建,不额外指定 defaultConversationId
                        MessageChatMemoryAdvisor.builder(chatMemory)// 记忆
                                .build()
                )
                .defaultTools(courseTools)//工具类
                .build();
    }

那么tool就是把响应结果注入到传统编程的参数中的过程,或者可以理解为一个注入类。

  @Bean
    public ChatClient serviceChatClient(DashScopeChatModel model, ChatMemory chatMemory, CourseTools courseTools) {
        return ChatClient
                .builder(model)// 对接阿里云百炼的大模型
                .defaultSystem(SystemConstants.SERVICE_SYSTEM_PROMPT)//系统AI设定
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                        // 直接用 builder(chatMemory) 构建,不额外指定 defaultConversationId
                        MessageChatMemoryAdvisor.builder(chatMemory)// 记忆
                                .build()
                )
                .defaultTools(courseTools)//工具类
                .build();
    }

如何编写一个TOOL

SpringAI已经封装好了注解,我们利用注解就能把AI的返回结果作为参数注入到方法中

@Tool注解:给AI作为一个标记,利用()中的description的描述来告诉AI这个方法的作用,比如下面的这个方法当AI需要查询课程的时候他就会通过description调用这个方法。

@ToolParam:工具类的参数,也就是AI返回结果在方法中充当的参数。

比如我告诉AI:我是大专生,我想学编程,帮我查询响应的课程。

AI会通过@ToolParam将“大专”和“编程”作为参数去查询queryCourse方法

@Slf4j
@Component
public class CourseTools {

    @Autowired
    private ICourseService courseService;
    @Autowired
    private ISchoolService schoolService;
    @Autowired
    private ICourseReservationService reservationService;

    @Tool(description = "根据条件查询课程")
    public List<Course> queryCourse(@ToolParam(description = "查询的条件", required = false) CourseQuery query) {
        if (query == null) {
            return courseService.list();
        }
        log.info("当前查询课程的条件为:{}",query);
        QueryChainWrapper<Course> wrapper = courseService.query()
                .eq(query.getType() != null, "type", query.getType()) // type = '编程'
                .le(query.getEdu() != null, "edu", query.getEdu());// edu <= 2
        log.info("查询接口为:{}",wrapper);
        if (query.getSorts() != null && !query.getSorts().isEmpty()) {
            for (CourseQuery.Sort sort : query.getSorts()) {
                wrapper.orderBy(true, sort.getAsc(), sort.getField());
            }
        }
        return wrapper.list();
    }

同理,通过我们给AI的提示词,AI就可以调用我们的接口实现功能(预约功能)

    @Tool(description = "生成预约单,返回预约单号")
    public Integer createCourseReservation(
            @ToolParam(description = "预约课程") String course,
            @ToolParam(description = "预约校区") String school,
            @ToolParam(description = "学生姓名") String studentName,
            @ToolParam(description = "联系电话") String contactInfo,
            @ToolParam(description = "备注", required = false) String remark) {
        CourseReservation reservation = new CourseReservation();
        reservation.setCourse(course);
        reservation.setSchool(school);
        reservation.setStudentName(studentName);
        reservation.setContactInfo(contactInfo);
        reservation.setRemark(remark);
        reservationService.save(reservation);

        return reservation.getId();
    }