跨品类编排:对比、搭配与售后一起跑
作者:程序员马丁
Ragent AI —— 从 0 到 1 纯手工打造企业级 Agentic RAG,拒绝 Demo 玩具!AI 时代,助你拿个offer。
上一篇实现了 TinyAgent 的技能系统——activate_skill 加载 SKILL.md 指令到主上下文,技能专属工具动态注入,LLM 在指令引导下按步骤执行。结尾留了一个悬念:之前的例子一直在处理单品类的需求,退一台扫地机、查一个订单。如果用户的一句话横跨多个品类,涉及对比、搭配、售后多种任务类型,TinyAgent 现有的能力能接得住吗?
这一篇就来回答这个问题。用跨品类场景来验证 Tool、Skill 和 Plan-and-Execute 的组合编排能力——对比 + 搭配 + 售后一起跑。
本项目中具体代码已上传 GitHub TinyAgent,大家 Clone 项目后,将代码分支切换到 1.12.x,默认主分支是最新代码。运行前复制
.env.example为.env,把自己的 API Key 填进去,默认阿里云百炼平台;.env已加入.gitignore,切分支时不会丢。
单品类够了,跨品类才是真考验
1. 比特严选的跨品类特性
回顾一下比特严选的品类结构:手机、平板电脑、笔记本、智能穿戴(手表、手环、耳机)、智能家居(扫地机、智能音箱、摄像头等)、影音配件——6 大品类,300-500 个 SKU。
之前的 Demo 都在同一个品类内打转:退扫地机走退款技能,查订单走查询技能,推荐扫地机搜知识库。但比特严选的核心竞争力不在单品类——而在跨品类的 IoT 生态体验。用户的真实需求经常是这样的:
比特 AirX 耳机和 BandPro 耳机哪个好?我主要通勤用。另外我手机是比特 Phone S1,想配一套运动装备,预算 1000 以内。顺便帮我查一下订单 88231 到了没。
一句话包含了三个子任务:
- 商品对比:耳机品类内的规格对比(AirX vs BandPro)
- IoT 搭配推荐:基于已有手机,跨品类推荐智能穿戴设备组合
- 订单查询:查一个订单的物流状态
三个子任务涉及智能穿戴、手机、售后三个领域,调用的工具也不一样——对比要用 compareProducts,搭配推荐要用 recommendBundle,查订单要用 queryOrder。更关键的是,这三个子任务之间没有依赖关系,可以按任意顺序执行。
2. 现有能力够不够
TinyAgent 目前有三种执行能力:ReAct(单步推理)、Skill(指令驱动执行)、Plan-and-Execute(动态规划)。面对上面这个跨品类需求,每种能力各有擅长和短板:
| 能力 | 能不能做 | 怎么做 | 问题在哪 |
|---|---|---|---|
| ReAct | 能 | 一步一步推理,先对比、再推荐、再查订单 | 三个独立任务混在一条推理链里,容易遗漏后面的子任务 |
| ReAct + Skill | 能 | 激活对比技能完成对比,再激活搭配技能完成推荐,最后查订单 | 连续激活多个技能会导致指令堆叠,上下文膨胀 |
| Plan-and-Execute | 能 | Planner 一次性拆解三个子任务,Executor 逐步执行 | 最稳,总 LLM 调用反而更少(后文有详细对比) |
用一句话概括:单子任务用 ReAct + Skill 足够;跨品类复合任务用 Plan-and-Execute 更可靠。
这不是理论推导——下面用代码和实际执行轨迹来验证。但在跑 Demo 之前,先要给 TinyAgent 补两个跨品类才需要的工具。
新增两个跨品类工具
之前 TinyAgent 只有 5 个基础工具:queryOrder、queryLogistics、applyRefund、searchKnowledge、getCurrentTime。这些工具覆盖了订单和售后场景,但做不了商品规格对比和 IoT 搭配推荐。现在要补两个:
1. CompareProductsTool:商品规格对比
用户问比特 AirX 耳机和 BandPro 耳机哪个好时,Agent 需要拿到两个商品的详细规格参数才能做对比分析。searchKnowledge 返回的是粗粒度的产品简介,不够对比用——对比需要精确到续航时间、重量、降噪方式这些具体参数。
public class CompareProductsTool implements Tool {
private static final Map<String, String> PRODUCTS = new LinkedHashMap<>();
static {
PRODUCTS.put("比特 AirX 真无线耳机",
"{\"name\":\"比特 AirX 真无线耳机\",\"category\":\"智能穿戴\","
+ "\"price\":399,\"type\":\"真无线入耳式\","
+ "\"noiseCancelling\":\"主动降噪 ANC\","
+ "\"battery\":\"单次 8 小时,总续航 30 小时\","
+ "\"weight\":\"5.2g(单耳)\",\"waterproof\":\"IPX4\","
+ "\"features\":\"蓝牙 5.3,通话降噪,触控操作,支持快充\"}");
PRODUCTS.put("比特 BandPro 头戴式耳机",
"{\"name\":\"比特 BandPro 头戴式耳机\",\"category\":\"智能穿戴\","
+ "\"price\":699,\"type\":\"头戴式包耳\","
+ "\"noiseCancelling\":\"混合主动降噪 + 通透模式\","
+ "\"battery\":\"40 小时\","
+ "\"weight\":\"258g\",\"waterproof\":\"无\","
+ "\"features\":\"Hi-Res 认证,可折叠,3.5mm 有线模式,多设备连接\"}");
PRODUCTS.put("比特 Phone S1 手机",
"{\"name\":\"比特 Phone S1 手机\",\"category\":\"手机\","
+ "\"price\":1999,\"screenSize\":\"6.7 英寸 AMOLED\","
+ "\"processor\":\"骁龙 7 Gen3\","
+ "\"ram\":\"12GB\",\"storage\":\"256GB\","
+ "\"battery\":\"5000mAh\","
+ "\"features\":\"120Hz 刷新率,NFC,红外遥控\"}");
PRODUCTS.put("比特 WatchFit 智能手表",
"{\"name\":\"比特 WatchFit 智能手表\",\"category\":\"智能穿戴\","
+ "\"price\":599,\"screenSize\":\"1.82 英寸 AMOLED\","
+ "\"battery\":\"典型使用 14 天\",\"waterproof\":\"5ATM\","
+ "\"features\":\"心率血氧监测,100+ 运动模式,"
+ "NFC 公交支付,消息通知\"}");
// ...... 更多商品
}
@Override
public String name() { return "compareProducts"; }
@Override
public String description() {
return "对比两个比特严选商品的规格参数,"
+ "返回两者的详细规格信息供对比分析。";
}
@Override
public String parameters() {
return """
{
"type": "object",
"properties": {
"productA": {
"type": "string",
"description": "第一个商品名称,如 比特 AirX 真无线耳机"
},
"productB": {
"type": "string",
"description": "第二个商品名称,如 比特 BandPro 头戴式耳机"
}
},
"required": ["productA", "productB"]
}""";
}
@Override
public String invoke(String input) {
String nameA = ToolUtils.extractRequiredField(input, "productA");
if (nameA.isBlank()) {
return ToolUtils.missingRequiredField("productA");
}
String nameB = ToolUtils.extractRequiredField(input, "productB");
if (nameB.isBlank()) {
return ToolUtils.missingRequiredField("productB");
}
String specA = fuzzyMatch(nameA);
String specB = fuzzyMatch(nameB);
if (specA == null && specB == null) {
return "{\"error\":" + ToolUtils.toJsonString(
"未找到商品:" + nameA + " 和 " + nameB) + "}";
}
if (specA == null) {
return "{\"error\":" + ToolUtils.toJsonString(
"未找到商品:" + nameA) + ",\"productB\":" + specB + "}";
}
if (specB == null) {
return "{\"error\":" + ToolUtils.toJsonString(
"未找到商品:" + nameB) + ",\"productA\":" + specA + "}";
}
return "{\"productA\":" + specA + ",\"productB\":" + specB + "}";
}
// fuzzyMatch:模糊匹配商品名,兼容用户简写
// ......
}
PRODUCTS 是一个静态 Map,存放比特严选商品的规格 Mock 数据——实际项目中这部分应该对接商品数据库。关键设计点:
入参是两个商品名,返回两者的完整规格 JSON。Agent 拿到结构化的规格数据后,自己做对比分析和推荐——对比逻辑由 LLM 完成,工具只负责提供数据。这种职责分离和 RAG 系列里的检索增强生成是同一个思路:工具提供事实,LLM 做推理。
模糊匹配兼容简写。用户说 AirX 耳机而不是比特 AirX 真无线耳机,fuzzyMatch 方法用关键词拆分匹配来处理。
2. RecommendBundleTool:IoT 搭配推荐
用户说想给手机配一套运动装备时,Agent 需要知道有哪些搭配组合可选、每个组合包含什么、组合价多少。这个工具根据基础商品推荐跨品类搭配方案:
public class RecommendBundleTool implements Tool {
@Override
public String name() { return "recommendBundle"; }
@Override
public String description() {
return "根据用户已有或感兴趣的商品,推荐 IoT 生态搭配组合"
+ "(手机 + 手表 + 音箱等跨品类组合),"
+ "返回搭配方案和组合价。";
}
@Override
public String parameters() {
return """
{
"type": "object",
"properties": {
"baseProduct": {
"type": "string",
"description": "用户已有或感兴趣的基础商品名称"
},
"budget": {
"type": "number",
"description": "搭配总预算(元),可选"
},
"preferences": {
"type": "string",
"description": "用户偏好描述,如 运动健康监测、全屋智能控制"
}
},
"required": ["baseProduct"]
}""";
}
@Override
public String invoke(String input) {
String baseProduct =
ToolUtils.extractRequiredField(input, "baseProduct");
if (baseProduct.isBlank()) {
return ToolUtils.missingRequiredField("baseProduct");
}
// 根据基础商品匹配搭配方案
if (baseProduct.contains("Phone") || baseProduct.contains("手机")) {
return "{\"baseProduct\":\"比特 Phone S1 手机\","
+ "\"bundles\":["
+ "{\"name\":\"运动健康套装\","
+ "\"items\":[\"比特 Phone S1 手机(¥1999)\","
+ "\"比特 WatchFit 智能手表(¥599)\","
+ "\"比特 AirX 真无线耳机(¥399)\"],"
+ "\"totalPrice\":2997,\"bundlePrice\":2799,"
+ "\"saving\":198,"
+ "\"scenario\":\"手机接收手表的运动和健康数据,"
+ "耳机连接手机听歌跑步\"},"
+ "{\"name\":\"全屋智能套装\","
+ "\"items\":[\"比特 Phone S1 手机(¥1999)\","
+ "\"比特 SoundBox Mini 智能音箱(¥299)\","
+ "\"比特 WatchFit 智能手表(¥599)\"],"
+ "\"totalPrice\":2897,\"bundlePrice\":2699,"
+ "\"saving\":198,"
+ "\"scenario\":\"手机作为智能家居控制中心,"
+ "音箱做语音控制入口,手表随身提醒\"}"
+ "]}";
}
// ...... 其他商品的搭配方案
}
}
返回的 JSON 里每个搭配方案包含四个关键信息:包含商品(items)、原价(totalPrice)、组合价(bundlePrice)、适用场景(scenario)。这些结构化数据给了 LLM 足够的素材来做推荐——LLM 可以根据用户的预算和偏好从多个方案中筛选。
注意一个细节:
bundlePrice包含了基础商品(如手机)的价格,但用户可能已经拥有基础商品,不需要重复购买。LLM 需要结合对话上下文判断哪些商品用户已有,再做预算计算——这也是工具只提供数据、推理交给 LLM 的好处。
3. 工具全景
加上新增的两个工具,TinyAgent 现在有 7 个基础工具:
| 工具名 | 品类覆盖 | 职责 |
|---|---|---|
queryOrder | 订单/售后 | 查订单详情 |
queryLogistics | 订单/售后 | 查物流轨迹 |
applyRefund | 订单/售后 | 申请退款 |
searchKnowledge | 全品类 | 检索知识库(产品信息、政策) |
getCurrentTime | 通用 | 获取当前时间 |
compareProducts | 跨品类 | 对比两个商品的规格参数 |
recommendBundle | 跨品类 | 推荐 IoT 搭配组合 |
前 5 个是之前就有的,后 2 个是本篇新增的。searchKnowledge 是粗粒度的知识检索(返回产品简介和政策文档),compareProducts 是细粒度的规格对比(返回详细参数 JSON),两者不冲突——知识检索用于回答用户扫地机推荐这类开放问题,规格对比用于 A vs B 这类明确的对比需求。
新增两个跨品类技能
有了工具,还要给它们配上技能——这样 ReAct + Skill 模式下,LLM 可以按预定义的 流程执行对比和搭配推荐,而不是自己临时决定步骤。
1. product-comparison:商品对比技能
<!-- resources/skills/product-comparison.md -->
---
name: product-comparison
description: >
商品对比技能:查询两个商品的详细规格参数并进行对比分析,
给出结构化的对比结论和购买建议。适用于用户要求对比两个商品、
不知道选哪个的场景。
tools:
- compareProducts
---
# 商品对比
## 概述
你是比特严选的选购顾问。当用户要求对比两个商品时,按照以下流程处理。
## 处理步骤
### Step 1: 对比商品规格
使用 compareProducts 查询两个商品的详细规格参数。
### Step 2: 给出对比结论
根据返回的规格数据,从以下维度进行对比分析:
- 价格差异
- 核心功能差异(针对品类特点选择关键维度)
- 各自适合的使用场景
## 输出要求
给出清晰的对比表格或分点说明,最后根据用户提到的需求偏好
给出购买建议。如果用户没有明确偏好,列出两者各自的优势场景
让用户自行选择。
这个技能只声明了一个专属工具 compareProducts——对比场景只需要这一个。技能指令要求 LLM 从价格、核心功能、使用场景三个维度做对比分析,这比让 LLM 自由发挥更有结构感,输出质量也更稳定。
2. iot-bundle:IoT 搭配推荐技能
<!-- resources/skills/iot-bundle.md -->
---
name: iot-bundle
description: >
IoT 搭配推荐技能:根据用户已有或感兴趣的商品,推荐跨品类 IoT 生态
搭配组合,包含组合价和使用场景说明。适用于用户提到搭配、套装、组合、
生态等需求的场景。
tools:
- recommendBundle
---
# IoT 搭配推荐
## 概述
你是比特严选的 IoT 生态顾问。当用户想了解商品搭配方案时,
按照以下流程处理。
## 处理步骤
### Step 1: 获取搭配方案
使用 recommendBundle 查询基于用户已有或感兴趣商品的搭配组合方案。
如果用户提到了预算,传入 budget 参数。
如果用户提到了使用偏好(如运动健康、全屋智能),传入 preferences 参数。
### Step 2: 给出搭配建议
根据返回的搭配方案,说明每个组合包含哪些商品、组合价省多少、
适合什么场景。
## 输出要求
列出推荐的搭配方案,每个方案说清楚包含商品、原价、组合价、省多少钱、
适合什么场景。如果有多个方案,根据用户偏好排序推荐。
3. 技能全景
加上新增的两个,TinyAgent 现在有 4 个技能:
| 技能名 | 专属工具 | 适用场景 |
|---|---|---|
process-refund | queryOrder、applyRefund | 退款处理 |
order-inquiry | queryOrder、queryLogistics | 订单全流程查询 |
product-comparison | compareProducts | 商品对比 |
iot-bundle | recommendBundle | IoT 搭配推荐 |
4 个技能覆盖了比特严选客服的四大高频场景。注意 queryOrder 同时出现在 process-refund 和 order-inquiry 两个技能里——上一篇讲过,DynamicToolProvider 注入时会去重,不会在 LLM 可见列表里出现两次。
现在 LLM 初始可见的工具列表变成了 3 个:searchKnowledge、getCurrentTime、activate_skill——通用工具不变,activate_skill 的 description 里多了两个技能的说明。7 个基础工具中,除 searchKnowledge 和 getCurrentTime 外的 5 个都被至少一个技能声明为专属工具,激活前不可见。
下面这张图把工具和技能的可见性机制画清楚了——左边是 LLM 一开始就能看到的 3 个工具,右边是被 4 个技能封装起来的 5 个专属工具,中间的 activate_skill 是唯一的桥梁:

场景一:ReAct + Skill 跑单任务
先用最简单的方式验证新工具和新技能是否工作——ReAct + Skill 模式处理单个跨品类任务。
1. 耳机对比
// CrossCategoryDemo.java(简化)
ToolRegistry toolRegistry = new ToolRegistry();
toolRegistry.register(new QueryOrderTool());
toolRegistry.register(new QueryLogisticsTool());
toolRegistry.register(new ApplyRefundTool());
toolRegistry.register(new SearchKnowledgeTool());
toolRegistry.register(new GetCurrentTimeTool());
toolRegistry.register(new CompareProductsTool()); // 新增
toolRegistry.register(new RecommendBundleTool()); // 新增
SkillRegistry skillRegistry = new SkillRegistry();
skillRegistry.loadFromDirectory(Path.of("src/main/resources/skills"));
ToolRegistry agentTools = skillRegistry.buildAgentRegistry(toolRegistry);
ReActAgent reactAgent = new ReActAgent(llmClient, agentTools, 10, 8000);
// 耳机对比
String answer = reactAgent.run(
"比特 AirX 耳机和 BandPro 耳机哪个好?我主要通勤用");
预期执行轨迹:
[SkillRegistry] 加载技能:process-refund(process-refund.md)
[SkillRegistry] 加载技能:order-inquiry(order-inquiry.md)
[SkillRegistry] 加载技能:product-comparison(product-comparison.md)
[SkillRegistry] 加载技能:iot-bundle(iot-bundle.md)
[SkillRegistry] 技能专属工具(激活前不可见):
[queryOrder, applyRefund, queryLogistics, compareProducts, recommendBundle]
========== 场景 1:耳机对比(ReAct + Skill) ==========
===== 第 1 圈 =====
[工具调用] activate_skill({"name":"product-comparison"})
[Skill] 激活技能:product-comparison,解锁工具:[compareProducts]
[动态工具] 解锁 1 个技能专属工具:[compareProducts]
===== 第 2 圈 =====
[工具调用] compareProducts({"productA":"比特 AirX 真无线耳机",
"productB":"比特 BandPro 头戴式耳机"})
[工具结果] {"productA":{"name":"比特 AirX 真无线耳机","price":399,
"type":"真无线入耳式","battery":"单次 8 小时,总续航 30 小时",
"weight":"5.2g(单耳)","waterproof":"IPX4",...},
"productB":{"name":"比特 BandPro 头戴式耳机","price":699,
"type":"头戴式包耳","battery":"40 小时","weight":"258g",...}}
===== 第 3 圈 =====
[最终答复] 两款耳机各有优势,以下是对比分析:
| 维度 | AirX 真无线 | BandPro 头戴式 |
|------|-----------|-------------|
| 价格 | ¥399 | ¥699 |
| 佩戴方式 | 入耳式,轻便 | 包耳式,舒适但较重 |
| 续航 | 总续航 30 小时 | 40 小时 |
| 降噪 | 主动降噪 ANC | 混合降噪 + 通透模式 |
| 防水 | IPX4 | 无 |
通勤推荐:AirX 真无线耳机。理由是轻便便携、IPX4 防水防汗、
价格更友好,通勤场景下入耳式比头戴式方便很 多。
LLM 的行为完全符合预期:识别到对比需求 → 激活 product-comparison 技能 → 调 compareProducts 拿到规格数据 → 按技能指令的三个维度做对比分析 → 结合用户的通勤偏好给出推荐。整个过程 3 圈搞定。
2. IoT 搭配推荐
String answer = reactAgent.run(
"我刚买了比特 Phone S1,想配一些智能设备,主要想运动时用");
预期执行轨迹:
===== 第 1 圈 =====
[工具调用] activate_skill({"name":"iot-bundle"})
[Skill] 激活技能:iot-bundle,解锁工具:[recommendBundle]
[动态工具] 解锁 1 个技能专属工具:[recommendBundle]
===== 第 2 圈 =====
[工具调用] recommendBundle({"baseProduct":"比特 Phone S1 手机",
"preferences":"运动"})
[工具结果] {"baseProduct":"比特 Phone S1 手机","bundles":[
{"name":"运动健康套装",
"items":["比特 Phone S1 手机(¥1999)","比特 WatchFit 智能手表(¥599)",
"比特 AirX 真无线耳机(¥399)"],
"totalPrice":2997,"bundlePrice":2799,"saving":198,
"scenario":"手机接收手表的运动和健康数据,耳机连接手机听歌跑步"},
{"name":"全屋智能套装",...}]}
===== 第 3 圈 =====
[最终答复] 配合您的比特 Phone S1,推荐运动健康套装:
- 比特 WatchFit 智能手表(¥599):记录运动数据,心率血氧监测
- 比特 AirX 真无线耳机(¥399):运动时听歌,IPX4 防汗
- 套装组合价 ¥2799(省 ¥198)
三件设备互联:手表记录运动数据同步到手机,耳机连接手机听歌跑步。
LLM 准确地识别了搭配需求,激活了 iot-bundle 技能,还把用户的运动偏好传入了 preferences 参数,最终从两个方案中筛选了更匹配的运动健康套装。
两个单任务场景都跑通了。ReAct + Skill 在单品类和单跨品类任务上表现稳定——激活一个技能,按指令走完流程,3 圈搞定。
场景二:Plan-and-Execute 跑复合任务
现在来真正的考验——一句话包含三个跨品类子任务。
1. 为什么不用 ReAct + Skill
先想一下 ReAct + Skill 处理这个复合任务会怎么走。用户说:
帮我对比一下比特 AirX 耳机和 BandPro 耳机,另外我买的比特 Phone S1 手机想配一套运动装备,预算 1000 以内,顺便帮我查一下订单 88231 到了没。
LLM 初始可见 4 个工具:searchKnowledge、getCurrentTime、activate_skill。它需要:
- 激活
product-comparison,调compareProducts,完成对比 - 激活
iot-bundle,调recommendBundle,完成搭配推荐 - 激活
order-inquiry,调queryOrder,完成订单查询
这意味着 LLM 要在一次 run() 里连续激活三个技能。上一篇的进阶思考部分提过:连续激活多个技能会导致指令堆叠。三个技能的 Markdown 指令加起来约 1500-2000 Token,全部进入主上下文后,LLM 可能搞混不同技能的步骤——对比技能要求使用 compareProducts,搭配技能要求使用 recommendBundle,LLM 面对两份同时生效的指令,选择正确工具的难度显著上升。
更麻烦的是,上一篇提到 dynamicToolMap 是 run() 的局部变量,每次 run() 调用独立。所以在同一次 run() 内,三个技 能的专属工具会逐步叠加到可见列表——第一个技能解锁 compareProducts,第二个再解锁 recommendBundle,第三个再解锁 queryOrder 和 queryLogistics。这在技术上是可行的,但 LLM 看到一堆工具和一堆指令,决策质量容易下降。
ReAct + Skill 更适合一次一技能的场景。多技能协作,还是交给 Plan-and-Execute。
2. Plan-and-Execute 的优势
Plan-and-Execute 处理这个场景的方式完全不同——它不走技能路径,而是直接用基础工具:
// 场景 3:跨品类复合任务
PlanAndExecuteAgent planAgent =
new PlanAndExecuteAgent(llmClient, toolRegistry, 2);
String answer = planAgent.run(
"帮我对比一下比特 AirX 耳机和 BandPro 耳机,"
+ "另外我买的比特 Phone S1 手机想配一套运动装备,预算 1000 以内,"
+ "顺便帮我查一下订单 88231 到了没");
注意这里传入的是 toolRegistry(全量注册表,7 个基础工具全部可见),而不是 agentTools(经过技能过滤的注册表)。Plan-and-Execute 不需要技能——Planner 自己拆步骤,Executor 直接调基础工具。
这一点很重要。Skill 的价值是把高频、稳定的编排沉淀下来,避免每次都临时规划;但 Plan-and-Execute 的 Planner 本身就能根据工具列表生成合理的步骤编排。对于跨品类复合任务这种低频、非标的需求,Planner 临时规划反而比套用预定义技能更灵活。
下面这张时序图展示了 Plan-and-Execute 处理跨品类复合任务的完整流程——从用户输入到三个子任务分步执行,再到最终综合回复:

3. 完整执行轨迹
预期控制台输出(最终回复的措辞和排版因模型而异,以下为示意):
========== 场景 3:跨品类复合任务(Plan-and-Execute) ==========
[Plan] 正在规划...
[Plan] 计划生成完成:
○ Step 1: 对比比特 AirX 耳机和 BandPro 耳机的规格参数 → compareProducts
○ Step 2: 根据比特 Phone S1 查询运动装备搭配推荐 → recommendBundle
○ Step 3: 查询订单 88231 的状态 → queryOrder
○ Step 4: 综合对比结论、搭配推荐和订单状态,给出最终回复 → null
[Execute] ▶ Step 1: 对比比特 AirX 耳机和 BandPro 耳机的规格参数
[工具调用] compareProducts({"productA":"比特 AirX 真无线耳机",
"productB":"比特 BandPro 头戴式耳机"})
[工具结果] {"productA":{...},"productB":{...}}
[Execute] ✓ Step 1 完成
[Execute] ▶ Step 2: 根据比特 Phone S1 查询运动装备搭配推荐
[工具调用] recommendBundle({"baseProduct":"比特 Phone S1 手机",
"budget":1000,"preferences":"运动"})
[工具结果] {"baseProduct":"比特 Phone S1 手机","bundles":[...]}
[Execute] ✓ Step 2 完成
[Execute] ▶ Step 3: 查询订单 88231 的状态
[工具调用] queryOrder({"orderId":"88231"})
[工具结果] {"orderId":"88231","product":"比特 S10 Pro 扫地机",
"status":"已签收",...}
[Execute] ✓ Step 3 完成
[Execute] ▶ Step 4: 综合对比结论、搭配推荐和订单状态,给出最终回复
[Execute] ✓ Step 4 完成
[Plan] 执行完成:
✓ Step 1: 对比耳机规格 → AirX 399 元入耳式 vs BandPro 699 元头戴式...
✓ Step 2: 搭配推荐 → 运动健康套装(手表 ¥599 + 耳机 ¥399)...
✓ Step 3: 查订单 → 88231 已签收...
✓ Step 4: 综合回复 → 已处理...
========== 最终结果 ==========
为您汇总三个问题的处理结果:
【耳机对比】AirX vs BandPro
| 维度 | AirX 真无线(¥399) | BandPro 头戴式(¥699) |
|------|-------------------|---------------------|
| 佩戴 | 入耳式,5.2g 超轻 | 包耳式,258g |
| 续航 | 总续航 30 小时 | 40 小时 |
| 降噪 | 主动降噪 | 混合降噪 + 通透模式 |
| 防水 | IPX4 | 无 |
| 音质 | 蓝牙 5.3 | Hi-Res 认证 |
两款定位不同:AirX 轻便防水,适合运动通勤;BandPro 音质更强,
适合长时间音乐欣赏。
【运动装备搭配】
考虑到您 1000 元以内的预算,推荐单独搭配比特 WatchFit 智能手表
(¥599):心率血氧监测 + 100 种运动模式,与 Phone S1 数据互通。
如果预算放宽,还可以加一副 AirX 耳机(¥399),凑成运动健康套装
组合价 ¥2799(省 ¥198)。
【订单 88231】
您购买的比特 S10 Pro 扫地机已于 6 月 22 日签收。
如需其他帮 助,随时联系!
整个过程 4 步搞定,三个子任务一个不漏。来看几个关键细节:
Planner 自动识别了三个独立子任务。规划阶段一次性拆出 4 步,每步对应一个独立目标。因为三个子任务没有依赖关系(对比结果不影响搭配推荐,搭配推荐不影响订单查询),Planner 可以按任意顺序编排。
Executor 直接调基础工具,不走技能。Step 1 直接调 compareProducts,不需要先 activate_skill 再调工具。Plan-and-Execute 模式下,Planner 已经把步骤和工具对应关系写清楚了,不需要技能指令来引导。
Step 2 的 budget 参数被正确传入。Executor 看到步骤描述里有预算 1000 以内的信息,结合 recommendBundle 的参数 Schema 里有 budget 字段,自动组装了 {"baseProduct":"比特 Phone S1 手机","budget":1000,"preferences":"运动"}。这是 Executor 的 LLM 理解能力在起作用——步骤描述和工具参数 Schema 共同约束了参数组装。
综合步骤把三个结果组织得有条理。Step 4 不是简单拼凑三个工具的 JSON 返回值,而是用 LLM 重新组织成面向用户的自然语言回复。
Plan-and-Execute vs ReAct + Skill:跨品类场景的执行对比
用同一个复合任务,对比两种方式的执行过程: