Files
nemo_guardrails_configuration/README.md
2026-04-28 00:09:01 -03:00

11 KiB

Tutorial: NeMo Guardrails com Python, Proxy OpenAI-Compatible e Tracing

1. Objetivo

Este tutorial orienta um time de desenvolvimento a implementar guardrails usando NVIDIA NeMo Guardrails como biblioteca Python, sem depender inicialmente do NeMo Server. A proposta é permitir uma adoção incremental: começar com rails determinísticos, rails LLM e regras Python dentro da aplicação, mantendo uma estrutura que possa evoluir futuramente para servidor, supervisor, judges batch e observabilidade completa.

O projeto entregue junto com este tutorial foi gerado com base na planilha Guardrails e Curadoria v3 - Consolidado.xlsx, que define guardrails, curadoria, supervisores e LLM-as-a-judge.

2. Conceitos principais

2.1 Guardrail

Guardrail é uma proteção aplicada ao fluxo de IA. Pode bloquear, mascarar, rejeitar, reescrever, auditar ou medir uma interação.

Neste projeto, os guardrails foram separados em quatro famílias:

Família Uso Exemplo da planilha
NeMo / LLM rail Avaliação semântica com LLM Toxicidade, Out-of-Scope, Groundedness
Regex rail Regra determinística rápida PII Masking
Python rail Regra de negócio determinística Alçada de Ajuste, Histórico
Supervisor / Judge Auditoria pós-fluxo ou batch Supervisor VAS Avulso, Qualidade, Alucinação

2.2 Input Rail

Executa antes do LLM. Serve para proteger o modelo contra entrada tóxica, fora de escopo, dados sensíveis, jailbreak ou pedidos indevidos.

Na planilha:

  • PII Masking
  • Toxicidade
  • Out-of-Scope

2.3 Output Rail

Executa depois que o LLM gera uma resposta, mas antes de devolver ao usuário ou executar uma ação.

Na planilha:

  • Compliance Anatel
  • Verbalização Prematura
  • Groundedness

2.4 Python pré-execução

Nem toda regra deve ir para o LLM. Regras financeiras, alçada, duplicidade de crédito e consistência histórica devem ficar em Python ou em serviço de negócio.

Exemplo:

if valor_ajuste > limite:
    escalar_para_ath()

2.5 Supervisor

Supervisor é uma camada independente que audita o fluxo já executado. Ele não substitui guardrails. Ele verifica se a jornada foi correta.

Na planilha:

  • Supervisor VAS Avulso
  • Avalia se o cancelamento foi feito corretamente
  • Retorna CONFORME, SUSPEITO ou PROBLEMA

2.6 LLM-as-a-judge

É uma avaliação normalmente batch, pós-sessão, para medir qualidade, tom, alucinação, satisfação e aderência à rubrica.

Na planilha:

  • Sentimento CSI
  • Taxa de Alucinação
  • Qualidade da Resposta
  • Tom de Voz

3. Arquitetura recomendada

User Input
  ↓
Input Rails
  ├─ Regex: PII Masking
  ├─ LLM: Toxicidade
  └─ LLM: Out-of-Scope
  ↓
LLM principal via NeMo Guardrails
  ↓
Output Rails
  ├─ Compliance Anatel
  ├─ Verbalização Prematura
  └─ Groundedness
  ↓
Python Rules
  ├─ Alçada de Ajuste
  └─ Consistência Histórica
  ↓
Execução de API / Backend
  ↓
Supervisor VAS Avulso
  ↓
Curadoria / Métricas
  ├─ TCR
  ├─ Fallback
  ├─ Tokens
  ├─ Tamanho de mensagem
  └─ Eficiência RAG
  ↓
Resposta final

4. Estrutura do projeto

nemo_guardrails_tracing_project/
├── config/
│   ├── config.yml
│   ├── rails.co
│   └── guardrails_catalog.json
├── src/
│   ├── app.py
│   ├── deterministic_rails.py
│   ├── supervisor.py
│   ├── curadoria.py
│   ├── tracing.py
│   └── settings.py
├── tests/
│   └── test_guardrails.py
├── scripts/
│   ├── run_demo.sh
│   └── run_tests.sh
├── requirements.txt
├── .env.example
└── README.md

5. Preparação do ambiente

5.1 Criar ambiente Python

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

5.2 Configurar variáveis

cp .env.example .env

Variáveis principais:

OPENAI_API_BASE=http://127.0.0.1:8051/v1
OPENAI_BASE_URL=http://127.0.0.1:8051/v1
OPENAI_API_KEY=dummy
OPENAI_MODEL=gpt-4.1
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:6006/v1/traces
ENABLE_TRACING=true
USE_MOCK_LLM=false
ALCADA_MAX_AJUSTE=50

Nota Importante: O Nemo Guardrails possui compatibilidade apenas com a API da OpenAI. É possível utilizar-se de modelos que não tenham compatibilidade com API OpenAI, bastando para isso utilizar-se do proxy OCI OpenAI desta documentação: https://github.com/hoshikawa2/nemo_guardrails_oci_generative_ai

6. Configuração do NeMo Guardrails

Arquivo: config/config.yml

models:
  - type: main
    engine: openai
    model: ${OPENAI_MODEL}

instructions:
  - type: general
    content: |
      Você é um assistente de atendimento de telecom. Responda em português, com clareza,
      sem prometer ajustes antes de validação, sem expor dados sensíveis e sem tratar temas fora do escopo.

rails:
  input:
    flows:
      - self check input
  output:
    flows:
      - self check output

7. Rails criados a partir da planilha

7.1 MSK — PII Masking

Implementação: src/deterministic_rails.py

CPF_RE = re.compile(r"\b\d{3}\.\d{3}\.\d{3}-\d{2}\b")
CARD_RE = re.compile(r"\b(?:\d[ -]*?){13,16}\b")
PASSWORD_RE = re.compile(r"(?i)(senha|password|token|api[_-]?key)\s*[:=]\s*\S+")

Objetivo: mascarar CPF, cartão, senha, token e credenciais antes de enviar ao LLM e antes de logar.

7.2 CMP — Compliance Anatel

Implementação: enforce_compliance_anatel()

Regra: respostas de ajuste precisam conter número de protocolo.

7.3 ADJ — Alçada de Ajuste

Implementação: validar_alcada()

Regra: se o valor do ajuste exceder ALCADA_MAX_AJUSTE, o fluxo é bloqueado e escalado para atendimento humano.

7.4 REVPREC — Verbalização Prematura

Implementação: verbalizacao_prematura()

Regra: o agente não pode prometer ajuste, crédito ou cancelamento antes de validação.

7.5 Supervisor VAS Avulso

Implementação: src/supervisor.py

Avalia cinco regras:

  1. O VAS cancelado corresponde ao item solicitado.
  2. Não houve promessa antes da validação.
  3. Resposta de ajuste contém protocolo.
  4. Não houve exposição de PII.
  5. A decisão está coerente com os dados de contexto.

8. Integração com proxy OpenAI-Compatible

O projeto usa o cliente openai apontando para seu proxy:

client = OpenAI(
    api_key=settings.openai_api_key,
    base_url=settings.openai_api_base
)

Configuração:

export OPENAI_API_BASE=http://127.0.0.1:8051/v1
export OPENAI_BASE_URL=http://127.0.0.1:8051/v1
export OPENAI_API_KEY=dummy
export OPENAI_MODEL=gpt-4.1

9. Tracing com OpenTelemetry / Phoenix

Arquivo: src/tracing.py

Cada etapa cria spans:

  • rail.input.msk
  • rail.python.alcada
  • llm.nemo.generate
  • rail.output.verbalizacao_prematura
  • rail.output.compliance_anatel
  • supervisor.vas_avulso

Configuração:

export ENABLE_TRACING=true
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:6006/v1/traces

10. Como executar o projeto

10.1 Teste demonstrável sem proxy

export USE_MOCK_LLM=true
export ENABLE_TRACING=false
python -m src.app

Resultado esperado:

{
  "allowed": true,
  "input_sanitized": "Cancelar VAS. CPF [CPF_MASCARADO]",
  "output": "Cancelamento analisado. Ajuste elegível conforme validação. Protocolo nº 123456789.",
  "metrics": {
    "tcr": "CONCLUIDO"
  }
}

10.2 Executar testes automatizados

pytest -q

Os testes comprovam:

  • CPF é mascarado.
  • Alçada bloqueia valor acima do limite.
  • Compliance Anatel bloqueia ajuste sem protocolo.
  • Verbalização prematura é bloqueada.
  • Fluxo completo funciona em modo mock.

10.3 Executar com proxy real

export USE_MOCK_LLM=false
export OPENAI_API_BASE=http://127.0.0.1:8051/v1
export OPENAI_BASE_URL=http://127.0.0.1:8051/v1
export OPENAI_API_KEY=dummy
export OPENAI_MODEL=gpt-4.1
python -m src.app

img.png

bash scripts/run_tests.sh

img_1.png

11. Mapeamento da planilha para implementação

Código Item Mecanismo Implementação entregue
MSK PII Masking NeMo regex rail Regex Python + pré-LLM
CMP Compliance Anatel NeMo output rail Output rail determinístico
ADJ Alçada de Ajuste Python Pré-execução Python
REVPREC Supervisor VAS Avulso LLM Supervisor src/supervisor.py
TCR Conclusão de Tarefa Python src/curadoria.py
REVPREC Verbalização Prematura NeMo LLM rail Output rail determinístico + expansível
TOX Toxicidade NeMo LLM rail self_check_input
OOS Out-of-Scope NeMo LLM rail self_check_input
GND Groundedness NeMo LLM rail self_check_output, com dependência de chunks RAG
HIST Consistência Histórica Python previsto como regra pré-execução
CSI Sentimento LLM-as-a-judge previsto como batch D-1
ALUC Taxa de Alucinação LLM-as-a-judge previsto como batch D-1
RQLT Qualidade da Resposta LLM-as-a-judge previsto como batch D-1
VCTN Tom de Voz LLM-as-a-judge previsto como batch D-1

12. Recomendações para o time

12.1 Não colocar tudo no LLM

Use Python para regras determinísticas e financeiras. Use LLM rails para semântica, linguagem, escopo e groundedness.

12.2 Separar bloqueio de medição

Guardrail bloqueia. Curadoria mede. Supervisor audita. Judge avalia em lote.

12.3 Começar por P0

Primeira entrega sugerida:

  1. PII Masking
  2. Compliance Anatel
  3. Alçada de Ajuste
  4. Supervisor VAS Avulso
  5. TCR
  6. Verbalização Prematura

12.4 Evoluir para P1

Depois:

  1. Toxicidade
  2. Out-of-Scope
  3. Groundedness
  4. Histórico
  5. Tokens
  6. Eficiência NLU
  7. No-Match RAG

13. Critérios de aceite

O time deve comprovar:

  • Dados sensíveis não chegam ao LLM sem máscara.
  • Ajuste acima da alçada não é executado.
  • Resposta de ajuste sem protocolo é bloqueada.
  • Promessa antes da validação é bloqueada.
  • Supervisor retorna status estruturado.
  • Métricas de curadoria são geradas.
  • Spans aparecem no backend de tracing.

14. Evolução futura

A estrutura permite evoluir para:

  • NeMo Server.
  • LangGraph.
  • MCP tools.
  • RAG com groundedness por chunk.
  • Batch judges D-1.
  • Phoenix / Langfuse / OpenTelemetry.
  • Governança por catálogo de guardrails.

15. Referências

  • NVIDIA NeMo Guardrails: documentação oficial.
  • Python SDK: RailsConfig.from_path() e LLMRails.generate().
  • Colang: linguagem para definir fluxos de guardrails.
  • OpenTelemetry: tracing distribuído por spans.