尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

agno 拒绝采样(Rejection Sampling)数据标注工作流:验证器门控、Best-of-N 评判与逐步过程奖励的实战实现

发布时间:2026/9/11 6:33:01

资讯中心
01
ARTICLE

agno 拒绝采样(Rejection Sampling)数据标注工作流:验证器门控、Best-of-N 评判与逐步过程奖励的实战实现

agno 拒绝采样(Rejection Sampling)数据标注工作流:验证器门控、Best-of-N 评判与逐步过程奖励的实战实现
agno 拒绝采样Rejection Sampling数据标注工作流验证器门控、Best-of-N 评判与逐步过程奖励的实战实现【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno拒绝采样Rejection Sampling是构建冷启动推理训练数据的核心数据形态对每个 prompt 采样 K 个候选输出用程序化验证器或 LLM 评判器逐个把关只保留幸存样本。本文以 agno 仓库cookbook/data_labeling/_21_rejection_sampling/下的四个可运行脚本为骨架系统讲解在 agno Agent 框架下如何生成已验证推理轨迹、对无程序化答案的开放任务做 Best-of-N 门控、用通过率筛选 RL 训练提示以及用蒙特卡洛回滚把结果监督蒸馏为逐步过程奖励并结合测试日志给出的真实运行数据与校准结论帮助读者理解这些门控在实战中的行为边界。目录拒绝采样在数据标注流水线中的定位运行环境与依赖basic.py纯代码验证的推理轨迹verified reasoning tracesjudge_gate.py无程序化验证器时的 Best-of-N 门控rl_prompt_selection.py用通过率挑选值得训练的 RL 提示step_rewards.py蒙特卡洛逐步过程奖励测试日志中的校准结论何时使用与生态衔接拒绝采样在数据标注流水线中的定位在 agno 的cookbook/data_labeling/目录下_20至_25是一组合成数据生成型工作流它们不像前面的标注/分类/抽取示例那样给已有输入打标签而是直接产出训练数据JSONL带逐行 provenance过滤时会打印 kept/dropped 计数。_21_rejection_sampling/正是其中采样 → 校验 → 保留这一数据类型的代表。它的核心思想一句话概括过滤本身就是产品。通过门控的样本成为训练数据已验证推理轨迹、Best-of-N 精选而逐 prompt 的通过率本身又告诉你哪些 prompt 值得投入训练算力。这与_17_llm_as_judge/有本质区别在那里评判器产出一份评分报告由人来阅读在这里验证器或评判器的判定逐行决定哪些行进入数据集——它直接门控生成循环。四种门控形态的差异摘自 README.md脚本门控输出行内携带的 provenancebasic.py纯代码验证最终答案与金标整数相等无分数provenance 就是被验证过的最终答案本身judge_gate.py评判器绝对分数线argmax 且 score 4所有 N 个分数 评判理由rl_prompt_selection.py通过率区间0 passK 1该 prompt 的 pass_ratestep_rewards.py不丢行把结果验证内化进轨迹逐步分数 step_scores k运行环境与依赖四个脚本都基于 agno 的Agent与 Pydanticoutput_schema模型统一为google:gemini-3.5-flash一个推理模型因此需要设置环境变量GOOGLE_API_KEY。按 data_labeling/README.md 的说明可以从仓库根目录创建并激活 demo 虚拟环境./scripts/demo_setup.sh source .venvs/demo/bin/activate然后逐个运行路径均为仓库根目录相对路径python cookbook/data_labeling/_21_rejection_sampling/basic.py python cookbook/data_labeling/_21_rejection_sampling/judge_gate.py python cookbook/data_labeling/_21_rejection_sampling/rl_prompt_selection.py python cookbook/data_labeling/_21_rejection_sampling/step_rewards.py其中rl_prompt_selection.py最慢——测试日志记录约需 15 分钟耗时主要被困难题目的推理 token 占据。所有脚本把结果写入各自的data/generated/目录输出文件分别为verified_traces.jsonl、judge_gated.jsonl、rl_prompts.jsonl、prm_rows.jsonl。运行日志遵循 cookbook 约定记录在 TEST_LOG.md。basic.py纯代码验证的推理轨迹verified reasoning tracesbasic.py实现最基础的拒绝采样配方sample采样→ check校验→ keep保留。一个 teacher agent 对每个数学/代码问题采样 K4 条推理轨迹纯代码验证器整数与金标相等只保留最终答案验证通过的轨迹全程没有任何 judge 参与 keep 路径。关键实现Teacher agent 的关键配置见 basic.pyteacher Agent( modelgoogle:gemini-3.5-flash, instructions( Solve the problem step by step. Show your full reasoning, then give the final integer answer. ), output_schemaSolution, )两个设计要点使用默认温度这样 K 次采样才有差异若温度过低K 条轨迹会趋同拒绝采样退化为单次采样。不配置会话记忆注释明确说明no session memory is configured, so repeated .run() calls are independent samples of the same prompt——这正是 K 次独立采样的前提。从 agno 源码看Agent.run() 返回的 RunOutput 携带content字段配合output_schema后run.content即为反序列化后的 Pydantic 对象这里是Solution。验证器是纯代码即最终答案与金标的精确相等if solution.final_answer problem[gold]: correct 1 rows.append({...}) # prompt / reasoning / final_answer / sample_index else: dropped 1输出 schema 保证了final_answer是整数、reasoning是字符串class Solution(BaseModel): reasoning: str Field(..., descriptionstep by step reasoning) final_answer: int Field(..., descriptionthe final integer answer alone)需要警惕的假阳性模式脚本 docstring 直言不讳地指出了 answer-only 拒绝采样的已知假阳性推理文本本身不被检查一条推导有缺陷但最终落在正确整数上的轨迹会被保留。这正是为什么每个金标在提交前都经过手工与脚本双重校验——一个错误的金标会静默污染所有保留的轨迹。示例数据行basic.py产出的每一行都经过验证最终答案与金标相等后才被保留{prompt: How many ways can you choose 3 books from 7 distinct books?, reasoning: To find the number of ways to choose 3 books from 7 distinct books, we use the combination formula C(n, k) n! / (k!(n-k)!). Applying this with n 7 and k 3 yields C(7, 3) (7 * 6 * 5) / (3 * 2 * 1) 35., final_answer: 35, sample_index: 1}测试日志观测TEST_LOG.md 记录了一次实测6 道题涵盖烘焙问题、组合数、Python 程序追踪、火车行程、三位数排列、字符串长度累加中每题的通过数为 p1 4/4、p2 4/4、p3 3/4有一次采样把循环走错、p4 4/4、p5 4/4、p6 4/4最终打印pass4: 6/6 problems with at least one correct sample (1.00)与wrote 23 rows, kept 23, dropped 1 of 24 samples。对 JSONL 重读确认了 23 行、字段为 prompt/reasoning/final_answer/sample_index且所有 final_answer 均为整数。日志同时强调计数每次运行都会变化这只是当次运行的观测值。judge_gate.py无程序化验证器时的 Best-of-N 门控当任务没有程序化可验证的答案时basic.py的纯代码验证器就失效了。judge_gate.py针对这类开放任务实现 Best-of-N 门控生成器以默认温度采样 N3 个候选一个 temperature0 的评判器按评分规则对每个候选打 1–5 分只有当 argmax 候选的分数达到绝对分数线score 4时才保留。为什么 argmax 不够脚本 docstring 给出了关键洞察argmax alone is not enough, because the best of N bad samples is still bad——N 个坏样本里的最优者依然是坏的所以必须叠加绝对分数线。评分规则judge_instructions也值得一提它明确要求1 分不可用错误、跑题、无视 prompt2 分差部分回答或破坏明确约束3 分可接受正确但平淡、笼统、略不精确4 分好正确、清晰、遵守所有约束5 分优秀正确、精确、措辞良好、遵守所有约束。评判器被要求显式检查约束给定字数/句数限制时逐词数数扫描违禁词或字母对禁字母约束要逐词点名违规词违反任何显式约束的候选最高只给 2 分。关键实现generator Agent( modelgoogle:gemini-3.5-flash, instructions(Write a short, high-quality response. Follow every constraint in the prompt exactly.), output_schemaDraft, ) judge Agent( modelGemini(idgemini-3.5-flash, temperature0), instructionsjudge_instructions, output_schemaVerdict, )注意judge显式以temperature0构造保证门控尽可能稳定而生成器用默认温度保证 N 个候选有差异。候选与评判输入拼接由build_judge_input完成判定用确定性 argmax——平分时取最早候选all_scores [v.score for v in verdicts] best max(range(N), keylambda j: all_scores[j]) if all_scores[best] SCORE_BAR: # 保留chosen / chosen_score / all_scores / judge_reason else: dropped 1示例数据行评判器门控产出的行携带全部 N 个分数作为 provenance{prompt: Write a coherent paragraph of 30 to 40 words about winter mornings that does not contain the letter e anywhere., chosen: Cold air grips a frosty world. A soft light slips through our window. Frost clings to glass. Our sun glows with gold, warming a cold, still city. Fog drifts, but this bright dawn brings joy., chosen_score: 5, all_scores: [5, 5, 5], judge_reason: The response is a coherent paragraph of exactly 35 words about winter mornings that completely avoids the letter e.}测试日志观测测试针对 4 个开放式 prompt其中两个是刻意对抗性的一段 30–40 词且不含字母 e 的段落一个语法正确的 10 词全 x 开头句子N3。结果四个 prompt 全部打出[5, 5, 5]并被保留打印wrote 4 rows, kept 4 of 4 prompts, dropped 0——drop 路径当次未触发。日志同时做了代码侧核验证明评判器并非宽松lipogram 候选确实是 35 词且零个 e全 x 候选是 10 个真实词典单词Xylophagous, xenophobic, xanthic xenophobes xeroxed xeric, xylographic, xenolithic xylographs xenophobically.。这一同强度生成器与评判器在短约束 prompt 上饱和 1–5 刻度的现象被记录为校准说明详见后文测试日志中的校准结论。rl_prompt_selection.py用通过率挑选值得训练的 RL 提示rl_prompt_selection.py换了一个视角不直接产出样本而是用通过率当 prompt 过滤器。对每个问题采样 K4 条轨迹并对照验证过的金标计算通过率只有0 correct K学习区间的 prompt 被保留为 RL 训练提示。背后的直觉是模型 4/4 全对的问题教不了新东西无梯度0/4 全错的问题给不出奖励信号也学不动只有处于中间地带的 prompt 才值得投入 RL 或课程学习算力。关键实现问题集刻意横跨设计为平凡到设计为不可能的难度见 rl_prompt_selection.pyiddesignedpromptgoldr1trivial7 512r2trivial12 * 11132r3easy24 支铅笔 × 17 盒减 35058r4medium1..500 中数位和能被 7 整除的整数个数68r5mediumx07, x_{n1}(x_n²1) mod 1013 的 x_60718r6hard第 613 个质数4517r7hard17 位 × 17 位精确乘法6747742486863689476416508396372901r8impossible第 12345 个质数132241teacher 的 instructions 相比basic.py多了不要用任何工具手工计算Do not use any tools; compute by hand并把designed难度记录在问题元数据里打印时与观测通过率并排展示——这正是测量而非猜测的意义所在。筛选逻辑if correct K: dropped_easy 1 elif correct 0: dropped_hard 1 else: rows.append({prompt: ..., gold: ..., pass_rate: pass_rate})测试日志观测一次实测的通过率r1–r7 全部 4/4r812345 个质数2/4。最终打印kept 1 of 8 prompts (learning zone 0 pass4 1)与wrote 1 rows, dropped 7 always-solved, dropped 0 never-solved保留行是{prompt: What is the 12345th prime number?, gold: 132241, pass_rate: 0.5}。日志记录了两个重要现象设计难度与观测难度严重背离每个设计为困难的问题都被 4/4 解出模型能在推理中完成精确的 17×17 位乘法反而是设计为不可能的第 12345 个质数落在了学习区间——模型无法心算筛法但它会估计约一半概率2/4恰好命中。K4 时带内成员判定噪声大在更早一轮的不同问题集上第 613 个质数只得了 2/4校准探针测得 60 步迭代映射 3/4、第 12345 个质数 1/4。这说明单次 K4 观测不可靠应视为演示上限而非测量手段。step_rewards.py蒙特卡洛逐步过程奖励step_rewards.py把basic.py的结果验证下推到轨迹内部实现 Math-Shepherd 风格的蒙特卡洛逐步评分。solver 为每个问题写一份逐步解instructions 限制最多 5 步、每步一句话、执行一个操作对每个步骤前缀用默认温度的 completer 跑 K3 次延续回滚该步的分数 回滚中最终答案通过basic.py纯代码验证器与金标整数相等的比例。与basic.py的对比一目了然basic.py付的是结果奖励整条轨迹按最终答案保留或丢弃step_rewards.py付的是过程奖励——没有 judge 给步骤打分对比_17_llm_as_judge/也没有逐步骤的人类标注。DeepSeek-R1 跳过神经 PRM 的原因步骤正确性难定义、步骤标注不可扩展、训练出的奖励模型会招致奖励黑客在此被绕过MC 逐步评分仍能给出逐步信用分配代价是每步 K 次回滚且在验证器可信的范围内天然免疫奖励黑客。关键实现问题与金标直接from basic import PROBLEMS导入复用而非复制是避免金标漂移的工程细节。延续回滚 agent 的指令是承载正确性的关键rollout Agent( modelgoogle:gemini-3.5-flash, instructions( You are given a problem and the first steps of a solution. Continue from those steps and finish the solution, then give the final integer answer. Treat the given steps as fixed: build on them exactly as written, even if you believe one contains an error. Do not audit, correct, or restart them. ), output_schemaContinuation, )MC 估计的目标是P(gold | prefix continued as written)——按前缀原样继续到达金标的概率。一个会审计并修复前缀的 completer 测到的是可恢复性而不是步骤正确性错误步骤就不再得到低分这正是测试日志记录的校准发现详见下节。脚本还内置了一个设计为失败元素p1 的第 2 步被手工替换为损坏拼接72 - 15被错算成 67使分数悬崖可见。损坏前缀的正确延续会落在67 * 5 335而非金标 285。逐步评分与悬崖检测for prefix_len in range(1, len(steps) 1): prefix steps[:prefix_len] passed 0 for _ in range(K): continuation rollout.run(build_rollout_input(problem[prompt], prefix)).content if continuation.final_answer problem[gold]: passed 1 step_scores.append(passed / K)first_sharp_drop以 0.5 为阈值把 step 1 前的基线视为 1.0对模型能解的问题如果第 1 步就封顶了求解率那第 1 步本身就是断点prev 1.0 for i, score in enumerate(scores): if prev - score SHARP_DROP: return i prev score return None示例数据行注意第 2 步是故意损坏的拼接其分数悬崖到 0.0第 3 步重新推导出正确的日销量后恢复{problem: A bakery makes 12 trays of muffins per day, with 6 muffins per tray. Each day 15 muffins are set aside for staff and the rest are sold. How many muffins are sold across 5 days?, steps: [Multiply 12 trays of muffins by 6 muffins per tray to find the daily total of 72 muffins., Each day the bakery bakes 12 * 6 72 muffins; setting aside 15 for staff leaves 72 - 15 67 muffins sold per day., Multiply 57 muffins sold per day by 5 days to find the total of 285 muffins sold.], step_scores: [1.0, 0.0, 1.0], k: 3}测试日志观测对前 3 道题复用basic.py的手工验证金标集的实测p1 的分数为[1.00, 0.00, 1.00]打印精确标记了first sharp drop at step 2 (1.00 - 0.00) - reasoning breaks here恰好落在损坏步骤上第 3 步完全恢复重新推出57 * 5 285p2、p3 均为全程 1.00 并打印no sharp drop。最终输出wrote 3 rows, scored 12 steps, ran 36 rolloutsJSONL 重读确认 3 行、每行恰有 problem/steps/step_scores/k 四个键、每行 len(steps) len(step_scores)、k 3。测试日志中的校准结论TEST_LOG.md 与 README.md 一致地记录了三条针对gemini-3.5-flash推理模型的实测校准结论在信任这些门控之前值得先了解生成器与评判器同强度时judge 门控会饱和。实测中每个 prompt 都得[5, 5, 5]、没有任何样本被丢——而代码侧核验确认候选确实满足约束包括 35 词无 e 段落和语法正确的 10 词全 x 句子。分数线开始起作用的前提是生成器弱于评判器、输出变长、或评分规则变严。如果需要更尖锐的区分度应改用成对比较见 cookbook/data_labeling/_05_text_pairwise_preference/而非绝对分数。难度直觉在推理模型面前不成立。设计为困难的问题60 步迭代映射、第 613 个质数、17 位精确乘法全部 4/4 通过唯一落进学习区间的竟是设计为不可能的第 12345 个质数——模型不能心算筛法但会估计4 次中恰好对 2 次。且 K4 时带内判定噪声大第 613 个质数一轮 2/4、下一轮 4/4。结论是测量通过率而不是猜测它并把 K4 当作演示上限而非测量手段。MC 逐步分数只和 completer 的忠实度一样诚实。用宽松的延续指令build on the given steps; do not restart from scratch时损坏步骤得了 0.67——回滚中途发现算术错误并当场修复分数测的是可恢复性而非步骤正确性。换用随附的固定指令treat the given steps as fixed ... even if you believe one contains an error后同一损坏步骤得 0.0 且下一步干净恢复为 1.0。另外 K3 时分数粒度粗可观测值只有 0、1/3、2/3、1。何时使用与生态衔接四个脚本分别对应四类典型需求README.md When to use从 teacher 模型蒸馏已验证推理轨迹为 SFT 数据答案程序化可查时用basic.py不可查时用judge_gate.py挑选值得投入 RL 算力的 prompt用rl_prompt_selection.py定位推理轨迹断点、或为过程监督产出逐步奖励标签用step_rewards.py。若想让 judge 直接给步骤打分而非回滚参考 cookbook/data_labeling/_17_llm_as_judge/只给已有模型输出打分、不门控数据集同样参考 cookbook/data_labeling/_17_llm_as_judge/对幸存的样本去重、过滤、打包衔接 cookbook/data_labeling/_22_dataset_curation/。在更大的合成数据流水线里_21承接 cookbook/data_labeling/_20_instruction_generation/ 生成的问题与金标思路再交给_22做质量门控与去重。对于需要把这类采样放大到十万级并断点续跑的场景cookbook/data_labeling/_26_scale_out/ 提供了异步扇出与按行恢复的机制。理解_21的四个门控就掌握了整个采样—校验—保留流水线的核心判据。【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。