mirror of
https://github.com/hoshikawa2/nemo_guardrails_configuration.git
synced 2026-07-09 17:04:20 +00:00
First Commit
This commit is contained in:
414
README.md
414
README.md
@@ -1 +1,413 @@
|
||||
# nemo_guardrails_configuration
|
||||
# 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:
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```text
|
||||
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
|
||||
|
||||
```text
|
||||
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
|
||||
|
||||
```bash
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 5.2 Configurar variáveis
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
Variáveis principais:
|
||||
|
||||
```bash
|
||||
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](https://github.com/hoshikawa2/nemo_guardrails_oci_generative_ai)
|
||||
|
||||
## 6. Configuração do NeMo Guardrails
|
||||
|
||||
Arquivo: `config/config.yml`
|
||||
|
||||
```yaml
|
||||
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`
|
||||
|
||||
```python
|
||||
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:
|
||||
|
||||
```python
|
||||
client = OpenAI(
|
||||
api_key=settings.openai_api_key,
|
||||
base_url=settings.openai_api_base
|
||||
)
|
||||
```
|
||||
|
||||
Configuração:
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
export USE_MOCK_LLM=true
|
||||
export ENABLE_TRACING=false
|
||||
python -m src.app
|
||||
```
|
||||
|
||||
Resultado esperado:
|
||||
|
||||
```json
|
||||
{
|
||||
"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
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
|
||||

|
||||
|
||||
```bash
|
||||
bash scripts/run_tests.sh
|
||||
```
|
||||
|
||||

|
||||
|
||||
## 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.
|
||||
|
||||
Reference in New Issue
Block a user