13 · Escrevendo um guardrail a partir de uma regra em prosa¶
A Escrita de Guardrails (Guardrail Writing) transforma uma regra que você sabe dizer numa política que você pode publicar, com a evidência por trás dela. Você declara a regra com as suas próprias palavras e nomeia a obrigação que ela tem de cumprir; o serviço pede ao seu modelo, com a sua chave, que redija a política, compila o rascunho, verifica a obrigação nele e o repara onde ele vaza. Este capítulo diz como uma requisição é feita, o que volta, e o que uma política gerada é e não é.
A requisição¶
Uma requisição de guardrail leva generation no lugar de uma política. A obrigação é sua, em operands, e
nunca cabe ao modelo escolhê-la:
result = client.generate_and_verify(
"Funds may move only for a signed-in user whose account is not frozen.",
"execute_transfer_funds", # the action the rule is about
"is_authenticated", # the context it must never fire without
provider="anthropic", model="claude-sonnet-5-5",
api_key_env="ANTHROPIC_API_KEY", # your key, sent with this one request and never stored
rounds=3,
)
print(result.outcome["verdict_produced"], result.status)
for checked in result.envelope["obligations_verified"]: # a list, so its shortness is visible
print(checked["round"], checked["action"], checked["context"], checked["status"])
print("ship it" if result.shipping_candidate else "nothing verified to ship")
| Campo | O que é |
|---|---|
provider, model |
anthropic, gemini ou openai_compatible, e o nome do modelo como esse provedor o escreve |
api_key |
a sua chave desse provedor. Obrigatória: o serviço não tem credencial de modelo própria, nem nenhuma a que recorrer |
prompt |
a regra com as suas palavras, no máximo 8 KB |
rounds |
de 1 a 3, e o seu plano pode permitir menos (capítulo 40): 1 redige e verifica uma vez; 2 ou 3 devolvem o reparo do solver ao seu modelo para uma nova redação enquanto a obrigação ainda falha |
dialect |
o rascunho é escrito em Colang 2, a menos que você peça Colang 1 |
base_policy |
um arquivo existente ao qual a regra deve ser acrescentada |
base_url |
para um provedor compatível com OpenAI, o seu próprio gateway, onde o seu plano inclui um e o host está na lista do seu tenant |
cases |
no máximo 16 situações declaradas nos seus termos, cada uma com o que deve acontecer: bloqueada ou permitida. Cada uma é resolvida sobre a política a publicar |
O que acontece, numa rodada¶
- Pede-se um rascunho ao seu modelo, com a sua chave, mantida só em memória durante a chamada.
- O rascunho é compilado. Um rascunho que o compilador não entendeu por inteiro não recebe veredito.
Uma regra que falta parece uma aprovação, e um rascunho fluente é ao mesmo tempo o mais provável de
esconder uma e o mais provável de ser aceito de confiança. Então um rascunho com qualquer diagnóstico
de análise é nulo:
outcome.verdict_producedéfalse, as linhas que o compilador não conseguiu ler são citadas com os seus números, e nenhuma resolução roda. O job ainda tem sucesso, porque a resposta é real: o seu rascunho não diz o que você pensa. - Um rascunho que nunca menciona a ação ou o contexto falha como
obligation_absent: um desvio por omissão. - Caso contrário, a obrigação é verificada no rascunho, sob
patcha menos que você nomeie um perfil, e uma obrigação que falha volta com o reparo do solver.
As rodadas dois e três só acontecem enquanto a obrigação ainda falha e o solver tem um reparo a devolver. O prompt então traz o rascunho anterior, o veredito e a proteção do solver, com os próprios nomes do rascunho, com a instrução de não mudar mais nada. A obrigação nunca muda entre as rodadas: verificar uma pergunta diferente seria o laço corrigindo a própria prova. Uma rodada que não compila interrompe o laço, e uma rodada pior é relatada como pior.
O que volta¶
A resposta começa com outcome: se um veredito foi produzido, uma frase dizendo o que aconteceu, os seus
casos bloqueados e permitidos, e o shipping_candidate, o arquivo a publicar. Ele é escolhido nesta
ordem:
- o primeiro rascunho de uma rodada que o verificador não conseguiu quebrar;
- senão, a própria política reparada pelo solver, da melhor rodada;
- senão, nada.
Essa ordem é o ponto da funcionalidade. Quando o seu modelo e o reparo do solver discordam, o reparo é publicado, porque é ele que tem uma prova anexada, e ele traz a verificação de bloqueio excessivo que uma nova redação não traz.
A evidência vem em seguida: obligations_verified (uma lista, para que a sua brevidade fique visível), o
veredito, o certificado e o relato completo em generation: o rascunho de cada rodada como um artefato,
o seu veredito e os seus diagnósticos, por que o laço parou, e as chamadas ao modelo feitas, com os tokens
que o seu provedor relatou. Todo artefato registra qual lado o produziu (produced_by): o modelo ou o
solver.
A sua chave e o seu prompt¶
O serviço não guarda nenhum dos dois. A sua chave e o seu prompt viajam da borda até o worker num único valor do armazenamento privado do serviço, lido e apagado numa única operação, e expiram com a fila do job. Eles nunca são escritos num banco de dados, num armazenamento de objetos, num log ou num evento, e, enquanto uma chamada está em andamento, a sua chave fica registrada no filtro de logs, que a substitui onde quer que apareça, inclusive num erro que um provedor repita. O job guarda o SHA-256 do prompt e o seu tamanho; nenhuma resposta bruta do modelo é guardada. O rascunho é guardado, como um arquivo de política sob a sua retenção, porque ele é o produto (capítulo 16).
Duas consequências que você vai encontrar:
- Se um worker para no meio de um job e o job é refeito, a chave e o prompt já não existem: o job falha
como
generation_input_expired, não é cobrado, e você o envia de novo com uma nova chave de idempotência. - Uma requisição cujo armazenamento de passagem não pode ser alcançado é recusada com
503eRetry-After, em vez de a chave ser guardada em algum lugar durável.
Uma política em Colang 2¶
Os rascunhos são escritos em Colang 2 por padrão, e a verificação lê um subconjunto declarado dele. Uma
construção fora do subconjunto não é aproximada: um job sobre uma política que usa uma dentro do alcance
da pergunta é recusado como colang2_construct_unsupported, nomeando a linha
(capítulo 6). Para tudo o mais que o Colang consegue expressar, veja a documentação
do NeMo Guardrails; este guia documenta o que o verificador compila.
O que uma política gerada é e não é¶
O rascunho é do modelo; o veredito, o certificado e o reparo são do solver. Toda resposta diz isso, na
sua ressalva permanente draft_is_the_models, e todo artefato nomeia quem o produziu.
- Ela não é uma política correta. Uma obrigação nomeada foi verificada sobre um rascunho, e
obligations_verifiedlista exatamente isso. Toda resposta traz a ressalvaverified_only_as_asked. Uma obrigação que a regra exige e que o rascunho nunca menciona não tem variável nem linha, e nada aqui a encontra. - Ela não é um guardrail que uma IA verificou. Um modelo escreveu um texto; o solver verificou uma proposição sobre esse texto. A resposta nunca chama um rascunho de verificado além das obrigações que lista.
- Ela é um ponto de partida com evidência. Um rascunho verificado é uma política que cumpre a obrigação que você nomeou, com um certificado que qualquer pessoa pode conferir. Revise-o como revisaria a política de um colega, e acrescente o resto das suas regras como perguntas próprias (capítulo 4).
Se o seu modelo aceita uma regra escrita em outra língua, em português por exemplo, é assunto do seu modelo: o serviço repassa o seu prompt como você o escreveu, e não afirma nada sobre como um modelo o lê.
Os limites¶
- Uma política gerada é verificada para as obrigações listadas em
obligations_verified, e para nada mais. - A qualidade do rascunho é a do seu modelo. O serviço o confere e o repara; ele não torna o modelo certo.
- Um rascunho nulo não tem veredito. Não o publique, e não cite para ele o veredito de uma rodada anterior.