ARTICLE · 1080405
Spring AI 2.0 电商助手实战:使用 Tool‑Calling 实现订单查询业务
用 Tool‑Calling 实现订单查询业务
各位朋友大家好,我是一言,继续更新 Spring AI 2.0 系列。
上一篇讲的是回答怎样推送到页面上,而今天要讲的就是助手怎么调用 Java 查订单。输入“查一下 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 表示没有发货:

四、换一个订单号之后再查看调用
同一对话继续查询 A1002,参数更新为 A1002,返回人体工学椅、SHIPPED、899 元:

规划提示词为:根据最新的需求来确定参数,出现代词的时候才去联系历史,不能沿用旧订单。
改查 A9999,工具收到该订单号后返回“内容不存在或者没有权限访问”:

工具的状态是 FAILED,任务仍然是 COMPLETED:助手给出了错误的回答,但是业务查询没有成功。
一次订单查询就串起了模型生成参数、Java 执行工具、模型根据结果回答。Spring AI 提供工具定义、模型调用和执行回调、Runner 控制工具顺序、业务服务校验访问权限;创建售后单等写操作需要服务端确认。
我是一言,关注我,继续拆解 Spring AI 项目的使用方法。
谢谢你读到这里。想第一时间看到我的更新,记得把「雷一言」设为星标。以后有新文章,也不容易错过。