夜雨聆风学习资料网

ARTICLE · 1080405

Spring AI 2.0 电商助手实战:使用 Tool‑Calling 实现订单查询业务

Spring AI 2.0 电商助手实战:使用 Tool‑Calling 实现订单查询业务

用 Tool‑Calling 实现订单查询业务

各位朋友大家好,我是一言,继续更新 Spring AI 2.0 系列。

上一篇讲的是回答怎样推送到页面上,而今天要讲的就是助手怎么调用 Java 查订单。输入“查一下 A1001 订单”,查询桌面收纳架的模拟订单:

查询 A1001:执行订单查询并显示回答

Tool Calling 的分工为:模型生成调用请求、Java 执行业务方法、模型根据返回值组织回答。

一、先确定本次要查的内容

AfterSalesAgentRunner(简称 Runner)把整个链条连接起来:

用户:查一下 A1001 订单  ↓ 模型识别需求ORDER:查订单  ↓ Runner 限定工具queryOrder  ↓ 模型生成参数{"orderId":"A1001"}  ↓ Java 查询并校验归属订单结果 → 模型组织回答

模型根据历史返回业务类型 Intent.operation,Runner 校验分类之后决定工具的顺序:

List<String> required = switch (intent.operation()) {  case "ORDER" -> List.of("queryOrder");  case "LOGISTICS" -> List.of("queryOrder", "queryLogistics");  case "RETURN", "CANCEL" ->      List.of("loadSkill", "queryOrder", "searchPolicy");  case "POLICY" -> List.of("searchPolicy");  case "PICKUP" -> List.of("bookPickup");  default -> List.of();};

查询订单调用 queryOrder,查询物流先查订单再查配送,顺序由项目的 Runner 来决定。

二、给模型工具定义,让它填入参数

@Tool 描述 Java 方法的作用,ToolCallbacks.from(tools) 会得到包含名称、描述以及参数结构的回调。Runner 只取当前工具,重要的配置为:

var options = ((OpenAiChatOptions) rawModel.getDefaultOptions())    .mutate()    .toolChoice(Map.of(        "type", "function",        "function", Map.of("name", requiredTool)))    .parallelToolCalls(false)    .toolCallbacks(callback)    .toolContext(context)    .build();var response = rawModel.call(new Prompt(planning, options));var calls = response.getResult().getOutput().getToolCalls();

规划、要求、历史等都属于 planning,而 toolChoice 就是指选择工具。模型可以从问题里得到订单号:

{"orderId":"A1001"}

Runner 校验工具名、调用次数,对于相同的参数进行去重之后再执行:

callback.call(call.arguments(), new ToolContext(context));

这里使用 ChatModel 来获取请求,Runner 手动调用回调;Spring AI 2.0 的 ChatClient 也支持自动工具调用循环。

三、Java 查询订单,模型根据结果作答

queryOrder 负责查询订单,trace 记录参数、结果和状态:

@Tool(description = "查询当前认证用户的订单。orderId例如A1001。用户身份由服务端提供。")public Object queryOrder(String orderId, ToolContext context) {  return trace("queryOrder", "local", Map.of("orderId", orderId),      "查询订单", () -> {        var row = orders.findOwned(orderId, actor);        var result = new LinkedHashMap<String, Object>();        for (String key : List.of(            "id", "product", "state", "amount", "tracking_number"))          if (row.get(key) != null) result.put(key, row.get(key));        result.put("demo", true);        return result;      });}

用户的身份由服务端提供。findOwned() 还可以过滤掉订单号、租户和用户,从而限制订单的访问范围:

select * from orderswhere id = ? and tenant_id = ? and user_id = ?

A1001 返回:

{  "id": "A1001",  "product": "桌面收纳架",  "state": "PAID",  "amount": 129,  "demo":true}

结果被写入到 tool_executions 中,Runner 读取本轮的结果以及历史,并把它们交给模型来生成回答。演示商城里 PAID 表示没有发货:

订单查询完成:处理面板显示 queryOrder,聊天区展示订单状态和金额

四、换一个订单号之后再查看调用

同一对话继续查询 A1002,参数更新为 A1002,返回人体工学椅、SHIPPED、899 元:

改查 A1002:提问、queryOrder 参数和人体工学椅查询结果

规划提示词为:根据最新的需求来确定参数,出现代词的时候才去联系历史,不能沿用旧订单。

改查 A9999,工具收到该订单号后返回“内容不存在或者没有权限访问”:

查询 A9999:工具返回访问错误,助手提示核对订单号

工具的状态是 FAILED,任务仍然是 COMPLETED:助手给出了错误的回答,但是业务查询没有成功。

一次订单查询就串起了模型生成参数、Java 执行工具、模型根据结果回答。Spring AI 提供工具定义、模型调用和执行回调、Runner 控制工具顺序、业务服务校验访问权限;创建售后单等写操作需要服务端确认。

我是一言,关注我,继续拆解 Spring AI 项目的使用方法。

谢谢你读到这里。想第一时间看到我的更新,记得把「雷一言」设为星标。以后有新文章,也不容易错过。

相关学习资料