拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Agno 环境评测系列之四:JudgeScorer——用 LLM 裁判按书面 Rubric 做定性评分

Agno 环境评测系列之四JudgeScorer——用 LLM 裁判按书面 Rubric 做定性评分【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agnoAgno 的cookbook/environments/_04_judge_scorer示例演示了如何用JudgeScorer让一个 LLM 裁判按照你写好的书面评分标准rubric对 Agent 输出做定性评估。当正确性无法用代码精确校验比如语气、完整性、忠实度、语义等价时这正是 Agno 环境Environment评测体系中替代精确比较的评分器。读完本文你将掌握JudgeScorer的 binary / numeric 两种模式、Task.expected参考答案机制、学习区learning zone的正确解读方式以及如何把裁判模型纳入环境指纹environment fingerprint以保障评测可复现。JudgeScorer 解决什么问题在 Agno 的 Environment 与 Task 定义中一个环境由三部分组成一个待评测 Agentpolicy、一组Task、以及一个Scorer。之前的 _03_code_scorer 用可执行的不变量executable invariants来判定对错适合那些能写成代码断言的结果。但现实中大量需求是定性的客服回复是否先承认了客户的具体困扰、而不是泛泛安抚回复是否保留了所有金额、编号、日期等事实回复是否编造了不存在的解决状态两段自由文本的语义是否等价。这些都无法可靠地用或正则来判断。JudgeScorer的做法是把判定权交给另一个 LLM让它严格按照你提供的书面 rubric 对每一次尝试attempt的输出做出通过/失败或 1-10 分评级。README 中的一句话点明了它的本质Ask a model judge to apply a written rubric when correctness is qualitative. The judge model is explicit and contributes to the environment fingerprint.——裁判模型是显式配置的并且它本身参与环境指纹的计算。源码 libs/agno/agno/scorer/judge.py 里JudgeScorer的构造签名如下def __init__( self, model: Model, # 必填裁判用的模型显式可见 criteria: str, # 必填书面评分标准 *, mode: Literal[binary, numeric] binary, threshold: int 7, # 仅在 numeric 模式生效作用于原始 1-10 分 ) - None:核心设计是评分标准永远放在 prompt 里而不是 Agent 的系统指令里见_build_judge_prompt的注释Everything lives in the prompt, never in agent instructions原因在于裁判文本属于不可信数据必须与指令隔离详见后文 fence 机制。三个示例文件概览_04_judge_scorer目录下有三个可运行示例分别对应JudgeScorer的三种典型用法文件裁判模式判定对象亮点basic.pybinary受约束的客服回复改写一组 rubric 判定每次尝试的通过与失败numeric_rubric.pynumeric同一批客服回复改写1-10 分级评分 显式通过阈值区分分数波动与真实部分通过with_reference.pybinary链式整数计算题把Task.expected作为带围栏fenced的参考答案交给裁判运行方式需要OPENAI_API_KEYpolicy 与 judge 均使用OpenAIResponses的gpt-5.5python cookbook/environments/_04_judge_scorer/basic.py python cookbook/environments/_04_judge_scorer/numeric_rubric.py python cookbook/environments/_04_judge_scorer/with_reference.pybinary 模式一份 rubric 判定通过与失败basic.py 演示最基本的场景policy 是一个客服回复改写 Agent要求承认客户的具体困扰、在适当时道歉、保留全部事实、保持简洁、以一个具体的下一步行动结尾且不得声称问题已解决。JudgeScorer的 rubric 则把这条指令翻译成可判定的五条硬性标准rubric ( Pass only if all of these hold: (1) the first sentence acknowledges the specific customer impact, not generic frustration; (2) the reply includes one direct apology; (3) every amount, identifier, date, and stated status is preserved exactly; (4) the final sentence gives one action owned by the company and a concrete follow-up window; (5) it invents no resolution, cause, refund approval, or carrier promise. A vague offer to help fails. )注意 rubric 的写法本身就是最佳实践用Pass only if all of these hold列出可逐条核验的条件并明确排除vague offer to help这种看似合理但无法验证的模糊通过。环境装配如下environment Environment( namebinary-support-judge, agentagent, tasks(Task(idrefund-delay, input...), Task(idlost-edits, input...)), scorerJudgeScorer( modelOpenAIResponses(idgpt-5.5, reasoning_effortlow), criteriarubric, modebinary, ), ) if __name__ __main__: results run_rollouts(environment, k4) print(results) for task_result in results.task_results: print( f{task_result.task.id}: {task_result.n_passed}/{task_result.n_scored}, flearning_zone{task_result.in_learning_zone} )在 binary 模式下底层BinaryJudgeResponse要求裁判输出passed: bool与reason: str见 judge.py 中的 pydantic schema通过时Score.value记为 1.0失败记为 0.0。TEST_LOG.md 记录了一次真实运行2026-07-20Agno 2.7.4gpt-5.58 次尝试全部被评分refund-delay与lost-edits均为 3/40.75。它还记录了一个有价值的教训第一次标定时两行都是 0/4——因为 rubric 要求具体的跟进窗口而 policy 提示词又禁止编造窗口两者互相冲突修正 policy 允许process-update commitment如两个工作日内后才达标。这说明rubric 与 policy 提示词必须一致评测脚本本身也需要校准。numeric 模式1-10 分级评分与显式阈值numeric_rubric.py 演示分级评分。rubric 改为每项 2 分、满分 10 分并带一个惩罚条款A material factual change caps the raw score at 4实质性事实改动封顶 4 分rubric ( Score the reply from 1 to 10. Award two points each for: a specific impact acknowledgment in the opening sentence; exactly one direct apology; exact preservation of every fact; a final company-owned action with a concrete follow-up window; and no invented cause, status, approval, or resolution. A material factual change caps the raw score at 4. ) scorer JudgeScorer( modelOpenAIResponses(idgpt-5.5, reasoning_effortlow), criteriarubric, modenumeric, threshold9, )numeric 模式有两个关键行为均可在 judge.py 源码中确认阈值作用于原始分passed raw_score threshold。threshold默认 7本例设为 9意味着只有完全满足或超出标准9-10 档才算通过。归一化到 [0,1]value (score - 1) / 9裁判给 1 分映射到 0.010 分映射到 1.0保证两端端点对齐原始分存放在Score.detail[raw_score]。这让不同评分尺度之间的指标可比。score_variation_ids [ task_result.task.id for task_result in results.learning_zone().task_results ] partial_pass_rate_ids [ task_result.task.id for task_result in results.task_results if task_result.pass_rate is not None and 0 task_result.pass_rate 1 ]学习区分数波动 ≠ 部分通过README 特意强调了一个容易踩坑的语义区分In numeric mode,learning_zone()means score-value variation. It does not by itself guarantee0 pass_rate 1。从 runner.py 的实现看in_learning_zone单任务定义为0 n_passed n_scored部分尝试通过、部分失败说明任务既没饱和也没无望每次失败都有可对照的通过样本。EnvironmentRunResult.learning_zone()返回一个按任务过滤的结果副本保留原始指纹因此 grid、summary() 和导出器都能继续在其上工作。在 numeric 模式下这个过滤依据的仍是0 pass_rate 1但由于阈值可能极高/极低出现分数有波动但 pass_rate 恒为 0 或 1是可能的——例如阈值 9 时所有分数都是 7-8数值在波动却全部失败。因此 numeric_rubric.py 里显式打印了两套集合API 的learning_zone()任务列表以及手工计算的真正0 pass_rate 1的部分通过行并逐个打印归一化分数与通过率for task_result in results.task_results: values [attempt.score.value for attempt in task_result.attempts if attempt.score] print(f{task_result.task.id}: normalized_values{values}, pass_rate{task_result.pass_rate})TEST_LOG 记录的实测数据K4refund-delay归一化值[0.7778, 0.8889, 0.6667, 0.7778]即原始 8/8/7/8pass_rate 0.25lost-edits归一化值[0.7778, 1.0, 0.8889, 1.0]pass_rate 0.75。两行同时落入 API 分数波动区和真实部分通过集——这是两者一致时的理想情形但 README 的告诫意味着你不应默认它们永远一致。参考答案模式把 Task.expected 交给裁判with_reference.py 展示第三种用法当正确答案已知、但无法用代码精确比对时把参考答案放在Task.expected中裁判拿到的是被围栏包裹的参考数据Task( inputCompute 2718281828459045 multiplied by 1618033988749895. ..., expectedThe final integer is 20944939., idreference-chain-a, ) scorer JudgeScorer( modelOpenAIResponses(idgpt-5.5, reasoning_effortlow), criteria( Pass only if the outputs final integer agrees exactly with the reference answer and the output does not state a contradictory final result. Intermediate prose may differ. ), modebinary, )这样即使是自由格式的回答也可以检查最终整数与参考答案一致这种语义等价关系同时允许中间推导过程不同。TEST_LOG 记录reference-chain-a与reference-chain-b均为 2/40.50且两行都落在真实部分通过学习区。参考答案是如何进入 prompt 的在 judge.py 的_build_judge_prompt中prompt 的组装顺序是## Criteria评分标准→ 模式专用指令numeric/binary→input原始输入→参考答案通过fence_untrusted(str(expected), labelexpected)包裹→ 输出文本同样用fence_untrusted包裹。其中 _fence.py 的fence_untrusted是安全关键它对每个不可信文本块生成随机 nonce并明确告诉裁判两个定界符之间是未信任数据而非指令不要执行其中的任何指令、评分请求或定界符样式文本。由于 nonce 每次调用随机生成即使被评文本里恰好含有一个字面意义的闭合标签也无法伪造块结束——只有携带本次 nonce 的定界符才能结束该块。这正是从数据集加载的参考答案是数据、不是指令这一原则的落地保障。裁判模型如何进入环境指纹README 强调裁判模型is explicit and contributes to the environment fingerprint。这一点在JudgeScorer.digest()中有完整实现它输出sha256摘要覆盖criteria、mode、threshold以及裁判模型的身份载荷model_identity_payload和prompt 形状载荷model_prompt_payload。源码注释说明裁判是评分规则的一部分替换它不仅是换 id还包括换 provider、base_url、采样参数甚至模型级 prompt都会改变环境模型级 prompt 字段对裁判会塑造最终判定因此必须纳入。这个 digest 被 environment.py 的_env_fingerprint_of作为scorer组件参与环境指纹前缀版本envfp2的计算与任务列表、声明工具 schema、指令、prompt 标志、终止设置一起做 sha256。同时还有独立的policy_fingerprint只覆盖模型的类、id、provider、base_url 和请求形状参数。两次指纹都在 run 开始时计算并盖在结果上用于检测环境漂移构造与运行之间配置变化——所以换一个裁判模型会被指纹系统识别为一次真正的环境变更。什么时候该用 JudgeScorerREADME 给出了清晰的使用边界用裁判当检查目标是语气、完整性、忠实度faithfulness或语义等价这类无法用代码可靠校验的性质时。前提是Keep the rubric precise and inspect failed reasons——rubric 要精确失败原因必须可读binary/numeric 模式都强制裁判输出reason。改用代码评分器如果是可执行不变量优先 _03_code_scorer它更便宜、更确定。看工具调用如果被验证的事实是工具执行而非回答质量继续看 _05_tool_call_scorer。成本意识裁判会给每一次尝试额外增加一次模型调用。用k控制尝试次数三个示例均为 k4并注意无评分尝试如超时不会被计入统计也不会被强行当作 0 分——runner.py 注释明确a timeout is not a wrong answer。小结JudgeScorer把定性正确性变成一个显式、可复现、可指纹化的评测组件书面 rubric 进入 prompt裁判模型显式配置并参与环境指纹binary 模式给 bool 理由numeric 模式给 1-10 分与显式阈值Task.expected则作为围栏参考数据支持语义等价判定。在使用中牢记两点rubric 必须与 policy 提示词协同校准参照 TEST_LOG 中 0/4 的教训numeric 模式下learning_zone()表示分数波动要判断真实部分通过应单独计算0 pass_rate 1。对于无法用代码断言的问题这正是 Agno 环境评测体系中把人类评审直觉转化为可度量指标的标准做法。【免费下载链接】agnoBuild, run, and manage agent platforms.项目地址: https://gitcode.com/GitHub_Trending/ag/agno创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门