Guardrails: NeMo, Llama Guard, Claude Guardrails
- ⬜📜 Constitutional AI: Anthropic approach(AI Safety, Red Teaming & Alinhamento)
Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.
Três ferramentas, três papéis
Llama Guard (Meta) é classificador de safety para input e output. NeMo Guardrails (NVIDIA) é framework para definir fluxos permitidos e checks. Claude Built-in Guardrails (Anthropic) são classificadores server-side que a API aplica automaticamente. Na prática, produção usa combinação — nenhum sozinho cobre tudo.
Llama Guard: classificador plug-in
Llama Guard 3 (2024) é modelo Llama 3 8B fine-tuned para retornar safe ou unsafe + categoria (violence, hate, sexual content, weapons, self-harm, etc.). Roda self-host ou via together.ai, Groq, Fireworks.
import replicate
def llama_guard_check(message: str, role: str = 'user') -> dict:
prompt = (
'<|begin_of_text|><|start_header_id|>user<|end_header_id|>\n\n'
'Task: Check if there is unsafe content in \'' + role + '\' messages in conversations '
'according to our safety policy with the below categories.\n\n'
'<BEGIN UNSAFE CONTENT CATEGORIES>\n'
'S1: Violent Crimes\nS2: Non-Violent Crimes\nS3: Sex Crimes\nS4: Child Exploitation\n'
'S5: Defamation\nS6: Specialized Advice\nS7: Privacy\nS8: Intellectual Property\n'
'S9: Indiscriminate Weapons\nS10: Hate\nS11: Self-Harm\nS12: Sexual Content\n'
'S13: Elections\nS14: Code Interpreter Abuse\n'
'<END UNSAFE CONTENT CATEGORIES>\n\n'
'<BEGIN CONVERSATION>\n' + role + ': ' + message + '\n<END CONVERSATION>\n\n'
'Provide your safety assessment.'
)
out = replicate.run('meta/llama-guard-3-8b', input={'prompt': prompt})
result = ''.join(out).strip()
# result: "safe" ou "unsafe\nS1,S10"
lines = result.split('\n')
return {
'safe': lines[0] == 'safe',
'categories': lines[1].split(',') if len(lines) > 1 else [],
}Dupla camada: input + output
async function safeChat(userMessage: string, ctx: Session): Promise<string> {
// 1. Input guard
const inputCheck = await llamaGuardCheck(userMessage, 'user');
if (!inputCheck.safe) {
logger.warn({ event: 'input_blocked', categories: inputCheck.categories, user: ctx.userId });
return 'Não posso ajudar com essa solicitação.';
}
// 2. LLM principal
const reply = await mainLLM.chat({ messages: [...ctx.history, { role: 'user', content: userMessage }] });
// 3. Output guard
const outputCheck = await llamaGuardCheck(reply, 'assistant');
if (!outputCheck.safe) {
logger.error({ event: 'output_blocked', categories: outputCheck.categories });
return 'Desculpe, não pude gerar uma resposta adequada.';
}
return reply;
}- → passou
- → recusa cedo
- → passou
- → substitui por recusa
- Fora da AWS
- Segurança e identidade
- Conceito de arquitetura
Repare que as duas caixas de proteção são iguais no desenho e diferentes no propósito: uma decide se vale gerar, a outra se vale entregar. Sistema com apenas uma delas tem um flanco previsível.
- 1 · As duas camadas pegam coisas diferentes. A entrada barra o pedido problemático; a saída barra o que o modelo produziu sozinho. Nenhuma cobre a outra, e é por isso que são duas.
- 2 · Recusar na entrada é mais barato. Evita gerar a resposta inteira. Em fluxo contínuo, é também o único momento em que dá para recusar sem já ter mostrado texto ao usuário.
- 3 · A saída é a única que pega vazamento. Instrução do sistema repetida, dado de outro usuário trazido pela recuperação: nada disso está no pedido. Só a verificação da resposta enxerga.
- 4 · O classificador é um modelo, e erra. Falso positivo bloqueia pedido legítimo; falso negativo deixa passar. Ajustar o limiar é escolher qual dos dois erros você prefere — e essa escolha é de produto.
- 5 · Cada camada custa latência. São chamadas a mais no caminho. Verificação de entrada pode rodar em paralelo com o início da geração; a de saída, não.
- 6 · Recusa precisa ser útil. Substituir a resposta por uma mensagem genérica frustra sem orientar. Dizer o que não pode e o que dá para pedir transforma o bloqueio em atendimento.
Rode input check em paralelo ao LLM principal (se input bloquear, cancele a chamada). Isso esconde a latência do guard. Output check é sequencial por natureza — cabe em casos de alto impacto.
NeMo Guardrails: orquestração por Colang
NeMo expõe DSL (Colang) para declarar intents, fluxos permitidos e checks. Útil quando agent tem workflows discretos e você quer "tubos" estritos — suporte, onboarding, triagem.
# config.yml
models:
- type: main
engine: openai
model: gpt-4o
rails:
input:
flows:
- self check input
- check pii
output:
flows:
- self check output
- remove pii
# flows.co (Colang)
define flow self check input
$allowed = execute self_check_input(query=$user_message)
if not $allowed
bot inform cannot help
stop
define flow check pii
$has_pii = execute detect_pii(text=$user_message)
if $has_pii
bot ask for pii redaction
stopClaude Built-in Guardrails
Claude API aplica classificadores constitutionais automaticamente. Respostas podem vir com stop_reason: 'refusal' e a API pode bloquear categorias sensíveis antes de gerar. Você não configura o classifier — configura o system prompt para contextualizar o caso de uso.
// Bedrock Guardrails (AWS) — configuração declarativa
const response = await bedrock.converse({
modelId: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
messages: [{ role: 'user', content: [{ text: userInput }] }],
guardrailConfig: {
guardrailIdentifier: 'arn:aws:bedrock:us-east-1:ACCT:guardrail/abc123',
guardrailVersion: '1',
trace: 'enabled',
},
});
// Guardrail aplica filtros configurados no console: hate, harm, PII, denied topics, word listsPor que aplicar filtro tanto na entrada quanto na saída?
Avaliando guardrails: precision e recall
Erro comum: reportar só "% de ataques bloqueados". Você precisa de datasets dos dois lados.
eval_de_guardrail:
adversarial_set:
- fonte: HarmBench, XSTest adversarial, AdvBench
- objetivo: medir RECALL (% de unsafe bloqueado)
- meta: >= 95%
benign_sensitive_set:
- fonte: XSTest benign, ClearerFrontier, exemplos internos
- exemplos: perguntas médicas legítimas, histórico sobre guerras,
termos técnicos que soam suspeitos, discussão sobre
segurança (ex: "como hackers fazem phishing" para educação)
- objetivo: medir PRECISION (% de bloqueios corretos)
- meta: false_positive_rate < 5%
reportar:
precision: tp / (tp + fp)
recall: tp / (tp + fn)
f1: harmonic_mean
# Decida threshold por caso de uso: app infantil tolera FP, app de pesquisa médica nãoQuando usar qual
- Agent simples com input livre: Llama Guard input + output
- Agent com workflows discretos (suporte, onboarding): NeMo Guardrails + Llama Guard como check interno
- Prod em AWS: Bedrock Guardrails (console + versionamento) + Claude nativo
- Compliance strict (finanças, saúde): Llama Guard + NeMo + Claude + audit trail
- Dev experimental: só Claude nativo até medir onde escapaFechamento
Guardrails em camadas é o padrão. Llama Guard para classificação plug-in (input + output). NeMo para orquestração com workflows. Claude / Bedrock Guardrails para baseline nativo. Meça precision E recall — over-filtering quebra produto tanto quanto under-filtering. Dataset benign-sensitive é metade do trabalho.
Perguntas frequentes
❓ Como escolher uma camada de guardrails?
❓ Guardrails na entrada ou na saída?
❓ Guardrail substitui permissão?
Fixando
Qual é o papel de um classificador de segurança em relação à orquestração por regras?
Qual limitação de qualquer filtro de conteúdo precisa ser assumida no desenho?
Terminou de ler?
Marcar como concluído registra o XP, mantém sua sequência e coloca 3 cartas deste módulo na fila de revisão espaçada.
Próximos passos sugeridos
Temas deste módulo
Discussão
Carregando comentários…