ToolGrad 复现笔记:不用 ToolBench key 先跑 MCP demo,A100 上再补 BFCL 与 SFT
想给工具调用模型造一批数据、或者微调一个能稳定发 function call 的小模型,卡点通常不在算法而在数据。query-first 的合成流程要先生成用户问题、再让模型去凑工具链,成本高,链路还容易偏短。ToolGrad 把顺序反过来了:先生成 ground-truth 工具调用链,再回填对应的用户 prompt。它用 ToolBench(16k+ 真实 API)生成数据,在 ToolGrad-500 上微调 Gemma-3(1B/4B/12B),在 Berkeley Function Calling Leaderboard (BFCL) V1 & V2 上评测,且评测工具集与训练时不同(OOD)。ToolGrad-12B 在开源模型里领先,也能和部分专有模型比拼。
项目信息
- GitHub:https://github.com/zhongyi-zhou/toolgrad(Apache 2.0,Python,61 stars)
- 论文 arXiv:http://arxiv.org/abs/2508.04086
作者:Zhongyi Zhou, Kohei Uehara, Haoyu Zhang, Jingtao Zhou, Lin Gu, Ruofei Du, Zheng Xu, Tatsuya Harada;primaryClass cs.CL。Google Research(Zhongyi Zhou、Ruofei Du 等,Google / 东大 / 北大),ACL 2026 Findings。 - PyPI:https://pypi.org/project/toolgrad
- 数据集 ToolGrad-500:https://huggingface.co/datasets/zhongyi-zhou/toolgrad-500
- 模型 ToolGrad-1B:https://huggingface.co/zhongyi-zhou/toolgrad-1b ;ToolGrad-4B:https://huggingface.co/zhongyi-zhou/toolgrad-4b ;ToolGrad-12B:https://huggingface.co/zhongyi-zhou/toolgrad-12b
- ToolBench(API 数据库来源):https://github.com/openbmb/toolbench
Part I:Quick Start(不需要 GPU,不需要 ToolBench API key)
这一段之所以门槛低,是因为它走的是 MCP filesystem 服务,只要一个 Gemini API key,不碰 ToolBench 也不占显存。
git clone https://github.com/zhongyi-zhou/toolgrad.git
cd toolgrad
uv venv
uv sync
source .venv/bin/activate
跑 ToolGrad on Model Context Protocol (MCP) filesystem 服务。MCP 服务需要 Node.js/npx:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
nvm install 20
nvm alias default 20
跑 demo(需要 Gemini API key):
export GEMINI_API_KEY=YOUR_GEMINI_KEY
export PYTHONPATH=./
python examples/mcp_filesystem.py
执行时会打印 API proposer / API executor 日志,例如 [Iteration 2] Proposed 3 API proposals、Executed 3 proposals: 3 successful, 0 failed,并打印每个 proposal 调用的 tool 与 input(read_text_file / read_multiple_files / list_directory)。输出写到 examples/outputs/ 下:trace_example/00123.json、example_seed=123__iter=3__num_apis=5.json。
框架四个核心模块是 propose、execute、select、update。工具配置使用 textual gradients 的概念,迭代地从大工具库构建复杂、合法的 API workflow。
Part II:Reproduction(需要 GPU)
作者在单张 NVIDIA A100-40GB 上验证。这一段和 Quick Start 的分界线就是显存。
1) 复现 BFCL 评测
git submodule update --init --recursive
本地推理在 GPU Docker 容器里跑,用官方 vllm/vllm-openai:v0.22.1-cu129 镜像,已验证单张 NVIDIA A100-SXM4-40GB。在仓库根目录执行(可选传 toolgrad_1b / toolgrad_4b / toolgrad_12b,默认 toolgrad_1b):
docker run --rm --entrypoint bash \
--device /dev/nvidia0 --device /dev/nvidia-uvm --device /dev/nvidiactl \
-v /usr/lib/x86_64-linux-gnu/libcuda.so.1:/usr/lib/x86_64-linux-gnu/libcuda.so.1 \
-v /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1:/usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1 \
-v $(pwd):$(pwd) \
-v ~/.cache/huggingface:/root/.cache/huggingface \
vllm/vllm-openai:v0.22.1-cu129 $(pwd)/src/scripts/run_bfcl_eval.sh toolgrad_1b
若模型权重本地 HF cache 没有,会自动从 HF Hub 下载;也可以用 --local-model-path 指定本地 checkpoint。结果:生成的 responses 在 submodule 目录 ext/gorilla-for-toolgrad/berkeley-function-call-leaderboard/result/ 下,分数与 CSV 在 score/(如 score/data_overall.csv)。
2) SFT Gemma 3(在 ToolGrad-500 上)
source .venv/bin/activate
python src/train/train_sft.py \
--model google/gemma-3-1b-it \
--learning_rate 1e-5 \
--num_epochs 3 \
--seq_length 8192 \
--gradient_checkpointing \
--gradient_accumulation_steps 2
单卡靠 gradient accumulation 还原 global batch size 2,即 --gradient_accumulation_steps 2。4B/12B 配方见 src/train/README.md。
Part III:生成自己的 ToolGrad-500(需要 ToolBench API key)
ToolBench API key 要申请,可能要等,所以这一步不适合作为第一站。
export TOOLBENCH_KEY=YOUR_TOOLBENCH_API_KEY
还要准备 ToolBench API 数据库:从 Google Drive 下 tools.zip 解压,设 TOOLBENCH_LIBRARY_ROOT 指向解压路径。
单次生成:
python src/generate_toolgrad_data.py \
--cfg examples/configs/gemini-2.5-lite.gin \
--iter 10 \
--num_apis 50 \
--output_dir /path/to/output_dir \
--seed 123
批量生成 500 条用 src/scripts/generate_toolgrad_500.sh(需自行调配置 / worker 数 / 输出目录)。
Pipeline:
raw workflow JSONs → [format] → positive SFT samples
→ [negatives] → negative SFT samples
→ [split] → train.jsonl / test.jsonl
格式化和负样本生成:
python src/data/data_format_main.py \
--workspace_dir $(pwd) \
--num_tools 10 \
--test_ratio 0.0 \
--negative_ratio 0.2 \
--output_format python
--num_tools 是每条 SFT 样本的工具候选数;--negative_ratio 是用于生成负样本的原始样本比例,示例里取 0.2。
可选:ToolBench 预处理转 TRL 格式(--tokenizer_name google/gemma-3-4b-it --chat_template src/data/toolbench/gemma_custom.jinja);过滤超 8k 上下文(--max_length 8000)。