GraphForge:让训练任务从真实文件里"长"出来,还自带评分标准

核心摘要

训练"干活型"智能体(读文件、调工具、交交付物的那种)一直卡在一个尴尬的地方:你需要大量基于真实文件、且结果可验证的任务,但现成的合成管线要么让模型自己编文件(假),要么拿真实文件建任务却没有评分标准(没法验收)。GraphForge 的思路很直接:从 ONET 职业数据库取种子控制多样性,抓真实文件搭工作空间,在文件关系上建一张证据图,任务描述和评分细则都从这张图编译出来——每条评分标准都锚定到"验收时需要看哪几个文件"。用 2,169 条轨迹 SFT 一个 Qwen3.6-27B,GDPVal 涨了 65.7 个 Elo 点,SpreadsheetBench II 涨了 13.7 个点*。我的判断:这不是模型层的突破,是数据工程管线的一次漂亮升级,做 Agent 训练数据的人都值得看一眼。

论文信息

  • 标题:GraphForge: Training Working Agents with Graph-Anchored Workspace Synthesis
  • 作者:Qisheng Su, Hanchen Wang, Guanru Zhu, Huicheng Jiang, Qiuyinzhe Zhang, Kou Shi, Zhen Fang, Ziao Zhang, Qingnan Ren, Honglin Guo, Zehui Chen, Tao Gui, Feng Zhao
  • 机构:中国科学技术大学、复旦大学、上海创智学院
  • 链接:https://arxiv.org/abs/2609.38923 (2026 年 9 月 30 日提交,v2 于 10 月 4 日修订)
  • 模型:https://huggingface.co/collections/groundhogLLM/graphforge

为什么这篇论文值得看

你有没有发现一个现象:会聊天的 Agent 一大堆,真让它"把这份年报和去年对比一下,做个估值工作簿发我",就开始各种翻车?

问题不在模型笨,而在训练数据难产。干活型 Agent 的训练数据有个苛刻的要求:任务得建立在一堆真实文件上(PDF、Excel、HTML 混着来),而且结果得能验证——你不能光让模型跑一遍就收工,得有人(或有东西)判它交出来的东西对不对。

现有的两条管线恰好各占一个坑。EnvCraft 用模型生成文件,再用 Python 脚本检查工作空间状态——但脚本读不了文件内容,交付物写得对不对根本查不出来。NexForge 倒是用了真实文件,但没有任务级的评分细则,质量没法系统检查。

说实话,这个痛点我自己碰过。之前做数据合成的时候,"任务看起来合理"和"任务可以被严格验收"之间隔着一条鸿沟,大多数情况下我们是靠人工抽查糊过去的。GraphForge 想填的就是这条沟。

核心思路:任务和评分标准,都从同一张图上编译出来

一句话版本:先抓真实文件,再让任务从文件里长出来,而不是先编任务再找文件凑合。

整个管线分五步,种子和文件各司其职:种子负责"定方向"(职业、任务类型、执行模式),文件负责"出内容"(具体任务和验收标准都从文件里推导)。

GraphForge 管线总览

图 1:GraphForge 五阶段管线。以一个 NVDA 投资分析任务为例:ONET 种子(金融分析师 × 定量建模)→ 抓取 5 个真实文件(年报、财报、公司概况,各有 core/supporting 隐藏角色)→ 建证据图并编译出任务和评分标准(每条标准锚定到具体文件节点)→ 教师模型先跑一遍,修订 agent 只改任务/细则 → 证据锚定的 judge 打分,合格的轨迹才入库。*

第一步:O*NET 职业种子,把多样性焊死

让模型自由发挥编任务,它会迅速坍缩到高频职业和通用分析任务——这是合成数据的老毛病了。GraphForge 直接从 O*NET 职业数据库取种子,只保留 AI4Work 标注为"数字化可执行"的任务,映射到官方的 Detailed Work Activities(DWA)分类体系。过滤后剩 246 个职业、16 个行业大类、891 种 DWA 任务类型、3,419 个有效的"职业-任务类型"对。

每个种子是个六元组:职业、DWA 任务类型、工作需求、主导执行模式(16 种,从定量建模到政策设计)、预期输入文件族、职业证据。

选种子时用边际覆盖增益的贪心策略:候选种子的增益是

\[\Delta(s \mid \mathcal{S}) = \sum_{d \in \mathcal{D}} \frac{1}{1 + n_d(v_d(s))}\]

通俗讲就是:你在某个维度(职业/任务类型/执行模式/文件族)上已经选过的取值越多,再选同值的种子收益越低。这样就逼着语料往没覆盖到的角落长,而不是堆在"商业分析师做数据分析"这种重灾区。

第二步:真实文件工作空间,文件还有"隐藏角色"

种子是中性的——它只说"金融分析师要做定量建模",不指定公司。搜索 agent 去找一个连贯的公开案例,把工作所需的文件全抓回来:原生格式下载、按格式解析、去重去无效。

有意思的是每个文件都被分配了隐藏角色:core(驱动主要计算)、supporting(提供政策或上下文)、confuser(看似相关实则不适用的干扰项)、ambient(真实冗余)。confuser 这个角色我很喜欢——真实工作环境里从来都不是"给你的恰好都是需要的",掺入合理但不适用的文件,逼着模型学会甄别。这些角色只用于组装和出题,干活 agent 看不到。

第三步:证据图,这是全文最值钱的设计

给定工作空间 \(W_i\),构建证据图 \(G_i = (V_i, E_i)\):节点记录"某个文件提供了什么事实/字段、在任务里扮演什么角色",边记录"解释、对比、核对、推导所需的跨文件依赖"。

然后图被编译成任务规范 \((q_i, \mathcal{D}_i, \mathcal{R}_i^+, \mathcal{R}_i^-)\):任务描述、交付物要求、正向评分标准、负向惩罚标准。每条正向标准长这样:

\[c_k = (d_k, r_k, z_k, w_k, A_k, \phi_k), \quad A_k \subseteq V_i\]

关键是最后两个字段:\(A_k\) 是证据锚点(验收这条标准需要看哪些文件节点),\(\phi_k\) 是验证程序(告诉 judge 怎么查)。

这个设计把执行和验证彻底分开了。干活 agent 只看到任务描述和文件,看不到图、看不到锚点;judge 拿到锚点和验证指令,知道该翻哪几个文件、查交付物的哪部分。评分标准不是空泛的"分析是否合理",而是"FY2025 营收应为 130,497M 美元,从 F2 读数,与 F1、F5 交叉核对"这种可以一条条对着文件验的东西。

等等,你可能会问:图本身错了怎么办?论文明确说图不是 ground truth,只是中间表示,图的声明必须能从原文件里还原——所以后面还有一步执行检验。

第四步:跑一遍再修,执行条件化的一步修订

静态检查抓不住长程任务里的所有歧义。GraphForge 让强教师模型先把任务跑一遍,然后修订 agent 拿着原文件、证据图、完整任务细则和这次执行记录,检查四件事:任务是否自然可执行、所需数值是否有依据、每条标准锚定是否正确、验证指令是否足以检查交付物。

有个省钱的细节:修订只改了评分细则没改任务描述?那初始轨迹直接复用,拿新细则重新判分就行,不用重跑教师。只有任务描述变了(用归一化哈希判断)才重跑。从漏斗数据看,81.6% 的轨迹是复用的,这个省 token 的设计挺务实。

第五步:交付物级准入 + 轨迹清洗

轨迹准入前先做确定性检查(文件名、格式可读、表格里有没有要求的 sheet 和公式),再由证据锚定 judge 逐条打分:

\[Q_i(\tau) = \frac{\sum_{k} w^+_{ik} \, a_{ik}(\tau) - \sum_{j} \lambda_{ij} \, v_{ij}(\tau)}{\sum_{k} w^+_{ik}}\]

正向标准按"要求满足比例 × 权重"给分,负向标准按"违规证据程度"扣分,原始分可以是负的。\(Q > 0.90\) 才准入,再过滤掉工具调用退化的轨迹(重复不轮询调用、工具滥用、高失败率、反复截断)。

数据长什么样

从 3,638 个物化任务到最后 2,169 条 SFT 轨迹,漏斗大致是:2,967 条轨迹复用(81.6%),2,153 个任务过 \(Q > 0.90\) 门槛,2,150 个独立工作空间。语料覆盖 466 种 O*NET 任务类型、15 个行业大类、全部 16 种执行模式。

语料多样性

图 2(a):行业大类 × 执行模式的联合覆盖热力图,256 个组合中实现了 164 个。数据分析和报告占 14.2%,研究和来源综合占 13.2%,其余模式都不超过 9%——不算均匀,但考虑到职业需求和准入过滤,这个形状可以理解。另外 PDF 出现在 96.7% 的轨迹里,真实工作确实被 PDF 统治。

轨迹长度也值得说:平均 50 步 assistant 交互(中位数 48,P95 是 82),平均 162K token(P95 达 224.8K),28 条(1.3%)顶到了 262,144 token 的训练上限。这是真正的长程任务数据,不是那种三步就完事的玩具轨迹。

实验:涨分扎实,跨脚手架迁移是亮点

训练用 GLM-5.2 驱动整个管线(建空间、建图、修订、教师 rollout、judge),在 Qwen3.6-27B 和 Qwen3.6-35B-A3B 上做 SFT。评测在三个基准:GDPVal-AA(220 任务金标子集,报 Elo)、Workspace-Bench-Lite、SpreadsheetBench II。

模型 GDPVal (OpenHands) GDPVal (Codex) WS-Bench-Lite (Claude Code) SpreadsheetBench II (Claude Code)
Claude Opus 5 1774.1 1753.1 70.1 33.6
GLM-5.3 1667.0 1543.7 67.7 32.1
Kimi-K3 1615.5 1664.4 65.8 35.8
Nex-N2-Mini-35B(NexForge 开源基线) 1288.8 1342.3 33.1 6.5
Qwen3.6-35B-A3B 1260.6 1283.0 55.9 2.8
35B + SFT(GraphForge) 1362.3(+101.7) 1384.4(+101.4) 59.7(+3.8) 19.3(+16.5)
Qwen3.6-27B 1380.0 1364.0 56.0 10.3
27B + SFT(GraphForge) 1445.7(+65.7) 1427.4(+63.4) 63.7(+7.7) 24.0(+13.7)

表 1:主实验结果(节选)。GDPVal 报 Elo(锚定 GLM-5.3 OpenHands = 1667),SpreadsheetBench II 报执行准确率。

几个值得说的点:

跨脚手架迁移是真的。 所有训练轨迹都是用 Codex 脚手架 roll 出来的,但评测覆盖了 OpenHands、Codex、Claude Code 三种,SFT 模型在每个脚手架下都涨。说明语料教的是可迁移的干活技能,不是绑死在某个脚手架上的操作习惯。这一点比绝对涨分更重要——要是换个脚手架就掉回基线,那数据价值就得大打折扣。

35B 涨得比 27B 猛(101.7 vs 65.7 Elo),但 27B 的绝对分反而更高。 27B 基座本身强(1380 vs 1260.6),天花板效应在起作用。另外坦率讲,27B/35B 都是 Qwen3.6 家族的,跨模型族的泛化这篇没验证,论文自己也承认了。

和前沿模型的差距仍然明显。 SFT 后 27B 是 1445.7,Claude Opus 5 是 1774.1——差着 300 多个 Elo 点,按 400 分对应 10:1 赔率的换算,基本是两个档次。所以别指望 2K 条数据抹平代差,这不是这篇论文的主张。

RFT:评分细则还能当筛选信号用

SFT 之后还有一手:让 SFT 模型自己在 2,000 个新查询上每个采样 4 条轨迹,用证据锚定 judge 挑出分最高的(超过 0.95 才留),得到 462 条做拒绝采样微调。三个对照臂共享同一批候选池和训练预算,只有筛选规则不同:锚定 judge、无锚 judge(看细则文本但看不到证据锚点)、随机选。

RFT 变体 GDPVal (OpenHands) WS-Bench-Lite (Claude Code) SpreadsheetBench II (Claude Code)
35B SFT 1362.3 59.7 19.3
+ RFT(锚定) 1369.5(+7.2) 63.7(+4.0) 20.3(+1.0)
+ RFT(无锚) 1396.4(+34.1) 62.2(+2.5) 17.5(-1.8)
+ RFT(随机选 4 选 1) 1353.3(-9.0) 60.8(+1.1) 19.0(-0.3)

表 2:RFT 消融。三个臂共享 462 个查询和候选池,唯一变量是筛选规则。

Workspace-Bench-Lite 和 SpreadsheetBench II 上的排序完全符合设计预期:锚定 > 无锚 > 随机。随机筛选在两个基准上几乎不涨甚至倒退——筛选质量本身就是信号,这是证据锚定值钱的直接证据。

但 GDPVal 上有点拧巴:无锚臂的点估计反而最高(+34.1),论文很坦诚地承认 220 个任务的 Elo 差异在统计上分辨不开,"噪音而非定论"。这个态度我欣赏,没有硬拗故事。

两个让人放心的审计实验

污染审计。 GDPVal 和种子都用 O*NET 分类体系,重叠风险最高。论文审了三层:文件层 39,201 个训练文件 vs 260 个 GDPVal 文件,零重合;文本层 top-20 相似 13-gram 对无实质共享内容;职业层 44 个 GDPVal 职业只覆盖 13 个。更妙的是分组迁移测试:SFT 在 155 个职业未覆盖任务上的胜率(0.739)不低于 65 个已覆盖任务上的胜率(0.692)。涨的是可迁移技能,不是背题。

judge 敏感性。 删掉某条标准引用的工作表,对应标准得分平均掉 0.377,非目标标准几乎不动(平均变化 0.016)——judge 确实在看引用的文件,响应是局部的。但细粒度破坏(改行、改数字、改引用)只引起 0.03 以下的变化,说明 GLM-5.2 当 judge 能抓结构性证据缺失,却验不了细粒度内容。这个短板论文也没藏着。

我的判断

这篇论文最值钱的地方不是涨了多少分,而是把"任务生成"和"任务验证"用同一张证据图绑在了一起。之前两条管线各缺一条腿:EnvCraft 能验证但文件是假的,NexForge 文件真但没验证。GraphForge 的锚点设计——每条评分标准显式声明"验收我需要看哪几个文件的哪部分"——让 judge 从"凭感觉打分"变成"照单查验",RFT 消融里锚定臂稳定压过无锚臂就是这个设计价值的直接体现。

问题也有。2,169 条轨迹的规模偏小,数据量的 scaling 完全没研究;整个管线绑死在 GLM-5.2 上,judge 的细粒度验证短板会跟着模型能力走;基座只试了 Qwen3.6 一个家族。另外 GDPVal-AA 只有 220 个任务,Elo 置信区间宽得能跑马,主表上的 +65.7 看着漂亮,但论文附录里的置信区间你得自己掂量。

如果你在做 Agent 训练数据合成,三个可以直接偷的点:confuser 文件角色(掺干扰项逼模型甄别)、修订时按任务描述哈希决定复用还是重跑(省 80% 教师 rollout 开销)、评分标准显式锚定证据文件(让 judge 可审计)。就冲这三点,这篇值得细读。


觉得有启发的话,欢迎点赞、在看、转发。跟进最新AI前沿,关注我