Deep Agents 学习笔记(七):Grading Rubrics——让 Agent 按验收标准自我迭代

学习资料:Datawhale《Deep Agents 实战》第十三章:Grading Rubrics

本章重点:RubricMiddleware、LLM-as-a-Judge、Evidence Tool、RubricEvaluation、on_evaluation、Fail-Closed。

一、为什么 Agent 需要运行时验收?

前面学习了 Deep Agents 的任务规划、SubAgent、Skills 和长期记忆等机制,它们分别解决任务执行、能力复用和状态管理的问题。

但还有一个问题:Agent 生成了答案,是否就意味着任务完成?

例如,让 Agent 实现一个 find_duplicates(values) 函数,要求返回所有重复元素,每个元素只出现一次,并支持不可哈希类型。

常见实现:

复制代码
def find_duplicates(values):
    seen = set()
    duplicates = []
    for value in values:
        if value in seen:
            duplicates.append(value)
        seen.add(value)
    return duplicates

这个函数可以处理整数,却无法处理嵌套列表:

复制代码
find_duplicates([[1], [1]])
# TypeError: unhashable type: 'list'

模型虽然生成了完整代码,但并没有满足全部要求。

传统方案通常依赖 Prompt 约束、自检或者失败后重新生成。然而,这些方法往往缺少明确的验收标准和独立证据。

因此,本章引入 Grading Rubrics(评分量规)。

它的核心思想是:

在 Agent 生成结果后,使用预先定义的验收标准进行独立评审;如果未通过,就将具体差距反馈给 Agent,驱动下一轮修订。

二、RubricMiddleware 的工作原理

RubricMiddleware 将评审过程接入 Agent 的运行循环。

其中涉及四个核心角色:

角色 职责
Working Model 生成和修订任务结果
Rubric 定义明确的验收标准
Grader Model 评审候选结果并给出结论
Evidence Tool 通过测试等方式提供客观证据

整个过程形成一个闭环:

复制代码
用户任务 + Rubric
        |
        v
   Working Model
      生成结果
        |
        v
    Grader Model
      独立评审
        |
        v
    Evidence Tool
     获取测试证据
        |
        v
      评审结论
        |
        +-- satisfied
        |      |
        |      v
        |    验收通过
        |
        +-- needs_revision
        |      |
        |      v
        |   反馈具体差距
        |      |
        |      v
        |   Working Model
        |      重新修订
        |
        +-- failed / grader_error
               |
               v
            终止并拒绝

需要注意,工作模型和评分模型可以是同一个底层模型,但承担不同角色。

不过,使用独立评分模型并不能保证结果正确。能够通过测试确定的事实,仍然应该交给工具验证。

三、如何设计高质量 Rubric?

Rubric 不是简单重复用户需求,而是把任务要求转换为可验证的标准。

以 find_duplicates 为例:

复制代码
rubric = """
- 函数名称必须为 find_duplicates。
- 每个重复元素只返回一次。
- 结果按照元素第二次出现的位置排序。
- 必须支持列表等不可哈希对象。
- 不允许修改输入列表。
- 必须运行 run_test_suite。
- 只有测试结果 ok=true 才能通过。
"""

一个有效的 Rubric 应满足三个特点:

特点 含义
可判定 每项标准能够明确判断是否通过
可取证 可以通过测试、Schema 或文件获取证据
可修订 失败时能够指出具体修改方向

例如,"代码质量优秀"属于模糊要求,而"函数不能修改输入参数"可以通过测试直接验证。

设计 Rubric 时,最好将复杂标准拆成多个原子条件,避免评分模型无法定位问题。

四、Evidence Tool:使用工具验证结果

LLM-as-a-Judge 可以进行语义判断,但代码正确性、文件格式和数值计算等问题,最好使用确定性工具验证。

下面定义一个简化版测试工具:

复制代码
from langchain.tools import tool

@tool
def run_test_suite(code: str) -> dict:
    """测试 find_duplicates 函数。"""
    namespace = {}

    try:
        exec(code, namespace)
        func = namespace["find_duplicates"]

        tests = [
            ([1, 2, 2, 3, 1], [2, 1]),
            ([], []),
            ([[1], [1]], [[1]])
        ]

        failures = []

        for values, expected in tests:
            result = func(values.copy())

            if result != expected:
                failures.append({
                    "input": values,
                    "expected": expected,
                    "actual": result
                })

        return {
            "ok": len(failures) == 0,
            "failures": failures
        }

    except Exception as e:
        return {
            "ok": False,
            "failures": [str(e)]
        }

工具返回两个关键字段:

  • ok:表示测试是否通过。

  • failures:记录失败用例和错误信息。

评分模型可以根据这些结构化证据判断哪些标准未满足。

需要注意,这里使用 exec() 仅用于教学演示。它不能安全隔离不可信代码,生产环境必须使用独立沙箱限制文件、网络、计算资源和执行时间。

另外,这个简化示例只覆盖部分行为,实际测试还应验证输入是否被修改、结果是否包含重复项,以及更多边界条件。

五、创建 RubricMiddleware

本章使用两个模型角色:

复制代码
from langchain.chat_models import init_chat_model

working_model = init_chat_model(
    "openai:<working-model-id>"
)

grader_model = init_chat_model(
    "openai:<grader-model-id>"
)

实际运行时,需要替换为可用的模型 ID 并配置 API Key。评分模型应支持结构化输出和工具调用。

创建评分中间件:

复制代码
from deepagents import RubricMiddleware

rubric_middleware = RubricMiddleware(
    model=grader_model,
    tools=[run_test_suite],
    max_iterations=3,
)

其中主要参数:

参数 作用
model 指定评分模型
tools 提供评分模型的取证工具
system_prompt 定义评分角色与规则
max_iterations 最大评分轮数
on_evaluation 每轮评分后的回调

特别注意,RubricMiddleware(tools=[...]) 配置的工具只供评分模型使用,不会自动成为工作模型的工具。

然后将 Middleware 挂载到 Agent:

复制代码
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver

agent = create_deep_agent(
    model=working_model,
    middleware=[rubric_middleware],
    checkpointer=InMemorySaver(),
)

调用时需要同时传入任务和 Rubric:

复制代码
result = agent.invoke(
    {
        "messages": [{
            "role": "user",
            "content": "实现 find_duplicates(values)"
        }],
        "rubric": rubric,
    },
    config={
        "configurable": {
            "thread_id": "rubric-demo"
        }
    },
)

这里的 rubric 属于运行状态,而不是创建 Agent 时固定的构造参数,因此同一个 Agent 可以处理不同任务和验收标准。

六、RubricEvaluation:如何判断是否真正通过?

评分过程中可能出现五种状态:

状态 含义 是否通过
satisfied
相关推荐
Mr. zhihao2 天前
Deep Agent 架构深度解析:主Agent与子Agent完整交互机制与核心参数作用
python·ai·langgraph·deepagent
树獭哥6 天前
Deep Agents 学习笔记(三):任务规划与分解——让 Agent 学会拆解复杂任务
deepagent
树獭哥6 天前
Deep Agents 学习笔记(五):Skills——可复用的 Agent 能力包
deepagent
小马过河R1 个月前
开篇|3天从0到1入门AI应用开发
人工智能·语言模型·llm·agent·ai编程·deepagent
深兰科技3 个月前
深兰科技携手绿地集团布局行业智能体,绿地深兰科技智能体科技公司揭牌
人工智能·科技·启发式算法·推荐算法·深兰科技·绿地集团·deepagent
甘露s3 个月前
Eino DeepAgent 详解:让 Agent 从工具调用走向复杂任务执行
ai·agent·deepagent
学Linux的语莫4 个月前
deepagent中agent的易混淆功能区别
deepagent
学Linux的语莫5 个月前
DeepAgents Skills :掌握 Agent 的可复用专业能力
ai·skill·deepagent
果汁华5 个月前
Deep Agents 深度解析:LangChain 高层 Agent 模式如何走向生产级
langchain·deepagent