가드레일

adk-guardrail을 사용한 입력/출력 유효성 검사 및 콘텐츠 안전.

개요

가드레일은 안전, 규정 준수 및 품질을 보장하기 위해 Agent의 입력과 출력을 검증하고 변환합니다. 이들은 Agent 실행과 병렬로 실행되며 다음을 수행할 수 있습니다:

  • 유해하거나 주제에서 벗어난 콘텐츠 차단
  • PII (이메일, 전화번호, SSN, 신용카드) 수정
  • 출력에 JSON 스키마 적용
  • 콘텐츠 길이 제한

설치

[dependencies]
adk-guardrail = "0.2.0"

# JSON 스키마 유효성 검사를 위한 설정
adk-guardrail = { version = "0.2.0", features = ["schema"] }

핵심 개념

GuardrailResult

모든 가드레일은 세 가지 결과 중 하나를 반환합니다:

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);

스키마 유효성 검사

Agent 출력에 JSON 스키마를 적용합니다 (schema 기능 필요):

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

여러 가드레일을 결합합니다:

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

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

GuardrailExecutor

Guardrail을 실행하고 상세 결과를 얻습니다:

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>,      // 수정된 Content (있는 경우)
    pub failures: Vec<(String, String, Severity)>, // (이름, 사유, 심각도)
}

Custom Guardrails

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
    }

    // 다른 Guardrail들과 병렬로 실행 (기본값: true)
    fn run_parallel(&self) -> bool {
        true
    }

    // 이 Guardrail 실패 시 빠르게 실패 처리 (기본값: true)
    fn fail_fast(&self) -> bool {
        true
    }
}

Agents와의 통합

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()?;

실행 흐름

사용자 입력
    │
    ▼
┌─────────────────────┐
│  입력 Guardrail     │ ← PII 비식별화, Content 필터링
│  (병렬)             │
└─────────────────────┘
    │
    ▼ (변환되거나 차단됨)
┌─────────────────────┐
│  Agent 실행         │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│  출력 Guardrail     │ ← Schema 유효성 검사, 안전성 확인
│  (병렬)             │
└─────────────────────┘
    │
    ▼
최종 응답

예시

# 기본 PII 및 Content 필터링
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를 제거합니다.
출력 스키마JSON schema를 사용하여 구조화된 출력을 검증합니다.
적절한 심각도Critical은 아껴서 사용하고, Low는 경고에 사용합니다.
철저히 테스트가드레일은 보안에 중요한 코드입니다.

이전: ← 접근 제어 | 다음: 메모리 →