Guardrails
Guardrails(防護欄)會與你的代理(Agent)_並行_運作,讓你能夠對使用者輸入進行檢查與驗證。例如,假設你有一個代理(Agent)使用非常聰明(因此也較慢或昂貴)的模型來協助處理客戶請求。你不會希望惡意使用者要求該模型協助他們完成數學作業。因此,你可以使用一個快速/低成本的模型來執行 guardrail。如果 guardrail 偵測到惡意使用行為,它可以立即拋出錯誤,從而阻止昂貴的模型執行,幫你節省時間與金錢。
Guardrails 有兩種類型:
- Input guardrails(輸入防護欄):在使用者最初輸入時執行
- Output guardrails(輸出防護欄):在代理(Agent)最終輸出時執行
Input guardrails(輸入防護欄)
Input guardrails(輸入防護欄)會經過三個步驟:
- 首先,guardrail 會接收到與代理(Agent)相同的輸入。
- 接著,guardrail 函式會執行,產生一個 [
GuardrailFunctionOutput
][agents.guardrail.GuardrailFunctionOutput],然後包裝成一個 [InputGuardrailResult
][agents.guardrail.InputGuardrailResult] - 最後,我們會檢查 [
.tripwire_triggered
][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] 是否為 true。如果為 true,則會拋出 [InputGuardrailTripwireTriggered
][agents.exceptions.InputGuardrailTripwireTriggered] 例外,你可以適當地回應使用者或處理該例外狀況。
Note
Input guardrails(輸入防護措施)是設計用來運行於使用者輸入上的,因此一個 Agent 的 guardrails 僅會在該 Agent 為第一個 Agent 時執行。你可能會好奇,為什麼 guardrails
屬性會放在 Agent 上,而不是傳遞給 Runner.run
?這是因為 guardrails 通常與實際的 Agent 相關——你會針對不同的 Agent 執行不同的 guardrails,因此將程式碼放在一起有助於提升可讀性。
Output guardrails(輸出防護措施)
Output guardrails 的執行分為三個步驟:
- 首先,guardrail 會接收由 Agent 產生的輸出。
- 接著,guardrail 函式會運行,產生一個 [
GuardrailFunctionOutput
][agents.guardrail.GuardrailFunctionOutput],然後包裝成一個 [OutputGuardrailResult
][agents.guardrail.OutputGuardrailResult]。 - 最後,我們會檢查 [
.tripwire_triggered
][agents.guardrail.GuardrailFunctionOutput.tripwire_triggered] 是否為 true。如果為 true,則會拋出一個 [OutputGuardrailTripwireTriggered
][agents.exceptions.OutputGuardrailTripwireTriggered] 例外(exception),讓你可以適當地回應使用者或處理該例外狀況。
Note
Output guardrails 旨在運行於最終的 Agent 輸出,因此一個 Agent 的 guardrails 只會在該 Agent 是最後一個 Agent 時執行。這與 input guardrails 類似,原因是 guardrails 通常與實際的 Agent 相關——你會針對不同的 Agent 執行不同的 guardrails,因此將程式碼放在一起有助於提升可讀性。
Tripwires
如果輸入或輸出未通過 guardrail,Guardrail 可以透過 tripwire 來發出訊號。一旦發現有 guardrail 觸發了 tripwires,我們會立即拋出 {Input,Output}GuardrailTripwireTriggered
例外並終止 Agent 執行。
實作 guardrail
你需要提供一個接收輸入並回傳 [GuardrailFunctionOutput
][agents.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="Check if the user is asking you to do their math homework.",
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="Customer support agent",
instructions="You are a customer support agent. You help customers with their questions.",
input_guardrails=[math_guardrail],
)
async def main():
# This should trip the guardrail
try:
await Runner.run(agent, "Hello, can you help me solve for x: 2x + 3 = 11?")
print("Guardrail didn't trip - this is unexpected")
except InputGuardrailTripwireTriggered:
print("Math homework guardrail tripped")
- 我們會在 guardrail 函式中使用這個 Agent。
- 這是 guardrail 函式,會接收 Agent 的輸入或上下文,並回傳結果。
- 我們可以在 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)!
reasoning: str
is_math: bool
guardrail_agent = Agent(
name="Guardrail check",
instructions="Check if the output includes any math.",
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="Customer support agent",
instructions="You are a customer support agent. You help customers with their questions.",
output_guardrails=[math_guardrail],
output_type=MessageOutput,
)
async def main():
# This should trip the guardrail
try:
await Runner.run(agent, "Hello, can you help me solve for x: 2x + 3 = 11?")
print("Guardrail didn't trip - this is unexpected")
except OutputGuardrailTripwireTriggered:
print("Math output guardrail tripped")
- 這是實際 Agent 的輸出型別。
- 這是 guardrail 的輸出型別。
- 這是 guardrail 函式,會接收 Agent 的輸出並回傳結果。
- 這是定義工作流程的實際 Agent。