护栏
使用 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 类型:
| 类型 | 模式 | 删减 |
|---|---|---|
Email | user@domain.com | [EMAIL REDACTED] |
Phone | 555-123-4567 | [PHONE REDACTED] |
Ssn | 123-45-6789 | [SSN REDACTED] |
CreditCard | 4111-1111-1111-1111 | [CREDIT CARD REDACTED] |
IpAddress | 192.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 集成
Guardrail 与 LlmAgentBuilder 集成:
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 |
| 彻底测试 | 安全护栏是安全关键代码 |