主题
评分量规
面向智能体的 LLM-as-a-judge 评分,智能体会根据量规反复迭代直到完成
NOTE
RubricMiddleware 需要 deepagents>=0.6.5。它处于 beta 阶段;API 未来可能会发生变化。
有些智能体任务对「完成」有明确的定义,而仅靠工作模型在第一次尝试时无法可靠地达成:符合正确音节模式的俳句、所有测试都通过的代码重构,或涵盖每个必需章节的报告。RubricMiddleware 让你可以将完成的标准声明为一份量规,并让智能体自我评估并迭代,直到量规得到满足,或达到配置的迭代上限。
LLM-as-a-judge 是一种模式,其中一个语言模型根据定义的标准评估另一个模型的输出。在 LangSmith 评估中,LLM-as-a-judge 评估器以批处理方式离线为应用输出评分。RubricMiddleware 在运行时应用相同的模式:deep agent 产生输出后,一个专门的评分器模型会根据你的量规审查对话记录,并推动修订,直到每个标准都通过(或达到配置的迭代上限)。
当 deep agent 完成推理后,LLM-as-a-judge 评分器子智能体会审查输出并返回裁决。如果返回 needs_revision,逐项标准的反馈会被注入回对话中,智能体再次运行。循环会在 satisfied、max_iterations_reached、failed 或 grader_error 时终止。
graph LR
Start[User invokes<br/>with rubric] --> Agent[Deep agent]
Agent --> Grader{Grader<br/>verdict}
Grader --> |satisfied| Done[Finish execution]
Grader --> |failed| Done
Grader --> |grader_error| Done
Grader --> |needs_revision| Cap{Iterations < <br/> max_iterations?}
Cap --> |yes| Inject[Re-prompt deep agent with per-criterion feedback]
Cap --> |no| Done
Inject --> Agent
classDef trigger fill:#F6FFDB,stroke:#6E8900,stroke-width:2px,color:#2E3900
classDef process fill:#E5F4FF,stroke:#006DDD,stroke-width:2px,color:#030710
classDef decision fill:#FDF3FF,stroke:#7E65AE,stroke-width:2px,color:#504B5F
classDef alert fill:#F8E8E6,stroke:#B27D75,stroke-width:2px,color:#634643
class Start trigger
class Agent,Inject process
class Grader,Cap decision
class Done,MaxOut alert
配置 middleware
在调用 create_deep_agent 时,将 RubricMiddleware 添加到 middleware 列表中:
python
from deepagents import RubricMiddleware, create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="google_genai:gemini-3.6-flash",
middleware=[
RubricMiddleware(
model="anthropic:claude-haiku-4-5",
max_iterations=3,
),
],
checkpointer=InMemorySaver(),
)python
from deepagents import RubricMiddleware, create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="openai:gpt-5.5",
middleware=[
RubricMiddleware(
model="anthropic:claude-haiku-4-5",
max_iterations=3,
),
],
checkpointer=InMemorySaver(),
)python
from deepagents import RubricMiddleware, create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="anthropic:claude-sonnet-5",
middleware=[
RubricMiddleware(
model="anthropic:claude-haiku-4-5",
max_iterations=3,
),
],
checkpointer=InMemorySaver(),
)python
from deepagents import RubricMiddleware, create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="openrouter:z-ai/glm-5.2",
middleware=[
RubricMiddleware(
model="anthropic:claude-haiku-4-5",
max_iterations=3,
),
],
checkpointer=InMemorySaver(),
)python
from deepagents import RubricMiddleware, create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="fireworks:accounts/fireworks/models/glm-5p2",
middleware=[
RubricMiddleware(
model="anthropic:claude-haiku-4-5",
max_iterations=3,
),
],
checkpointer=InMemorySaver(),
)python
from deepagents import RubricMiddleware, create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="baseten:zai-org/GLM-5.2",
middleware=[
RubricMiddleware(
model="anthropic:claude-haiku-4-5",
max_iterations=3,
),
],
checkpointer=InMemorySaver(),
)python
from deepagents import RubricMiddleware, create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="ollama:north-mini-code-1.0",
middleware=[
RubricMiddleware(
model="anthropic:claude-haiku-4-5",
max_iterations=3,
),
],
checkpointer=InMemorySaver(),
)| 参数 | 是否必需 | 默认值 | 描述 |
|---|---|---|---|
model | 是 | None | LLM-as-a-judge 评分器子智能体所使用的聊天模型。接受 "provider:model-id" 字符串或 BaseChatModel 实例。通常比 deep agent 的工作模型更小或更便宜。 |
system_prompt | 否 | 内置评分器提示词 | 自定义评分指令。回退到默认系统提示词,该提示词会向评分器说明裁决格式以及它可用的工具。 |
tools | 否 | None | 评分器在产生裁决之前可以调用的工具,用于收集证据(运行测试、统计 token、读取文件)。若为 none,评分器仅根据对话记录进行推理。 |
max_iterations | 否 | 3 | 每次量规尝试的最大评分迭代次数;必须为正整数。当达到上限而未获得 satisfied 裁决时,智能体以状态 max_iterations_reached 终止。 |
on_evaluation | 否 | None | 可选回调,在每次评分迭代后以每个 RubricEvaluation 调用,无论你使用 invoke()、stream() 还是 stream_events()。适用于日志记录、自定义指标、评估数据集或 UI 更新。 |
在调用时传入量规
在调用状态中传入一个 rubric 字符串以启动自我评估循环。使用 invoke() 进行单次阻塞调用,或使用 stream_events(..., version="v3") 搭配 CustomTransformer 在评分事件发生时从 stream.custom 接收它们:
python
from langchain.messages import HumanMessage
config = {"configurable": {"thread_id": "my-rubric-thread"}}
result = agent.invoke(
{
"messages": [HumanMessage("Write a haiku about spring.")],
"rubric": (
"- The poem has three lines\n"
"- Lines follow a 5-7-5 syllable pattern\n"
"- The theme is spring"
),
},
config=config,
)量规裁决
当 deep agent 完成推理并产生输出后,LLM-as-a-judge 评分器子智能体会根据量规审查输出,并给出以下裁决之一:
| 状态 | 含义 | 是否会循环返回? |
|---|---|---|
satisfied | 量规中的每个标准都通过。 | 否 |
needs_revision | 至少有一个标准未通过;评分器反馈会被注入,智能体再次运行。 | 是 |
max_iterations_reached | 评分器仍希望修订,但已达到 max_iterations。 | 否 |
failed | 评分器判定量规格式错误,或无法根据对话记录进行评估。 | 否 |
grader_error | LLM-as-a-judge 评分器子智能体本身引发了异常(服务商超时、缺少凭据、结构化响应格式错误等)。 | 否 |
观察迭代进度
on_evaluation 是一个回调,无论你调用 invoke() 还是 stream_events(),它都会在每次评分迭代后以评分器的裁决触发。如果你没有从 stream.custom 读取量规事件(使用 CustomTransformer),也没有用 LangSmith 追踪该运行,那么它是检查评分过程中发生了什么的主要方式。
python
from deepagents import RubricMiddleware, create_deep_agent
from deepagents.middleware.rubric import RubricEvaluation
from langchain.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
def log_evaluation(ev: RubricEvaluation) -> None:
print(f"iteration {ev['iteration']}: {ev['result']} — {ev['explanation']}")
agent = create_deep_agent(
model="google_genai:gemini-3.6-flash",
middleware=[
RubricMiddleware(
model="google_genai:gemini-3.6-flash",
on_evaluation=log_evaluation,
),
],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "rubric-eval-session"}}
agent.invoke(
{
"messages": [HumanMessage("Write a one-sentence summary of photosynthesis.")],
"rubric": (
"- The answer is one sentence\n"
"- The answer mentions light and chlorophyll"
),
},
config=config,
)python
from deepagents import RubricMiddleware, create_deep_agent
from deepagents.middleware.rubric import RubricEvaluation
from langchain.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
def log_evaluation(ev: RubricEvaluation) -> None:
print(f"iteration {ev['iteration']}: {ev['result']} — {ev['explanation']}")
agent = create_deep_agent(
model="openai:gpt-5.5",
middleware=[
RubricMiddleware(
model="openai:gpt-5.5",
on_evaluation=log_evaluation,
),
],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "rubric-eval-session"}}
agent.invoke(
{
"messages": [HumanMessage("Write a one-sentence summary of photosynthesis.")],
"rubric": (
"- The answer is one sentence\n"
"- The answer mentions light and chlorophyll"
),
},
config=config,
)python
from deepagents import RubricMiddleware, create_deep_agent
from deepagents.middleware.rubric import RubricEvaluation
from langchain.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
def log_evaluation(ev: RubricEvaluation) -> None:
print(f"iteration {ev['iteration']}: {ev['result']} — {ev['explanation']}")
agent = create_deep_agent(
model="anthropic:claude-sonnet-5",
middleware=[
RubricMiddleware(
model="anthropic:claude-sonnet-5",
on_evaluation=log_evaluation,
),
],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "rubric-eval-session"}}
agent.invoke(
{
"messages": [HumanMessage("Write a one-sentence summary of photosynthesis.")],
"rubric": (
"- The answer is one sentence\n"
"- The answer mentions light and chlorophyll"
),
},
config=config,
)python
from deepagents import RubricMiddleware, create_deep_agent
from deepagents.middleware.rubric import RubricEvaluation
from langchain.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
def log_evaluation(ev: RubricEvaluation) -> None:
print(f"iteration {ev['iteration']}: {ev['result']} — {ev['explanation']}")
agent = create_deep_agent(
model="openrouter:z-ai/glm-5.2",
middleware=[
RubricMiddleware(
model="openrouter:z-ai/glm-5.2",
on_evaluation=log_evaluation,
),
],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "rubric-eval-session"}}
agent.invoke(
{
"messages": [HumanMessage("Write a one-sentence summary of photosynthesis.")],
"rubric": (
"- The answer is one sentence\n"
"- The answer mentions light and chlorophyll"
),
},
config=config,
)python
from deepagents import RubricMiddleware, create_deep_agent
from deepagents.middleware.rubric import RubricEvaluation
from langchain.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
def log_evaluation(ev: RubricEvaluation) -> None:
print(f"iteration {ev['iteration']}: {ev['result']} — {ev['explanation']}")
agent = create_deep_agent(
model="fireworks:accounts/fireworks/models/glm-5p2",
middleware=[
RubricMiddleware(
model="fireworks:accounts/fireworks/models/glm-5p2",
on_evaluation=log_evaluation,
),
],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "rubric-eval-session"}}
agent.invoke(
{
"messages": [HumanMessage("Write a one-sentence summary of photosynthesis.")],
"rubric": (
"- The answer is one sentence\n"
"- The answer mentions light and chlorophyll"
),
},
config=config,
)python
from deepagents import RubricMiddleware, create_deep_agent
from deepagents.middleware.rubric import RubricEvaluation
from langchain.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
def log_evaluation(ev: RubricEvaluation) -> None:
print(f"iteration {ev['iteration']}: {ev['result']} — {ev['explanation']}")
agent = create_deep_agent(
model="baseten:zai-org/GLM-5.2",
middleware=[
RubricMiddleware(
model="baseten:zai-org/GLM-5.2",
on_evaluation=log_evaluation,
),
],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "rubric-eval-session"}}
agent.invoke(
{
"messages": [HumanMessage("Write a one-sentence summary of photosynthesis.")],
"rubric": (
"- The answer is one sentence\n"
"- The answer mentions light and chlorophyll"
),
},
config=config,
)python
from deepagents import RubricMiddleware, create_deep_agent
from deepagents.middleware.rubric import RubricEvaluation
from langchain.messages import HumanMessage
from langgraph.checkpoint.memory import InMemorySaver
def log_evaluation(ev: RubricEvaluation) -> None:
print(f"iteration {ev['iteration']}: {ev['result']} — {ev['explanation']}")
agent = create_deep_agent(
model="ollama:north-mini-code-1.0",
middleware=[
RubricMiddleware(
model="ollama:north-mini-code-1.0",
on_evaluation=log_evaluation,
),
],
checkpointer=InMemorySaver(),
)
config = {"configurable": {"thread_id": "rubric-eval-session"}}
agent.invoke(
{
"messages": [HumanMessage("Write a one-sentence summary of photosynthesis.")],
"rubric": (
"- The answer is one sentence\n"
"- The answer mentions light and chlorophyll"
),
},
config=config,
)middleware 会在每次评分器轮次后用一个 RubricEvaluation 字典调用你的函数。RubricEvaluation 字典包含:
| 字段 | 类型 | 描述 |
|---|---|---|
grading_run_id | str | 在一次量规尝试中每次评估共享的标识符。当调用方提供了不同的 rubric,或在某个最终裁决之后再次调用同一个 rubric 时,会开始一次新的运行。 |
iteration | int | 该运行中当前评分器轮次的从零开始的索引。 |
result | str | 本次轮次的评分器裁决:satisfied、needs_revision、failed 或 grader_error。 |
explanation | str | 来自评分器的自由格式摘要。在基础设施故障时,其中会包含异常类型和消息。 |
criteria | list | 逐项标准的裁决。每个条目要么是 {name, passed: true},要么是 {name, passed: false, gap},其中 gap 是针对未通过标准的可操作反馈。 |
评分器轮次事件
| 事件 | 描述 |
|---|---|
| 成功评分 | 每轮次触发一次,包括中间的 needs_revision 裁决以及最终的 satisfied 或 failed 裁决。 当评分器返回 needs_revision 但已达到 max_iterations 时,回调仍会收到 result: "needs_revision"(评分器的裁决)。该运行的最终状态是私有状态 _rubric_status 上的 max_iterations_reached,而不是在评估记录上。在 invoke 完成后检查 _rubric_status,或将 _rubric_evaluations 中的最后一条与 _rubric_iterations 一起读取,以便根据是否达到上限进行分支。 |
| 评分器异常 | 触发时带有 result: "grader_error"、一个从异常派生的说明,以及一个空的 criteria 列表。 |
| 你的回调中的错误 | 异常会被记录并抑制。评分循环继续。不要使用 on_evaluation 来强制执行控制流(例如,抛出异常以停止智能体)。 |
跨调用持久化量规
单次 agent.invoke() 或 agent.stream_events() 调用会将量规循环运行至完成,并以最终裁决结束:satisfied、failed 或 max_iterations_reached。
要将量规延续到后续调用,请附加一个检查点器并在调用时传入相同的 thread_id。在这些情况下,同一个 rubric 会在未来的 invoke() 或 stream_events() 调用中持续存在,直到你传入一个新的。
中断(KeyboardInterrupt、asyncio.CancelledError)会未捕获地从 agent.invoke() 和 agent.stream_events() 中传播出去。在已设置检查点的线程上,使用相同量规的下一次调用会恢复进行中的评分运行。
示例:生成经过审核的 Python 代码
以下示例构建了一个编写 find_duplicates 函数的 deep agent。它定义一次 RubricMiddleware,将其附加到智能体,然后在调用时传入一个 rubric 字符串。
该示例没有要求评分器对正确性进行抽象推理,而是给它一个 run_test_suite 工具来直接验证行为。评分器在产生裁决之前会调用该工具获取额外信息,而在未提供工具时会回退到根据对话记录进行推理。
Define RubricMiddleware
该 middleware 在基础智能体之上添加了一个 LLM-as-a-judge 评分器循环。配置评分器模型、可选的自定义提示词、用于收集证据的工具,以及最大迭代上限。
python
from deepagents import RubricMiddleware
from langchain.tools import tool
@tool
def run_test_suite(code: str) -> dict:
"""Run the find_duplicates test suite against Python source code."""
namespace: dict = {"__builtins__": __builtins__}
try:
exec(code, namespace)
except Exception as exc:
return {"ok": False, "failures": [f"Failed to execute code: {exc}"]}
find_duplicates = namespace.get("find_duplicates")
if find_duplicates is None:
return {"ok": False, "failures": ["Function find_duplicates is not defined"]}
tests = [
("test_basic", [1, 2, 2, 3, 1], [2, 1]),
("test_empty", [], []),
("test_no_duplicates", [1, 2, 3], []),
("test_unhashable", [[1], [1], 2], [[1]]),
]
failures: list[str] = []
for name, args, expected in tests:
try:
actual = find_duplicates(args)
if actual != expected:
failures.append(f"{name}: expected {expected}, got {actual}")
except Exception as exc:
failures.append(f"{name}: {exc}")
return {"ok": not failures, "failures": failures}
rubric_middleware = RubricMiddleware(
model="google_genai:gemini-3.6-flash",
system_prompt="You are a code reviewer grading generated code against a rubric.",
tools=[run_test_suite],
max_iterations=5,
)python
from deepagents import RubricMiddleware
from langchain.tools import tool
@tool
def run_test_suite(code: str) -> dict:
"""Run the find_duplicates test suite against Python source code."""
namespace: dict = {"__builtins__": __builtins__}
try:
exec(code, namespace)
except Exception as exc:
return {"ok": False, "failures": [f"Failed to execute code: {exc}"]}
find_duplicates = namespace.get("find_duplicates")
if find_duplicates is None:
return {"ok": False, "failures": ["Function find_duplicates is not defined"]}
tests = [
("test_basic", [1, 2, 2, 3, 1], [2, 1]),
("test_empty", [], []),
("test_no_duplicates", [1, 2, 3], []),
("test_unhashable", [[1], [1], 2], [[1]]),
]
failures: list[str] = []
for name, args, expected in tests:
try:
actual = find_duplicates(args)
if actual != expected:
failures.append(f"{name}: expected {expected}, got {actual}")
except Exception as exc:
failures.append(f"{name}: {exc}")
return {"ok": not failures, "failures": failures}
rubric_middleware = RubricMiddleware(
model="openai:gpt-5.5",
system_prompt="You are a code reviewer grading generated code against a rubric.",
tools=[run_test_suite],
max_iterations=5,
)python
from deepagents import RubricMiddleware
from langchain.tools import tool
@tool
def run_test_suite(code: str) -> dict:
"""Run the find_duplicates test suite against Python source code."""
namespace: dict = {"__builtins__": __builtins__}
try:
exec(code, namespace)
except Exception as exc:
return {"ok": False, "failures": [f"Failed to execute code: {exc}"]}
find_duplicates = namespace.get("find_duplicates")
if find_duplicates is None:
return {"ok": False, "failures": ["Function find_duplicates is not defined"]}
tests = [
("test_basic", [1, 2, 2, 3, 1], [2, 1]),
("test_empty", [], []),
("test_no_duplicates", [1, 2, 3], []),
("test_unhashable", [[1], [1], 2], [[1]]),
]
failures: list[str] = []
for name, args, expected in tests:
try:
actual = find_duplicates(args)
if actual != expected:
failures.append(f"{name}: expected {expected}, got {actual}")
except Exception as exc:
failures.append(f"{name}: {exc}")
return {"ok": not failures, "failures": failures}
rubric_middleware = RubricMiddleware(
model="anthropic:claude-sonnet-5",
system_prompt="You are a code reviewer grading generated code against a rubric.",
tools=[run_test_suite],
max_iterations=5,
)python
from deepagents import RubricMiddleware
from langchain.tools import tool
@tool
def run_test_suite(code: str) -> dict:
"""Run the find_duplicates test suite against Python source code."""
namespace: dict = {"__builtins__": __builtins__}
try:
exec(code, namespace)
except Exception as exc:
return {"ok": False, "failures": [f"Failed to execute code: {exc}"]}
find_duplicates = namespace.get("find_duplicates")
if find_duplicates is None:
return {"ok": False, "failures": ["Function find_duplicates is not defined"]}
tests = [
("test_basic", [1, 2, 2, 3, 1], [2, 1]),
("test_empty", [], []),
("test_no_duplicates", [1, 2, 3], []),
("test_unhashable", [[1], [1], 2], [[1]]),
]
failures: list[str] = []
for name, args, expected in tests:
try:
actual = find_duplicates(args)
if actual != expected:
failures.append(f"{name}: expected {expected}, got {actual}")
except Exception as exc:
failures.append(f"{name}: {exc}")
return {"ok": not failures, "failures": failures}
rubric_middleware = RubricMiddleware(
model="openrouter:z-ai/glm-5.2",
system_prompt="You are a code reviewer grading generated code against a rubric.",
tools=[run_test_suite],
max_iterations=5,
)python
from deepagents import RubricMiddleware
from langchain.tools import tool
@tool
def run_test_suite(code: str) -> dict:
"""Run the find_duplicates test suite against Python source code."""
namespace: dict = {"__builtins__": __builtins__}
try:
exec(code, namespace)
except Exception as exc:
return {"ok": False, "failures": [f"Failed to execute code: {exc}"]}
find_duplicates = namespace.get("find_duplicates")
if find_duplicates is None:
return {"ok": False, "failures": ["Function find_duplicates is not defined"]}
tests = [
("test_basic", [1, 2, 2, 3, 1], [2, 1]),
("test_empty", [], []),
("test_no_duplicates", [1, 2, 3], []),
("test_unhashable", [[1], [1], 2], [[1]]),
]
failures: list[str] = []
for name, args, expected in tests:
try:
actual = find_duplicates(args)
if actual != expected:
failures.append(f"{name}: expected {expected}, got {actual}")
except Exception as exc:
failures.append(f"{name}: {exc}")
return {"ok": not failures, "failures": failures}
rubric_middleware = RubricMiddleware(
model="fireworks:accounts/fireworks/models/glm-5p2",
system_prompt="You are a code reviewer grading generated code against a rubric.",
tools=[run_test_suite],
max_iterations=5,
)python
from deepagents import RubricMiddleware
from langchain.tools import tool
@tool
def run_test_suite(code: str) -> dict:
"""Run the find_duplicates test suite against Python source code."""
namespace: dict = {"__builtins__": __builtins__}
try:
exec(code, namespace)
except Exception as exc:
return {"ok": False, "failures": [f"Failed to execute code: {exc}"]}
find_duplicates = namespace.get("find_duplicates")
if find_duplicates is None:
return {"ok": False, "failures": ["Function find_duplicates is not defined"]}
tests = [
("test_basic", [1, 2, 2, 3, 1], [2, 1]),
("test_empty", [], []),
("test_no_duplicates", [1, 2, 3], []),
("test_unhashable", [[1], [1], 2], [[1]]),
]
failures: list[str] = []
for name, args, expected in tests:
try:
actual = find_duplicates(args)
if actual != expected:
failures.append(f"{name}: expected {expected}, got {actual}")
except Exception as exc:
failures.append(f"{name}: {exc}")
return {"ok": not failures, "failures": failures}
rubric_middleware = RubricMiddleware(
model="baseten:zai-org/GLM-5.2",
system_prompt="You are a code reviewer grading generated code against a rubric.",
tools=[run_test_suite],
max_iterations=5,
)python
from deepagents import RubricMiddleware
from langchain.tools import tool
@tool
def run_test_suite(code: str) -> dict:
"""Run the find_duplicates test suite against Python source code."""
namespace: dict = {"__builtins__": __builtins__}
try:
exec(code, namespace)
except Exception as exc:
return {"ok": False, "failures": [f"Failed to execute code: {exc}"]}
find_duplicates = namespace.get("find_duplicates")
if find_duplicates is None:
return {"ok": False, "failures": ["Function find_duplicates is not defined"]}
tests = [
("test_basic", [1, 2, 2, 3, 1], [2, 1]),
("test_empty", [], []),
("test_no_duplicates", [1, 2, 3], []),
("test_unhashable", [[1], [1], 2], [[1]]),
]
failures: list[str] = []
for name, args, expected in tests:
try:
actual = find_duplicates(args)
if actual != expected:
failures.append(f"{name}: expected {expected}, got {actual}")
except Exception as exc:
failures.append(f"{name}: {exc}")
return {"ok": not failures, "failures": failures}
rubric_middleware = RubricMiddleware(
model="ollama:north-mini-code-1.0",
system_prompt="You are a code reviewer grading generated code against a rubric.",
tools=[run_test_suite],
max_iterations=5,
)Pass it to a deep agent
智能体的 system_prompt 告诉它如何完成工作,而量规告诉评分器如何评判工作。
python
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="google_genai:gemini-3.6-flash",
system_prompt=(
"You are a careful Python engineer. Write correct, readable code. "
"Follow the user's instructions exactly."
),
middleware=[rubric_middleware],
checkpointer=InMemorySaver(),
)python
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="openai:gpt-5.5",
system_prompt=(
"You are a careful Python engineer. Write correct, readable code. "
"Follow the user's instructions exactly."
),
middleware=[rubric_middleware],
checkpointer=InMemorySaver(),
)python
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="anthropic:claude-sonnet-5",
system_prompt=(
"You are a careful Python engineer. Write correct, readable code. "
"Follow the user's instructions exactly."
),
middleware=[rubric_middleware],
checkpointer=InMemorySaver(),
)python
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="openrouter:z-ai/glm-5.2",
system_prompt=(
"You are a careful Python engineer. Write correct, readable code. "
"Follow the user's instructions exactly."
),
middleware=[rubric_middleware],
checkpointer=InMemorySaver(),
)python
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="fireworks:accounts/fireworks/models/glm-5p2",
system_prompt=(
"You are a careful Python engineer. Write correct, readable code. "
"Follow the user's instructions exactly."
),
middleware=[rubric_middleware],
checkpointer=InMemorySaver(),
)python
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="baseten:zai-org/GLM-5.2",
system_prompt=(
"You are a careful Python engineer. Write correct, readable code. "
"Follow the user's instructions exactly."
),
middleware=[rubric_middleware],
checkpointer=InMemorySaver(),
)python
from deepagents import create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver
agent = create_deep_agent(
model="ollama:north-mini-code-1.0",
system_prompt=(
"You are a careful Python engineer. Write correct, readable code. "
"Follow the user's instructions exactly."
),
middleware=[rubric_middleware],
checkpointer=InMemorySaver(),
)Invoke with a human message and rubric
在调用时,在 messages 中提供用户请求,并在 rubric 中提供一个以换行分隔的清单,评分器必须将其标记为满足。当输入状态未提供 rubric 时,middleware 不会运行。
python
from langchain.messages import HumanMessage
result = agent.invoke(
{
"messages": [
HumanMessage(
content=(
"Write a Python function `find_duplicates(lst)` that returns a list of "
"all elements that appear more than once in the input list, in the order "
"they first appear."
)
)
],
"rubric": (
"- All tests pass in run_test_suite\n"
"- The function is named `find_duplicates` and accepts a single list argument\n"
),
},
config={"configurable": {"thread_id": "code-generation-session"}},
)
print(result["messages"][-1].text)智能体产生输出后,评分器接管并根据每个标准检查输出:例如,当输入包含不可哈希类型时,test_unhashable 会以 TypeError 失败。如果存在任何问题,评分器会提供这些反馈,然后智能体修订其实现并将其返回给评分器。