当前位置: 首页 > news >正文

Spring AI Alibaba-04- Spring AI + RAG + ToolCalling 智能对话应用开发全流程

Spring AI Alibaba-04- Spring AI + RAG + ToolCalling 智能对话应用开发全流程

文章目录

  • Spring AI Alibaba-04- Spring AI + RAG + ToolCalling 智能对话应用开发全流程
    • 概述
      • **Tool Calling 的核心优势在于:**
      • 功能介绍
    • 环境准备
    • 测试验证

概述

Tool Calling 的核心优势在于:

简化开发流程:通过统一的工具调用接口,开发者可以专注于业务逻辑,而无需处理繁琐的 HTTP 请求和响应解析。
增强扩展性:工具可以动态注册和调用,支持快速集成新服务。
提升用户体验:通过工具调用,应用可以实时获取外部数据(如天气、假期等),为用户提供了一个更智能、更全面的服务体验。
在本篇文章中,我们将通过一个具体的案例,展示如何使用 Spring AI 的 Tool Calling 功能来调用天气服务和 OA 服务,帮助开发者快速上手这一强大功能。

功能介绍

Spring AI 的 Tool Calling 提供了以下核心功能:

  1. 工具注册与管理:支持动态注册工具,并通过注解或配置文件定义工具的描述和参数。
  2. 工具调用链:通过方法链式调用,开发者可以轻松组合多个工具,实现复杂业务逻辑。

在本案例中,我们将实现以下功能:

  • 调用外部天气 API,获取指定城市的天气预报。
  • 调用内部 OA 服务,查询员工剩余假期和提交请假申请。
  • 通过 RAG 找到医生后,进行挂号
  • 挂号当日在医院附近找饭店
  • 对比两种实现方式(无工具调用 vs 工具调用),展示 Tool Calling 的优势。

环境准备

  • 操作系统:Windows 11
  • Java 版本:JDK 17+(请注意 Spring Boot 3.4.4 的兼容性),Redis 、Elasticsearch、Milvus向量数据库
  • 依赖管理:Maven 3.8.3+
  • 天气服务:需要注册天气服务 API 账号申请
  • 阿里云百炼平台: 账号申请 后,可以查看到以下模型的选择 Deepseek接入

通过 Spring 的依赖注入机制,将 Redis 聊天记忆模型与 ChatClient 进行绑定,确保对话记忆功能能够正常工作。

Tool calling 相关服务

  1. 医院挂号服务
package com.lison.ai.spring_ai_alibaba_demo.toolcalling;import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.context.annotation.Description;@Slf4j
@Description("医院挂号的功能")
public class HospitalService {@Tool(description = "挂号接口,帮患者在线挂号的接口")String registeInHos (@ToolParam(description = "医生名称", required = true) String docName,@ToolParam(description = "时间", required = true) String time ,@ToolParam(description = "病情描述", required = false) String desc,@ToolParam(description = "患者ID") String userId) {String rtn1 = "好的,已经为您挂了【"+docName+"】医生的号,就诊时间【"+time+"】,人数为【"+desc+"】";String rtn2 = "抱歉,暂时无法为您挂到医生【"+docName+"】的号,请稍后再试";return System.currentTimeMillis() % 4 == 0 ? rtn2 : rtn1;}}
  1. 办公OA服务
package com.lison.ai.spring_ai_alibaba_demo.toolcalling;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.context.annotation.Description;@Slf4j
@Description("OA相关服务,主要用于假期查询和请假")
public class OaService {private static int LEFT_DAYS = 5;@Tool(description = "员工剩余假期查询:查询员工还有几天的假期可以请")public String getCurrentDateTime() {return "目前,你还有 【"+LEFT_DAYS+"】 天的假期可以使用";}@Tool(description = "员工请假,需要传用户id(userId),和需要请假的天数 (days)")String askForLeave(@ToolParam(description = "员工工号") String userId ,@ToolParam(description = "需要请假的天数") String days) {if(!StringUtils.isNumeric(days)){throw new IllegalArgumentException("days参数必须是数字");}int dayInt = Integer.parseInt(days);String rtn1 = "好的,员工【"+userId+"】,已经请假【"+days+"】天,请好好享受假期";String rtn2 = "你的假期不足,无法请假";return dayInt>=LEFT_DAYS?rtn2:rtn1;}
}
  1. 饭店查询服务
package com.lison.ai.spring_ai_alibaba_demo.toolcalling;import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.context.annotation.Description;import java.util.Set;@Slf4j
@Description("饭店查询和预定服务")
public class RestaurantService {private static int LEFT_DAYS = 5;private static Set<String> RESTAURANT_NAME = Set.of( "红龙餐厅", "金莲小馆", "樱花寿司吧", "丝绸之路餐馆", "意大利小酒馆");@Tool(description = "查询不爱学习康复医院附近的饭店,餐厅,吃的,甜品,小吃")public String queryRestaurantName(@ToolParam(description = "当前位置", required = true) String location) {// 从 RESTAURANT_NAME 中随机选择String rtn = RESTAURANT_NAME.stream().skip((int) (Math.random() * RESTAURANT_NAME.size())).limit(3).reduce((a, b) -> a + "," + b).get();return "当前位置" + location + ",推荐 restaurantName:" + rtn;}@Tool(description = "预定餐厅,需要提供饭店名称,时间和人数")String bookRestaurant (@ToolParam(description = "饭店名称", required = true) String restName,@ToolParam(description = "订餐时间", required = true) String time ,@ToolParam(description = "就餐人数", required = true) String userNumber) {String rtn1 = "好的,已经为您预定了【"+restName+"】,就餐时间为【"+time+"】,人数为【"+userNumber+"】";String rtn2 = "抱歉,暂时无法为您预定【"+restName+"】,请稍后再试";return System.currentTimeMillis() % 4 == 0 ? rtn2 : rtn1;}
}

控制器(ToolCallController.java)

  @GetMapping(value = "/rag/chat", produces = "text/plain; charset=UTF-8")public String ragChat(@RequestParam String userId, @RequestParam String message) {log.info("userId -> [{}], message --> [{}]", userId, message);String text = chatClient.prompt().user(message).advisors(new MessageChatMemoryAdvisor(chatMemory,userId,100)).tools(new OaService(), new RestaurantService(),new HospitalService(),new WeatherService(webClient)).call().content();return text;}

测试验证

1、无工具调用

http://localhost:8080/ai/v1/rag/simpleChat?message=我计划明天从郑州到北京,帮我看一下这两个地方的天气,再帮我看一下我还剩几天假期,

响应结果:

在这里插入图片描述

说明

  • 无工具调用接口只能基于预设的逻辑进行简单回复,无法调用外部服务获取实时数据。
  • 这种方式适合处理简单的聊天逻辑,但对于复杂需求(如实时天气查询和假期管理)显得力不从心

2、工具调用接口

http://localhost:8080/ai/v1/rag/chat?message=我计划明天从郑州到北京,帮我看一下这两个地方的天气,再帮我看一下我还剩几天假期,

在这里插入图片描述

继续调用

http://localhost:8080/ai/v1/rag/chat?message=我需要修复牙齿缺损,帮我挂明天任意一位主任医师的号,然后帮我请2天假,并定一天的酒店

在这里插入图片描述

说明

  • 工具调用接口通过调用天气服务和 OA 服务,能够提供更全面和准确的响应。
  • 这种方式适合处理复杂的业务逻辑,但需要确保工具的稳定性和正确性
http://www.xdnf.cn/news/342523.html

相关文章:

  • # 如何使用 PyQt5 创建一个简单的警报器控制界面
  • Linux基础(最常用基本命令)
  • 用kompose将docker-compose文件转换为K8S资源清单
  • WHAT - ahooks vs swr 请求
  • Qt获取CPU使用率及内存占用大小
  • 基于STM32、HAL库的CP2104 USB转UART收发器 驱动程序设计
  • Node.js 技术原理分析系列9——Node.js addon一文通
  • 【嵌入式面试高频知识点】-wifi相关
  • 钯铂贵金属分离回收树脂
  • 【写作格式】写论文时常见格式问题
  • sherpa-ncnn:Endpointing(断句规则)
  • 05_项目集成飞书预警
  • 浙大与哈佛联合开源图像编辑模型IC-Edit,实现高效、精准、快速的指令编辑~
  • 淘宝九宫格验证码识别
  • 【UltralyticsYolo11图像分类完整项目-02】onnx模型转engine格式+TensorRT版Gpu预测C++实现
  • 动态规划之两个数组的dp问题(最长公共子序列)
  • Unity图集系统(Sprite Atlas)
  • Vue实现不同网站之间的Cookie共享功能
  • 信息系统项目管理工程师备考计算类真题讲解十四
  • 【软件设计师:软件工程】9.软件开发模型与方法
  • Java三大基本特征之多态
  • auto_ptr和unique_ptr
  • 统一授权与加密防护,CodeMeter 护航机器视觉创新全链路
  • kafka logs storage
  • 日语学习-日语知识点小记-构建基础-JLPT-N4阶段(16):单词与句子
  • Element-ui Table tree 结构使用(解决无展开箭头)
  • (14)Element Plus项目综合案例
  • 基础算法系列——树的入门
  • kafka records deletion policy
  • 如何设置内网映射端口到外网访问?哪些软件可以进行端口映射?