Guardrails 防护机制
Guardrails 与你的 agents 并行运行,让你能够对用户输入进行检查和验证。想象一下,你有一个使用超级智能(但速度慢且昂贵)模型来处理客户请求的 agent。你肯定不希望有人恶意让模型帮他们做数学作业吧?这时,你可以用一个快速且便宜的模型运行 guardrail。如果 guardrail 检测到恶意使用,它会立即抛出错误,阻止昂贵模型运行,为你节省时间和金钱。
Guardrails 分为两种类型:
- Input guardrails(输入防护)在初始用户输入时运行
- Output guardrails(输出防护)在 agent 最终输出时运行
Input guardrails 输入防护
Input guardrails 分三步运行:
- 首先,guardrail 接收与 agent 相同的输入。
- 接着,guardrail 函数运行并生成
GuardrailFunctionOutput,然后被包装在InputGuardrailResult中。 - 最后,我们检查
.tripwire_triggered是否为 true。如果是,就会抛出InputGuardrailTripwireTriggered异常,这样你就可以适当地回应用户或处理异常。
注意
Input guardrails 旨在处理用户输入,所以 agent 的 guardrails 只有在该 agent 是第一个 agent 时才会运行。你可能会想,为什么 guardrails 属性在 agent 上而不是传给 Runner.run?这是因为 guardrails 通常与实际的 Agent 相关 - 不同的 agents 会运行不同的 guardrails,所以把代码放在一起有助于提高可读性。
Output guardrails 输出防护
Output guardrails 同样分三步运行:
- 首先,guardrail 接收与 agent 相同的输入。
- 接着,guardrail 函数运行并生成
GuardrailFunctionOutput,然后被包装在OutputGuardrailResult中。 - 最后,我们检查
.tripwire_triggered是否为 true。如果是,就会抛出OutputGuardrailTripwireTriggered异常,这样你就可以适当地回应用户或处理异常。
注意
Output guardrails 旨在处理 agent 的最终输入,所以 agent 的 guardrails 只有在该 agent 是最后一个 agent 时才会运行。与输入防护类似,我们这样做是因为 guardrails 通常与实际的 Agent 相关 - 不同的 agents 会运行不同的 guardrails,所以把代码放在一起有助于提高可读性。
Tripwires 触发机制
如果输入或输出未通过 guardrail,Guardrail 可以通过 tripwire 发出信号。一旦我们看到 guardrail 触发了 tripwires,我们会立即抛出 {Input,Output}GuardrailTripwireTriggered 异常并停止 Agent 执行。
实现一个 guardrail
你需要提供一个接收输入并返回 GuardrailFunctionOutput 的函数。在这个例子中,我们将通过在底层运行一个 Agent 来实现这一点。
from pydantic import BaseModel
from agents import (
Agent,
GuardrailFunctionOutput,
InputGuardrailTripwireTriggered,
RunContextWrapper,
Runner,
TResponseInputItem,
input_guardrail,
)
class MathHomeworkOutput(BaseModel):
is_math_homework: bool
reasoning: str
guardrail_agent = Agent( # (1)!
name="Guardrail check",
instructions="检查用户是否在要求你帮他们做数学作业。",
output_type=MathHomeworkOutput,
)
@input_guardrail
async def math_guardrail( # (2)!
ctx: RunContextWrapper[None], agent: Agent, input: str | list[TResponseInputItem]
) -> GuardrailFunctionOutput:
result = await Runner.run(guardrail_agent, input, context=ctx.context)
return GuardrailFunctionOutput(
output_info=result.final_output, # (3)!
tripwire_triggered=result.final_output.is_math_homework,
)
agent = Agent( # (4)!
name="客户支持助手",
instructions="你是一个客户支持助手。你帮助客户解答他们的问题。",
input_guardrails=[math_guardrail],
)
async def main():
# 这应该会触发 guardrail
try:
await Runner.run(agent, "你好,能帮我解一下这个方程吗:2x + 3 = 11?")
print("Guardrail 没有触发 - 这很意外")
except InputGuardrailTripwireTriggered:
print("数学作业 guardrail 已触发")
- 我们将在 guardrail 函数中使用这个 agent。
- 这是接收 agent 输入/上下文并返回结果的 guardrail 函数。
- 我们可以在 guardrail 结果中包含额外信息。
- 这是定义工作流程的实际 agent。
Output guardrails 的实现类似。
from pydantic import BaseModel
from agents import (
Agent,
GuardrailFunctionOutput,
OutputGuardrailTripwireTriggered,
RunContextWrapper,
Runner,
output_guardrail,
)
class MessageOutput(BaseModel): # (1)!
response: str
class MathOutput(BaseModel): # (2)!
is_math: bool
reasoning: str
guardrail_agent = Agent(
name="Guardrail check",
instructions="检查输出是否包含任何数学内容。",
output_type=MathOutput,
)
@output_guardrail
async def math_guardrail( # (3)!
ctx: RunContextWrapper, agent: Agent, output: MessageOutput
) -> GuardrailFunctionOutput:
result = await Runner.run(guardrail_agent, output.response, context=ctx.context)
return GuardrailFunctionOutput(
output_info=result.final_output,
tripwire_triggered=result.final_output.is_math,
)
agent = Agent( # (4)!
name="客户支持助手",
instructions="你是一个客户支持助手。你帮助客户解答他们的问题。",
output_guardrails=[math_guardrail],
output_type=MessageOutput,
)
async def main():
# 这应该会触发 guardrail
try:
await Runner.run(agent, "你好,能帮我解一下这个方程吗:2x + 3 = 11?")
print("Guardrail 没有触发 - 这很意外")
except OutputGuardrailTripwireTriggered:
print("数学输出 guardrail 已触发")
- 这是实际 agent 的输出类型。
- 这是 guardrail 的输出类型。
- 这是接收 agent 输出并返回结果的 guardrail 函数。
- 这是定义工作流程的实际 agent。