Ir para o conteúdo

43 · Segurança das respostas

Idiomas

O seletor lê turnos escritos em inglês e em português do Brasil (pt-BR). O idioma é escolhido, nunca adivinhado a partir do turno: na página Settings do console (Language the selector reads), em language numa requisição de plano, ou no settings.language do seu arquivo de vocabulário; sem nenhum deles, inglês. Um turno em português pode ser digitado com os acentos ou sem eles. O português europeu não é uma gramática que o seletor tenha, e um turno em qualquer outra língua não é lido.

Com replies: {rules: ...} configurado, todo turno que uma pessoa envia é examinado em busca de dados pessoais antes que o roteador ou o modelo o leia, e toda resposta que o modelo escreve é examinada de novo antes de ser mostrada, tenha havido uma ação antes dela ou não. As suas regras dizem o que cada classe de dado pessoal recebe, quais expressões nunca são ditas, quais ofertas uma resposta pode fazer e quais frases precisam acompanhar uma escrita. Nenhum modelo julga nada disso: o runtime na sua máquina decide cada regra.

Dados pessoais

As classes que o runtime encontra, como cada uma é encontrada, o que ela recebe quando as suas regras não dizem nada, e como é mascarada, gerados a partir dos detectores do runtime:

Classe Como é encontrada Padrão Mascarada como
email um endereço da forma nome@domínio allow j***@example.com
iban um número de conta com o comprimento que o seu país define, cujos dígitos de verificação conferem redact GB** **** 2681
national_id um social security number dos EUA, um national insurance number do Reino Unido, ou um CPF cujos dígitos verificadores conferem redact ***6789
card de 13 a 19 dígitos cuja soma de verificação (Luhn) confere: um número que não confere fica como está redact **** 1111
phone um número internacional de 8 a 15 dígitos, ou um nacional de 10 ou 11 allow ***0123

Um número de cartão é encontrado pela sua soma de verificação, não pela sua forma: dezesseis dígitos que não passam na verificação de Luhn ficam como estão, porque não são um número de cartão. Cada classe recebe uma de três ações:

Ação Num turno enviado ao modelo Numa resposta que o modelo escreveu
redact mascarado antes que o roteador e o modelo leiam o turno mascarado na frase
withhold o turno inteiro é retido: nada o lê, e a pessoa é convidada a enviá-lo de novo sem o valor a frase é removida
allow deixado como está deixado como está

Um valor que uma frase de resultado pode repetir. Uma frase que relata uma escrita pode citar um valor que a escrita recebeu -- o cartão para onde foi um reembolso -- e esse valor é mascarado nela em vez de removido, qualquer que seja a ação da classe, a menos que a classe seja permitida.

Redação

  • never_say: expressões que nunca são ditas. Uma frase que contenha uma delas, em palavras inteiras e em qualquer caixa, é removida.
  • offers: as ofertas que uma resposta pode fazer. Uma frase que contenha um dos markers (como discount ou voucher) e nenhuma das ofertas allowed é removida.
  • must_accompany: frases que precisam acompanhar algo: um aviso acrescentado quando a chamada de uma ferramenta rodou neste turno (when_done), ou quando uma resposta cita uma passagem com uma etiqueta (when_cited). Ele é acrescentado uma vez, onde a resposta ainda não o diz.

O arquivo de regras de resposta

As regras são um arquivo, YAML ou JSON, nomeado no agent.yaml como replies: {rules: reply-rules.yaml} ou em Python como Agent(..., replies={"rules": "reply-rules.yaml"}). O da loja:

# As regras de resposta da loja, como a página Reply rules do console as salva.
personal_data:
  card: redact            # o padrão, escrito por extenso
  national_id: withhold   # um turno com um deles não chega a nenhum modelo; uma resposta com um deles perde a frase
  email: allow
never_say:
  - "estorno garantido"
must_accompany:
  - when_done: refund_card
    add: "Os estornos chegam ao cartão em três a cinco dias úteis."

Cada chave que o runtime lê, gerada a partir do runtime:

Chave O que diz
personal_data para cada classe de dado pessoal, redact, withhold ou allow
must_accompany frases que precisam acompanhar uma escrita feita ou uma passagem citada
must_accompany[].add a frase acrescentada
must_accompany[].when_done acrescentada quando a chamada desta ferramenta rodou neste turno
must_accompany[].when_cited acrescentada quando uma resposta cita uma passagem com esta etiqueta
reply_exactly respostas dadas palavra por palavra no lugar de qualquer outra resposta, sem modelo e sem nada acrescentado
reply_exactly[].when_cited dada quando uma resposta cita uma passagem com esta etiqueta
reply_exactly[].when_asked dada quando o turno diz uma das expressões do assunto: as suas words ou, sem elas, o nome do assunto com _ e - lidos como espaços
reply_exactly[].say a resposta exata, sem nada acrescentado
reply_exactly[].words com when_asked: as expressões que perguntam sobre o assunto, comparadas como palavras inteiras, sem distinguir maiúsculas, por exemplo alergia, alérgico, amendoim
never_say expressões que nunca se devem dizer: uma frase que contenha uma delas é removida
offers as ofertas que uma resposta pode fazer
offers.allowed as ofertas permitidas
offers.markers as palavras que fazem de uma frase uma oferta: uma frase com um marcador e sem oferta permitida é removida

As mesmas regras ficam na página Regras de resposta do console, como um formulário sobre o mesmo arquivo, e em /v1/reply-rules, em versões. Um arquivo que o runtime não consegue ler -- uma classe que ele não conhece, uma ação que não é uma das três -- é recusado com a chave que está errada.

As respostas da loja, examinadas

A loja roda com uma licença Enterprise. Os pedidos dela guardam o cartão cadastrado e o cliente, que são dados pessoais, e um modelo lê os dados pessoais que uma ferramenta devolve só no Enterprise, com a sua própria chave; em outro plano, a resposta diz que foi escrita sem um modelo.

O modelo abaixo faz o papel do seu, e registra o que recebeu:

SEEN = []          # o que o modelo recebeu, turno a turno

# Faz as vezes do seu modelo: o que lhe perguntam, e a resposta que ele escreve.
SCRIPT = {
    "zork": (None, ""),
    "o meu cartão é **** 1111, ele está cadastrado?": (
        None,
        "O seu cartão 4111 1111 1111 1111 está cadastrado; o cartão 4111 1111 1111 1112 não está."),
    "a encomenda do 4412 desapareceu": (
        {"name": "refund_card", "arguments": {"order_id": "4412", "amount": 12.50}},
        "Estornei 12,50 reais pelo pedido 4412. É um estorno garantido."),
}


def model(conversation):
    turn = [m for m in conversation if m["role"] == "user"][-1]["content"]
    SEEN.append(turn)
    call, reply = SCRIPT[turn]
    if conversation[-1]["role"] == "user" and call:
        return {"content": "", "tool_calls": [call]}
    return reply
desk = Agent("desk", tools=[get_order, refund_card], model=model, on_unread="model",
             replies={"rules": "reply-rules.yaml", "language": "pt"})

for text in ("zork",
             "o meu cartão é 4111 1111 1111 1111, ele está cadastrado?",
             "o meu CPF é 123.456.789-09",
             "a encomenda do 4412 desapareceu"):
    reply = desk.chat(text, user="u-17")
    if reply.waiting:
        reply = desk.confirm("u-17", "approve")
    print(f"{text}\n  -> {reply.text}")

print("O modelo recebeu:", SEEN)
zork
  -> Não reconheci nada nisso. Posso get order ou refund card. Pode dizer qual ferramenta ou qual item você quer?
o meu cartão é 4111 1111 1111 1111, ele está cadastrado?
  -> O seu cartão **** 1111 está cadastrado; o cartão 4111 1111 1111 1112 não está.
o meu CPF é 123.456.789-09
  -> Essa mensagem tinha dados que não posso receber aqui, então não a li nem fiz nada. Envie de novo sem eles, por favor.
a encomenda do 4412 desapareceu
  -> Estornei 12,50 reais pelo pedido 4412. Os estornos chegam ao cartão em três a cinco dias úteis.
O modelo recebeu: ['o meu cartão é **** 1111, ele está cadastrado?', 'a encomenda do 4412 desapareceu', 'a encomenda do 4412 desapareceu']
  • O número de cartão que a pessoa digitou foi mascarado antes que algo lesse o turno: o modelo recebeu **** 1111.
  • A resposta do modelo citou o mesmo cartão válido, mascarado, e um número de dezesseis dígitos que não passa na soma de verificação, deixado como está.
  • O turno com um CPF foi retido inteiro, sob national_id: withhold: nada o leu, e a pessoa foi convidada a enviá-lo de novo sem o número. Ele não está no que o modelo recebeu.
  • Depois que o reembolso rodou, É um estorno garantido. foi removida (never_say), e o aviso que as regras exigem para um reembolso foi acrescentado.

As contagens

Cada verificação é contada, pelo medidor sob o qual é registrada, com os outros medidores da sua licença. Uma contagem é um número: não carrega nenhum texto, nenhum valor e nenhum turno.

Contagem O que conta
reply_temperature_kept uma variação que, relida, teve outro modo ou outras palavras travadas, então a própria frase do modelo foi enviada
reply_temperature_varied uma frase do modelo dita de outro jeito, com a temperatura das respostas ligada
reply_exact_reply uma resposta dada palavra por palavra no lugar de qualquer outra, por reply_exactly
reply_pd_detected_<class> um valor daquela classe de dado pessoal encontrado
reply_pd_masked um valor enviado a uma escrita, repetido na frase do seu próprio resultado, mascarado
reply_pd_withheld um turno retido, ou uma frase removida, por um valor que as regras retêm
reply_pd_redacted um valor mascarado porque as regras ocultam a sua classe
reply_assertion_refused uma frase dizendo que uma escrita foi feita sem que nada na sessão a tentasse, substituída
reply_outcome_replaced uma frase que o resultado da sua ação não permite, substituída pela formulação
reply_value_highlighted uma frase num trabalho da equipe que afirma um valor que nenhum registro tem, mantida e destacada
reply_value_replaced uma frase que afirma um valor que a sua ação não recebeu nem devolveu, substituída
reply_outcome_added uma escrita deste turno que a resposta omitiu, acrescentada a partir da sua formulação
reply_wording_removed uma frase com uma expressão que nunca se deve dizer, removida
reply_offer_removed uma frase que faz uma oferta fora das permitidas, removida
reply_wording_added uma frase que as regras exigem, acrescentada
reply_facts_untraced um valor que a resposta afirma e que nenhum registro de chamada tem
reply_facts_traced um valor que a resposta afirma, rastreado até a chamada e o campo de onde veio
reply_facts_conflict um valor rastreado que outra fonte deste turno dá diferente, para a mesma coisa
reply_facts_stale um valor rastreado lido há mais tempo do que a fonte diz que um resultado vale
reply_facts_out_of_range um valor rastreado fora do intervalo que o esquema de saída da ferramenta permite

Os limites

  • Um detector encontra as classes que nomeia, e nenhuma outra. Um nome, um endereço postal, uma data de nascimento ou um identificador de outro país não é detectado, e fica como está.
  • Um detector encontra um valor escrito como ele o lê. Um número de cartão escrito por extenso, ou dividido em duas mensagens, não é encontrado.
  • Nenhum modelo julga uma resposta. Uma regra casa com as palavras que recebe: uma expressão dita com outras palavras não é uma expressão que never_say lista.
  • O exame cobre os turnos que o agente lê e as respostas que o seu modelo escreve. Uma resposta que nenhum modelo escreveu -- uma pergunta fixa, uma recusa, uma formulação -- é o texto do próprio produto.