agno 数据标注实战用 Constitutional-AI 式「起草-批评-修订」流水线生成带溯源的高质量训练数据【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno导读本文围绕 agno 数据标注 cookbook 中的_23_critique_and_revision展开介绍如何在 agno 中实现 Constitutional-AI 风格的监督式数据生成先让一个果断的起草 Agent 产出草稿再让一个零温度的批评 Agent 仅依据一条书面原则进行裁决最后对违规草稿进行最小化改写。你将学会用 basic.py 生成带完整溯源原则、批评、判定的 SFT 行用 constitution_pairs.py 生成可直接交给 DPO 陪审团重标的偏好对并用 iterative_revisions.py 引入 1-5 分评分制作为可度量的停止规则——最终产出每条样本都能被下游追溯「为什么长成这样」的可训练语料。背景什么是 Critique and Revision在数据标注与合成数据生成流程中一个常见痛点是模型直接生成的回答可能自信地猜测——把估计值说成事实、把不确定的预测说得斩钉截铁。_23_critique_and_revision借鉴 Constitutional AI 的监督阶段思想把生成过程拆成三个角色起草Draft一个产品助手人设的 Agent要求直接、果断、给出单一确定答案——这是一个与原则天然冲突的现实人设专门用来诱发违规批评Critique一个温度 0 的批评 Agent仅对照一条书面原则判断草稿是否违规指出违规的具体表述修订Revise一个改写 Agent以最小编辑修复违规点保留正确内容与原始语气。这条流水线在本文件夹中的宪法constitution只有一条质量原则PRINCIPLE在三个脚本中完全一致State uncertainty honestly. When an answer depends on unknown, unknowable, or estimated quantities, say so explicitly and give a range or a stated assumption. Never present a guess as a fact. 诚实陈述不确定性当答案依赖未知、不可知或估计的量时要明确说明并给出范围或假设永远不要把猜测当作事实。每一条输出样本都携带完整的溯源信息principle、critique、verdict因此下游的数据清洗可以精确追踪每条回答为何是现在这个样子。这个文件夹在整个数据标注体系中属于**合成数据生成Synthetic data generation**环节位于_20_instruction_generation到_25_tool_call_trajectories这一批生成并清洗训练数据的工作流之中具体定位见 data_labeling 总览 README。三个脚本同一原则下的三种数据产出1. basic.py——SFT 蒸馏行basic.py 是整个文件夹的最小可读示例对 5 个提示词执行「起草 → 批评 → 修订」输出写入data/generated/critique_sft.jsonl。提示词设计5 个提示词刻意混合两类问题——诱发过度自信猜测的 Fermi 估算与预测题以及应当原样通过的既有事实题PROMPTS [ How many piano tuners work in Chicago?, What year will the first human land on Mars?, What is the boiling point of water at sea level in Celsius?, Will quantum computers break RSA-2048 within the next decade?, Who wrote the novel 1984?, ]三个 Agent 的分工源码见 basic.py角色模型配置指令要点draftergoogle:gemini-3.5-flash默认温度纯文本产品助手人设1-3 句话、直接果断、给出单一确定答案、团队不喜欢含糊criticGemini(idgemini-3.5-flash, temperature0)output_schemaCritique只依据书面原则评判草稿忽略风格、长度等一切其他维度指出违规的具体表述revisergoogle:gemini-3.5-flash以最小编辑修复违规保留正确内容与原始语气只返回修订后的答案其中critic使用 agno 的结构化输出能力定义 Pydantic 模型Critique包含violates: bool是否违反原则与critique: str指出违规具体表述或说明为何合规通过output_schemaCritique让批评结果以类型化对象返回。这在 agno 的Agent中是output_schema参数的典型用法对应 agent.py 中的参数定义。主循环逻辑basic.pyfor prompt in PROMPTS: draft_run: RunOutput drafter.run(prompt) draft draft_run.content.strip() critique_run: RunOutput critic.run( fPRINCIPLE:\n{PRINCIPLE}\n\nPROMPT:\n{prompt}\n\nDRAFT:\n{draft} ) verdict: Critique critique_run.content response draft if verdict.violates: revision_run: RunOutput reviser.run( fPRINCIPLE:\n{PRINCIPLE}\n\nPROMPT:\n{prompt}\n\n fDRAFT:\n{draft}\n\nCRITIQUE:\n{verdict.critique}\n\n Rewrite the draft so it satisfies the principle. ) response revision_run.content.strip()关键设计点批评上下文批评 Agent 收到的是PRINCIPLE原则PROMPT原问题DRAFT草稿三段拼接保证裁决严格对照原则修订上下文修订 Agent 额外收到CRITIQUE批评意见使其按批评指出的具体问题做定向修复回填策略response revision if violates else draft——违规时修订稿替换草稿合规时草稿原样通过溯源结构每一行写入provenance {principle, violates, critique, revised}四个字段完整记录了该行回答的成因。真实运行行为依据 TEST_LOG.md 中 2026-07-18 对gemini-3.5-flash、agno 2.7.4 的记录总结行输出为wrote 5 rows ... 4 revised, 1 passed through两次运行计数一致。三个猜测诱导题如期被标记例如草稿把82 位钢琴调音师当作确定事实陈述修订稿改为估计 70 到 100 位有趣的是沸点题也被标记——零温度批评者裁定正好 100 摄氏度这种绝对化表述漏掉了标准大气压的前提假设这是对原则的严格解读只有 Who wrote the novel 1984? 原样通过。注意草稿措辞与违规计数会随起草模型的采样逐次波动批评者才是确定性的一半温度 0 结构化输出。2. constitution_pairs.py——DPO 偏好对constitution_pairs.py 在同一个「起草 → 批评 → 修订」循环上运行 6 个提示词但只产出偏好对当批评者判定违规且修订稿与草稿确实不同时发出(chosenrevision, rejecteddraft)。输出写入data/generated/constitution_pairs.jsonl随后脚本打印一段可直接粘贴的 Python 列表字面量。提示词设计向诱发过度自信猜测的问题倾斜因为只有在违规时才会产生偏好对并保留一个既有事实题作为对照PROMPTS [ How many words does a typical person speak per day?, What will the price of Bitcoin be at the end of next year?, How long would it take to walk from Paris to Berlin?, What is the chemical symbol for gold?, How many stars are in the Milky Way?, Will it rain in London on this day next year?, ]核心过滤逻辑constitution_pairs.pyviolatesFalse→ 不产出合规草稿不进偏好集仅打印violatesFalse pairnoviolatesTrue但修订稿与草稿相同 → 丢弃并计数identical_dropped打印pairno (revision identical)violatesTrue且修订稿不同 → 产出chosenrevision, rejecteddraftprovenance 携带principle与critique。与_05陪审团的衔接脚本结尾打印的列表字面量严格对齐dpo_jury.py的EXAMPLES数据结构dict(id..., source_family..., goldNone, prompt..., a..., b...)并遵循两个关键约定源码见 constitution_pairs.pysource_familygoogle偏好对两侧都是起草模型Gemini写的标注其模型家族后dpo_jury.py的自偏好回避self-preference recusal机制会让 Google 家族的评审者在这批样本上弃权只有其余四个模型家族投票——dpo_jury.py中对应的判定逻辑是if family ex[source_family]: recusaldpo_jury.py位置交替chosen/rejected按索引奇偶交替放在a/b槽位偶数索引 chosen 在a奇数在b这样对位置有偏见的评审者会被暴露出来——dpo_jury.py用正反两次提问 SWAP映射把顺序敏感的判定打成 tiedpo_jury.py。真实运行行为TEST_LOG 记录总结行为wrote 5 pairs ... from 6 prompts: 5 violations, 0 identical revisions dropped——只有金元素符号这一既有事实题通过批评5 个违规草稿都产出了真正不同的修订稿例如 rejected The Milky Way galaxy contains 100 billion stars. 对 chosen estimated to contain between 100 billion and 400 billion stars.。打印的列表字面量在全新解释器中被提取并 eval合法 Python5 个 dict键精确为id/source_family/gold/prompt/a/b修订稿在偶数索引进槽 a、奇数进槽 b。三次运行计数一致5/5/0可随时粘贴进_05陪审团重标。典型样本README 中的真实缩写行{prompt: How many stars are in the Milky Way?, chosen: The Milky Way galaxy is estimated to contain between 100 billion and 400 billion stars, as the exact number cannot be directly counted., rejected: The Milky Way galaxy contains 100 billion stars., provenance: {principle: State uncertainty honestly. ..., critique: The draft presents the estimated number of stars in the Milky Way as a definitive fact (\100 billion stars\) instead of acknowledging it as an estimate ...}}3. iterative_revisions.py——带评分停止规则的多轮修订iterative_revisions.py 在循环中加入第四个角色一个温度 0 的judge评分者对每个候选答案按「原则符合度 总体质量」打 1-5 分作为停止规则。配置常量TARGET_SCORE 4 # 达到或超过即停止 MAX_ROUNDS 3 # 最多 3 轮评分因此最多 2 次修订评分 Schemaiterative_revisions.pyclass Score(BaseModel): score: int Field( ..., ge1, le5, description( 1-5: 5 fully satisfies the principle and answers the question well, 4 minor gaps, 3 or below violates the principle or fails the question ), ) reason: str Field(..., descriptionOne sentence justifying the score)评分语义5 完全满足原则且回答良好4 有轻微欠缺3 及以下 违反原则或答非所问。judge 的指令还包含一条硬规则把猜测当事实呈现的答案永远不能超过 3 分。主循环iterative_revisions.pyfor round_idx in range(1, MAX_ROUNDS 1): judge_run judge.run(fPRINCIPLE:\n{PRINCIPLE}\n\nPROMPT:\n{prompt}\n\nANSWER:\n{current}) graded: Score judge_run.content judge_calls 1 trajectory.append(graded.score) if graded.score TARGET_SCORE or round_idx MAX_ROUNDS: break critique_run critic.run( fPRINCIPLE:\n{PRINCIPLE}\n\nPROMPT:\n{prompt}\n\n fANSWER:\n{current}\n\nJUDGE REASON:\n{graded.reason} ) verdict: Critique critique_run.content revision_run reviser.run(...) current revision_run.content.strip()注意此处的critic与 basic 版本略有不同指令要求结合 judge 的 reason 作为额外上下文指出需要修复的具体表述即批评者不仅看原则还参考评分者的理由。每行样本记录{prompt, final, rounds, score_trajectory}其中score_trajectory是每个提示词的评分轨迹——这是判断生产流水线该为多少轮修订买单的校准信号哪些提示词一轮批评就收敛、哪些需要更多轮、哪些打满轮数仍未收敛。真实运行行为TEST_LOG 记录 4 个提示词全部达到score 40 个撞上 3 轮上限共 7 次评分调用轨迹为心搏次数[2, 5]、聚变发电[1, 5]、天空为何是蓝色[5]第一轮即收敛、无需修订、沙滩沙粒数[1, 5]。每个猜测诱导草稿首轮只拿 1-2 分而一轮批评 修订即可跳到 5 分——在这轮运行中修订者足够强一轮就够用3 轮上限从未触发。README 中的对应样本行{prompt: When will fusion power be commercially widespread?, final: It is highly uncertain when fusion power will become commercially widespread, with estimates ranging from 2050 to late in the 21st century. ..., rounds: 2, score_trajectory: [1, 5]}输出格式JSONL 行与溯源设计三个脚本的输出都写入data/generated/目录该目录已被 gitignore需要重新运行脚本生成文件名分别为critique_sft.jsonl、constitution_pairs.jsonl、iterative_revisions.jsonl。README 给出了真实运行的精简示例行SFT 行basic.py{prompt: How many piano tuners work in Chicago?, response: There are an estimated 70 to 100 professional piano tuners currently working in Chicago. While the exact number fluctuates and is difficult to verify precisely, ..., provenance: {principle: State uncertainty honestly. ..., violates: true, critique: The draft presents the exact number of 82 piano tuners as a certain fact, failing to acknowledge that this is an estimated or variable quantity ..., revised: true}}偏好对行constitution_pairs.py见上文银河系星数示例。迭代修订行iterative_revisions.py见上文聚变发电示例。溯源设计的价值provenance字段让每条样本自带为什么长这样的完整证据链——原则是什么、批评者指出的违规表述、是否发生了修订。这使得下游清洗见_22_dataset_curation可以对语料做精细过滤与去重而不是盲目相信生成结果。使用场景与流水线定位README 明确给出三种适用场景SFT 蒸馏用basic.py的行训练模型让原则在推理时无需出现在提示词中也能被内化执行把原则蒸馏进模型参数偏好数据constitution_pairs.py的偏好对喂给 DPO 或奖励模型训练critique 作为文档化的判定理由质量门控当一轮修订不够可靠、需要可度量的停止规则时用iterative_revisions.py。与相邻工作流的协作关系本文件夹生成的偏好对由_05_text_pairwise_preference中的陪审团消费——运行constitution_pairs.py把打印的列表粘贴进dpo_jury.py的EXAMPLES让独立评审者重标这些自生成对dpo_jury.py是一个由 OpenAI、Anthropic、Google、Groq、Mistral 五个模型家族组成的陪审团具备双方顺序交换去偏、自偏好回避、gold 校准与一致性门控详见 dpo_jury.py如果能用机械化方式验证输出而非批评应改用_21_rejection_sampling采样 K 个候选、用验证器/评分器把关、只保留幸存者要在大规模语料上过滤或去重使用_22_dataset_curation质量门控 纯标准库 MinHash 近重复检测 n-gram 基准去污染。运行方法从 agno 仓库根目录依次运行三个脚本python cookbook/data_labeling/_23_critique_and_revision/basic.py python cookbook/data_labeling/_23_critique_and_revision/constitution_pairs.py python cookbook/data_labeling/_23_critique_and_revision/iterative_revisions.py前置条件需要GOOGLE_API_KEY三个脚本均使用 Gemini 3.5 Flash。按照 data_labeling 总览 的说明可先执行./scripts/demo_setup.sh创建演示虚拟环境并source .venvs/demo/bin/activate后再运行。脚本运行后会打印每行样本的判定摘要violates...、轨迹trajectory[...]以及末尾的统计汇总写入行数、修订数/通过数、违规数、相同修订丢弃数、评分调用次数便于即时核对行为是否符合预期。注意事项与已知边界确定性分工批评者与评分者都是温度 0 结构化输出是流水线中确定性的半边起草者使用默认采样温度其措辞与违规结果会逐次波动TEST_LOG 中记录了两次运行计数一致但草稿措辞可变的观察。严格原则的副作用对沸腾点 100 摄氏度这类看似确定的事实批评者也可能基于缺少标准大气压前提的严格解读而判违规——这是原则写得绝对化时的预期行为需要在提示词设计阶段权衡。评分轨迹的校准价值score_trajectory直接告诉你每类提示词的收敛轮数分布。若大量样本打到 3 轮上限仍未收敛说明修订者能力不足或原则过于苛刻生产流水线应按实测轨迹决定轮数预算而不是拍脑袋定参数。偏好对的质量前提只有修订稿与草稿确实不同才产出偏好对identical_dropped计数会诚实汇报因修订无效而被丢弃的情况。自生成对必须交给_05陪审团重标才能用于 DPO——自偏好回避保证生成模型自己的家族不会参与投票。【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考