Qwen-Agent 购物规划基准 ShoppingBench 实战:从环境搭建、Agent 推理到结果解读的完整指南
【免费下载链接】Qwen-AgentAgent framework and applications built upon Qwen>=3.0, featuring Function Calling, MCP, Code Interpreter, RAG, Chrome extension, etc.项目地址: https://gitcode.com/GitHub_Trending/qw/Qwen-Agent
DeepPlanning 基准是评估大模型 Agent 复杂规划能力的多领域测试框架,其中购物规划(Shopping Planning)子基准模拟真实电商购物场景:Agent 需要调用一系列工具完成"搜索商品 → 多条件筛选 → 加入购物车 → 应用优惠券"的完整任务链。本文以 Qwen-Agent 仓库中的购物规划基准为对象,系统讲解从环境准备、数据下载、模型配置到推理与评估的全流程,并结合仓库源码剖析 Agent 的工具调用机制、评分规则与统计口径,帮助你完整复现并理解该基准的每一个环节。
ShoppingBench 概览:它在 DeepPlanning 基准中的位置
购物规划基准位于 benchmark/deepplanning/shoppingplanning/,是 DeepPlanning 基准的独立领域之一。根据 benchmark/deepplanning/README.md 的说明,DeepPlanning 同时覆盖两个领域:
- Travel Planning(旅行规划):评估 Agent 的行程规划能力;
- Shopping Planning(购物规划):评估 Agent 的电商购物任务完成能力。
两个领域既可以由 run_all.sh 统一编排运行,也可以各自独立运行。本文聚焦购物规划域:它的独立入口文档为 shoppingplanning/README.md,对应入口脚本为 run.sh。
购物基准的核心场景是:给 Agent 一段用户购物需求(例如"买一双橙色、好评率高的 Nike 鞋,配送时间小于 2 天"),Agent 必须自主规划执行步骤,通过函数调用工具查询商品数据库、按品牌/颜色/尺码/评分/销量等条件筛选、最终把商品和优惠券放入购物车,评测系统再将 Agent 的购物车与人工标注的 ground truth 逐项比对打分。
环境准备:安装依赖
购物基准与整个 DeepPlanning 共享同一套运行环境,依赖统一安装在项目根目录。推荐使用 conda 创建 Python 3.10 环境:
# 若当前位于 shoppingplanning/,先回到项目根目录 cd .. # 创建新的 conda 环境(推荐 Python 3.10) conda create -n deepplanning python=3.10 -y # 激活环境 conda activate deepplanning # 从统一 requirements.txt 安装全部依赖 pip install -r requirements.txt # 回到 shoppingplanning 目录 cd shoppingplanning依赖清单定义在 benchmark/deepplanning/requirements.txt。从 agent/call_llm.py 的源码可以看出,Agent 通过 OpenAI Python SDK 调用兼容接口(openai.OpenAI(api_key=..., base_url=...)),因此openai库是核心运行时依赖。
数据准备:下载并解压三级购物数据库
ShoppingBench 将任务按难度划分为 3 个 level,每个 level 对应一份独立的购物数据库压缩包,数据来源于 DeepPlanning 数据集(公开数据集,可在对应数据页获取):
| 文件 | 说明 |
|---|---|
database_zip/database_level1.tar.gz | Level 1 购物数据库 |
database_zip/database_level2.tar.gz | Level 2 购物数据库 |
database_zip/database_level3.tar.gz | Level 3 购物数据库 |
下载后将三个压缩包放入shoppingplanning/database_zip/目录,然后解压到上一级(即shoppingplanning/根目录):
cd database_zip tar -xzf database_level1.tar.gz -C .. tar -xzf database_level2.tar.gz -C .. tar -xzf database_level3.tar.gz -C .. cd ..解压后会得到database_level1/、database_level2/、database_level3/三个目录,每个目录内按case_{id}/组织,每个 case 包含该样本的商品库文件products.jsonl。每个 level 对应的测试查询任务则来自 data/level_1_query_meta.json、data/level_2_query_meta.json 和 data/level_3_query_meta.json。
以 level 1 的样本为例,查询通常是一条包含多个子需求的复合指令,例如"寻找 Nike 橙色且好评的商品(一星评论少于 10 条、四星评论多于 300 条),同时需要 Puma 的某款男鞋且配送时间小于 2 天……",可见任务对 Agent 的多条件组合筛选与预算/时间约束理解提出了明确要求。
模型配置:编辑 models_config.json
所有领域的模型配置统一放在项目根目录(即 shoppingplanning/ 的上一级),文件名为models_config.json。编辑它来声明要测试的模型:
{ "models": { "qwen-plus": { "model_name": "qwen-plus", "model_type": "openai", "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", "api_key_env": "DASHSCOPE_API_KEY", "temperature": 0.0 }, "gpt-4o-2024-11-20": { "model_name": "gpt-4o-2024-11-20", "model_type": "openai", "base_url": "https://api.openai.com/v1/models", "api_key_env": "OPENAI_API_KEY", "temperature": 0.0 } } }支持的模型类型:
openai:OpenAI 及其兼容接口的模型(GPT-4 系列、Qwen、DeepSeek 等)。调用时使用 OpenAI 兼容协议,通过base_url指向服务端点、通过api_key_env指定的环境变量读取密钥。
仓库中已附带的 models_config.json 还展示了更多配置维度:例如qwen3-max(同样走 DashScope 兼容端点)、gpt-5-2025-08-07-high(通过extra_body.reasoning_effort: "high"传入推理模型的额外参数)。
从 agent/call_llm.py 源码可确认以下配置项的解析逻辑:
model_name:实际传给 API 的模型名,缺省时回退为配置键名;temperature:采样温度,0.0保证输出确定性,利于基准复现。源码中会自动跳过对推理模型(模型名含o1、o3、o4-mini、reasoner等关键词)传 temperature 参数;max_retries/backoff:API 调用失败重试次数(默认 30 次)与退避间隔(默认 1.5 秒),两者未配置时使用默认值;extra_body:透传给 OpenAI 客户端的额外请求体(如 reasoning_effort);- 配置查找顺序:
load_model_config会优先在当前领域目录(shoppingplanning/models_config.json)查找,其次回退到项目根目录;找不到配置文件或配置名时抛出明确的FileNotFoundError/ValueError。
API 密钥配置
API 密钥同样统一在项目根目录配置。两种方式任选其一:
# 方式一:在项目根目录创建 .env 文件 cd .. cp .env.example .env # 编辑 .env 填入你的 API Key # 方式二:直接设置环境变量 export DASHSCOPE_API_KEY="your_dashscope_api_key" export OPENAI_API_KEY="your_openai_api_key"benchmark/deepplanning/env.example 中已经给出了两个变量的模板(DASHSCOPE_API_KEY与OPENAI_API_KEY)。Agent 初始化时会自行加载.env:根据 agent/shopping_agent.py 中_load_env_from_dotenv的实现,它优先读取项目根目录的.env,其次回退到领域目录shoppingplanning/.env,且不会覆盖已经存在的同名环境变量。
运行基准测试
方式一:环境变量配置(推荐)
不修改任何文件,通过环境变量即可完成一次完整运行:
SHOPPING_AGENT_MODEL="qwen-plus" \ SHOPPING_LEVELS="1 2 3" \ SHOPPING_WORKERS=50 \ SHOPPING_MAX_LLM_CALLS=400 \ bash run.sh可用环境变量一览:
| 变量 | 含义 | 默认值 |
|---|---|---|
SHOPPING_AGENT_MODEL | 来自 models_config.json 的模型名(多个模型用空格分隔,将按顺序逐一运行) | qwen-plus |
SHOPPING_LEVELS | 要运行的级别(空格分隔,如"1 2 3") | 1 2 3 |
SHOPPING_WORKERS | 并行 worker 数量 | 50 |
SHOPPING_MAX_LLM_CALLS | 每个样本的最大 LLM 调用次数 | 400 |
方式二:修改 run.sh 默认值(永久生效)
如果希望长期固定配置,可直接编辑 run.sh 中的默认值(修改每行最后一个:-之后的值):
TEST_LEVELS="${BENCHMARK_LEVELS:-${SHOPPING_LEVELS:-1 2 3}}" # 修改级别 WORKERS="${BENCHMARK_WORKERS:-${SHOPPING_WORKERS:-50}}" # 修改 worker 数 MAX_LLM_CALLS="${BENCHMARK_MAX_LLM_CALLS:-${SHOPPING_MAX_LLM_CALLS:-400}}" # 修改最大 LLM 调用数 SHOPPING_AGENT_MODEL="${BENCHMARK_MODEL:-${SHOPPING_AGENT_MODEL:-qwen-plus}}" # 修改模型然后直接执行:
bash run.sh注意变量的生效优先级链为:BENCHMARK_*(统一编排层)→SHOPPING_*(领域层)→ 脚本内默认值。如果通过 run_all.sh 统一运行两个领域,只需设置BENCHMARK_MODEL即可同时驱动购物与旅行两个域。
run.sh 的执行流程(源码解读)
对照 run.sh 源码,一次运行内部会完成:
- 创建隔离数据库副本:为每次运行生成带唯一时间戳的目录(如
database_run_qwen-plus_level1_20250105143022_12345/),通过cp -r database_level{N}/*复制得到。隔离机制保证多个并发运行互不干扰,可安全地并行测试不同模型; - 按模型 × 级别顺序推理:外层循环遍历模型、内层遍历级别,对每个组合调用
python run.py --workers ... --level ... --max-llm-calls ... --database-dir ...; - 结果归档:推理完成后将运行目录改名为
database_{model}_level{N}_{YYYYMMDDHHMM}并移动到database_infered/下(mv而非复制,节省磁盘); - 逐级评估:对每个级别调用
python evaluation/evaluation_pipeline.py --database_dir {OUTPUT_FOLDER},报告始终生成并保存到result_report/,即使模型无效(invalid)也会保留报告以便调试; - 跨级统计:完成某模型所有级别后,调用
python evaluation/score_statistics.py --model_name {MODEL},将各级别汇总结果写入result_report/{model_name}_statistics.json; - 内置冷却间隔:级别之间 sleep 10 秒、模型之间 sleep 60 秒,规避 API 限流。
run.py 的命令行参数
run.py 是推理阶段的直接入口,支持以下参数:
| 参数 | 说明 | 默认值 |
|---|---|---|
--model | 模型配置名(缺省取SHOPPING_AGENT_MODEL环境变量,再回退qwen-plus) | qwen-plus |
--level | 任务级别,choices=[1, 2, 3],决定测试数据文件与系统提示词 | 1 |
--workers | 并发 worker 数量 | 5 |
--max-llm-calls | 每个样本最大 LLM 调用次数 | 400 |
--database-dir | 数据库目录路径,支持相对/绝对路径;传入唯一路径即可支持并发隔离运行 | database/ |
--verbose/--debug | 详细输出 / 调试模式(打印异常堆栈) | 关闭 |
run.py 启动时会依次校验:测试数据文件data/level_{N}_query_meta.json是否存在、数据库目录是否存在、工具 schema 文件 tools/shopping_tool_schema.json 是否存在;系统提示词按级别从 agent/prompts.py 的SYSTEM_PROMPT_level{N}动态读取。
理解 Pipeline:推理与评估两阶段
Stage 1:推理(Agent 规划)
做什么:
- 从
data/level_{N}_query_meta.json加载购物规划任务; - 调用 LLM Agent 生成购物方案;
- Agent 通过工具查询数据库(搜索商品、筛选、加入购物车、应用优惠券等);
- 将 Agent 轨迹与执行日志保存到数据库副本目录的
case_{id}/下。
输出目录结构:
database/ ├── case_0/ │ ├── messages.json # Agent 执行轨迹 │ ├── cart.json # 最终购物车 │ └── validation_cases.json # Ground truth ├── case_1/ │ └── ... └── ...其中messages.json记录了完整的 LLM 与工具往返消息(每一步 LLM 响应、每次 tool_call 的参数与工具返回结果都会即时落盘),cart.json是 Agent 最终确定的购物车(含商品与优惠券),validation_cases.json是评测用的标准答案。
Agent 主循环原理:
购物 Agent 是一个框架无关的轻量函数调用 Agent,实现在 agent/shopping_agent.py 的ShoppingFnAgent类中,其运行机制为:
- 加载 tools/shopping_tool_schema.json(406 行的完整 OpenAI function schema),作为
tools参数传给 LLM; - 通过
@register_tool装饰器机制动态加载工具实例:工具类在定义时注册到base_shopping_tool.TOOL_REGISTRY,导入tools包即触发全部注册,随后逐一实例化; - 进入主循环:调用 LLM → 检测
tool_calls→ 执行对应工具并把结果作为tool角色消息回填 → 继续调用 LLM,直到 LLM 不再请求工具为止; - 规划阶段结束后,Agent 自动追加一段"检查购物车是否符合要求,必要时补充商品,完成后停止"的用户消息(
_add_to_cart方法),进入收尾校验阶段,再次循环调用工具直至任务收敛——这是 ShoppingBench 保证最终以购物车内容为准的设计要点; - 所有样本通过
ThreadPoolExecutor(max_workers=workers)并行执行,每个样本一个独立ShoppingFnAgent实例,并通过--database-dir与sample_id定位到隔离的case_{id}/数据库。
Stage 2:评估
做什么:
- 将 Agent 生成的购物车与 ground truth 比对;
- 计算准确率分数(商品匹配、优惠券匹配);
- 校验用例是否完整完成;
- 生成评估报告。
输出目录结构:
result_report/database_{MODEL}_level{LEVEL}_{TIMESTAMP}/ ├── summary_report.json # 总体指标与统计 ├── case_0_report.json # 单用例详细报告 ├── case_1_report.json └── ... # 每个用例一份报告查看与解读结果
跨级别统计(整体分数)
运行完某模型的所有级别后,脚本自动聚合生成跨级别统计,全面展示该模型在不同难度下的表现:
# 查看某模型的整体统计 cat result_report/{MODEL}_statistics.json示例输出:
{ "model_name": "qwen-plus", "statistics_time": "2026-01-05T12:30:45.123456", "levels": { "level_1": { "folder_name": "database_qwen-plus_level1_202601051200", "total_cases": 50, "successful_cases": 45, "failed_cases": 5, "total_matched_products": 200, "total_expected_products": 210, "total_extra_products": 10, "average_case_score": 0.90, "overall_match_rate": 0.952, "incomplete_cases": 0, "incomplete_rate": 0.0, "valid": true }, "level_2": { "folder_name": "database_qwen-plus_level2_202601051300", "total_cases": 50, "successful_cases": 30, "failed_cases": 20, "total_matched_products": 150, "total_expected_products": 180, "total_extra_products": 25, "average_case_score": 0.60, "overall_match_rate": 0.833, "incomplete_cases": 2, "incomplete_rate": 0.04, "valid": true }, "level_3": { "folder_name": "database_qwen-plus_level3_202601051400", "total_cases": 50, "successful_cases": 20, "failed_cases": 30, "total_matched_products": 100, "total_expected_products": 200, "total_extra_products": 40, "average_case_score": 0.40, "overall_match_rate": 0.500, "incomplete_cases": 5, "incomplete_rate": 0.10, "valid": true } }, "total": { "total_cases": 150, "successful_cases": 95, "failed_cases": 55, "total_matched_products": 450, "total_expected_products": 590, "total_extra_products": 75, "successful_rate": 0.6333, "match_rate": 0.7627, "weighted_average_case_score": 0.6333, "incomplete_cases": 7, "incomplete_rate": 0.0467, "valid": true, "levels_completed": [1, 2, 3] } }核心指标释义:
successful_rate:取得满分(商品与优惠券全部匹配)的用例占比;match_rate⭐:正确匹配商品占全部期望商品的比例,论文报告的主要指标之一;weighted_average_case_score⭐:按各级别用例数加权的平均用例分,论文报告的主要指标之一;levels_completed:纳入统计的级别列表;valid:模型是否有效——要求所有级别的不完成率(incomplete_rate)≤ 10%。
重要说明:无论
valid是否为 true,评估报告都会照常生成。即使模型因提前终止或出错导致高不完成率,报告也会保留用于调试分析;valid字段只是标注其结果是否可作为可信基准参考。
级别统计
cat result_report/database_{MODEL}_level{LEVEL}_{TIMESTAMP}/summary_report.json示例输出:
{ "evaluation_time": "2026-01-04T12:09:18.522300", "overall_statistics": { "total_cases": 50, "successful_cases": 11, "failed_cases": 39, "average_score": 0.22, "average_case_score": 0.22, "max_score": 1.0, "min_score": 0.0, "total_matched_products": 152, "total_expected_products": 215, "total_extra_products": 54, "overall_match_rate": 0.707, "incomplete_cases": 0, "incomplete_rate": 0.0, "valid": true }, "case_results": [ { "case_name": "case_1", "success": false, "score": 0.8, "matched_count": 4, "expected_count": 5, "extra_products_count": 1, "case_score": 0.0, "is_completed": true } ], "detailed_results": [...] }单用例详情
# 查看某个用例的详细报告 cat result_report/database_{MODEL}_level{LEVEL}_{TIMESTAMP}/case_0_report.json示例输出:
{ "case_name": "case_1", "evaluation_time": "2026-01-04T12:09:18.174467", "summary": { "score": 0.8, "matched_count": 4, "expected_count": 5, "extra_products_count": 1, "coupon_score": 0.0 }, "query": "User shopping query...", "matched_products": ["706395e1", "3b5b2e0e", ...], "matched_coupons": [], "ground_truth_coupons": [], "unmatched_ground_truth_products": [...], "extra_products": [...], "ground_truth_products": [...] }该报告既包含query(原始用户需求)便于回查,也列出matched_products、extra_products(多买的商品)、unmatched_ground_truth_products(漏买的商品)以及优惠券的匹配明细(matched_coupons中每张券都会记录coupon_name、quantity、expected_quantity与match布尔值),可精准定位 Agent 的每一个决策偏差。
评分与统计的源码级原理
单用例评分(evaluation_pipeline.py)
benchmark/deepplanning/shoppingplanning/evaluation/evaluation_pipeline.py 中的evaluate_single_case实现了核心评分逻辑:
- 商品匹配:对购物车与 ground truth 的商品
product_id取集合交集,得到matched_product_ids; - 优惠券匹配:购物车
used_coupons中的券名与数量需同时与ground_truth_coupons一致才算命中; - 分数公式:
score = matched_count / expected_count(商品与优惠券合并计算);case_score则是 0/1 的严格分数——只有全部匹配才为 1.0,用于统计成功用例; - 完成度判定:
check_case_completion检查messages.json的最后一条消息——若末尾是tool角色消息或 assistant 消息仍带有tool_calls,则判定用例未完成(incomplete); - 有效性阈值:
incomplete_rate ≤ 0.1时模型视为有效,与文档中"valid"字段口径完全一致。
跨级别统计(score_statistics.py)
benchmark/deepplanning/shoppingplanning/evaluation/score_statistics.py 负责聚合跨级数据,其实现细节值得注意:
- 目录解析:通过正则
^database_(.+?)_level([123])_(\d+)$从result_report/下的目录名解析出模型名、级别与时间戳; - 去重策略:同一模型同一级别存在多次运行记录时,按时间戳降序选取最新一次的结果,避免历史脏数据干扰;
- 加权口径:
weighted_average_case_score以各级别用例数为权重计算加权平均,因此级别样本量不同时不会简单平均; - 完整性校验:若某模型缺少某个级别的数据会打印警告,但只要至少有一个级别的数据仍会继续计算(
levels_completed如实记录已完成的级别)。
与统一基准的衔接
当购物域通过 run_all.sh 与旅行域统一运行时,benchmark/deepplanning/aggregate_results.py 会进一步将两域结果聚合到aggregated_results/{model_name}_aggregated.json。其中跨域综合指标avg_acc定义为购物域weighted_average_case_score与旅行域case_acc的平均值,作为跨领域的主报告指标(详见 deepplanning/README.md 的结果说明部分)。
实用注意事项
- 基准每次运行都会自动管理数据库初始化与隔离副本,无需手工清理;
- 推理结果会在每次模型推理后备份到
database_infered/; - 评估报告统一保存到
result_report/; - 脚本支持多模型顺序运行,模型之间内置 60 秒延时、级别之间 10 秒延时,可在 run.sh 中调整;
- 由于每个运行使用独立的数据库目录,可以安全地同时启动多个基准进程(例如并行测试不同模型);
- 若自定义工具或需要查看工具定义细节,可阅读 tools/shopping_tool_schema.json 与 tools/base_shopping_tool.py;工具的搜索、筛选、购物车、优惠券等实现分布在 tools/ 目录的各个
*_tool.py文件中。
小结
ShoppingBench 购物规划基准为评估 Agent 的多步规划与工具调用能力提供了一套可独立运行、可精确复现的评测流程:从models_config.json声明模型、.env配置密钥,到run.sh完成隔离推理与自动评估,再到*_statistics.json与summary_report.json提供论文级别的match_rate、weighted_average_case_score等核心指标。理解其评分口径(集合匹配、0/1 用例分、10% 不完成率阈值)与统计逻辑(最新时间戳去重、按用例数加权),不仅能帮助你正确复现结果,也能为设计自己的 Agent 评测体系提供可借鉴的工程范式。
【免费下载链接】Qwen-AgentAgent framework and applications built upon Qwen>=3.0, featuring Function Calling, MCP, Code Interpreter, RAG, Chrome extension, etc.项目地址: https://gitcode.com/GitHub_Trending/qw/Qwen-Agent
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考