新闻详情

新闻详情

首页 / 资讯中心 / 详情

用 agno 生成 Tool-Call 轨迹训练数据:真实 Schema 校验、多轮模拟与法官过滤实战

发布时间:2026/9/10 9:03:02来源:尧图网络
用 agno 生成 Tool-Call 轨迹训练数据:真实 Schema 校验、多轮模拟与法官过滤实战
用 agno 生成 Tool-Call 轨迹训练数据真实 Schema 校验、多轮模拟与法官过滤实战【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno本文基于 agno 仓库cookbook/data_labeling/_25_tool_call_trajectories/目录讲解如何让框架自产自销函数调用Function-CallingSFT 数据以真实 agno 工具 Schema 为约束生成单步 (query, tool call) 配对用模拟用户与真实执行工具的助手对话产出多轮轨迹再由温度 0 的法官过滤出可入训的 rollout。读完你将掌握一条从运行中的 Agent到可训练的 Tool-Call 轨迹数据的完整数据管线以及每一环节在 agno 源码中的实现依据。一、为什么让 Agent 自己生成训练数据函数调用Function Calling是 Agent 与外部工具交互的核心能力。要训练模型学会面对用户请求 → 选出正确工具 → 给出符合 Schema 的参数 → 依据真实执行结果继续需要高质量的 (query, tool call) 配对与多轮工具使用轨迹。人工构造这类数据成本高、覆盖差且容易与实际运行的工具 Schema 脱节。agno 在cookbook/data_labeling/_25_tool_call_trajectories/中给出了一条完全不同的路径让框架自己生成自己的训练数据。核心思路是从 agno 真正运行的 ToolkitCalculatorTools、DuckDuckGoTools中提取每个函数的真实 JSON Schema用生成器 Agent 依据这些 Schema 写出候选配对再用纯代码校验器逐一核对工具是否已知、参数能否解析、必需参数是否齐全、有无未知参数、原始类型是否匹配多轮数据则来自模拟用户与一个真实执行工具调用的助手之间的对话执行过的调用工具名、参数、结果直接从RunOutput中提取最后用一个temperature-0 的法官判定每条轨迹是否真正达成了用户的阶段性目标只有验证通过的 rollout 才进入训练集。这种keep-what-passes的形态与目录_21_rejection_sampling/一脉相承只是这里被采样的对象从单条响应变成了整条轨迹_21_rejection_sampling/README.md。二、目录总览与三阶段管线cookbook/data_labeling/_25_tool_call_trajectories/下包含四个文件文件角色产出basic.pySchema 校验的单步 (query, tool call) 配对生成data/generated/tool_call_sft.jsonlmulti_turn_simulation.py模拟用户与真实执行工具的助手对话生成多轮轨迹data/generated/multi_turn_trajectories.jsonljudge_filter.py温度 0 法官校验多轮轨迹只保留验证成功的 rolloutdata/generated/verified_trajectories.jsonlREADME.md/TEST_LOG.md使用说明与实测记录—整个管线是单步配对 → 多轮模拟 → 法官过滤的递进关系basic.py解决模型是否会按 Schema 发出格式正确的调用multi_turn_simulation.py解决模型能否在多步计算中连续、正确地使用工具judge_filter.py解决只有被验证成功过的轨迹才能进入训练。三、阶段一basic.py—— 基于真实 Schema 的单步配对3.1 从 Toolkit 提取真实 JSON Schemabasic.py的关键设计是训练数据的 Schema 不是手写的而是直接从 agno 真实运行的 Toolkit 中提取。toolkit_schemas()遍历工具包注册的每个函数调用fn.process_entrypoint()让函数从其签名与 docstring 生成参数 Schema然后组装成{name, description, parameters, source}结构def toolkit_schemas(toolkit: Any, source: str) - Dict[str, dict]: Extract each tools real JSON schema from an agno toolkit. schemas {} for name, fn in toolkit.functions.items(): fn.process_entrypoint() # populates fn.parameters from the signature and docstring schemas[name] { name: name, description: fn.description, parameters: fn.parameters, source: source, } return schemas见 basic.py这里的process_entrypoint()是 agno 框架内部处理函数入口、生成模型可用参数 Schema 的统一入口位于 libs/agno/agno/tools/function.pyProcess the entrypoint and make it ready for use by an agent.。也就是说校验器面对的 Schema 与 Agent 运行时实际交给大模型的 Schema 是同一份不存在训练数据与推理时工具定义不一致的问题。本 demo 汇入了两套真实工具包CalculatorTools()来自 libs/agno/agno/tools/calculator.py注册了 8 个纯本地计算函数add、subtract、multiply、divide、exponentiate、factorial、is_prime、square_root见 calculator.py每个函数返回 JSON 字符串例如add返回{operation: addition, result: ...}DuckDuckGoTools()来自 libs/agno/agno/tools/duckduckgo.py是WebSearchTools的便捷包装backend默认 duckduckgo提供搜索/新闻搜索函数。3.2 用 Pydantic 输出模型约束生成器生成器 Agent 使用结构化输出模型ToolCallPairs内含N_PAIRS 8个候选配对每个配对由query自然语言用户请求、tool_nameSchema 列表中的精确工具名、arguments_jsonJSON 对象字符串形式的调用参数组成class ToolCallPair(BaseModel): query: str Field(..., descriptionA realistic user request answerable by a single call to one of the listed tools) tool_name: str Field(..., descriptionThe tool to call, exactly as named in the schema list) arguments_json: str Field(..., descriptionThe call arguments as a JSON object string, for example {a: 2, b: 3}) class ToolCallPairs(BaseModel): pairs: list[ToolCallPair] Field(..., descriptionCandidate (query, tool call) pairs, each using a listed tool)见 basic.py生成器 Agent 的指令明确要求每个 query 必须能被恰好一次调用回答参数必须严格满足 Schema必需参数齐全、无多余参数、原始类型正确要变化工具与措辞并在 query 中放入具体数值generator Agent( modelgoogle:gemini-3.5-flash, instructions( You write function-calling SFT data. Given a list of tool JSON schemas, produce natural user queries that are each answerable by exactly one call to one of the tools, together with that call. Arguments must satisfy the tools schema exactly: required params present, no extra params, correct primitive types. Vary the tools and the phrasing; put concrete values in every query. ), output_schemaToolCallPairs, )见 basic.py提示构造build_prompt()会把全部工具的真实 Schema 以 JSON 序列化后拼入并要求覆盖至少 5 个不同工具见 basic.py。3.3 纯 stdlib 校验器不依赖 LLM 的质量门槛这是basic.py最值得借鉴的部分候选数据由 LLM 生成但验收完全由确定性代码完成。json_type_matches()实现 JSON Schema 原始类型与 Python 值的对应关系注意integer与number都排除了bool因为 Python 中True/False是int子类def json_type_matches(expected: Optional[str], value: Any) - bool: if expected string: return isinstance(value, str) if expected integer: return isinstance(value, int) and not isinstance(value, bool) if expected number: return isinstance(value, (int, float)) and not isinstance(value, bool) if expected boolean: return isinstance(value, bool) if expected array: return isinstance(value, list) if expected object: return isinstance(value, dict) return True # schema declares no primitive type for this param: accept见 basic.pyvalidate_pair()按顺序执行五重检查工具已知 → 参数可被json.loads解析 → 参数是 JSON 对象 → 所有required参数存在 → 无未知参数且原始类型匹配任一失败即返回(None, reason)def validate_pair(pair: ToolCallPair) - Tuple[Optional[dict], str]: Check one candidate against the real schema. Returns (arguments, reason). schema SCHEMAS.get(pair.tool_name) if schema is None: return None, funknown tool {pair.tool_name} try: arguments json.loads(pair.arguments_json) except json.JSONDecodeError as exc: return None, farguments are not valid JSON: {exc.msg} if not isinstance(arguments, dict): return None, arguments are not a JSON object properties schema[parameters].get(properties, {}) for name in schema[parameters].get(required, []): if name not in arguments: return None, fmissing required param {name} for name, value in arguments.items(): if name not in properties: return None, funknown param {name} expected properties[name].get(type) if not json_type_matches(expected, value): return None, fparam {name} should be {expected}, got {type(value).__name__} return arguments, ok见 basic.py主流程对N_PAIRS个候选逐一校验仅将通过的配对写入data/generated/tool_call_sft.jsonl并为每行附上schema_source溯源字段如agno.tools.calculator被丢弃的候选打印丢弃原因见 basic.py。3.4 产出行示例{query: Calculate the sum of 124.5 and 89.2, tool_name: add, arguments: {a: 124.5, b: 89.2}, schema_source: agno.tools.calculator}每一行的参数都已经过真实 Schema 校验schema_source保证其来源可追溯。四、阶段二multi_turn_simulation.py—— 模拟用户驱动真实执行的多轮轨迹4.1 双 Persona 用户模拟器multi_turn_simulation.py用两个 Persona 模拟用户USER_SIMS每个都带一个多步计算目标每轮只请求一步、绝不自己心算达成全部目标后以单词DONE结束PERSONAS: Dict[str, str] { dinner_host: ( You are simulating a user planning a dinner for friends. Your goal, step by step: (1) find the cost of 4 pizzas at 18.50 each, (2) add the 12.75 delivery fee, (3) split the total evenly among 5 people. ), math_student: ( You are simulating a student double-checking homework. Your goal, step by step: (1) find out whether 97 is a prime number, (2) compute 12 factorial divided by 10 factorial. ), }见 multi_turn_simulation.py助手端是一个真正配置了tools[CalculatorTools()]的 agno Agent指令要求每一步算术都走工具而不是心算回答保持一两句并给出数值结果见 multi_turn_simulation.py。4.2 模拟循环与轨迹提取run_conversation()在MAX_TURNS 3的硬上限内循环模拟用户先产出下一条 user 消息若是DONE则剥离该标记并结束随后把完整对话记录交给助手助手真实地执行工具调用并回答最后遍历assistant_run.tools把实际执行过的调用工具名、参数、结果逐条追加到tool_callsfor tool in assistant_run.tools or []: tool_calls.append( { tool_name: tool.tool_name, arguments: tool.tool_args, result: tool.result, } ) turns 1见 multi_turn_simulation.py这里的关键点是tool_calls里记录的是RunOutput.tools中真实执行并返回结果的调用而不是模型打算调用的内容——这正是真实 tool-executing rollouts的含义。每条对话产出一行包含persona、完整messages、执行过的tool_calls与turns轮数写入data/generated/multi_turn_trajectories.jsonl{persona: dinner_host, messages: [{role: user, content: Hey! Im planning a dinner with some friends ...}, ...], tool_calls: [{tool_name: multiply, arguments: {b: 18.5, a: 4}, result: {\operation\: \multiplication\, \result\: 74.0}}, ...], turns: 3}五、阶段三judge_filter.py—— 温度 0 法官把关多轮轨迹虽然真实执行了但执行成功不等于达成了用户目标。judge_filter.py解决最后一个问题哪些 rollout 才值得进训练集。5.1 独立可跑的过滤脚本它从multi_turn_simulation.py导入PERSONAS、render_transcript、run_conversation并重新运行模拟因此不依赖任何预先存在的 JSONL可独立执行见 judge_filter.py。5.2 法官的判定结构法官用Gemini(idgemini-3.5-flash, temperature0)构造温度 0 保证判定可复现输出模型TrajectoryVerdict由success与reason组成class TrajectoryVerdict(BaseModel): success: bool Field( ..., descriptionTrue only if every step of the users goal was answered correctly using the executed tool calls, ) reason: str Field( ..., descriptionOne or two sentences citing the specific tool calls or answers behind the verdict, )见 judge_filter.py法官指令要求逐条核对助手是否用正确的参数与正确的算术完成了目标的每一步数字错误、跳步、最终答案没有对应执行过的工具调用均判失败见 judge_filter.py。评审提示build_judge_prompt()把 Persona 目标、对话全文、执行过的工具调用三者一并交给法官见 judge_filter.py。5.3 通过才保留理由进 provenance只有verdict.success为真的轨迹才会写入data/generated/verified_trajectories.jsonl且法官的理由被记入provenance{persona: math_student, messages: [...], tool_calls: [...], turns: 3, provenance: {judge: gemini-3.5-flash, reason: The assistant correctly checked if 97 is prime using the is_prime tool and computed 12 factorial divided by 10 factorial ... obtaining the correct result of 132.}}失败轨迹则打印原因并丢弃见 judge_filter.py。至此数据是否可入训由可验证的判定背书而不是由生成过程默认成立。六、设计边界离线、确定性与刻意收敛目录 README 明确说明了一个刻意为之的边界执行侧只使用离线 CalculatorTools。basic.py中的 DuckDuckGo 工具只以 Schema 形式出现、从不真正调用因此整个 demo 在工具侧是确定性的除模型 API 外不需要任何网络请求。这带来两个好处训练数据生成过程可复现、可审计工具执行结果恒定演示可以聚焦Schema 校验 轨迹提取 法官过滤这三个数据工程要点不被外部服务的不确定性干扰。TEST_LOG.md的实测记录也印证了这一点在一次运行中math_student用multiply(12, 11)一步化简 12!/10!法官正确接受了这一等价简化并引用which simplifies to 12 * 11 ... obtaining the correct result of 132说明校验器/法官评估的是目标是否达成 结果是否正确而非僵化的步骤顺序。七、运行方式与环境要求在仓库根目录下依次执行三个脚本即可python cookbook/data_labeling/_25_tool_call_trajectories/basic.py python cookbook/data_labeling/_25_tool_call_trajectories/multi_turn_simulation.py python cookbook/data_labeling/_25_tool_call_trajectories/judge_filter.py依赖需要GOOGLE_API_KEY三个脚本均使用google:gemini-3.5-flash模型环境前提已在环境中安装 agnodemo 实测版本为 agno 2.7.4见 TEST_LOG.md产出位置所有行写入cookbook/data_labeling/_25_tool_call_trajectories/data/generated/该目录已被 gitignore运行脚本即可重新生成规模参考basic.py一次生成 8 个配对multi_turn_simulation.py每次为 2 个 Persona 各跑至多 3 轮judge_filter.py重跑模拟后再逐条判定。据 TEST_LOG 实测一次完整运行得到2 行多轮轨迹 / 8 次执行工具调用dinner_host3 轮 3 次调用math_student3 轮 5 次调用工具调用次数会因模型行为在运行间略有浮动。八、何时使用这套管线README 的 When to use 给出了三个明确的适用场景单步配对当你要教模型针对固定 Schema 发出格式良好的调用对应basic.py多轮轨迹当你要教模型在上下文中进行多步工具使用、并带有真实执行结果对应multi_turn_simulation.py法官过滤当只有验证成功过的 rollout 才应进入训练对应judge_filter.py。前提是你已经在用带类型化工具typed tools的 agno Agent 运行任务。此外管线的上下游衔接也已打通上游形态参考keep-what-passes的思路与_21_rejection_sampling/一致区别在于这里被采样的单元是整条轨迹而非单条响应下游加工需要大规模去重、过滤与混配时使用_22_dataset_curation/LLM 质量门 MinHash 近重复检测 13-gram 去污染其中 dedup 与 decontamination 均为纯 stdlib、完全确定性的实现。九、实测结论与调优提示TEST_LOG.md记录了 2026-07-18 针对gemini-3.5-flash、agno 2.7.4 的实测basic.py通过率两次运行均wrote 8 rows ... kept 8, dropped 0模型对这类简单 Schema 能稳定产出精确参数数字写成 JSON number、factorial/is_prime写整数、max_results仅在查询需要时才出现。校验器该次运行未触发但 kept/dropped 会随运行变化——这正是纯代码校验器存在的意义把不确定的 LLM 输出收敛为确定的数据质量。multi_turn_simulation.pydinner_host依次执行multiply(4, 18.5) → 74.0、add(74, 12.75) → 86.75、divide(86.75, 5) → 17.35全部正确math_student执行is_prime(97)、factorial(12)、factorial(10)、divide → 132.0及一次验证性multiply(12, 11)。导出器在写 JSONL 前剥离DONE标记因此目标完成与否在数据中不可见而dinner_host在 3 轮上限处结束最后一问仍在回答正是硬轮数上限下的多步目标的预期形态。judge_filter.py实测 wrote 2 rows ... kept 2, dropped 0两条轨迹均通过验证失败路径当时仅由代码检视覆盖因为上下文中有正确的计算器算术时助手很少在这些小目标上失败。这几点对实际使用有直接提示不要把生成器的输出直接当训练数据而是永远让确定性校验器或法官决定取舍多轮数据要在轮数上限与目标完整性之间取舍工具调用次数存在运行间浮动数据量统计应基于多次运行的平均水平。结语_25_tool_call_trajectories演示了一条对训练数据工程很有参考价值的模式Schema 取自运行时、候选由 Agent 生成、质量由确定性代码与可验证判定把关、溯源字段全程留痕。无论是为 Function-Calling 微调构造单步配对还是为多步工具使用构造带真实执行结果的多轮轨迹这套生成 → 校验 → 过滤的三段式管线都可以直接迁移到你自己的 agno 工具集上。【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Simulink仿真生成输电线路故障数据的技术实践 2026/9/10 9:42:08

Simulink仿真生成输电线路故障数据的技术实践

1. 项目背景与核心价值在电力系统运行维护中,输电线路故障数据的获取与分析一直是行业痛点。传统方式依赖现场实测,不仅成本高昂,且难以覆盖所有故障类型。这个项目通过Simulink仿真批量生成六类典型故障数据(单相接地、两相接地、…

阅读更多 →
arXiv学术信息流操作系统:结构化切片+技术谱系树 2026/9/10 9:42:08

arXiv学术信息流操作系统:结构化切片+技术谱系树

1. 这不是“爬虫教程”,而是一份可落地的学术信息流操作系统你有没有过这种体验:每天早上打开arXiv,面对3000篇新提交论文,像站在瀑布前接水——手忙脚乱,接满一杯,下一秒又被冲走;收藏夹里躺着…

阅读更多 →
Arduino ESP32 开发环境搭建:四层拆解,首次烧录一次跑通 2026/9/10 9:42:08

Arduino ESP32 开发环境搭建:四层拆解,首次烧录一次跑通

Arduino ESP32 开发环境搭建:四层拆解,首次烧录一次跑通 【免费下载链接】arduino-esp32 Arduino core for the ESP32 family of SoCs 项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32 搭 Arduino ESP32 开发环境时最常见的卡点…

阅读更多 →
DeepSeek Harness 通用设置与 Agent 预设实战:从零配置你的智能助手 2026/9/10 9:42:08

DeepSeek Harness 通用设置与 Agent 预设实战:从零配置你的智能助手

上一篇把 DeepSeek Harness 装好之后,很多人问得最多的其实不是“怎么让它跑起来”,而是“装完以后到底应该先动哪些设置,才能让这个 Agent 真的听我指挥”。这一篇就把通用设置和 Agent 预设这两块掰开揉碎讲清楚。我自己刚开始用的时候&…

阅读更多 →
AutoHedge:基于Python与Solana的轻量级AI智能体协同框架 2026/9/10 9:42:08

AutoHedge:基于Python与Solana的轻量级AI智能体协同框架

1. 项目概述:AutoHedge 不是“自动对冲”,而是智能体协同决策的底层范式重构 AutoHedge 这个名字乍看像金融领域的自动对冲工具,但结合 swarm intelligence(群体智能)、AI agents(AI智能体)、So…

阅读更多 →
开源具身智能数据采集平台选型指南:从遥操作到模仿学习 2026/9/10 9:39:07

开源具身智能数据采集平台选型指南:从遥操作到模仿学习

这两年做具身智能方向,尤其在实验室里,我感受最深的一件事是:数据采集平台的选型,比很多人想象中更容易卡住项目进度。机器人本体买了、训练算法定了,结果发现“怎么稳定地录一批高质量演示数据”成了最费人的环节。有…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞