护栏

使用 adk-guardrail 进行输入/输出验证和内容安全。

概览

Guardrails 验证并转换 agent 的输入和输出,以确保安全、合规性和质量。它们与 agent 执行并行运行,并且可以:

  • 阻止有害或离题的内容
  • 删减 PII(电子邮件、电话、SSN、信用卡)
  • 对输出强制执行 JSON schema
  • 限制内容长度

安装

[dependencies]
adk-guardrail = "0.2.0"

# For JSON schema validation
adk-guardrail = { version = "0.2.0", features = ["schema"] }

核心概念

GuardrailResult

每个 guardrail 返回以下三种结果之一:

pub enum GuardrailResult {
    Pass,                                    // 内容有效
    Fail { reason: String, severity: Severity },  // 内容被拒绝
    Transform { new_content: Content, reason: String },  // 内容被修改
}

严重性级别

pub enum Severity {
    Low,      // 仅警告,不阻止
    Medium,   // 阻止但继续其他检查
    High,     // 立即阻止
    Critical, // 阻止并快速失败
}

PII 删减

自动检测和删减个人身份信息:

use adk_guardrail::{PiiRedactor, PiiType};

// 默认: 电子邮件、电话、SSN、信用卡
let redactor = PiiRedactor::new();

// 或者选择特定类型
let redactor = PiiRedactor::with_types(&[
    PiiType::Email,
    PiiType::Phone,
]);

// 直接删减
let (redacted, found_types) = redactor.redact("Email: test@example.com");
// redacted = "Email: [EMAIL REDACTED]"
// found_types = [PiiType::Email]

支持的 PII 类型:

类型模式删减
Emailuser@domain.com[EMAIL REDACTED]
Phone555-123-4567[PHONE REDACTED]
Ssn123-45-6789[SSN REDACTED]
CreditCard4111-1111-1111-1111[CREDIT CARD REDACTED]
IpAddress192.168.1.1[IP REDACTED]

内容过滤

阻止有害内容或强制执行主题约束:

use adk_guardrail::ContentFilter;

// 阻止有害内容模式
let filter = ContentFilter::harmful_content();

// 阻止特定关键词
let filter = ContentFilter::blocked_keywords(vec![
    "forbidden".into(),
    "banned".into(),
]);

// 强制执行主题相关性
let filter = ContentFilter::on_topic("cooking", vec![
    "recipe".into(),
    "cook".into(),
    "bake".into(),
]);

// 限制内容长度
let filter = ContentFilter::max_length(1000);

自定义内容过滤器

use adk_guardrail::{ContentFilter, ContentFilterConfig, Severity};

let config = ContentFilterConfig {
    blocked_keywords: vec!["spam".into()],
    required_topics: vec!["rust".into(), "programming".into()],
    max_length: Some(5000),
    min_length: Some(10),
    severity: Severity::High,
};

let filter = ContentFilter::new("custom_filter", config);

Schema 验证

对 agent 输出强制执行 JSON schema(需要 schema feature):

use adk_guardrail::SchemaValidator;
use serde_json::json;

let schema = json!({
    "type": "object",
    "properties": {
        "name": { "type": "string" },
        "age": { "type": "integer", "minimum": 0 }
    },
    "required": ["name"]
});

let validator = SchemaValidator::new(&schema)?
    .with_name("user_schema")
    .with_severity(Severity::High);

验证器从以下内容中提取 JSON:

  • 原始 JSON 文本
  • Markdown 代码块 (```json ... ```)

GuardrailSet

组合多个 guardrail:

use adk_guardrail::{GuardrailSet, ContentFilter, PiiRedactor};

let guardrails = GuardrailSet::new()
    .with(ContentFilter::harmful_content())
    .with(ContentFilter::max_length(5000))
    .with(PiiRedactor::new());

GuardrailExecutor

运行防护措施并获取详细结果:

use adk_guardrail::{GuardrailExecutor, GuardrailSet, PiiRedactor};
use adk_core::Content;

let guardrails = GuardrailSet::new()
    .with(PiiRedactor::new());

let content = Content::new("user")
    .with_text("Contact: test@example.com");

let result = GuardrailExecutor::run(&guardrails, &content).await?;

if result.passed {
    // Use transformed content if available
    let final_content = result.transformed_content.unwrap_or(content);
    println!("Content passed validation");
} else {
    for (name, reason, severity) in &result.failures {
        println!("Guardrail '{}' failed: {} ({:?})", name, reason, severity);
    }
}

ExecutionResult

pub struct ExecutionResult {
    pub passed: bool,                              // 整体通过/失败
    pub transformed_content: Option<Content>,      // 修改后的内容(如果有)
    pub failures: Vec<(String, String, Severity)>, // (名称, 原因, 严重性)
}

自定义防护措施

实现 Guardrail trait:

use adk_guardrail::{Guardrail, GuardrailResult, Severity};
use adk_core::Content;
use async_trait::async_trait;

pub struct ProfanityFilter {
    words: Vec<String>,
}

#[async_trait]
impl Guardrail for ProfanityFilter {
    fn name(&self) -> &str {
        "profanity_filter"
    }

    async fn validate(&self, content: &Content) -> GuardrailResult {
        let text: String = content.parts
            .iter()
            .filter_map(|p| p.text())
            .collect();

        for word in &self.words {
            if text.to_lowercase().contains(word) {
                return GuardrailResult::Fail {
                    reason: format!("Contains profanity: {}", word),
                    severity: Severity::High,
                };
            }
        }

        GuardrailResult::Pass
    }

    // 与其他防护措施并行运行 (默认: true)
    fn run_parallel(&self) -> bool {
        true
    }

    // 此防护措施失败时快速失败 (默认: true)
    fn fail_fast(&self) -> bool {
        true
    }
}

与 Agent 集成

GuardrailLlmAgentBuilder 集成:

use adk_agent::LlmAgentBuilder;
use adk_guardrail::{GuardrailSet, ContentFilter, PiiRedactor};

let input_guardrails = GuardrailSet::new()
    .with(ContentFilter::harmful_content())
    .with(PiiRedactor::new());

let output_guardrails = GuardrailSet::new()
    .with(SchemaValidator::new(&output_schema)?);

let agent = LlmAgentBuilder::new("assistant")
    .model(model)
    .instruction("You are a helpful assistant.")
    .input_guardrails(input_guardrails)
    .output_guardrails(output_guardrails)
    .build()?;

执行流程

用户输入
    │
    ▼
┌─────────────────────┐
│  输入防护措施         │ ← PII 匿名化, 内容过滤
│  (并行)             │
└─────────────────────┘
    │
    ▼ (已转换或已阻止)
┌─────────────────────┐
│  Agent 执行         │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│  输出防护措施         │ ← Schema 验证, 安全检查
│  (并行)             │
└─────────────────────┘
    │
    ▼
最终响应

示例

# 基本 PII 和内容过滤
cargo run --example guardrail_basic --features guardrails

# JSON schema 验证
cargo run --example guardrail_schema --features guardrails

# 完整的 Agent 集成
cargo run --example guardrail_agent --features guardrails

最佳实践

实践描述
分层安全护栏输入使用安全护栏保证安全性,输出使用安全护栏保证质量
输入上的 PII在 PII 达到模型之前进行编校
输出上的 Schema使用 JSON schema 验证结构化输出
适当的严重性谨慎使用 Critical,对警告使用 Low
彻底测试安全护栏是安全关键代码

上一页← 访问控制 | 下一页内存 →