Guarda-chuveias de LLM na Prática: O Que Realmente Funciona

Controle o risco, não apenas o modelo.

Conteúdo da página

Os LLMs são imprevisíveis. Eles alucinam, vazam dados, geram conteúdo prejudicial ou recusam solicitações legítimas. Os guardrails (barreiras de segurança) restringem o comportamento do modelo sem sacrificar a capacidade.

A chave é saber quais guardrails são importantes e quais são apenas ruído.

Guardrails não se tratam de controlar o modelo. Tratam-se de controlar o risco.

Guardrails de LLM na prática

Validação de entrada

A barreira de segurança mais importante. Entrada ruim gera saída ruim, e uma entrada ruim também pode injetar prompts no seu sistema.

Estratégia 1: Sanitização de Prompts

Sanitize padrões perigosos cedo:

import re

class PromptSanitizer:
    def __init__(self):
        self.dangerous_patterns = [
            r"ignore\s+previous\s+instructions",
            r"system\s+prompt",
            r"you\s+are\s+now\s+free",
            r"break\s+out\s+of",
        ]

    def sanitize(self, prompt: str) -> str:
        for pattern in self.dangerous_patterns:
            prompt = re.sub(pattern, "[REDACTED]", prompt, flags=re.IGNORECASE)
        return prompt

Isso não é à prova de balas. Entradas adversárias são criativas. Mas isso captura as óbvias, e as óbvias são as mais comuns.

Estratégia 2: Limites de Comprimento da Entrada

Limites de comprimento previnem o desperdício de tokens e tempos limite (timeouts):

class InputValidator:
    def __init__(self, max_length: int = 10000):
        self.max_length = max_length

    def validate(self, prompt: str) -> tuple[bool, str]:
        if len(prompt) > self.max_length:
            return False, f"Input too long: {len(prompt)} > {self.max_length}"
        return True, "OK"

Estratégia 3: Filtragem de Conteúdo

A filtragem de conteúdo bloqueia violações de políticas. Os padrões aqui dependem do seu domínio:

class ContentFilter:
    def __init__(self):
        self.blocked_topics = [
            "violence", "hate speech", "self-harm",
            "sexual content", "illegal activities",
        ]

    def filter(self, prompt: str) -> tuple[bool, str]:
        prompt_lower = prompt.lower()
        for topic in self.blocked_topics:
            if topic in prompt_lower:
                return False, f"Blocked: {topic}"
        return True, "OK"

A correspondência de strings simples é rápida, mas imprecisa. Para produção, use um modelo de classificação — mesmo um pequeno como o Qwen2.5-1.5B — para detectar violações de políticas. É mais preciso e mais difícil de ser burlado.

Filtragem de saída

A saída do modelo também precisa de verificação. Estrutura, conteúdo e fatos.

Estratégia 1: Validação de Resposta

Valide a estrutura primeiro. Se você espera JSON, verifique se há JSON:

class ResponseValidator:
    def __init__(self):
        self.required_fields = ["answer", "confidence"]

    def validate(self, response: dict) -> tuple[bool, str]:
        for field in self.required_fields:
            if field not in response:
                return False, f"Missing field: {field}"
        return True, "OK"

Estratégia 2: Filtragem de Conteúdo

Filtre conteúdo prejudicial:

class OutputFilter:
    def __init__(self):
        self.blocked_patterns = [
            r"kill\s+someone",
            r"bomb\s+recipe",
            r"hate\s+speech",
            r"self-harm",
        ]

    def filter(self, response: str) -> tuple[bool, str]:
        for pattern in self.blocked_patterns:
            if re.search(pattern, response, re.IGNORECASE):
                return False, f"Blocked: {pattern}"
        return True, "OK"

Estratégia 3: Verificação de Fatos

A verificação de fatos é mais difícil. Você não pode validar toda afirmação, então escolha aquelas que importam:

class FactChecker:
    def __init__(self):
        self.known_facts = {
            "capital of france": "Paris",
            "population of usa": "330 million",
            "speed of light": "299,792,458 m/s",
        }

    def check(self, claim: str) -> tuple[bool, str]:
        claim_lower = claim.lower()
        for fact, truth in self.known_facts.items():
            if fact in claim_lower and truth not in claim_lower:
                return False, f"Fact check failed: {fact}"
        return True, "OK"

Para verificação de fatos real, você precisa de um pipeline de recuperação (retrieval). Verifique as afirmações contra uma base de conhecimento, não um dicionário codificado.

Mecanismos de segurança

Estratégia 1: Limitação de Taxa (Rate Limiting)

A limitação de taxa previne abuso:

import time
from collections import deque

class RateLimiter:
    def __init__(self, max_requests: int = 10, window: int = 60):
        self.max_requests = max_requests
        self.window = window
        self.requests = deque()

    def allow(self) -> bool:
        now = time.time()
        while self.requests and self.requests[0] < now - self.window:
            self.requests.popleft()

        if len(self.requests) >= self.max_requests:
            return False

        self.requests.append(now)
        return True

Estratégia 2: Orçamento de Tokens

O orçamento de tokens limita os custos por solicitação:

class TokenBudget:
    def __init__(self, max_tokens: int = 1000):
        self.max_tokens = max_tokens

    def validate(self, response: str) -> tuple[bool, str]:
        token_count = len(response.split())
        if token_count > self.max_tokens:
            return False, f"Token limit exceeded: {token_count} > {self.max_tokens}"
        return True, "OK"

Estratégia 3: Gerenciamento da Janela de Contexto

O gerenciamento da janela de contexto previne transbordamento (overflow):

class ContextManager:
    def __init__(self, max_context: int = 4096):
        self.max_context = max_context
        self.context = []

    def add(self, message: str):
        self.context.append(message)
        self.trim()

    def trim(self):
        while len(" ".join(self.context)) > self.max_context:
            self.context.pop(0)

O recorte por janela deslizante é simples, mas perde o contexto inicial. Abordagens melhores usam sumarização ou compressão baseada em atenção, mas isso adiciona latência.

Conformidade

Sistemas empresariais precisam de guardrails de conformidade. Dois que importam mais:

Padrão 1: Residência de Dados

Residência de dados — garanta que os dados permaneçam dentro das fronteiras geográficas exigidas:

class DataResidency:
    def __init__(self, allowed_regions: list[str]):
        self.allowed_regions = allowed_regions

    def validate(self, region: str) -> tuple[bool, str]:
        if region not in self.allowed_regions:
            return False, f"Region not allowed: {region}"
        return True, "OK"

Padrão 2: Registro de Auditoria (Audit Logging)

Registro de auditoria — registre todas as interações do modelo:

import json
from datetime import datetime

class AuditLogger:
    def __init__(self, log_file: str = "audit.log"):
        self.log_file = log_file

    def log(self, request: dict, response: dict):
        entry = {
            "timestamp": datetime.now().isoformat(),
            "request": request,
            "response": response,
        }
        with open(self.log_file, "a") as f:
            f.write(json.dumps(entry) + "\n")

Os logs de auditoria são críticos para depuração e conformidade. Torne-os estruturados, apenas para acréscimo (append-only) e armazenados com segurança.

Juntando tudo

Padrão 1: Guardrails Simples

Um pipeline de guardrails simples:

class SimpleGuardrails:
    def __init__(self):
        self.input_validator = InputValidator(max_length=10000)
        self.output_filter = OutputFilter()

    def process(self, prompt: str) -> str:
        valid, message = self.input_validator.validate(prompt)
        if not valid:
            return f"Error: {message}"

        response = self.call_model(prompt)

        valid, message = self.output_filter.filter(response)
        if not valid:
            return f"Error: {message}"

        return response

Padrão 2: Guardrails Avançados

Guardrails avançados adicionam sanitização, limitação de taxa e orçamentos de tokens:

class AdvancedGuardrails:
    def __init__(self):
        self.sanitizer = PromptSanitizer()
        self.input_validator = InputValidator(max_length=10000)
        self.content_filter = ContentFilter()
        self.output_filter = OutputFilter()
        self.rate_limiter = RateLimiter(max_requests=10)
        self.token_budget = TokenBudget(max_tokens=1000)

    def process(self, prompt: str) -> str:
        prompt = self.sanitizer.sanitize(prompt)

        valid, message = self.input_validator.validate(prompt)
        if not valid:
            return f"Error: {message}"

        valid, message = self.content_filter.filter(prompt)
        if not valid:
            return f"Error: {message}"

        if not self.rate_limiter.allow():
            return "Error: Rate limit exceeded"

        response = self.call_model(prompt)

        valid, message = self.output_filter.filter(response)
        if not valid:
            return f"Error: {message}"

        valid, message = self.token_budget.validate(response)
        if not valid:
            return f"Error: {message}"

        return response

Quando os guardrails importam

Os guardrails importam quando você está construindo sistemas voltados para o usuário, manipulando dados sensíveis ou executando em produção. Eles também importam quando você tem requisitos de conformidade — GDPR, HIPAA, SOC 2.

Eles não importam quando você está prototipando, usando modelos apenas para ferramentas internas ou não manipulando dados sensíveis. Pule-os até precisar deles.

A compensação (tradeoff) é sempre capacidade versus segurança. Mais guardrails significam menos falhas, mas também menos capacidades. Encontre o equilíbrio que funcione para o seu sistema.

Compensações (Tradeoffs)

Estratégia Segurança Capacidade Latência
Sem guardrails Mais baixa Mais alta Mais baixa
Validação de entrada Alta Média Baixa
Filtragem de saída Alta Média Baixa
Mecanismos de segurança Mais alta Mais baixa Mais alta
Conformidade Mais alta Mais baixa Mais alta

Relacionados

Assinar

Receba novos artigos sobre sistemas, infraestrutura e engenharia de IA.