
如果你正在尝试让大语言模型LLM学会使用外部工具比如调用 API、查询数据库、执行代码那么一个核心的难题会立刻摆在面前高质量的训练数据从哪里来传统的指令微调数据大多是“用户提问 - 模型回答”的格式。但要让模型学会在思考中主动调用工具数据需要包含“何时调用”、“调用哪个”、“如何解析结果”以及“如何整合结果继续回答”的完整决策链条。手动构造这种数据成本极高且难以覆盖复杂的真实场景。这就是MidTool项目要解决的核心痛点。它不是一个新模型而是一种创新的“训练中数据合成”方法论。简单来说它能在模型训练的中期动态地、有针对性地生成训练模型使用工具所需的高质量数据从而显著提升模型在“工具使用”这项任务上的能力。很多人可能会误以为这只是另一个数据增强工具。但它的关键洞察在于在模型已有一定知识的基础上针对其当前能力的薄弱环节合成最能促进其学习的“教学材料”。这比盲目扩充数据量要高效得多。本文将为你彻底拆解 MidTool 的核心思想、工作原理并通过一个完整的实践示例展示如何将这种思路应用到你的智能体Agent开发项目中。无论你是正在研究 Agent 框架还是希望提升现有模型的工具调用能力这篇文章都将提供一条清晰、可落地的技术路径。1. 为什么“训练中数据合成”是 Agent 工具使用的关键在深入 MidTool 之前我们必须先理解当前 LLM 工具使用能力训练的普遍困境。困境一数据稀缺与成本。完美的工具使用数据应该是一个多轮对话其中模型展示了完整的思考过程CoT识别用户需求中的工具使用点 - 选择正确的工具 - 构造正确的调用参数 - 解析工具返回的可能是复杂、有噪声的结果 - 将结果整合成自然语言回复。构造这样的数据需要领域专家和大量的时间是阻碍 Agent 能力提升的主要瓶颈。困境二静态数据的局限性。即使我们耗费巨资构建了一个静态的高质量工具使用数据集用它来训练模型也存在问题。模型在学习过程中其知识状态和能力短板是动态变化的。初期它可能不懂如何解析 JSON 结果后期可能卡在如何将多个工具调用串联起来。一份固定的数据集无法“因材施教”针对模型当前最需要学习的部分进行强化。困境三泛化能力不足。在静态数据集上训练出的模型往往只能较好地处理与训练数据相似的工具和查询。一旦遇到新的工具新的 API Schema或更复杂的组合查询性能就会急剧下降。这就像只做过题库练习的学生无法应对开放式应用题。MidTool 提出的Mid-training Data Synthesis正是针对以上困境的“动态解法”。它的核心思想可以类比为一个拥有顶级教学能力的AI教练观察学生模型在训练的中期评估模型当前在工具使用任务上的表现找出它的薄弱环节例如不擅长处理嵌套参数、容易误解错误码。设计针对性习题根据发现的薄弱环节自动合成一批新的训练数据。这些数据不是随机的而是精确瞄准了模型需要改进的那个“知识点”。融入教学进程将这批新合成的数据加入到下一轮的训练中让模型进行学习。循环迭代重复这个过程使得模型的工具使用能力在训练过程中被持续、定向地强化。这种方法将数据生成从“一次性的前期准备”变成了“贯穿训练的动态过程”实现了数据与模型能力的共同进化。2. MidTool 核心概念与工作原理拆解理解 MidTool需要掌握几个关键概念Agentic Tool Use (智能体工具使用)指大语言模型能够像智能体一样自主规划、选择并执行外部工具如计算器、搜索引擎、代码解释器、业务API来完成复杂任务的能力。这要求模型具备理解工具描述、规划序列、处理不确定性和整合信息的高级认知技能。Data Synthesis (数据合成)不同于从现有数据集中抽取或标注合成是指根据特定规则、模板或通过另一个模型如更强大的LLM自动生成新的训练样本。在 MidTool 的语境下合成是高度定向和策略性的。Mid-training (训练中期)这是区别于传统流程的关键。传统流程是准备数据 - 训练模型 - 评估。而 Mid-training 是指在模型已经经过一定轮次epoch的训练具备初步能力后再介入进行数据合成与补充训练。此时模型已非“白板”合成数据可以更有针对性。MidTool 的工作流程结合公开的研究思路一个典型的 MidTool 式工作流程可以拆解为以下步骤基础训练使用一个通用的工具使用指令数据集如ToolBench、Gorilla的部分数据对基座模型进行初步微调让模型获得工具使用的基本概念。能力评估与薄弱点诊断在验证集或一个动态任务池上测试当前模型。分析其错误案例进行归因。例如错误可能集中在工具选择错误该用“天气查询”却用了“股票查询”。参数构造错误API 调用参数格式不对、缺少必填字段。结果解析错误无法从工具返回的复杂 JSON 或 HTML 中提取关键信息。流程规划错误在多步任务中步骤顺序错误或遗漏必要步骤。针对性数据合成根据上一步的诊断结果启动数据合成引擎。例如如果模型在“参数构造”上薄弱合成引擎会重点生成大量需要构造复杂、嵌套参数的查询并附上正确的调用格式。合成引擎可以利用一个更强大的 LLM如 GPT-4作为“教师”根据工具描述和错误模式模拟用户提问并生成高质量的思考链和工具调用序列。数据融合与继续训练将新合成的数据与原有数据混合继续训练模型。新数据就像“强化补习资料”直接作用于模型的薄弱项。迭代循环重复步骤 2-4。随着模型能力提升合成的数据也会越来越难、越来越复杂推动模型能力不断向上突破。这个过程的核心优势在于“数据闭环”模型的表现驱动数据生成新数据又反过来提升模型形成一个自我增强的循环。3. 环境准备构建你的 MidTool 实验平台要实践 MidTool 思想你需要搭建一个能够支持动态数据合成和迭代训练的实验环境。以下是一个基于 Python 的推荐配置操作系统: Linux (Ubuntu 20.04) 或 macOSWindows 建议使用 WSL2。Python: 3.9 或 3.10。关键依赖库:深度学习框架: PyTorch (2.0) 或 TensorFlow。本文以 PyTorch 为例。大模型训练框架: Transformers (Hugging Face)这是管理和训练模型的核心。大模型调用/合成引擎: OpenAI SDK 或litellm。我们将使用一个更强的 LLM如 GPT-4作为数据合成的“教师模型”。工具使用环境: 准备一些简单的工具函数或 API 模拟器用于构建训练和测试任务。数据管理:datasets库Hugging Face用于高效加载和混合数据集。你可以通过以下requirements.txt文件来安装主要依赖# requirements.txt torch2.0.0 transformers4.35.0 datasets2.14.0 openai1.3.0 # 用于调用合成教师模型 litellm1.0.0 # 可选用于统一多模型API调用 accelerate0.24.0 # 用于简化分布式训练 peft0.7.0 # 可选用于参数高效微调 tqdm4.65.0 # 进度条 pydantic2.0.0 # 用于数据验证和工具Schema定义安装命令pip install -r requirements.txt重要提醒确保你的机器有足够的 GPU 内存至少 16GB来运行 7B 参数规模的模型进行微调。如果资源有限可以考虑使用QLoRA通过peft库进行 4-bit 量化微调这能大幅降低显存需求。4. 项目实战实现一个简化的 MidTool 训练循环我们将通过一个完整的例子模拟 MidTool 的核心流程训练一个模型使用“计算器”和“天气查询”两个工具并通过合成数据修复其“参数构造”的薄弱点。4.1 步骤一定义工具与基础数据首先明确定义我们的工具。这是模型学习的基础。# tool_definitions.py from pydantic import BaseModel, Field from typing import List, Optional import json # 定义工具的模式Schema这类似于给模型的“工具说明书” class CalculatorInput(BaseModel): 用于执行数学计算的工具。 expression: str Field(description一个有效的数学表达式例如3 5 * (2 - 1)) class WeatherInput(BaseModel): 用于查询城市天气的工具。 city: str Field(description城市名称例如北京New York) date: Optional[str] Field(defaultNone, description查询日期格式 YYYY-MM-DD默认为今天) # 模拟的工具函数实现 def execute_calculator(expression: str) - str: 执行计算器工具安全版本。 try: # 警告实际生产中应对表达式做严格的安全过滤这里仅为演示 allowed_chars set(0123456789-*/(). ) if not all(c in allowed_chars for c in expression): return 错误表达式包含非法字符。 result eval(expression) # 仅用于演示生产环境禁用eval return f计算结果{result} except Exception as e: return f计算错误{e} def execute_weather(city: str, date: str None) - str: 模拟天气查询工具。 # 模拟一个简单的数据库 weather_db { 北京: {today: 晴15-25°C, tomorrow: 多云16-26°C}, 上海: {today: 小雨18-22°C, tomorrow: 阴19-23°C}, New York: {today: 晴10-18°C, tomorrow: 雨9-16°C}, } date_key today if date is None else tomorrow if city in weather_db: return f{city}的天气{date_key}{weather_db[city][date_key]} else: return f未找到城市 {city} 的天气信息。 # 工具注册表 TOOL_REGISTRY { calculator: { description: 执行数学计算。, schema: CalculatorInput, function: execute_calculator, }, weather: { description: 查询城市天气。, schema: WeatherInput, function: execute_weather, } }接下来创建一个小型的基础训练数据集。数据格式采用OpenAI的function calling或ReAct格式。# create_base_dataset.py from datasets import Dataset import json # 基础训练数据示例格式用户指令 包含工具调用的模型思考过程 base_examples [ { instruction: 请计算一下 15 加上 27 等于多少, thought: 用户需要计算一个加法。我应该使用计算器工具。, action: calculator, action_input: {expression: 15 27}, observation: 计算结果42, # 模拟工具返回 response: 15 加上 27 等于 42。 }, { instruction: 北京今天天气怎么样, thought: 用户询问北京今天的天气。我应该使用天气查询工具。, action: weather, action_input: {city: 北京}, observation: 北京的天气today晴15-25°C, response: 北京今天天气晴朗气温在15到25摄氏度之间。 }, { instruction: 帮我算算 (12 - 3) * 4 的结果。, thought: 这是一个包含括号的数学表达式。我需要使用计算器工具。, action: calculator, action_input: {expression: (12 - 3) * 4}, observation: 计算结果36, response: (12 - 3) 乘以 4 等于 36。 } ] # 转换为 HuggingFace Dataset 格式 def convert_to_conversation(example): # 构建一个多轮对话格式模拟 ReAct 的 Thought-Action-Observation 循环 messages [ {role: user, content: example[instruction]}, {role: assistant, content: fThought: {example[thought]}\nAction: {example[action]}\nAction Input: {json.dumps(example[action_input], ensure_asciiFalse)}\nObservation: {example[observation]}\nResponse: {example[response]}} ] return {messages: messages} base_data [convert_to_conversation(e) for e in base_examples] base_dataset Dataset.from_list(base_data) base_dataset.save_to_disk(./data/base_tool_dataset) print(f基础数据集已保存共 {len(base_dataset)} 条样本。)4.2 步骤二初始模型训练与能力评估我们使用一个较小的开源模型如Qwen1.5-7B-Chat作为基座用基础数据集进行微调。这里使用transformers的SFTTrainer进行简化演示。# initial_training.py from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer from datasets import load_from_disk import torch # 1. 加载模型和分词器 model_name Qwen/Qwen1.5-7B-Chat # 也可使用其他 chat 模型 tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained(model_name, torch_dtypetorch.float16, device_mapauto) # 设置 padding token if tokenizer.pad_token is None: tokenizer.pad_token tokenizer.eos_token # 2. 加载基础数据集 dataset load_from_disk(./data/base_tool_dataset) # 3. 数据预处理将对话格式转换为模型输入 def format_chat_template(example): # 使用模型自带的 chat template 格式化数据 formatted_text tokenizer.apply_chat_template(example[messages], tokenizeFalse) return {text: formatted_text} tokenized_dataset dataset.map(format_chat_template, batchedFalse) # 4. 定义训练参数 training_args TrainingArguments( output_dir./models/initial_tool_model, num_train_epochs3, # 初始训练轮次 per_device_train_batch_size4, gradient_accumulation_steps2, warmup_steps50, logging_steps10, save_strategyepoch, learning_rate2e-5, fp16True, # 使用混合精度训练 ) # 5. 创建 Trainer 并开始训练 trainer Trainer( modelmodel, argstraining_args, train_datasettokenized_dataset, tokenizertokenizer, ) trainer.train() trainer.save_model() tokenizer.save_pretrained(./models/initial_tool_model) print(初始模型训练完成并保存。)训练后我们需要一个简单的评估函数来诊断模型弱点。# evaluate_model.py from transformers import pipeline import json # 加载训练好的模型和分词器 model_path ./models/initial_tool_model tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained(model_path, torch_dtypetorch.float16, device_mapauto) generator pipeline(text-generation, modelmodel, tokenizertokenizer, device0) # 定义测试查询 test_queries [ 计算 100 除以 (2 3) 的平方。, # 复杂表达式 我想知道上海和北京明天天气的对比。, # 多工具、多参数 如果今天北京气温是20度明天预报高5度那么明天气温是多少, # 需要推理计算 ] def diagnose_model(query): prompt f你是一个有帮助的助手可以使用工具。用户说{query}\n请一步步思考如果需要使用工具请严格按照格式输出。 response generator(prompt, max_new_tokens300, do_sampleFalse)[0][generated_text] print(f查询: {query}) print(f模型响应:\n{response}\n{-*50}) # 这里可以添加更复杂的解析逻辑自动判断响应是否正确并归类错误类型。 # 例如检查是否调用了正确工具参数格式是否正确等。 for q in test_queries: diagnose_model(q)运行评估后你可能会发现模型在处理“复杂表达式”如包含除法和平方或“多城市天气对比”时表现不佳。这标识了我们的薄弱点。4.3 步骤三实现 Mid-training 数据合成引擎这是 MidTool 的核心。我们根据诊断出的薄弱点例如“复杂参数构造”使用一个更强的 LLM如 GPT-4作为教师来合成新的训练数据。# data_synthesis_engine.py import openai import json from typing import List, Dict import random # 配置 OpenAI 客户端请替换为你的 API Key client openai.OpenAI(api_keyyour-api-key-here) def synthesize_tool_use_data(tool_schemas: Dict, weakness_type: str, num_samples: int 5) - List[Dict]: 根据指定的薄弱点类型合成新的工具使用数据。 Args: tool_schemas: 工具定义字典。 weakness_type: 薄弱点类型如 complex_expression, multi_tool, parameter_parsing。 num_samples: 需要合成的样本数量。 synthesized_data [] # 构建工具描述文本用于提示教师模型 tools_desc [] for name, info in tool_schemas.items(): schema info[schema] desc f- {name}: {info[description]} 输入参数: {schema.schema()[properties]} tools_desc.append(desc) tools_text \n.join(tools_desc) # 根据薄弱点类型设计不同的系统提示 if weakness_type complex_expression: system_prompt f你是一个高级数据生成器。你的任务是生成用于训练AI助手使用工具的高质量对话数据。 可用的工具如下 {tools_text} 请生成 {num_samples} 个用户查询这些查询需要助手使用 **计算器calculator** 工具来解决并且表达式应该**相对复杂**例如包含 - 多层括号 - 混合运算加、减、乘、除、乘方 - 涉及分数或小数 - 需要理解运算优先级 对于每个查询请生成一个完整的对话轮次包含 1. 用户指令 (instruction) 2. 助手的思考过程 (thought)说明为什么以及如何使用工具。 3. 正确的工具调用动作 (action) 和输入参数 (action_input必须是有效的JSON)。 4. 模拟的工具返回结果 (observation)。 5. 助手最终给用户的自然语言回复 (response)。 请以JSON列表格式输出每个元素是一个字典包含上述5个字段。 elif weakness_type multi_tool: system_prompt f...类似地设计针对多工具/多参数查询的提示... else: system_prompt f...通用提示... try: response client.chat.completions.create( modelgpt-4-turbo-preview, # 使用能力强的模型作为教师 messages[{role: system, content: system_prompt}, {role: user, content: 请开始生成数据。}], temperature0.7, response_format{type: json_object} # 要求返回JSON ) content response.choices[0].message.content data json.loads(content) # 假设返回格式为 {samples: [...]} synthesized_data data.get(samples, []) except Exception as e: print(f数据合成失败: {e}) # 可以回退到基于模板的合成 synthesized_data fallback_synthesis(tool_schemas, weakness_type, num_samples) return synthesized_data def fallback_synthesis(tool_schemas, weakness_type, num_samples): 备选方案基于规则模板合成数据 samples [] if weakness_type complex_expression: complex_exprs [ ((15 3) * 2 - 8) / 4, 2 ** 3 10 / (6 - 1), sqrt(16) log10(100), # 注意我们的简单计算器不支持这里需要调整或作为反面案例 max(23, 17, 42) - min(5, 10, 15) ] for expr in complex_exprs[:num_samples]: # 这里需要确保表达式在我们的安全计算器允许范围内 safe_expr expr.replace(sqrt, ).replace(log10, ).replace(max, ).replace(min, ) # 简化处理 if not safe_expr: safe_expr 10 20 sample { instruction: f请计算 {expr} 的值。, thought: f用户要求计算一个复杂表达式 {expr}。我需要使用计算器工具并确保输入格式正确。, action: calculator, action_input: {expression: safe_expr}, observation: execute_calculator(safe_expr), # 调用模拟工具 response: f表达式 {safe_expr} 的计算结果是 {execute_calculator(safe_expr).replace(计算结果, )}。 } samples.append(sample) return samples # 示例合成针对“复杂表达式”薄弱点的数据 from tool_definitions import TOOL_REGISTRY new_data synthesize_tool_use_data(TOOL_REGISTRY, weakness_typecomplex_expression, num_samples3) print(f合成了 {len(new_data)} 条新数据。) for d in new_data: print(json.dumps(d, indent2, ensure_asciiFalse))4.4 步骤四数据融合与迭代训练将合成的新数据与原始数据混合进行新一轮的训练。# mid_training_iteration.py from datasets import Dataset, concatenate_datasets, load_from_disk from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer import torch # 1. 加载上一轮训练好的模型 model_path ./models/initial_tool_model tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained(model_path, torch_dtypetorch.float16, device_mapauto) # 2. 加载原始数据集和新合成的数据集 base_dataset load_from_disk(./data/base_tool_dataset) # 假设 new_data 是上一步合成的数据列表 new_data_list [...] # 从 data_synthesis_engine 获得的数据 new_dataset Dataset.from_list([convert_to_conversation(e) for e in new_data_list]) # 使用相同的转换函数 # 3. 合并数据集 combined_dataset concatenate_datasets([base_dataset, new_dataset]) print(f合并后数据集大小: {len(combined_dataset)} (原始: {len(base_dataset)}, 新增: {len(new_dataset)})) # 4. 格式化并分词 tokenized_combined_dataset combined_dataset.map(lambda ex: {text: tokenizer.apply_chat_template(ex[messages], tokenizeFalse)}, batchedFalse) # 5. 进行 Mid-training (继续训练) mid_training_args TrainingArguments( output_dir./models/mid_tool_model_v1, num_train_epochs2, # Mid-training 轮次可以较少 per_device_train_batch_size4, gradient_accumulation_steps2, warmup_steps20, logging_steps10, save_strategyepoch, learning_rate1e-5, # 使用更小的学习率进行微调 fp16True, ) mid_trainer Trainer( modelmodel, argsmid_training_args, train_datasettokenized_combined_dataset, tokenizertokenizer, ) mid_trainer.train() mid_trainer.save_model() tokenizer.save_pretrained(./models/mid_tool_model_v1) print(Mid-training 迭代完成。)4.5 步骤五验证与迭代循环训练完成后再次使用评估脚本对模型进行测试。观察之前薄弱点复杂表达式计算的表现是否提升。如果仍有其他问题如多工具规划则针对新的薄弱点启动下一轮的数据合成与训练形成闭环。5. 运行结果与效果验证运行上述流程后你可以通过对比初始模型和 Mid-training 后模型在测试集上的表现来验证效果。一个简单的验证脚本如下# verify_improvement.py from transformers import pipeline import re def test_single_query(model_pipe, query, expected_toolNone, expected_action_input_keyNone): 测试模型对单个查询的响应。 prompt f你是一个有帮助的助手可以使用工具。用户说{query}\n请一步步思考如果需要使用工具请严格按照格式输出。 response model_pipe(prompt, max_new_tokens300, do_sampleFalse)[0][generated_text] # 简单解析响应提取 Action 和 Action Input action_match re.search(rAction:\s*(\w), response) action_input_match re.search(rAction Input:\s*(\{.*?\}), response, re.DOTALL) tool_used action_match.group(1) if action_match else None action_input_str action_input_match.group(1) if action_input_match else None print(f查询: {query}) print(f使用的工具: {tool_used}) print(f工具输入: {action_input_str}) print(f完整响应片段:\n{response[response.find(Thought:):response.find(Response:)100] if Thought: in response else response[-500:]}\n) # 进行一些基本断言 if expected_tool: assert tool_used expected_tool, f工具使用错误预期 {expected_tool}, 实际 {tool_used} if expected_action_input_key and action_input_str: import json try: action_input json.loads(action_input_str) assert expected_action_input_key in action_input, f输入参数中缺少关键字段 {expected_action_input_key} except json.JSONDecodeError: print(警告无法解析 Action Input 为 JSON。) return tool_used, action_input_str # 加载初始模型和 Mid-trained 模型 initial_pipe pipeline(text-generation, model./models/initial_tool_model, tokenizer./models/initial_tool_model, device0) mid_pipe pipeline(text-generation, model./models/mid_tool_model_v1, tokenizer./models/mid_tool_model_v1, device0) test_query 计算 ((100 - 20) / 4) 的平方再加上 15 等于多少 print( 初始模型测试 ) test_single_query(initial_pipe, test_query, expected_toolcalculator, expected_action_input_keyexpression) print(\n Mid-trained 模型测试 ) test_single_query(mid_pipe, test_query, expected_toolcalculator, expected_action_input_keyexpression)预期结果初始模型可能无法正确解析复杂的嵌套表达式生成的action_input可能格式错误如缺少括号或直接放弃使用工具而尝试心算。Mid-trained 模型由于经过了针对“复杂表达式”的强化合成数据训练它应该更倾向于正确调用计算器工具并且生成的expression参数格式更加准确。通过这种对比你可以直观地看到 Mid-training Data Synthesis 带来的性能提升。6. 常见问题与排查思路在实践 MidTool 方法时你可能会遇到以下问题问题现象可能原因排查方式解决方案合成数据质量差模型学偏1. 教师模型如GPT-4的提示词设计不佳。2. 合成数据未经过滤包含错误或矛盾。1. 人工检查一批合成数据样本。2. 分析模型在合成数据上的训练损失曲线是否异常。1. 优化系统提示词明确要求输出格式和质量。2. 增加数据后处理步骤如基于规则过滤或使用另一个模型进行质量评分。训练过程不稳定损失震荡1. 新合成数据与原始数据分布差异过大。2. 学习率设置过高。3. 批次内数据差异大。1. 检查合成数据和原始数据的统计特征如长度、工具分布。2. 监控训练日志看损失是在哪个阶段开始震荡。1. 逐步增加合成数据的混合比例而不是一次性全部加入。2. 在 Mid-training 阶段使用更小的学习率如1e-5到5e-6。3. 尝试梯度累积增大有效批次大小。模型过拟合合成数据的特定模式合成数据的多样性不足模式单一。检查模型在保留的原始测试集上性能是否下降。1. 在合成时引入更多随机性如多样化的用户表述。2. 确保合成数据覆盖不同类型的薄弱点而不是单一类型。3. 使用数据增强技术如对合成数据进行同义句改写。工具调用格式错误1. 训练数据格式不一致。2. 分词器对特殊符号如花括号{}处理不当。1. 检查训练数据中action_input的 JSON 格式是否严格正确。2. 查看模型生成的原始文本是否出现了 token 拼接错误。1. 在数据预处理阶段对 JSON 字符串进行标准化和验证。2. 在训练时可以对Action:和Action Input:等关键词增加损失权重通过自定义损失函数。教师模型 API 调用成本高合成大量数据时使用 GPT-4 等模型成本高昂。统计合成数据量和对应费用。1. 使用更经济的模型如gpt-3.5-turbo进行初筛再用强模型精修。2. 优先合成“困难样本”而非随机样本。3. 建立合成数据的缓存池避免重复合成相同模式的数据。7. 最佳实践与工程建议将 MidTool 思想有效整合到你的 Agent 开发流水线中需要考虑以下工程化实践建立系统化的薄弱点诊断体系不要依赖人工查看错误案例。构建一个自动化的评估流水线Evaluation Pipeline能够对模型在多种工具使用任务单工具、多工具、带条件、带状态等上进行批量测试并自动归类错误类型工具选择、参数构造、结果解析、逻辑规划。这为数据合成提供精准的“靶点”。设计分层的数据合成策略根据薄弱点的严重性和优先级设计不同“剂量”和“强度”的合成策略。基础纠错针对高频错误合成大量针对性数据。能力拓展针对模型从未见过的新工具或复杂组合合成引导性数据。对抗性强化主动设计一些容易让模型出错的“陷阱”查询如模糊的工具描述、冲突的参数合成数据来提升模型的鲁棒性。实现数据质量闭环合成数据并非总是高质量。需要建立验证机制格式验证确保合成的action_input是合法的 JSON 并符合工具 Schema。逻辑验证使用工具实际执行合成的调用检查observation是否与action_input匹配response是否合理总结了observation。多样性验证检查合成数据在语言表达、查询复杂度、工具组合上是否足够多样避免模式单一。与课程学习Curriculum Learning结合Mid-training Data Synthesis 可以很自然地与课程学习结合。在训练初期合成简单、单一工具的数据随着模型能力提升逐步合成需要多步推理、工具链组合的复杂数据。让模型的学习曲线更加平滑。注意灾难性遗忘在针对特定薄弱点进行强化训练时要避免模型遗忘之前已学会的其他技能。解决方案包括保留原始数据始终将一部分高质量的原始基础数据与合成数据混合训练。弹性权重巩固技术上可以采用更高级的训练技巧但最简单的做法是控制新数据的比例和学习率。安全与边界合成数据可能产生不合理或有害的查询。务必对合成数据的指令和工具调用进行安全检查避免生成涉及隐私、偏见或滥用工具的样本。特别是在使用外部教师模型时要在系统提示词中明确安全约束。MidTool 所代表的“训练中数据合成”范式其价值远不止于提升工具使用能力。它为我们提供了一种更通用、更高效的模型能力迭代思路让模型在训练过程中主动暴露弱点并动态生成“补习资料”进行强化。这比固定数据集训练和事后修补更加灵活和强大。你可以将这套方法论应用到更广泛的场景例如代码生成针对模型在特定 API 或算法实现上的错误合成相关的代码补全数据。复杂推理针对模型在逻辑链推理中容易断裂的环节合成 step-by-step 的推理数据。领域适应快速让一个通用模型适应医疗、法律等垂直领域通过合成该领域的专业问答数据。开始实践的最佳方式就是从你当前 Agent 项目中最令你头疼的那一类工具使用错误开始。定义好工具收集一批错误案例然后用本文提供的代码框架尝试合成第一批“特效药”数据。你会发现模型学习的效率和质量很可能因此获得显著的提升。