编程 ToolGrad 复现笔记:不用 ToolBench key 先跑 MCP demo,A100 上再补 BFCL 与 SFT

2026-09-13 00:06:09

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 在开源模型里领先,也能和部分专有模型比拼。

项目信息

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 proposalsExecuted 3 proposals: 3 successful, 0 failed,并打印每个 proposal 调用的 tool 与 input(read_text_file / read_multiple_files / list_directory)。输出写到 examples/outputs/ 下:trace_example/00123.jsonexample_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)。

复制全文 生成海报 Google-Research ToolGrad 工具调用 BFCL Gemma MCP

推荐文章

程序员茄子在线接单